-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcourt_line_candidate_detector.py
154 lines (107 loc) · 5.11 KB
/
court_line_candidate_detector.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
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
145
146
147
148
149
150
151
152
153
154
import numpy as np
from skimage.transform import hough_line, hough_line_peaks
from skimage.feature import canny
from skimage import img_as_ubyte, img_as_float
from scipy import stats
from line import Line
from config import HOUGH_THRESHOLD, THRESHOLD_R
# Section 3.2 Court Line Candidate Detector
class CourtLineCandidateDetector:
def __init__(self) -> None:
self.blur_canny = None
def execute(self, img, line_structure_const_and):
'''
Section 3.2: Court line candidate detector
line_structure_const_and: detected white pixels with line structure constraint.
return: a dictionary of lines
'''
# init parameters to be accessed
self.img = np.array(img)
self.line_structure_const_and = line_structure_const_and
self.height, self.width = img.shape[:2]
self.lines = {}
temp = img_as_float(self.line_structure_const_and)
self.blur_canny = canny(temp, sigma=3)
# hough line transform from skimage
tested_angles = np.linspace(-np.pi, np.pi, 360, endpoint=False)
h, theta, d = hough_line(self.blur_canny, theta=tested_angles)
thresh_hough = HOUGH_THRESHOLD * np.amax(h)
for id, (_, angle, dist) in enumerate(zip(*hough_line_peaks(h, theta, d, threshold=thresh_hough))):
(x0, y0) = dist * np.array([np.cos(angle), np.sin(angle)])
slope = np.tan(angle + np.pi/2)
# draw a line on opencv
l = Line.from_point_slope(id, (x0, y0), slope)
self.lines[id] = l
# l.draw_line_extended(img_1, (255, 0, 0))
# convert the image back to numpy array compatible for opencv
self.blur_canny = img_as_ubyte(self.blur_canny)
# parameterized every lines by its normal (normalized, start coordinate is (0, 0))
for line in self.lines.values():
line.line_parameterization()
# the set L of court line candidate pixels for each line
self.court_line_candidate_pixels = {}
dist_thresh = THRESHOLD_R
for y in range(self.height):
for x in range(self.width):
# check for zero pixels
if self.line_structure_const_and[y, x] < 127:
continue
for line in self.lines.values():
p = np.array([x, y, 1])
q = line.get_parameterized()
if abs(np.dot(q, p)) < dist_thresh:
if line.id not in self.court_line_candidate_pixels:
self.court_line_candidate_pixels[line.id] = [[], []]
# court_line_candidate_pixels[line.id].append([x, y])
self.court_line_candidate_pixels[line.id][0].append(x)
self.court_line_candidate_pixels[line.id][1].append(y)
# Apply LMedS estimator. Yet I cannot find any python implementation.
# A similar one with same % breakdown point will be "Robust Regression Using Repeated Medians".
# scipy.stats.siegelslopes implements the paper.
self.refinded_lines = {}
for key, points in self.court_line_candidate_pixels.items():
x = points[0]
y = points[1]
m, c = stats.siegelslopes(y, x)
regressed = Line.from_point_slope(id=key, p1=(0, c), m=m)
# line paramaterization for the new line
regressed.line_parameterization()
self.refinded_lines[key] = regressed
return self.refinded_lines
####################
# Get-setters
####################
def get_court_line_candidate_pixels(self):
return self.court_line_candidate_pixels
def get_refined_lines(self):
return self.refinded_lines
########################################
# Visualization Methods (intermediate processes)
########################################
def court_line_cand_pixels_imgs(self):
'''
Return a set of images representing the court line candidate pixels
that are close to each line
'''
court_line_cand_img = {}
for k in self.court_line_candidate_pixels.keys():
img_line = np.zeros((self.height, self.width))
lists = self.court_line_candidate_pixels[k]
for p in zip(lists[0], lists[1]):
img_line[p[1], p[0]] = 1
court_line_cand_img[k] = img_line
return court_line_cand_img
def regression_before_and_after_imgs(self):
'''
Return a set of images showing the before and after regression is applied
of each lines
'''
regression_ba = {}
for key in self.court_line_candidate_pixels.keys():
img_siegelslope = np.array(self.img)
self.lines_extended[key].draw_line_extended(img_siegelslope, (255, 0, 0))
self.refinded_lines[key].draw_line_extended(img_siegelslope, (0, 0, 255))
# draw the normal
self.lines_extended[key].draw_normal(img_siegelslope, (255, 127, 127), length=80, thickness=2)
regression_ba[key] = img_siegelslope
return regression_ba