简体   繁体   中英

Intersection over union on non rectangular quadrilaterals

I am working on the problem of parking space detection. To detect empty parking space I am using intersection over union. But, parking spaces aren't always rectangular. So, I have made a labeling tool that can draw polygons of various shapes. Now, I want to know if there is any python library that provides IOU functionality? If not is there any alternative?

在此处输入图像描述

You should use the shapely Python library:

from shapely.geometry import box, Polygon

# Define Each polygon 
pol1_xy = [[130, 27], [129.52, 27], [129.45, 27.1], [130.13, 26]]
pol2_xy = [[30, 27.200001], [129.52, 27.34], [129.45, 27.1], [130.13, 26.950001]]
polygon1_shape = Polygon(pol1_xy)
polygon2_shape = Polygon(pol2_xy)

# Calculate Intersection and union, and tne IOU
polygon_intersection = polygon1_shape.intersection(polygon2_shape).area
polygon_union = polygon1_shape.union(polygon2_shape).area
IOU = polygon_intersection / polygon_union 

There is a slight improvement that can be made to ibarrond's answer . Finding the union of our two quadrilaterals is a costly operation. Instead, we can find the area of the union by first adding the areas of both quadrilaterals. This will over-count the area where the quadrilaterals overlap, but we can correct this by subtracting the area of the intersect, which we already calculated:

def IOU(pol1_xy, pol2_xy):
    # Define each polygon
    polygon1_shape = Polygon(pol1_xy)
    polygon2_shape = Polygon(pol2_xy)

    # Calculate intersection and union, and the IOU
    polygon_intersection = polygon1_shape.intersection(polygon2_shape).area
    polygon_union = polygon1_shape.area + polygon2_shape.area - polygon_intersection
    return polygon_intersection / polygon_union

The following code verifies that this improvement gives the same result, and then it times both versions. Function IOU1 contain's ibarrond's code, and function IOU2 contains the improvement.

from shapely.geometry import Polygon
from timeit import timeit

def IOU1(pol1_xy, pol2_xy):
    # Define each polygon
    polygon1_shape = Polygon(pol1_xy)
    polygon2_shape = Polygon(pol2_xy)

    # Calculate intersection and union, and the IOU
    polygon_intersection = polygon1_shape.intersection(polygon2_shape).area
    polygon_union = polygon1_shape.union(polygon2_shape).area
    return polygon_intersection / polygon_union

def IOU2(pol1_xy, pol2_xy):
    # Define each polygon
    polygon1_shape = Polygon(pol1_xy)
    polygon2_shape = Polygon(pol2_xy)

    # Calculate intersection and union, and tne IOU
    polygon_intersection = polygon1_shape.intersection(polygon2_shape).area
    polygon_union = polygon1_shape.area + polygon2_shape.area - polygon_intersection
    return polygon_intersection / polygon_union

if __name__ == '__main__':
    # Define test coordinates:
    pol1_xy = [[130, 27], [129.52, 27], [129.45, 27.1], [130.13, 26]]
    pol2_xy = [[30, 27.200001], [129.52, 27.34], [129.45, 27.1], [130.13, 26.950001]]

    # Test that results are the same (except for minor rounding differences):
    assert abs(IOU1(pol1_xy, pol2_xy) - IOU2(pol1_xy, pol2_xy)) < 1e-16

    # Determine speeds of both functions:
    t1=timeit('IOU1(pol1_xy, pol2_xy)', number=100000,
              setup='from __main__ import IOU1, pol1_xy, pol2_xy')
    t2=timeit('IOU2(pol1_xy, pol2_xy)', number=100000,
              setup='from __main__ import IOU2, pol1_xy, pol2_xy')
    print('time for IOU1:  %s' %t1)
    print('time for IOU2:  %s' %t2)

Here's the result I obtained:

time for IOU1:  20.0208661
time for IOU2:  11.0288122

Note that the exact times will vary based on the hardware and the current background activity.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM