我的代码既不是完美的也不是最优的;但最好开始:)
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)))
在这种情况下,您可以找到集群、它们的范围以及每个集群的大致中心。在下一步中,您可以更详细地检查每个集群的范围。