使用 Python 检测图像中带有间隙的形状

问题描述 投票:0回答:1

我有以下图片:

我想提取以下轮廓,以便检查轮廓内是否有一个点:

我有以下 python 代码来使用 cv2.findContours 提取形状的轮廓:

import cv2
import numpy as np

img = cv2.imread(
    r'inp.png', cv2.IMREAD_COLOR)

def parse_shape(img):
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

    # Dilate the image 
    kernel = np.ones((3,3), np.uint8)
    dilate = cv2.dilate(hsv, kernel, iterations = 2)

    # Get all the white pixels
    lower_white_hsv = np.array([0, 0, 200])
    upper_white_hsv = np.array([255, 255, 255])

    # Create a mask for the white pixels and find contours
    mask_hsv = cv2.inRange(dilate, lower_white_hsv, upper_white_hsv)
    contours, _ = cv2.findContours(mask_hsv, cv2.RETR_TREE , cv2.CHAIN_APPROX_SIMPLE)
    if len(contours) == 0:
        print("No contours found from mask")
        return None

    # Filter out contours that are too small 
    # This filters out some noise but not all
    contour_area_threshold = 600

    valid_contours = []
    for cnt in contours:
        if cv2.contourArea(cnt) > contour_area_threshold:
            valid_contours.append(cnt)

    if len(valid_contours) == 0:
        print("No valid contours found from mask")
        return None

    # Draw the contours on the image and show the resulting image
    draw_img = img.copy()
    cv2.drawContours(draw_img, valid_contours, -1, (0, 255, 0), cv2.FILLED)
    cv2.imshow("draw_img", draw_img)
    cv2.imshow("mask_hsv", mask_hsv)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    return valid_contours

# Do stuff
lines = parse_shape(img)

产生以下结果

现在已经非常接近了,但是正如您所看到的,仍然存在一些较大的间隙,这些间隙不能通过仅增加图像的稀释度来修复。 有什么办法可以填补空白吗? 如果形状被正确检测到,检查一个点是否在形状内部是非常简单的,但我似乎无法找到间隙的解决方案。

python image opencv contour
1个回答
0
投票

这不是通用解决方案,而是解决方案。
我添加了一个配置“DILATE_PARAMETER”,它指定膨胀多少次,以创建一个消除间隙的封闭区域。然后会找到该区域的轮廓,给出闭合轮廓。
“CONTOUR_AREA_THRESHOLD”也需要根据您的用例进行微调。
问题之一是轮廓与实际所需的轮廓有点远。

import cv2
import numpy as np

DILATE_PARAMETER = 8
CONTOUR_AREA_THRESHOLD = 5000

img = cv2.imread('ring.png', cv2.IMREAD_COLOR)

def parse_shape(img):

    # Dilate the image
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    kernel = np.ones((3,3), np.uint8)
    dilate = cv2.dilate(img_gray, kernel, iterations = 2)
    
    for _ in range(DILATE_PARAMETER-1):
        dilate = cv2.dilate(dilate, kernel, iterations = 2)


    # Create a mask for the white pixels and find contours
    mask = cv2.inRange(dilate, 200, 255)
    contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL , cv2.CHAIN_APPROX_SIMPLE)
    if len(contours) == 0:
        print("No contours found from mask")
        return None

    # Filter out contours that are too small 
    # This filters out some noise but not all
    

    valid_contours = []
    for cnt in contours:
        if cv2.contourArea(cnt) > CONTOUR_AREA_THRESHOLD:
            valid_contours.append(cnt)
    
    if len(valid_contours) == 0:
        print("No valid contours found from mask")
        return None

    # Draw the contours on the image and show the resulting image
    draw_img = img.copy()
    cv2.drawContours(draw_img, valid_contours, -1, (0, 255, 0), 5)
    cv2.imwrite("result.png",draw_img)
    cv2.imshow("draw_img", draw_img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    return valid_contours

# Do stuff
lines = parse_shape(img)

输出

© www.soinside.com 2019 - 2024. All rights reserved.