opencv 模板匹配方法汇总

在OpenCV中,模板匹配是一种在较大图像中查找特定模板图像位置的技术。OpenCV提供了多种模板匹配方法,通过cv2.matchTemplate函数实现,该函数支持的匹配方式主要有以下6种,下面详细介绍每种方法的原理、特点和适用场景。

1. cv2.TM_SQDIFF(平方差匹配法)

  • 原理:计算模板与图像中每个可能位置的像素值平方差的总和。匹配结果值越小,表示匹配程度越高。
  • 特点:对光照变化比较敏感,因为它直接比较像素值的差异。
  • 公式 : R ( x , y ) = ∑ 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'))^2 R(x,y)=∑x′,y′(T(x′,y′)−I(x+x′,y+y′))2,其中 T T T 是模板图像, I I I 是输入图像, R R R 是匹配结果图像。
  • 适用场景:适用于模板和目标图像的光照条件较为一致的情况。

2. cv2.TM_SQDIFF_NORMED(归一化平方差匹配法)

  • 原理 :是cv2.TM_SQDIFF的归一化版本,将平方差结果归一化到 [0, 1] 范围内。匹配结果值越接近 0,表示匹配程度越高。
  • 特点:对光照变化有一定的鲁棒性,因为归一化操作减少了不同图像之间像素值范围差异的影响。
  • 适用场景:当模板和目标图像的光照有一定差异,但差异不是特别大时适用。

3. cv2.TM_CCORR(相关性匹配法)

  • 原理:计算模板与图像中每个可能位置的像素值相关性。匹配结果值越大,表示匹配程度越高。
  • 特点:对光照变化也比较敏感,因为它直接依赖于像素值的相关性。
  • 公式 : R ( x , y ) = ∑ x ′ , y ′ ( T ( x ′ , y ′ ) ⋅ I ( x + x ′ , y + y ′ ) ) R(x,y)=\sum _{x',y'} (T(x',y') \cdot I(x + x',y + y')) R(x,y)=∑x′,y′(T(x′,y′)⋅I(x+x′,y+y′))
  • 适用场景:适用于模板和目标图像的光照条件较为一致,且模板和目标之间的亮度模式相似的情况。

4. cv2.TM_CCORR_NORMED(归一化相关性匹配法)

  • 原理 :是cv2.TM_CCORR的归一化版本,将相关性结果归一化到 [0, 1] 范围内。匹配结果值越接近 1,表示匹配程度越高。
  • 特点:对光照变化有较好的鲁棒性,因为归一化操作消除了不同图像之间像素值范围差异的影响。
  • 适用场景:在光照条件不稳定的情况下,是一种比较常用的匹配方法。

5. cv2.TM_CCOEFF(相关系数匹配法)

  • 原理:计算模板与图像中每个可能位置的像素值相关系数。匹配结果值越大,表示匹配程度越高。相关系数衡量的是两个信号之间的线性相关性。
  • 特点:对光照变化有一定的鲁棒性,因为它考虑了模板和图像的均值。
  • 适用场景:适用于模板和目标图像的光照有一定差异,但整体结构相似的情况。

6. cv2.TM_CCOEFF_NORMED(归一化相关系数匹配法)

  • 原理 :是cv2.TM_CCOEFF的归一化版本,将相关系数结果归一化到 [-1, 1] 范围内。匹配结果值越接近 1,表示匹配程度越高。
  • 特点:对光照变化具有较强的鲁棒性,是一种比较稳定的匹配方法。
  • 适用场景:在各种光照条件下都能有较好的表现,是最常用的模板匹配方法之一。

代码示例

python 复制代码
import cv2
import numpy as np

# 读取图像和模板
img = cv2.imread('image.jpg', 0)
template = cv2.imread('template.jpg', 0)
h, w = template.shape[:2]

# 定义匹配方法
methods = ['cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED', 'cv2.TM_CCORR',
           'cv2.TM_CCORR_NORMED', 'cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED']

for meth in methods:
    img2 = img.copy()
    method = eval(meth)

    # 执行模板匹配
    res = cv2.matchTemplate(img2, template, method)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

    # 根据不同的匹配方法确定最佳匹配位置
    if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
        top_left = min_loc
    else:
        top_left = max_loc
    bottom_right = (top_left[0] + w, top_left[1] + h)

    # 在图像上绘制矩形框标记匹配位置
    cv2.rectangle(img2, top_left, bottom_right, 255, 2)

    # 显示结果
    cv2.imshow(meth, img2)

