Home  >  Q&A  >  body text

c++ - 关于opencv滚动条的问题

下面两版代码,第一个代码运行时灰度值不能随滚动条的调节而变化,但是第二版程序就可以。麻烦帮我分析一下为什么?环境是vs2012+opencv2.4.8

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace std;
using namespace cv;

static void on_thresholdAdjustment(int, void*);  //滚动条回调函数

int g_threshold=70;
Mat binaryImage;
Mat dstImage;



int main()
{
    //1.读取图像并在窗口中显示
    Mat srcImage = imread("dota.jpg", 1);
    if (!srcImage.data)
    {
        cerr <<"图片读取错误!\n";
        return -1;
    }
    namedWindow("原图窗口");
    imshow("原图窗口", srcImage);

    waitKey(0);
    //2.对灰度图像进行二值化处理

    //srcImage.copyTo(binaryImage);    
    binaryImage = srcImage.clone(); 
    if (!binaryImage.data)
    {
        cerr << "binaryImage is empty!\n" <<endl;
    }
    cvtColor(srcImage, binaryImage, CV_RGB2GRAY);//COLOR_RGB2GRAY  CV_RGBA2GRAY


    namedWindow("二值化图像", 1);

    createTrackbar("阈值 ", "二值化图像", &g_threshold, 150, on_thresholdAdjustment);
    on_thresholdAdjustment(g_threshold, 0);

    waitKey(0);
}

static void on_thresholdAdjustment(int, void*)
{
    int rowNumber = binaryImage.rows;
    int colNumber = binaryImage.cols;
    for (int i = 0; i < rowNumber; i++)
    {
        uchar* data = binaryImage.ptr<uchar>(i);  //获取第i行的首地址
        for(int j = 0; j < colNumber; j++)
        {    
            if (data[j] < (g_threshold)) 
            {
                data[j] = 0;
            }
            else
            {
                data[j] = 255;
            } 
        }
    }
    imshow("二值化图像", binaryImage);
    
    cout<< "finished" << endl;
}

第二版程序 使用了一个中间的mat

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace std;
using namespace cv;

static void on_thresholdAdjustment(int, void*);  //滚动条回调函数

int g_threshold=70;
Mat binaryImage;
Mat dstImage;



int main()
{
    //1.读取图像并在窗口中显示
    Mat srcImage = imread("dota.jpg", 1);
    if (!srcImage.data)
    {
        cerr <<"图片读取错误!\n";
        return -1;
    }
    namedWindow("原图窗口");
    imshow("原图窗口", srcImage);

    waitKey(0);
    //2.对灰度图像进行二值化处理

    //srcImage.copyTo(binaryImage);    
    binaryImage = srcImage.clone(); 
    if (!binaryImage.data)
    {
        cerr << "binaryImage is empty!\n" <<endl;
    }
    cvtColor(srcImage, binaryImage, CV_RGB2GRAY);//COLOR_RGB2GRAY  CV_RGBA2GRAY
    dstImage = Mat::zeros(binaryImage.size(), binaryImage.type());//这里不同

    namedWindow("二值化图像", 1);

    createTrackbar("阈值 ", "二值化图像", &g_threshold, 150, on_thresholdAdjustment);
    on_thresholdAdjustment(g_threshold, 0);

    waitKey(0);
}

static void on_thresholdAdjustment(int, void*)
{
    int rowNumber = binaryImage.rows;
    int colNumber = binaryImage.cols;
    for (int i = 0; i < rowNumber; i++)
    {
        uchar* data = binaryImage.ptr<uchar>(i);  //获取第i行的首地址
        uchar* data2 = dstImage.ptr<uchar>(i);  //这里不同
        for(int j = 0; j < colNumber; j++)
        {    
            if (data[j] < (g_threshold)) 
            {
                data2[j] = 0;
            }
            else
            {
                data2[j] = 255;
            } 
        }
    }
    imshow("二值化图像", dstImage);

    cout<< "finished" << endl;
}

PHP中文网PHP中文网2765 days ago624

reply all(1)I'll reply

  • 阿神

    阿神2017-04-17 13:33:51

    I want to tell you that the first program is not ineffective, but the status of the first program has been saved in binaryImage
    After running the on_thresholdAdjustment function for the first time, the content in binaryImage has only There are two values: 0 and 255

    Modifications in the future will be based on the only 0 and 255 in binaryImage, so the threshold g_threshold will inevitably fail. You can see the effect by changing the threshold to 0.

    It is very necessary to keep the original information. You cannot always plan based on the calculated values. You must use the original information for calculation. If you don’t want 3 Mats, you can change it like this:

    #include <iostream>
    #include <opencv2/opencv.hpp>
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    
    using namespace std;
    using namespace cv;
    
    static void on_thresholdAdjustment(int, void*);  //滚动条回调函数
    
    int g_threshold = 70;
    Mat binaryImage;
    Mat srcImage;
    
    
    int main()
    {
        //1.读取图像并在窗口中显示
        srcImage = imread("dota.jpg", 1);
        if (!srcImage.data)
        {
            cerr << "图片读取错误!\n";
            return -1;
        }
        namedWindow("原图窗口");
        imshow("原图窗口", srcImage);
    
        waitKey(0);
    
        // 把这里的代码删掉
    
        namedWindow("二值化图像", 1);
    
        createTrackbar("阈值 ", "二值化图像", &g_threshold, 150, on_thresholdAdjustment);
        on_thresholdAdjustment(g_threshold, 0);
    
        waitKey(0);
    }
    
    static void on_thresholdAdjustment(int, void*)
    {  
        // 把代码粘贴到这里来,保证binaryImage每次都重新生成
        //2.对灰度图像进行二值化处理
        binaryImage = srcImage.clone();
        if (!binaryImage.data)
        {
            cerr << "binaryImage is empty!\n" << endl;
        }
        cvtColor(srcImage, binaryImage, CV_RGB2GRAY);
        // 把代码粘贴到这里来
    
        int rowNumber = binaryImage.rows;
        int colNumber = binaryImage.cols;
        for (int i = 0; i < rowNumber; i++)
        {
            uchar* data = binaryImage.ptr<uchar>(i);  //获取第i行的首地址
            for (int j = 0; j < colNumber; j++)
            {
                if (data[j] < (g_threshold))
                {
                    data[j] = 0;
                }
                else
                {
                    data[j] = 255;
                }
            }
        }
        imshow("二值化图像", binaryImage);
    
        cout << "finished" << g_threshold << endl;
    }

    reply
    0
  • Cancelreply