导读
本文将重点介绍 OpenCV带掩码(mask)的模板匹配使用技巧与演示。(来源公众号:OpenCV与AI深度学习)
背景介绍
在使用模板匹配时,一些特定情况中我们并不需要将整个模板图像拿来匹配,而只需要其中特定的部分做模板,其他部分则加入反而会影响匹配结果。如下图所示:
原本左边的模板图除了我们想要的部分外,还有外部的白色背景区域,如果将整张图作为模板,来做模板匹配,匹配结果会出错,结果如下:
加上掩码后匹配,结果如下:
详细步骤
在核心方法还是使用OpenCV的matchTemplate函数,只是这次我们要指定mask(掩码),匹配时对于掩码中的非0像素匹配算法起作用,掩码中的灰度值为0像素位置,匹配算法不起作用。
【1】通过模板图像获得掩码图像。
这里获取掩码的方法不唯一,可以通过预先加载获得,可以通过二值化,图像分割等手段获得,最终的掩码图像需要与模板图像大小一致,同时为单通道图像,mask的非0像素对应的位置就是我们关心的匹配内容,灰度值为的0像素对应的位置则是无关内容。本文是通过二值化获得如下右图的mask图像:
代码语言:javascript复制Mat mask;
cvtColor(temp, mask, COLOR_BGR2GRAY);
threshold(mask, mask, 10, 255, THRESH_BINARY);
imshow("mask", mask);
【2】模板匹配,指定mask参数为步骤【1】获得的掩码图像。
代码语言:javascript复制matchTemplate(src, temp, result, TM_CCOEFF_NORMED, mask);
匹配结果与源码如下:
实例一:
实例二:
实例三:
代码语言:javascript复制// 公众号:OpenCV与AI深度学习
// 作 者:Color Space
#include "pch.h"
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
void main()
{
///单模板匹配
Mat img = imread("A2.png");
Mat temp = img(Rect(420, 20, 90, 90)).clone();
imshow("ROI", temp);
waitKey();
Mat src = img(Rect(0, 0, 400, img.rows)); //待搜索图像
imshow("temp", temp);
imshow("src", src);
Mat mask;
cvtColor(temp, mask, COLOR_BGR2GRAY);
threshold(mask, mask, 10, 255, THRESH_BINARY);
imshow("mask", mask);
Mat dst = src.clone(); //原图备份
int width = src.cols - temp.cols 1; //result 宽度
int height = src.rows - temp.rows 1; //result 高度
Mat result(height, width, CV_32FC1); //创建结果映射图像
matchTemplate(src, temp, result, TM_CCOEFF_NORMED, mask); //化相关系数匹配最佳值 1
imshow("result", result);
//normalize(result, result, 0, 1, NORM_MINMAX, -1); //归一化到0--1范围
double minValue, maxValue;
Point minLoc, maxLoc;
minMaxLoc(result, &minValue, &maxValue, &minLoc, &maxLoc);
cout<<"minValue="<<minValue<<endl;
cout<<"maxValue="<<maxValue<<endl;
rectangle(dst, maxLoc, Point(maxLoc.x temp.cols, maxLoc.y temp.rows), Scalar(0, 255, 0), 2, 8);
imshow("dst", dst);
waitKey(0);
}