OpenCV自学(二)——模板匹配函数详解

matchTemplate函数的源代码在OpenCV的源代码目录下的 modules/imgproc/src/templmatch.cpp 文件中。其核心函数代码如下:

void matchTemplate( const Mat& _img, const Mat& _templ, Mat& result, int method )
{
    CV_Assert( CV_TM_SQDIFF <= method && method <= CV_TM_CCOEFF_NORMED );
    //numType用来表示模板匹配的方式,0表示相关匹配法,1表示相关系数匹配法,2表示平方差匹配法
    //isNormed表示是否进行归一化处理,true表示进行归一化,false表示不进行归一化处理
    int numType = method == CV_TM_CCORR || method == CV_TM_CCORR_NORMED ? 0 :
                  method == CV_TM_CCOEFF || method == CV_TM_CCOEFF_NORMED ? 1 : 2;
    bool isNormed = method == CV_TM_CCORR_NORMED ||
                    method == CV_TM_SQDIFF_NORMED ||
                    method == CV_TM_CCOEFF_NORMED;
    //判断两幅图像的大小关系,如果输入的原始图像比匹配图像要小,则将原始图像作为模板,原来的模板图像作为搜索图
    Mat img = _img, templ = _templ;
    if( img.rows < templ.rows || img.cols < templ.cols )
        std::swap(img, templ);
    
    CV_Assert( (img.depth() == CV_8U || img.depth() == CV_32F) &&
               img.type() == templ.type() );
   //crossCorr函数是将输入图像做了一次DFT变换(离散傅里叶变换),将空间域的图像转换到频率域中来进行处理,并将处理的结果存放在result中
    int cn = img.channels();
    crossCorr( img, templ, result,
               Size(img.cols - templ.cols + 1, img.rows - templ.rows + 1),
               CV_32F, Point(0,0), 0, 0);
    //如果是相关匹配方法,此处已经计算完毕,返回
    if( method == CV_TM_CCORR )
        return;
    //将模板看作单位1,计算每一个像元所占的百分比(也可以理解为整个模板面积为1,计算每个像元的面积)
    double invArea = 1./((double)templ.rows * templ.cols);
    Mat sum, sqsum;
    Scalar templMean, templSdv;
    double *q0 = 0, *q1 = 0, *q2 = 0, *q3 = 0;
    double templNorm = 0, templSum2 = 0;
    //相关系数匹配算法
    if( method == CV_TM_CCOEFF )
    {
        integral(img, sum, CV_64F);//对原始图像进行求和
        templMean = mean(templ);//计算模板图像的均值向量
    }
    else//其他匹配算法
    {
        integral(img, sum, sqsum, CV_64F);//计算原始图像的和以及平方和
        meanStdDev( templ, templMean, templSdv );//计算模板图像的均值向量和方差向量
        templNorm = CV_SQR(templSdv[0]) + CV_SQR(templSdv[1]) +
                    CV_SQR(templSdv[2]) + CV_SQR(templSdv[3]);//计算所有通道的方差和
        if( templNorm < DBL_EPSILON && method == CV_TM_CCOEFF_NORMED )
        {//如果所有通道的方差的和等于0,并且使用的方法是归一化相关系数匹配方法,则返回
            result = Scalar::all(1);
            return;
        }
        
        templSum2 = templNorm +
                     CV_SQR(templMean[0]) + CV_SQR(templMean[1]) +
                     CV_SQR(templMean[2]) + CV_SQR(templMean[3]);//计算所有通道的均值的平方和
        if( numType != 1 )//匹配方式不是相关系数,对模板均值向量和templNorm重新赋值
        {
            templMean = Scalar::all(0);
            templNorm = templSum2;
        }
        
        templSum2 /= invArea;
        templNorm = sqrt(templNorm);
        templNorm /= sqrt(invArea); // care of accuracy here
        q0 = (double*)sqsum.data;
        q1 = q0 + templ.cols*cn;
        q2 = (double*)(sqsum.data + templ.rows*sqsum.step);
        q3 = q2 + templ.cols*cn;
    }
    //下面就是在结果图像中进行查找匹配的结果位置,代码略去,具体可参考OpenCV源代码

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Opencv3.2中的模板匹配函数是`cv2.matchTemplate()`。该函数用于在图像中寻找与给定模板匹配的区域。 函数的语法如下: ``` cv2.matchTemplate(image, template, method[, result[, mask]]) ``` 参数解释: - `image`:待搜索的输入图像。 - `template`:要匹配模板图像。 - `method`:匹配方法,指定了用于比较模板和输入图像的算法。常用的方法有: - `cv2.TM_SQDIFF`:平方差匹配法。 - `cv2.TM_SQDIFF_NORMED`:归一化平方差匹配法。 - `cv2.TM_CCORR`:相关匹配法。 - `cv2.TM_CCORR_NORMED`:归一化相关匹配法。 - `cv2.TM_CCOEFF`:相关系数匹配法。 - `cv2.TM_CCOEFF_NORMED`:归一化相关系数匹配法。 - `result`:可选参数,输出的匹配结果图像。 - `mask`:可选参数,掩码图像。如果提供了掩码图像,则只有掩码对应位置的像素才参与匹配函数返回一个包含匹配结果的灰度图像。你可以使用`cv2.minMaxLoc()`函数找到最佳匹配位置的坐标。 示例代码: ```python import cv2 import numpy as np # 读取输入图像和模板图像 image = cv2.imread('image.jpg') template = cv2.imread('template.jpg') # 进行模板匹配 result = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED) # 找到最佳匹配位置的坐标 min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) top_left = max_loc bottom_right = (top_left[0] + template.shape[1], top_left[1] + template.shape[0]) # 在原图像中标记匹配区域 cv2.rectangle(image, top_left, bottom_right, (0, 255, 0), 2) # 显示结果图像 cv2.imshow('Matched Image', image) cv2.waitKey(0) cv2.destroyAllWindows() ``` 这是一个简单的模板匹配示例,你可以根据自己的需求进行更复杂的操作和参数调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值