Skip to content

Commit 6638323

Browse files
committed
added comments and reference
1 parent c02b225 commit 6638323

File tree

1 file changed

+69
-4
lines changed

1 file changed

+69
-4
lines changed

src/houghtransform.jl

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,54 @@ threshold::Integer, linesMax::Integer) where T<:Union{Bool,Gray{Bool}}
103103

104104
end
105105

106+
"""
107+
```
108+
lines = hough_line_probabilistic(image, ρ, θ, threshold, lineLength, lineGap, linesMax)
109+
```
110+
111+
Returns lines :
112+
vector of lines identified, lines in format ((r0, c0), (r1, c1))
113+
indicating line start and end.
114+
115+
The lines are generated by applying hough transform on the image.
116+
117+
Parameters:
118+
- `image` = Image to be transformed (eltype should be `Bool`)
119+
- `ρ` = Discrete step size for perpendicular length of line
120+
- `θ` = List of angles for which the transform is computed
121+
- `threshold` = Accumulator threshold for line detection
122+
- 'lineLength' = minimum length of a good_line
123+
- 'lineGap' = minimum gap between two different lines.
124+
- `linesMax` = Maximum no of lines to return
125+
126+
# Example
127+
```julia
128+
julia> img = load("line.jpg");
129+
130+
julia> img_edges = canny(img, (Percentile(0.99), Percentile(0.97)), 1);
131+
132+
julia> lines = hough_line_probabilistic(img_edges, 1, linspace(0,π,180),30,30,10,10)
133+
10-element Array{NTuple{4,Int64},1}:
134+
(186, 283, 20, 283)
135+
(186, 20, 20, 20)
136+
(200, 218, 200, 291)
137+
(20, 68, 20, 180)
138+
(186, 85, 186, 197)
139+
(48, 59, 69, 199)
140+
(50, 58, 65, 160)
141+
(200, 35, 200, 147)
142+
(20, 186, 20, 282)
143+
(155, 138, 75, 198)
144+
```
145+
May use LineSegment of ImageDraw to draw lines.
146+
147+
References
148+
----------
149+
.. [1] C. Galamhos, J. Matas and J. Kittler, "Progressive probabilistic
150+
Hough transform for line detection", in IEEE Computer Society
151+
Conference on Computer Vision and Pattern Recognition, 1999.
152+
"""
153+
106154
function hough_line_probabilistic(
107155
img::AbstractArray{T,2},
108156
ρ::Real, θ::Range,
@@ -123,6 +171,7 @@ threshold::Integer, lineLength::Integer, lineGap::Integer, linesMax::Integer) wh
123171
nzloc = Vector{Tuple{Int64,Int64}}(0)
124172
lines = Vector{Tuple{Int64, Int64, Int64, Int64}}(0)
125173

174+
#collect non-zero image points
126175
for pix in CartesianRange(size(img))
127176
pix1 = (pix[1], pix[2])
128177
if(img[pix])
@@ -134,9 +183,12 @@ threshold::Integer, lineLength::Integer, lineGap::Integer, linesMax::Integer) wh
134183
end
135184

136185
count_ = size(nzloc)[1]+1
186+
187+
# stage 2. process all the points in random order
137188
while(count_>1)
138189
count_-=1
139190
good_line = false
191+
# choose random point out of the remaining ones
140192
idx = rand(1:count_)
141193
max_val = threshold-1
142194
max_n = 1
@@ -147,12 +199,14 @@ threshold::Integer, lineLength::Integer, lineGap::Integer, linesMax::Integer) wh
147199
x0, y0, dx0, dy0, xflag = 0, 0, 0, 0, 0
148200
const shift = 16
149201

202+
# "remove" it by overriding it with the last element
150203
nzloc[idx] = nzloc[count_]
151204

152205
if(!(mask[point[1], point[2]]))
153206
continue
154207
end
155208

209+
# update accumulator, find the most probable line
156210
for n in 0:numangle-1
157211
dist = round(Int, point[2]*cosθ[n+1] + point[1]*sinθ[n+1])
158212
dist += constadd
@@ -165,10 +219,12 @@ threshold::Integer, lineLength::Integer, lineGap::Integer, linesMax::Integer) wh
165219
end
166220
end
167221

222+
# if it is too "weak" candidate, continue with another point
168223
if(max_val < threshold)
169224
continue
170225
end
171226

227+
# from the current point walk in each direction along the found line
172228
a = -sinθ[max_n]
173229
b = cosθ[max_n]
174230
x0 = j
@@ -187,6 +243,7 @@ threshold::Integer, lineLength::Integer, lineGap::Integer, linesMax::Integer) wh
187243
x0 = (x0 << shift) + (1 << (shift-1));
188244
end
189245

246+
# pass 1: walk the line, merging lines less than specified gap length
190247
for k = 1:2
191248
gap = 0
192249
x = x0
@@ -209,26 +266,30 @@ threshold::Integer, lineLength::Integer, lineGap::Integer, linesMax::Integer) wh
209266
j1 = x>>shift
210267
i1 = y
211268
end
212-
269+
270+
# check when line exits image boundary
213271
if( j1 < 0 || j1 >= w || i1 < 0 || i1 >= h )
214272
break;
215273
end
216274
gap+=1
275+
276+
# if non-zero point found, continue the line
217277
if(mask[i1+1, j1+1])
218278
gap = 0
219279
line_end[k][1] = i1+1
220280
line_end[k][2] = j1+1
221-
281+
# if gap to this point was too large, end the line
222282
elseif(gap > lineGap)
223283
break
224284
end
225285
x = Int64(x+dx)
226286
y = Int64(y+dy)
227287
end
228288
end
229-
289+
# confirm line length is sufficient
230290
good_line = abs(line_end[2][1] - line_end[1][1]) >= lineLength || abs(line_end[2][2] - line_end[1][2]) >= lineLength
231291

292+
# pass 2: walk the line again and reset accumulator and mask
232293
for k = 1:2
233294
x = x0
234295
y = y0
@@ -240,6 +301,7 @@ threshold::Integer, lineLength::Integer, lineGap::Integer, linesMax::Integer) wh
240301
dy = -dy
241302
end
242303

304+
# walk along the line using fixed-point arithmetics,
243305
while(true)
244306
i1, j1 = 0,0
245307

@@ -250,6 +312,8 @@ threshold::Integer, lineLength::Integer, lineGap::Integer, linesMax::Integer) wh
250312
j1 = x >>shift
251313
i1 = y
252314
end
315+
316+
# if non-zero point found, continue the line
253317
if(mask[i1+1, j1+1])
254318
if(good_line)
255319
for n = 0:numangle-1
@@ -260,7 +324,7 @@ threshold::Integer, lineLength::Integer, lineGap::Integer, linesMax::Integer) wh
260324
end
261325
end
262326
end
263-
327+
# exit when the point is the line end
264328
if((i1+1) == line_end[k][1] && (j1+1) == line_end[k][2])
265329
break
266330
end
@@ -269,6 +333,7 @@ threshold::Integer, lineLength::Integer, lineGap::Integer, linesMax::Integer) wh
269333
end
270334

271335
end
336+
# add line to the result
272337
if(good_line)
273338
push!(lines, (line_end[1][1], line_end[1][2], line_end[2][1], line_end[2][2]))
274339

0 commit comments

Comments
 (0)