Image Component Library (ICL)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Classes | Public Member Functions | Private Attributes
icl::filter::LUTOp3Channel< T > Class Template Reference

class for applying table look-up transformation to 3-channel integer-valued images More...

#include <LUTOp3Channel.h>

Inheritance diagram for icl::filter::LUTOp3Channel< T >:
icl::filter::UnaryOp icl::utils::Uncopyable icl::utils::Configurable

List of all members.

Classes

class  Plugin
 Internal plugin class for the LUTOp3Channel. More...

Public Member Functions

 LUTOp3Channel (Plugin *p=0, icl8u shift=0)
 creates a LUT object with given lut (LUT-mode)
virtual ~LUTOp3Channel ()
 Destructor.
virtual void apply (const core::ImgBase *src, core::ImgBase **dst)
 Common Filter apply function using current mode.
void setPlugin (Plugin *p)
 Sets a new plugin and re-calculates the internal LUT.
PluginremovePlugin ()
 removes the internal plugin so it is not deleted with the LUTOp

Private Attributes

core::Img< T > m_oLUT
 Image that holds the lut data.
Pluginm_poPlugin
 Current plugin pointer.
icl8u m_ucShift
 channel range increment (...)

Detailed Description

template<class T>
class icl::filter::LUTOp3Channel< T >

class for applying table look-up transformation to 3-channel integer-valued images

In many applications it is necessary to create a feature map on 3-channel input images. These feature map creation procedure can take much time, depending on the complexity of the calculated feature. In a very simple case for instance, the LUTOp3Channel can be used to create thresholded color-distance map using the the euclidean distance to a reference color and a threshold for each pixel of the source image. This operation can be applied on each input (r,g,b)-Tuple by the following function (which is basically implemented in the "'Plugin" structure nested in the LUTOp3Channel class:

        virtual T transform(icl8u v1, icl8u v2, icl8u v3){
          return ::sqrt( ::pow(r-m_aiRGB[0],2) + ::pow(g-m_aiRGB[1],2) + ::pow(b-m_aiRGB[2],2) ) / (::sqrt(3.0)) < thresh ? 255 : 0; 
        }

This virtual function can be reimplemented by special plugins to calculate custom LUT-accelerated maps on icl8u/icl16s and icl32s -source images. The source images must be at least integer-typed, as the LUT, which is used internally has only discrete entries.
It is recommended to work with icl8u input images to avoid illegal memory access when using the LUT.

Implementing the Configurable Interface

The following procedure is used to create the LUT internally;

        void create_lut(Plugin p, T lut[16777216]){
          for(int r = 0; r < 256; ++r){
            for(int g = 0; g < 256; ++g){
              for(int b = 0; b < 256; ++b){
                lut[r+ 256*g + 65536*b] = p.transform( r,g,b );
              }
            }
          } 
        }      

When the LUT is created internally, it can be used for fast feature map calculation using a simple table look-up:

        \#define CAST(x) Cast<srcT,icl8u>::cast(x)       
  
        template<class srcT, class dstT>
        void apply_lut_op_3(const Img<srcT> &src, Img<dstT> &dst, dstT *lut){
          const srcT * pSrcR = src.getData(0); 
          const srcT * pSrcG = src.getData(1); 
          const srcT * pSrcB = src.getData(2);
          dstT *pDst = dst.getData(0);
          dstT *pDstEnd = pDst+dst.getDim();
          while(pDst < pDstEnd){
            *pDst++  = lut[ CAST(*pSrcR++) + 256*CAST(*pSrcG++) + 65536*CAST(*pSrcB++) ];
          }
        }

Performance

As it can be seen in section Implementing the Configurable Interface, each pixel is transformed by a simple table look up, which is performed by 2 multiplications, 2 additions and a simple dereferencing. The more complex part of this calculation is done by the calls to the Cast-class template. This is necessary to avoid index overruns due to the higher range of all non-icl8u input images types. The performance is much better, when using icl8u input images, because the Cast- call is left out in this case.

Benchmarks

The default Plugins operation of threshold an implicitly created euclidean distance map takes about 18msec on an 640x480 3-channel icl8u input image. This can be accelerated by 61% to 11msec (1.6Mhz Pentium M) by using the LUTOp3Channel class. This benefit is not very high, but the euclidean distance function is only one possible function

\[ f:R^3~\rightarrow~R \]

which can be implemented using the 3 channel lut. Consider, that all of these possibly very complex operations will not take more then the above measured 11msec.

Optimization "Shift"

In some applications, it is sufficient to use a decreased resolution for each channel range. E.g. if we use only 7Bit per channel, we can reduce the LUT size from $2^{24} \mbox{bytes} = 16.8\mbox{MB}$ to $2^{21} \mbox{bytes} = 2.1\mbox{MB}$ further reduction of the quantization level of each channel to 6Bit results in a $2^{18} \mbox{bytes}=262\mbox{kB}$ LUT.
The benefit of this optimization is at first of course the saving of a large part of necessary memory, but in a second view, it also increases processing speed even beyond the speed enhancement achieved using a LUT. The reason for the speed advantage compared with the full size LUT can be explained by the cpu's cache management: When using a 16.8MB data array which is nearly randomly accessed, the data can not be cached permanently, so the cache flow in influenced negatively. The following table illustrates some benchmark results using different bit shifts, compared on a 640x480 rgb icl8u image.

Shift LUT size Time*
0 (no shift) 16.8MB 11ms
1 2.2MB 8ms
2 262kB 4.3ms
3 33kB 3.5ms
4 4kB 3.5ms
5 512 Bytes 3.5ms
6 64 Bytes 3.5ms
7 8 Bytes 3.5ms

A bit shift value of 2 seems to be the best compromise between data resolution vs. speed and not at least memory usage. But note: There are some applications, where the data resolution can not be scaled down using bit shifts.


Constructor & Destructor Documentation

template<class T >
icl::filter::LUTOp3Channel< T >::LUTOp3Channel ( Plugin p = 0,
icl8u  shift = 0 
)

creates a LUT object with given lut (LUT-mode)

Parameters:
pplugin to use for the creation of the internal lut. Note:the LUTOp3Channel takes the ownership of the given plugin
shiftsee Optimization "Shift"
template<class T >
virtual icl::filter::LUTOp3Channel< T >::~LUTOp3Channel ( ) [virtual]

Destructor.


Member Function Documentation

template<class T >
virtual void icl::filter::LUTOp3Channel< T >::apply ( const core::ImgBase src,
core::ImgBase **  dst 
) [virtual]

Common Filter apply function using current mode.

Parameters:
srcsource image
dstdestination image**

Implements icl::filter::UnaryOp.

template<class T >
Plugin* icl::filter::LUTOp3Channel< T >::removePlugin ( ) [inline]

removes the internal plugin so it is not deleted with the LUTOp

template<class T >
void icl::filter::LUTOp3Channel< T >::setPlugin ( Plugin p)

Sets a new plugin and re-calculates the internal LUT.

Parameters:
pplugin to use for the creation of the internal lut. Note:the LUTOp3Channel takes the ownership of the given plugin

Member Data Documentation

template<class T >
core::Img<T> icl::filter::LUTOp3Channel< T >::m_oLUT [private]

Image that holds the lut data.

template<class T >
Plugin* icl::filter::LUTOp3Channel< T >::m_poPlugin [private]

Current plugin pointer.

template<class T >
icl8u icl::filter::LUTOp3Channel< T >::m_ucShift [private]

channel range increment (...)


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