[英]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.