我已经使用opencv创建了一些轮廓,我需要在轮廓上标识一个特定点,通常是“ V”形的最内点。在所附的图像中,我要识别的点由绿色箭头显示。
在左侧是一种简单的情况,例如,可以通过计算轮廓的凸包,然后找到距该包最远的点来进行识别。
但是,在所附图像的右侧是一个更为困难的情况,在该情况下,我得到的不是1个轮廓,而是几个轮廓,并且不存在漂亮的“ V”形,这使得无法识别轮廓的最内点。 'V'。如红色虚线所示,一种解决方法是外推较高的轮廓,直到与较低的轮廓相交。有人知道我该怎么做吗?还是有更好的解决方案?
为了记录,我尝试过:
膨胀/腐蚀(当多个轮廓靠近时起作用,否则不起作用)
进行p变换(倾向于将目标点定位)
任何指针将不胜感激。
答案 0 :(得分:1)
此解决方案适用于您提供的两个图像。对于所有其他颜色相似且指向右侧的“ v”形(或至少部分“ v”形)的图像,这也应该是一个很好的解决方案。
首先让我们看一下更简单的图像。我首先使用颜色空间对图像进行了细分。
# Convert frame to hsv color space
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# Define range of pink color in HSV
(b,r,g,b1,r1,g1) = 0,0,0,110,255,255
lower = np.array([b,r,g])
upper = np.array([b1,r1,g1])
# Threshold the HSV image to get only pink colors
mask = cv2.inRange(hsv, lower, upper)
接下来,我发现mid_point
的该行的上方和下方都有相等数量的白色。
# Calculate the mid point
mid_point = 1
top, bottom = 0, 1
while top < bottom:
top = sum(sum(mask[:mid_point, :]))
bottom = sum(sum(mask[mid_point:, :]))
mid_point += 1
然后,我从中点开始填充图像: bg = np.zeros((h + 2,w + 2),np.uint8)
kernel = np.ones((k_size, k_size),np.uint8)
cv2.floodFill(mask, bg, (0, mid_point), 123)
现在我有了泛洪的图像,我知道要寻找的点是最接近图像右侧的灰色像素。
# Find the gray pixel that is furthest to the right
idx = 0
while True:
column = mask_temp[:,idx:idx+1]
element_id, gray_px, found = 0, [], False
for element in column:
if element == 123:
v_point = idx, element_id
found = True
element_id += 1
# If no gray pixel is found, break out of the loop
if not found: break
idx += 1
结果:
现在获取较难的图像。在右图中,“ v”未完全连接:
要关闭“ v”,我迭代检查了是否已连接的面罩:
# Flood fill and dilate loop
k_size, iters = 1, 1
while True:
bg = np.zeros((h+2, w+2), np.uint8)
mask_temp = mask.copy()
kernel = np.ones((k_size, k_size),np.uint8)
mask_temp = cv2.dilate(mask_temp,kernel,iterations = iters)
cv2.floodFill(mask_temp, bg, (0, mid_point), 123)
cv2.imshow('mask', mask_temp)
cv2.waitKey()
k_size += 1
iters += 1
# Break out of the loop of the right side of the image is black
if mask_temp[h-1,w-1]==0 and mask_temp[1, w-1]==0: break
这是结果输出: