enter image description hereI have a data frame like -
image label bb0 bb1 bb2 bb3
im1 L1 0.16602577 0.20398015 0.6750162 1.0
im1 L2 0.38657066 0.5192988000000001 0.45647129999999997 0.93410575
im1 L2 0.019637141 0.66581047 0.1369443 0.9160644
im1 L2 0.3700079 0.32554457 0.45773253 0.581625
where bb0, bb1, bb2, bb3 are coordinates for predicted bounding boxes in order y1, x1, y2, x2. I want to merge the bounding boxes for each label based on the overlapping area (IOU) i.e. if iou is greater than some threshold then merge the boxes otherwise keep it as it is. In the final data frame i want updated bounding boxes only.
A scenario can be seen in the attached image. The two orange boxes in the middle will combine to make the yellow box and all other boxes will remain same. The final data will contain three rows, one for L1, one orange box which is not overlapping and one new yellow box. I want to update the dataframe in this manner.
I am using folowing code -
def iou(box1, box2):
assert box1['bb1'] < box1['bb3']
assert box1['bb0'] < box1['bb2']
assert box2['bb1'] < box2['bb3']
assert box2['bb0'] < box2['bb2']
# determine the coordinates of the intersection rectangle
x_left = max(box1['bb1'], box2['bb1'])
y_top = max(box1['bb0'], box2['bb0'])
x_right = min(box1['bb3'], box2['bb3'])
y_bottom = min(box1['bb2'], box2['bb2'])
if x_right < x_left or y_bottom < y_top:
iou1 = 0
else:
intersection_area = (x_right - x_left) * (y_bottom - y_top)
# compute the area of both AABBs
bb1_area = (box1["bb3"] - box1["bb1"]) * (box1["bb2"] - box1['bb0'])
bb2_area = (box2["bb3"] - box2["bb1"]) * (box2["bb2"] - box2['bb0'])
#intersection over union
iou1 = intersection_area / float(bb1_area + bb2_area - intersection_area)
return iou1
def get_iou(df):
df_out = pd.DataFrame(columns = df.columns)
for i in (df["image"].unique()):
print(i)
#df_out = pd.DataFrame(columns = df.columns)
k1 = df[df["image"] == str(i)]
k2 = k1["class"].value_counts().reset_index()
k3 = k2[k2["class"] > 1]
k8 = k2[k2["class"] == 1]
k9 = df[(df["image"] == str(i)) & (df["class"].isin(k8["index"]))]
df_out = df_out.append(k9, ignore_index = True)
new_df = pd.DataFrame(columns = ["class","Combinations", "IOU"])
for j in k3["index"].unique():
k4 = df[(df["image"] == str(i)) & (df["class"] == str(j))]
k4["unique_id"] = list(range(len(k4)))
#k5 = k4
#k6 = k5.to_dict(orient='records')
#k7 = list(itertools.combinations(k6, 2))
gg = list(itertools.combinations(k4["unique_id"], 2))
#new_df = pd.DataFrame(columns = ["Combinations", "IOU"])
#print(k7, "\n")
df_out2 = pd.DataFrame(columns = df.columns)
l = (0,1)
while l in gg:
#print(l)
box1 = k4[k4["unique_id"] == l[0]].to_dict('records')[0]
#print(box1)
box2 = k4[k4["unique_id"] == l[1]].to_dict('records')[0]
iou1 = iou(box1, box2)
assert iou1 >= 0.0
assert iou1 <= 1.0
print(iou1)
if iou1 <= 0.05:
print("No Overlap")
else:
x_left_new = min(box1["bb1"], box2["bb1"])
x_right_new = max(box2["bb3"], box1["bb3"])
y_top_new = min(box2["bb0"], box2["bb0"])
y_bottom_new = max(box1["bb2"], box2["bb2"])
new_bb = {'image' : box1["image"],
'class' : box1['class'],
'score' : np.nan,
'bb0' : y_top_new,
'bb1' : x_left_new,
'bb2' : y_bottom_new,
'bb3' : x_right_new,
'key' : box1["key"]}
k4 = k4.append(new_bb, ignore_index = True)
k4 = k4[~k4["unique_id"].isin(l)]
k4["unique_id"] = list(range(len(k4)))
gg = list(itertools.combinations(k4["unique_id"], 2))
df_out2 = df_out2.append(k4)