简体   繁体   中英

How to combine bounding boxes in OpenCV (Python)

Hello I have an array of rectangles rect that represent the bounding boxes for detected objects. Often, these rectangles overlap and I would like to merge all rectangles that are intersecting into one big rectangle (and have multiple rectangles on screen if there are two separate clusters for example). Is there a way to do this?

I have already tried cv2.groupRectangles(rect, 1, .5) , but clusters of rectangles are grouped into one rectangle in the middle that is the same size as the original rectangles.

EDIT:

Here is the pic without grouping: 在此处输入图像描述

Here is the pic with grouping and the method described below在此处输入图像描述

To clarify a little more about what I am looking for I would just want red boxes over the individual blocks (Or ideally one box over the entire row), instead of in the middle, just so can condense the amount of boxes that I need to do computations for to speed up the program

You are to go through groupped rectangles and check them with source rectangles and to rewrite their bounds if they intersects while anything changes (see flag ):

def get_intersection_area(box_a, box_b):
    x_a = max(box_a[0], box_b[0])
    y_a = max(box_a[1], box_b[1])
    x_b = min(box_a[2], box_b[2])
    y_b = min(box_a[3], box_b[3])
    return max(0, x_b - x_a) * max(0, y_b - y_a)


groupped = cv2.groupRectangles(rect, 1, 0.5)[0]
groupped = [(x, y, x+w, y+h) for x, y, w, h in groupped]
rect = [(x, y, x+w, y+h) for x, y, w, h in rect]
flag = True
while flag:
    flag = False
    for i in range(len(groupped)):
        for r in rect:
            if 0 < get_intersection_area(groupped[i], r) <\
                    (r[2]-r[0])*(r[3]-r[1]):
                groupped[i] = (
                    min(groupped[i][0], r[0]), min(groupped[i][1], r[1]),
                    max(groupped[i][2], r[2]), max(groupped[i][3], r[3]),)
                flag = True

(I have converted boxes from tlwh format to tlrb as it more convenient for me)

Here is what it gives now:

结果

To keep rects what aren't intersected don't use cv2.groupRectangles()
and just say groupped = np.copy(rect) , though it may do an extra job this way and some optimization is needed.

An easy approach is to draw all rectangles filled on a mask. Then perform findContours on that mask to find the combined shapes. To make the result a square you can use boundingRect to find the x, y, width and height. Note that this combines all rectangles completely, not just the overlapping part.

You can find sample code for combining rectangles example here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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