如何使用Python查找图片中的几个关键像素点?

时间:2018-06-28 16:11:56

标签: python image opencv

我知道通过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解决方案。我认为可以通过遍历像素来解决,但这不能保证性能。那有更好的方法吗?

1 个答案:

答案 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)