Leptonica  1.82.0
Image processing and image analysis suite
bilateral.c File Reference
#include <math.h>
#include "allheaders.h"
#include "bilateral.h"

Go to the source code of this file.

Macros

#define DEBUG_BILATERAL   0
 

Functions

static L_BILATERALbilateralCreate (PIX *pixs, l_float32 spatial_stdev, l_float32 range_stdev, l_int32 ncomps, l_int32 reduction)
 
static PIXbilateralApply (L_BILATERAL *bil)
 
static void bilateralDestroy (L_BILATERAL **pbil)
 
PIXpixBilateral (PIX *pixs, l_float32 spatial_stdev, l_float32 range_stdev, l_int32 ncomps, l_int32 reduction)
 
PIXpixBilateralGray (PIX *pixs, l_float32 spatial_stdev, l_float32 range_stdev, l_int32 ncomps, l_int32 reduction)
 
PIXpixBilateralExact (PIX *pixs, L_KERNEL *spatial_kel, L_KERNEL *range_kel)
 
PIXpixBilateralGrayExact (PIX *pixs, L_KERNEL *spatial_kel, L_KERNEL *range_kel)
 
PIXpixBlockBilateralExact (PIX *pixs, l_float32 spatial_stdev, l_float32 range_stdev)
 
L_KERNELmakeRangeKernel (l_float32 range_stdev)
 

Detailed Description

    Top level approximate separable grayscale or color bilateral filtering
         PIX                 *pixBilateral()
         PIX                 *pixBilateralGray()
    Implementation of approximate separable bilateral filter
         static L_BILATERAL  *bilateralCreate()
         static void         *bilateralDestroy()
         static PIX          *bilateralApply()
    Slow, exact implementation of grayscale or color bilateral filtering
         PIX                 *pixBilateralExact()
         PIX                 *pixBilateralGrayExact()
         PIX                 *pixBlockBilateralExact()
    Kernel helper function
         L_KERNEL            *makeRangeKernel()
 This includes both a slow, exact implementation of the bilateral
 filter algorithm (given by Sylvain Paris and Frédo Durand),
 and a fast, approximate and separable implementation (following
 Yang, Tan and Ahuja).  See bilateral.h for algorithmic details.
 The bilateral filter has the nice property of applying a gaussian
 filter to smooth parts of the image that don't vary too quickly,
 while at the same time preserving edges.  The filter is nonlinear
 and cannot be decomposed into two separable filters; however,
 there exists an approximate method that is separable.  To further
 speed up the separable implementation, you can generate the
 intermediate data at reduced resolution.
 The full kernel is composed of two parts: a spatial gaussian filter
 and a nonlinear "range" filter that depends on the intensity difference
 between the reference pixel at the spatial kernel origin and any other
 pixel within the kernel support.
 In our implementations, the range filter is a parameterized,
 one-sided, 256-element, monotonically decreasing gaussian function
 of the absolute value of the difference between pixel values; namely,
 abs(I2 - I1).  In general, any decreasing function can be used,
 and more generally,  any two-dimensional kernel can be used if
 you wish to relax the 'abs' condition.  (In that case, the range
 filter can be 256 x 256).

Definition in file bilateral.c.

Function Documentation

◆ bilateralApply()

◆ bilateralCreate()

static L_BILATERAL * bilateralCreate ( PIX pixs,
l_float32  spatial_stdev,
l_float32  range_stdev,
l_int32  ncomps,
l_int32  reduction 
)
static

bilateralCreate()

Parameters
[in]pixs8 bpp gray, no colormap
[in]spatial_stdevof gaussian kernel; in pixels, > 0.5
[in]range_stdevof gaussian range kernel; > 5.0; typ. 50.0
[in]ncompsnumber of intermediate sums J(k,x); in [4 ... 30]
[in]reduction1, 2 or 4
Returns
bil, or NULL on error
Notes:
     (1) This initializes a bilateral filtering operation, generating all
         the data required.  It takes most of the time in the bilateral
         filtering operation.
     (2) See bilateral.h for details of the algorithm.
     (3) See pixBilateral() for constraints on input parameters, which
         are not checked here.

Definition at line 295 of file bilateral.c.

