image_funcs.h

Go to the documentation of this file.
00001 //
00002 // Generic image functions
00003 //
00004 // Bala Amavasai (bala@amavasai.org)
00005 // Mon Oct  1 15:41:44 BST 2001
00006 //
00007 // $Header: /cvs/mimas2/include/image_funcs.h,v 1.1.1.1 2005/08/09 15:37:45 engmb Exp $
00008 //
00009 
00010 #ifndef IMAGE_FUNCS_H
00011 #define IMAGE_FUNCS_H
00012 
00013 #include "mimasconfig.h"
00014 #include <cassert>
00015 #include <float.h>
00016 #include <iostream>
00017 #include <vector>
00018 #include <algorithm>
00019 #include <cstdlib>
00020 #include <values.h>
00021 #include <cmath>
00022 #include "image.h"
00023 #include "image_conv.h"
00024 #include "image_op.h"
00025 #include "rgba.h"
00026 #include "prop.h"
00027 #include "property_image.h"
00028 #include "image_draw.h"
00029 
00030 namespace mimas {
00031 
00032 template< typename T, typename TPtr >
00033 T min_val( const const_image_ref< T, TPtr > &image )
00034 {
00035   T retVal;
00036   if ( image.initialised() ) {
00037     int size = image.getWidth() * image.getHeight();
00038     retVal = *std::min_element( image.rawData(),
00039                                 image.rawData() + size );
00040   } else
00041     retVal = T();
00042   return retVal;
00043 }
00044 
00045 template< typename T, typename TPtr >
00046 T max_val( const const_image_ref< T, TPtr > &image )
00047 {
00048   T retVal;
00049   if ( image.initialised() ) {
00050     int size = image.getWidth() * image.getHeight();
00051     retVal = *std::max_element( image.rawData(),
00052                                 image.rawData() + size );
00053   } else
00054     retVal = T();
00055   return retVal;
00056 }
00057 
00058 template< typename T >
00059 image_ref< T > &normaliseIt( image_ref< T > &im,
00060                              const T &val1, const T &val2 )
00061 {
00062   _normalise< T > f( min_val( im ), max_val( im ), val1, val2 );
00063   return image_apply( im, im,
00064                       _multi_help1< T, T, _normalise< T > >( f ) );
00065 }
00066 
00067 template< typename T, typename TPtr >
00068 image< T > normalise( const const_image_ref< T, TPtr > &im,
00069                       const T &val1, const T &val2 )
00070 {
00071   if ( im.initialised() ) {// Image must not be empty.
00072     return image_func< T >( im,
00073                             _normalise< T >( min_val( im ),
00074                                              max_val( im ), val1, val2 ) );
00075   } else
00076     return image< T >();
00077 }
00078 
00079 template<typename T>
00080 void equaliseIt( image_ref<T> &imagein )
00081 {
00082 
00083     int H[256], TR[256];
00084 
00085     for (int count=0; count<256; count++)
00086   H[count]=0;
00087 
00088     int intensity;
00089     for (int j=0; j<imagein.getHeight(); j++)
00090         for (int i=0; i<imagein.getWidth(); i++)
00091   {
00092       intensity=imagein.pixel(i,j);
00093        assert( intensity <= 255 );
00094       H[intensity]+=1;
00095   }
00096     
00097    // convert to cumulative histogram 
00098     int imagesize=imagein.getWidth()*imagein.getHeight();
00099     for (int count=1; count<256; count++)
00100     {
00101   H[count]=H[count]+H[count-1];
00102   TR[count-1]=(255*H[count-1])/imagesize;
00103     }
00104     TR[255]=(255*H[255])/imagesize;
00105      
00106     for (int j=0; j<imagein.getHeight(); j++)
00107         for (int i=0; i<imagein.getWidth(); i++)
00108           imagein.pixel(i,j)=(T)TR[imagein.pixel(i,j)];
00109 }
00110 
00111 template< typename T >
00112 image_ref< T > &bilevelIt( image_ref< T > &im, T threshval,
00113                            T val1, T val2 )
00114 {
00115   std::binder2nd< _bilevel< T > > f( _bilevel< T >( val1, val2 ),
00116                                      threshval );
00117   return image_apply
00118     ( im, im,
00119       _multi_help1< T, T, std::binder2nd< _bilevel< T > > >( f ) );
00120 }
00121 
00122 template< typename T, typename TPtr >
00123 image< T > bilevel( const const_image_ref< T, TPtr > &im,
00124                     T threshval, T val1, T val2 )
00125 {
00126   return image_func< T >( im,
00127                           std::bind2nd( _bilevel< T >( val1, val2 ),
00128                                         threshval ) );
00129 }
00130 
00131 template< typename T >
00132 image_ref< T > &thresholdIt( image_ref< T > &im, T threshval )
00133 {
00134   std::binder2nd< _threshold< T > > f( _threshold< T >(), threshval );
00135   return image_apply
00136     ( im, im,
00137       _multi_help1< T, T, std::binder2nd< _threshold< T > > >( f ) );
00138 }
00139 
00140 template< typename T, typename TPtr >
00141 image< T > threshold( const const_image_ref< T, TPtr > &im, T threshval )
00142 {
00143   return image_func< T >( im, std::bind2nd( _threshold< T >(),
00144                                             threshval ) );
00145 }
00146 
00147 template< typename T >
00148 image_ref< T > &bilevel_doubleIt( image_ref< T > &im,
00149                                   T min, T max, T val1, T val2 )
00150 {
00151   _bilevel_double< T > f( val1, val2, min, max );
00152   return image_apply( im, im,
00153                       _multi_help1< T, T, _bilevel_double< T > >( f ) );
00154 }
00155 
00156 template< typename T, typename TPtr >
00157 image< T > bilevel_double( const const_image_ref< T, TPtr > &im,
00158                            T min, T max, T val1, T val2 )
00159 {
00160   return multi_func< T >( im.rawData(),
00161                           _bilevel_double< T >( val1, val2, min, max ) );
00162 }
00163 
00164 template<typename T, typename TPtr, typename U>
00165 void despeckleKuwahara( const const_image_ref< T, TPtr > &imagein,
00166                         image< U > &imageout )
00167 {
00168   if ( &imageout != &imagein )
00169     imageout.init(imagein.getWidth(),imagein.getHeight());
00170     
00171     U intensity;
00172     float m_ul, m_ur, m_ll, m_lr;
00173     float v_ul, v_ur, v_ll, v_lr;
00174     
00175     for (int y=0; y<imagein.getHeight(); y++)
00176   for (int x=0; x<imagein.getWidth(); x++)
00177   {
00178       if (y<2 || y>imagein.getHeight()-3 || x<2 || x>imagein.getWidth()-3)
00179       {
00180          imageout.pixel(x,y)=imagein.pixel(x,y);
00181     continue;
00182 
00183       }
00184 
00185 
00186       // mean
00187       m_ul=0.0; m_ur=0.0; m_ll=0.0; m_lr=0.0;
00188 
00189       for (int j=0; j<3; j++)
00190     for (int i=0; i<3; i++)
00191     {
00192         m_ul+=(float)imagein.pixel(x-2+i,y-2+j);
00193         m_ur+=(float)imagein.pixel(x+i,y-2+j);
00194         m_ll+=(float)imagein.pixel(x-2+i,y+j);
00195         m_lr+=(float)imagein.pixel(x+i,y+j);
00196     }
00197 
00198       m_ul=m_ul/9.0;
00199       m_ur=m_ur/9.0;
00200       m_ll=m_ll/9.0;
00201       m_lr=m_lr/9.0;
00202 
00203       
00204       // estimated variance
00205       v_ul=0.0; v_ur=0.0; v_ll=0.0; v_lr=0.0;
00206       
00207       for (int j=0; j<3; j++)
00208     for (int i=0; i<3; i++)
00209     {
00210         v_ul+=(((float)imagein.pixel(x-2+i,y-2+j)-m_ul)*((float)imagein.pixel(x-2+i,y-2+j)-m_ul));
00211         v_ur+=(((float)imagein.pixel(x+i,y-2+j)-m_ur)*((float)imagein.pixel(x+i,y-2+j)-m_ur));
00212         v_ll+=(((float)imagein.pixel(x-2+i,y+j)-m_ll)*((float)imagein.pixel(x-2+i,y+j)-m_ll));
00213         v_lr+=(((float)imagein.pixel(x+i,y+j)-m_lr)*((float)imagein.pixel(x+i,y+j)-m_lr));
00214     }
00215 
00216       intensity=(U)m_ul;
00217       intensity=v_ur<v_ul?(U)m_ur:intensity;
00218       intensity=v_ll<v_ur?(U)m_ll:intensity;
00219       intensity=v_lr<v_ll?(U)m_lr:intensity;
00220 
00221       imageout.pixel(x,y)=intensity;
00222   }  
00223 }
00224 
00225 
00226 template<typename T>
00227 void despeckleKuwaharaIt( image_ref<T> &imagein )
00228 {
00229     image<T> tempimage;
00230 
00231     despeckleKuwahara(imagein, tempimage);
00232 
00233     imagein = tempimage;
00234 }
00235 
00236 template< typename T, typename TPtr >
00237 image< T > gradSobelX( const const_image_ref< T, TPtr > &im )
00238 {
00239   const T sobelx1[1][3]={ {-1, 0, 1} };
00240   const T sobelx2[3][1]={ { 1 },
00241                           { 2 },
00242                           { 1 } };
00243   const_image_ref< T >
00244     filter1( &sobelx1[0][0], 3, 1 ),
00245     filter2( &sobelx2[0][0], 1, 3 );
00246   return correlate( correlate( im, filter1 ), filter2 );
00247 }
00248 
00249 
00250 template< typename T, typename TPtr >
00251 image< T > gradSobelY( const const_image_ref< T, TPtr > &im )
00252 {
00253   const T sobely1[3][1]={ { -1 },
00254                           {  0 },
00255                           {  1 } };
00256   const T sobely2[1][3]={ { 1, 2, 1} };
00257   const_image_ref< T >
00258     filter1( &sobely1[0][0], 1, 3 ),
00259     filter2( &sobely2[0][0], 3, 1 );
00260   return correlate( correlate( im, filter1 ), filter2 );
00261 }
00262 
00263 template< typename T, typename TPtr >
00264 image< T > edgeSobelSqr( const const_image_ref< T, TPtr > &im )
00265 {
00266   image< T >
00267     gradX( gradSobelX( im ) ),
00268     gradY( gradSobelY( im ) );
00269   return gradX * gradX + gradY * gradY;
00270 }
00271 
00272 template< typename T, typename TPtr >
00273 image< T > edgeSobelNorm( const const_image_ref< T, TPtr > &im )
00274 {
00275   return squareRoot( edgeSobelSqr( im ) );
00276 }
00277 
00278 // template<typename T, typename U>
00279 // void edgeSobelOrientation(const image<T> &imagein, image<U> &imageout)
00280 // {
00281 //     int  x,y, sx,sy;
00282 //     int  height, width;
00283 //     image<U> tempimage;
00284 //     float  sxIntensity, syIntensity;
00285 
00286 
00287 //     static float sobelx[3][3]={  { -1.0, -2.0,-1.0},
00288 //                                 {  0.0,  0.0, 0.0},
00289 //                                 {  1.0,  2.0, 1.0}};
00290 
00291 //     static float sobely[3][3]={  {-1.0, 0.0, 1.0},
00292 //                                  {-2.0, 0.0, 2.0},
00293 //                                  {-1.0, 0.0, 1.0}};
00294 
00295 //     height=imagein.getHeight();
00296 //     width=imagein.getWidth();
00297 //     tempimage.init(width,height);
00298 
00299 //     for(y=1;y<height-1;y++)
00300 //         for (x=1;x<width-1;x++)
00301 //         {
00302 //             sxIntensity=0.0; syIntensity=0.0;
00303 //             for(sx=0;sx<3;sx++)
00304 //                 for(sy=0;sy<3;sy++)
00305 //                 {
00306 //                     sxIntensity+=sobelx[sy][sx]*(float)imagein.pixel(x+sx-1,y+sy-1);
00307 //                     syIntensity+=sobely[sy][sx]*(float)imagein.pixel(x+sx-1,y+sy-1);
00308 //                 }
00309 //             if (sxIntensity==0.0)
00310 //               tempimage.pixel(x,y)=0.0;
00311 //             else
00312 //               tempimage.pixel(x,y)=atan(syIntensity/sxIntensity);
00313 
00314 
00315 //         }
00316 
00317 //     imageout = tempimage;
00318 // }
00319 
00320 template< typename T, typename TPtr >
00321 image< T > edgeLaplacian( const const_image_ref< T, TPtr > &im )
00322 {
00323   const T laplacian[3][3]={ {  0, -1,  0 },
00324                             { -1,  4, -1 },
00325                             {  0, -1,  0 } };
00326   const_image_ref< T > f( &laplacian[0][0], 3, 3 );
00327   return correlate( im, f );
00328 }
00329 
00332 template< typename T, typename TPtr >
00333 image< T > edgeLoG( const const_image_ref< T, TPtr > &imagein )
00334 {
00335   const T LoG[9][9]= { {   0,  0,  3,  2,  2,  2,  3,  0,  0},
00336                        {   0,  2,  3,  5,  5,  5,  3,  2,  0},
00337                        {   3,  3,  5,  3,  0,  3,  5,  3,  3},
00338                        {   2,  5,  3,-12,-23,-12,  3,  5,  2},
00339                        {   2,  5,  0,-23,-40,-23,  0,  5,  2},
00340                        {   2,  5,  3,-12,-23,-12,  3,  5,  2},
00341                        {   3,  3,  5,  3,  0,  3,  5,  3,  3},
00342                        {   0,  2,  3,  5,  5,  5,  3,  2,  0},
00343                        {   0,  0,  3,  2,  2,  2,  3,  0,  0} };
00344 
00345   const_image_ref< T > filter( &LoG[0][0], 9, 9 );
00346   image< T > tempimage( correlate( imagein, filter ) );
00347     
00348   /*static float LoG[5][5]={{  0.0, 0.0,-1.0, 0.0, 0.0},
00349                             {  0.0,-1.0,-2.0,-1.0, 0.0},
00350                             { -1.0,-2.0,16.0,-2.0,-1.0},
00351                             {  0.0,-1.0,-2.0,-1.0, 0.0},
00352                             {  0.0, 0.0,-1.0, 0.0, 0.0}};
00353   */
00354 
00355   bilevelIt( tempimage, (T)0, (T)255, (T)0 );
00356   
00357   image< T > imageout;
00358   imageout.init( imagein.getWidth(), imagein.getHeight() );
00359 
00360   // Shouldn't actually threshold - must check zero crossings
00361   for ( int y=4; y<imagein.getHeight()-4; y++ )
00362     for ( int x=4; x<imagein.getWidth()-4; x++ ) {
00363       if (tempimage.pixel(x,y)<=127) continue;
00364       if ( ( tempimage.pixel( x-1, y-1 ) > 127 ) ||
00365            ( tempimage.pixel( x-1, y   ) > 127 ) ||
00366            ( tempimage.pixel( x-1, y+1 ) > 127 ) ||
00367            ( tempimage.pixel( x  , y-1 ) > 127 ) ||
00368            ( tempimage.pixel( x  , y+1 ) > 127 ) ||
00369            ( tempimage.pixel( x+1, y-1 ) > 127 ) ||
00370            ( tempimage.pixel( x+1, y   ) > 127 ) ||
00371            ( tempimage.pixel( x+1, y+1 ) > 127 ) )
00372         imageout.pixel( x  , y   ) = 255;
00373     }
00374   return imageout;
00375 }
00376 
00377 // IMPORTANT NOTE
00378 // imagein1 is image at time t-1
00379 // imagein2 is image at time t
00380 template< typename T, typename T1Ptr, typename T2Ptr >
00381 image< T > edgeHaynesJain( const const_image_ref< T, T1Ptr > &imagein1,
00382                            const const_image_ref< T, T2Ptr > &imagein2 )
00383 {
00384     MMERROR( imagein2.getWidth () == imagein1.getWidth () &&
00385              imagein2.getHeight() == imagein1.getHeight(),
00386              mimasexception, , "image_funcs::edgeHaynesJain - "
00387              "size of input images do not match" );
00388 
00389     return absolute<T>( edgeSobelNorm<T>( imagein2 ) * ( imagein2 -
00390                                                          imagein1 ) );
00391 }
00392 
00393 
00394 template<typename T, typename TPtr, typename U>
00395 void halfResolution( const const_image_ref< T, TPtr > &imagein,
00396                      image_ref<U> &imageout)
00397 {
00398     // note that this is only an estimate!
00399     static float gauss[3][3]={  {  1.0,  2.0, 1.0},
00400                                {  2.0,  4.0, 2.0},
00401                                {  1.0,  2.0, 1.0}};
00402     static float gaussfac=(1.0/16.0);
00403 
00404     assert( &imageout != &imagein );
00405     imageout.init(imagein.getWidth()/2, imagein.getHeight()/2);
00406 
00407     for (int j=1; j<imagein.getHeight(); j+=2)
00408         for (int i=1; i<imagein.getWidth(); i+=2)
00409         {
00410             float tempval=0.0;
00411             for (int y=-1; y<=1; y++)
00412                 for (int x=-1; x<=1; x++)
00413                     tempval+=(imagein.pixel(i+x,j+y)*gauss[y+1][x+1]);
00414             imageout.pixel(i/2,j/2)=(U)(tempval*gaussfac);
00415         }
00416 }
00417 
00418 
00419 template<typename T>
00420 void halfResolutionIt( image_ref<T> &imagein )
00421 {
00422     image<T> tempimage;
00423 
00424     halfResolution(imagein, tempimage);
00425 
00426     imagein = tempimage;
00427 }
00428 
00429 // Note this assumes black edges on white background unlike halfResolution
00430 // above
00431 template<typename T, typename TPtr, typename U>
00432 void halfResolutionEdgePyramid( const const_image_ref< T, TPtr > &imagein,
00433                                 image<U> &imageout)
00434 {
00435   // set background colour of object to be white
00436   assert( &imageout != &imagein );
00437   imageout.init(imagein.getWidth()/2, imagein.getHeight()/2);
00438   imageout.fill(255);
00439 
00440     for (int j=1; j<imagein.getHeight(); j+=2)
00441         for (int i=1; i<imagein.getWidth(); i+=2)
00442         {
00443             int tempval=0;
00444       for (int y=-1; y<=1; y++)
00445                 for (int x=-1; x<=1; x++)
00446                     if (imagein.getPixel(i+x,j+y)>127)
00447       tempval=255;
00448       
00449       imageout.pixel(i/2,j/2)=(U)tempval;
00450         }
00451 }
00452 
00453 
00454 template<typename T>
00455 void halfResolutionEdgePyramidIt( image_ref<T> &imagein )
00456 {
00457     image<T> tempimage;
00458 
00459     halfResolutionEdgePyramid(imagein, tempimage);
00460 
00461     imagein = tempimage;
00462 }
00463 
00464 // 3x3 median despecking filter
00465 template< typename T, typename TPtr >
00466 void despeckleMedian( const const_image_ref<T,TPtr> &imagein,
00467                       image<T> &imageout)
00468 {
00469   std::vector<T> pixvals;
00470   assert( &imageout != &imagein );
00471   imageout.init(imagein.getWidth(),imagein.getHeight());
00472  
00473   for (int j=1; j<imagein.getHeight()-1; j++)
00474   for (int i=1; i<imagein.getWidth()-1; i++)
00475   {
00476       if (!pixvals.empty()) pixvals.clear();
00477       for (int y=-1; y<=1; y++)
00478     for (int x=-1; x<=1; x++)
00479         pixvals.push_back(imagein.pixel(i+x,j+y));
00480       
00481       sort(pixvals.begin(), pixvals.end());
00482       imageout.pixel(i,j)=pixvals[pixvals.size()/2];
00483   }
00484  
00485     for (int j=0; j<imagein.getHeight(); j++)
00486     {
00487       imageout.pixel(0,j) = imagein.pixel(0,j);
00488       imageout.pixel(imagein.getWidth()-1,j)=imagein.pixel(imagein.getWidth()-1,j);
00489     }
00490     
00491     for (int i=0; i<imagein.getWidth(); i++)
00492     {
00493       imageout.pixel(i,0)=imagein.pixel(i,0);
00494       imageout.pixel(i,imagein.getHeight()-1)=imagein.pixel(i,imagein.getHeight()-1);
00495     }
00496 }
00497  
00498 template<typename T>
00499 void despeckleMedianIt( image_ref<T> &imagein )
00500 {
00501     image<T> tempimage;
00502 
00503     despeckleMedian(imagein, tempimage);
00504 
00505     imagein = tempimage;
00506 }
00507 
00508 template<typename T>
00509 void chamfer(image_ref<T> &inimage)
00510 {
00511     int nw,n,ne,w,e,sw,s,se;
00512     int fp;
00513 
00514     for (int j=1; j<inimage.getHeight()-1; j++)
00515         for (int i=1; i<inimage.getWidth(); i++)
00516         {
00517             fp=inimage.pixel(i,j);
00518             nw=4+inimage.pixel(i-1,j-1);
00519             n=3+inimage.pixel(i,j-1);
00520             w=3+inimage.pixel(i-1,j);
00521             sw=4+inimage.pixel(i-1,j+1);
00522 
00523             fp=fp<nw?fp:nw;
00524             fp=fp<n?fp:n;
00525             fp=fp<w?fp:w;
00526             fp=fp<sw?fp:sw;
00527             inimage.pixel(i,j)=fp;
00528 
00529         }
00530 
00531     for (int j=inimage.getHeight()-2; j>0; j--)
00532         for (int i=inimage.getWidth()-2; i>=0; i--)
00533         {
00534             fp=inimage.pixel(i,j);
00535             ne=4+inimage.pixel(i+1,j-1);
00536             e=3+inimage.pixel(i+1,j);
00537             s=3+inimage.pixel(i,j+1);
00538             se=4+inimage.pixel(i+1,j+1);
00539 
00540             fp=fp<ne?fp:ne;
00541             fp=fp<e?fp:e;
00542             fp=fp<s?fp:s;
00543             fp=fp<se?fp:se;
00544             inimage.pixel(i,j)=fp;
00545 
00546         }
00547     
00548     for (int i=0; i<inimage.getWidth(); i++)
00549     {
00550       inimage.pixel(i,0)=inimage.pixel(i,1);
00551       inimage.pixel(i,inimage.getHeight()-1)=inimage.pixel(i,inimage.getHeight()-2);
00552     }
00553     
00554     for (int j=0; j<inimage.getHeight(); j++)
00555     {
00556       inimage.pixel(0,j)=inimage.pixel(1,j);
00557       inimage.pixel(inimage.getWidth()-1,j)=inimage.pixel(inimage.getWidth()-2,j);
00558     }
00559  }
00560 
00561 
00562 template<typename T,typename TPtr>
00563 void paethRotateRadian(const const_image_ref<T,TPtr> &imagein,
00564                        image<T> &imageout,
00565                        float radian)
00566 {
00567   assert( &imageout != &imagein );
00568   imageout.init(imagein.getWidth(),imagein.getHeight());
00569   imageout.fill(255);
00570 
00571     if (fabs(radian-M_PI)<1e-3) radian=radian<M_PI?M_PI-1e-3:M_PI+1e-3; // Quick hack to fix the problem when tan goes to infinity
00572     float s1=-tan(-radian/2.0);
00573     float s2=sin(-radian);
00574 
00575     float xr, yr;
00576     int x,y;
00577     for (int j=0; j<imageout.getHeight(); j++)
00578         for (int i=0; i<imageout.getWidth(); i++)
00579         {
00580             x=i-imageout.getWidth()/2;
00581             y=j-imageout.getHeight()/2;
00582             //x=i;
00583             //y=j;
00584 
00585             xr = (float)x + s1 * (float)y;
00586             yr = (float)y + s2 * xr;
00587             xr = xr + s1 * yr;
00588 
00589             xr+=(float)imageout.getWidth()/2;
00590             yr+=(float)imageout.getHeight()/2;
00591             imageout.pixel(i, j)=imagein.getPixel((int)xr,(int)yr);
00592             //imageout.setPixel(i,j, imagein.getPixel(i,j));
00593         }
00594 }
00595 
00596 template< typename T, typename T1Ptr, typename T2Ptr >
00597 void multiLevelCorrelation( const const_image_ref< T, T1Ptr > &edgemap,
00598                             const const_image_ref< T, T2Ptr > &objectedgemap,
00599                             int levels, int &x, int &y, float &corrval,
00600                             bool chamferObject)
00601 {
00602     image<T> object[levels], image[levels];
00603     
00604     image[0] = edgemap;
00605    // invert(image[0]);
00606 
00607     object[0] = objectedgemap;
00608    // invert(object[0]);
00609   
00610      for (int l=1; l<levels; l++)
00611     {
00612         halfResolutionEdgePyramid(image[l-1],image[l]);
00613         halfResolutionEdgePyramid(object[l-1],object[l]);
00614     }
00615     
00616     for (int l=0; l<levels; l++)
00617     {
00618       image[l] = (T)255 - image[l];
00619       object[l] = (T)255 - object[l];
00620   //image[l].display();
00621   //object[l].display();
00622   chamfer(image[l]);
00623   if (chamferObject) chamfer(object[l]);
00624     }
00625  
00626      int xmin = INT_MIN, ymin = INT_MIN;
00627     int xminsearch, xmaxsearch, yminsearch, ymaxsearch;
00628     float corr, mincorr;
00629 
00630     x=0; y=0;
00631     xminsearch=0;
00632     yminsearch=0;
00633     xmaxsearch=image[levels-1].getWidth();
00634     ymaxsearch=image[levels-1].getHeight();
00635 
00636     for (int l=levels-1; l>=0; l--)
00637     {
00638   //object[l].display();
00639   //image[l].display();
00640 
00641         mincorr=FLT_MAX;
00642         for (int j=yminsearch; j<ymaxsearch-object[l].getHeight(); j++)
00643             for (int i=xminsearch; i<xmaxsearch-object[l].getWidth(); i++)
00644             {
00645                 corr=0.0;
00646     int count=0;
00647                 for (int b=0; b<object[l].getHeight(); b++)
00648                     for (int a=0; a<object[l].getWidth(); a++)
00649                     {
00650                         if (!chamferObject) if (object[l].pixel(a,b)>127) continue;
00651                         corr+=(float)abs((int)image[l].pixel(i+a,j+b)-(int)object[l].pixel(a,b));
00652       count++;
00653                     }
00654 
00655     corr/=count;
00656                 if (corr<mincorr)
00657                 {
00658                     xmin=i; ymin=j;
00659                     mincorr=corr;
00660                 }
00661             }
00662 
00663         if (l!=0)
00664         {
00665             xminsearch=(xmin*2)-1-20;
00666             yminsearch=(ymin*2)-1-20;
00667 
00668             xmaxsearch=(xmin*2)-1+object[l-1].getWidth()+20;
00669             ymaxsearch=(ymin*2)-1+object[l-1].getHeight()+20;
00670 
00671             if (xminsearch<0) xminsearch=0;
00672             if (yminsearch<0) yminsearch=0;
00673 
00674             if (xmaxsearch>image[l-1].getWidth()) xmaxsearch=image[l-1].getWidth();
00675             if (ymaxsearch>image[l-1].getHeight()) ymaxsearch=image[l-1].getHeight();
00676         }
00677 
00678 
00679     }
00680 
00681     assert( xmin != INT_MIN && ymin != INT_MIN );
00682     x=xmin;
00683     y=ymin;
00684     corrval=mincorr;
00685 
00686 }
00687 
00688 template< typename T, typename T1Ptr, typename T2Ptr >
00689 void correlation( const const_image_ref<T> &imagein,
00690                   const const_image_ref<T> &templatein,
00691                   int &x, int &y, float &corrval)
00692 {
00693 
00694     int xmin = INT_MIN, ymin = INT_MIN;
00695     int xminsearch, xmaxsearch, yminsearch, ymaxsearch;
00696     float corr, mincorr;
00697 
00698     x=0; y=0;
00699     xminsearch=0;
00700     yminsearch=0;
00701     xmaxsearch=imagein.getWidth();
00702     ymaxsearch=imagein.getHeight();
00703 
00704     mincorr=FLT_MAX;
00705     for (int j=yminsearch; j<ymaxsearch-templatein.getHeight(); j++)
00706         for (int i=xminsearch; i<xmaxsearch-templatein.getWidth(); i++)
00707         {
00708             corr=0.0;
00709             for (int b=0; b<templatein.getHeight(); b++)
00710                 for (int a=0; a<templatein.getWidth(); a++)
00711                 {
00712                     //if (object[l].getPixel(a,b)>127) continue;
00713                     corr+=(float)abs((int)imagein.pixel(i+a,j+b)-(int)templatein.pixel(a,b));
00714                 }
00715 
00716             if (corr<mincorr)
00717             {
00718                 xmin=i; ymin=j;
00719                 mincorr=corr;
00720             }
00721         }
00722 
00723     assert( xmin != INT_MIN && ymin != INT_MIN );
00724     x=xmin;
00725     y=ymin;
00726     corrval=mincorr;
00727 
00728 }
00729 
00730 template<typename T, typename T1Ptr, typename T2Ptr >
00731 void correlationChamfer( const const_image_ref< T, T1Ptr > &imagein,
00732                          const const_image_ref< T, T2Ptr > &templatein,
00733                         int &x, int &y, float &corrval)
00734 {
00735 
00736     int xmin = INT_MIN, ymin = INT_MIN;
00737     int xminsearch, xmaxsearch, yminsearch, ymaxsearch;
00738     float corr, mincorr;
00739 
00740     x=0; y=0;
00741     xminsearch=0;
00742     yminsearch=0;
00743     xmaxsearch=imagein.getWidth();
00744     ymaxsearch=imagein.getHeight();
00745 
00746     mincorr=FLT_MAX;
00747     for (int j=yminsearch; j<ymaxsearch-templatein.getHeight(); j++)
00748         for (int i=xminsearch; i<xmaxsearch-templatein.getWidth(); i++)
00749         {
00750             corr=0.0;
00751             for (int b=0; b<templatein.getHeight(); b++)
00752                 for (int a=0; a<templatein.getWidth(); a++)
00753                 {
00754         if (templatein.pixel(a,b)>127) continue;
00755                     corr+=(float)abs((int)imagein.pixel(i+a,j+b)-(int)templatein.pixel(a,b));
00756                 }
00757 
00758             if (corr<mincorr)
00759             {
00760                 xmin=i; ymin=j;
00761                 mincorr=corr;
00762             }
00763         }
00764 
00765     assert( xmin != INT_MIN && ymin != INT_MIN );
00766     x=xmin;
00767     y=ymin;
00768     corrval=mincorr;
00769 
00770 }
00771 
00772 template<typename T>
00773 void rotationChamferCorrelationEdgeMap(image<T> &edgemap, image<T>
00774   &objectedgemap, int angle1, int angle2, int anglestep, int &x, int &y, int &outangle, float &corrval)
00775 {
00776     image<T> chamferedImage, rotatedObject, chamferedObject;
00777 
00778     chamferedImage = (T)255 - edgemap;
00779     chamfer(chamferedImage);
00780 
00781   
00782     objectedgemap = (T)255 - objectedgemap;
00783     // Make sure that object boundaries are white:
00784     drawLine(objectedgemap, 0,0,0,objectedgemap.getHeight()-1,255);
00785     drawLine(objectedgemap, objectedgemap.getWidth()-1,0,objectedgemap.getWidth()-1,objectedgemap.getHeight()-1,255);
00786     drawLine(objectedgemap, 0,0,objectedgemap.getWidth()-1,objectedgemap.getHeight()-1,255);
00787     drawLine(objectedgemap, 0,objectedgemap.getHeight()-1,objectedgemap.getWidth()-1,objectedgemap.getHeight()-1,255);
00788     //chamfer(objectedgemap);
00789 
00790     float cval;
00791     int tx,ty;
00792     corrval=FLT_MAX;
00793     for (int angle=angle1; angle<=angle2; angle+=anglestep)
00794     {
00795    rotatedObject = objectedgemap;
00796   //invert(rotatedObject);
00797   paethRotateRadian(rotatedObject,chamferedObject,(float)angle*M_PI/180.0);
00798   //chamfer(chamferedObject);
00799   correlationChamfer(chamferedImage, chamferedObject, tx, ty, cval);
00800 
00801   if (cval<corrval)
00802   {
00803       corrval=cval;
00804       x=tx;
00805       y=ty;
00806       outangle=angle;
00807   }
00808     }
00809 }
00810 
00811 template< typename T, typename TPtr >
00812 image< T > focusEnhance( const const_image_ref< T, TPtr > &im )
00813 {
00814   const T enhance[3][3]={ { -1,  0, -1 },
00815                           {  0,  7,  0 },
00816                           { -1,  0, -1 } };
00817   const_image_ref< T > filter( &enhance[0][0], 3, 3 );
00818   return normalise( correlate( im, filter ), (T)0, (T)255 );
00819 }
00820 
00821 template< typename T, typename TPtr >
00822 image< T > featureEnhance( const const_image_ref< T, TPtr > &im )
00823 {
00824   const T enhance[3][3]={ {  0, -1,  0 },
00825                           { -1, 10, -1 },
00826                           {  0, -1,  0 } };
00827   const_image_ref< T > filter( &enhance[0][0], 3, 3 );
00828   return normalise( correlate( im, filter ), (T)0, (T)255 );
00829 }
00830 
00831 template< typename T, typename TPtr >
00832 image< T > emboss( const const_image_ref< T, TPtr > &im )
00833 {
00834   const T diff[3][3]={ { -1,  0,  0 },
00835                        {  0,  0,  0 },
00836                        {  0,  0,  1 } };
00837   const_image_ref< T > filter( &diff[0][0], 3, 3 );
00838   return normalise( correlate( im, filter ), (T)0, (T)255 );
00839 }
00840 
00841 template< typename T, typename TPtr >
00842 image< T > softenHeavy( const const_image_ref< T, TPtr > &im )
00843 {
00844   const T median[3]={ 1, 1, 1 };
00845   const_image_ref< T >
00846     filterx( &median[0], 3, 1 ),
00847     filtery( &median[0], 1, 3 );
00848  return
00849    normalise( correlate( correlate( im, filterx ), filtery ),
00850               (T)0, (T)255 );
00851 }
00852 
00853 template< typename T, typename TPtr >
00854 image< T > softenMedium( const const_image_ref< T, TPtr > &im )
00855 {
00856   const T soften[3][3]={ {  1,  1,  1 },
00857                          {  1,  2,  1 },
00858                          {  1,  1,  1 } };
00859   const_image_ref< T > filter( &soften[0][0], 3, 3 );
00860   return normalise( correlate( im, filter ), (T)0, (T)255 );
00861 }
00862 
00863 template< typename T, typename TPtr >
00864 image< T > softenLight( const const_image_ref< T, TPtr > &im )
00865 {
00866   const T soften[3][3]={ {  6,  12,  6 },
00867                          { 12,  25, 12 },
00868                          {  6,  12,  6 } };
00869   const_image_ref< T > filter( &soften[0][0], 3, 3 );
00870   return normalise( correlate( im, filter ), (T)0, (T)255 );
00871 }
00872 
00873 template< typename T, typename TPtr >
00874 void oilPainting( const const_image_ref< T, TPtr > &imagein,
00875                   image<T> &imageout,
00876                   int regiondim)
00877 {
00878    const int fy=regiondim;
00879     const int fx=regiondim;
00880 
00881     assert( &imageout != &imagein );
00882     imageout.init(imagein.getWidth(),imagein.getHeight());
00883     
00884     for (int y=0; y<imagein.getHeight(); y++)
00885   for (int x=0; x<imagein.getWidth(); x++)
00886   {
00887       if (y-fy/2<0 || y+fy/2>imagein.getHeight()-1 || x-fx/2<0 || x+fx/2>imagein.getWidth()-1)
00888       {
00889          imageout.pixel(x,y)=imagein.pixel(x,y);
00890     continue;
00891       }
00892 
00893        std::vector<int> pixcolor(regiondim*regiondim);
00894        std::vector<int> graylevel(256);
00895     
00896       int count=0;
00897       for (int j=-fy/2; j<=fy/2; j++)
00898     for (int i=-fx/2; i<=fx/2; i++)
00899     {
00900         pixcolor[count]=imagein.pixel(x+i,y+j);
00901         graylevel[pixcolor[count]]+=1;
00902         
00903         count++;
00904     }
00905       
00906       count=0;
00907       int intensity=0, maxuse=0;
00908       for (int j=-fy/2; j<=fy/2; j++)
00909     for (int i=-fx/2; i<=fx/2; i++)
00910     {
00911         if (graylevel[pixcolor[count]]>maxuse)
00912         {
00913       maxuse=graylevel[pixcolor[count]];
00914       intensity=pixcolor[count];
00915         }
00916 
00917         count++;
00918     }
00919       
00920       imageout.pixel(x,y)=(T)(intensity);
00921   }
00922 
00923     
00924 }
00925 
00926 #ifdef HAVE_OPENGL
00927 template<typename T,typename TPtr>
00928 void displayWithOverlay( image_output< rgba< unsigned char > > &display,
00929                          const const_image_ref<T,TPtr>& im,
00930                          const property_image& pim)
00931 {
00932   image< rgba< unsigned char > > output;
00933   output.init( im.getWidth(), im.getHeight() );
00934     
00935   for( int j=0;j<im.getHeight();j++)
00936     for( int i=0;i<im.getWidth();i++) {
00937       prop_ptr p( pim.pixel(i,j) );
00938       if( p )
00939   p->draw( output, i, j, false);
00940     }
00941     
00942   for( int j=0;j<im.getHeight();j++)
00943     for( int i=0;i<im.getWidth();i++)
00944       if ( (int)output.pixel( i, j ) ==  0 ) {
00945   unsigned char value = (unsigned char)im.pixel( i, j );
00946   output.pixel( i, j ) =
00947     rgba< unsigned char >( value, value, value );
00948       };
00949           
00950   display << output;
00951 }
00952 #endif
00953 
00954 
00955 //some common features here with vector class ...
00956 //a cleverer man could probably use the same underlying base class
00957 //but for now it doesnt matter
00958  template< typename T, typename T1Ptr, typename T2Ptr >
00959 double dotProduct( const const_image_ref<T,T1Ptr> &im1,
00960                    const const_image_ref<T,T2Ptr> &im2 ) throw (mimasexception)
00961 {
00962   MMERROR( im1.getWidth() == im2.getWidth() &&
00963            im1.getHeight() == im2.getHeight(),
00964            mimasexception, ,
00965            "Can't (won't) compute the dot product of two images of "
00966            "differing sizes." );
00967 
00968   double result = 0.0;
00969 
00970   const int size = (signed)im1.getSize();
00971   const T
00972     *p = im1.rawData(),
00973     *q = im2.rawData();
00974 
00975   for ( int i=0; i<size; i++ )
00976     result += *p++ * *q++;
00977 
00978   return result;
00979 }
00980 
00988 template<
00989   typename T1, typename T2,
00990   typename TAPtr, typename TBPtr, typename TCPtr
00991 >
00992 image< bool > nonMaximaSuppression
00993   ( const const_image_ref< T1, TAPtr > &gradientX,
00994     const const_image_ref< T1, TBPtr > &gradientY,
00995     const const_image_ref< T2, TCPtr > &gradientSqr,
00996     T2 threshold );
00997 
00998 }
00999 
01000 #include "image_funcs.tcc"
01001 
01002 #endif

[GNU/Linux] [Qt] [Mesa] [STL] [Lapack] [Boost] [Magick++] [Xalan-C and Xerces-C] [doxygen] [graphviz] [FFTW] [popt] [xine] [Gnuplot] [gnu-arch] [gcc] [gstreamer] [autoconf/automake/make] [freshmeat.net] [opensource.org] [sourceforge.net] [MMVL]
mimas 2.1 - Copyright Mon Oct 30 11:31:17 2006, Bala Amavasai, Stuart Meikle, Arul Selvan, Fabio Caparrelli, Jan Wedekind, Manuel Boissenin, ...