簡體   English   中英

檢測 opencv 中的嵌套形狀

[英]Detecting Nested Shapes in opencv

這段代碼的問題在於,如果三角形位於圓形、正方形或矩形等其他形狀內,它甚至會將三角形檢測為嵌套三角形。 我似乎無法找到解決此問題的方法。

用例:如果三角形位於正方形、圓形或矩形等其他形狀內,則不會將其檢測為嵌套三角形。

import numpy as np
import cv2

img = cv2.imread('triangles.png', cv2.IMREAD_GRAYSCALE)  # Read input image as grayscale,

# edges = cv2.Canny(img, 50, 200)

# Invert polarity of img, instead of using Canny - we need the contours to be white.
img = 255 - img

contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

hierarchy = hierarchy[0] # get the actual inner list of hierarchy descriptions

img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) # Convert image to BGR, for using colored text.

for component in zip(contours, hierarchy):
currentContour = component[0]
#currentHierarchy = hierarchy[1] # Why ?
currentHierarchy = component[1]

approx = cv2.approxPolyDP(currentContour, 0.01 * cv2.arcLength(currentContour, True), True)
x = approx.ravel()[0]
y = approx.ravel()[1] - 5

# https://docs.opencv.org/master/d9/d8b/tutorial_py_contours_hierarchy.html
# Hierarchy Representation in OpenCV
# Each contour has its own information regarding what hierarchy it is, who is its child, who is its parent etc. 
# OpenCV represents it as an array of four values : [Next, Previous, First_Child, Parent]

#if (currentHierarchy[1] < 0) and len(approx) == 3:

if (currentHierarchy[2] < 0) and len(approx) == 3:
    # These are the innermost child components

    parent_idx = currentHierarchy[3]  # Get the index of the parent contour
    parent_hier = hierarchy[parent_idx]  # Get the hierarchy of the parent.

    if parent_hier[3] >= 0:
        # Contour is nested only if the parent has a parent.
        cv2.putText(img, "Nested", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 0, 0), 2)
        cv2.drawContours(img, [currentContour], -1, (0, 255, 0), 1)
        cv2.waitKey(1000)
        cv2.imshow("image", img)

   cv2.waitKey()
   cv2.destroyAllWindows()

測試圖像:

在此處輸入圖像描述

在此處輸入圖像描述

我們有這個圖像:

在此處輸入圖像描述

我們想要檢測三角形內的每個三角形,而不是任何其他形狀內的三角形。 在上圖中,有兩個這樣的三角形。

  1. 導入必要的庫:
import cv2
import numpy as np
  1. 將圖像讀入一個變量,定義另一個變量來存儲轉換為灰度的圖像,並用灰度圖像,找到圖像的輪廓和層次:
img = cv2.imread('shapes.png')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

contours, hierarchy = cv2.findContours(255 - img_gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
hierarchy = hierarchy[0]
  1. 定義兩個列表; 一個存儲形狀中的每個三角形, potential_nested ,另一個存儲不是三角形的每個形狀, not_triangles
potential_nested = list()
not_triangles = list()
  1. 使用內置的zip()方法並行遍歷圖像的輪廓和層次結構,並找到迭代的每個輪廓的近似輪廓:
for cnt, hry in zip(contours, hierarchy):
    peri = cv2.arcLength(cnt, True)
    approx = cv2.approxPolyDP(cnt, 0.01 * peri, True)
  1. 通過檢查近似輪廓的長度是否等於 3 來檢查它是否是三角形。如果不是,則將 append not_triangles列表中。 如果是這樣,請在將其附加到potential_nested列表之前檢查它是否處於其他形狀。
    if len(approx) == 3:
        if hry[2] < 0:
            parent_idx = hry[3]
            parent_hier = hierarchy[parent_idx]
            if parent_hier[3] >= 0:
                potential_nested.append(cnt)
    else:
        not_triangles.append(cnt)
  1. 現在我們可以遍歷另一個形狀的每個三角形和不是三角形的每個形狀,如果三角形中的點都不在非三角形內,我們找到了嵌套三角形:
for triangle in potential_nested:
    for cnt in not_triangles:
        if any(cv2.pointPolygonTest(cnt, tuple(p), True) > 0 for p in triangle.squeeze()):
            break
    else:
        cv2.putText(img, "Nested", tuple(triangle[0, 0]), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 255, 255), 2)
  1. 最后,我們可以顯示在其上繪制了文本的圖像:
cv2.imshow("Shapes", img)
cv2.waitKey(0)

Output:

在此處輸入圖像描述

共:

import cv2
import numpy as np

img = cv2.imread('shapes.png')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

contours, hierarchy = cv2.findContours(255 - img_gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
hierarchy = hierarchy[0]

potential_nested = list()
not_triangles = list()

for cnt, hry in zip(contours, hierarchy):
    peri = cv2.arcLength(cnt, True)
    approx = cv2.approxPolyDP(cnt, 0.01 * peri, True)
    if len(approx) == 3:
        if hry[2] < 0:

            parent_idx = hry[3]
            parent_hier = hierarchy[parent_idx]

            if parent_hier[3] >= 0:
                potential_nested.append(cnt)
    else:
        not_triangles.append(cnt)

for triangle in potential_nested:
    for cnt in not_triangles:
        if any(cv2.pointPolygonTest(cnt, tuple(p), True) > 0 for p in triangle.squeeze()):
            break
    else:
        cv2.putText(img, "Nested", tuple(triangle[0, 0]), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 255, 255), 2)

cv2.imshow("Shapes", img)
cv2.waitKey(0)

暫無
暫無

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

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