给定具有多个边界框的图像,如何仅突出显示完全在另一个边界框内的那些边界框?

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 值

【讨论】:

以上是关于给定具有多个边界框的图像,如何仅突出显示完全在另一个边界框内的那些边界框?的主要内容,如果未能解决你的问题,请参考以下文章

单击jqgrid网格时如何仅突出显示单元格

Excel:如果在另一列中发现重复的单元格值,则突出显示绿色

仅突出显示掌纹图像中的折痕(主要线条和皱纹)

如何在 Phaser 3, Spine 中获取边界框的大小?

VBA 突出显示边界条件外范围内的单元格

模型训练 - 对象的裁剪图像 VS 带有边界框的更大图像