|
a |
|
b/tf_iou.py |
|
|
1 |
################################################################################################################################ |
|
|
2 |
|
|
|
3 |
import numpy as np |
|
|
4 |
import tensorflow as tf |
|
|
5 |
|
|
|
6 |
################################################################################################################################ |
|
|
7 |
|
|
|
8 |
# This function is designed to work with Keras datagenerators as a model metric. |
|
|
9 |
|
|
|
10 |
# SOURCE1: https://github.com/Balupurohit23/IOU-for-bounding-box-regression-in-Keras/blob/master/iou_metric.py |
|
|
11 |
# SOURCE2: https://www.kaggle.com/vbookshelf/keras-iou-metric-implemented-without-tensor-drama |
|
|
12 |
|
|
|
13 |
# I made use of the two sources because they each offered something I needed. I essentially used the framework of |
|
|
14 |
# Source 2, but with the code of Source 1 because the format aligned with my data. |
|
|
15 |
|
|
|
16 |
# I also reassigned the 'astype' numpy code to fit with tensorflow as well as converting the keras functions to np. |
|
|
17 |
|
|
|
18 |
def tf_iou(y_true, y_pred): |
|
|
19 |
# iou as metric for bounding box regression |
|
|
20 |
# input must be as [x1, y1, x2, y2] |
|
|
21 |
|
|
|
22 |
results = [] |
|
|
23 |
|
|
|
24 |
for i in range(0,y_true.shape[0]): |
|
|
25 |
|
|
|
26 |
y_true = tf.dtypes.cast(y_true, tf.float32) |
|
|
27 |
y_pred = tf.dtypes.cast(y_pred, tf.float32) |
|
|
28 |
|
|
|
29 |
# AOG = Area of Groundtruth box |
|
|
30 |
AoG = np.abs(np.transpose(y_true)[2] - np.transpose(y_true)[0] + 1) * np.abs(np.transpose(y_true)[3] -\ |
|
|
31 |
np.transpose(y_true)[1] + 1) |
|
|
32 |
|
|
|
33 |
# AOP = Area of Predicted box |
|
|
34 |
AoP = np.abs(np.transpose(y_pred)[2] - np.transpose(y_pred)[0] + 1) * np.abs(np.transpose(y_pred)[3] - \ |
|
|
35 |
np.transpose(y_pred)[1] + 1) |
|
|
36 |
|
|
|
37 |
# overlaps are the co-ordinates of intersection box |
|
|
38 |
overlap_0 = np.maximum(np.transpose(y_true)[0], np.transpose(y_pred)[0]) |
|
|
39 |
overlap_1 = np.maximum(np.transpose(y_true)[1], np.transpose(y_pred)[1]) |
|
|
40 |
overlap_2 = np.minimum(np.transpose(y_true)[2], np.transpose(y_pred)[2]) |
|
|
41 |
overlap_3 = np.minimum(np.transpose(y_true)[3], np.transpose(y_pred)[3]) |
|
|
42 |
|
|
|
43 |
# intersection area |
|
|
44 |
intersection = (overlap_2 - overlap_0 + 1) * (overlap_3 - overlap_1 + 1) |
|
|
45 |
|
|
|
46 |
# area of union of both boxes |
|
|
47 |
union = AoG + AoP - intersection |
|
|
48 |
|
|
|
49 |
# iou calculation |
|
|
50 |
iou = intersection / union |
|
|
51 |
|
|
|
52 |
# bounding values of iou to (0,1) |
|
|
53 |
epsilon = np.finfo(np.float32).eps |
|
|
54 |
iou = np.clip(iou, 0.0 + epsilon, 1.0 - epsilon) |
|
|
55 |
iou = tf.dtypes.cast(iou, tf.float32) |
|
|
56 |
|
|
|
57 |
# append the result to a list at the end of each loop |
|
|
58 |
results.append(iou) |
|
|
59 |
|
|
|
60 |
# return the mean IoU score for the batch |
|
|
61 |
return np.mean(results) |
|
|
62 |
|
|
|
63 |
################################################################################################################################ |