OpenCV11-图像的模版匹配

OpenCV11-图像的模版匹配


图像的模版匹配

前面通过图像直方图反向投影的方式在图像中寻找模版图像,由于直方图不能直接反映图像的纹理,因此,如果两幅不同的模版图像具有相同的直方图分布特性,那么在同一幅图中对着两幅模版图像的直方图进行反向投影,最终结果将不具有参考意义。

在图像中寻找模版图像时,可以直接通过比较图像像素的形式来搜索是否存在相同的内容,这种通过比较像素灰度值来寻找相同内容的方法称作图像的模版匹配。

OpenCV中提供了用于图像模版匹配的函数matchTemplate能够实现模版匹配过程中图像与模版相似性的计算:

cpp 复制代码
void matchTemplate(
    InputArray image,   // 原图 CV_8U或者CV_32F
    InputArray templ,   // 模板图
    OutputArray result, // 输出图像 CV_32F
    int method, // 模板匹配方法标志
    InputArray mask = noArray() // 匹配模板的掩码,通常情况下不使用,仅在 TM_SQDIFF和 TM_CCORR_NOrMED两种匹配方法中使用
);

第三个参数为相似性矩阵,滑动窗口与模板的相似性系数存放在滑动窗口左上角第一个像素出,因此输出的相似性矩阵尺寸小于原始图像的尺寸,如果原始图像尺寸为 W × H W \times H W×H ,模板图像尺寸为 w × h w \times h w×h ,那么相似性矩阵尺寸为 ( W − w + 1 ) × ( H − h + 1 ) (W-w+1) \times (H-h+1) (W−w+1)×(H−h+1) 。此外,无论输入的是彩色图像还是灰度图像,函数输出结果都是单通道矩阵。

第4个参数是滑动窗口与模板匹配方法标志也称作相似性系数。

cpp 复制代码
enum TemplateMatchModes {
    // 平方差匹配法
    TM_SQDIFF        = 0,
	// 归一化平方差匹配法
    TM_SQDIFF_NORMED = 1,
    // 相关匹配法
    TM_CCORR         = 2,
    // 归一化相关匹配法
    TM_CCORR_NORMED  = 3,
    // 系数匹配法
    TM_CCOEFF        = 4,
    // 归一化相关系数匹配法
    TM_CCOEFF_NORMED = 5
};

相似性系数公式:method公式计算方法

下面公式中, T T T 表示模版图像, I I I 表示原始图像。

0.TM_SQDIFF:两者匹配程度越低,计算数值越大。

R ( x , y ) = ∑ x ′ , y ′ ( T ( x ′ , y ′ ) − I ( x + x ′ , y + y ′ ) ) 2 R ( x , y ) = ∑ x ′ , y ′ ( ( T ( x ′ , y ′ ) − I ( x + x ′ , y + y ′ ) ) ⋅ M ( x ′ , y ′ ) ) 2 R(x,y) = \sum_{x',y'}(T(x', y') - I(x+x', y+y'))^2 \\ R(x,y) = \sum_{x',y'}((T(x', y') - I(x+x', y+y')) \cdot M(x',y'))^2 \\ R(x,y)=x′,y′∑(T(x′,y′)−I(x+x′,y+y′))2R(x,y)=x′,y′∑((T(x′,y′)−I(x+x′,y+y′))⋅M(x′,y′))2

1.TM_SQDIFF_NORMED:两者匹配程度越低,计算数值越大。
R ( x , y ) = ∑ x ′ , y ′ ( T ( x ′ , y ′ ) − I ( x + x ′ , y + y ′ ) ) 2 ∑ x ′ , y ′ T ( x ′ , y ′ ) 2 ⋅ ∑ x ′ , y ′ I ( x + x ′ , y + y ′ ) 2 R ( x , y ) = ∑ x ′ , y ′ ( ( T ( x ′ , y ′ ) − I ( x + x ′ , y + y ′ ) ) ⋅ M ( x ′ , y ′ ) ) 2 ∑ x ′ , y ′ ( T ( x ′ , y ′ ) ⋅ M ( x ′ , y ′ ) ) 2 ⋅ ∑ x ′ , y ′ ( I ( x + x ′ , y + y ′ ) ⋅ M ( x ′ , y ′ ) ) 2 R(x,y) = \frac{\sum_{x',y'}(T(x', y') - I(x+x', y+y'))^2}{\sqrt{\sum_{x',y'}T(x',y')^2 · \sum_{x',y'}I(x+x',y+y')^2}} \\ R(x,y) = \frac{\sum_{x',y'}((T(x', y') - I(x+x', y+y')) \cdot M(x',y'))^2}{\sqrt{\sum_{x',y'}(T(x',y') \cdot M(x',y'))^2 · \sum_{x',y'}(I(x+x',y+y') \cdot M(x',y'))^2}} \\ R(x,y)=∑x′,y′T(x′,y′)2⋅∑x′,y′I(x+x′,y+y′)2 ∑x′,y′(T(x′,y′)−I(x+x′,y+y′))2R(x,y)=∑x′,y′(T(x′,y′)⋅M(x′,y′))2⋅∑x′,y′(I(x+x′,y+y′)⋅M(x′,y′))2 ∑x′,y′((T(x′,y′)−I(x+x′,y+y′))⋅M(x′,y′))2

