-
Notifications
You must be signed in to change notification settings - Fork 143
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added Hough Line Transform #601
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
|
||
|
||
function is_binary_image{T}(img::AbstractArray{T,2}) | ||
for pix in CartesianRange(size(img)) | ||
if img[pix] != 0.0 && img[pix] != 1.0 | ||
return false | ||
end | ||
end | ||
return true | ||
end | ||
|
||
""" | ||
lines = hough_transform_standard(image, rho, theta, min_theta, max_theta, threshold, linesMax) | ||
|
||
Returns an array of tuples corresponding to the tuples of (r,t) where r and t are parameters for normal form of line: | ||
x*cos(t) + y*sin(t) = r | ||
|
||
r = length of perpendicular from (0,0) to the line | ||
t = angle between perpendicular from (0,0) to the line and axis | ||
|
||
The lines are generated by applying hough transform on the image. | ||
|
||
Parameters: | ||
image = image to apply hough transform on | ||
rho = discrete steps for radius | ||
theta = discrete steps for theta | ||
min_theta = minimum theta of lines | ||
max_theta = maximum theta of lines | ||
threshold = no of points to pass through line for considering it valid | ||
linesMax = maximum no of lines to return | ||
|
||
""" | ||
|
||
function hough_transform_standard{T}( | ||
img::AbstractArray{T,2}, | ||
rho::Float64, theta::Float64, | ||
min_theta::Float64, max_theta::Float64, | ||
threshold::Int64, linesMax::Int64) | ||
|
||
theta > 0 || error("theta threshold must be positive") | ||
rho > 0 || error("radius threshold must be positive") | ||
min_theta < max_theta || error("max_theta must be greater than min_theta") | ||
|
||
if ! is_binary_image(img) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Better to just require an |
||
img = canny(img) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This breaks orthogonality; what if someone wants a different algorithm than Hmm, I hadn't noticed that |
||
end | ||
|
||
width::Int64 = size(img)[2] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to declare types like this. |
||
height::Int64 = size(img)[1] | ||
irho::Float64 = 1 / rho; | ||
numangle::Int64 = round((max_theta - min_theta)/theta) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
numrho::Int64 = round(((width + height)*2 + 1)/rho) | ||
|
||
accumulator_matrix = Array{Int64}(numangle + 2, numrho + 2) | ||
fill!(accumulator_matrix, 0) | ||
|
||
#Pre-Computed sines and cosines in tables | ||
tabsin = Array{Float64}(numangle) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even better, |
||
tabcos = Array{Float64}(numangle) | ||
for i in 1:numangle | ||
tabsin[i] = (sin(min_theta + (i-1)*theta) * irho) | ||
tabcos[i] = (cos(min_theta + (i-1)*theta) * irho) | ||
end | ||
|
||
|
||
#Hough Transform implementation | ||
for pix in CartesianRange(size(img)) | ||
if img[pix] == 1.0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you're using |
||
for i in 1:numangle | ||
dist::Int64 = round((pix[1] * tabsin[i] + pix[2] * tabcos[i])) | ||
dist += round((numrho -1)/2) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This constant could be hoisted out of the loop. |
||
accumulator_matrix[i + 1, dist + 1] += 1 | ||
end | ||
end | ||
end | ||
|
||
#Finding local maximum lines | ||
validLines = Array{CartesianIndex}(0) | ||
for val in CartesianRange(size(accumulator_matrix)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps we should add a function input to |
||
if accumulator_matrix[val] > threshold && | ||
accumulator_matrix[val] > accumulator_matrix[val[1],val[2] - 1] && | ||
accumulator_matrix[val] >= accumulator_matrix[val[1],val[2] + 1] && | ||
accumulator_matrix[val] > accumulator_matrix[val[1] - 1,val[2]] && | ||
accumulator_matrix[val] >= accumulator_matrix[val[1] + 1,val[2]] | ||
push!(validLines,val) | ||
end | ||
end | ||
|
||
#Sorting by value in accumulator_matrix | ||
sort!(validLines, by = (x)->accumulator_matrix[x], rev = true) | ||
|
||
linesMax = min(linesMax, size(validLines)[1]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can just use |
||
|
||
lines = Array{Tuple{Float64,Float64}}(0) | ||
|
||
#Getting lines with Maximum value in accumulator_matrix && size(lines) < linesMax | ||
for l in 1:linesMax | ||
lrho = ((validLines[l][2]-1) - (numrho - 1)*0.5)*rho | ||
langle = ((validLines[l][1]-1)*theta + min_theta) | ||
push!(lines,(lrho,langle)) | ||
end | ||
|
||
lines | ||
|
||
end | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Too restrictive on the types? Particularly for people who have 32-bit machines,
Int64
is not native (better to useInt
).Number
andInteger
might even be best.