本文共 3560 字,大约阅读时间需要 11 分钟。
模板匹配是一种图像处理技术,旨在在给定图像中找到与模板图像最相似的区域。这种方法在图像分析、图像识别等领域有广泛应用。以下将详细介绍模板匹配的基础理论、实现方法以及使用OpenCV库进行模板匹配的具体操作。
模板匹配通过将模板图像在目标图像上滑动,逐像素计算匹配度,找到最相似区域。匹配度的计算基于不同基准方法,常见的包括平方差(SQDIFF)、归一化平方差(SQDIFF NORMED)、协方差(CCORR)和协方差归一化(CCORR NORMED)等。其中,SQDIFF方法通过找到最小值来确定匹配区域,而CCORR和CCORR NORMED方法则通过找到最大值来实现。
模板匹配过程类似于图像的空间卷积操作。假设模板的宽度为ω,高度为h,目标图像的宽度为W,高度为H。经过匹配后,结果图像的宽度将为W - ω + 1,高度为H - h + 1。
在OpenCV库中,matchTemplate函数用于实现模板匹配。该函数接收以下参数:
函数返回匹配结果图像,匹配区域的坐标也可通过minMaxLoc函数获取。
在支持mask的匹配方法(如SQDIFF和CCORR NORMED)中,可以通过mask图像来限制匹配区域的有效范围。mask图像中的每个像素值(0或1)表示对应位置是否参与匹配。1表示有效区域,0表示无效区域。
以下是使用OpenCV库进行模板匹配的代码示例:
#include#include #include #include using namespace std;bool use_mask = false;cv::Mat img, templ, mask, res;const char *img_window = "Source";const char *res_window = "Result";int match_method = 0;int max_trackbar = 5;void MatchingMethod(int, void *) { cv::Mat img_display = img.clone(); int res_width = img.cols - templ.cols + 1; int res_height = img.rows - templ.rows + 1; res.create(res_height, res_width, CV_32FC1); bool method_accepts_mask = (match_method == cv::TM_SQDIFF || match_method == cv::TM_CCORR_NORMED); if (use_mask && method_accepts_mask) { cv::matchTemplate(img, templ, res, match_method, mask); } else { cv::matchTemplate(img, templ, res, match_method); } cv::normalize(res, res, 0, 1, cv::NORM_MINMAX, -1, cv::Mat()); double min_val, max_val; cv::Point min_loc, max_loc, match_loc; cv::minMaxLoc(res, &min_val, &max_val, &min_loc, &max_loc, cv::Mat()); match_loc = (match_method == cv::TM_SQDIFF || match_method == cv::TM_SQDIFF_NORMED) ? min_loc : max_loc; cv::rectangle(img_display, match_loc, cv::Point(match_loc.x + templ.cols, match_loc.y + templ.rows), cv::Scalar::all(0), 2, 9, 0); cv::rectangle(res, match_loc, cv::Point(match_loc.x + templ.cols, match_loc.y + templ.rows), cv::Scalar::all(0), 2, 9, 0); cout << "===》》》 template match res size: " << res.size << endl; cv::imwrite("display_img.png", img_display); cv::imwrite("res_match.png", res);}int main(int argc, char **argv) { if (argc < 3) { cout << "Not enough parameters" << endl; cout << "Usage:" << endl << argv[0] << " [" << " " << "]" << endl; return -1; } img = cv::imread(argv[1], cv::IMREAD_COLOR); templ = cv::imread(argv[2], cv::IMREAD_COLOR); if (argc > 3) { use_mask = true; mask = cv::imread(argv[3], cv::IMREAD_COLOR); } if (img.empty() || templ.empty() || (use_mask && mask.empty())) { cout << "Can't read one of the images" << endl; return EXIT_FAILURE; } cv::namedWindow(img_window, cv::WINDOW_AUTOSIZE); cv::namedWindow(res_window, cv::WINDOW_AUTOSIZE); const char *trackbar_label = "Method:\n 0: SQDIFF \n 1: SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED"; cv::createTrackbar(trackbar_label, img_window, &match_method, max_trackbar, MatchingMethod); MatchingMethod(0, 0); cv::waitKey(0); return EXIT_SUCCESS; }
匹配完成后,结果图像的宽度将为W - ω + 1,高度为H - h + 1。通过cv::rectangle函数可以在目标图像和结果图像中绘制匹配区域,帮助用户直观查看匹配结果。
这种方法在图像识别、图像修复等领域有广泛应用,能够有效地定位模板图像在目标图像中的位置。
转载地址:http://kohfk.baihongyu.com/