Both DerivativeFilter
and RidgeFilter
take an optional parameter σ
to indicate the scale of derivatives being used. I would like to reproduce an algorithm I've been working on in another language, so I need to figure out what exactly these functions do with that parameter. However, the docs aren't giving much away. We have this from DerivativeFilter
:
[...] computes the derivative at a Gaussian scale of standard deviation
σ
.
Image derivatives are susceptible to noise. To counteract this effect, you can regularize the image or data by a Gaussian kernel of standard deviation
σ
. The default value isσ = 0
.
And this from RidgeFilter
:
[...] uses the specified ridge scale
σ
.
In
RidgeFilter[image, σ]
,σ
is the scale of the ridges that is used to compute the derivatives in the Hessian. By default,σ = 1
is used.
I believe that the exact effect of σ
is the same in both functions, because the docs of DerivativeFilter
contain a reimplementation of RidgeFilter
. It doesn't exactly match the outputs of RidgeFilter
, but we can fix that by adding a simple Clip
:
ridgeFilter[img_, σ_: 1] := Module[
{data = ImageData[img], Lxx, Lxy, Lyy},
{Lxx, Lxy, Lyy} =
DerivativeFilter[data, {{0, 2}, {1, 1}, {2, 0}}, σ];
Image[
Clip[Chop[σ^(3/2)/2 (Sqrt[(Lxx - Lyy)^2 + 4 Lxy^2] - Lxx - Lyy)], {0, ∞}]
]
]
The results of this are identical (except for small numerical errors) to RidgeFilter
and this just passes the σ
through to DerivativeFilter
.
Nevertheless, combining the information from the two pages of the docs, I still can't tell what exactly the functions are doing. It sounds to me like they simply run a GaussianFilter
over the image first. I can obtain results at the same scale by using 2 σ
as the radius of the Gaussian filter, but then I still get a lot of small scale artefacts that are missing when I use DerivativeFilter
or RidgeFilter
directly:
img = ColorConvert[ExampleData[{"TestImage", "Mandrill"}], "Grayscale"]
σ = 10;
ImageAssemble @ {
ImageAdjust @ DerivativeFilter[img, {1, 1}, σ],
ImageAdjust @ DerivativeFilter[GaussianFilter[img, 2 σ], {1, 1}]
}
Results in:
I'm actually completely baffled that I need to double σ
(instead of halving it) since the docs for GaussianFilter
call this parameter the radius r
and they even say explicitly:
GaussianFilter[image, r]
usesr = σ/2
.
All of this seems highly confusing, and there must be more to it than simply smoothing the input up front.
What exactly is the magic behind this σ
parameter in DerivativeFilter
(and by extension RidgeFilter
)?