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;
}
相关推荐
BulingQAQ2 小时前
论文阅读:PET/CT Cross-modal medical image fusion of lung tumors based on DCIF-GAN
论文阅读·深度学习·生成对抗网络·计算机视觉·gan
家有狸花2 小时前
VSCODE驯服日记(三):配置C++环境
c++·ide·vscode
dengqingrui1233 小时前
【树形DP】AT_dp_p Independent Set 题解
c++·学习·算法·深度优先·图论·dp
C++忠实粉丝3 小时前
前缀和(8)_矩阵区域和
数据结构·c++·线性代数·算法·矩阵
ZZZ_O^O3 小时前
二分查找算法——寻找旋转排序数组中的最小值&点名
数据结构·c++·学习·算法·二叉树
CV-King4 小时前
opencv实战项目(三十):使用傅里叶变换进行图像边缘检测
人工智能·opencv·算法·计算机视觉
禁默4 小时前
2024年计算机视觉与艺术研讨会(CVA 2024)
人工智能·计算机视觉
春末的南方城市6 小时前
FLUX的ID保持项目也来了! 字节开源PuLID-FLUX-v0.9.0,开启一致性风格写真新纪元!
人工智能·计算机视觉·stable diffusion·aigc·图像生成
小飞猪Jay6 小时前
C++面试速通宝典——13
jvm·c++·面试
jndingxin6 小时前
OpenCV视频I/O(14)创建和写入视频文件的类:VideoWriter介绍
人工智能·opencv·音视频