基于 OpenCV 的模板匹配算法的 C 语言实现

c 复制代码
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <stdio.h>

int main() {
    // 1. 读取目标图像和模板图像
    IplImage* target = cvLoadImage("target.jpg", CV_LOAD_IMAGE_COLOR);
    IplImage* template_img = cvLoadImage("template.jpg", CV_LOAD_IMAGE_COLOR);
    
    if(!target || !template_img) {
        printf("错误:无法加载图像!\n");
        return -1;
    }

    // 2. 获取模板尺寸
    int width = template_img->width;
    int height = template_img->height;
    
    // 3. 创建匹配结果矩阵
    CvSize result_size;
    result_size.width = target->width - width + 1;
    result_size.height = target->height - height + 1;
    
    IplImage* result = cvCreateImage(result_size, IPL_DEPTH_32F, 1);
    
    // 4. 执行模板匹配(使用归一化相关系数法)
    cvMatchTemplate(target, template_img, result, CV_TM_CCOEFF_NORMED);
    
    // 5. 寻找最佳匹配位置
    double min_val, max_val;
    CvPoint min_loc, max_loc;
    cvMinMaxLoc(result, &min_val, &max_val, &min_loc, &max_loc, NULL);
    
    printf("最高相似度: %.2f\n", max_val);
    
    // 6. 设置匹配阈值(0-1之间)
    double threshold = 0.8;
    
    if(max_val >= threshold) {
        // 7. 绘制匹配矩形(绿色)
        cvRectangle(
            target,
            max_loc,
            cvPoint(max_loc.x + width, max_loc.y + height),
            CV_RGB(0, 255, 0),
            2
        );
        
        printf("匹配位置: (%d, %d)\n", max_loc.x, max_loc.y);
    } else {
        printf("未找到匹配项!\n");
    }
    
    // 8. 显示结果
    cvNamedWindow("目标图像", CV_WINDOW_AUTOSIZE);
    cvShowImage("目标图像", target);
    
    cvNamedWindow("模板图像", CV_WINDOW_AUTOSIZE);
    cvShowImage("模板图像", template_img);
    
    // 9. 等待按键
    cvWaitKey(0);
    
    // 10. 清理资源
    cvReleaseImage(&target);
    cvReleaseImage(&template_img);
    cvReleaseImage(&result);
    cvDestroyAllWindows();
    
    return 0;
}

编译与运行

bash 复制代码
# 编译(需安装OpenCV开发库)
gcc template_matching.c -o tm `pkg-config --cflags --libs opencv`

# 运行
./tm

关键函数说明

  1. cvMatchTemplate() - 核心匹配函数

    c 复制代码
    void cvMatchTemplate(
        const CvArr* image,      // 目标图像
        const CvArr* templ,      // 模板图像
        CvArr* result,           // 结果矩阵
        int method               // 匹配方法
    );

    支持的匹配方法:

    • CV_TM_SQDIFF:平方差匹配法
    • CV_TM_CCORR:相关匹配法
    • CV_TM_CCOEFF:相关系数匹配法
    • 加上_NORMED后缀表示归一化版本(推荐)
  2. cvMinMaxLoc() - 查找极值位置

    c 复制代码
    void cvMinMaxLoc(
        const CvArr* arr,        // 输入数组
        double* min_val,          // 最小值指针
        double* max_val,          // 最大值指针
        CvPoint* min_loc,         // 最小值位置
        CvPoint* max_loc,         // 最大值位置
        const CvArr* mask = NULL  // 可选掩码
    );

多目标匹配增强版

c 复制代码
// 在找到最大值后添加多目标处理:
CvPoint* locations = NULL;
int match_count = 0;
double threshold = 0.75;

// 获取所有高于阈值的匹配位置
for(int y = 0; y < result->height; y++) {
    float* row = (float*)(result->imageData + y * result->widthStep);
    for(int x = 0; x < result->width; x++) {
        if(row[x] >= threshold) {
            match_count++;
            locations = (CvPoint*)realloc(locations, match_count * sizeof(CvPoint));
            locations[match_count-1] = cvPoint(x, y);
        }
    }
}

// 绘制所有匹配位置
for(int i = 0; i < match_count; i++) {
    cvRectangle(
        target,
        locations[i],
        cvPoint(locations[i].x + width, locations[i].y + height),
        CV_RGB(0, 255, 0),
        2
    );
}

free(locations);

参考代码 基于opencv的模板匹配算法,可以从一副大图中搜索出与模板相似度最高的部分 youwenfan.com/contentcso/72869.html

算法特点及注意事项

  1. 适用场景

    • 固定大小的物体检测
    • 不变形、不旋转的模板
    • 光照变化较小的环境
  2. 性能优化

    c 复制代码
    // 转换为灰度图提高速度
    IplImage* gray_target = cvCreateImage(cvGetSize(target), IPL_DEPTH_8U, 1);
    IplImage* gray_template = cvCreateImage(cvGetSize(template_img), IPL_DEPTH_8U, 1);
    cvCvtColor(target, gray_target, CV_BGR2GRAY);
    cvCvtColor(template_img, gray_template, CV_BGR2GRAY);
    // 然后使用灰度图进行匹配
  3. 常见问题解决

    • 旋转问题:旋转模板创建多个版本
    • 尺度问题:使用图像金字塔多尺度匹配
    • 光照问题:使用边缘特征(Canny)代替原始图像
  4. 替代方案建议

    • 当模板>图像尺寸25%时,考虑特征匹配(SIFT/SURF)
    • 复杂场景下使用YOLO等深度学习模型

此实现使用OpenCV的C接口,兼容OpenCV 2.x版本。对于新项目,推荐使用OpenCV C++ API(Mat类代替IplImage)。

相关推荐
NAGNIP5 小时前
一文搞懂树模型与集成模型
算法·面试
NAGNIP5 小时前
万字长文!一文搞懂监督学习中的分类模型!
算法·面试
技术狂人1685 小时前
工业大模型工程化部署实战!4 卡 L40S 高可用集群(动态资源调度 + 监控告警 + 国产化适配)
人工智能·算法·面试·职场和发展·vllm
D_FW5 小时前
数据结构第六章:图
数据结构·算法
你怎么知道我是队长5 小时前
C语言---头文件
c语言·开发语言
a程序小傲6 小时前
京东Java面试被问:动态规划的状态压缩和优化技巧
java·开发语言·mysql·算法·adb·postgresql·深度优先
自学不成才6 小时前
深度复盘:一次flutter应用基于内存取证的黑盒加密破解实录并完善算法推理助手
c++·python·算法·数据挖掘
3有青年6 小时前
nios ii 中 ‘ALT_CPU_FREQ‘ could not be resolved的分析和解决办法
c语言·fpga开发
June`6 小时前
全排列与子集算法精解
算法·leetcode·深度优先