如何在 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()

以下是在图像上以 greenred 颜色绘制的检测到的矩形的输出: