Merging bounding boxes based on overlap and predicted lables

Viewed 196

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)
0 Answers
Related