[Python] How to stop opencv from splitting contours?

Discussão em 'Python' iniciado por Stack, Julho 17, 2025.

  1. Stack

    Stack Membro Participativo

    Currently I am trying to use opencv to solve the "puzzle piece" captcha where you move the puzzle piece to a darkened position. To do this, I am using opencv to get the contours and returning the center of the contour with a certain area. However, it appears that opencv is splitting the puzzle piece contour into multiple smaller contours. The smaller contours don't cover the entire area of the puzzle piece.

    For example, lets say my threshold image looks like this, where the puzzle piece on the right is the desired final position for the puzzle piece.

    [​IMG]

    When I get the contours and draw them on separate images with

    mask = np.zeros(img_gray.shape, dtype=np.uint8)
    cv2.fillPoly(mask, [contour], 255)
    cv2.imshow('mask', mask)
    cv2.waitKey()


    it shows that the contours are all small fragments like this

    [​IMG]

    how can I prevent opencv from splitting the contours? my code looks something like this

    def get_captcha_puzzle_coordinates(image_bytes: bytes, thresh: int, lower: int, upper: int) -> Optional[tuple[int, int]]:
    np_array = np.frombuffer(image_bytes, np.uint8)
    img = cv2.imdecode(np_array, cv2.IMREAD_COLOR)
    img_gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

    _, thresh = cv2.threshold(img_gray, thresh, 255, cv2.THRESH_BINARY_INV)
    contours, _ = cv2.findContours(thresh, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)

    for contour in contours:

    mask = np.zeros(img_gray.shape, dtype=np.uint8)
    cv2.fillPoly(mask, [contour], 255)
    area = cv2.countNonZero(mask)

    if lower < area < upper:
    moments = cv2.moments(contour)
    coordinate_x = int(moments['m10'] / moments['m00'])
    coordinate_y = int(moments['m01'] / moments['m00'])
    return coordinate_x, coordinate_y
    return None

    Continue reading...

Compartilhe esta Página