簡體   English   中英

如何在 Python OpenCV 中刪除輪廓內的輪廓?

[英]How to remove a contour inside contour in Python OpenCV?

Python 中的 OpenCV 提供以下代碼:

regions, hierarchy = cv2.findContours(binary_image, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)


for region in regions:
    x, y, w, h = cv2.boundingRect(region)

    cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 1)

這給出了輪廓內的一些輪廓。 如何在 Python 中刪除它們?

為此,您應該查看本教程,了解如何使用findContours方法返回的hierarchy對象。

要點是您應該使用cv2.RETR_TREE而不是cv2.RETR_LIST來獲取集群之間的父/子關系:

regions, hierarchy = cv2.findContours(binary_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

然后,您可以通過檢查hierarchy[0,i,3]是否等於 -1 來檢查索引為i的輪廓是否在另一個輪廓內。 如果它不同於-1,那么你的輪廓在另一個里面。

為了刪除輪廓內的輪廓:

shapes, hierarchy = cv2.findContours(image=image, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE)

但是,在某些情況下,您可能會觀察到整個圖像上形成了一個大輪廓,並且應用上述內容會返回一個大輪廓。

為了避免這種情況,請嘗試反轉圖像:

image = cv2.imread("Image Path")
image = 255 - image
shapes, hierarchy = cv2.findContours(image=image, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE)

這將為您提供所需的結果。

更新:

如果在整個圖像上近似一個大邊界框,層次結構不起作用的原因是, hierarchy[0,iteration,3]的輸出僅對於繪制在整個圖像上的一個邊界框為-1 ,與所有其他邊界一樣框在這個大邊界框內,其中任何一個的hierarchy[0,iteration,3]都不等於-1 因此,將需要反轉圖像以符合以下要求:

在 OpenCV 中,尋找輪廓就像從黑色背景中尋找白色物體。 所以請記住,要找到的對象應該是白色的,背景應該是黑色的。

但是,正如@Jeru 所指出的,這不是一個通用的解決方案,必須在反轉圖像之前將其可視化。 考慮這張圖片: 在此處輸入圖像描述

跑步

shapes, hierarchy = cv2.findContours(image=image, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_SIMPLE)

結果是

在此處輸入圖像描述

現在,僅顯示具有hierarchy[0,iteration,3] = -1的輪廓會導致

在此處輸入圖像描述

這是不正確的。 如果我們想獲得包含形狀和文本形狀的矩形,我們可以這樣做

image = 255 - image
shapes, hierarchy = cv2.findContours(image=thresh, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE)

在這種情況下,我們得到:

在此處輸入圖像描述

代碼:

import cv2
from easyocr import Reader
import math


shape_number = 2

image = cv2.imread("Image Path")
deep_copy = image.copy()

image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(image_gray, 210, 255, cv2.THRESH_BINARY)
thresh = 255 - thresh

shapes, hierarchy = cv2.findContours(image=thresh, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(image=deep_copy, contours=shapes, contourIdx=-1, color=(0, 255, 0), thickness=2, lineType=cv2.LINE_AA)

for iteration, shape in enumerate(shapes):

        if hierarchy[0,iteration,3] == -1:
                print(hierarchy[0,iteration,3])
                print(iteration)

cv2.imshow('Shapes', deep_copy)
cv2.waitKey(0)
cv2.destroyAllWindows()
img_output, contours, hierarchy = cv2.findContours(blank_image_firstImage, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

這將刪除子輪廓

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM