52 #ifndef VIGRA_NON_LOCAL_MEAN
53 #define VIGRA_NON_LOCAL_MEAN
60 #include "multi_array.hxx"
61 #include "multi_convolution.hxx"
63 #include "threading.hxx"
64 #include "gaussians.hxx"
68 struct NonLocalMeanParameter{
70 NonLocalMeanParameter(
71 const double sigmaSpatial = 2.0,
72 const int searchRadius = 3,
73 const int patchRadius = 1,
74 const double sigmaMean = 1.0,
75 const int stepSize = 2,
76 const int iterations=1,
77 const int nThreads = 8,
78 const bool verbose =
true
80 sigmaSpatial_(sigmaSpatial),
81 searchRadius_(searchRadius),
82 patchRadius_(patchRadius),
83 sigmaMean_(sigmaMean),
85 iterations_(iterations),
103 class RatioPolicyParameter{
105 RatioPolicyParameter(
106 const double sigma = 5.0,
107 const double meanRatio = 0.95,
108 const double varRatio = 0.5,
109 const double epsilon = 0.00001
112 meanRatio_(meanRatio),
123 template<
class PIXEL_TYPE_IN>
127 typedef RatioPolicyParameter ParameterType;
128 typedef typename NumericTraits<PIXEL_TYPE_IN>::RealPromote PixelType;
129 typedef typename NumericTraits<PIXEL_TYPE_IN>::ValueType ValueType;
132 RatioPolicy(
const ParameterType & param)
133 : meanRatio_(static_cast<ValueType>(param.meanRatio_)),
134 varRatio_(static_cast<ValueType>(param.varRatio_)),
135 epsilon_(static_cast<ValueType>(param.epsilon_)),
136 sigmaSquared_(param.sigma_*param.sigma_){
140 bool usePixel(
const PixelType & meanA,
const PixelType & varA)
const{
141 return sum(meanA) > epsilon_ &&
sum(varA) > epsilon_;
146 const PixelType & meanA,
const PixelType & varA,
147 const PixelType & meanB,
const PixelType & varB
150 const ValueType m = mean(meanA/meanB);
151 const ValueType v = mean(varA/varB);
152 return (m > meanRatio_ && m < (1.0 / meanRatio_) && v > varRatio_ && v < (1.0 / varRatio_));
155 ValueType distanceToWeight(
const PixelType & ,
const PixelType & ,
const ValueType distance){
156 return exp(-distance /sigmaSquared_);
160 ValueType meanRatio_;
163 ValueType sigmaSquared_;
171 class NormPolicyParameter{
174 const double sigma = 5.0,
175 const double meanDist = 0.95,
176 const double varRatio = 0.5,
177 const double epsilon = 0.00001
192 template<
class V,
int SIZE>
193 inline bool equal(
const TinyVector<V,SIZE> & a,
const TinyVector<V,SIZE> b){
194 for(
int i=0;i<SIZE;++i)
202 template<
int DIM,
bool ALWAYS_INSIDE>
206 struct BorderHelper<DIM,true>{
207 template<
class COORD,
class IMAGE>
208 static bool isInside(
const COORD & ,
const IMAGE & ){
211 template<
class COORD,
class IMAGE>
212 static bool isOutside(
const COORD & ,
const IMAGE & ){
216 template<
class COORD,
class IMAGE>
217 static void mirrorIfIsOutsidePoint(COORD & ,IMAGE & ){
223 struct BorderHelper<DIM,false>{
224 template<
class COORD,
class IMAGE>
225 static bool isInside(
const COORD & c,
const IMAGE & img){
226 return img.isInside(c);
228 template<
class COORD,
class IMAGE>
229 static bool isOutside(
const COORD & c,
const IMAGE & img){
230 return img.isOutside(c);
233 template<
class COORD,
class IMAGE>
234 static void mirrorIfIsOutsidePoint(COORD & coord,
const IMAGE & img){
235 for(
int c=0;c<DIM;++c){
237 coord[c]=-1*coord[c];
238 else if(coord[c]>= img.shape(c))
239 coord[c] = 2 * img.shape(c) - coord[c] - 1;
249 template<
class PIXEL_TYPE_IN>
253 typedef NormPolicyParameter ParameterType;
254 typedef typename NumericTraits<PIXEL_TYPE_IN>::RealPromote PixelType;
255 typedef typename NumericTraits<PIXEL_TYPE_IN>::ValueType ValueType;
258 NormPolicy(
const ParameterType & param)
259 : meanDist_(static_cast<ValueType>(param.meanDist_)),
260 varRatio_(static_cast<ValueType>(param.varRatio_)),
261 epsilon_(static_cast<ValueType>(param.epsilon_)),
262 sigmaSquared_(param.sigma_*param.sigma_){
266 bool usePixel(
const PixelType & ,
const PixelType & varA)
const{
267 return sum(varA)>epsilon_;
272 const PixelType & meanA,
const PixelType & varA,
273 const PixelType & meanB,
const PixelType & varB
277 const ValueType v = mean(varA/varB);
279 return (m < meanDist_ && v > varRatio_ && v < (1.0 / varRatio_));
282 ValueType distanceToWeight(
const PixelType & ,
const PixelType & ,
const ValueType distance){
283 return exp(-distance /sigmaSquared_);
290 ValueType sigmaSquared_;
296 template<
int DIM,
class PIXEL_TYPE_IN,
class SMOOTH_POLICY>
297 class BlockWiseNonLocalMeanThreadObject{
298 typedef PIXEL_TYPE_IN PixelTypeIn;
299 typedef typename NumericTraits<PixelTypeIn>::RealPromote RealPromotePixelType;
300 typedef typename NumericTraits<RealPromotePixelType>::ValueType RealPromoteScalarType;
303 typedef NonLocalMeanParameter ParameterType;
306 typedef void result_type;
307 typedef MultiArrayView<DIM,PixelTypeIn> InArrayView;
308 typedef MultiArrayView<DIM,RealPromotePixelType> MeanArrayView;
309 typedef MultiArrayView<DIM,RealPromotePixelType> VarArrayView;
310 typedef MultiArrayView<DIM,RealPromotePixelType> EstimateArrayView;
311 typedef MultiArrayView<DIM,RealPromoteScalarType> LabelArrayView;
312 typedef std::vector<RealPromotePixelType> BlockAverageVectorType;
313 typedef std::vector<RealPromoteScalarType> BlockGaussWeightVectorType;
314 typedef SMOOTH_POLICY SmoothPolicyType;
316 typedef TinyVector<int,2> RangeType;
319 typedef threading::thread ThreadType;
320 typedef threading::mutex MutexType;
322 BlockWiseNonLocalMeanThreadObject(
323 const InArrayView & inImage,
324 MeanArrayView & meanImage,
325 VarArrayView & varImage,
326 EstimateArrayView & estimageImage,
328 const SmoothPolicyType & smoothPolicy,
329 const ParameterType & param,
330 const size_t nThreads,
331 MutexType & estimateMutex,
332 MultiArray<1,int> & progress
336 meanImage_(meanImage),
338 estimageImage_(estimageImage),
339 labelImage_(labelImage),
340 smoothPolicy_(smoothPolicy),
345 estimateMutexPtr_(&estimateMutex),
347 average_(std::pow( (double)(2*param.patchRadius_+1), DIM) ),
348 gaussWeight_(std::pow( (double)(2*param.patchRadius_+1), DIM) ),
349 shape_(inImage.shape()),
353 for(
int dim=0;dim<DIM;++dim)
354 totalSize_*=(shape_[dim]/param.stepSize_);
357 void setRange(
const RangeType & lastAxisRange){
358 lastAxisRange_=lastAxisRange;
360 void setThreadIndex(
const size_t threadIndex){
361 threadIndex_=threadIndex;
369 template<
bool ALWAYS_INSIDE>
370 void processSinglePixel(
const Coordinate & xyz);
372 template<
bool ALWAYS_INSIDE>
373 void processSinglePair(
const Coordinate & xyz,
const Coordinate & nxyz,RealPromoteScalarType & wmax,RealPromoteScalarType & totalweight);
375 template<
bool ALWAYS_INSIDE>
376 RealPromoteScalarType patchDistance(
const Coordinate & xyz,
const Coordinate & nxyz);
378 template<
bool ALWAYS_INSIDE>
379 void patchExtractAndAcc(
const Coordinate & xyz,
const RealPromoteScalarType weight);
381 template<
bool ALWAYS_INSIDE>
382 void patchAccMeanToEstimate(
const Coordinate & xyz,
const RealPromoteScalarType globalSum);
385 bool isAlwaysInside(
const Coordinate & coord)
const{
386 const Coordinate r = (Coordinate(param_.searchRadius_) + Coordinate(param_.patchRadius_) +1 );
387 const Coordinate test1 = coord - r;
388 const Coordinate test2 = coord + r;
389 return inImage_.isInside(test1) && inImage_.isInside(test2);
392 void initalizeGauss();
394 void progressPrinter(
const int counter);
398 InArrayView inImage_;
399 MeanArrayView meanImage_;
400 VarArrayView varImage_;
401 EstimateArrayView estimageImage_;
402 LabelArrayView labelImage_;
405 SmoothPolicyType smoothPolicy_;
408 ParameterType param_;
411 RangeType lastAxisRange_;
414 MutexType * estimateMutexPtr_;
415 MultiArrayView<1,int> progress_;
419 BlockAverageVectorType average_;
420 BlockGaussWeightVectorType gaussWeight_;
426 template<
int DIM,
class PIXEL_TYPE_IN,
class SMOOTH_POLICY>
427 inline void BlockWiseNonLocalMeanThreadObject<DIM, PIXEL_TYPE_IN, SMOOTH_POLICY>::initalizeGauss(){
429 const int pr = param_.patchRadius_;
430 Gaussian<RealPromoteScalarType> gaussian(param_.sigmaSpatial_);
432 RealPromoteScalarType
sum = RealPromoteScalarType(0.0);
434 for (xyz[1] = -pr; xyz[1] <=pr; ++xyz[1])
435 for (xyz[0] = -pr; xyz[0] <=pr; ++xyz[0],++c){
436 const RealPromoteScalarType distance =
norm(xyz);
437 const RealPromoteScalarType w =gaussian(distance);
443 for (xyz[2] = -pr; xyz[2] <=pr; ++xyz[2])
444 for (xyz[1] = -pr; xyz[1] <=pr; ++xyz[1])
445 for (xyz[0] = -pr; xyz[0] <=pr; ++xyz[0],++c){
446 const RealPromoteScalarType distance =
norm(xyz);
447 const RealPromoteScalarType w =gaussian(distance);
453 for (xyz[3] = -pr; xyz[3] <=pr; ++xyz[3])
454 for (xyz[2] = -pr; xyz[2] <=pr; ++xyz[2])
455 for (xyz[1] = -pr; xyz[1] <=pr; ++xyz[1])
456 for (xyz[0] = -pr; xyz[0] <=pr; ++xyz[0],++c){
457 const RealPromoteScalarType distance =
norm(xyz);
458 const RealPromoteScalarType w =gaussian(distance);
464 for(
size_t i=0;i<gaussWeight_.size();++i){
465 gaussWeight_[i]/=
sum;
470 template<
int DIM,
class PIXEL_TYPE_IN,
class SMOOTH_POLICY>
471 inline void BlockWiseNonLocalMeanThreadObject<DIM, PIXEL_TYPE_IN, SMOOTH_POLICY>::progressPrinter(
const int counter){
472 progress_[threadIndex_] = counter;
473 if(threadIndex_==nThreads_-1){
474 if(counter%100 == 0){
476 for(
size_t ti=0;ti<nThreads_;++ti)
481 std::cout<<
"\rprogress "<<std::setw(10)<<pr<<
" %%"<<std::flush;
486 template<
int DIM,
class PIXEL_TYPE_IN,
class SMOOTH_POLICY>
487 void BlockWiseNonLocalMeanThreadObject<DIM, PIXEL_TYPE_IN, SMOOTH_POLICY>::operator()(){
488 const int start = lastAxisRange_[0];
489 const int end = lastAxisRange_[1];
490 const int stepSize = param_.stepSize_;
492 this->initalizeGauss();
496 if(param_.verbose_ && threadIndex_==nThreads_-1){
497 std::cout<<
"progress";
501 for (xyz[1] = start; xyz[1] < end; xyz[1] += stepSize)
502 for (xyz[0] = 0; xyz[0] < shape_[0]; xyz[0] += stepSize){
504 if(isAlwaysInside(xyz))
505 this->processSinglePixel<true>(xyz);
507 this->processSinglePixel<false>(xyz);
509 this->progressPrinter(c);
514 for (xyz[2] = start; xyz[2] < end; xyz[2] += stepSize)
515 for (xyz[1] = 0; xyz[1] < shape_[1]; xyz[1] += stepSize)
516 for (xyz[0] = 0; xyz[0] < shape_[0]; xyz[0] += stepSize){
517 if(isAlwaysInside(xyz))
518 this->processSinglePixel<true>(xyz);
520 this->processSinglePixel<false>(xyz);
522 this->progressPrinter(c);
527 for (xyz[3] = start; xyz[3] < end; xyz[3] += stepSize)
528 for (xyz[2] = 0; xyz[2] < shape_[2]; xyz[2] += stepSize)
529 for (xyz[1] = 0; xyz[1] < shape_[1]; xyz[1] += stepSize)
530 for (xyz[0] = 0; xyz[0] < shape_[0]; xyz[0] += stepSize){
531 if(isAlwaysInside(xyz))
532 this->processSinglePixel<true>(xyz);
534 this->processSinglePixel<false>(xyz);
536 this->progressPrinter(c);
540 if(param_.verbose_ && threadIndex_==nThreads_-1){
541 std::cout<<
"\rprogress "<<std::setw(10)<<
"100"<<
" %%"<<
"\n";
547 template<
int DIM,
class PIXEL_TYPE_IN,
class SMOOTH_POLICY>
548 template<
bool ALWAYS_INSIDE>
549 inline void BlockWiseNonLocalMeanThreadObject<DIM, PIXEL_TYPE_IN, SMOOTH_POLICY>::processSinglePixel(
550 const Coordinate & xyz
552 Coordinate nxyz(SkipInitialization);
553 std::fill(average_.begin(),average_.end(),RealPromotePixelType(0.0));
554 RealPromoteScalarType totalweight = 0.0;
556 if(smoothPolicy_.usePixel(meanImage_[xyz],varImage_[xyz])){
558 RealPromoteScalarType wmax = 0.0;
559 const Coordinate start = xyz- Coordinate(param_.searchRadius_);
560 const Coordinate end = xyz+ Coordinate(param_.searchRadius_);
563 for (nxyz[1] = start[1]; nxyz[1] <= end[1]; nxyz[1]++)
564 for (nxyz[0] = start[0]; nxyz[0] <= end[0]; nxyz[0]++){
568 this->processSinglePair<ALWAYS_INSIDE>(xyz,nxyz,wmax,totalweight);
572 for (nxyz[2] = start[2]; nxyz[2] <= end[2]; nxyz[2]++)
573 for (nxyz[1] = start[1]; nxyz[1] <= end[1]; nxyz[1]++)
574 for (nxyz[0] = start[0]; nxyz[0] <= end[0]; nxyz[0]++){
577 this->processSinglePair<ALWAYS_INSIDE>(xyz,nxyz,wmax,totalweight);
581 for (nxyz[3] = start[3]; nxyz[3] <= end[3]; nxyz[3]++)
582 for (nxyz[2] = start[2]; nxyz[2] <= end[2]; nxyz[2]++)
583 for (nxyz[1] = start[1]; nxyz[1] <= end[1]; nxyz[1]++)
584 for (nxyz[0] = start[0]; nxyz[0] <= end[0]; nxyz[0]++){
587 this->processSinglePair<ALWAYS_INSIDE>(xyz,nxyz,wmax,totalweight);
597 this->patchExtractAndAcc<ALWAYS_INSIDE>(xyz,wmax);
601 if (totalweight != 0.0){
602 this->patchAccMeanToEstimate<ALWAYS_INSIDE>(xyz,totalweight);
607 const double wmax = 1.0;
608 this->patchExtractAndAcc<ALWAYS_INSIDE>(xyz,wmax);
610 this->patchAccMeanToEstimate<ALWAYS_INSIDE>(xyz,totalweight);
616 template<
int DIM,
class PIXEL_TYPE_IN,
class SMOOTH_POLICY>
617 template<
bool ALWAYS_INSIDE>
618 inline void BlockWiseNonLocalMeanThreadObject<DIM, PIXEL_TYPE_IN, SMOOTH_POLICY>::processSinglePair(
619 const Coordinate & xyz,
620 const Coordinate & nxyz,
621 RealPromoteScalarType & wmax,
622 RealPromoteScalarType & totalweight
625 if(BorderHelper<DIM,ALWAYS_INSIDE>::isInside(nxyz,inImage_)){
627 if(smoothPolicy_.usePixel(meanImage_[nxyz],varImage_[nxyz])){
631 if(smoothPolicy_.usePixelPair(meanImage_[xyz],varImage_[xyz],meanImage_[nxyz],varImage_[nxyz])){
632 const RealPromoteScalarType distance =this->patchDistance<ALWAYS_INSIDE>(xyz,nxyz);
633 const RealPromoteScalarType w = smoothPolicy_.distanceToWeight(meanImage_[xyz],varImage_[xyz],distance);
634 wmax = std::max(w,wmax);
635 this->patchExtractAndAcc<ALWAYS_INSIDE>(nxyz,w);
644 template<
int DIM,
class PIXEL_TYPE_IN,
class SMOOTH_POLICY>
645 template<
bool ALWAYS_INSIDE>
646 inline typename BlockWiseNonLocalMeanThreadObject<DIM, PIXEL_TYPE_IN, SMOOTH_POLICY>::RealPromoteScalarType
647 BlockWiseNonLocalMeanThreadObject<DIM,PIXEL_TYPE_IN,SMOOTH_POLICY>::patchDistance(
648 const Coordinate & pA,
649 const Coordinate & pB
653 const int f = param_.patchRadius_;
654 Coordinate offset(SkipInitialization),nPa(SkipInitialization),nPb(SkipInitialization);
656 RealPromoteScalarType distancetotal = 0;
660 #define VIGRA_NLM_IN_LOOP_CODE \
663 BorderHelper<DIM,ALWAYS_INSIDE>::mirrorIfIsOutsidePoint(nPa,inImage_); \
664 BorderHelper<DIM,ALWAYS_INSIDE>::mirrorIfIsOutsidePoint(nPb,inImage_); \
665 const RealPromoteScalarType gaussWeight = gaussWeight_[c]; \
666 const RealPromotePixelType vA = inImage_[nPa]; \
667 const RealPromotePixelType vB = inImage_[nPb]; \
668 distancetotal += gaussWeight*vigra::sizeDividedSquaredNorm(vA-vB); \
672 for (offset[1] = -f; offset[1] <= f; ++offset[1])
673 for (offset[0] = -f; offset[0] <= f; ++offset[0],++c){
674 VIGRA_NLM_IN_LOOP_CODE;
678 for (offset[2] = -f; offset[2] <= f; ++offset[2])
679 for (offset[1] = -f; offset[1] <= f; ++offset[1])
680 for (offset[0] = -f; offset[0] <= f; ++offset[0],++c){
681 VIGRA_NLM_IN_LOOP_CODE;
685 for (offset[3] = -f; offset[3] <= f; ++offset[3])
686 for (offset[2] = -f; offset[2] <= f; ++offset[2])
687 for (offset[1] = -f; offset[1] <= f; ++offset[1])
688 for (offset[0] = -f; offset[0] <= f; ++offset[0],++c){
689 VIGRA_NLM_IN_LOOP_CODE;
692 #undef VIGRA_NLM_IN_LOOP_CODE
693 return distancetotal / acu;
698 template<
int DIM,
class PIXEL_TYPE_IN,
class SMOOTH_POLICY>
699 template<
bool ALWAYS_INSIDE>
701 BlockWiseNonLocalMeanThreadObject<DIM,PIXEL_TYPE_IN,SMOOTH_POLICY>::patchExtractAndAcc(
702 const Coordinate & xyz,
703 const RealPromoteScalarType weight
705 Coordinate xyzPos(SkipInitialization),abc(SkipInitialization);
706 Coordinate nhSize3(param_.patchRadius_);
707 const int ns = 2 * param_.patchRadius_ + 1;
712 #define VIGRA_NLM_IN_LOOP_CODE \
713 xyzPos = xyz + abc - nhSize3; \
714 if(BorderHelper<DIM,ALWAYS_INSIDE>::isOutside(xyzPos,inImage_)) \
715 average_[count] += inImage_[xyz]* weight; \
717 average_[count] += inImage_[xyzPos]* weight; \
721 for (abc[1] = 0; abc[1] < ns; abc[1]++)
722 for (abc[0] = 0; abc[0] < ns; abc[0]++){
723 VIGRA_NLM_IN_LOOP_CODE;
727 for (abc[2] = 0; abc[2] < ns; abc[2]++)
728 for (abc[1] = 0; abc[1] < ns; abc[1]++)
729 for (abc[0] = 0; abc[0] < ns; abc[0]++){
730 VIGRA_NLM_IN_LOOP_CODE;
734 for (abc[3] = 0; abc[3] < ns; abc[3]++)
735 for (abc[2] = 0; abc[2] < ns; abc[2]++)
736 for (abc[1] = 0; abc[1] < ns; abc[1]++)
737 for (abc[0] = 0; abc[0] < ns; abc[0]++){
738 VIGRA_NLM_IN_LOOP_CODE;
742 #undef VIGRA_NLM_IN_LOOP_CODE
746 template<
int DIM,
class PIXEL_TYPE_IN,
class SMOOTH_POLICY>
747 template<
bool ALWAYS_INSIDE>
749 BlockWiseNonLocalMeanThreadObject<DIM,PIXEL_TYPE_IN,SMOOTH_POLICY>::patchAccMeanToEstimate(
750 const Coordinate & xyz,
751 const RealPromoteScalarType globalSum
753 Coordinate abc(SkipInitialization),xyzPos(SkipInitialization),nhSize(param_.patchRadius_);
755 const int ns = 2 * param_.patchRadius_ + 1;
757 #define VIGRA_NLM_IN_LOOP_CODE \
758 xyzPos = xyz + abc - nhSize; \
759 if(BorderHelper<DIM,ALWAYS_INSIDE>::isInside(xyzPos,inImage_)){ \
760 estimateMutexPtr_->lock(); \
761 RealPromotePixelType value = estimageImage_[xyzPos]; \
762 const RealPromoteScalarType gw = gaussWeight_[count]; \
763 RealPromotePixelType tmp =(average_[count] / globalSum); \
766 estimageImage_[xyzPos] = value; \
767 labelImage_[xyzPos]+=gw; \
768 estimateMutexPtr_->unlock(); \
773 for (abc[1] = 0; abc[1] < ns; abc[1]++)
774 for (abc[0] = 0; abc[0] < ns; abc[0]++){
775 VIGRA_NLM_IN_LOOP_CODE;
779 for (abc[2] = 0; abc[2] < ns; abc[2]++)
780 for (abc[1] = 0; abc[1] < ns; abc[1]++)
781 for (abc[0] = 0; abc[0] < ns; abc[0]++){
782 VIGRA_NLM_IN_LOOP_CODE;
786 for (abc[3] = 0; abc[3] < ns; abc[3]++)
787 for (abc[2] = 0; abc[2] < ns; abc[2]++)
788 for (abc[1] = 0; abc[1] < ns; abc[1]++)
789 for (abc[0] = 0; abc[0] < ns; abc[0]++){
790 VIGRA_NLM_IN_LOOP_CODE;
793 #undef VIGRA_NLM_IN_LOOP_CODE
798 template<
int DIM,
class PIXEL_TYPE_IN,
class SMOOTH_POLICY,
class PIXEL_TYPE_OUT>
799 inline void gaussianMeanAndVariance(
810 for(
int scanOrderIndex=0;scanOrderIndex<inArray.
size();++scanOrderIndex){
811 tmpArray[scanOrderIndex]=
vigra::pow(inArray[scanOrderIndex],2);
814 for(
int scanOrderIndex=0;scanOrderIndex<inArray.
size();++scanOrderIndex){
815 PIXEL_TYPE_OUT var = varArray[scanOrderIndex] -
vigra::pow(meanArray[scanOrderIndex],2);
818 varArray[scanOrderIndex] = var;
822 template<
int DIM,
class PIXEL_TYPE_IN,
class SMOOTH_POLICY,
class PIXEL_TYPE_OUT>
823 inline void gaussianMeanAndVariance(
830 gaussianMeanAndVariance<DIM,PIXEL_TYPE_IN,PIXEL_TYPE_OUT>(inArray,sigma,meanArray,varArray,tmpArray);
833 namespace detail_non_local_means{
835 template<
int DIM,
class PIXEL_TYPE_IN,
class PIXEL_TYPE_OUT,
class SMOOTH_POLICY>
836 void nonLocalMean1Run(
838 const SMOOTH_POLICY & smoothPolicy,
839 const NonLocalMeanParameter param,
843 typedef PIXEL_TYPE_IN PixelTypeIn;
844 typedef typename vigra::NumericTraits<PixelTypeIn>::RealPromote RealPromotePixelType;
845 typedef typename vigra::NumericTraits<RealPromotePixelType>::ValueType RealPromoteScalarType;
846 typedef SMOOTH_POLICY SmoothPolicyType;
848 typedef BlockWiseNonLocalMeanThreadObject<DIM,PixelTypeIn,SmoothPolicyType> ThreadObjectType;
852 vigra_precondition(param.stepSize_>=1,
"NonLocalMean Parameter: \"stepSize>=1\" violated");
853 vigra_precondition(param.searchRadius_>=1,
"NonLocalMean Parameter: \"searchRadius >=1\" violated");
854 vigra_precondition(param.patchRadius_>=1,
"NonLocalMean Parameter: \"searchRadius >=1\" violated");
855 vigra_precondition(param.stepSize_-1<=param.patchRadius_,
"NonLocalMean Parameter: \"stepSize -1 <= patchRadius\" violated");
867 gaussianMeanAndVariance<DIM,PixelTypeIn,RealPromotePixelType>(image,param.sigmaMean_,meanImage,varImage);
870 labelImage = RealPromoteScalarType(0.0);
871 estimageImage = RealPromotePixelType(0.0);
878 typedef threading::thread ThreadType;
879 typedef threading::mutex MutexType;
881 MutexType estimateMutex;
884 const size_t nThreads = param.nThreads_;
889 std::vector<ThreadObjectType> threadObjects(nThreads,
890 ThreadObjectType(image, meanImage, varImage, estimageImage, labelImage,
891 smoothPolicy, param, nThreads, estimateMutex,progress)
895 std::vector<ThreadType *> threadPtrs(nThreads);
896 for(
size_t i=0; i<nThreads; ++i){
897 ThreadObjectType & threadObj = threadObjects[i];
898 threadObj.setThreadIndex(i);
899 typename ThreadObjectType::RangeType lastAxisRange;
900 lastAxisRange[0]=(i * image.shape(DIM-1)) / nThreads;
901 lastAxisRange[1]=((i+1) * image.shape(DIM-1)) / nThreads;
902 threadObj.setRange(lastAxisRange);
905 threadPtrs[i] =
new ThreadType(threadObjects[i]);
907 for(
size_t i=0; i<nThreads; ++i)
908 threadPtrs[i]->join();
909 for(
size_t i=0; i<nThreads; ++i)
910 delete threadPtrs[i];
917 for(
int scanOrderIndex=0; scanOrderIndex<labelImage.size(); ++scanOrderIndex){
918 if (labelImage[scanOrderIndex] <= RealPromoteScalarType(0.00001))
919 outImage[scanOrderIndex]=image[scanOrderIndex];
921 outImage[scanOrderIndex]=estimageImage[scanOrderIndex] / labelImage[scanOrderIndex];
927 template<
int DIM,
class PIXEL_TYPE_IN,
class PIXEL_TYPE_OUT,
class SMOOTH_POLICY>
930 const SMOOTH_POLICY & smoothPolicy,
931 const NonLocalMeanParameter param,
934 detail_non_local_means::nonLocalMean1Run<DIM,PIXEL_TYPE_IN,PIXEL_TYPE_OUT,SMOOTH_POLICY>(image,smoothPolicy,param,outImage);
935 if(param.iterations_>1){
938 for(
size_t i=0;i<static_cast<size_t>(param.iterations_-1);++i){
940 detail_non_local_means::nonLocalMean1Run<DIM,PIXEL_TYPE_OUT,PIXEL_TYPE_OUT,SMOOTH_POLICY>(tmp,smoothPolicy,param,outImage);
unsigned int labelImage(...)
Find the connected components of a segmented image.
const difference_type & shape() const
Definition: multi_array.hxx:1648
linalg::TemporaryMatrix< T > exp(MultiArrayView< 2, T, C > const &v)
FFTWComplex< R >::SquaredNormType squaredNorm(const FFTWComplex< R > &a)
squared norm (= squared magnitude)
Definition: fftw3.hxx:1044
Main MultiArray class containing the memory management.
Definition: multi_array.hxx:2474
view_type::difference_type difference_type
Definition: multi_array.hxx:2522
FFTWComplex< R >::NormType norm(const FFTWComplex< R > &a)
norm (= magnitude)
Definition: fftw3.hxx:1037
difference_type_1 size() const
Definition: multi_array.hxx:1641
NumericTraits< V >::Promote sum(TinyVectorBase< V, SIZE, D1, D2 > const &l)
sum of the vector's elements
Definition: tinyvector.hxx:2073
TinyVector< V, SIZE > pow(TinyVectorBase< V, SIZE, D1, D2 > const &v, E exponent)
Definition: tinyvector.hxx:2036
Base class for, and view to, vigra::MultiArray.
Definition: multi_array.hxx:704
TinyVector< V, SIZE > clipLower(TinyVector< V, SIZE > const &t)
Clip negative values.
Definition: tinyvector.hxx:2268
void gaussianSmoothMultiArray(...)
Isotropic Gaussian smoothing of a multi-dimensional arrays.