我实现了以下代码,以使用裁剪后的小图像作为模板来匹配植物中的节点。
img_rgb = cv2.imread('Exp.2 - Florestópolis, 35DAE, 2017-2018, T4, R2, P4.jpg')
img_rgb = cv2.medianBlur(img_rgb, 7)
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template_image = cv2.imread('TemplateNode.jpg',0)
template_image = cv2.medianBlur(template_image, 5)
width, height = template_image.shape[::-1]
res = cv2.matchTemplate(img_gray, template_image, cv2.TM_CCOEFF_NORMED)
threshold = 0.6
locations = np.where(res >= threshold)
for position_tuple in zip(*locations[::-1]):
cv2.rectangle(img_rgb, position_tuple, (position_tuple[0] + width, position_tuple[1] + height), (0,255,0), 1)
但是,它在同一位置周围生成了太多的边界框(元组),如下所示:
因此,有解决此问题的方法吗?
编辑:
答案 0 :(得分:1)
这是一种可能的方法。代码不太可能是一种有效的代码。我认为从某些软件包进行k均值聚类可能会更好。想法是将太近的位置分组在一起:
def group_locations(locations, min_radius):
x = locations[:, 0][ : , None]
dist_x = x - x.T
y = locations[:, 1][ : , None]
dist_y = y - y.T
dist = np.sqrt(dist_x**2 + dist_y**2)
np.fill_diagonal(dist, min_radius+1)
too_close = np.nonzero(dist <= min_radius)
groups = []
points = np.arange(len(locations))
i = 0
j = 0
while i < len(points):
groups.append([points[i]])
for j in range(len(too_close[0])):
if too_close[0][j] == points[i]:
groups[i].append(too_close[1][j])
points = np.delete(points, np.nonzero(points == too_close[1][j]))
i += 1
new_locations = []
for group in groups:
new_locations.append(np.mean(locations[group], axis=0))
return np.array(new_locations)
因此,在绘制之前,请先对位置进行分组并分组:
locations = []
size = 600
for _ in range(50):
locations.append((random.randint(0, size), random.randint(0, size)))
locations = np.array(locations)
min_radius = 50
new_locations = group_locations(locations, min_radius)
#I run it second time as sometimes locations form chains which are longer than radius
new_locations = group_locations(new_locations, min_radius)
plt.scatter(locations[:, 0], locations[:, 1], c='blue', label='Original locations')
plt.scatter(new_locations[:, 0], new_locations[:, 1], c='red', marker='x', label='New grouped locations')
plt.legend()
plt.show()
使用提供的图片进行了实际的尝试
img_rgb = cv2.imread('obsvu.jpg')
img_rgb = cv2.medianBlur(img_rgb, 7)
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template_image = cv2.imread('template.jpg',0)
template_image = cv2.medianBlur(template_image, 5)
width, height = template_image.shape[::-1]
res = cv2.matchTemplate(img_gray, template_image, cv2.TM_CCOEFF_NORMED)
threshold = 0.6
locations = np.where(res >= threshold)
new_locations = group_locations(np.array(locations).T, 50).T
for position_tuple in zip(*new_locations.astype(int)[::-1]):
cv2.rectangle(img_rgb, position_tuple, (position_tuple[0] + width, position_tuple[1] + height), (0,255,0), 5)
原始位置:723个
新位置:6(是的,不是最好的模板选择)