# What exactly do DerivativeFilter and RidgeFilter do with the scale parameter?

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] uses r = σ/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)?

DerivativeFilter calculates two sequential convolutions of original image with one-dimesional gaussian kernels. First with vertical kernel and then with horizontal one.

Parameter sigma defines the standard deviation of the gaussian distribution which is used to calculate each one-dimensional kernel.

Here is a code which reproduces DerivativeFilter using ImageConvolve:

mockupDerivativeFilter[image_, {verticalDerivativeOrder_, horizontalDerivativeOrder_}, sigma_] := Module[
{verticalKernel, horizontalKernel, verticallyFilteredImage},

verticalKernel = Transpose[{gaussianDerivativeKernel[verticalDerivativeOrder, sigma]}];
horizontalKernel = {gaussianDerivativeKernel[horizontalDerivativeOrder, sigma]};

verticallyFilteredImage = ImageConvolve[
image,
verticalKernel,
];

ImageConvolve[
verticallyFilteredImage,
horizontalKernel,
]
];

gaussianDerivativeKernel[derivativeOrder_Integer, sigma_] := Module[
radius =  Ceiling[1.0 + 6.23 sigma];
Table[ N[D[1/(Sqrt[2 Pi] sigma) Exp[-xvar^2/(2 sigma^2)], {xvar, derivativeOrder}] /. xvar->x] , {x, -radius, radius}]
];

img = Image[ColorConvert[ExampleData[{"TestImage", "Mandrill"}], "Grayscale"], "Real32"];

referenceImage = ImageAdjust@DerivativeFilter[img, {1, 1}, 10];

mockupImage = ImageAdjust@mockupDerivativeFilter[img, {1, 1}, 10];

{referenceImage, mockupImage, referenceImage - mockupImage}


The function GaussianFilter[image, r] indeed uses standard deviation sigma=r/2. The corresponding help page seems to be corrected in Mathematica 11.