导读

本文将重点介绍 OpenCV带掩码(mask)的模板匹配使用技巧与演示。(公众号:OpenCV与AI深度学习)

 背景介绍

    在使用模板匹配时,一些特定情况中我们并不需要将整个模板图像拿来匹配,而只需要其中特定的部分做模板,其他部分则加入反而会影响匹配结果。如下图所示: 

实战 | OpenCV带掩码(mask)的模板匹配使用技巧与演示(附源码)_模板匹配

原本左边的模板图除了我们想要的部分外,还有外部的白色背景区域,如果将整张图作为模板,来做模板匹配,匹配结果会出错,结果如下:

实战 | OpenCV带掩码(mask)的模板匹配使用技巧与演示(附源码)_#include_02

加上掩码后匹配,结果如下:

实战 | OpenCV带掩码(mask)的模板匹配使用技巧与演示(附源码)_深度学习_03

实战 | OpenCV带掩码(mask)的模板匹配使用技巧与演示(附源码)_模板匹配_04

详细步骤

    在核心方法还是使用OpenCV的matchTemplate函数,只是这次我们要指定mask(掩码),匹配时对于掩码中的非0像素匹配算法起作用,掩码中的灰度值为0像素位置,匹配算法不起作用

实战 | OpenCV带掩码(mask)的模板匹配使用技巧与演示(附源码)_模板匹配_05

【1】通过模板图像获得掩码图像。

这里获取掩码的方法不唯一,可以通过预先加载获得,可以通过二值化,图像分割等手段获得,最终的掩码图像需要与模板图像大小一致,同时为单通道图像,mask的非0像素对应的位置就是我们关心的匹配内容,灰度值为的0像素对应的位置则是无关内容。本文是通过二值化获得如下右图的mask图像:

实战 | OpenCV带掩码(mask)的模板匹配使用技巧与演示(附源码)_深度学习_03

Mat mask;
cvtColor(temp, mask, COLOR_BGR2GRAY);
threshold(mask, mask, 10, 255, THRESH_BINARY);
imshow("mask", mask);

【2】模板匹配,指定mask参数为步骤【1】获得的掩码图像。

matchTemplate(src, temp, result, TM_CCOEFF_NORMED, mask);

匹配结果与源码如下:

实例一:

实战 | OpenCV带掩码(mask)的模板匹配使用技巧与演示(附源码)_#include_07

实战 | OpenCV带掩码(mask)的模板匹配使用技巧与演示(附源码)_#include_08

实例二:

实战 | OpenCV带掩码(mask)的模板匹配使用技巧与演示(附源码)_模板匹配_09

实战 | OpenCV带掩码(mask)的模板匹配使用技巧与演示(附源码)_模板匹配_10

实例三:

实战 | OpenCV带掩码(mask)的模板匹配使用技巧与演示(附源码)_模板匹配_11

实战 | OpenCV带掩码(mask)的模板匹配使用技巧与演示(附源码)_深度学习_12

// 公众号: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);
}


—THE END—


觉得有用,记得点个赞