찾다

 >  Q&A  >  본문

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中文网2813일 전649

모든 응답(1)나는 대답할 것이다

  • 阿神

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

    我想告诉你,第一个程序并不是没有效果,而是第一个程序的状态已经保存到binaryImage中去了
    经过第一次运行on_thresholdAdjustment函数后,binaryImage中的内容已经只有0、255两种值了

    以后再次修改,也是基于binaryImage中仅有的0和255进行,因此阈值g_threshold就必然会失效,可以通过将阈值改成0你可以看到效果。

    保持原始的信息是非常有必要的,不能总是基于计算出来的值进行计划,必须使用原始信息进行计算,如果你不想要3个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 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;
    }

    회신하다
    0
  • 취소회신하다