【问题标题】:How to determine regions out of a list of coordinates?如何从坐标列表中确定区域?
【发布时间】:2021-10-22 13:42:14
【问题描述】:

我正在努力使用 OpenCv for python 进行对象检测:我使用 matchTemplate 方法检测图像,但结果以同一对象的多个坐标结束。

[(798, 540), (799, 540), (800, 540), (798, 541), (799, 541), (800, 541), (798, 542), (799, 542), (800, 542), (798, 543), (799, 543), (800, 543), (798, 544), (799, 544), (800, 544)]

我只希望检测到的每张图像都有一个坐标,所以我应用了所有坐标的平均值,结果很好(图像上的红点):(799, 542)

问题是有时在同一帧中检测到两个图像,它不适用于平均方法(给出两个坐标的中间)。

您对如何对 2,3,4... 检测到的图像执行此操作有任何(非天真的)想法吗?

谢谢:)

【问题讨论】:

  • 你好 :) 也许KNN 是你的答案。
  • 是的,这是我想到的第一件事,但我认为这是矫枉过正:(
  • 也许吧。但不管怎样,我测试了 10 分,在 3 次迭代中得到了很好的结果:)
  • 我会推荐一种聚类算法,例如k-means,使用一些自动计算聚类数量的方法。
  • 最小生成树聚类。您添加边直到它们太长(或构建树 - 在这种情况下您有一个集群),然后是组件。 citeseerx.ist.psu.edu/viewdoc/….

标签: python algorithm opencv coordinates object-detection


【解决方案1】:

我的代码既不是完美的也不是最优的;但最好开始:)

import matplotlib.pyplot as plt
import numpy as np
import random
import math

# 'o': without cluster
# '*': first cluster
# '^': second cluster
pts = [
    [6.0, 4.0, 'o'], [1.0, 2.0, 'o'], [2.0, 1.0, 'o'], [2.0, 2.0, 'o'],
    [6.0, 6.0, 'o'], [6.0, 5.0, 'o'], [5.0, 6.0, 'o'], [5.0, 5.0, 'o']
]

def distance(pt1, pt2):
    return math.hypot(pt1[0] - pt2[0], pt1[1] - pt2[1])

def getRandomPoint():
    rnd = random.randint(0, len(pts)-1)
    return [pts[rnd][0], pts[rnd][1]]

def plotClusterCenter(c='o'):
    s = []
    for p in pts:
        if p[2] == c:
            s.append(p)
    print(s)
    cx, cy = np.mean([d[0] for d in s]), np.mean([d[1] for d in s])
    plt.plot(cx, cy, c, c=(1, .5, 0))


x, y, c = [d[0] for d in pts], [d[1] for d in pts], [d[2] for d in pts]
A, B = getRandomPoint(), getRandomPoint()


for _ in range(0, len(pts)//2):
    for i in range(0, len(x)):
        if c[i] == "*":
            A = [(A[0] + x[i]) / 2, (A[1] + y[i]) / 2]
        else:
            B = [(B[0] + x[i]) / 2, (B[1] + y[i]) / 2]
        pt = (x[i], y[i])
        c[i] = "*" if distance(A, pt) < distance(B, pt) else "^"
        pts[i][2]=c[i]

for i in range(0, len(x)):
    plt.plot(x[i], y[i], c[i], c=(0, 0, 0))

plotClusterCenter('*')
plotClusterCenter('^')
plt.show()

这段代码不能解决簇数的问题,我认为如果你知道簇数,目前它很有用。


更新:

读完cmets(尤其是@Christoph Rackwitz 的完整描述);我得出的结论是,我提出的方法可能不是正确的。


更新:

我更多地考虑了解释和讨论。我认为如果你有一个面具,如果你尝试这样的事情可能不是最糟糕的主意:

import sys
import cv2
import numpy as np

org = cv2.imread(sys.path[0]+'/mask.png')
im = org.copy()
H, W = org.shape[:2]

gry = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
gry = cv2.erode(gry, np.ones((31, 31)))

cnts, _ = cv2.findContours(gry, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
for cnt in cnts:
    x, y, w, h = cv2.boundingRect(cnt)
    if w < W:
        cv2.rectangle(im, (x, y), (x+w, y+h), (50, 250, 10), 2)
        cv2.circle(im,  (x+w//2, y+h//2),3, (240, 20, 100), 3)

cv2.imwrite(sys.path[0]+'/output.png', np.hstack((org, im)))

在这种情况下,您可以找到集群、它们的范围以及每个集群的大致中心。在下一步中,您可以更详细地检查每个集群的范围。

【讨论】:

    猜你喜欢
    • 2017-04-16
    • 1970-01-01
    • 1970-01-01
    • 2012-11-08
    • 2011-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多