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

下面两版代码,第一个代码运行时灰度值不能随滚动条的调节而变化,但是第二版程序就可以。麻烦帮我分析一下为什么?环境是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;
}
いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート