Filtering of CPL images.


Defines

#define inline
#define OUT_TYPE   IN_TYPE
#define assure(x)   assert(x)
#define mybool   unsigned char
#define mytrue   1
#define myfalse   0
#define S_SWAP(SCA, i, j)
#define BITS   64
#define sort3(p0, p1, p2, i0, i1, i2)
 sort 3 elements

Functions

static void qsort_int (unsigned *SCA, unsigned n, const IN_TYPE *image)
 quick sort
static void SCA_init (dheap *dh, unsigned x)
 initialize sorted column array
static void SCA_replace (dheap *dh, unsigned x, unsigned yold, unsigned ynew)
 Update sorted column array.
static void HEAP_SWAP (unsigned i, unsigned j, unsigned int *B, unsigned int *heaps)
 Swap elements in double heap.
static void median (dheap *dh)
 Partion double heaps array in median and upper/lower values.
static unsigned bubble_down_gt (const IN_TYPE *image, unsigned *B, unsigned *heaps, unsigned m, unsigned m1, unsigned root)
 bubble down (towards leaves) in upper heap
static unsigned bubble_up_gt (const IN_TYPE *image, unsigned *B, unsigned *heaps, unsigned m1, unsigned child)
 bubble up (towards root) in upper heap
static void heapify_gt (dheap *dh)
 establish upper heap
static unsigned bubble_down_lt (const IN_TYPE *image, unsigned *B, unsigned *heaps, unsigned end, unsigned root)
 bubble down in lower heap
static unsigned bubble_up_lt (const IN_TYPE *image, unsigned *B, unsigned *heaps, unsigned child)
 bubble up in lower heap
static void heapify_lt (dheap *dh)
 establish lower heap
static void dheap_establish (dheap *dh)
 Initialize double heap.
static dheap * dheap_new (const IN_TYPE *image, unsigned Nx, unsigned Ny, unsigned rx, unsigned ry)
 double heap constructor
static void dheap_delete (dheap *dh)
 double heap destructor
static IN_TYPE dheap_median (const dheap *dh)
 get current median
static void dheap_replace (const IN_TYPE *image, unsigned *B, unsigned *heaps, unsigned m, unsigned m1, unsigned anew, unsigned aold)
 Insert and remove element in double heap.
static IN_TYPE get_kth (IN_TYPE *a, unsigned n, int k)
static IN_TYPE max3 (IN_TYPE p0, IN_TYPE p1, IN_TYPE p2)
 max of 3 elements
static IN_TYPE min3 (IN_TYPE p0, IN_TYPE p1, IN_TYPE p2)
 min of 3 elements
static IN_TYPE median5 (IN_TYPE p0, IN_TYPE p1, IN_TYPE p2, IN_TYPE p3, IN_TYPE p4)
 median of 5
static IN_TYPE median9_2 (IN_TYPE p0, IN_TYPE p1, IN_TYPE p2, IN_TYPE p3, IN_TYPE p4, IN_TYPE p5, IN_TYPE p6, IN_TYPE p7, IN_TYPE p8)
 median of 9
static IN_TYPE median9_1 (IN_TYPE p0, IN_TYPE p1, IN_TYPE p2, IN_TYPE p3, IN_TYPE p4, IN_TYPE p5, IN_TYPE p6, IN_TYPE p7, IN_TYPE p8)
 median of 9
static void filter_median_1 (const IN_TYPE *in, OUT_TYPE *out, unsigned Nx, unsigned Ny, unsigned border_mode)
 fast 3x3 image median filter
static void fill_row (IN_TYPE *in, unsigned nx, unsigned y, unsigned xmin, unsigned xmax, IN_TYPE val1, IN_TYPE val2)
 Write values to image row.
static void fill_chess (IN_TYPE *in_larger, const IN_TYPE *in, unsigned Nx_larger, unsigned Ny_larger, unsigned Nx, unsigned Ny, unsigned rx, unsigned ry)
 Fill image border with +- infinity.
static void filter_median (const IN_TYPE *in, OUT_TYPE *out, unsigned Nx, unsigned Ny, unsigned rx, unsigned ry, unsigned border_mode)
 Fast, any bit-depth, image median filter.

Detailed Description

Synopsis:
     #include <irplib_filter.h>
Example:
Usage: define the following preprocessor symbols as needed, then include this file

Define Documentation

#define S_SWAP ( SCA,
i,
 ) 

Value:

do { \
    const unsigned SCAi = SCA[i]; \
    const unsigned SCAj = SCA[j]; \
    SCA[i] = SCAj; \
    SCA[j] = SCAi; \
} while(0)

Definition at line 117 of file filter_median.c.

Referenced by qsort_int(), and SCA_replace().

#define sort3 ( p0,
p1,
p2,
i0,
i1,
i2   ) 

Value:

do {                                                          \
    if (i0 <= i1) {                                           \
        if (i1 <= i2) {                                       \
             p0 = i0; p1 = i1; p2 = i2;                       \
        } else if (i0 <= i2) {                                \
            /* i0, i2, i1 */                                  \
            p0 = i0; p1 = i2; p2 = i1;                        \
        } else {                                              \
            /*  i2, i0, i1 */                                 \
            p0 = i2; p1 = i0; p2 = i1;                        \
        }                                                     \
    } else {                                                  \
        if (i0 <= i2) {                                       \
            /* i1, i0, i2 */                                  \
            p0 = i1; p1 = i0; p2 = i2;                        \
        } else if (i1 < i2) {                                 \
            /* i1, i2, i0 */                                  \
            p0 = i1; p1 = i2; p2 = i0;                        \
        } else {                                              \
            /* i2, i1, i0 */                                  \
            p0 = i2; p1=i1; p2 = i0;                          \
        }                                                     \
    }                                                         \
} while(0)
sort 3 elements

Parameters:
p0 (out) rank 1
p1 (out) rank 2
p2 (out) rank 3
i0 (in) element
i1 (in) element
i2 (in) element
Cost: 2 (probability 1/3) or 3 (probability 2/3) = 8/3 = 2.66 comparisons

Definition at line 998 of file filter_median.c.

Referenced by filter_median_1().


Function Documentation

static void qsort_int ( unsigned *  SCA,
unsigned  n,
const IN_TYPE *  image 
) [static]

quick sort

Parameters:
SCA sorted column array to be sorted
n length of SCA
image input image
SCA is sorted in increasing order by image[SCA[i]]

Definition at line 136 of file filter_median.c.

References BITS, and S_SWAP.

Referenced by SCA_init().

static void SCA_init ( dheap *  dh,
unsigned  x 
) [static]

initialize sorted column array

Parameters:
dh double heap
x current column

Definition at line 221 of file filter_median.c.

References qsort_int().

Referenced by dheap_new(), and filter_median().

static void SCA_replace ( dheap *  dh,
unsigned  x,
unsigned  yold,
unsigned  ynew 
) [static]

Update sorted column array.

Parameters:
dh double heap
x current column
yold image row of previous element
ynew image row of new element

Definition at line 245 of file filter_median.c.

References S_SWAP.

Referenced by filter_median().

static void HEAP_SWAP ( unsigned  i,
unsigned  j,
unsigned int *  B,
unsigned int *  heaps 
) [static]

Swap elements in double heap.

Parameters:
i index in heaps array
j index in heaps array
B image to heap map
heaps heaps array

Definition at line 307 of file filter_median.c.

Referenced by bubble_down_gt(), bubble_down_lt(), bubble_up_gt(), bubble_up_lt(), dheap_replace(), and median().

static void median ( dheap *  dh  )  [static]

Partion double heaps array in median and upper/lower values.

Parameters:
dh double heap with elements in no particular order

Definition at line 328 of file filter_median.c.

References HEAP_SWAP().

Referenced by dheap_establish(), irplib_spectrum_find_brightest(), opt_measure_profile_order(), uves_average_reject(), and uves_get_blaze_ratio().

