调用cv2.matchTemplate触发(-215:Assertion failed)错误的技术咨询
解决OpenCV matchTemplate断言失败(输入图像小于模板尺寸)的问题
这个错误其实已经把问题说得很直白了——你用摄像头捕获的实时帧(gri_kare)的高度或宽度,比要匹配的模板图像(nesne)还小,而cv2.matchTemplate有个硬性要求:输入的待匹配图像必须比模板图像大,或者至少尺寸相同,不然没法完成模板匹配的滑动计算。
先捋下你代码里的几个小问题:
- 每次循环都重新加载模板图像,既浪费性能又完全没必要;
- 画矩形的逻辑错了——你把框画在模板图像上了,而不是要显示的摄像头帧;
- 遍历匹配坐标的方式不对,
zip(loc)没法正确拿到每个匹配点的位置; - 没有做尺寸检查就直接匹配,导致触发断言错误。
给你改好的完整代码,每一步都做了优化和修复:
import cv2 import numpy as np # 模板图像只加载一次,放到循环外面,避免重复读硬盘 nesne = cv2.imread("nesn.jpg", 0) # 先检查模板是否加载成功,避免后续莫名其妙报错 if nesne is None: print("哎呀,模板图像加载失败了!检查下文件路径对不对?") exit() # 注意:shape返回的是(高度, 宽度),反转后得到(宽度, 高度),方便后续画矩形 w, h = nesne.shape[::-1] kamera = cv2.VideoCapture(0) # 可选操作:强制设置摄像头分辨率,确保帧尺寸比模板大(比如640x480) kamera.set(cv2.CAP_PROP_FRAME_WIDTH, 640) kamera.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) while True : ret, kare = kamera.read() # 检查是否成功获取帧 if not ret: print("没法获取摄像头画面,可能摄像头出问题了?") break gri_kare = cv2.cvtColor(kare, cv2.COLOR_BGR2GRAY) # 关键:匹配前先检查帧和模板的尺寸,避免触发断言错误 if gri_kare.shape[0] < nesne.shape[0] or gri_kare.shape[1] < nesne.shape[1]: print("摄像头帧比模板小,这次就不匹配啦") cv2.imshow("asd", kare) if cv2.waitKey(25) & 0xFF == ord("q"): break continue # 执行模板匹配 res = cv2.matchTemplate(gri_kare, nesne, cv2.TM_CCOEFF_NORMED) esikdeger = 0.8 loc = np.where(res >= esikdeger) # 正确遍历匹配点,在摄像头帧上画矩形 for pt in zip(*loc[::-1]): # 把loc的行/列转换成x/y坐标 # 用绿色框标记匹配区域,线宽2 cv2.rectangle(kare, pt, (pt[0] + w, pt[1] + h), (0, 255, 0), 2) cv2.imshow("asd", kare) if cv2.waitKey(25) & 0xFF == ord("q"): break kamera.release() cv2.destroyAllWindows()
几个关键修复点说明:
- 模板加载优化:把
cv2.imread移到循环外,只加载一次,还加了加载失败的判断,避免后续无效计算; - 前置尺寸检查:在匹配前先对比帧和模板的尺寸,如果帧更小就跳过这次匹配,直接显示画面,不会再触发断言错误;
- 坐标逻辑修正:模板的
shape返回的是(高,宽),所以反转后得到(宽,高),这样画矩形时的右下角坐标才是正确的;同时zip(*loc[::-1])把匹配结果的行/列转换成x/y坐标,确保框能画在正确的位置; - 可选分辨率设置:通过
kamera.set强制设置摄像头分辨率,从根源上避免帧尺寸太小的问题。
额外小建议:
如果你的模板图像确实太大,也可以考虑先缩小模板,比如用cv2.resize(nesne, (new_width, new_height))来调整尺寸,适配你的摄像头帧;另外也可以试试其他匹配方法,比如TM_SQDIFF_NORMED,说不定更适合你的场景。
内容的提问来源于stack exchange,提问作者J.Doe
相关产品推荐
相关产品推荐

