-
Notifications
You must be signed in to change notification settings - Fork 59
/
Copy pathtopology_exception.py
105 lines (93 loc) · 3.42 KB
/
topology_exception.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# -*- coding: utf-8 -*-
"""
Created on Sat Dec 31 12:22:50 2016
@author: ironbar
Function for dealing with topology exception errors
"""
import pandas as pd
import numpy as np
import time
import shapely
import shapely.geometry
def __get_valid_wkt_str(input, precision, debug_print):
"""
Function that checks that a wkt str is valid
"""
if type(input) is str:
wkt_str = input
else:
#Get the initial str
wkt_str = shapely.wkt.dumps(input, rounding_precision=precision)
#Loop until we find a valid polygon
for i in range(100):
polygon = shapely.wkt.loads(wkt_str)
if not polygon.is_valid:
#print debugging info
print 'Invalid polygon in %s. Iteration: %i' % (debug_print, i)
#Use buffer to try to fix the polygon
polygon = polygon.buffer(0)
#Get back to multipolygon if necesary
if polygon.type == 'Polygon':
polygon = shapely.geometry.MultiPolygon([polygon])
#Dump to str again
wkt_str = shapely.wkt.dumps(polygon, rounding_precision=precision)
else:
break
return wkt_str
def __create_square_around_point(point, side):
"""
Creates a square polygon with shapely given
the center point
"""
#Create canonical square points
square_points = np.zeros((4,2))
square_points[1, 0] = 1
square_points[2] = 1
square_points[3, 1] = 1
#Scale the square
square_points *= side
#Position to have the point in the center
for i in range(2):
square_points[:, i] += point[i] - side/2.
pol = shapely.geometry.Polygon(square_points)
return pol
def repair_topology_exception(submission_path, precision, image_id, n_class, point,
side=1e-4):
"""
Tries to repair the topology exception error by creating a squared
hole in the given point with the given side
"""
start_time = time.time()
#Load the submission
print 'Loading the submission...'
df = pd.read_csv(submission_path)
#Loop over the values changing them
#I'm going to use the values because I think iterating over the dataframe is slow
#But I'm not sure
print 'Looping over the polygons'
polygons = df.MultipolygonWKT.values
img_ids = df.ImageId.values
class_types = df.ClassType.values
for i, polygon, img_id, class_type in zip(range(len(polygons)), polygons,
img_ids, class_types):
if img_id == image_id and n_class == class_type:
polygon = shapely.wkt.loads(polygon)
square = __create_square_around_point(point, side)
polygon = polygon.difference(square)
polygons[i] = __get_valid_wkt_str(polygon, precision,
'%s class%i' % (img_id, class_type))
#Update the dataframe
df.MultipolygonWKT = polygons
#Save to a new file
print 'Saving the submission...'
df.to_csv(submission_path,
index=False)
print 'It took %i seconds to repair the submission' % (
time.time() - start_time)
if __name__ == '__main__':
repair_topology_exception('/home/guillermo/sample_submission.csv',
precision=6,
image_id='6100_0_2',
n_class=4,
point= (0.006539, -0.005582),
side=1e-4)