static unsigned bubble_down_gt ( const IN_TYPE *  image,
unsigned *  B,
unsigned *  heaps,
unsigned  m,
unsigned  m1,
unsigned  root 
) [static]

bubble down (towards leaves) in upper heap

Parameters:
image input image
B inverse map
heaps double heap array
m heap size
m1 m + 1
root double heap position
Returns:
final position

Definition at line 374 of file filter_median.c.

References HEAP_SWAP().

Referenced by dheap_replace(), and heapify_gt().

static unsigned bubble_up_gt ( const IN_TYPE *  image,
unsigned *  B,
unsigned *  heaps,
unsigned  m1,
unsigned  child 
) [static]

bubble up (towards root) in upper heap

Parameters:
image input image
B inverse map
heaps double heap array
m1 heap size + 1
child double heap position
Returns:
final position

Definition at line 414 of file filter_median.c.

References HEAP_SWAP().

Referenced by dheap_replace().

static void heapify_gt ( dheap *  dh  )  [static]

establish upper heap

Parameters:
dh double heap

Definition at line 440 of file filter_median.c.

References bubble_down_gt().

Referenced by dheap_establish().

static unsigned bubble_down_lt ( const IN_TYPE *  image,
unsigned *  B,
unsigned *  heaps,
unsigned  end,
unsigned  root 
) [static]

bubble down in lower heap

Parameters:
image input image
B inverse map
heaps double heap array
end double heap last position
root double heap position
Returns:
final position

Definition at line 465 of file filter_median.c.

References HEAP_SWAP().

Referenced by dheap_replace(), and heapify_lt().

static unsigned bubble_up_lt ( const IN_TYPE *  image,
unsigned *  B,
unsigned *  heaps,
unsigned  child 
) [static]

bubble up in lower heap

Parameters:
image input image
B inverse map
heaps double heap array
child double heap position
Returns:
final position

Definition at line 501 of file filter_median.c.

References HEAP_SWAP().

Referenced by dheap_replace().

static void heapify_lt ( dheap *  dh  )  [static]

establish lower heap

Parameters:
dh double heap

Definition at line 525 of file filter_median.c.

References bubble_down_lt().

Referenced by dheap_establish().

static void dheap_establish ( dheap *  dh  )  [static]

Initialize double heap.

Parameters:
dh double heap with elements in no particular order

Definition at line 544 of file filter_median.c.

References heapify_gt(), heapify_lt(), and median().

Referenced by dheap_new().

static dheap* dheap_new ( const IN_TYPE *  image,
unsigned  Nx,
unsigned  Ny,
unsigned  rx,
unsigned  ry 
) [static]

double heap constructor

Parameters:
image input image
Nx image width
Ny image height
rx filtering half-size in x
ry filtering half-size in y
Returns:
newly allocated double heap which may be destroyed using dheap_delete()
The double heap, inverse map and SCA invariants are established using the first image window

Definition at line 567 of file filter_median.c.

References assure, dheap_establish(), and SCA_init().

Referenced by filter_median().

static void dheap_delete ( dheap *  dh  )  [static]

double heap destructor

Parameters:
dh double heap

Definition at line 620 of file filter_median.c.

static IN_TYPE dheap_median ( const dheap *  dh  )  [static]

get current median

Parameters:
dh double heap
Returns:
the median element value

Definition at line 636 of file filter_median.c.

Referenced by filter_median().

static void dheap_replace ( const IN_TYPE *  image,
unsigned *  B,
unsigned *  heaps,
unsigned  m,
unsigned  m1,
unsigned  anew,
unsigned  aold 
) [static]

Insert and remove element in double heap.

Parameters:
image input image
B inverse map
heaps double heap array
m heap size
m1 m + 1
anew image index of pixel to be inserted
aold image index of pixel to be removed
Note: Uses static memory, not thread-safe

Algorithm: The inverse map is used to quickly locate the old pixel, which is replaced, and the new element bubbled to a (non-unique) correct position until the double heap structure is re-established. The inverse map is maintained while swapping heap elements.

