如何修改OpenCV-Python的Template Matching代码以检测计数图片右下角星星?
OpenCV模板匹配检测星星失败的修改方案
针对你的星星检测代码无法识别目标图中星星的问题,可以从以下几个方向调整:
降低匹配阈值
你当前设置的threshold = 0.8可能过高,实际匹配得分达不到这个标准。可以先尝试调低阈值(比如0.6),再根据输出的res值调整到合适的数值,确保能覆盖真实匹配结果。添加多尺度匹配逻辑
如果目标图中的星星和模板图尺寸不一致,单尺度模板匹配会失效。可以通过缩放模板或目标图,在不同尺度下执行匹配:# 多尺度匹配示例片段 scales = [0.8, 1.0, 1.2] # 根据实际情况调整缩放比例 for scale in scales: resized_template = cv.resize(template, None, fx=scale, fy=scale, interpolation=cv.INTER_AREA) w, h = resized_template.shape[::-1] res = cv.matchTemplate(img_gray, resized_template, cv.TM_CCOEFF_NORMED) loc = np.where(res >= threshold) for pt in zip(*loc[::-1]): cv.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)增加图像预处理步骤
对目标图和模板做预处理,突出星星特征、减少噪声:# 示例:二值化处理 _, img_gray_bin = cv.threshold(img_gray, 127, 255, cv.THRESH_BINARY_INV) # 根据星星颜色调整阈值和反转参数 _, template_bin = cv.threshold(template, 127, 255, cv.THRESH_BINARY_INV) # 用二值化后的图像做匹配 res = cv.matchTemplate(img_gray_bin, template_bin, cv.TM_CCOEFF_NORMED)尝试不同的匹配方法
不同匹配算法的适配场景不同,比如TM_SQDIFF_NORMED的匹配得分越低越接近匹配,你可以替换方法测试:res = cv.matchTemplate(img_gray, template, cv.TM_SQDIFF_NORMED) threshold = 0.2 # 注意这个方法的阈值逻辑相反,需要调低 loc = np.where(res <= threshold)验证图像加载正确性
检查img_rgb和template是否成功加载,避免路径错误或图像损坏:if img_rgb is None: print("目标图加载失败") if template is None: print("模板图加载失败")
修改后的完整示例代码(结合多尺度+预处理):
import cv2 as cv import numpy as np img_rgb = cv.imread('page.png') if img_rgb is None: print("目标图加载失败") exit() img_gray = cv.cvtColor(img_rgb, cv.COLOR_BGR2GRAY) # 二值化预处理 _, img_gray_bin = cv.threshold(img_gray, 150, 255, cv.THRESH_BINARY_INV) template = cv.imread('star_temp.png', 0) if template is None: print("模板图加载失败") exit() _, template_bin = cv.threshold(template, 150, 255, cv.THRESH_BINARY_INV) threshold = 0.6 scales = [0.9, 1.0, 1.1] star_count = 0 for scale in scales: resized_template = cv.resize(template_bin, None, fx=scale, fy=scale, interpolation=cv.INTER_AREA) w, h = resized_template.shape[::-1] # 避免缩放后模板尺寸大于目标图 if w > img_gray_bin.shape[1] or h > img_gray_bin.shape[0]: continue res = cv.matchTemplate(img_gray_bin, resized_template, cv.TM_CCOEFF_NORMED) loc = np.where(res >= threshold) star_count += len(loc[0]) for pt in zip(*loc[::-1]): cv.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2) cv.imwrite('res.png', img_rgb) print(f"检测到星星数量:{star_count}")
内容的提问来源于stack exchange,提问作者Ekoar
相关产品推荐
相关产品推荐

