使用 C/C++ 和 OpenCV 进行模板匹配

代码示例

在你运行此代码前,请确保你已经安装并配置好了 OpenCV 库。

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

int main() {
    // 1. 加载源图像和模板图像
    // 将 "source_image.jpg" 替换为你的源图像路径
    // 将 "template_image.jpg" 替换为你的模板图像路径
    cv::Mat srcImage = cv::imread("source_image.jpg", cv::IMREAD_COLOR);
    cv::Mat templateImage = cv::imread("template_image.jpg", cv::IMREAD_COLOR);

    // 检查图像是否成功加载
    if (srcImage.empty() || templateImage.empty()) {
        std::cerr << "错误: 无法加载图像!" << std::endl;
        return -1;
    }

    // 2. 创建用于存放结果的矩阵
    // 结果矩阵的尺寸: (W - w + 1, H - h + 1)
    // W, H 是源图像的宽高; w, h 是模板图像的宽高
    int result_cols = srcImage.cols - templateImage.cols + 1;
    int result_rows = srcImage.rows - templateImage.rows + 1;
    cv::Mat resultImage;
    resultImage.create(result_rows, result_cols, CV_32FC1);

    // 3. 执行模板匹配
    // TM_CCOEFF_NORMED 是一种常用的匹配算法,它返回归一化的相关系数
    // 结果越接近 1,表示匹配度越高
    cv::matchTemplate(srcImage, templateImage, resultImage, cv::TM_CCOEFF_NORMED);

    // 4. 找到最佳匹配位置
    double minVal, maxVal;
    cv::Point minLoc, maxLoc;
    cv::Point matchLoc;

    cv::minMaxLoc(resultImage, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat());

    // 对于 TM_CCOEFF_NORMED 方法,最佳匹配点是最大值所在的位置
    matchLoc = maxLoc;

    // 5. 在源图像上绘制矩形框来标记匹配区域
    cv::rectangle(srcImage, matchLoc,
                  cv::Point(matchLoc.x + templateImage.cols, matchLoc.y + templateImage.rows),
                  cv::Scalar(0, 255, 0), 2, 8, 0);

    // 6. 显示结果
    cv::imshow("匹配结果", srcImage);
    cv::imshow("模板图像", templateImage);

    // 等待用户按键后退出
    cv::waitKey(0);

    return 0;
}

如何编译和运行

你需要准备两张图片:

  • source_image.jpg: 你要在其中进行搜索的大图。
  • template_image.jpg: 你要搜索的小图(模板)。

将这两张图片与你的 C++ 文件放在同一个目录下。

编译命令 (以 g++ 为例):

假设你的 C++ 文件名为 match.cpp。你需要链接 OpenCV 库来编译它。请根据你自己的 OpenCV 安装路径来修改命令。

bash 复制代码
g++ match.cpp -o match `pkg-config --cflags --libs opencv4`

如果你没有使用 pkg-config,你需要手动指定头文件和库文件的路径:

bash 复制代码
g++ match.cpp -o match -I/path/to/opencv/include -L/path/to/opencv/lib -lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_imgcodecs

运行:

bash 复制代码
./match

程序会弹出两个窗口,一个显示模板图像,另一个显示源图像,并在源图像上用一个绿色矩形标出了最佳匹配位置。


代码讲解 📝

  1. 加载图像 (cv::imread): 读取源图像和模板图像。确保路径正确。
  2. 创建结果矩阵 (cv::Mat) : matchTemplate 函数的输出是一个浮点型的矩阵,其中每个像素值代表了在该点模板与源图像的匹配程度。
  3. 模板匹配 (cv::matchTemplate) : 这是核心函数。它将模板图像在源图像上滑动,并在每个位置计算一个相似度得分。
    • cv::TM_CCOEFF_NORMED 是众多匹配算法中的一种。它计算的是归一化相关系数,结果范围在 -1.0 到 1.0 之间,1.0 代表完美匹配。其他常用的方法还有 TM_SQDIFF_NORMED (值越小越好) 等。
  4. 定位最佳匹配 (cv::minMaxLoc) : 在结果矩阵中找到最大值 (最匹配) 和最小值 (最不匹配) 的位置。对于 TM_CCOEFF_NORMED 方法,我们关心的是最大值的位置 maxLoc
  5. 绘制矩形 (cv::rectangle) : 使用 maxLoc 作为左上角顶点,结合模板的尺寸,在源图像上画出矩形框,以可视化匹配结果。
  6. 显示图像 (cv::imshow) : 展示最终的结果。cv::waitKey(0) 会让程序暂停,直到用户按下任意键。
相关推荐
神仙别闹1 天前
基于QT(C++)实现学本科教务系统(URP系统)
数据库·c++·qt
deng-c-f1 天前
Linux C/C++ 学习日记(49):线程池
c++·学习·线程池
南棱笑笑生1 天前
20251217给飞凌OK3588-C开发板适配Rockchip原厂的Buildroot【linux-5.10】后调通ov5645【只能预览】
linux·c语言·开发语言·rockchip
ulias2121 天前
C++ 的容器适配器——从stack/queue看
开发语言·c++
daidaidaiyu1 天前
FFmpeg 关键的结构体
c++·ffmpeg
欧特克_Glodon1 天前
C++医学图像处理经典ITK库用法详解<一>:图像输入输出模块功能
c++·图像处理·itk
aduzhe1 天前
int32 - int32MAX 出现异常
c语言·stm32
一个不知名程序员www1 天前
算法学习入门---priority_queue(C++)
c++·算法
Pafey1 天前
C++的左值引用、右值引用以及转发和完美转发
c++
CoderCodingNo1 天前
【GESP】C++三级真题 luogu-B4414 [GESP202509 三级] 日历制作
开发语言·c++·算法