Python OpenCV:reduce";“模糊极大值”;成单点

Python OpenCV:reduce";“模糊极大值”;成单点,python,numpy,opencv,Python,Numpy,Opencv,我使用了: result = cv2.matchTemplate(frame, template, cv2.TM_CCORR_NORMED) 要生成此输出,请执行以下操作: 我需要一个(x,y)元组列表,位于结果中每个局部极大值(亮点)处。简单地找到阈值以上的所有点是行不通的,因为在每个最大值周围都有许多这样的点 我可以保证任意两个最大值之间的最小距离,这应该有助于加快速度 有没有一种有效的方法可以做到这一点 (注意:这是交叉过账的) 更新 基于by,我将骨架化添加到阈值图像中。很接近,但骨骼

我使用了:

result = cv2.matchTemplate(frame, template, cv2.TM_CCORR_NORMED)
要生成此输出,请执行以下操作: 我需要一个(x,y)元组列表,位于结果中每个局部极大值(亮点)处。简单地找到阈值以上的所有点是行不通的,因为在每个最大值周围都有许多这样的点

我可以保证任意两个最大值之间的最小距离,这应该有助于加快速度

有没有一种有效的方法可以做到这一点

(注意:这是交叉过账的)

更新 基于by,我将骨架化添加到阈值图像中。很接近,但骨骼化仍然有许多“蠕虫”,而不是单个点。我的处理流程如下:

# read the image
im = cv.imread("image.png", cv.IMREAD_GRAYSCALE)
# apply thresholding
ret, im2 = cv.threshold(im, args.threshold, 255, cv.THRESH_BINARY)
# dilate the thresholded image to eliminate "pinholes"
im3 = cv.dilate(im2, None, iterations=2)
# skeletonize the result
im4 = cv.ximgproc.thinning(im3, None, cv.ximgproc.THINNING_ZHANGSUEN)
# print the number of points found
x, y = np.nonzero(im5)
print(x.shape)
# => 1208
这是朝着正确的方向迈出的一步,但应该有220点,而不是1208点

以下是中间结果。正如您在上一张图片(骷髅化)中看到的,仍然有很多小“蠕虫”,而不是单点。有更好的方法吗

阈值:

扩大:

骨骼化:

更新2/14:似乎骨骼化只让你走了一段路。这里有一个更好的解决方案,我相信它会帮你解决剩下的问题。下面是您在scikit图像中的操作方法-也许您可以在OpenCV中找到类似的操作-看起来像是
cv2。FindOntours
将是一个好的开始

# mask is the thresholded image (before or after dilation should work, no skeletonization.

from skimage.measure import label, regionprops
labeled_image = label(mask)
output_points = [region.centroid for region in regionprops(labeled_image)]
说明:Label会将二进制图像转换为带标签的图像,其中每个遮罩具有不同的整数值。然后,regionprops使用这些标签来分离每个遮罩,从中我们可以使用质心属性来计算每个遮罩的中点-这保证是单个点


简单地找到阈值以上的所有点是行不通的,因为 在每个最大值周围有许多这样的点

事实上,这是可行的——只要您再应用一个处理步骤。在阈值化之后,我们想要骨骼化。Scikit图像有一个很好的功能来实现这一点,它应该给你一个单点的二进制掩码

之后,您可能会想运行以下内容:

indices = zip(*np.where(skeleton))
为了得到你的最后分数

基于,以下是对我有效的解决方案(使用所有openCV而不是Skipage):

这正是我们想要的结果:


如果阈值以上的点已连接,则可以使用骨架化或斑点检测或轮廓提取+重心。如果阈值以上的点未连接,则可以尝试查找阈值以上点之间的距离簇。如果幸运的话,有一个清晰的距离阈值,在该阈值下可以合并点(再次使用重心来找到中心。谢谢你给我指明了这个方向。FWIW,cv2的新版本包括一个骨架化功能:--我来试试。@fearless_傻瓜用一个更好的解决方案更新了我的答案,应该可以帮到你。)。
# read in color image and create a grayscale copy
im = cv.imread("image.png")
img = cv.cvtColor(im, cv.COLOR_BGR2GRAY)

# apply thresholding
ret, im2 = cv.threshold(img, args.threshold, 255, cv.THRESH_BINARY)
# dilate the thresholded peaks to eliminate "pinholes"
im3 = cv.dilate(im2, None, iterations=2)

contours, hier = cv.findContours(im3, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
print('found', len(contours), 'contours')
# draw a bounding box around each contour
for contour in contours:
    x,y,w,h = cv.boundingRect(contour)
    cv.rectangle(im, (x,y), (x+w,y+h), (255,0,0), 2)

cv.imshow('Contours', im)
cv.waitKey()