OpenCV之图像处理(二十八) 模板匹配(Template Match)

模板匹配介绍
    模板匹配就是在整个图像区域发现与给定子图像匹配的小块区域。
    所以模板匹配首先需要一个模板图像T(给定的子图像)
    另外需要一个待检测的图像-源图像S
    工作方法,在带检测图像上,从左到右,从上向下计算模板图像与重叠子图像的匹配度,匹配程度越大,两者相同的可能性越大。

OpenCV中提供了六种常见的匹配算法如下:  计算公式参考 源码 TemplateMatchModes 的注释
    1. 计算平方不同               计算出来的值越小,越相关        TM_SQDIFF        = 0
    2. 计算相关性                计算出来的值越大,越相关        TM_CCORR         = 2
    3. 计算相关系数               计算出来的值越大,越相关        TM_CCOEFF        = 4
    4. 计算归一化平方不同        计算出来的值越接近0,越相关      TM_SQDIFF_NORMED = 1
    5. 计算归一化相关性         计算出来的值越接近1,越相关      TM_CCORR_NORMED  = 3
    6. 计算归一化相关系数        计算出来的值越接近1,越相关      TM_CCOEFF_NORMED = 5    建议使用归一化的方法

matchTemplate(
    InputArray image,// 源图像,必须是8-bit或者32-bit浮点数图像
    InputArray templ,// 模板图像,类型与输入图像一致
    OutputArray result,// 输出结果,必须是单通道32位浮点数,假设源图像WxH,模板图像wxh, 则结果必须为W-w+1, H-h+1的大小。
    int method,// 使用的匹配方法
    InputArray mask=noArray()//(optional)
)

代码

    #include "../common/common.hpp"

    static Mat src, temp, dst;
    static char title[] = "ret28";
    static int match_method = TM_SQDIFF;
    static int max_track = 5;

    static void match(int, void*);

    void main(int argc, char** argv)
    {
        src = imread(getCVImagesPath("images/test1.png"), IMREAD_COLOR);
        temp = imread(getCVImagesPath("images/sample.png"), IMREAD_COLOR);

        namedWindow(title, CV_WINDOW_AUTOSIZE);
        createTrackbar("match:", title, &match_method, max_track, match);
        match(0, 0);

        waitKey(0);
    }

    void match(int, void*)
    {
        int width = src.cols - temp.cols + 1;
        int height = src.rows - temp.rows + 1;
        Mat result(width, height, CV_32FC1);

        matchTemplate(src, temp, result, match_method, Mat());//当TM_CCORR时,匹配不准确,OpenCV本身算法导致的?
        normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());//matchTemplate的计算结果不定,归一

        Point minLoc;
        Point maxLoc;
        double min, max;
        src.copyTo(dst);
        minMaxLoc(result, &min, &max, &minLoc, &maxLoc, Mat());//寻找result中最大值,最小值,及它们所在的位置
        Point temLoc;
        if (match_method == TM_SQDIFF || match_method == TM_SQDIFF_NORMED) {
            temLoc = minLoc;
        }
        else {
            temLoc = maxLoc;
        }

        // 绘制矩形
        rectangle(dst, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2, LINE_8);
        rectangle(result, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2, LINE_8);

        imshow(title, result);
        imshow("matchTemplate", dst);
    }

效果图

这里写图片描述

猜你喜欢

转载自blog.csdn.net/huanghuangjin/article/details/81180568