【问题标题】:How to find a specific point on a contour in opencv/python如何在opencv / python中找到轮廓上的特定点
【发布时间】:2019-10-07 03:09:53
【问题描述】:

我使用opencv创建了一些轮廓,我需要识别轮廓上的一个特定点,这通常是'V'形的最里面的点。在附图中,我要识别的点由绿色箭头表示。

左边是一个简单的例子,可以通过计算轮廓的凸包来进行识别(例如),然后找到离凸包最远的点。

但是,在所附图像的右侧是一个更困难的情况,我得到了几个轮廓而不是 1 个轮廓,并且没有漂亮的“V”形,因此无法识别最里面的点'V'。如红色虚线所示,一种解决方案可能是外推较高的轮廓,直到它与较低的轮廓相交。有谁知道我会怎么做?或者有更好的解决方案?

我试过的记录:

  • 膨胀/侵蚀(当多个轮廓靠近时有效,否则无效)

  • hough 变换 p(容易误定位目标点)

任何指针将不胜感激。

【问题讨论】:

    标签: python opencv hough-transform convex-hull opencv-contour


    【解决方案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
    

    这是结果输出:

    【讨论】:

    • 非常感谢!对于更难的图像,膨胀的效果是将目标点向左推得比实际应该稍微远一些,但我认为我可以很容易地根据膨胀迭代次数来补偿这一点。再次感谢您的辛勤工作和出色的解决方案。
    猜你喜欢
    • 2019-12-07
    • 2015-08-11
    • 2019-01-25
    • 2012-02-25
    • 2021-09-13
    • 1970-01-01
    • 2020-09-14
    • 2020-03-28
    • 2023-03-09
    相关资源
    最近更新 更多