00001
00002
00003
00004
00005
00006
00007
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() ) {
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
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
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
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
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
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
00349
00350
00351
00352
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
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
00378
00379
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
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
00430
00431 template<typename T, typename TPtr, typename U>
00432 void halfResolutionEdgePyramid( const const_image_ref< T, TPtr > &imagein,
00433 image<U> &imageout)
00434 {
00435
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
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;
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
00583
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
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
00606
00607 object[0] = objectedgemap;
00608
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
00621
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
00639
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
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
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
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
00797 paethRotateRadian(rotatedObject,chamferedObject,(float)angle*M_PI/180.0);
00798
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
00956
00957
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