Skip to content

Commit 3de515a

Browse files
annimesh2809timholy
authored andcommitted
Added Hough Line Transform (#28)
1 parent ccdaf2b commit 3de515a

File tree

4 files changed

+133
-1
lines changed

4 files changed

+133
-1
lines changed

src/ImageFeatures.jl

+5-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ include("brief.jl")
1212
include("orb.jl")
1313
include("freak.jl")
1414
include("brisk.jl")
15+
include("houghtransform.jl")
1516

1617
export Keypoint, Keypoints, Feature, Features, Params, BRIEF, ORB, FREAK, BRISK
1718

@@ -57,5 +58,8 @@ export
5758
random_coarse,
5859
gaussian,
5960
gaussian_local,
60-
center_sample
61+
center_sample,
62+
63+
#Lines and Ellipses
64+
hough_transform_standard
6165
end

src/houghtransform.jl

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
2+
"""
3+
```
4+
lines = hough_transform_standard(image, ρ, θ, threshold, linesMax)
5+
```
6+
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
9+
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+
13+
The lines are generated by applying hough transform on the image.
14+
15+
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
21+
22+
"""
23+
24+
function hough_transform_standard{T<:Union{Bool,Gray{Bool}}}(
25+
img::AbstractArray{T,2},
26+
ρ::Number, θ::Range,
27+
threshold::Integer, linesMax::Integer)
28+
29+
30+
#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)
33+
for val in CartesianRange(size(accumulator_matrix))
34+
if accumulator_matrix[val] > threshold &&
35+
accumulator_matrix[val] > accumulator_matrix[val[1],val[2] - 1] &&
36+
accumulator_matrix[val] >= accumulator_matrix[val[1],val[2] + 1] &&
37+
accumulator_matrix[val] > accumulator_matrix[val[1] - 1,val[2]] &&
38+
accumulator_matrix[val] >= accumulator_matrix[val[1] + 1,val[2]]
39+
push!(validLines,val)
40+
end
41+
end
42+
validLines
43+
end
44+
45+
ρ > 0 || error("Discrete step size must be positive")
46+
47+
height, width = size(img)
48+
ρinv = 1 / ρ
49+
numangle = length(θ)
50+
numrho = round(Integer,(2(width + height) + 1)*ρinv)
51+
52+
accumulator_matrix = zeros(Integer, numangle + 2, numrho + 2)
53+
54+
#Pre-Computed sines and cosines in tables
55+
sinθ, cosθ = sin.(θ).*ρinv, cos.(θ).*ρinv
56+
57+
#Hough Transform implementation
58+
constadd = round(Integer,(numrho -1)/2)
59+
for pix in CartesianRange(size(img))
60+
if img[pix]
61+
for i in 1:numangle
62+
dist = round(Integer, pix[1] * sinθ[i] + pix[2] * cosθ[i])
63+
dist += constadd
64+
accumulator_matrix[i + 1, dist + 1] += 1
65+
end
66+
end
67+
end
68+
69+
#Finding local maximum lines
70+
validLines = findlocalmaxima(accumulator_matrix, threshold)
71+
72+
#Sorting by value in accumulator_matrix
73+
sort!(validLines, by = (x)->accumulator_matrix[x], rev = true)
74+
75+
linesMax = min(linesMax, length(validLines))
76+
77+
lines = Vector{Tuple{Number,Number}}(0)
78+
79+
#Getting lines with Maximum value in accumulator_matrix && size(lines) < linesMax
80+
for l in 1:linesMax
81+
lrho = ((validLines[l][2]-1) - (numrho - 1)*0.5)*ρ
82+
langle = θ[validLines[l][1]-1]
83+
push!(lines,(lrho,langle))
84+
end
85+
86+
lines
87+
88+
end

test/houghtransform.jl

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using ImageFeatures
2+
3+
@testset "Hough_Transform" begin
4+
@testset "Hough Line Transform" begin
5+
6+
#For images containing a straight line parallel to axes
7+
img = zeros(Bool,10,10)
8+
for i in 1:size(img)[1]
9+
for j in 1:size(img)[2]
10+
img[i,j] = true
11+
end
12+
h = hough_transform_standard(img,1,linspace(0/2,100),9,2)
13+
@test length(h) == 1
14+
@test h[1][1] == i
15+
for j in 1:size(img)[2]
16+
img[i,j] = false
17+
end
18+
end
19+
20+
#For images with diagonal line
21+
img = diagm([true, true ,true])
22+
h = hough_transform_standard(img,1,linspace(0,π,100),2,3)
23+
@test length(h) == 1
24+
@test h[1][1] == 0
25+
26+
#For a square image
27+
img = zeros(Bool,10,10)
28+
for i in 1:10
29+
img[2,i] = img[i,2] = img[7,i] = img[i,9] = true
30+
end
31+
h = hough_transform_standard(img,1,linspace(0/2,100),9,10)
32+
@test length(h) == 4
33+
r = [h[i][1] for i in CartesianRange(size(h))]
34+
@test all(r .== [2,2,7,9])
35+
theta = [h[i][2] for i in CartesianRange(size(h))]
36+
er = sum(map((t1,t2) -> abs(t1-t2), theta, [0, π/2, π/2, 0]))
37+
@test er <= 0.1
38+
end
39+
end

test/runtests.jl

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ include("corner.jl")
5353
include("orb.jl")
5454
include("freak.jl")
5555
include("brisk.jl")
56+
include("houghtransform.jl")
5657

5758
isinteractive() || FactCheck.exitstatus()
5859

0 commit comments

Comments
 (0)