[Python] Contour completion for complex contour

Discussão em 'Python' iniciado por Stack, Março 27, 2025.

  1. Stack

    Stack Membro Participativo

    I have a discontinuous circular contour, and I want to calculate the area enclosed by this contour. I applied OpenCV's contourArea to compute the area, but due to the discontinuity in the contour, errors occur during the calculation. To address this, I tried completing the contour using neighboring point interpolation (Delaunay triangulation). However, this method causes distortion in the contour. How can I effectively complete my contour?

    This is the code I used for calculating the area

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt


    image_path = "processed_images2/cropped_good4.jpg_640x640.jpg"
    image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)


    _, binary = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)


    contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)


    total_area = sum(cv2.contourArea(cnt) for cnt in contours)


    image_contours = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)


    cv2.drawContours(image_contours, contours, -1, (0, 255, 0), thickness=2)


    plt.figure(figsize=(6,6))
    plt.imshow(image_contours)
    plt.title(f"Estimated Area: {total_area:.2f} pixels²")
    plt.axis("off")
    plt.show()


    here's the code that I implement the Delaunay triangulation for contour

    import scipy.spatial
    import cv2

    image = cv2.imread("processed_images2\\cropped_147.jpg_640x640.jpg", cv2.IMREAD_GRAYSCALE)
    edges = cv2.Canny(image, 50, 150)


    y, x = np.where(edges > 0)
    contour_points = np.column_stack((x, y))

    fixed_image = image.copy()
    tri = scipy.spatial.Delaunay(contour_points)
    for simplex in tri.simplices:
    pts = contour_points[simplex]
    cv2.polylines(fixed_image, [pts], isClosed=True, color=255, thickness=1)

    plt.figure(figsize=(6, 6))
    plt.imshow( fixed_image, cmap='gray')
    # plt.title(f"OR Operation: {image_name}")
    plt.axis("off")
    plt.show()


    This is the input image

    [​IMG]

    output

    [​IMG]

    At the same time, I also tested KNN and KD-tree methods to complete the contour, but the results were not ideal. I hope the final contour is a closed curve without distortion.

    KD tree:

    import cv2
    import numpy as np
    from scipy.spatial import KDTree


    image = cv2.imread("processed_images2\\cropped_147.jpg_640x640.jpg", cv2.IMREAD_GRAYSCALE)
    edges = cv2.Canny(image, 50, 150)


    y, x = np.where(edges > 0)
    contour_points = np.column_stack((x, y))


    tree = KDTree(contour_points)


    missing_points = np.array([[100, 150], [120, 200]]) # (x, y)


    _, nearest_idx = tree.query(missing_points)


    fixed_image = image.copy()
    for i, idx in enumerate(nearest_idx):
    x_nearest, y_nearest = contour_points[idx]
    cv2.circle(fixed_image, (missing_points[0], missing_points[1]), 2, 255, -1)

    plt.figure(figsize=(6, 6))
    plt.imshow( fixed_image, cmap='gray')
    # plt.title(f"OR Operation: {image_name}")
    plt.axis("off")
    plt.show()


    KNN

    from sklearn.neighbors import KNeighborsClassifier


    knn = KNeighborsClassifier(n_neighbors=3)
    knn.fit(contour_points, np.ones(len(contour_points)))


    predictions = knn.predict(missing_points)


    for i, pred in enumerate(predictions):
    if pred == 1:
    cv2.circle(fixed_image, (missing_points[0], missing_points[1]), 2, 255, -1)

    plt.figure(figsize=(6, 6))
    plt.imshow( fixed_image, cmap='gray')
    # plt.title(f"OR Operation: {image_name}")
    plt.axis("off")
    plt.show()

    Continue reading...

Compartilhe esta Página