如何从坐标列表中确定区域?
How to determine regions out of a list of coordinates?
我正在为 python 的 OpenCv 对象检测而苦苦挣扎:我使用 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... 检测到的图像执行此操作,您有任何(非天真的)想法吗?
谢谢:)
我的代码既不完美也不优化;但开始可能会很好 :)
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()
这段代码不能解决簇数的问题,如果你知道簇数,我认为目前有用。
更新:
阅读评论后(尤其是@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)))
在这种情况下,您可以找到聚类、它们的范围以及每个聚类的大致中心。在下一步中,您可以更详细地检查每个集群的范围。
我正在为 python 的 OpenCv 对象检测而苦苦挣扎:我使用 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... 检测到的图像执行此操作,您有任何(非天真的)想法吗?
谢谢:)
我的代码既不完美也不优化;但开始可能会很好 :)
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()
这段代码不能解决簇数的问题,如果你知道簇数,我认为目前有用。
更新:
阅读评论后(尤其是@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)))
在这种情况下,您可以找到聚类、它们的范围以及每个聚类的大致中心。在下一步中,您可以更详细地检查每个集群的范围。