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

2024-04-26 22:54:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道,通过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中的一些像素被提取出来,其余的用红色填充。你知道吗

我没有找到opencvpython或PIL解决方案。我认为可以通过遍历像素来解决这个问题,但这并不能保证性能。有更好的方法吗?你知道吗


Tags: 函数图片template像素resultcv2opencvcolor
1条回答
网友
1楼 · 发布于 2024-04-26 22:54:14

根据Neeraj Komuravalli对this question的回答,matchTemplate支持mask参数,将模板中的某些像素排除在匹配(docs)中。你知道吗

要基于红色像素生成遮罩,一个简单的解决方案是使用布尔表达式来选择那些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在应用时无法对模板中的红色像素进行遮挡,因此红色像素区域的边界会影响边缘检测的结果,从而使模板看起来与原始图像有很大的不同。你知道吗

在本例中,匹配失败的结果是返回一个完全错误的位置。你知道吗

删除精明的步骤解决了这个问题。。。但这也使得该方法的健壮性/精确性有所下降。在这种情况下,匹配实际上似乎与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)

相关问题 更多 >