@@ -156,7 +156,7 @@ img::AbstractArray{T,2},
156
156
ρ:: Real , θ:: Range ,
157
157
threshold:: Integer , lineLength:: Integer , lineGap:: Integer , linesMax:: Integer ) where T<: Union{Bool,Gray{Bool}}
158
158
159
- ρ > 0 || error ( " Discrete step size must be positive" )
159
+ ρ > 0 || throw ( ArgumentError ( " Discrete step size must be positive" ) )
160
160
indsy, indsx = indices (img)
161
161
ρinv = 1 / ρ
162
162
numangle = length (θ)
@@ -165,48 +165,30 @@ threshold::Integer, lineLength::Integer, lineGap::Integer, linesMax::Integer) wh
165
165
accumulator_matrix = zeros (Int, numangle + 2 , numrho + 2 )
166
166
h, w = size (img)
167
167
mask = zeros (Bool, h, w)
168
-
168
+ x0, y0 = 0 , 0
169
169
# Pre-Computed sines and cosines in tables
170
170
sinθ, cosθ = sin .(θ).* ρinv, cos .(θ).* ρinv
171
171
nzloc = Vector {Tuple{Int64,Int64}} (0 )
172
172
lines = Vector {Tuple{Int64, Int64, Int64, Int64}} (0 )
173
-
174
- # collect non-zero image points
175
- for pix in CartesianRange (size (img))
176
- pix1 = (pix[1 ], pix[2 ])
177
- if (img[pix])
178
- push! (nzloc, pix1)
179
- mask[pix] = true
180
- else
181
- mask[pix] = false
173
+ const shift = 16
174
+
175
+ # function to mark and collect all non zero points
176
+ function collect_points ()
177
+ for pix in CartesianRange (size (img))
178
+ pix1 = (pix[1 ], pix[2 ])
179
+ if (img[pix])
180
+ push! (nzloc, pix1)
181
+ mask[pix] = true
182
+ else
183
+ mask[pix] = false
184
+ end
182
185
end
183
- end
186
+ end
184
187
185
- count_ = size (nzloc)[1 ]+ 1
186
-
187
- # stage 2. process all the points in random order
188
- while (count_> 1 )
189
- count_-= 1
190
- good_line = false
191
- # choose random point out of the remaining ones
192
- idx = rand (1 : count_)
193
- max_val = threshold- 1
188
+ # function to update the accumulator matrix for every point selected
189
+ function update_accumulator (point)
194
190
max_n = 1
195
- point = nzloc[idx]
196
- line_end = [[0 ,0 ],[0 ,0 ]]
197
- i = point[1 ]- 1
198
- j = point[2 ]- 1
199
- x0, y0, dx0, dy0, xflag = 0 , 0 , 0 , 0 , 0
200
- const shift = 16
201
-
202
- # "remove" it by overriding it with the last element
203
- nzloc[idx] = nzloc[count_]
204
-
205
- if (! (mask[point[1 ], point[2 ]]))
206
- continue
207
- end
208
-
209
- # update accumulator, find the most probable line
191
+ max_val = threshold- 1
210
192
for n in 0 : numangle- 1
211
193
dist = round (Int, point[2 ]* cosθ[n+ 1 ] + point[1 ]* sinθ[n+ 1 ])
212
194
dist += constadd
@@ -218,32 +200,12 @@ threshold::Integer, lineLength::Integer, lineGap::Integer, linesMax::Integer) wh
218
200
max_n = n+ 1
219
201
end
220
202
end
203
+ return max_n, max_val
204
+ end
221
205
222
- # if it is too "weak" candidate, continue with another point
223
- if (max_val < threshold)
224
- continue
225
- end
226
-
227
- # from the current point walk in each direction along the found line
228
- a = - sinθ[max_n]
229
- b = cosθ[max_n]
230
- x0 = j
231
- y0 = i
232
- good_line = false
233
-
234
- if (abs (a) > abs (b))
235
- xflag = 1
236
- dx0 = a > 0 ? 1 : - 1
237
- dy0 = round (b* (1 << shift)/ abs (a))
238
- y0 = (y0 << shift) + (1 << (shift- 1 ))
239
- else
240
- xflag = 0
241
- dy0 = b > 0 ? 1 : - 1
242
- dx0 = round ( a* (1 << shift)/ abs (b) );
243
- x0 = (x0 << shift) + (1 << (shift- 1 ));
244
- end
245
-
246
- # pass 1: walk the line, merging lines less than specified gap length
206
+ # function to detect the line segment after merging lines within lineGap
207
+ function pass_1 (xflag, x0, y0, dx0, dy0)
208
+ line_end = [[0 ,0 ],[0 ,0 ]]
247
209
for k = 1 : 2
248
210
gap = 0
249
211
x = x0
@@ -286,10 +248,11 @@ threshold::Integer, lineLength::Integer, lineGap::Integer, linesMax::Integer) wh
286
248
y = Int64 (y+ dy)
287
249
end
288
250
end
289
- # confirm line length is sufficient
290
- good_line = abs (line_end[ 2 ][ 1 ] - line_end[ 1 ][ 1 ]) >= lineLength || abs (line_end[ 2 ][ 2 ] - line_end[ 1 ][ 2 ]) >= lineLength
251
+ return line_end
252
+ end
291
253
292
- # pass 2: walk the line again and reset accumulator and mask
254
+ # function to reset the mask and accumulator_matrix
255
+ function pass_2 (xflag, x0, y0, dx0, dy0, good_line, line_end)
293
256
for k = 1 : 2
294
257
x = x0
295
258
y = y0
@@ -331,8 +294,70 @@ threshold::Integer, lineLength::Integer, lineGap::Integer, linesMax::Integer) wh
331
294
x = Int64 (x+ dx)
332
295
y = Int64 (y+ dy)
333
296
end
297
+ end
298
+ end
299
+
300
+ # collect non-zero image points
301
+ collect_points ()
302
+
303
+ count_ = size (nzloc)[1 ]+ 1
304
+
305
+ # stage 2. process all the points in random order
306
+ while (count_> 1 )
307
+ count_-= 1
308
+ good_line = false
309
+ # choose random point out of the remaining ones
310
+ idx = rand (1 : count_)
311
+ max_n = 1
312
+ point = nzloc[idx]
313
+ i = point[1 ]- 1
314
+ j = point[2 ]- 1
315
+ x0, y0, dx0, dy0, xflag = 0 , 0 , 0 , 0 , 0
316
+ max_n = 1
317
+
318
+ # "remove" it by overriding it with the last element
319
+ nzloc[idx] = nzloc[count_]
320
+
321
+ if (! (mask[point[1 ], point[2 ]]))
322
+ continue
323
+ end
324
+
325
+ # update accumulator, find the most probable line
326
+ max_n, max_val = update_accumulator (point)
327
+
328
+ # if it is too "weak" candidate, continue with another point
329
+ if (max_val < threshold)
330
+ continue
331
+ end
332
+
333
+ # from the current point walk in each direction along the found line
334
+ a = - sinθ[max_n]
335
+ b = cosθ[max_n]
336
+ x0 = j
337
+ y0 = i
338
+ good_line = false
339
+
340
+ if (abs (a) > abs (b))
341
+ xflag = 1
342
+ dx0 = a > 0 ? 1 : - 1
343
+ dy0 = round (b* (1 << shift)/ abs (a))
344
+ y0 = (y0 << shift) + (1 << (shift- 1 ))
345
+ else
346
+ xflag = 0
347
+ dy0 = b > 0 ? 1 : - 1
348
+ dx0 = round ( a* (1 << shift)/ abs (b) );
349
+ x0 = (x0 << shift) + (1 << (shift- 1 ));
350
+ end
351
+
352
+ # pass 1: walk the line, merging lines less than specified gap length
353
+ line_end = pass_1 (xflag, x0, y0, dx0, dy0)
354
+
355
+ # confirm line length is sufficient
356
+ good_line = abs (line_end[2 ][1 ] - line_end[1 ][1 ]) >= lineLength || abs (line_end[2 ][2 ] - line_end[1 ][2 ]) >= lineLength
357
+
358
+ # pass 2: walk the line again and reset accumulator and mask
359
+ pass_2 (xflag, x0, y0, dx0, dy0, good_line, line_end)
334
360
335
- end
336
361
# add line to the result
337
362
if (good_line)
338
363
push! (lines, (line_end[1 ][1 ], line_end[1 ][2 ], line_end[2 ][1 ], line_end[2 ][2 ]))
0 commit comments