The problem with this code is that it even detect a triangle as nested triangle if it is inside another shape like circle, square or rectangular. I can't seem to find a solution to this problem.
Usecases: If the triangle is inside another shape like square, cricle or rectangular it not detect it as nested triangle.
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()
Image For Testing:
We have this image:
We want to detect every triangle that is inside a triangle, while not inside any other shape. With the above image, there are two such triangles.
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
, and the other to store every shape that is not a triangle, not_triangles
:potential_nested = list()
not_triangles = list()
zip()
method, and find the approximate contour for each contours of the iterations:for cnt, hry in zip(contours, hierarchy):
peri = cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, 0.01 * peri, True)
not_triangles
list. If so, check to see if it's in another shape before appending it to the potential_nested
list. 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)
Output:
Altogether:
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)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.