-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsequence.py
More file actions
144 lines (111 loc) · 3.87 KB
/
Copy pathsequence.py
File metadata and controls
144 lines (111 loc) · 3.87 KB
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
from DSU import DSU
import numpy as np
import math
EPS = 10**(-9)
def getDistance(x1, y1, x2, y2):
return math.sqrt((x1 - x2)**2 + (y1 - y2)**2)
def getDistanceBetweenBox(box1, box2):
x1Min, y1Min, x1Max, y1Max = box1[0], box1[1], box1[2], box1[3]
x2Min, y2Min, x2Max, y2Max = box2[0], box2[1], box2[2], box2[3]
if x2Max < x1Min:
# box1 below box2
if y2Min > y1Max:
# box1 on left
return getDistance(x1Min, y1Max, x2Max, y2Min)
elif y2Max < y1Min:
# box1 on right
return getDistance(x1Min, y1Min, x2Max, y2Max)
else:
# box1 in-between
return x1Min - x2Max
elif x1Max < x2Min:
# box1 above box2
if y2Min > y1Max:
# box1 on left
return getDistance(x1Max, y1Max, x2Min, y2Min)
elif y2Max < y1Min:
# box1 on right
return getDistance(x1Max, y1Min, x2Min, y2Max)
else:
# box1 in-between
return x2Min - x1Max
else:
if y2Min >= y1Max:
# box1 on left (parallel)
return y2Min - y1Max
elif y2Max <= y1Min:
# box1 on right (parallel)
return y1Min - y2Max
else:
# overlap
return 0
def getSlope(x1, y1, x2, y2):
slope = (x2 - x1) / (y2 - y1 + EPS)
return abs(math.atan(slope)) * 180 / math.pi
def getSlopeFactor(slope):
return 50 * math.exp(-slope * slope / 150)
def getDistanceFactor(distance):
return -pow(distance, 2) / 1000 + 50
def connectivityStrength(x1, y1, x2, y2, D):
slope = getSlope(x1, y1, x2, y2)
slopeFactor = getSlopeFactor(slope)
distanceFactor = getDistanceFactor(D)
CSF = distanceFactor + slopeFactor
return CSF - 50
def lineCorrection(line, CSF):
correction = []
line = sorted(line, key=lambda x: (x[0][1] + x[0][3]) / 2)
for l in line:
maxCSF, ind = 0, -1
for i in range(len(correction)):
if CSF[correction[i][-1][1]][l[1]] - EPS > maxCSF:
maxCSF = CSF[correction[i][-1][1]][l[1]]
ind = i
if ind == -1:
correction.append([l])
else:
correction[ind].append(l)
return correction
def arrange(contours, centroids):
n = len(contours)
C = np.zeros([n, n])
CSF = np.zeros([n, n])
# CSF[i, j] shows the connectivity strength between the connected components i and j
V = sorted([(contours[i], i) for i in range(len(contours))],
key=lambda x: getDistance(0, 0, centroids[x[1]][0], centroids[x[1]][1]))
dsu = DSU(len(V))
for i in range(n):
for j in range(n):
C[i][j] = getDistanceBetweenBox(contours[i], contours[j])
CSF[i][j] = connectivityStrength(
centroids[i][0], centroids[i][1], centroids[j][0], centroids[j][1], C[i][j])
for _ in range(len(V)):
i = V[_][1]
maxCSF, j = 0, -1
for temp_ind in range(max(_ - 40, 0), min(_ + 40, n)):
ind = V[temp_ind][1]
# skip the ind_th box if it lies on the left side of i_th box
if contours[ind][3] < contours[i][3]:
continue
if CSF[i][ind] > maxCSF and ind != i:
maxCSF = CSF[i][ind]
j = ind
if j != -1:
dsu.union(j, i)
lines = [[] for _ in range(dsu.distinctParents())]
indexDictionary = {}
curr = 0
for _ in range(len(V)):
i = V[_][1]
root = dsu.find(i)
if root in indexDictionary:
index_of_root = indexDictionary[root]
else:
index_of_root = indexDictionary[root] = curr
curr += 1
lines[index_of_root].append(V[_])
correctedLines = []
for line in lines:
for lines in lineCorrection(line, CSF):
correctedLines.append(lines)
return correctedLines