Image Component Library (ICL)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Public Member Functions

Class that provides median filter abilities \. More...

#include <MedianOp.h>

Inheritance diagram for icl::filter::MedianOp:
icl::filter::NeighborhoodOp icl::filter::UnaryOp icl::utils::Configurable

List of all members.

Public Member Functions

 MedianOp (const utils::Size &maskSize)
 Constructor that creates a median filter object, with specified mask size.
void apply (const core::ImgBase *poSrc, core::ImgBase **ppoDst)
 applies the median operation on poSrc and stores the result in poDst
virtual utils::Size adaptSize (const utils::Size &size)
 ensures that mask width and height are odd

Detailed Description

Class that provides median filter abilities \.

The median class provides the ability for arbitrary mask sizes. Although the functionality of the IPP-optimized implementation and the fallback C++-implementation is identical, the performances are of different orders of magnitude. Fallback-functions for masks with dimensions 3x3 and 5x5 are optimizied with SSE-instructions, but the computation time for images of types Img8u and Img16s is still greater than the one of IPP-implementations. However SSE-implementations show a better performance for the type icl32f. Here the algorithm just takes the median using min and max functions. Images of the type Img8u and Img16s with other mask sizes are processed by the algorithm, that was introduced by Thomas S. Huang. With the help of a histogram the algorithm runs in O(n). For all other types a trivial implementation was designed to calculate the median values. It uses the naive algorithm of sorting all N pixel values inside the median mask, and setting the destination pixel value to the mid-element of the sorted pixel list. This algorithm runs in O(w*h*N*log(N)) where (w,h) is the size of source images ROI, and N=n*n is the mask size used. The following code extract explains the operation of the fallback algorithm in Img-style notation for a single channel image, and Img8u type (the real implementation uses some special optimizations, that are not mentioned further):

        void channel_median_8u(Img8u &src, Img8u &dst, int w, int h, int c)
        {
            std::vector<icl8u> list;
            for(Img8u::iterator s=src.begin(c), d=dst.begin(c); s.inRegion() ; s++, d++ )
            {
                for(Img8u::iterator sR(s,w,h); sR.inRegion(); sR++)
                {
                   list.push_back(*sR);
                }
                std::sort(list.begin(),list.end());
d = list[w*h/2];
                list.clear();
            }
        }
        

The IPP implementation uses a fast median algorithm that estimates the median not by sorting a list, but by working on a histogram. Look at the IPPI manual for more detail.

IPP for floats

Currently the IPP implementation of 2D-median filtering for Ipp32f type is slower than the C++-implementation, so the C++-fallback is always used then.

Mask-Sizes

Although the fallback C++ implementation can work with arbitrary mask sizes, the Median will internally use odd mask dimension like 3x3 or 5x7. If an even width or height parameter is given to the Median constructor, the next higher odd value is used.

Benchmarks

table

3x3 5x5 51x51 51x3 3x51
icl8u, ipp ~1.8ms ~2.6ms ~292ms ~32.4ms ~328ms
icl8u, c++ ~2.6ms ~11.7ms ~323ms ~350ms ~47ms
icl16s, ipp ~2.7ms ~4ms ~21100ms ~338ms ~420ms
icl16s, c++ ~4.2ms ~16.2ms ~370ms ~384ms ~90ms
float, ipp ~25ms ~257ms ~?ms ~52000ms ~49000ms
float, c++ ~11.6ms ~39ms ~217000ms ~8700ms ~8700ms

Details

Test A 1000x1000 icl8u-image with IPP

Test B 1000x1000 icl8u-image no IPP

Test A 1000x1000 icl8u-image with IPP

Test B 1000x1000 icl16s-image no IPP

Test C 1000x1000 icl32f-image with IPP

Test C 1000x1000 icl32f-image no IPP

Example

Here is an examle, how to use the Median object.

create source and destination image
      Img8u src(640,480,3), *poDst=0;
acquire some image data
      ...
create the median object
      Median m(Size(5,5));
apply the median on the images - first call (slow)
destination image is renewed to 640x480x3 (memory allocation)
      m.apply(&src,&poDst);
enter iteration loop 
      while(1)
      {
aquire some new image data
          ...
apply the median filter (now fast, as no memory
allocation must be performed)
          m.apply(&src,&poDst);
further processing steps
          ...
      }
      

Constructor & Destructor Documentation

icl::filter::MedianOp::MedianOp ( const utils::Size maskSize) [inline]

Constructor that creates a median filter object, with specified mask size.

Parameters:
maskSizeof odd width and height Even width or height is increased to next higher odd value.

Member Function Documentation

virtual utils::Size icl::filter::MedianOp::adaptSize ( const utils::Size size) [inline, virtual]

ensures that mask width and height are odd

This is a workaround, necessary because of an ipp Bug that allows no even mask sizes here!

Parameters:
sizesize to adjust
Returns:
adjusted size (width and height are rounded up to the next higher odd value

Reimplemented from icl::filter::NeighborhoodOp.

void icl::filter::MedianOp::apply ( const core::ImgBase poSrc,
core::ImgBase **  ppoDst 
) [virtual]

applies the median operation on poSrc and stores the result in poDst

The depth, channel count and size of poDst is adapted to poSrc' ROI:

Parameters:
poSrcsource image
ppoDstpointer to destination image

Implements icl::filter::UnaryOp.


The documentation for this class was generated from the following file:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines