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;
}
相关推荐
凤枭香16 分钟前
Python OpenCV 傅里叶变换
开发语言·图像处理·python·opencv
ULTRA??19 分钟前
C加加中的结构化绑定(解包,折叠展开)
开发语言·c++
凌云行者1 小时前
OpenGL入门005——使用Shader类管理着色器
c++·cmake·opengl
凌云行者1 小时前
OpenGL入门006——着色器在纹理混合中的应用
c++·cmake·opengl
ctrey_1 小时前
2024-11-4 学习人工智能的Day21 openCV(3)
人工智能·opencv·学习
~yY…s<#>1 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode
可均可可2 小时前
C++之OpenCV入门到提高004:Mat 对象的使用
c++·opencv·mat·imread·imwrite
白子寰2 小时前
【C++打怪之路Lv14】- “多态“篇
开发语言·c++
小芒果_013 小时前
P11229 [CSP-J 2024] 小木棍
c++·算法·信息学奥赛
蒙娜丽宁3 小时前
《Python OpenCV从菜鸟到高手》——零基础进阶,开启图像处理与计算机视觉的大门!
python·opencv·计算机视觉