Definition at line 659 of file filter_median.c.

References bubble_down_gt(), bubble_down_lt(), bubble_up_gt(), bubble_up_lt(), HEAP_SWAP(), mybool, myfalse, and mytrue.

Referenced by filter_median().

static IN_TYPE max3 ( IN_TYPE  p0,
IN_TYPE  p1,
IN_TYPE  p2 
) [static]

max of 3 elements

Parameters:
p0 element
p1 element
p2 element
Returns:
maximum element
Cost: 2 comparisons

Definition at line 839 of file filter_median.c.

Referenced by median5().

static IN_TYPE min3 ( IN_TYPE  p0,
IN_TYPE  p1,
IN_TYPE  p2 
) [static]

min of 3 elements

Parameters:
p0 element
p1 element
p2 element
Returns:
minimum element
Cost: 2 comparisons

Definition at line 860 of file filter_median.c.

Referenced by median5().

static IN_TYPE median5 ( IN_TYPE  p0,
IN_TYPE  p1,
IN_TYPE  p2,
IN_TYPE  p3,
IN_TYPE  p4 
) [static]

median of 5

Parameters:
p0 element
p1 element
p2 element
p3 element
p4 element
Returns:
median
Precondition: p0 <= p1 <= p2

Cost: 2 + 0 (probability 4/7) or 2 + 2 (probability 3/7) = 20/7 = 2.86 comparisons

Definition at line 888 of file filter_median.c.

References max3(), and min3().

Referenced by median9_2().

static IN_TYPE median9_2 ( IN_TYPE  p0,
IN_TYPE  p1,
IN_TYPE  p2,
IN_TYPE  p3,
IN_TYPE  p4,
IN_TYPE  p5,
IN_TYPE  p6,
IN_TYPE  p7,
IN_TYPE  p8 
) [static]

median of 9

Parameters:
p0 element
p1 element
p2 element
p3 element
p4 element
p5 element
p6 element
p7 element
p8 element
Returns:
median
Precondition: p0 <= p1 <= p2 p3 <= p4 <= p5 p6 <= p7 <= p8 p1 <= p4

Cost: 1 + 2.86 (probability 1/3) or 2 + 2.86 (probability 2/3) = 95/21 = 4.52 comparisons

Definition at line 933 of file filter_median.c.

References median5().

Referenced by median9_1().

static IN_TYPE median9_1 ( IN_TYPE  p0,
IN_TYPE  p1,
IN_TYPE  p2,
IN_TYPE  p3,
IN_TYPE  p4,
IN_TYPE  p5,
IN_TYPE  p6,
IN_TYPE  p7,
IN_TYPE  p8 
) [static]

median of 9

Parameters:
p0 element
p1 element
p2 element
p3 element
p4 element
p5 element
p6 element
p7 element
p8 element
Returns:
median
Precondition: p0 <= p1 <= p2 p3 <= p4 <= p5 p6 <= p7 <= p8

Cost: 1 + 4.52 = 116/21 = 5.52 comparisons

Definition at line 971 of file filter_median.c.

References median9_2().

Referenced by filter_median_1().

static void filter_median_1 ( const IN_TYPE *  in,
OUT_TYPE *  out,
unsigned  Nx,
unsigned  Ny,
unsigned  border_mode 
) [static]

fast 3x3 image median filter

Parameters:
in image to filter
out pre-allocated output image, must not overlap with the input image
Nx image width
Ny image height
border_mode periodic boundaries

Definition at line 1036 of file filter_median.c.

References assure, get_kth(), median9_1(), OUT_TYPE, and sort3.

Referenced by filter_median().

static void fill_row ( IN_TYPE *  in,
unsigned  nx,
unsigned  y,
unsigned  xmin,
unsigned  xmax,
IN_TYPE  val1,
IN_TYPE  val2 
) [static]

Write values to image row.

Parameters:
in image to fill
nx image width
y row (?) to fill
xmin first column to fill (inclusive)
xmax last column to fill (exclusive)
val1 value to write first position (xmin, y)
val2 other value
Every second pixel is filled with val1, other pixels with val2

