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