opencv2鼠标选定感兴趣区域用反投影算法检测相似部分

来源:互联网 发布:人工智能 军民融合 编辑:程序博客网 时间:2024/05/18 03:39

请广大博友转载时,注明文章出处,谢谢!!!

这个是对上一篇,在反投影算法中使用颜色信息的一个拓展,理解了上一篇和鼠标事件后,这个就是组合

#include<opencv2/imgproc/imgproc.hpp>#include<opencv2/imgproc/types_c.h>#include<opencv2/highgui/highgui.hpp>#include<opencv2/core/core.hpp>#include<iostream>#include<vector>#include<opencv2/nonfree/features2d.hpp>#include<opencv2/legacy/legacy.hpp>#include<opencv2/features2d/features2d.hpp>#include<opencv2/calib3d/calib3d.hpp>#include<opencv2/video/tracking.hpp>using namespace cv;using namespace std;class Package{private:public:Mat CalcBack_Color(const Mat &InImage, const Rect &rectROI);MatND ComterGrayHistogram(const Mat &InImage, bool isdisplay, bool isshow, const Scalar &color, int channelsnum);Mat colorReduce(const Mat &InImage, int div);};Mat Package::colorReduce(const Mat &InImage, int div){Mat OutImage(InImage.rows, InImage.cols, InImage.type());int x = InImage.rows;int y = InImage.cols*InImage.channels();for (int i = 0; i < x; i++){const uchar* data = InImage.ptr<const uchar>(i);uchar* data_out = OutImage.ptr<uchar>(i);for (int j = 0; j < y; j++){data_out[j] = data[j] / div*div + div / 2;}}return OutImage;}Mat Package::CalcBack_Color(const Mat &InImage, const Rect &rectROI){Mat OutImage = InImage;//先初始化一些变量,在函数中用做中间参数使用float hranges[2];    //最小值和最大值const float *ranges[3];int channels[3];MatND histogram;int histSize[3];ranges[0] = hranges;ranges[1] = hranges;ranges[2] = hranges;hranges[0] = 0.0;hranges[1] = 255.0;channels[0] = 0;channels[1] = 1;channels[2] = 2;histSize[0] = 256;histSize[1] = 256;histSize[2] = 256;//使用颜色减缩函数OutImage = colorReduce(OutImage, 32);Mat OutImageROI = OutImage(rectROI);MatND hist;calcHist(&OutImageROI, 1, channels, Mat(), hist, 3, histSize, ranges);normalize(hist, hist, 1.0);Mat result;calcBackProject(&OutImage, 1, channels, hist, result, ranges, 255.0);cout << "OK" << endl;return result;}MatND Package::ComterGrayHistogram(const Mat &InImage, bool isdisplay, bool isshow, const Scalar &color, int channelsnum){Mat GrayImage;vector<Mat>channelsvector;if (InImage.channels() == 3){split(InImage, channelsvector);if (channelsnum == 0){cvtColor(InImage, GrayImage, CV_BGR2GRAY);}if (channelsnum == 1){GrayImage = channelsvector[0];}if (channelsnum == 2){GrayImage = channelsvector[1];}if (channelsnum == 3){GrayImage = channelsvector[2];}}else{GrayImage = InImage;}//通道数int channels[1];//计算0号通道channels[0] = 0;//项的数量int histSize[1];histSize[0] = 256;//像素值的范围const float *ranges[1];//像素的最小及最大值,为了给hranges一个变量的分配的空间float hranges[2];ranges[0] = hranges;//存放最小范围hranges[0] = 0;//存放最大范围hranges[1] = 255;MatND hist;calcHist(&GrayImage, 1, channels, Mat(), hist, 1, histSize, ranges);if (isdisplay == 1){for (int i = 0; i < 256; i++){cout << "Value" << i << "=" << hist.at<float>(i) << endl;}}/*开始直观的显示出直方图,如果将isshow置零,将不显示*/if (isshow == 1){double minVal;double maxVal;//找到数组的最大值和最小值,目的是需要用最大和最小值将得到的对应像素的像素点个数归一化,这里的归一化是都归在0~255之间//这个处理仅仅是为了显示起来方便,如果不规定一个统一的最大值,那么显示的尺寸就要就会随着最大值在不断的变换minMaxLoc(hist, &minVal, &maxVal, 0, 0);//定义显示直方图的Mat型,包括显示窗口的长度和宽度//这里就把最大值限制在histSize[0]上了Mat showhist(histSize[0], histSize[0], CV_8UC3, Scalar(255, 255, 255));//将最高点设置为横坐标总长的90%,最大值就不会超过256*0.9,这样在一个正好是256*256的图像中就不会有值刚好在边界上,增强了可视化int hpt = static_cast<int>(0.9*histSize[0]);for (int x = 0; x < histSize[0]; x++)       //绘制直方图{//得到每个像素点对应的像素的个数float binVal = hist.at<float>(x);int intensity = static_cast<int>(binVal*hpt / maxVal);//由于图像的y轴是竖直向下的,所以连线的时候起始坐标是(x, histSize[0]),而不是(0, 0))line(showhist, Point(x, histSize[0]), Point(x, histSize[0] - intensity), color);}}return hist;}Package P;Point coord;//储存初始坐标Rect sqart;//储存矩形框的起始坐标以及长度和宽度bool draw;Mat img;//过度图像Mat dst;//感兴趣区域图像Mat org;//将org作为原始图像储存void onMouse(int event, int x, int y, int flags, void *param){/*cout << "Event:" << event << endl;cout << "x=" << x << "     " << "y=" << y << endl;cout << "flags:" << endl;cout << "param" << param << endl;*/switch (event){//按下鼠标左键case CV_EVENT_LBUTTONDOWN://在第二次点击鼠标图像时,这里清除了一下显示小窗口的步骤cvDestroyWindow("dst");//储存起始坐标coord = Point(x, y);//将起始矩形框初始化sqart = Rect(x, y, 0, 0);draw = true;break;//松开鼠标左键case CV_EVENT_LBUTTONUP:if (sqart.height > 0 && sqart.width > 0){//将img中的矩形区域复制给dst,并显示在img窗口中dst = img(Rect(sqart.x, sqart.y, sqart.width, sqart.height));rectangle(img, sqart, Scalar(0, 0, 255), 1);namedWindow("img");imshow("img", img);//将画过矩形框的图像用org原图像还原org.copyTo(img);imshow("Mouse", img);Mat calc = P.CalcBack_Color(img, Rect(sqart.x, sqart.y, sqart.width, sqart.height));namedWindow("calc");imshow("calc", calc);namedWindow("dst");imshow("dst", dst);waitKey(0);}draw = false;break;case CV_EVENT_MOUSEMOVE:if (draw/*&&sqart.height > 0 && sqart.width > 0*/){//用MIN得到左上点作为矩形框的其实坐标,如果不加这个,画矩形时只能向一个方向进行sqart.x = MIN(x, coord.x);sqart.y = MIN(y, coord.y);sqart.width = abs(coord.x - x);sqart.height = abs(coord.y - y);//防止矩形区域超出图像的范围sqart &= Rect(0, 0, org.cols, org.rows);}break;}}int main(){img = imread("F:\\color.jpg");namedWindow("Mouse");setMouseCallback("Mouse", onMouse, NULL);imshow("Mouse", img);img.copyTo(org);//将org作为原始图像储存waitKey(0);return 0;}


运行结果:


0 0
原创粉丝点击