00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef __itkBoxUtilities_h
00019 #define __itkBoxUtilities_h
00020 #include "itkProgressReporter.h"
00021 #include "itkShapedNeighborhoodIterator.h"
00022 #include "itkImageRegionConstIterator.h"
00023 #include "itkImageRegionIterator.h"
00024 #include "itkConstantBoundaryCondition.h"
00025 #include "itkImageRegionIteratorWithIndex.h"
00026 #include "itkImageRegionIterator.h"
00027 #include "itkImageRegionConstIterator.h"
00028 #include "itkOffset.h"
00029 #include "itkNumericTraits.h"
00030 #include "itkNeighborhoodAlgorithm.h"
00031 #include "itkShapedNeighborhoodIterator.h"
00032 #include "itkZeroFluxNeumannBoundaryCondition.h"
00033
00034 namespace itk {
00035
00036 template< class TIterator >
00037 TIterator*
00038 setConnectivityEarlyBox( TIterator* it, bool fullyConnected=false )
00039 {
00040
00041 typename TIterator::OffsetType offset;
00042 it->ClearActiveList();
00043 if( !fullyConnected)
00044 {
00045
00046
00047 offset.Fill( 0 );
00048 for( unsigned int d=0; d < TIterator::Dimension; ++d )
00049 {
00050 offset[d] = -1;
00051 it->ActivateOffset( offset );
00052 offset[d] = 0;
00053 }
00054 }
00055 else
00056 {
00057
00058
00059 unsigned int centerIndex = it->GetCenterNeighborhoodIndex();
00060 for( unsigned int d=0; d < centerIndex; d++ )
00061 {
00062 offset = it->GetOffset( d );
00063
00064 bool keep = true;
00065 for (unsigned i = 0; i < TIterator::Dimension; i++)
00066 {
00067 if (offset[i] > 0)
00068 {
00069 keep = false;
00070 break;
00071 }
00072 }
00073 if (keep)
00074 {
00075 it->ActivateOffset( offset );
00076 }
00077 }
00078 offset.Fill(0);
00079 it->DeactivateOffset( offset );
00080 }
00081 return it;
00082 }
00083
00084 template <class TInputImage, class TOutputImage>
00085 void
00086 BoxAccumulateFunction(const TInputImage * inputImage,
00087 const TOutputImage * outputImage,
00088 typename TInputImage::RegionType inputRegion,
00089 typename TOutputImage::RegionType outputRegion,
00090 ProgressReporter &progress)
00091 {
00092
00093 typedef TInputImage InputImageType;
00094 typedef typename TInputImage::RegionType RegionType;
00095 typedef typename TInputImage::SizeType SizeType;
00096 typedef typename TInputImage::IndexType IndexType;
00097 typedef typename TInputImage::PixelType PixelType;
00098 typedef typename TInputImage::OffsetType OffsetType;
00099 typedef TOutputImage OutputImageType;
00100 typedef typename TOutputImage::PixelType OutputPixelType;
00101 typedef typename TInputImage::PixelType InputPixelType;
00102
00103 typedef ImageRegionConstIterator<TInputImage> InputIterator;
00104 typedef ImageRegionIterator<TOutputImage> OutputIterator;
00105
00106 typedef ShapedNeighborhoodIterator<TOutputImage> NOutputIterator;
00107 InputIterator inIt( inputImage, inputRegion);
00108 typename TInputImage::SizeType kernelRadius;
00109 kernelRadius.Fill(1);
00110
00111 NOutputIterator noutIt( kernelRadius, outputImage, outputRegion);
00112
00113 setConnectivityEarlyBox( &noutIt, true );
00114
00115 ConstantBoundaryCondition<OutputImageType> oBC;
00116 oBC.SetConstant( NumericTraits< OutputPixelType >::Zero );
00117 noutIt.OverrideBoundaryCondition(&oBC);
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 std::vector<int> Weights;
00128 typename NOutputIterator::ConstIterator sIt;
00129 for( typename NOutputIterator::IndexListType::const_iterator idxIt = noutIt.GetActiveIndexList().begin();
00130 idxIt != noutIt.GetActiveIndexList().end();
00131 idxIt++ )
00132 {
00133 OffsetType offset = noutIt.GetOffset(*idxIt);
00134 int w = -1;
00135 for (unsigned k = 0; k < InputImageType::ImageDimension; k++)
00136 {
00137 if (offset[k] != 0)
00138 w *= offset[k];
00139 }
00140
00141 Weights.push_back(w);
00142 }
00143
00144 for (inIt.GoToBegin(), noutIt.GoToBegin(); !noutIt.IsAtEnd(); ++inIt, ++noutIt )
00145 {
00146 OutputPixelType Sum = 0;
00147 int k;
00148 for (k = 0, sIt = noutIt.Begin(); !sIt.IsAtEnd();++sIt, ++k)
00149 {
00150 Sum += sIt.Get() * Weights[k];
00151 }
00152 noutIt.SetCenterPixel(Sum + inIt.Get());
00153 progress.CompletedPixel();
00154 }
00155 }
00156
00157
00158 template <class ImType>
00159 std::vector<typename ImType::OffsetType> CornerOffsets(const ImType * im)
00160 {
00161 typedef ShapedNeighborhoodIterator<ImType> NIterator;
00162 typename ImType::SizeType unitradius;
00163 unitradius.Fill(1);
00164 NIterator N1(unitradius, im, im->GetRequestedRegion());
00165 unsigned int centerIndex = N1.GetCenterNeighborhoodIndex();
00166 typename NIterator::OffsetType offset;
00167 std::vector<ITK_TYPENAME ImType::OffsetType> result;
00168 for( unsigned int d=0; d < centerIndex*2 + 1; d++ )
00169 {
00170 offset = N1.GetOffset( d );
00171
00172 bool corner = true;
00173 for (unsigned k = 0; k < ImType::ImageDimension; k++)
00174 {
00175 if (offset[k] == 0)
00176 {
00177 corner = false;
00178 break;
00179 }
00180 }
00181 if (corner)
00182 result.push_back(offset);
00183 }
00184 return(result);
00185 }
00186
00187 template <class TInputImage, class TOutputImage>
00188 void
00189 BoxMeanCalculatorFunction(const TInputImage * accImage,
00190 TOutputImage * outputImage,
00191 typename TInputImage::RegionType inputRegion,
00192 typename TOutputImage::RegionType outputRegion,
00193 typename TInputImage::SizeType Radius,
00194 ProgressReporter &progress)
00195 {
00196
00197 typedef TInputImage InputImageType;
00198 typedef typename TInputImage::RegionType RegionType;
00199 typedef typename TInputImage::SizeType SizeType;
00200 typedef typename TInputImage::IndexType IndexType;
00201 typedef typename TInputImage::PixelType PixelType;
00202 typedef typename TInputImage::OffsetType OffsetType;
00203 typedef TOutputImage OutputImageType;
00204 typedef typename TOutputImage::PixelType OutputPixelType;
00205 typedef typename TInputImage::PixelType InputPixelType;
00206
00207 typedef NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType>
00208 FaceCalculatorType;
00209 typedef typename FaceCalculatorType::FaceListType FaceListType;
00210 typedef typename FaceCalculatorType::FaceListType::iterator FaceListTypeIt;
00211 FaceCalculatorType faceCalculator;
00212
00213 FaceListType faceList;
00214 FaceListTypeIt fit;
00215 ZeroFluxNeumannBoundaryCondition<TInputImage> nbc;
00216
00217
00218
00219 SizeType kernelSize, internalRadius, RegionLimit;
00220 IndexType RegionStart = inputRegion.GetIndex();
00221 for( int i=0; i<TInputImage::ImageDimension; i++ )
00222 {
00223 kernelSize[i] = Radius[i] * 2 + 1;
00224 internalRadius[i] = Radius[i] + 1;
00225 RegionLimit[i] = inputRegion.GetSize()[i] + RegionStart[i] - 1;
00226 }
00227
00228 typedef typename NumericTraits<OutputPixelType>::RealType AccPixType;
00229
00230 std::vector<OffsetType> UnitCorners = CornerOffsets<TInputImage>(accImage);
00231 std::vector<OffsetType> RealCorners;
00232 std::vector<AccPixType> Weights;
00233
00234 for (unsigned k = 0; k < UnitCorners.size(); k++)
00235 {
00236 int prod = 1;
00237 OffsetType ThisCorner;
00238 for (unsigned i = 0; i < TInputImage::ImageDimension; i++)
00239 {
00240 prod *= UnitCorners[k][i];
00241 if (UnitCorners[k][i] > 0)
00242 {
00243 ThisCorner[i] = Radius[i];
00244 }
00245 else
00246 {
00247 ThisCorner[i] = -(Radius[i]+1);
00248 }
00249 }
00250 Weights.push_back((AccPixType)prod);
00251 RealCorners.push_back(ThisCorner);
00252 }
00253
00254
00255 faceList = faceCalculator(accImage, outputRegion, internalRadius);
00256
00257 for (fit = faceList.begin(); fit != faceList.end(); ++fit)
00258 {
00259 if (fit == faceList.begin())
00260 {
00261
00262
00263
00264 AccPixType pixelscount = 1;
00265 for (unsigned i = 0; i < TInputImage::ImageDimension; i++)
00266 {
00267 pixelscount *= (AccPixType)(2*Radius[i] + 1);
00268 }
00269
00270 typedef ImageRegionIterator<OutputImageType> OutputIteratorType;
00271 typedef ImageRegionConstIterator<InputImageType> InputIteratorType;
00272
00273 typedef std::vector<InputIteratorType> CornerItVecType;
00274 CornerItVecType CornerItVec;
00275
00276 for (unsigned k = 0; k < RealCorners.size(); k++)
00277 {
00278 typename InputImageType::RegionType tReg=(*fit);
00279 tReg.SetIndex(tReg.GetIndex() + RealCorners[k]);
00280 InputIteratorType tempIt(accImage, tReg);
00281 tempIt.GoToBegin();
00282 CornerItVec.push_back(tempIt);
00283 }
00284
00285 OutputIteratorType oIt(outputImage, *fit);
00286
00287 for (oIt.GoToBegin(); !oIt.IsAtEnd(); ++oIt)
00288 {
00289 AccPixType Sum = 0;
00290
00291 for (unsigned k = 0; k < CornerItVec.size(); k++)
00292 {
00293 Sum += Weights[k] * CornerItVec[k].Get();
00294
00295 ++(CornerItVec[k]);
00296 }
00297 oIt.Set(static_cast<OutputPixelType>(Sum/pixelscount));
00298 progress.CompletedPixel();
00299 }
00300 }
00301 else
00302 {
00303
00304 typedef ImageRegionIteratorWithIndex<OutputImageType> OutputIteratorType;
00305 OutputIteratorType oIt(outputImage, *fit);
00306
00307 for (oIt.GoToBegin(); !oIt.IsAtEnd(); ++oIt)
00308 {
00309
00310
00311
00312 RegionType currentKernelRegion;
00313 currentKernelRegion.SetSize( kernelSize );
00314
00315 IndexType kernelRegionIdx = oIt.GetIndex();
00316 IndexType CentIndex = kernelRegionIdx;
00317 for( int i=0; i<TInputImage::ImageDimension; i++ )
00318 {
00319 kernelRegionIdx[i] -= Radius[i];
00320 }
00321 currentKernelRegion.SetIndex( kernelRegionIdx );
00322 currentKernelRegion.Crop( inputRegion );
00323 long edgepixelscount = currentKernelRegion.GetNumberOfPixels();
00324 AccPixType Sum = 0;
00325
00326
00327
00328
00329
00330
00331
00332
00333 for (unsigned k = 0; k < RealCorners.size(); k++)
00334 {
00335 IndexType ThisCorner = CentIndex + RealCorners[k];
00336 bool IncludeCorner = true;
00337 for (unsigned j = 0; j < TInputImage::ImageDimension; j++)
00338 {
00339 if (UnitCorners[k][j] > 0)
00340 {
00341
00342 ThisCorner[j] = vnl_math_min(ThisCorner[j], (long)RegionLimit[j]);
00343 }
00344 else
00345 {
00346
00347 if (ThisCorner[j] < RegionStart[j])
00348 {
00349 IncludeCorner = false;
00350 break;
00351 }
00352 }
00353 }
00354 if (IncludeCorner)
00355 {
00356 Sum += accImage->GetPixel(ThisCorner) * Weights[k];
00357 }
00358 }
00359
00360 oIt.Set(static_cast<OutputPixelType>(Sum/(AccPixType)edgepixelscount));
00361 progress.CompletedPixel();
00362 }
00363 }
00364 }
00365 }
00366
00367
00368 template <class TInputImage, class TOutputImage>
00369 void
00370 BoxSigmaCalculatorFunction(const TInputImage * accImage,
00371 TOutputImage * outputImage,
00372 typename TInputImage::RegionType inputRegion,
00373 typename TOutputImage::RegionType outputRegion,
00374 typename TInputImage::SizeType Radius,
00375 ProgressReporter &progress)
00376 {
00377
00378 typedef TInputImage InputImageType;
00379 typedef typename TInputImage::RegionType RegionType;
00380 typedef typename TInputImage::SizeType SizeType;
00381 typedef typename TInputImage::IndexType IndexType;
00382 typedef typename TInputImage::PixelType PixelType;
00383 typedef typename TInputImage::OffsetType OffsetType;
00384 typedef TOutputImage OutputImageType;
00385 typedef typename TOutputImage::PixelType OutputPixelType;
00386 typedef typename TInputImage::PixelType InputPixelType;
00387 typedef typename InputPixelType::ValueType ValueType;
00388
00389 typedef typename NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType>
00390 FaceCalculatorType;
00391 typedef typename FaceCalculatorType::FaceListType FaceListType;
00392 typedef typename FaceCalculatorType::FaceListType::iterator FaceListTypeIt;
00393 FaceCalculatorType faceCalculator;
00394
00395 FaceListType faceList;
00396 FaceListTypeIt fit;
00397 ZeroFluxNeumannBoundaryCondition<TInputImage> nbc;
00398
00399
00400
00401 SizeType kernelSize, internalRadius, RegionLimit;
00402 IndexType RegionStart = inputRegion.GetIndex();
00403 for( int i=0; i<TInputImage::ImageDimension; i++ )
00404 {
00405 kernelSize[i] = Radius[i] * 2 + 1;
00406 internalRadius[i] = Radius[i] + 1;
00407 RegionLimit[i] = inputRegion.GetSize()[i] + RegionStart[i] - 1;
00408 }
00409
00410 typedef typename NumericTraits<OutputPixelType>::RealType AccPixType;
00411
00412 std::vector<OffsetType> UnitCorners = CornerOffsets<TInputImage>(accImage);
00413 std::vector<OffsetType> RealCorners;
00414 std::vector<AccPixType> Weights;
00415
00416 for (unsigned k = 0; k < UnitCorners.size(); k++)
00417 {
00418 int prod = 1;
00419 OffsetType ThisCorner;
00420 for (unsigned i = 0; i < TInputImage::ImageDimension; i++)
00421 {
00422 prod *= UnitCorners[k][i];
00423 if (UnitCorners[k][i] > 0)
00424 {
00425 ThisCorner[i] = Radius[i];
00426 }
00427 else
00428 {
00429 ThisCorner[i] = -(Radius[i]+1);
00430 }
00431 }
00432 Weights.push_back((AccPixType)prod);
00433 RealCorners.push_back(ThisCorner);
00434 }
00435
00436
00437 faceList = faceCalculator(accImage, outputRegion, internalRadius);
00438
00439 for (fit = faceList.begin(); fit != faceList.end(); ++fit)
00440 {
00441 if (fit == faceList.begin())
00442 {
00443
00444
00445
00446 AccPixType pixelscount = 1;
00447 for (unsigned i = 0; i < TInputImage::ImageDimension; i++)
00448 {
00449 pixelscount *= (AccPixType)(2*Radius[i] + 1);
00450 }
00451
00452 typedef ImageRegionIterator<OutputImageType> OutputIteratorType;
00453 typedef ImageRegionConstIterator<InputImageType> InputIteratorType;
00454
00455 typedef std::vector<InputIteratorType> CornerItVecType;
00456 CornerItVecType CornerItVec;
00457
00458 for (unsigned k = 0; k < RealCorners.size(); k++)
00459 {
00460 typename InputImageType::RegionType tReg=(*fit);
00461 tReg.SetIndex(tReg.GetIndex() + RealCorners[k]);
00462 InputIteratorType tempIt(accImage, tReg);
00463 tempIt.GoToBegin();
00464 CornerItVec.push_back(tempIt);
00465 }
00466
00467 OutputIteratorType oIt(outputImage, *fit);
00468
00469 for (oIt.GoToBegin(); !oIt.IsAtEnd(); ++oIt)
00470 {
00471 AccPixType Sum = 0;
00472 AccPixType SquareSum = 0;
00473
00474 for (unsigned k = 0; k < CornerItVec.size(); k++)
00475 {
00476 const InputPixelType & i = CornerItVec[k].Get();
00477 Sum += Weights[k] * i[0];
00478 SquareSum += Weights[k] * i[1];
00479
00480 ++(CornerItVec[k]);
00481 }
00482
00483 oIt.Set(static_cast<OutputPixelType>( vcl_sqrt( ( SquareSum - Sum*Sum/pixelscount ) / ( pixelscount -1 ) ) ) );
00484 progress.CompletedPixel();
00485 }
00486 }
00487 else
00488 {
00489
00490 typedef ImageRegionIteratorWithIndex<OutputImageType> OutputIteratorType;
00491 OutputIteratorType oIt(outputImage, *fit);
00492
00493 for (oIt.GoToBegin(); !oIt.IsAtEnd(); ++oIt)
00494 {
00495
00496
00497
00498 RegionType currentKernelRegion;
00499 currentKernelRegion.SetSize( kernelSize );
00500
00501 IndexType kernelRegionIdx = oIt.GetIndex();
00502 IndexType CentIndex = kernelRegionIdx;
00503 for( int i=0; i<TInputImage::ImageDimension; i++ )
00504 {
00505 kernelRegionIdx[i] -= Radius[i];
00506 }
00507 currentKernelRegion.SetIndex( kernelRegionIdx );
00508 currentKernelRegion.Crop( inputRegion );
00509 long edgepixelscount = currentKernelRegion.GetNumberOfPixels();
00510 AccPixType Sum = 0;
00511 AccPixType SquareSum = 0;
00512
00513
00514
00515
00516
00517
00518
00519
00520 for (unsigned k = 0; k < RealCorners.size(); k++)
00521 {
00522 IndexType ThisCorner = CentIndex + RealCorners[k];
00523 bool IncludeCorner = true;
00524 for (unsigned j = 0; j < TInputImage::ImageDimension; j++)
00525 {
00526 if (UnitCorners[k][j] > 0)
00527 {
00528
00529 ThisCorner[j] = vnl_math_min(ThisCorner[j], (long)RegionLimit[j]);
00530 }
00531 else
00532 {
00533
00534 if (ThisCorner[j] < RegionStart[j])
00535 {
00536 IncludeCorner = false;
00537 break;
00538 }
00539 }
00540 }
00541 if (IncludeCorner)
00542 {
00543 const InputPixelType & i = accImage->GetPixel(ThisCorner);
00544 Sum += Weights[k] * i[0];
00545 SquareSum += Weights[k] * i[1];
00546 }
00547 }
00548
00549 oIt.Set(static_cast<OutputPixelType>( vcl_sqrt( ( SquareSum - Sum*Sum/edgepixelscount ) / ( edgepixelscount -1 ) ) ) );
00550 progress.CompletedPixel();
00551 }
00552 }
00553 }
00554 }
00555
00556
00557 template <class TInputImage, class TOutputImage>
00558 void
00559 BoxSquareAccumulateFunction(const TInputImage * inputImage,
00560 TOutputImage * outputImage,
00561 typename TInputImage::RegionType inputRegion,
00562 typename TOutputImage::RegionType outputRegion,
00563 ProgressReporter &progress)
00564 {
00565
00566 typedef TInputImage InputImageType;
00567 typedef typename TInputImage::RegionType RegionType;
00568 typedef typename TInputImage::SizeType SizeType;
00569 typedef typename TInputImage::IndexType IndexType;
00570 typedef typename TInputImage::PixelType PixelType;
00571 typedef typename TInputImage::OffsetType OffsetType;
00572 typedef TOutputImage OutputImageType;
00573 typedef typename TOutputImage::PixelType OutputPixelType;
00574 typedef typename OutputPixelType::ValueType ValueType;
00575 typedef typename TInputImage::PixelType InputPixelType;
00576
00577 typedef ImageRegionConstIterator<TInputImage> InputIterator;
00578 typedef ImageRegionIterator<TOutputImage> OutputIterator;
00579
00580 typedef ShapedNeighborhoodIterator<TOutputImage> NOutputIterator;
00581 InputIterator inIt( inputImage, inputRegion);
00582 typename TInputImage::SizeType kernelRadius;
00583 kernelRadius.Fill(1);
00584
00585 NOutputIterator noutIt( kernelRadius, outputImage, outputRegion);
00586
00587 setConnectivityEarlyBox( &noutIt, true );
00588
00589 ConstantBoundaryCondition<OutputImageType> oBC;
00590 oBC.SetConstant( NumericTraits< OutputPixelType >::Zero );
00591 noutIt.OverrideBoundaryCondition(&oBC);
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601 std::vector<int> Weights;
00602 typename NOutputIterator::ConstIterator sIt;
00603 for( typename NOutputIterator::IndexListType::const_iterator idxIt = noutIt.GetActiveIndexList().begin();
00604 idxIt != noutIt.GetActiveIndexList().end();
00605 idxIt++ )
00606 {
00607 OffsetType offset = noutIt.GetOffset(*idxIt);
00608 int w = -1;
00609 for (unsigned k = 0; k < InputImageType::ImageDimension; k++)
00610 {
00611 if (offset[k] != 0)
00612 w *= offset[k];
00613 }
00614 Weights.push_back(w);
00615 }
00616
00617 for (inIt.GoToBegin(), noutIt.GoToBegin(); !noutIt.IsAtEnd(); ++inIt, ++noutIt )
00618 {
00619 ValueType Sum = 0;
00620 ValueType SquareSum = 0;
00621 int k;
00622 for (k = 0, sIt = noutIt.Begin(); !sIt.IsAtEnd();++sIt, ++k)
00623 {
00624 const OutputPixelType & v = sIt.Get();
00625 Sum += v[0] * Weights[k];
00626 SquareSum += v[1] * Weights[k];
00627 }
00628 OutputPixelType o;
00629 const InputPixelType & i = inIt.Get();
00630 o[0] = Sum + i;
00631 o[1] = SquareSum + i*i;
00632 noutIt.SetCenterPixel( o );
00633 progress.CompletedPixel();
00634 }
00635 }
00636
00637
00638 }
00639
00640 #endif
00641