繁体   English   中英

如何丢弃图像中的重叠矩形?

[英]How to discard overlapping rectangles in an image?

我使用openCV库来检测图像的 object(图 1),见下文。 图。1

为此,我编写了以下代码:

import matplotlib.pyplot as plt
import cv2 

# source data
img_file= "Fig1.jpg"

# create an OpenCV image
img= cv2.imread(img_file)

# convert color image to grey image
gray_img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

im_gauss = cv2.GaussianBlur(gray_img, (5, 5), 0)
ret, thresh = cv2.threshold(im_gauss, 127, 255, 0)
# get contours
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

margin = 40
# calculate area and filter 
for con in contours:
    area = cv2.contourArea(con)
    if 100 < area < 500:
        x,y,w,h = cv2.boundingRect(con)
        cv2.rectangle(img, (x-margin, y-margin), (x + w+margin, y + h+margin), (0,255,0), 2)
        
plt.imshow(img, cmap='gray')

这些代码将能够为您提供检测到 object 的图像,请参见下图图2 .

现在在这里您可以看到,在检测对象时,一些矩形重叠。 这不是预期的结果。 我想要一个丢弃所有重叠矩形的图形,并附带另一个仅包含那些不重叠的矩形的图形。 知道怎么做吗? 提前致谢。

假设每个矩形都有xy 、宽度和高度,则需要对每两个矩形进行成对比较,通过比较 if

  • 矩形 #1 的xxx + 矩形 #2 的宽度之间,或
  • 矩形 #1 的yyy + 矩形 #2 的高度之间,或
  • ...

幸运的是,您可以使用 NumPy 的矢量化功能来避免嵌套循环。

在下面的代码中,我生成了一些随机矩形,并过滤掉那些重叠的:

import cv2
import numpy as np

# Randomly generate n white rectangles on black background
n = 20
rects = [[np.random.randint(0, 350),
          np.random.randint(0, 250),
          np.random.randint(10, 50),
          np.random.randint(10, 50)] for i in range(n)]

img = np.zeros((300, 400), np.uint8)

for rect in rects:
    img = cv2.rectangle(img, (rect[0], rect[1]),
                        (rect[0] + rect[2], rect[1] + rect[3]), 255, 1)

# Calculate left, right, top, bottom limits
rects = np.array(rects)
left = np.expand_dims(rects[:, 0], axis=1)
right = np.expand_dims(rects[:, 0] + rects[:, 2], axis=1)
top = np.expand_dims(rects[:, 1], axis=1)
bottom = np.expand_dims(rects[:, 1] + rects[:, 3], axis=1)

# Check for left limit intrusions, right limit intrusions, ...
check_l = (left <= left.T) & (left.T <= right)
check_r = (left <= right.T) & (right.T <= right)
check_t = (top <= top.T) & (top.T <= bottom)
check_b = (top <= bottom.T) & (bottom.T <= bottom)

# Check for combinations of left-top intrusions, left-bottom intrusions, ...
check_lt = check_l & check_t
check_lb = check_l & check_b
check_rt = check_r & check_t
check_rb = check_r & check_b

# Get all combinations; get rid of self identical matches
check = check_lt | check_lb | check_rt | check_rb
check = np.bitwise_xor(check, np.eye(n).astype(bool))
check = np.argwhere(check)

# Get unique indices of corrupted rectangles
corrupted = np.unique(check)

# Draw cleaned image
img_clean = np.zeros_like(img)
for i, rect in enumerate(rects):
    if i not in corrupted:
        img_clean = cv2.rectangle(img_clean, (rect[0], rect[1]),
                                  (rect[0] + rect[2], rect[1] + rect[3]), 255, 1)

# Output
cv2.imshow('Original image', img)
cv2.imshow('Cleaned image', img_clean)
cv2.waitKey(0)
cv2.destroyAllWindows()

首先,我们来看看“输入”和“输出”:

输入

输出

基本上,计算每个矩形的左、右、上和下限。 然后,计算矩形#1 的每个组合从左侧、或从顶部、或从右侧“侵入”到矩形#2 中,依此类推。

几个大小为(n, n)bool矩阵,其中n是矩形的数量,中间存储,但我猜,对于n <= 2000左右,memory 消耗应该可以忽略不计。 由于矢量化,这种方法非常快。

----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.16299-SP0
Python:        3.9.1
NumPy:         1.20.2
OpenCV:        4.5.1
----------------------------------------

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM