OpenCV笔记6——模板匹配(匹配与模板对应的所有目标)

    科技2024-04-03  38

    1.模板匹配的原理

    2.相关API

    2.1模板匹配API:

    注: 1.关于result的size为什么是(W-w+1,H-h+1),其中W、H是原图像的宽和高,w、h是模板的宽和高,而且要求w≦W,h≦H,这张图应该可以很好的解释; 2.OpenCV提供的method总共有六种,如下: cv::TM_SQDIFF


    cv::TM_SQDIFF_NORMED


    cv::TM_CCORR


    cv::TM_CCORR_NORMED


    cv::TM_CCOEFF


    cv::TM_CCOEFF_NORMED


    3.这六种method处理后的结果对比: 通常使用的都是第2、4、6个,即归一化之后的method;

    选择第2种method处理后的值越小说明越相似,即越接近0,越相似; 选择第4、6中method处理后的值越大说明越相似,即越接近1,越相似; 更多关于这六种method的说明请参考OpenCV相关手册;

    2.2在模板匹配处理后的图像中获取相关值的API:

    注: 这里的minVal和maxVal都是double类型的,并且是指针操作,所以在引用的时候要对实参进行&取地址操作;

    3.实验代码

    #include <iostream> #include <opencv2/opencv.hpp> using namespace cv; int main() { char *str_Input_Window_Title = "Read Image Window"; char *str_Output_Window_Title = "Result Window"; char *str_Template_Window_Title = "Template Window"; Mat img = imread("E:/chess.jpg");//从指定路径加载图像 Mat img_temp = imread("E:/chess_template.jpg"); if (!img.data || !img_temp.data)//加载图像失败 { printf("Fault to load image!\n\r"); return -1; } imshow(str_Input_Window_Title, img); imshow(str_Template_Window_Title, img_temp); Mat dst; dst.create(img.size(), img.type());//实践证明,result在初始化时可以不用设定为模板匹配中要求宽高 matchTemplate(img, img_temp, dst, TM_SQDIFF_NORMED);//method选择TM_SQDIFF_NORMED,越接近0,匹配度越高 imshow("Match Window", dst);//显示匹配后的图像 //normalize(dst, dst, 0, 1, NORM_MINMAX, -1);//根据所选的method决定是否归一化 double min_value, max_value; Point Point_Max, Point_Min; minMaxLoc(dst, &min_value, &max_value, &Point_Min, &Point_Max);//寻找最小值点 printf("Max:%4f Min:%4f\nX:%d Y:%d\n", max_value, min_value, Point_Min.x, Point_Min.y); imshow(str_Output_Window_Title, dst); //在原图像中圈出匹配到的目标区域 rectangle(img, Rect(Point_Min.x, Point_Min.y, img_temp.cols, img_temp.rows), Scalar(0, 0, 255), 2,8); imshow(str_Output_Window_Title, img);//显示原图像 waitKey(0); return 0; }

    4.运行结果

    原图像: 模板: 处理后的图像:

    5.匹配原图像中所有的目标

    OpenCV提供的这个模板匹配的接口只能检测到其中的一个,为了能够匹配原图像中所有的目标,我简单的处理了一下,封装了一个API,直接输入原图像和模板等参数,就可以输出所有检测到的目标的坐标,源代码如下:

    #include <iostream> #include <opencv2/opencv.hpp> using namespace cv; using namespace std; void GetAllMinLoc(Mat image, Mat templ, double sim, Scalar mask, vector<Point> *all_min_loc); int main() { char *str_Input_Window_Title = "Read Image Window"; char *str_Template_Window_Title = "Template Window"; Mat img = imread("E:/chess.jpg");//从指定路径加载图像 Mat img_temp = imread("E:/chess_template.jpg"); if (!img.data || !img_temp.data)//加载图像失败 { printf("Fault to load image!\n\r"); return -1; } imshow(str_Input_Window_Title, img); imshow(str_Template_Window_Title, img_temp); //调用函数检测 vector<Point> P;//存储所有检测目标的坐标 GetAllMinLoc(img, img_temp, 0.05, Scalar(0,0,0), &P); //根据获取的全部坐标数据圈出待检测目标 for (int k = 0; k < P.size(); k++) { Point loc = P[k]; rectangle(img, Rect(loc.x, loc.y, img_temp.cols, img_temp.rows), Scalar(0, 0, 255), 2, 8); } imshow("Match_Result Window", img); waitKey(0); return 0; }

    运行结果:

    个人拙见,仅供参考;

    Processed: 0.041, SQL: 8