2.TM_CCORR:数值越大匹配效果越好,0表示最坏匹配结果。
R ( x , y ) = ∑ x ′ , y ′ ( T ( x ′ , y ′ ) ⋅ I ( x + x ′ , y + y ′ ) ) R ( x , y ) = ∑ x ′ , y ′ ( ( T ( x ′ , y ′ ) ⋅ I ( x + x ′ , y + y ′ ) ) ⋅ M ( x ′ , y ′ ) 2 ) R(x,y) = \sum_{x',y'}(T(x', y') \cdot I(x+x', y+y')) \\ R(x,y) = \sum_{x',y'}((T(x', y') \cdot I(x+x', y+y')) \cdot M(x',y')^2) \\ R(x,y)=x′,y′∑(T(x′,y′)⋅I(x+x′,y+y′))R(x,y)=x′,y′∑((T(x′,y′)⋅I(x+x′,y+y′))⋅M(x′,y′)2)

3.TM_CCORR_NORMED:完全匹配时结果为1,完全不匹配结果为0
R ( x , y ) = ∑ x ′ , y ′ ( T ( x ′ , y ′ ) ⋅ I ( x + x ′ , y + y ′ ) ) ∑ x ′ , y ′ T ( x ′ , y ′ ) 2 ⋅ ∑ x ′ , y ′ I ( x + x ′ , y + y ′ ) 2 R ( x , y ) = ∑ x ′ , y ′ ( T ( x ′ , y ′ ) ⋅ I ( x + x ′ , y + y ′ ) ⋅ M ( x ′ , y ′ ) 2 ) ∑ x ′ , y ′ ( T ( x ′ , y ′ ) ⋅ M ( x ′ , y ′ ) ) 2 ⋅ ∑ x ′ , y ′ ( I ( x + x ′ , y + y ′ ) ⋅ M ( x ′ , y ′ ) ) 2 R(x,y) = \frac{\sum_{x',y'}(T(x', y') \cdot I(x+x', y+y'))}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'}I(x+x',y+y')^2}} \\ R(x,y) = \frac{\sum_{x',y'}(T(x', y') \cdot I(x+x', y+y') \cdot M(x',y')^2)}{\sqrt{\sum_{x',y'}(T(x',y') \cdot M(x',y'))^2 \cdot \sum_{x',y'}(I(x+x',y+y') \cdot M(x',y'))^2}} \\ R(x,y)=∑x′,y′T(x′,y′)2⋅∑x′,y′I(x+x′,y+y′)2 ∑x′,y′(T(x′,y′)⋅I(x+x′,y+y′))R(x,y)=∑x′,y′(T(x′,y′)⋅M(x′,y′))2⋅∑x′,y′(I(x+x′,y+y′)⋅M(x′,y′))2 ∑x′,y′(T(x′,y′)⋅I(x+x′,y+y′)⋅M(x′,y′)2)

4.TM_CCOEFF:这种方法采用相关匹配法对模版减去均值的结果和原始图像减去均值的结果进行匹配,可以很好地解决模版图像和原始图像之间由于亮度不同而产生的影响。匹配程度越高数值越大,匹配程度越低数值越小,结果可以为负值。
R ( x , y ) = ∑ x ′ , y ′ ( T ′ ( x ′ , y ′ ) ⋅ I ′ ( x + x ′ , y + y ′ ) ) 其中 { T ′ ( x ′ , y ′ ) = T ( x ′ , y ′ ) − 1 w ⋅ h ∑ x ′ ′ , y ′ ′ T ( x ′ ′ , y ′ ′ ) I ′ ( x ′ , y ′ ) = I ( x + x ′ , y + y ′ ) − 1 w ⋅ h ∑ x ′ ′ , y ′ ′ I ( x + x ′ ′ , y + y ′ ′ ) R(x,y) = \sum_{x',y'}(T'(x', y') \cdot I'(x+x', y+y')) \\ 其中\left\{ \begin{array}{ll} T'(x',y') = T(x',y') - \frac{1}{w \cdot h}\sum_{x'',y''}T(x'',y'') \\ I'(x',y') = I(x+x',y+y') - \frac{1}{w \cdot h} \sum_{x'',y''}I(x+x'',y+y'') \\ \end{array} \right. R(x,y)=x′,y′∑(T′(x′,y′)⋅I′(x+x′,y+y′))其中{T′(x′,y′)=T(x′,y′)−w⋅h1∑x′′,y′′T(x′′,y′′)I′(x′,y′)=I(x+x′,y+y′)−w⋅h1∑x′′,y′′I(x+x′′,y+y′′)

5.TM_CCOEFF_NORMED:归一化到1~-1之间,完全匹配数值为1,完全不匹配数值为-1。
R ( x , y ) = ∑ x ′ , y ′ ( T ′ ( x ′ , y ′ ) ⋅ I ′ ( x + x ′ , y + y ′ ) ) ∑ x ′ , y ′ T ′ ( x ′ , y ′ ) 2 ⋅ ∑ x ′ , y ′ I ′ ( x + x ′ , y + y ′ ) 2 R(x,y) = \frac{\sum_{x',y'}(T'(x', y') \cdot I'(x+x', y+y'))}{\sqrt{ \sum_{x',y'}T'(x', y')^2 \cdot \sum_{x',y'}I'(x+x', y+y')^2 }} \\ R(x,y)=∑x′,y′T′(x′,y′)2⋅∑x′,y′I′(x+x′,y+y′)2 ∑x′,y′(T′(x′,y′)⋅I′(x+x′,y+y′))


示例:

cpp 复制代码
#include <opencv2/core/utils/logger.hpp>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
	cout << "OpenCV Version: " << CV_VERSION << endl;
	utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);

	Mat img = imread("lena.png");
	Mat temp = imread("lena_face.png");
	if (img.empty() || temp.empty())
	{
		cout << "请确认图像文件名称是否正确" << endl;
		return -1;
	}
	cout << "img.size(): " << img.size() << endl; // [512 x 512]
	cout << "img_template.size(): " << temp.size() << endl; // [164 x 172]

	Mat result;
	matchTemplate(img, temp, result, TM_CCOEFF_NORMED);//模板匹配
	cout << "result.size(): " << result.size() << endl; // [349 x 341]

	double maxVal, minVal;
	Point minLoc, maxLoc;
	//寻找匹配结果中的最大值和最小值以及坐标位置
	minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);
	//绘制最佳匹配区域
	rectangle(img, cv::Rect(maxLoc.x, maxLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2);
	imshow("原图", img);
	imshow("模板图像", temp);
	imshow("result", result);

	int k = waitKey(0); // Wait for a keystroke in the window
	return 0;
}
相关推荐
蜀黍@猿14 分钟前
【C++ 基础】从C到C++有哪些变化
c++
Am心若依旧40915 分钟前
[c++11(二)]Lambda表达式和Function包装器及bind函数
开发语言·c++
zh路西法25 分钟前
【C++决策和状态管理】从状态模式,有限状态机,行为树到决策树(一):从电梯出发的状态模式State Pattern
c++·决策树·状态模式
轩辰~39 分钟前
网络协议入门
linux·服务器·开发语言·网络·arm开发·c++·网络协议
lxyzcm1 小时前
C++23新特性解析:[[assume]]属性
java·c++·spring boot·c++23
蜀黍@猿1 小时前
C/C++基础错题归纳
c++
雨中rain2 小时前
Linux -- 从抢票逻辑理解线程互斥
linux·运维·c++
游客5202 小时前
opencv中的常用的100个API
图像处理·人工智能·python·opencv·计算机视觉
ALISHENGYA3 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战项目二)
数据结构·c++·算法
arong_xu3 小时前
现代C++锁介绍
c++·多线程·mutex