Image Component Library (ICL)
|
Class that provides median filter abilities \. More...
#include <MedianOp.h>
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 |
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. The fallback implementation 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.
Currently the IPP supports no 2D-median filtering for Ipp32f type, so the C++-fallback is used then.
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.
3x3 | 5x5 | 51x51 | 51x3 | 3x51 | |
icl8u, ipp | ~5ms | ~32ms | ~434ms | ~38ms | ~430ms |
icl8u, c++ | ~146ms | ~334ms | ~84000ms | ~3400ms | ~3500ms |
float, c++ | ~181ms | ~464ms | ~115000ms | ~4600ms | ~4700ms |
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 ... }
icl::filter::MedianOp::MedianOp | ( | const utils::Size & | maskSize | ) | [inline] |
Constructor that creates a median filter object, with specified mask size.
maskSize | of odd width and height Even width or height is increased to next higher odd value. |
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!
size | size to adjust |
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:
poSrc | source image |
ppoDst | pointer to destination image |
Implements icl::filter::UnaryOp.