cv2.waitKey(0)
cv2.destroyAllWindows()

这个示例代码展示了如何使用不同的模板匹配方法在图像中查找模板的位置,并在图像上绘制矩形框标记匹配结果。你可以根据实际需求选择合适的匹配方法。

cpp 复制代码
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

// 定义模板匹配方法名称和对应的枚举值
const char* method_names[] = { "TM_SQDIFF", "TM_SQDIFF_NORMED", "TM_CCORR",
                               "TM_CCORR_NORMED", "TM_CCOEFF", "TM_CCOEFF_NORMED" };
const int methods[] = { TM_SQDIFF, TM_SQDIFF_NORMED, TM_CCORR,
                        TM_CCORR_NORMED, TM_CCOEFF, TM_CCOEFF_NORMED };

int main()
{
    // 读取图像和模板
    Mat img = imread("image.jpg", IMREAD_GRAYSCALE);
    Mat template_img = imread("template.jpg", IMREAD_GRAYSCALE);

    if (img.empty() || template_img.empty())
    {
        cout << "Could not open or find the image or template" << endl;
        return -1;
    }

    int h = template_img.rows;
    int w = template_img.cols;

    // 遍历不同的匹配方法
    for (int i = 0; i < 6; i++)
    {
        Mat img2 = img.clone();
        Mat result;

        // 执行模板匹配
        matchTemplate(img2, template_img, result, methods[i]);

        double minVal, maxVal;
        Point minLoc, maxLoc;
        // 查找匹配结果中的最小值和最大值以及它们的位置
        minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);

        Point topLeft;
        bool isMatch = false;
        // 根据不同的匹配方法确定最佳匹配位置,并判断是否匹配成功
        if (methods[i] == TM_SQDIFF || methods[i] == TM_SQDIFF_NORMED)
        {
            topLeft = minLoc;
            if (methods[i] == TM_SQDIFF_NORMED && minVal < 0.1) // 可调整阈值
            {
                isMatch = true;
            }
        }
        else if (methods[i] == TM_CCORR_NORMED && maxVal > 0.8) // 可调整阈值
        {
            topLeft = maxLoc;
            isMatch = true;
        }
        else if (methods[i] == TM_CCOEFF_NORMED && maxVal > 0.8) // 可调整阈值
        {
            topLeft = maxLoc;
            isMatch = true;
        }

        if (isMatch)
        {
            Point bottomRight(topLeft.x + w, topLeft.y + h);
            // 在图像上绘制矩形框标记匹配位置
            rectangle(img2, topLeft, bottomRight, Scalar(255), 2);
        }
        else
        {
            cout << "No match found using " << method_names[i] << endl;
        }

        // 显示结果
        imshow(method_names[i], img2);
    }

    waitKey(0);
    destroyAllWindows();

    return 0;
}
相关推荐
__Benco7 分钟前
OpenHarmony平台驱动开发(十一),PIN
人工智能·驱动开发·harmonyos
拓端研究室TRL8 分钟前
CNN-LSTM、GRU、XGBoost、LightGBM风电健康诊断、故障与中国银行股票预测应用实例
人工智能·神经网络·cnn·gru·lstm
零炻大礼包20 分钟前
【coze】意图识别(售前售后问题、搜索引擎去广告)
人工智能·coze
小小毛桃21 分钟前
使用PyTorch训练马里奥强化学习代理的完整指南
人工智能·pytorch·python
南玖yy28 分钟前
内存安全革命:工具、AI 与政策驱动的 C 语言转型之路
c语言·开发语言·c++·人工智能·安全·c++23·c++基础语法
Dipeak数巅科技31 分钟前
数巅智能携手北京昇腾创新中心深耕行业大模型应用
人工智能·数据分析·商业智能bi
明朝百晓生33 分钟前
【Survival Analysis】【机器学习】【3】deepseek流程图
人工智能·机器学习
mzak33 分钟前
Linux系统(OpenEuler22.03-LTS)部署FastGPT
linux·人工智能·fastgpt
仙人掌_lz1 小时前
为特定领域微调嵌入模型:打造专属的自然语言处理利器
人工智能·ai·自然语言处理·embedding·强化学习·rl·bge
亚里随笔1 小时前
StreamRL:弹性、可扩展、异构的RLHF架构
人工智能·架构·大语言模型·rlhf·推理加速