00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "stdafx.h"
00016
00017 #include <cfl/resource.h>
00018
00019 #include <Camera/InterfaceDll.h>
00020
00021 #include <cfl/ScanFilterFFTInverse.h>
00022 #include <cfl/ScanFilterClip.h>
00023 #include <cfl/ToolCilImage.h>
00024
00025 #include <cil/Math.h>
00026 #include <cil/Traits.h>
00027 #include <cil/FFTInverseImageFilter.h>
00028 #include <cil/RescaleIntensityImageFilter.h>
00029
00030 #pragma warning( disable : 4663 ) // template<> Class<type>
00031 #include <limits>
00032 #pragma warning( default : 4663 )
00033
00034 #undef min // use cil::min instead of macro
00035 #undef max // use cil::max instead of macro
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #ifdef _DEBUG
00050 #undef THIS_FILE
00051 static char THIS_FILE[]=__FILE__;
00052 #define new DEBUG_NEW
00053 #endif
00054
00055 #define CFL_SCHEMAVERSION_FILTERIFFT 0 // permanent storage schema version
00056
00057 LPCTSTR CScanFilterFFTInverse::m_lpcsFilterName = _T("Inverse-Fast-Fourier-Transform");
00058
00059 LPCTSTR CScanFilterFFTInverse::m_lpcsShortFilterName = _T( "FFT-1" );
00060
00061 IMPLEMENT_SERIAL( CScanFilterFFTInverse, CScanFilter, CFL_SCHEMAVERSION_FILTERIFFT)
00062
00063
00064
00065
00066 CScanFilterFFTInverse::CScanFilterFFTInverse()
00067 : m_lpsbTmp( new CScanBaseBuffer )
00068 {
00069
00070
00071 m_csFilterName = m_lpcsFilterName;
00072 }
00073
00074
00075
00076
00077 CScanFilterFFTInverse::~CScanFilterFFTInverse()
00078 {
00079
00080
00081 delete m_lpsbTmp;
00082 ;
00083 }
00084
00085
00086
00087
00088 BOOL CScanFilterFFTInverse::CanDoDialogEntry() const
00089 {
00090 return FALSE;
00091 }
00092
00093
00094
00095
00096
00097 void CScanFilterFFTInverse::Serialize(CArchive& ar)
00098 {
00099 CScanFilter::Serialize( ar );
00100
00101 if ( ar.IsStoring() )
00102 {
00103 ;
00104 }
00105 else
00106 {
00107 ;
00108 }
00109 };
00110
00111
00112
00113
00114 #pragma warning( push )
00115 #pragma warning( disable : 4100 ) // unreferenced formal parameter
00116
00117 BOOL CScanFilterFFTInverse::SetParameters(LPCTSTR lpParameters)
00118 {
00119 return TRUE;
00120 }
00121
00122 #pragma warning( pop )
00123
00124
00125
00126
00127 LPCTSTR CScanFilterFFTInverse::GetParameters() const
00128 {
00129 return NULL;
00130 }
00131
00132
00133
00134
00135
00136
00137 BOOL CScanFilterFFTInverse::Apply()
00138 {
00139
00140
00141 if ( Q_INVALID( NULL == m_lpsbIn && "ensure input buffer") )
00142 return FALSE;
00143
00144 if ( Q_INVALID( NULL == m_lpsbTmp ) && "ensure valid temporary buffer" )
00145 return FALSE;
00146
00147 if ( Q_INVALID( NULL == m_lpsbOut && "ensure output buffer" ) )
00148 return FALSE;
00149
00150 if ( Q_INVALID( !m_lpsbIn->IsCompleteFrame() && "ensure complete frame" ) )
00151 return FALSE;
00152
00153
00154
00155
00156 Q_RETURN( m_lpsbTmp->CreateOutputBufferFor( *m_lpsbIn ) );
00157
00158 m_lpsbTmp->m_csBufferName = m_lpsbIn->m_csBufferName + _T(" - ") + m_lpcsShortFilterName;
00159 m_lpsbTmp->m_csDataName.Format(_T("%s(%s)"), m_lpcsShortFilterName, m_lpsbIn->m_csDataName );
00160
00161
00162
00163
00164
00165 CProgressDlg dlg( AfxGetMainWnd() );
00166
00167 ThreadArgs threadArgs( &dlg, this );
00168
00169 CWinThread *hThread = AfxBeginThread(
00170 ComputationThreadFunction,
00171 &threadArgs,
00172 THREAD_PRIORITY_BELOW_NORMAL,
00173 0,
00174
00175 CREATE_SUSPENDED,
00176 NULL
00177 );
00178
00179
00180
00181
00182 if ( dlg.DoModal( hThread ) <= 0 )
00183 {
00184 return FALSE;
00185 };
00186
00187
00188
00189
00190 return threadArgs.bReturn;
00191 }
00192
00193
00194
00195
00196 UINT CScanFilterFFTInverse::ComputationThreadFunction( LPVOID lpContext )
00197 {
00198
00199
00200 CScanFilterFFTInverse::ThreadArgs *lpTreadArgs = static_cast< CScanFilterFFTInverse::ThreadArgs* >( lpContext );
00201
00202 lpTreadArgs->bReturn = lpTreadArgs->pThis->Compute( lpTreadArgs->pDlg );
00203
00204 lpTreadArgs->pDlg->Terminate();
00205
00206 return lpTreadArgs->bReturn;
00207 }
00208
00209
00210
00211
00212 BOOL CScanFilterFFTInverse::Compute( CProgressDlg *pDlg )
00213 {
00214
00215
00216 ASSERT( m_lpsbIn );
00217 ASSERT( m_lpsbTmp );
00218 ASSERT( m_lpsbOut );
00219
00220
00221
00222
00223 BOOL bL2R = m_lpsbIn->HasLeftToRightScan();
00224 BOOL bR2L = m_lpsbIn->HasRightToLeftScan();
00225
00226
00227
00228
00229 pDlg->SetText ( _T("Computing 2D inverse fast fourier transformation" ) );
00230 pDlg->SetRange( 0, bR2L && bL2R ? 2: 1 );
00231
00232
00233
00234
00235 if ( bL2R && 0 == m_lpsbIn->m_pdFourierL2R ||
00236 bR2L && 0 == m_lpsbIn->m_pdFourierR2L )
00237 {
00238 MessageBox(
00239 IsInteractive() ? m_pDlg->m_hWnd : AfxGetMainWnd()->m_hWnd,
00240 _T( "This scanbuffer does not contain a fourier spectrum." ),
00241 _T( "Cannot transform" ),
00242 MB_ICONEXCLAMATION | MB_OK
00243 );
00244
00245 return FALSE;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255 Q_RETURN( m_lpsbTmp->CopyFourierBufferFrom( *m_lpsbIn ) );
00256
00257
00258
00259
00260 int progress = 0;
00261
00262 if ( bL2R )
00263 {
00264 ComputePart( m_lpsbTmp->FourierDataL2R(), ToImage( m_lpsbTmp, false ) );
00265
00266 pDlg->SetPos( ++progress );
00267 }
00268
00269 if ( bR2L )
00270 {
00271 ComputePart( m_lpsbTmp->FourierDataR2L(), ToImage( m_lpsbTmp, true ) );
00272
00273 pDlg->SetPos( ++progress );
00274 }
00275
00276
00277
00278
00279
00280 m_lpsbTmp->DeleteFourierBuffer();
00281
00282
00283
00284
00285 Q_RETURN( CropImage() );
00286
00287
00288
00289
00290 m_lpsbOut->m_csBufferName.Format( _T("%s - %s"), m_lpsbIn->m_csBufferName, m_lpcsShortFilterName );
00291
00292
00293
00294
00295 if ( pDlg->StopRequested() )
00296 {
00297 return FALSE;
00298 }
00299 else
00300 {
00301 return TRUE;
00302 }
00303 }
00304
00305
00306
00307
00308 void CScanFilterFFTInverse::ComputePart( FourierElementType** pFFT, Image& dst )
00309 {
00310 using cil::Size2D;
00311
00312 typedef std::complex< FourierElementType > Complex;
00313
00314 typedef cil::Image< Complex > FFTImageType;
00315 typedef cil::Image< FourierElementType > IFFTImageType;
00316 typedef Image OutputImageType;
00317
00318 typedef cil::FFTInverseImageFilter < FFTImageType , IFFTImageType > FFTInverseImageFilter;
00319 typedef cil::RescaleIntensityImageFilter < IFFTImageType, OutputImageType > RescaleIntensityImageFilter;
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 Size2D fftSize( Size2D( dst.Width(), dst.Height() ) );
00335 FFTImageType fftImage( reinterpret_cast<FFTImageType::PixelType*>( cil::To1DView( pFFT ) ), fftSize );
00336
00337 IFFTImageType ifftImage;
00338
00339
00340
00341
00342 FFTInverseImageFilter fftiFilter;
00343 fftiFilter.Apply( fftImage, ifftImage );
00344
00345
00346
00347
00348 RescaleIntensityImageFilter scaleFilter;
00349 scaleFilter.SetOutputMinimum( lpm::NumericTraits< OutputImageType::ValueType >::Min() );
00350 scaleFilter.SetOutputMaximum( lpm::NumericTraits< OutputImageType::ValueType >::Max() );
00351 scaleFilter.Apply( ifftImage, dst );
00352 }
00353
00354
00355
00356
00357 BOOL CScanFilterFFTInverse::CropImage()
00358 {
00359 typedef CScanFilterClip CropFilter;
00360
00361 CropFilter cropFilter;
00362
00363 cropFilter.SetDragInput ( false, GetUsedRectangle() );
00364 cropFilter.SetInputBuffer ( 0, m_lpsbTmp );
00365 cropFilter.SetOutputBuffer( 0, m_lpsbOut );
00366
00367 return cropFilter.Apply();
00368 }
00369
00370
00371
00372
00373 bool CScanFilterFFTInverse::HasNonzeroEdge() const
00374 {
00375 Pointer data = m_lpsbTmp->Data();
00376 SizeType ncol = m_lpsbTmp->Columns();
00377 SizeType size = m_lpsbTmp->GetFrameSize();
00378
00379 return 0 != data[ 0 ]
00380 || 0 != data[ ncol - 1 ]
00381 || 0 != data[ size - ncol - 1 ]
00382 || 0 != data[ size - 1 ];
00383 }
00384
00385
00386
00387
00388
00389
00390 CRect CScanFilterFFTInverse::GetUsedRectangle() const
00391 {
00392 typedef Pointer Iterator;
00393
00394 #ifdef _CIL_MSC_6
00395 typedef std::reverse_iterator<Pointer, ValueType> ReverseIterator;
00396 #else
00397 typedef std::reverse_iterator<Pointer> ReverseIterator;
00398 #endif
00399
00400 SizeType nrow = m_lpsbTmp->Rows();
00401 SizeType ncol = m_lpsbTmp->Columns();
00402 SizeType size = m_lpsbTmp->GetFrameSize();
00403
00404
00405
00406
00407 SizeType left = 0;
00408 SizeType right = ncol - 0;
00409 SizeType top = 0;
00410 SizeType bottom = nrow - 0;
00411
00412 #ifdef USE_FULL_IFFT
00413 return CRect( left, top, right, bottom );
00414 #endif
00415
00416
00417
00418
00419 if ( HasNonzeroEdge() )
00420 {
00421 return CRect( left, top, right, bottom );
00422 }
00423
00424
00425
00426
00427 Iterator itopleft = m_lpsbTmp->Data();
00428 Iterator imidleft = itopleft + size / 2;
00429 Iterator icenter = imidleft + ncol / 2;
00430 Iterator ibotright = itopleft + size;
00431
00432
00433
00434
00435 Iterator pos = std::find_if(
00436 itopleft,
00437 icenter ,
00438 std::bind2nd( std::not_equal_to<ValueType>(), 0 )
00439 );
00440
00441 if ( pos != icenter )
00442 {
00443 top = 0 + ( pos - itopleft ) / ncol;
00444 }
00445
00446
00447
00448
00449 ReverseIterator rpos = std::find_if(
00450 ReverseIterator( ibotright ),
00451 ReverseIterator( icenter ),
00452 std::bind2nd( std::not_equal_to<ValueType>(), 0 )
00453 );
00454
00455 if ( rpos != ReverseIterator( icenter ) )
00456 {
00457 bottom = nrow - ( rpos - ReverseIterator( ibotright ) ) / ncol;
00458 }
00459
00460
00461
00462
00463
00464 for ( Iterator icol = itopleft; icol < itopleft + ncol / 2; ++icol )
00465 {
00466 for ( Iterator it = icol; it < icenter; it += ncol )
00467 {
00468 if ( 0 != *it )
00469 {
00470 left = 0 + ( it - itopleft ) % ncol;
00471 goto foundLeft;
00472 }
00473 }
00474 }
00475 foundLeft: ;
00476
00477
00478
00479
00480
00481 for ( ReverseIterator ricol = ReverseIterator( ibotright );
00482 ricol < ReverseIterator( itopleft + ncol / 2 ); ++ricol )
00483 {
00484 for ( ReverseIterator it = ricol; it < ReverseIterator( icenter ); it += ncol )
00485 {
00486 if ( 0 != *it )
00487 {
00488 right = ncol - ( it - ReverseIterator( ibotright ) ) % ncol;
00489 goto foundRight;
00490 }
00491 }
00492 }
00493 foundRight: ;
00494
00495 return CRect( left, top, right, bottom );
00496 }
00497
00498
00499
00500
00501