【问题标题】:How to discard overlapping rectangles in an image?如何丢弃图像中的重叠矩形?
【发布时间】:2021-06-26 07:14:42
【问题描述】:

我使用openCV 库来检测图像的对象(图 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')

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

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

【问题讨论】:

  • 您可能希望发布您希​​望输出看起来像的结果图像。目前尚不清楚您希望如何清除 ROI。
  • 感谢您的评论。我想要一个排除所有重叠矩形的图形。
  • 那么,基本上所有这些都是误报,没有一个有任何投资回报率?在这种情况下,@HansHirse 的解决方案就是您所需要的。

标签: python opencv computer-vision


【解决方案1】:

假设每个矩形都有xy、宽度和高度,您需要对每两个矩形进行成对比较,通过比较 if 来检查重叠

  • 矩形 #1 的 x 介于 xx + 矩形 #2 的宽度之间,或者
  • 矩形#1 的y 介于yy + 矩形#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,依此类推。

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

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

【讨论】:

  • 我添加了原始图形,还添加了一个显示矩形坐标的 excel 文件。标签:MN 表示红色矩形坐标,其余表示绿色矩形坐标。你能告诉我如何通过这些信息使用你的代码来获得我想要的结果吗?
  • 不知何故,我无法在此处上传 excel 文件。尽管如此,我在一个 Excel 文件中的所有矩形都有 x、y、宽度和高度。所以基本上,我必须使用从#Check for left limit intrusion, right limit intrusion开始的你的代码?
  • 不,您需要从# Calculate left, right, top, bottom limits 开始,因为rightbottom 是根据xy、宽度和高度计算得出的。
  • 我很难为给定的图像实现此代码。比方说,如果你把这张图片作为输入,那么我该如何使用你的代码。
  • 我的图片中的“rects”是什么?
猜你喜欢
  • 2018-01-01
  • 2020-04-07
  • 1970-01-01
  • 2013-06-05
  • 2018-11-02
  • 1970-01-01
  • 2021-11-27
  • 2023-04-01
  • 1970-01-01
相关资源
最近更新 更多