|
1 | 1 | using Images |
| 2 | + |
2 | 3 | """ |
3 | 4 | ``` |
4 | 5 | lines = hough_transform_standard(image, ρ, θ, threshold, linesMax) |
5 | 6 | ``` |
6 | 7 |
|
7 | | -Returns an vector of tuples corresponding to the tuples of (r,t) where r and t are parameters for normal form of line: |
8 | | - x*cos(t) + y*sin(t) = r |
| 8 | +Returns a vector of tuples corresponding to the tuples of (r,t) |
| 9 | +where r and t are parameters for normal form of line: |
| 10 | + `x \* cos(t) + y \* sin(t) = r` |
9 | 11 |
|
10 | | -r = length of perpendicular from (1,1) to the line |
11 | | -t = angle between perpendicular from (1,1) to the line and x-axis |
| 12 | +- `r` = length of perpendicular from (1,1) to the line |
| 13 | +- `t` = angle between perpendicular from (1,1) to the line and x-axis |
12 | 14 |
|
13 | 15 | The lines are generated by applying hough transform on the image. |
14 | 16 |
|
15 | 17 | Parameters: |
16 | | - image = Image to be transformed (eltype should be `Bool`) |
17 | | - ρ = Discrete step size for perpendicular length of line |
18 | | - θ = List of angles for which the transform is computed |
19 | | - threshold = No of points to pass through line for considering it valid |
20 | | - linesMax = Maximum no of lines to return |
| 18 | +- `image` = Image to be transformed (eltype should be `Bool`) |
| 19 | +- `ρ` = Discrete step size for perpendicular length of line |
| 20 | +- `θ` = List of angles for which the transform is computed |
| 21 | +- `threshold` = Accumulator threshold for line detection |
| 22 | +- `linesMax` = Maximum no of lines to return |
| 23 | +
|
| 24 | +# Example |
| 25 | +```julia |
| 26 | +julia> img = load("line.jpg"); |
| 27 | +
|
| 28 | +julia> img_edges = canny(img, (Percentile(0.99), Percentile(0.97)), 1); |
21 | 29 |
|
| 30 | +julia> lines = hough_transform_standard(img_edges, 1, linspace(0,π,30), 40, 5) |
| 31 | +5-element Array{Tuple{Float64,Float64},1}: |
| 32 | + (45.0,1.73329) |
| 33 | + (1.0,1.73329) |
| 34 | + (32.0,1.73329) |
| 35 | + (209.0,0.649985) |
| 36 | + (-9.0,2.49161) |
| 37 | +``` |
22 | 38 | """ |
23 | 39 |
|
24 | 40 | function hough_transform_standard{T<:Union{Bool,Gray{Bool}}}( |
25 | 41 | img::AbstractArray{T,2}, |
26 | | - ρ::Number, θ::Range, |
| 42 | + ρ::Real, θ::Range, |
27 | 43 | threshold::Integer, linesMax::Integer) |
28 | 44 |
|
29 | 45 |
|
30 | 46 | #function to compute local maximum lines with values > threshold and return a vector containing them |
31 | | - function findlocalmaxima(accumulator_matrix::Array{Integer,2},threshold::Integer) |
32 | | - validLines = Vector{CartesianIndex}(0) |
| 47 | + function findlocalmaxima!{T<:Integer}(validLines::AbstractVector{CartesianIndex{2}}, accumulator_matrix::Array{Int,2}, threshold::T) |
33 | 48 | for val in CartesianRange(size(accumulator_matrix)) |
34 | | - if accumulator_matrix[val] > threshold && |
35 | | - accumulator_matrix[val] > accumulator_matrix[val[1],val[2] - 1] && |
| 49 | + if accumulator_matrix[val] > threshold && |
| 50 | + accumulator_matrix[val] > accumulator_matrix[val[1],val[2] - 1] && |
36 | 51 | accumulator_matrix[val] >= accumulator_matrix[val[1],val[2] + 1] && |
37 | | - accumulator_matrix[val] > accumulator_matrix[val[1] - 1,val[2]] && |
| 52 | + accumulator_matrix[val] > accumulator_matrix[val[1] - 1,val[2]] && |
38 | 53 | accumulator_matrix[val] >= accumulator_matrix[val[1] + 1,val[2]] |
39 | 54 | push!(validLines,val) |
40 | 55 | end |
41 | 56 | end |
42 | | - validLines |
43 | 57 | end |
44 | 58 |
|
45 | 59 | ρ > 0 || error("Discrete step size must be positive") |
46 | 60 |
|
47 | | - height, width = size(img) |
| 61 | + indsy, indsx = indices(img) |
48 | 62 | ρinv = 1 / ρ |
49 | 63 | numangle = length(θ) |
50 | | - numrho = round(Integer,(2(width + height) + 1)*ρinv) |
| 64 | + numrho = round(Int,(2(length(indsx) + length(indsy)) + 1)*ρinv) |
51 | 65 |
|
52 | | - accumulator_matrix = zeros(Integer, numangle + 2, numrho + 2) |
| 66 | + accumulator_matrix = zeros(Int, numangle + 2, numrho + 2) |
53 | 67 |
|
54 | 68 | #Pre-Computed sines and cosines in tables |
55 | 69 | sinθ, cosθ = sin.(θ).*ρinv, cos.(θ).*ρinv |
56 | 70 |
|
57 | 71 | #Hough Transform implementation |
58 | | - constadd = round(Integer,(numrho -1)/2) |
| 72 | + constadd = round(Int,(numrho -1)/2) |
59 | 73 | for pix in CartesianRange(size(img)) |
60 | 74 | if img[pix] |
61 | 75 | for i in 1:numangle |
62 | | - dist = round(Integer, pix[1] * sinθ[i] + pix[2] * cosθ[i]) |
| 76 | + dist = round(Int, pix[1] * sinθ[i] + pix[2] * cosθ[i]) |
63 | 77 | dist += constadd |
64 | 78 | accumulator_matrix[i + 1, dist + 1] += 1 |
65 | 79 | end |
66 | 80 | end |
67 | 81 | end |
68 | 82 |
|
69 | 83 | #Finding local maximum lines |
70 | | - validLines = findlocalmaxima(accumulator_matrix, threshold) |
| 84 | + validLines = Vector{CartesianIndex{2}}(0) |
| 85 | + findlocalmaxima!(validLines, accumulator_matrix, threshold) |
71 | 86 |
|
72 | 87 | #Sorting by value in accumulator_matrix |
73 | | - sort!(validLines, by = (x)->accumulator_matrix[x], rev = true) |
| 88 | + @noinline sort_by_votes(validLines, accumulator_matrix) = sort!(validLines, lt = (a,b)-> accumulator_matrix[a]>accumulator_matrix[b]) |
| 89 | + sort_by_votes(validLines, accumulator_matrix) |
74 | 90 |
|
75 | 91 | linesMax = min(linesMax, length(validLines)) |
76 | 92 |
|
77 | | - lines = Vector{Tuple{Number,Number}}(0) |
| 93 | + lines = Vector{Tuple{Float64,Float64}}(0) |
78 | 94 |
|
79 | 95 | #Getting lines with Maximum value in accumulator_matrix && size(lines) < linesMax |
80 | 96 | for l in 1:linesMax |
81 | | - lrho = ((validLines[l][2]-1) - (numrho - 1)*0.5)*ρ |
| 97 | + lrho = ((validLines[l][2]-1) - (numrho-1)*0.5)*ρ |
82 | 98 | langle = θ[validLines[l][1]-1] |
83 | 99 | push!(lines,(lrho,langle)) |
84 | 100 | end |
|
0 commit comments