Definition at line 1276 of file filter_median.c.

Referenced by fill_chess().

static void fill_chess ( IN_TYPE *  in_larger,
const IN_TYPE *  in,
unsigned  Nx_larger,
unsigned  Ny_larger,
unsigned  Nx,
unsigned  Ny,
unsigned  rx,
unsigned  ry 
) [static]

Fill image border with +- infinity.

Parameters:
in_larger image to fill
in input image
Nx_larger in_larger width
Ny_larger in_larger height
Nx in width
Ny in height
rx filter x-radius
ry filter y-radius

Definition at line 1305 of file filter_median.c.

References fill_row().

Referenced by filter_median().

static void filter_median ( const IN_TYPE *  in,
OUT_TYPE *  out,
unsigned  Nx,
unsigned  Ny,
unsigned  rx,
unsigned  ry,
unsigned  border_mode 
) [static]

Fast, any bit-depth, image median filter.

Parameters:
in image to filter
out pre-allocated output image, may not overlap with the input image, same size as input image
Nx image width
Ny image height
rx filtering half-size in x, non-negative
ry filtering half-size in y, non-negative
border_mode Handling of the pixels near the border (the region where part of the kernel would be outside the image)
Supported border modes: IRPLIB_FILTER_BORDER_FILTER: Compute the median of available values. IRPLIB_FILTER_BORDER_NOP: The border region in the output image is not touched. IRPLIB_FILTER_BORDER_CROP: The border region is removed. Consequently the size of the output image must be (Nx - 2rx) x (Ny - 2ry) IRPLIB_FILTER_BORDER_COPY: The border is filled by copying the input pixels. IRPLIB_FILTER_BORDER_EXTRAPOL_OUT:

Unsupported filter modes: In-place: Possible using a pixel buffer of dimension (Nx + 2Rx) * (1 + 2Ry) Unsupported border modes: Input extrapolation: The input image is extended to (Nx+2Rx) * (Ny+2Ry) and the halo is filled using extrapolation of the input border. Mean: As any, except the arithmetic mean of the two central values is used.

For each pixel in the image the median of a (2*Rx + 1)(2*Ry + 1) window is computed.

The straightforward approach is to loop over the image and build and sort the kernel array for every pixel. This leads to an O(RxRy log RxRy) algorithm, or O(RxRy) if the median is computed by repeated partitions.

The basic idea in this implementation is to maintain a double heap structure of the running window pixels:

_____ \ / <-- minimum heap of elements greater than the median \ / . <-- median

/ \ <-- maximum heap of elements less than the median / \ -----

With every 1 pixel shift of the running window (2Ry + 1) pixels have to be removed from the double heap, and another (2Ry + 1) pixels must be inserted. The worst case time for inserting/removing one element is two heap heights, O(log RxRy), so the overall time is O(Ry log RxRy).

Various tricks improve the performance

Rather than sorting every time the (2Ry + 1) new and old values (which would cost O(Ry log Ry), a sorted array of the current pixels is maintained for every column in the image. To update the sorted column arrays (SCA) only one pixel needs to be inserted/removed per iteration. When using simple linear search and insertion, the maintenance cost for the SCAs is O(Ry). A possible optimization not pursued here is to implement the SCAs as balanced binary search trees, which would reduce their maintenance cost to O(log Ry) (but the heap maintenance cost would still be O(Ry).

Performance: While the theoretical time complexity is O(Ry log RxRy), the empirical behaviour (for realistic size images with random, uncorrelated pixels from the same probability distribution) is O(Ry) with small constant coefficients.

Rx = Ry = 1 is handled as a separate case.

Definition at line 1440 of file filter_median.c.

References assure, dheap_median(), dheap_new(), dheap_replace(), fill_chess(), filter_median(), filter_median_1(), OUT_TYPE, SCA_init(), and SCA_replace().


Generated on Fri Apr 18 14:11:45 2008 for UVES Pipeline Reference Manual by  doxygen 1.5.1