@@ -156,7 +156,7 @@ img::AbstractArray{T,2},
156156ρ:: Real , θ:: Range ,
157157threshold:: Integer , lineLength:: Integer , lineGap:: Integer , linesMax:: Integer ) where T<: Union{Bool,Gray{Bool}}
158158
159- ρ > 0 || error ( " Discrete step size must be positive" )
159+ ρ > 0 || throw ( ArgumentError ( " Discrete step size must be positive" ) )
160160 indsy, indsx = indices (img)
161161 ρinv = 1 / ρ
162162 numangle = length (θ)
@@ -165,48 +165,30 @@ threshold::Integer, lineLength::Integer, lineGap::Integer, linesMax::Integer) wh
165165 accumulator_matrix = zeros (Int, numangle + 2 , numrho + 2 )
166166 h, w = size (img)
167167 mask = zeros (Bool, h, w)
168-
168+ x0, y0 = 0 , 0
169169 # Pre-Computed sines and cosines in tables
170170 sinθ, cosθ = sin .(θ).* ρinv, cos .(θ).* ρinv
171171 nzloc = Vector {Tuple{Int64,Int64}} (0 )
172172 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
182185 end
183- end
186+ end
184187
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)
194190 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
210192 for n in 0 : numangle- 1
211193 dist = round (Int, point[2 ]* cosθ[n+ 1 ] + point[1 ]* sinθ[n+ 1 ])
212194 dist += constadd
@@ -218,32 +200,12 @@ threshold::Integer, lineLength::Integer, lineGap::Integer, linesMax::Integer) wh
218200 max_n = n+ 1
219201 end
220202 end
203+ return max_n, max_val
204+ end
221205
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 ]]
247209 for k = 1 : 2
248210 gap = 0
249211 x = x0
@@ -286,10 +248,11 @@ threshold::Integer, lineLength::Integer, lineGap::Integer, linesMax::Integer) wh
286248 y = Int64 (y+ dy)
287249 end
288250 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
291253
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)
293256 for k = 1 : 2
294257 x = x0
295258 y = y0
@@ -331,8 +294,70 @@ threshold::Integer, lineLength::Integer, lineGap::Integer, linesMax::Integer) wh
331294 x = Int64 (x+ dx)
332295 y = Int64 (y+ dy)
333296 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)
334360
335- end
336361 # add line to the result
337362 if (good_line)
338363 push! (lines, (line_end[1 ][1 ], line_end[1 ][2 ], line_end[2 ][1 ], line_end[2 ][2 ]))
0 commit comments