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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With