Это решение, которое я придумал.
Создание уникального ключа для каждой ограничивающей рамки
df['key']=df['xmin'].astype(str)+'_'+df['ymin'].astype(str)+'_'+df['xmax'].astype(str)+'_'+df['ymax'].astype(str)
Создание внешнего соединения всех строк на основе имени файла. (для вычисления IoU)
###copy df
df_1=df.copy()
###Renaming df columns with _1 suffix
df_cols=df.columns.tolist()
df_cols.remove('filename')
new_cols=[col+'_1' for col in df_cols]
new_col_dict=dict(zip(df_cols,new_cols))
df_1.rename(columns=new_col_dict,inplace=True)
### Outer joining both dataframes
newdf=pd.merge(df,df_1,'outer',on='filename')
Пример внешнего соединения:
Function to find IoU of each row
def IOU(df):
'''funtion to calulcate IOU within rows of dataframe'''
# determining the minimum and maximum -coordinates of the intersection rectangle
xmin_inter = max(df.xmin, df.xmin_1)
ymin_inter = max(df.ymin, df.ymin_1)
xmax_inter = min(df.xmax, df.xmax_1)
ymax_inter = min(df.ymax, df.ymax_1)
# calculate area of intersection rectangle
inter_area = max(0, xmax_inter - xmin_inter + 1) * max(0, ymax_inter - ymin_inter + 1)
# calculate area of actual and predicted boxes
actual_area = (df.xmax - df.xmin + 1) * (df.ymax - df.ymin + 1)
pred_area = (df.xmax_1 - df.xmin_1 + 1) * (df.ymax_1 - df.ymin_1+ 1)
# computing intersection over union
iou = inter_area / float(actual_area + pred_area - inter_area)
# return the intersection over union value
return iou
Расчет IoU для каждой строки и фильтрация строк с ioU < 0,4
newdf['iou']= newdf.apply(IOU, axis = 1)
### filtering all iou<0.4
newdf=newdf[newdf['iou']>=0.4]
Получение наилучшего соответствия для каждого ключа
как только у нас будет фрейм данных сопоставления IoU, проанализируйте каждый ограничивающий прямоугольник уникального ключа, получите значение с максимальной достоверностью для каждого уникального ключа с iou> 0,4
best_df=pd.DataFrame()
for i, v in df.iterrows():
key=v['key']
iou_match=newdf[newdf['key']==key]
iou_match.sort_values('confidence_1',ascending=False,inplace=True)
iou_match=iou_match.reset_index()
best_match=iou_match.loc[0,['filename','class_1','xmin_1','ymin_1','xmax_1','ymax_1','confidence_1']]
best_df=best_df.append(best_match,ignore_index=True)
best_df
теперь выглядит так:
class_1 confidence_1 filename xmax_1 xmin_1 ymax_1 ymin_1
0 cube 0.99 dummyfile.jpg 197.0 88.0 198.0 87.0
1 cube 0.99 dummyfile.jpg 197.0 88.0 198.0 87.0
2 cube 0.99 dummyfile.jpg 197.0 88.0 198.0 87.0
3 cube 0.89 dummyfile.jpg 603.0 492.0 295.0 187.0
4 cube 0.89 dummyfile.jpg 603.0 492.0 295.0 187.0
Удаление дубликатов для получения уникальных совпадений
best_df.drop_duplicates(inplace=True)
Окончательный результат:
class_1 confidence_1 filename xmax_1 xmin_1 ymax_1 ymin_1
0 cube 0.99 dummyfile.jpg 197.0 88.0 198.0 87.0
3 cube 0.89 dummyfile.jpg 603.0 492.0 295.0 187.0