References L_Bilateral::kfract, L_Bilateral::kindex, L_SELECT_MAX, L_SELECT_MIN, lept_stderr(), L_Bilateral::maxval, L_Bilateral::minval, L_Bilateral::nc, L_Bilateral::ncomps, pixaCreate(), pixAddMirroredBorder(), pixClone(), pixDestroy(), pixGetData(), pixGetDimensions(), pixGetExtremeValue(), L_Bilateral::pixs, L_Bilateral::pixsc, pixScaleAreaMap2(), L_Bilateral::range, L_Bilateral::range_stdev, L_Bilateral::reduction, L_Bilateral::spatial, and L_Bilateral::spatial_stdev.

◆ bilateralDestroy()

static void bilateralDestroy ( L_BILATERAL **  pbil)
static

◆ makeRangeKernel()

L_KERNEL* makeRangeKernel ( l_float32  range_stdev)

makeRangeKernel()

Parameters
[in]range_stdevmust be > 0.0
Returns
kel, or NULL on error
Notes:
     (1) Creates a one-sided Gaussian kernel with the given
         standard deviation.  At grayscale difference of one stdev,
         the kernel falls to 0.6, and to 0.01 at three stdev.
     (2) A typical input number might be 20.  Then pixels whose
         value differs by 60 from the center pixel have their
         weight in the convolution reduced by a factor of about 0.01.

Definition at line 809 of file bilateral.c.

References kernelCreate(), kernelSetElement(), and kernelSetOrigin().

◆ pixBilateral()

PIX* pixBilateral ( PIX pixs,
l_float32  spatial_stdev,
l_float32  range_stdev,
l_int32  ncomps,
l_int32  reduction 
)

pixBilateral()

