You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenCV模板匹配中如何返回匹配成功的模板可识别标识符

OpenCV模板匹配中如何返回匹配成功的模板可识别标识符

我们有如下函数,它的作用是在工作图像中找到匹配的模板。现在的需求是,如何得到一个可用于后续判断的输出结果(比如,如果匹配到的是绿色模板,就执行对应的操作)。

import cv2
    
red_template = cv2.imread('resources/temptest/red_template.png')
yellow_template = cv2.imread('resources/temptest/yellow_template.png')
blue_template = cv2.imread('resources/temptest/blue_template.png')
green_template = cv2.imread('resources/temptest/green_template.png')
work_image = cv2.imread('resources/temptest/work_image.png')
all_templates = [red_template, yellow_template, blue_template, green_template]
    
for template in all_templates:
    result = cv2.matchTemplate(work_image,template,
                               method=cv2.TM_CCORR_NORMED)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
    threshold = 0.945
    if max_val >= threshold:
        print('found it')
        break
    else:
        print('not found')
        continue

涉及的文件:
red template、yellow template、blue template、green template、work image

函数执行结果:

not found
not found
not found
found it

目前代码运行正常,当循环到匹配的模板时会输出“found it”,但我的问题是:如何输出匹配成功的模板的标识符?我尝试过添加return result或return template,但这些都没法得到一个可用于比较的对象,还经常遇到ValueError: operands could not be broadcast together with shapes .的错误。


其实你不用直接返回模板本身(毕竟模板是NumPy数组对象,直接比较很容易因为形状或元素问题报错),只要把模板和对应的标识符(比如颜色名称)绑定在一起,就能轻松追踪到匹配的是哪个模板了。下面给你两个实用的解决方法:

方法一:用元组列表绑定模板与名称

把每个模板和它的名称打包成元组,循环时同时获取模板和名称,匹配成功后直接记录名称即可:

import cv2

# 将模板和对应名称绑定成元组,存入列表
template_list = [
    (cv2.imread('resources/temptest/red_template.png'), "红色"),
    (cv2.imread('resources/temptest/yellow_template.png'), "黄色"),
    (cv2.imread('resources/temptest/blue_template.png'), "蓝色"),
    (cv2.imread('resources/temptest/green_template.png'), "绿色")
]
work_image = cv2.imread('resources/temptest/work_image.png')

threshold = 0.945
matched_name = None

for template, name in template_list:
    result = cv2.matchTemplate(work_image, template, method=cv2.TM_CCORR_NORMED)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
    
    if max_val >= threshold:
        print(f'找到匹配模板:{name}')
        matched_name = name
        break
    else:
        print(f'未匹配到{name}模板')

# 后续可根据匹配到的名称执行对应操作
if matched_name == "绿色":
    print("执行绿色模板对应的专属操作")
elif matched_name == "红色":
    print("执行红色模板对应的专属操作")

方法二:用字典存储模板与名称

如果后续需要单独调用某个模板,用字典会更灵活,键为名称,值为模板对象:

import cv2

# 字典键为模板名称,值为模板对象
template_dict = {
    "红色": cv2.imread('resources/temptest/red_template.png'),
    "黄色": cv2.imread('resources/temptest/yellow_template.png'),
    "蓝色": cv2.imread('resources/temptest/blue_template.png'),
    "绿色": cv2.imread('resources/temptest/green_template.png')
}
work_image = cv2.imread('resources/temptest/work_image.png')

threshold = 0.945
matched_name = None

for name, template in template_dict.items():
    result = cv2.matchTemplate(work_image, template, method=cv2.TM_CCORR_NORMED)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
    
    if max_val >= threshold:
        print(f'找到匹配模板:{name}')
        matched_name = name
        break
    else:
        print(f'未匹配到{name}模板')

# 后续操作示例
if matched_name:
    print(f'接下来将针对{matched_name}模板执行后续逻辑')

为什么之前的方法会报错?

你之前尝试返回template(也就是图像的NumPy数组),当后续想比较两个数组时,Python会逐元素对比,得到一个布尔数组,而不是你预期的“是否是同一个模板”的判断;如果两个数组形状不同,还会直接触发广播错误。而用字符串作为标识符,不仅比较简单直观,也完全不会有形状不兼容的问题。

备注:内容来源于stack exchange,提问作者APizzy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 16:39:32