[英]How to discard overlapping rectangles in an image?
我使用openCV
库来检测图像的 object(图 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 的图像,请参见下图 .
现在在这里您可以看到,在检测对象时,一些矩形重叠。 这不是预期的结果。 我想要一个丢弃所有重叠矩形的图形,并附带另一个仅包含那些不重叠的矩形的图形。 知道怎么做吗? 提前致谢。
假设每个矩形都有x
、 y
、宽度和高度,则需要对每两个矩形进行成对比较,通过比较 if
x
在x
和x
+ 矩形 #2 的宽度之间,或y
在y
和y
+ 矩形 #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.