Parameters
[in]pixs8 bpp gray or 32 bpp rgb, no colormap
[in]spatial_stdevof gaussian kernel; in pixels, > 0.5
[in]range_stdevof gaussian range kernel; > 5.0; typ. 50.0
[in]ncompsnumber of intermediate sums J(k,x); in [4 ... 30]
[in]reduction1, 2 or 4
Returns
pixd bilateral filtered image, or NULL on error
Notes:
     (1) This performs a relatively fast, separable bilateral
         filtering operation.  The time is proportional to ncomps
         and varies inversely approximately as the cube of the
         reduction factor.  See bilateral.h for algorithm details.
     (2) We impose minimum values for range_stdev and ncomps to
         avoid nasty artifacts when either are too small.  We also
         impose a constraint on their product:
              ncomps * range_stdev >= 100.
         So for values of range_stdev >= 25, ncomps can be as small as 4.
         Here is a qualitative, intuitive explanation for this constraint.
         Call the difference in k values between the J(k) == 'delta', where
             'delta' ~ 200 / ncomps
         Then this constraint is roughly equivalent to the condition:
             'delta' < 2 * range_stdev
         Note that at an intensity difference of (2 * range_stdev), the
         range part of the kernel reduces the effect by the factor 0.14.
         This constraint requires that we have a sufficient number of
         PCBs (i.e, a small enough 'delta'), so that for any value of
         image intensity I, there exists a k (and a PCB, J(k), such that
             |I - k| < range_stdev
         Any fewer PCBs and we don't have enough to support this condition.
     (3) The upper limit of 30 on ncomps is imposed because the
         gain in accuracy is not worth the extra computation.
     (4) The size of the gaussian kernel is twice the spatial_stdev
         on each side of the origin.  The minimum value of
         spatial_stdev, 0.5, is required to have a finite sized
         spatial kernel.  In practice, a much larger value is used.
     (5) Computation of the intermediate images goes inversely
         as the cube of the reduction factor.  If you can use a
         reduction of 2 or 4, it is well-advised.
     (6) The range kernel is defined over the absolute value of pixel
         grayscale differences, and hence must have size 256 x 1.
         Values in the array represent the multiplying weight
         depending on the absolute gray value difference between
         the source pixel and the neighboring pixel, and should
         be monotonically decreasing.
     (7) Interesting observation.  Run this on prog/fish24.jpg, with
         range_stdev = 60, ncomps = 6, and spatial_dev = {10, 30, 50}.
         As spatial_dev gets larger, we get the counter-intuitive
         result that the body of the red fish becomes less blurry.
     (8) The image must be sufficiently big to get reasonable results.
         This requires the dimensions to be at least twice the filter size.
         Otherwise, return a copy of the input with warning.

Definition at line 157 of file bilateral.c.

◆ pixBilateralExact()

PIX* pixBilateralExact ( PIX pixs,
L_KERNEL spatial_kel,
L_KERNEL range_kel 
)

pixBilateralExact()

Parameters
[in]pixs8 bpp gray or 32 bpp rgb
[in]spatial_kelgaussian kernel
[in]range_kel[optional] 256 x 1, monotonically decreasing
Returns
pixd 8 bpp bilateral filtered image
Notes:
     (1) The spatial_kel is a conventional smoothing kernel, typically a
         2-d Gaussian kernel or other block kernel.  It can be either
         normalized or not, but must be everywhere positive.
     (2) The range_kel is defined over the absolute value of pixel
         grayscale differences, and hence must have size 256 x 1.
         Values in the array represent the multiplying weight for each
         gray value difference between the target pixel and center of the
         kernel, and should be monotonically decreasing.
     (3) If range_kel == NULL, a constant weight is applied regardless
         of the range value difference.  This degenerates to a regular
         pixConvolve() with a normalized kernel.

Definition at line 597 of file bilateral.c.

◆ pixBilateralGray()

PIX* pixBilateralGray ( PIX pixs,
l_float32  spatial_stdev,
l_float32  range_stdev,
l_int32  ncomps,
l_int32  reduction 
)

pixBilateralGray()

Parameters
[in]pixs8 bpp gray
[in]spatial_stdevof gaussian kernel; in pixels, > 0.5
[in]range_stdevof gaussian range kernel; > 5.0; typ. 50.0
[in]ncompsnumber of intermediate sums J(k,x); in [4 ... 30]
[in]reduction1, 2 or 4
Returns
pixd 8 bpp bilateral filtered image, or NULL on error
Notes:
     (1) See pixBilateral() for constraints on the input parameters.
     (2) See pixBilateral() for algorithm details.

Definition at line 234 of file bilateral.c.

◆ pixBilateralGrayExact()

PIX* pixBilateralGrayExact ( PIX pixs,
L_KERNEL spatial_kel,
L_KERNEL range_kel 
)

pixBilateralGrayExact()

Parameters
[in]pixs8 bpp gray
[in]spatial_kelgaussian kernel
[in]range_kel[optional] 256 x 1, monotonically decreasing
Returns
pixd 8 bpp bilateral filtered image
Notes:
     (1) See pixBilateralExact().

Definition at line 651 of file bilateral.c.

◆ pixBlockBilateralExact()

PIX* pixBlockBilateralExact ( PIX pixs,
l_float32  spatial_stdev,
l_float32  range_stdev 
)

pixBlockBilateralExact()

Parameters
[in]pixs8 bpp gray or 32 bpp rgb
[in]spatial_stdevmust be > 0.0
[in]range_stdevmust be > 0.0
Returns
pixd 8 bpp or 32 bpp bilateral filtered image
Notes:
     (1) See pixBilateralExact().  This provides an interface using
         the standard deviations of the spatial and range filters.
     (2) The convolution window halfwidth is 2 * spatial_stdev,
         and the square filter size is 4 * spatial_stdev + 1.
         The kernel captures 95% of total energy.  This is compensated
         by normalization.
     (3) The range_stdev is analogous to spatial_halfwidth in the
         grayscale domain [0...255], and determines how much damping of the
         smoothing operation is applied across edges.  The larger this
         value is, the smaller the damping.  The smaller the value, the
         more edge details are preserved.  These approximations are useful
         for deciding the appropriate cutoff.
             kernel[1 * stdev] ~= 0.6  * kernel[0]
             kernel[2 * stdev] ~= 0.14 * kernel[0]
             kernel[3 * stdev] ~= 0.01 * kernel[0]
         If range_stdev is infinite there is no damping, and this
         becomes a conventional gaussian smoothing.
         This value does not affect the run time.
     (4) If range_stdev is negative or zero, the range kernel is
         ignored and this degenerates to a straight gaussian convolution.
     (5) This is very slow for large spatial filters.  The time
         on a 3GHz pentium is roughly
            T = 1.2 * 10^-8 * (A * sh^2)  sec
         where A = # of pixels, sh = spatial halfwidth of filter.

Definition at line 757 of file bilateral.c.