[英]image rectangle extraction with cv2
您可以使用扩张关闭矩形中的间隙,然后寻找内部也有轮廓的最大轮廓。
矩形是最大的轮廓,但是找到最大的轮廓接缝太具体了。
为了概括解决方案,我建议寻找其中包含另一个轮廓的最大轮廓。
假设是矩形以其“子轮廓”来区分。
寻找孙子:
轮廓层次结构有点难以理解......
我们需要处理一个空轮廓由两个轮廓组成的事实——外轮廓和内轮廓(内轮廓是外轮廓的子轮廓)。
我们需要寻找有孙子的轮廓,而不是寻找有孩子的轮廓。
您可以使用以下阶段:
这是一个代码示例:
import numpy as np
import cv2
img = cv2.imread('rect_img.png', cv2.IMREAD_GRAYSCALE) # Read input image as Grayscale
img = img[10:-10, 10:-10] # Crop the margins
thresh = cv2.threshold(img, 0, 255, cv2.THRESH_OTSU)[1] # Convert to binary (the input image is not binary).
# Use "dilate" morphological operation for closing the gaps between the lines of the rectangle
thresh = cv2.dilate(thresh, np.ones((3,3)))
# Find contours and hierarchy, use RETR_TREE for creating a tree of contours within contours
cnts, hiers = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[-2:] # [-2:] indexing takes return value before last (due to OpenCV compatibility issues).
hiers = hiers[0] # Remove redundant dimensions of hierarchy
# Merge two lists to list of pairs (before sorting), cnts_hiers is [(c,h), (c,h), (c,h), ...]
# https://stackoverflow.com/questions/2407398/how-to-merge-lists-into-a-list-of-tuples
cnts_hiers = zip(cnts, hiers)
# Sort contours (and hierarchy) by area - the largest comes first.
cnts_hiers = sorted(cnts_hiers, key=lambda c: cv2.contourArea(c[0]), reverse=True)
# Iterate the sorted contours (and hierarchy):
# Look for contour with largest area that have a grandchild contour
# Note: we are looking for a grandchild because each empty contour has an inner contour and an outer contour.
for c_h in cnts_hiers:
c = c_h[0] # The first index of c_h is the contour
h = c_h[1] # The second index of c_h is the hierarchy of the contour
# https://docs.opencv.org/master/d9/d8b/tutorial_py_contours_hierarchy.html
# OpenCV represents hierarchy as an array of four values : [Next, Previous, First_Child, Parent]
# If there is no child or parent, that field is taken as -1
# Check if contour has at least one child contour, and than check if the child has a child (look for grandchild)
if h[2] >= 0:
child_idx = h[2] # Get the index of the child (the child is the "inner contour").
child_hier = hiers[child_idx] # Get the hierarchy that applies the index of the child.
# Check if the child has a child (look for grandchild)
if child_hier[2] >= 0:
best_cnt = c # The best candidate contour was found.
break # Break the loop
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) # Convert to BGR before drawing the contour.
# Mark best_cnt with green line
cv2.drawContours(img, [best_cnt], 0, (0, 255, 0), 2)
cv2.imshow('img', img) # Show result for testing
cv2.waitKey()
cv2.destroyAllWindows()
裁剪矩形:
rect = cv2.minAreaRect(best_cnt) # Find rectangle with minimum area
box = cv2.boxPoints(rect)
box = np.int0(box) # convert all coordinates floating point values to int
(topy, topx) = (np.min(box[:,1]), np.min(box[:,0])) # https://stackoverflow.com/questions/28759253/how-to-crop-the-internal-area-of-a-contour
(bottomy, bottomx) = (np.max(box[:,1]), np.max(box[:,0]))
rect = img[topy:bottomy+1, topx:bottomx+1, :]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.