如何在 python OpenCv 中检测重叠或嵌入的矩形
How to detect overlapping or embedded rectangle in python OpenCv
所以我无法用 python OpenCv
检测作为单独矩形嵌入和重叠的矩形
如果给出这张图片:
These are rectangles embedded
或这张图片:
enter image description here
如何将这些矩形检测为 2 个独立的矩形,而不仅仅是一个大多边形?
你能把输出打印到图像上吗?
这里是分别识别矩形的代码。解释与代码内联:
import numpy as np
import cv2
# The standard stuff: image reading, grayscale conversion, blurring & edge detection
image = cv2.imread('rect_image.png')
orig = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (3, 3), 0)
edges = cv2.Canny(gray, 50, 200)
# Finding and sorting contours based on contour area
cnts = cv2.findContours(edges, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:6]
vertices = []
for i, c in enumerate(cnts):
if i == 0:
# This is the largest contour
# For overlapping case the largest one will be the only one contour
peri = cv2.arcLength(cnts[i], True)
approx = cv2.approxPolyDP(cnts[i], 0.02 * peri, True)
vertices.append(approx)
elif i < len(cnts) - 1:
# Searches for any other inner contour
# Also filters out close contours generated due to thick line
if not np.isclose(cv2.contourArea(cnts[i]), cv2.contourArea(cnts[i+1]), atol=20000):
peri = cv2.arcLength(cnts[i+1], True)
approx = cv2.approxPolyDP(cnts[i+1], 0.02 * peri, True)
vertices.append(approx)
if len(vertices) == 1:
# This case is where there is only one contour (the overlapping case)
# There are eight extreme points for two overlapping rectangles
# The distinct rectangles are colored in 'green' and 'red'
extLeft1 = tuple(vertices[0][vertices[0][:, :, 0].argmin()][0])
extRight1 = tuple(vertices[0][vertices[0][:, :, 0].argmax()][0])
extTop1 = tuple(vertices[0][vertices[0][:, :, 1].argmin()][0])
extBot1 = tuple(vertices[0][vertices[0][:, :, 1].argmax()][0])
mask = np.isin(vertices[0][:, :, 1], (extRight1, extLeft1, extTop1, extBot1))
indices = np.where(mask)
vertices = np.delete(vertices[0], indices, 0)
extLeft2 = tuple(vertices[vertices[:, :, 0].argmin()][0])
extRight2 = tuple(vertices[vertices[:, :, 0].argmax()][0])
extTop2 = tuple(vertices[vertices[:, :, 1].argmin()][0])
extBot2 = tuple(vertices[vertices[:, :, 1].argmax()][0])
x, y, w, h = cv2.boundingRect(np.array([extLeft1, extLeft2, extRight1, extRight2]))
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
x, y, w, h = cv2.boundingRect(np.array([extTop1, extTop2, extBot1, extBot2]))
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)
else:
# This case is where there are inner rectangle (the embedded case)
# The distinct rectangles are colored in 'green' and 'red'
x, y, w, h = cv2.boundingRect(vertices[0])
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
x, y, w, h = cv2.boundingRect(vertices[1])
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)
# Displaying the images with identified colored rectangles
cv2.imshow("Input", orig)
cv2.imshow("Contour", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
以下是在图像上以 green
和 red
颜色绘制的检测到的矩形的输出:
所以我无法用 python OpenCv
检测作为单独矩形嵌入和重叠的矩形如果给出这张图片: These are rectangles embedded
或这张图片:
enter image description here
如何将这些矩形检测为 2 个独立的矩形,而不仅仅是一个大多边形? 你能把输出打印到图像上吗?
这里是分别识别矩形的代码。解释与代码内联:
import numpy as np
import cv2
# The standard stuff: image reading, grayscale conversion, blurring & edge detection
image = cv2.imread('rect_image.png')
orig = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (3, 3), 0)
edges = cv2.Canny(gray, 50, 200)
# Finding and sorting contours based on contour area
cnts = cv2.findContours(edges, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:6]
vertices = []
for i, c in enumerate(cnts):
if i == 0:
# This is the largest contour
# For overlapping case the largest one will be the only one contour
peri = cv2.arcLength(cnts[i], True)
approx = cv2.approxPolyDP(cnts[i], 0.02 * peri, True)
vertices.append(approx)
elif i < len(cnts) - 1:
# Searches for any other inner contour
# Also filters out close contours generated due to thick line
if not np.isclose(cv2.contourArea(cnts[i]), cv2.contourArea(cnts[i+1]), atol=20000):
peri = cv2.arcLength(cnts[i+1], True)
approx = cv2.approxPolyDP(cnts[i+1], 0.02 * peri, True)
vertices.append(approx)
if len(vertices) == 1:
# This case is where there is only one contour (the overlapping case)
# There are eight extreme points for two overlapping rectangles
# The distinct rectangles are colored in 'green' and 'red'
extLeft1 = tuple(vertices[0][vertices[0][:, :, 0].argmin()][0])
extRight1 = tuple(vertices[0][vertices[0][:, :, 0].argmax()][0])
extTop1 = tuple(vertices[0][vertices[0][:, :, 1].argmin()][0])
extBot1 = tuple(vertices[0][vertices[0][:, :, 1].argmax()][0])
mask = np.isin(vertices[0][:, :, 1], (extRight1, extLeft1, extTop1, extBot1))
indices = np.where(mask)
vertices = np.delete(vertices[0], indices, 0)
extLeft2 = tuple(vertices[vertices[:, :, 0].argmin()][0])
extRight2 = tuple(vertices[vertices[:, :, 0].argmax()][0])
extTop2 = tuple(vertices[vertices[:, :, 1].argmin()][0])
extBot2 = tuple(vertices[vertices[:, :, 1].argmax()][0])
x, y, w, h = cv2.boundingRect(np.array([extLeft1, extLeft2, extRight1, extRight2]))
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
x, y, w, h = cv2.boundingRect(np.array([extTop1, extTop2, extBot1, extBot2]))
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)
else:
# This case is where there are inner rectangle (the embedded case)
# The distinct rectangles are colored in 'green' and 'red'
x, y, w, h = cv2.boundingRect(vertices[0])
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
x, y, w, h = cv2.boundingRect(vertices[1])
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)
# Displaying the images with identified colored rectangles
cv2.imshow("Input", orig)
cv2.imshow("Contour", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
以下是在图像上以 green
和 red
颜色绘制的检测到的矩形的输出: