Skip to content

Instantly share code, notes, and snippets.

@YaYaB
Last active April 17, 2024 08:43
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save YaYaB/39f9df9d481d784b786ad88eea8533e8 to your computer and use it in GitHub Desktop.
Save YaYaB/39f9df9d481d784b786ad88eea8533e8 to your computer and use it in GitHub Desktop.
Merge bounding boxes together.
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