我知道通过Opencv-python的matchtemplate函数可以匹配图片1中的图片2。
import cv2
template = cv2.imread("1.bmp")
template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
template = cv2.Canny(template, 50, 200)
edged = cv2.imread("2.bmp")
edged = cv2.cvtColor(edged, cv2.COLOR_BGR2GRAY)
edged = cv2.Canny(edged, 50, 200)
result = cv2.matchTemplate(edged, template, cv2.TM_CCOEFF_NORMED)
(_, maxVal, _, maxLoc) = cv2.minMaxLoc(result)
但是,如果我只有像图片3这样的像素,我该如何与图片1相匹配?
图片3:提取图片2中的一些像素,其余像素用红色填充。
我没有找到opencv-python或PIL解决方案。我认为可以通过遍历像素来解决,但这不能保证性能。那有更好的方法吗?
答案 0 :(得分:1)
根据Neeraj Komuravalli对this question的回答,matchTemplate
支持mask
参数,以作为排除模板中某些像素不被考虑的一种方法({{3 }}。
要基于红色像素生成蒙版,一个简单的解决方案是使用布尔表达式选择蓝色和绿色0
而红色255
的像素:
mask = (template[:,:,0]==0) & (template[:,:,1]==0) & (template[:,:,2]==255)
mask = ~mask
mask = mask.astype(np.uint8)
请注意,由于掩码必须与模板具有相同的数据类型,因此必须转换为uint8
。
编辑: ~mask
反转遮罩(0
变成1
,反之亦然),这是必须的,因为0
表示要至少在使用方法cv2.TM_CCORR_NORMED
时被屏蔽。
尽管这从原则上解决了您的问题,但在这种情况下不会产生有效的解决方案。
这是因为将Canny边缘滤镜应用于图像。由于在应用Canny时无法掩盖模板中的红色像素,因此红色像素区域的边界将影响边缘检测的结果,从而将模板更改为与原始外观完全不同。
在此示例中,匹配失败,从而返回了完全错误的位置。
删除Canny步骤可以解决此问题...但是,这也会使方法的健壮性/精确性降低一点。在这种情况下,匹配实际上似乎比100%正确匹配少了几个像素。不幸的是,我想不出任何改进方法。
以下是对我有用的完整代码(在精度方面有上述警告):
import cv2
import numpy as np
template = cv2.imread("masked_template.png")
mask = (template[:,:,0]==0) & (template[:,:,1]==0) & (template[:,:,2]==255)
mask = mask.astype(np.uint8)
template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
#template = cv2.Canny(template, 50, 200)
edged = cv2.imread("edged.png")
edged = cv2.cvtColor(edged, cv2.COLOR_BGR2GRAY)
#edged = cv2.Canny(edged, 50, 200)
result = cv2.matchTemplate(edged, template, cv2.TM_CCORR_NORMED, mask=mask)
(_, maxVal, _, maxLoc) = cv2.minMaxLoc(result)