Last active
April 17, 2024 08:43
-
-
Save YaYaB/39f9df9d481d784b786ad88eea8533e8 to your computer and use it in GitHub Desktop.
Merge bounding boxes together.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import copy | |
import cv2 | |
import os | |
def merge_bboxes(bboxes, delta_x=0.1, delta_y=0.1): | |
""" | |
Arguments: | |
bboxes {list} -- list of bounding boxes with each bounding box is a list [xmin, ymin, xmax, ymax] | |
delta_x {float} -- margin taken in width to merge | |
detlta_y {float} -- margin taken in height to merge | |
Returns: | |
{list} -- list of bounding boxes merged | |
""" | |
def is_in_bbox(point, bbox): | |
""" | |
Arguments: | |
point {list} -- list of float values (x,y) | |
bbox {list} -- bounding box of float_values [xmin, ymin, xmax, ymax] | |
Returns: | |
{boolean} -- true if the point is inside the bbox | |
""" | |
return point[0] >= bbox[0] and point[0] <= bbox[2] and point[1] >= bbox[1] and point[1] <= bbox[3] | |
def intersect(bbox, bbox_): | |
""" | |
Arguments: | |
bbox {list} -- bounding box of float_values [xmin, ymin, xmax, ymax] | |
bbox_ {list} -- bounding box of float_values [xmin, ymin, xmax, ymax] | |
Returns: | |
{boolean} -- true if the bboxes intersect | |
""" | |
for i in range(int(len(bbox) / 2)): | |
for j in range(int(len(bbox) / 2)): | |
# Check if one of the corner of bbox inside bbox_ | |
if is_in_bbox([bbox[2 * i], bbox[2 * j + 1]], bbox_): | |
return True | |
return False | |
def good_intersect(bbox, bbox_): | |
return (bbox[0] < bbox_[2] and bbox[2] > bbox_[0] and | |
bbox[1] < bbox_[3] and bbox[3] > bbox_[1]) | |
# Sort bboxes by ymin | |
bboxes = sorted(bboxes, key=lambda x: x[1]) | |
tmp_bbox = None | |
while True: | |
nb_merge = 0 | |
used = [] | |
new_bboxes = [] | |
# Loop over bboxes | |
for i, b in enumerate(bboxes): | |
for j, b_ in enumerate(bboxes): | |
# If the bbox has already been used just continue | |
if i in used or j <= i: | |
continue | |
# Compute the bboxes with a margin | |
bmargin = [ | |
b[0] - (b[2] - b[0]) * delta_x, b[1] - (b[3] - b[1]) * delta_y, | |
b[2] + (b[2] - b[0]) * delta_x, b[3] + (b[3] - b[1]) * delta_y | |
] | |
b_margin = [ | |
b_[0] - (b_[2] - b_[0]) * delta_x, b_[1] - (b[3] - b[1]) * delta_y, | |
b_[2] + (b_[2] - b_[0]) * delta_x, b_[3] + (b_[3] - b_[1]) * delta_y | |
] | |
# Merge bboxes if bboxes with margin have an intersection | |
# Check if one of the corner is in the other bbox | |
# We must verify the other side away in case one bounding box is inside the other | |
if intersect(bmargin, b_margin) or intersect(b_margin, bmargin): | |
tmp_bbox = [min(b[0], b_[0]), min(b[1], b_[1]), max(b_[2], b[2]), max(b[3], b_[3])] | |
used.append(j) | |
# print(bmargin, b_margin, 'done') | |
nb_merge += 1 | |
if tmp_bbox: | |
b = tmp_bbox | |
if tmp_bbox: | |
new_bboxes.append(tmp_bbox) | |
elif i not in used: | |
new_bboxes.append(b) | |
used.append(i) | |
tmp_bbox = None | |
# If no merge were done, that means all bboxes were already merged | |
if nb_merge == 0: | |
break | |
bboxes = copy.deepcopy(new_bboxes) | |
return new_bboxes |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment