-
Notifications
You must be signed in to change notification settings - Fork 0
/
ReflectorPipeline.py
129 lines (103 loc) · 4.69 KB
/
ReflectorPipeline.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
import cv2
class ReflectorPipeline:
"""
An OpenCV pipeline generated by GRIP.
"""
def __init__(self):
"""initializes all values to presets or None if need to be set
"""
self.__resize_image_width = 320.0
self.__resize_image_height = 240.0
self.__resize_image_interpolation = cv2.INTER_CUBIC
self.resize_image_output = None
self.__hsv_threshold_input = self.resize_image_output
# HSV Values:
self.__hsv_threshold_hue = [43.70503597122302, 83.03030303030303]
self.__hsv_threshold_saturation = [64.2086330935252, 255.0]
self.__hsv_threshold_value = [128.41726618705036, 255.0]
self.hsv_threshold_output = None
self.__find_contours_input = self.hsv_threshold_output
self.find_contours_output = None
self.__filter_contours_contours = self.find_contours_output
self.__filter_contours_min_area = 15.0
def process(self, source0):
"""
Runs the pipeline and sets all outputs to new values.
"""
# Step Resize_Image0:
self.__resize_image_input = source0
(self.resize_image_output) = self.__resize_image(self.__resize_image_input, self.__resize_image_width, self.__resize_image_height, self.__resize_image_interpolation)
# Step HSV_Threshold0:
self.__hsv_threshold_input = self.resize_image_output
(self.hsv_threshold_output) = self.__hsv_threshold(self.__hsv_threshold_input, self.__hsv_threshold_hue, self.__hsv_threshold_saturation, self.__hsv_threshold_value)
# Step Find_Contours0:
self.__find_contours_input = self.hsv_threshold_output
(self.find_contours_output) = self.__find_contours(self.__find_contours_input)
# Step Filter_Contours0:
self.__filter_contours_contours = self.find_contours_output
return self.__filter_contours(self.__filter_contours_contours, self.__filter_contours_min_area)
@staticmethod
def __resize_image(input, width, height, interpolation):
"""Scales and image to an exact size.
Args:
input: A numpy.ndarray.
width: The desired width in pixels.
height: The desired height in pixels.
interpolation: Opencv enum for the type fo interpolation.
Returns:
A numpy.ndarray of the new size.
"""
return cv2.resize(input, ((int)(width), (int)(height)), 0, 0, interpolation)
@staticmethod
def __hsv_threshold(input, hue, sat, val):
"""Segment an image based on hue, saturation, and value ranges.
Args:
input: A BGR numpy.ndarray.
hue: A list of two numbers the are the min and max hue.
sat: A list of two numbers the are the min and max saturation.
val: A list of two numbers the are the min and max value.
Returns:
A black and white numpy.ndarray.
"""
out = cv2.cvtColor(input, cv2.COLOR_BGR2HSV)
return cv2.inRange(out, (hue[0], sat[0], val[0]), (hue[1], sat[1], val[1]))
@staticmethod
def __find_contours(input):
"""Sets the values of pixels in a binary image to their distance to the nearest black pixel.
Args:
input: A numpy.ndarray.
Return:
A list of numpy.ndarray where each one represents a contour.
"""
im2, contours, hierarchy = cv2.findContours(input, mode=cv2.RETR_LIST, method=cv2.CHAIN_APPROX_SIMPLE)
return contours
@staticmethod
def __filter_contours(input_contours, min_area):
"""Filters out contours that do not meet certain criteria.
Args:
input_contours: Contours as a list of numpy.ndarray.
min_area: The minimum area of a contour that will be kept.
Returns:
Contours as a list of numpy.ndarray.
"""
output = []
for contour in input_contours:
area = cv2.contourArea(contour)
if (area < min_area):
continue
output.append(contour)
output.sort(key=lambda contour: cv2.contourArea(contour))
return output[len(output) - 2::]
# we might want to use this function
def reflector_filter(self, rotated_contour):
rotated_contour.sort(key=lambda cont: cv2.minAreaRect(cont)[0][0])
results = []
# find reflectors by pairs - each pair has one positive and one negatively angled reflector
for i in range(0, len(rotated_contour) - 1):
left = rotated_contour[i]
right = rotated_contour[i + 1]
left_angle = cv2.minAreaRect(left)[2]
right_angle = cv2.minAreaRect(right)[2]
if left_angle > 0 and right_angle < 0:
results.append((left, right))
return results