给定具有多个边界框的图像,如何仅突出显示完全在另一个边界框内的那些边界框?
Posted
技术标签:
【中文标题】给定具有多个边界框的图像,如何仅突出显示完全在另一个边界框内的那些边界框?【英文标题】:Given an image with several bounding boxes, how do I highlight only those bounding boxes that are completely inside another bounding box? 【发布时间】:2022-01-22 14:09:15 【问题描述】:我不想突出显示与其他框部分重叠或不与任何其他框重叠的边界框。我试图通过检测轮廓来做到这一点:
import cv2
# Read input image
img = cv2.imread('image.png')
# Convert to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Apply threshold
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# Find contours and hierarchy
cnts, hier = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[-2:]
# Draw all contours with green color for testing
cv2.drawContours(img, cnts, -1, (0, 255, 0))
# Hierarchy Representation in OpenCV
# So each contour has its own information regarding what hierarchy it is,
# who is its child, who is its parent etc.
# OpenCV represents it as an array of four values : [Next, Previous, First_Child, Parent]
# Iterate contours and hierarchy:
for c, h in zip(cnts, hier[0]):
# Check if contour has one partent and one at least on child:
if (h[3] >= 0) and (h[2] >= 0):
# Get the partent from the hierarchy
hp = hier[0][h[3]]
# Check if the parent has a parent:
if hp[3] >= 0:
# Get bounding rectange
x, y, w, h = cv2.boundingRect(c)
# Draw red rectange for testing
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 0, 255), thickness=1)
# Show result for testing
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
但它会选择图像中的每个轮廓。例如,如果这是原始图像:
那么这就是我运行上面代码时得到的结果:
如何首先仅检测此图像中的边界框,其次仅突出显示完全 100% 位于另一个边界框内的边界框?
【问题讨论】:
您应该首先了解获取用于绘制这些框的数据。从绘制的图像中提取它们对我来说似乎有点愚蠢。 【参考方案1】:步骤 1. 使用cv2.contourArea
按面积升序对边界框进行排序。看到这个question。
第 2 步 - For 循环 - 从最小的边界框开始 - 检查给定框与较大框的交集区域是否 = 给定框的面积。如果是,那么它是 100% 在另一个更大的盒子里。
例如,我们可以像这样将边界框转换为遮罩:
mask = np.zeros(img.shape[:2], dtype=np.float32)
(x, y, w, h) = [int(v) for v in bounding_box]
mask[y:y+h, x:x+w] = 1.
然后得到两个掩码相交的面积:
mask1_f = mask1.flatten()
mask2_f = mask2.flatten()
intersection = np.sum(mask1_f * mask2_f)
【讨论】:
【参考方案2】:要让一个盒子完全在另一个盒子里面,盒子的每个顶点都应该在更大的盒子里面。您可以使用嵌套的 for 循环来过滤框,以检查框 2 的所有坐标是否在框 1 的范围内。
collided_boxes = []
for box1 in boxes:
for box2 in boxes:
if box1 != box2:
if (box1[0] < box2[0] < box1[2] and box1[1] < box2[1] < box1[3]) and (box1[0] < box2[2] < box1[2] and box1[1] < box2[1] < box1[3]) and (box1[0] < box2[2] < box1[2] and box1[1] < box2[3] < box1[3]) and (box1[0] < box2[0] < box1[2] and box1[1] < box2[3] < box1[3]):
if box2 not in collided_boxes:
collided_boxes.append(box2)
在上面,我给出了盒子两个极端角的坐标值,即 [(min x value, min y value) and (max x value, max y value)]:box[0] =最小 x 值,框 [1] = 最小 y 值,框 [2] = 最大 x 值,框 [3] = 最大 y 值
【讨论】:
以上是关于给定具有多个边界框的图像,如何仅突出显示完全在另一个边界框内的那些边界框?的主要内容,如果未能解决你的问题,请参考以下文章
Excel:如果在另一列中发现重复的单元格值,则突出显示绿色