c++ - 关于opencv滚动条的问题
PHP中文网
PHP中文网 2017-04-17 13:31:51
0
1
650

下面两版代码,第一个代码运行时灰度值不能随滚动条的调节而变化,但是第二版程序就可以。麻烦帮我分析一下为什么?环境是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中文网

认证0级讲师

全部回覆(1)
阿神

我想告訴你,第一個程式並不是沒有效果,而是第一個程式的狀態已經保存到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;
}
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板