Intersection Over Union

Description

Intersection Over Union (IoU) is a is a metric that allows to evaluate how similar predicted bounding box is to the ground truth bounding box. Let's assume we have ground truth object (green color) and predicted object (red color):

Intersection Over Union

The Jaccard coefficient measures similarity between finite sample sets, and is defined as the size of the intersection divided by the size of the union of the sample sets:

Examples of Intersection Over Union

We can compare the ground truth bounding box and prediction bounding box by using IoU metric as:

Examples of Intersection Over Union

EXAMPLE

/* ANSI C89, C99, C11 compliance                                     */
/* The following example shows the usage of Intersection Over Union. */
#include <stdio.h>
#include <string.h>

#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))

/*
   a---
   |  |
   ---b
*/
struct OBJ_DET {
   unsigned int n_class;      /* class of object                                 */
   float        r_score;      /* detection score                                 */
   unsigned int n_x_a;        /* bounding box upper left corner x coordinate     */
   unsigned int n_y_a;        /* bounding box upper left corner y coordinate     */
   unsigned int n_x_b;        /* bounding box bottom right corner x coordinate   */
   unsigned int n_y_b;        /* bounding box bottom right corner y coordinate   */
   unsigned int n_width;      /* bounding box width                              */
   unsigned int n_height;     /* bounding box height                             */
   unsigned int n_area;       /* bounding box area                               */
   unsigned int n_state;      /* state of detection: 0 - non  active, 1 - active */
};

/* The Jaccard index, also known as Intersection over Union (IoU) and the Jaccard similarity coefficient. */
float intersection_over_union(unsigned int n_area_inter, unsigned int n_area_a, unsigned int n_area_b)   {
   return (float)n_area_inter / (float)(n_area_a + n_area_b - n_area_inter);
}

void object_area(struct OBJ_DET *pst_dt, size_t n_size)  {
   size_t i;


   for (i = 0; i < n_size; i++) {
      pst_dt[i].n_area = pst_dt[i].n_width * pst_dt[i].n_height;
      pst_dt[i].n_x_b = pst_dt[i].n_x_a + pst_dt[i].n_width;
      pst_dt[i].n_y_b = pst_dt[i].n_y_a + pst_dt[i].n_height;
   }
}

int main() {
   struct OBJ_DET st_gt = {0, 0.8f, 1, 1, 0, 0, 5, 4, 0, 1};   /* ground truth object */
   struct OBJ_DET st_ds[3] = {{0, 0.7f, 1, 1, 0, 0, 4, 4, 0, 1}, {0, 0.2f, 2, 2, 0, 0, 4, 4, 0, 1}, {0, 0.8f, 1, 1, 0, 0, 4, 4, 0, 1}};
   size_t         i, n_size;
   int            z_xx_a, z_yy_a, z_xx_b, z_yy_b, z_w, z_h;
   float          r_iou;


   
   n_size = 3;                                                 /* number of objects  */
   object_area(&st_ds[0], n_size);
   object_area(&st_gt, 1);
   for (i = 0; i < n_size; i++)  {
      z_xx_a = MAX(st_gt.n_x_a, st_ds[i].n_x_a);
      z_yy_a = MAX(st_gt.n_y_a, st_ds[i].n_y_a);
      z_xx_b = MIN(st_gt.n_x_b, st_ds[i].n_x_b);
      z_yy_b = MIN(st_gt.n_y_b, st_ds[i].n_y_b);               
      z_w = z_xx_b - z_xx_a;
      z_h = z_yy_b - z_yy_a;
      if ((z_w > 0) && (z_h > 0))   {
         r_iou = intersection_over_union(z_w * z_h, st_ds[i].n_area, st_gt.n_area);
         printf("IoU = %f\n", r_iou);
      }
   }
   return 0;
}

REFERENCES:

0. Jaccard index