From 2e1bc893ed5d8ed565ffa808ac3b14f681ebf224 Mon Sep 17 00:00:00 2001 From: "Dr. Zygmunt L. Szpak" Date: Tue, 1 Dec 2020 22:25:10 +1030 Subject: [PATCH] Fixes incorrect orientation value that was returned for undefined grad --- docs/src/index.md | 15 ++++++++------- src/EdgeDetectionAPI/edge_detection.jl | 8 ++++---- src/algorithms/gradient_orientation.jl | 14 ++++++++++++-- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/docs/src/index.md b/docs/src/index.md index caeea20..748421a 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -126,13 +126,14 @@ to specify the compass direction against which you intend to measure the angle, and whether you are measuring in a clockwise or counter-clockwise manner. In the example below, we map the angles `[0...360]` to the unit interval to -visualise the orientation of the circle edge test image using different -orientation conventions. Note that the angle `360` is used as a sentinel value -to demarcate pixels for which the gradient orientation is undefined. The -gradient orientation is undefined when the gradient magnitude is effectively -zero. This corresponds to regions of constant intensity in the image. In the -images that depict the gradient orientation, the undefined orientations are -represent as pure white pixels. +visualise the orientation of the image gradient using different orientation +conventions. Note that the angle `360` is used as a sentinel value to demarcate +pixels for which the gradient orientation is undefined. The gradient orientation +is undefined when the gradient magnitude is effectively zero. This corresponds +to regions of constant intensity in the image. In the In the panel of images, +the first image constitutes a black circle against a white background. The +subsequent images depict the image gradient orientation, where the undefined +gradient orientations are represent as pure white pixels. ```@example GradientOrientation using ImageEdgeDetection, MosaicViews, ImageFiltering, ImageCore diff --git a/src/EdgeDetectionAPI/edge_detection.jl b/src/EdgeDetectionAPI/edge_detection.jl index 817dae1..590823f 100644 --- a/src/EdgeDetectionAPI/edge_detection.jl +++ b/src/EdgeDetectionAPI/edge_detection.jl @@ -230,7 +230,7 @@ detect_subpixel_edges(img::AbstractArray{T}, detect_edges!([out,] img, f::AbstractEdgeDetectionAlgorithm, args...; kwargs...) Detect edges of `img` using algorithm `f`; if left unspecified, `f` is assumed -to be [`Canny`](@ref). +to be [`Canny`](@ref ImageEdgeDetection.Canny). # Output @@ -260,7 +260,7 @@ detect_edges! out = detect_edges([T::Type,] img, f::AbstractEdgeDetectionAlgorithm, args...; kwargs...) Detect edges of `img` using algorithm `f`; if left unspecified, `f` is assumed -to be [`Canny`](@ref). +to be [`Canny`](@ref ImageEdgeDetection.Canny). # Output @@ -294,7 +294,7 @@ detect_edges detect_subpixel_edges!(out₁, out₂, img, f::AbstractEdgeDetectionAlgorithm, args...; kwargs...) Detect edges of `img` to subpixel precision using algorithm `f`; if left -unspecified, `f` is assumed to be [`Canny`](@ref). +unspecified, `f` is assumed to be [`Canny`](@ref ImageEdgeDetection.Canny). # Output @@ -322,7 +322,7 @@ detect_subpixel_edges! out₁, out₂ = detect_subpixel_edges([T₁::Type, T₂::Type], img, f::AbstractEdgeDetectionAlgorithm, args...; kwargs...) Detect edges of `img` to subpixel precision using algorithm `f`; if left -unspecified, `f` is assumed to be [`Canny`](@ref). +unspecified, `f` is assumed to be [`Canny`](@ref ImageEdgeDetection.Canny). # Output diff --git a/src/algorithms/gradient_orientation.jl b/src/algorithms/gradient_orientation.jl index dcc6ee5..5d9ef06 100644 --- a/src/algorithms/gradient_orientation.jl +++ b/src/algorithms/gradient_orientation.jl @@ -170,11 +170,11 @@ function detect_gradient_orientation!(out::AbstractArray, g₁::AbstractArray, g end elseif is_clockwise && !in_radians @inbounds for i in CartesianIndices(g₁) - out[i] = rad2deg(zero_to_2PI(clockwise(valid_angle(g₁[i], g₂[i], offset, tol)))) + out[i] = rad2deg(zero_to_2PI(clockwise_valid_angle(g₁[i], g₂[i], offset, tol))) end elseif is_clockwise && in_radians @inbounds for i in CartesianIndices(g₁) - out[i] = zero_to_2PI(clockwise(valid_angle(g₁[i], g₂[i], offset, tol))) + out[i] = zero_to_2PI(clockwise_valid_angle(g₁[i], g₂[i], offset, tol)) end end return nothing @@ -195,6 +195,16 @@ function valid_angle(g₁, g₂, offset, tol) return is_angle_undefined ? 2π : atan(-g₁, g₂) + offset end +# When the angle is undefined because g₁ and g₂ are almost zero, we return +# a "dummy" value of 2π. +function clockwise_valid_angle(g₁, g₂, offset, tol) + # The expression for the angle when changing coordinate system from Raster + # to Cartesian coordinates is atan(-g₁, g₂). The offset is used to indicate + # against which compass direction we will measure angles. + is_angle_undefined = (abs(g₁) < tol && abs(g₂) < tol) + return is_angle_undefined ? 2π : clockwise(atan(-g₁, g₂) + offset) +end + function zero_to_2PI(θ) return (θ >= 0 ? θ : (2*π + θ)) end