19
19
20
20
class LeaderDetector :
21
21
image_type = {"Mask" , "Flow" , "RGB1" , "RGB2" , "Edge" , "RGB_Stats" , "Mask_Stats" , "Edge_debug" }
22
+
23
+ _width = 0
24
+ _height = 0
25
+
26
+ _x_grid = None
27
+ _y_grid = None
28
+
29
+ @staticmethod
30
+ def _init_grid_ (in_im ):
31
+ """ INitialize width, height, xgrid, etc so we don't have to keep re-making it
32
+ :param in_im: Input image
33
+ """
34
+ if LeaderDetector ._width == in_im .shape [1 ] and LeaderDetector ._height == in_im .shape [0 ]:
35
+ return
36
+ LeaderDetector ._width = in_im .shape [1 ]
37
+ LeaderDetector ._height = in_im .shape [0 ]
38
+
39
+ LeaderDetector ._x_grid , LeaderDetector ._y_grid = np .meshgrid (np .linspace (0.5 , LeaderDetector ._width - 0.5 , LeaderDetector ._width ), np .linspace (0.5 , LeaderDetector ._height - 0.5 , LeaderDetector ._height ))
40
+
22
41
def __init__ (self , path , image_name , b_output_debug = True , b_recalc = False ):
23
42
""" Read in the image, mask image, flow image, 2 rgb images
24
43
@param path: Directory where files are located
@@ -32,7 +51,7 @@ def __init__(self, path, image_name, b_output_debug=True, b_recalc=False):
32
51
# Read in all images that have name_ and are not debugging images
33
52
self .images = self .read_images (path , image_name )
34
53
# Split the mask into connected components, each of which might be a vertical leader
35
- self .vertical_leader_masks = self .split_mask (self .images ["Mask" ], b_debug = b_output_debug )
54
+ self .vertical_leader_masks = self .split_mask (self .images ["Mask" ], b_one_mask = True , b_debug = b_output_debug )
36
55
self .vertical_leader_stats = []
37
56
self .vertical_leader_quads = []
38
57
@@ -85,7 +104,7 @@ def __init__(self, path, image_name, b_output_debug=True, b_recalc=False):
85
104
pass
86
105
87
106
cv2 .imwrite (self .path_debug + image_name + "_" + f"{ i } _mask_points.png" , self .images ["Mask_Stats" ])
88
- cv2 .imwrite (self .path_debug + image_name + "_" + "rgb_points.png" , self .images ["RGB_Stats" ])
107
+ # cv2.imwrite(self.path_debug + image_name + "_" + "rgb_points.png", self.images["RGB_Stats"])
89
108
90
109
# Fit a quad to each vertical leader
91
110
print ("Fitting quads" )
@@ -164,16 +183,18 @@ def read_images(self, path, image_name):
164
183
165
184
return images
166
185
167
- def split_mask (self , in_im_mask , b_debug = False ):
186
+ def split_mask (self , in_im_mask , b_one_mask = True , b_debug = False ):
168
187
"""Split the mask image up into connected components, discarding anything really small
169
188
@param in_im_mask - the mask image
170
189
@param b_debug - print out mask labeled image
171
- @return a list of boolean indices for each componet """
190
+ @return a list of boolean indices for each component """
172
191
output = cv2 .connectedComponentsWithStats (in_im_mask )
173
192
labels = output [1 ]
174
193
stats = output [2 ]
175
194
176
195
ret_masks = []
196
+ i_widest = 0
197
+ i_area = 0
177
198
for i , stat in enumerate (stats ):
178
199
if np .sum (in_im_mask [labels == i ]) == 0 :
179
200
continue
@@ -182,11 +203,20 @@ def split_mask(self, in_im_mask, b_debug=False):
182
203
continue
183
204
if stat [cv2 .CC_STAT_HEIGHT ] < 0.5 * in_im_mask .shape [1 ]:
184
205
continue
206
+ if i_area < stat [cv2 .CC_STAT_AREA ]:
207
+ i_widest = len (ret_masks )
208
+ i_area = stat [cv2 .CC_STAT_AREA ]
185
209
ret_masks .append (labels == i )
186
210
187
211
if b_debug :
188
212
labels = 128 + labels * (120 // output [0 ])
189
213
cv2 .imwrite (self .path_debug + self .name + "_" + "labels.png" , labels )
214
+
215
+ try :
216
+ if b_one_mask :
217
+ return [ret_masks [i_widest ]]
218
+ except :
219
+ pass
190
220
return ret_masks
191
221
192
222
def stats_image (self , in_im , pixs_in_mask ):
@@ -195,13 +225,10 @@ def stats_image(self, in_im, pixs_in_mask):
195
225
@param im image
196
226
@returns stats as a dictionary of values"""
197
227
198
- width = in_im .shape [1 ]
199
- height = in_im .shape [0 ]
200
-
201
- x_grid , y_grid = np .meshgrid (np .linspace (0.5 , width - 0.5 , width ), np .linspace (0.5 , height - 0.5 , height ))
228
+ LeaderDetector ._init_grid_ (in_im )
202
229
203
- xs = x_grid [pixs_in_mask ]
204
- ys = y_grid [pixs_in_mask ]
230
+ xs = LeaderDetector . _x_grid [pixs_in_mask ]
231
+ ys = LeaderDetector . _y_grid [pixs_in_mask ]
205
232
206
233
stats = {}
207
234
stats ["x_min" ] = np .min (xs )
@@ -216,14 +243,14 @@ def stats_image(self, in_im, pixs_in_mask):
216
243
if stats ["x_span" ] > stats ["y_span" ]:
217
244
stats ["Direction" ] = "left_right"
218
245
stats ["Length" ] = stats ["x_span" ]
219
- for r in range (0 , width ):
246
+ for r in range (0 , LeaderDetector . _width ):
220
247
if sum (pixs_in_mask [:, r ]) > 0 :
221
248
avg_width += sum (pixs_in_mask [:, r ] > 0 )
222
249
count_width += 1
223
250
else :
224
251
stats ["Direction" ] = "up_down"
225
252
stats ["Length" ] = stats ["y_span" ]
226
- for c in range (0 , height ):
253
+ for c in range (0 , LeaderDetector . _height ):
227
254
if sum (pixs_in_mask [c , :]) > 0 :
228
255
avg_width += sum (pixs_in_mask [c , :] > 0 )
229
256
count_width += 1
@@ -258,10 +285,22 @@ def fit_quad(self, im_mask, pts, b_output_debug=True, quad_name=0):
258
285
@returns fitted quad"""
259
286
260
287
# Fit a quad to the trunk
261
- quad = Quad (pts ['lower_left' ], pts ['upper_right' ], 0.5 * pts ['width' ])
288
+ pt_lower_left = pts ['center' ]
289
+ vec_len = pts ["Length" ] * 0.4
290
+ while pt_lower_left [0 ] > 2 + pts ['x_min' ] and pt_lower_left [1 ] > 2 + pts ['y_min' ]:
291
+ pt_lower_left = pts ["center" ] - pts ["EigenVector" ] * vec_len
292
+ vec_len = vec_len * 1.1
293
+
294
+ pt_upper_right = pts ['center' ]
295
+ vec_len = pts ["Length" ] * 0.4
296
+ while pt_upper_right [0 ] < - 2 + pts ['x_max' ] and pt_upper_right [1 ] < - 2 + pts ['y_max' ]:
297
+ pt_upper_right = pts ["center" ] + pts ["EigenVector" ] * vec_len
298
+ vec_len = vec_len * 1.1
299
+
300
+ quad = Quad (pt_lower_left , pt_upper_right , 0.5 * pts ['width' ])
262
301
263
302
# Current parameters for the vertical leader
264
- params = {"step_size" : int (quad .radius_2d * 1.5 ), "width_mask" : 1.4 , "width" : 0.3 }
303
+ params = {"step_size" : int (quad .radius_2d * 1.5 ), "width_mask" : 1.4 , "width" : 0.25 }
265
304
266
305
# Iteratively move the quad to the center of the mask
267
306
for i in range (0 , 5 ):
0 commit comments