The Python Oracle

How to compute IOU(overlaps) using 2 pandas DataFrames

--------------------------------------------------
Hire the world's top talent on demand or became one of them at Toptal: https://topt.al/25cXVn
and get $2,000 discount on your first invoice
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: Puzzle Game 3 Looping

--

Chapters
00:00 How To Compute Iou(Overlaps) Using 2 Pandas Dataframes
02:29 Accepted Answer Score 1
03:29 Thank you

--

Full question
https://stackoverflow.com/questions/6161...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #python3x #pandas #numpy

#avk47



ACCEPTED ANSWER

Score 1


First, I noticed your get_iou function has a condition: x2 > x1, y2 > y1, x2p > x1p, y2p > y1p. You should make sure that condition holds for both data frames.

Second, the actual has columns Image Path and Object Name, while detections has image and object_name. You may want to change the corresponding columns to one single name.

That said, here's my solution with merge:

def area(df,columns):
    '''
    compute the box area 
    @param df: a dataframe
    @param columns: box coordinates (x_min, y_min, x_max, y_max)
    '''
    x1,y1,x2,y2 = [df[col] for col in columns]
    return (x2-x1)*(y2-y1)

# rename the columns
actual = actual.rename(columns={'Image Path':'image', 'Object Name':'object_name'})

# merge on `image` and `object_name`
total_df = (actual.merge(detections, on=['image', 'object_name'])

# compute the intersection
total_df['x_max_common'] = total_df[['X_max','x2']].min(1)
total_df['x_min_common'] = total_df[['X_min','x1']].max(1)
total_df['y_max_common'] = total_df[['Y_max','y2']].min(1)
total_df['y_min_common'] = total_df[['Y_min','y1']].max(1)

# valid intersection
true_intersect = (total_df['x_max_common'] > total_df['x_min_common']) & \
                 (total_df['y_max_common'] > total_df['y_min_common'])

# filter total_df with valid intersection
total_df = total_df[true_intersect]

# the various areas
actual_areas = area(total_df, ['X_min','Y_min','X_max','Y_max'])
predicted_areas = area(total_df, ['x1','y1','x2','y2'])
intersect_areas = area(total_df,['x_min_common','y_min_common','x_max_common', 'y_max_common'])

# IOU
iou_areas = intersect_areas/(actual_areas + predicted_areas - intersect_areas)

# assign the IOU to total_df
total_df['IOU'] = iou_areas