计算反向投影:calcBackProject()函数
void calcBackProject(const Mat* images, //输入的数组,须为相同的深度(CV_8U或CV_32F)和相同的尺寸,通道数任意 int nimages,//输入数组的个数 const int* channels,//需要统计的通道dim索引 InputArray hist,//输入的直方图 OutputArray backProject,//目标反向投影阵列,须为单通道,且和image[0]有相同大小/深度 const float** ranges,//表示一个维度的数组 double scale = 1,//默认1 bool uniform = true)//指示直方图是否均匀的标识符通道复制:mixChannels()函数
void mixChannels(const Mat*src,//输入的数组,所有的矩阵必须有相同尺寸和深度 size_t nsrcs,//第一个参数src输入的矩阵数 Mat* dst,//输出的数组,所有矩阵必须被初始化,且大小和深度必须与src[0]相同 size_t ndsts,//第三个参数dst输入的矩阵数 const int* fromTo,//对指定的通道进行复制的数组索引 size_t npairs)//第五个参数fromTo的索引数示例代码
#include <opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> using namespace cv; using namespace std; #define WINDOW_NAME1 "原图" Mat g_srcImage, g_hsvImage, g_hueImage; int g_bins = 30;//直方图组距 void on_BinChange(int, void*); int main() { g_srcImage = imread("6.jpg", 1); if (!g_srcImage.data) { printf("fail to load image!"); return -1; } cvtColor(g_srcImage, g_hsvImage, COLOR_BGR2HSV); //分离hue色调通道 g_hueImage.create(g_hsvImage.size(),g_hsvImage.depth()); int ch[ ] = { 0,0 }; mixChannels(&g_hsvImage, 1, &g_hueImage, 1, ch, 1); //创建Trackbar来输入bin的数目 namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE); createTrackbar("色调组距",WINDOW_NAME1,&g_bins,180,on_BinChange); on_BinChange(0, 0);//进行一次初始化 imshow(WINDOW_NAME1, g_srcImage); waitKey(0); return 0; } void on_BinChange(int, void*) { MatND hist; int histSize = MAX(g_bins, 2); float hue_range[] = { 0,180 }; const float* ranges = { hue_range }; //计算直方图并归一化 calcHist(&g_hueImage, 1, 0, Mat(), hist, 1, &histSize, &ranges, true, false); normalize(hist, hist, 0, 255, NORM_MINMAX, -1, Mat()); //计算反向投影 MatND backproj; calcBackProject(&g_hueImage, 1, 0, hist, backproj, &ranges,1, true); imshow("反向投影", backproj); //绘制直方图的参数准备 int w = 400, h = 400; int bin_w = cvRound((double)w / histSize); Mat histImg = Mat::zeros(w, h, CV_8UC3); //绘制直方图 for (int i = 0; i < g_bins; i++) { rectangle(histImg, Point(i * bin_w, h), Point((i + 1) * bin_w, h - cvRound(hist.at<float>(i) * h / 255.0)), Scalar(100, 123, 255), -1); imshow("直方图", histImg); } }实现模板匹配:matchTemplate()函数
void matchTemplate(InputArray image,//带搜索的图像,且需为8位或32位浮点型图像 InputArray temp1,//搜索模板,需和原图片有一样的数据类型,且尺寸不能大于源图像 OutputArray result,//比较结果的映射图像,必须为单通道,32位浮点型图像。 int method)//指定的匹配方法1.method=TM_SQDIFF 平方差匹配法 2.method=TM_SQDIFF_NORMED归一化平方差匹配法 3.method=TM_CCORR 相关匹配法 4.method=TM_CCORR_NORMED 归一化相关匹配法 5.method=TM_CCOEFF 系数匹配法 6.method=TM_CCOEFF_NORMED 化相关系数匹配法
#include <opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> using namespace cv; using namespace std; #define WINDOW_NAME1 "原图" #define WINDOW_NAME2 "效果图" Mat g_srcImage, g_templateImage, g_resultImage; int g_nMatchMethod;//直方图组距 int g_nMaxTrackbarNum = 5; void on_Matching(int, void*); int main() { g_srcImage = imread("5.jpg",1); g_templateImage = imread("4.jpg", 1); namedWindow(WINDOW_NAME1, CV_WINDOW_AUTOSIZE); namedWindow(WINDOW_NAME2, CV_WINDOW_AUTOSIZE); //创建滑动条并进行一次初始化 createTrackbar("方法", WINDOW_NAME1, &g_nMatchMethod, g_nMaxTrackbarNum, on_Matching); on_Matching(0, 0); waitKey(0); return 0; } void on_Matching(int, void*) { Mat srcImage; g_srcImage.copyTo(srcImage); //初始化用于输出的矩阵 int resultImage_rows = g_srcImage.rows - g_templateImage.rows + 1; int resultImage_cols = g_srcImage.cols - g_templateImage.cols + 1; g_resultImage.create(resultImage_rows, resultImage_cols, CV_32FC1); //进行匹配和标准化 matchTemplate(g_srcImage, g_templateImage, g_resultImage, g_nMatchMethod); normalize(g_resultImage, g_resultImage, 0, 1, NORM_MINMAX, -1, Mat()); //通过函数minMaxLoc定位最匹配的位置 double minValue, maxValue; Point minLocation, maxLocation,matchLocation; minMaxLoc(g_resultImage, &minValue, &maxValue, &minLocation, &maxLocation, Mat()); //对于方法SQDIFF和SQDIFF_NORMED,越小的数值有着更高的匹配结果,而其余的方法,数值越大匹配效果越好 if (g_nMatchMethod == TM_SQDIFF || g_nMatchMethod == TM_SQDIFF_NORMED) matchLocation = minLocation; else matchLocation = maxLocation; //绘制出矩形,并显示最终结果 rectangle(srcImage, matchLocation, Point(matchLocation.x + g_templateImage.cols, matchLocation.y + g_templateImage.rows), Scalar(0, 0, 255), 2, 8, 0); rectangle(g_resultImage, matchLocation, Point(matchLocation.x + g_templateImage.cols, matchLocation.y + g_templateImage.rows), Scalar(0, 0, 255), 2, 8, 0); imshow(WINDOW_NAME1, srcImage); imshow(WINDOW_NAME2, g_resultImage); }