]> Creatis software - clitk.git/blobdiff - itk/clitkRelativePositionAnalyzerFilter.txx
Moved from repository clitk to clitk.private/tests_dav
[clitk.git] / itk / clitkRelativePositionAnalyzerFilter.txx
index a732aab61e363fda81e3c8244f4509b9507a43ba..63af1191987386dfac0b632f0af23559ef967e10 100644 (file)
 template <class ImageType>
 clitk::RelativePositionAnalyzerFilter<ImageType>::
 RelativePositionAnalyzerFilter():
-itk::ImageToImageFilter<ImageType, ImageType>()
+  itk::ImageToImageFilter<ImageType, ImageType>()
 {
-  this->SetNumberOfRequiredInputs(3); // support, object, target
-  VerboseFlagOff();
+  this->SetNumberOfRequiredInputs(3); // Input : support, object, target
+  SetBackgroundValue(0);
+  SetForegroundValue(1);
+  SetNumberOfBins(100);
+  SetAreaLossTolerance(0.01);
+  SetSupportSize(0);
+  SetTargetSize(0);
+  SetSizeWithThreshold(0);
+  SetSizeWithReverseThreshold(0);
 }
 //--------------------------------------------------------------------
 
@@ -59,7 +66,7 @@ clitk::RelativePositionAnalyzerFilter<ImageType>::
 SetInputTarget(const ImageType * image) 
 {
   // Process object is not const-correct so the const casting is required.
-  this->SetNthInput(1, const_cast<ImageType *>(image));
+  this->SetNthInput(2, const_cast<ImageType *>(image));
 }
 //--------------------------------------------------------------------
   
@@ -75,61 +82,249 @@ PrintOptions()
 //--------------------------------------------------------------------
 
 
+//--------------------------------------------------------------------
+template <class ImageType>
+void 
+clitk::RelativePositionAnalyzerFilter<ImageType>::
+GenerateOutputInformation() 
+{ 
+  ImagePointer input = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
+  ImagePointer outputImage = this->GetOutput(0);
+  outputImage->SetRegions(outputImage->GetLargestPossibleRegion());
+}
+//--------------------------------------------------------------------
+
+
 //--------------------------------------------------------------------
 template <class ImageType>
 void 
 clitk::RelativePositionAnalyzerFilter<ImageType>::
 GenerateData() 
 {
-  DD("Update");
-  // Get input pointer
-  m_Support = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
+  ImagePointer temp = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
   m_Object = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(1));
-  m_Target = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(2));
-  static const unsigned int dim = ImageType::ImageDimension;
+  ImagePointer temp2 = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(2));
 
-  /*
-    Prerequisite:
-    - target fully inside support ? 
-  */
+  // Remove object from support (keep initial image)
+  m_Support = clitk::Clone<ImageType>(temp);
+  clitk::AndNot<ImageType>(m_Support, m_Object, GetBackgroundValue());
   
-  //for(int i=0; i<m_ListOfOrientation.size(); i++) {
-  //DD(i);
-    
-    // Compute Fuzzy map
-
-    // Get minimal value in the target area
-
-    // Or -> analyze floating point values inside the target area (histo ?)
-
-    // Set threshold and compute new support
-    
-    // Compute ratio of area before/after
-    // http://www.itk.org/Doxygen/html/classitk_1_1LabelStatisticsImageFilter.html#details
-    /*
-    typedef itk::LabelStatisticsImageFilter<ImageType, ImageType> StatisticsImageFilterType;
-    typename StatisticsImageFilterType::Pointer statisticsFilter = StatisticsImageFilterType::New();
-    statisticsFilter->SetInput(m_Input);
-    statisticsFilter->SetLabelInput(m_Input);
-    statisticsFilter->Update();
-    int n = labelStatisticsImageFilter->GetCount(GetForegroundValue());
-    DD(n);
-    statisticsFilter = StatisticsImageFilterType::New();
-    statisticsFilter->SetInput(m_Output);
-    statisticsFilter->SetLabelInput(m_Output);
-    statisticsFilter->Update();
-    int m = labelStatisticsImageFilter->GetCount(GetForegroundValue());
-    DD(m);
-    */
-    
-    // Print results
-    
-  //}
+  // Remove object from target. Important because sometimes, there is
+  // overlap between target and object.
+  m_Target = clitk::Clone<ImageType>(temp2);
+  clitk::AndNot<ImageType>(m_Target, m_Object, GetBackgroundValue());
+  
+  // Define filter to compute statics on mask image
+  typedef itk::LabelStatisticsImageFilter<ImageType, ImageType> StatFilterType;
+  typename StatFilterType::Pointer statFilter = StatFilterType::New();
+
+  // Compute the initial support size
+  statFilter->SetInput(m_Support);
+  statFilter->SetLabelInput(m_Support);
+  statFilter->Update();
+  SetSupportSize(statFilter->GetCount(GetForegroundValue()));
+  // DD(GetSupportSize());
+  
+  // Compute the initial target size
+  ImagePointer s = clitk::ResizeImageLike<ImageType>(m_Support, m_Target, GetBackgroundValue());
+  statFilter->SetInput(s);
+  statFilter->SetLabelInput(m_Target);
+  statFilter->Update();
+  SetTargetSize(statFilter->GetCount(GetForegroundValue()));
+  // DD(GetTargetSize());
+
+  //
+  int bins = GetNumberOfBins();
+  double tolerance = GetAreaLossTolerance();
+
+  // Compute Fuzzy map
+  double angle = GetDirection().angle1;
+  typename FloatImageType::Pointer map = ComputeFuzzyMap(m_Object, m_Target, m_Support, angle);
+  writeImage<FloatImageType>(map, "fuzzy_"+toString(clitk::rad2deg(angle))+".mha");
+
+  // Compute the optimal thresholds (direct and inverse)
+  double mThreshold=0.0;
+  double mReverseThreshold=1.0;
+  ComputeOptimalThresholds(map, m_Target, bins, tolerance, mThreshold, mReverseThreshold);
+
+  // DD(mThreshold);
+  // DD(mReverseThreshold);
+
+  // Use the threshold to compute new support
+  int s1 = GetSupportSize();
+  if (mThreshold > 0.0) {
+    ImagePointer support1 = 
+      clitk::SliceBySliceRelativePosition<ImageType>(m_Support, m_Object, 2, 
+                                                     mThreshold,
+                                                     angle,false, // inverseFlag
+                                                     false,  // uniqueConnectedComponent
+                                                     -1, true, 
+                                                     false);//singleObjectCCL
+    // Compute the new support size
+    statFilter->SetInput(support1);
+    statFilter->SetLabelInput(support1);
+    statFilter->Update();
+    s1 = statFilter->GetCount(GetForegroundValue());
+  }
+  
+  int s2 = GetSupportSize();
+  if (mReverseThreshold < 1.0) {
+    ImagePointer support2 = 
+      clitk::SliceBySliceRelativePosition<ImageType>(m_Support, m_Object, 2, 
+                                                     mReverseThreshold, 
+                                                     angle,true,// inverseFlag
+                                                     false, // uniqueConnectedComponent
+                                                     -1, true, 
+                                                     false); //singleObjectCCL
+    // Compute the new support size
+    statFilter = StatFilterType::New();
+    statFilter->SetInput(support2);
+    statFilter->SetLabelInput(support2);
+    statFilter->Update();
+    s2 = statFilter->GetCount(GetForegroundValue());
+  }
+  
+  // Check threshold, if we gain nothing, we force to max/min thresholds
+  // DD(GetSupportSize());
+  // DD(s1);
+  // DD(s2);
+  if (s1 >= GetSupportSize()) mThreshold = 0.0;
+  if (s2 >= GetSupportSize()) mReverseThreshold = 1.0;
+
+  // Set results values
+  m_Info.threshold = mThreshold;
+  m_Info.sizeAfterThreshold = s1;
+  m_Info.sizeBeforeThreshold = GetSupportSize();
+  m_Info.sizeReference = GetTargetSize();
+  m_InfoReverse.threshold = mReverseThreshold;
+  m_InfoReverse.sizeAfterThreshold = s2;
+  m_InfoReverse.sizeBeforeThreshold = GetSupportSize();
+  m_InfoReverse.sizeReference = GetTargetSize();  
+}
+//--------------------------------------------------------------------
+
 
+//--------------------------------------------------------------------
+template <class ImageType>
+typename clitk::RelativePositionAnalyzerFilter<ImageType>::FloatImageType::Pointer
+clitk::RelativePositionAnalyzerFilter<ImageType>::
+ComputeFuzzyMap(ImageType * object, ImageType * target, ImageType * support, double angle)
+{
+  typedef clitk::SliceBySliceRelativePositionFilter<ImageType> SliceRelPosFilterType;
+  typedef typename SliceRelPosFilterType::FloatImageType FloatImageType;
+  typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New();
+  sliceRelPosFilter->VerboseStepFlagOff();
+  sliceRelPosFilter->WriteStepFlagOff();
+  sliceRelPosFilter->SetInput(support);
+  sliceRelPosFilter->SetInputObject(object);
+  sliceRelPosFilter->SetDirection(2);
+  sliceRelPosFilter->SetIntermediateSpacingFlag(false);
+  //sliceRelPosFilter->AddOrientationTypeString(orientation);
+  sliceRelPosFilter->AddAnglesInRad(angle, 0.0);
+  sliceRelPosFilter->FuzzyMapOnlyFlagOn(); // do not threshold, only compute the fuzzy map
+  // sliceRelPosFilter->PrintOptions();
+  sliceRelPosFilter->Update();
+  typename FloatImageType::Pointer map = sliceRelPosFilter->GetFuzzyMap();
+  writeImage<FloatImageType>(map, "fuzzy_0_"+toString(clitk::rad2deg(angle))+".mha");
+
+  // Resize object like map to allow SetBackground
+  ImagePointer temp = clitk::ResizeImageLike<ImageType>(object, map, GetBackgroundValue());
+  //  writeImage<FloatImageType>(map, "fuzzy_1_"+toString(clitk::rad2deg(angle))+".mha");
+  
+  // Remove initial object from the fuzzy map
+  map = clitk::SetBackground<FloatImageType, ImageType>(map, temp, GetForegroundValue(), 0.0, true);
+  writeImage<FloatImageType>(map, "fuzzy_2_"+toString(clitk::rad2deg(angle))+".mha");
+  
+  // Resize the fuzzy map like the target, put 2.0 when outside
+  map = clitk::ResizeImageLike<FloatImageType>(map, target, 2.0);  // Put 2.0 when out of initial map
+  writeImage<FloatImageType>(map, "fuzzy_3_"+toString(clitk::rad2deg(angle))+".mha");
   
-  // Final Step -> set output TODO
-  // this->SetNthOutput(0, working_image);
-  //  this->GraftOutput(working_image);
+  // end
+  return map;
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::RelativePositionAnalyzerFilter<ImageType>::
+ComputeOptimalThresholds(FloatImageType * map, ImageType * target, int bins, double tolerance, 
+                         double & threshold, double & reverseThreshold)
+{
+  // Get the histogram of fuzzy values inside the target image
+  typedef itk::LabelStatisticsImageFilter<FloatImageType, ImageType> FloatStatFilterType;
+  typename FloatStatFilterType::Pointer f = FloatStatFilterType::New();
+  f->SetInput(map);
+  f->SetLabelInput(target);
+  f->UseHistogramsOn();
+  f->SetHistogramParameters(bins, 0.0-(1.0/bins), 1.0+(1.0/bins));
+  f->Update();
+  int count = f->GetCount(GetForegroundValue());
+  // DD(count);
+  typename FloatStatFilterType::HistogramPointer h = f->GetHistogram(GetForegroundValue());
+
+  // Debug : dump histogram
+  static int i=0;
+  std::ofstream histogramFile(std::string("fuzzy_histo_"+toString(i)+".txt").c_str());
+  for(int j=0; j<bins; j++) {
+    histogramFile << h->GetMeasurement(j,0) 
+                  << "\t" << h->GetFrequency(j) 
+                  << "\t" << (double)h->GetFrequency(j)/(double)count << std::endl;
+  }
+  histogramFile.close();  
+  std::ofstream histogramFile2(std::string("fuzzy_histo_R_"+toString(i)+".txt").c_str());
+  for(int j=bins-1; j>=0; j--) {
+    histogramFile2 << h->GetMeasurement(j,0) 
+                  << "\t" << h->GetFrequency(j) 
+                  << "\t" << (double)h->GetFrequency(j)/(double)count << std::endl;
+  }
+  histogramFile2.close();  
+  i++;
+
+  // Analyze the histogram (direct)
+  double sum = 0.0;
+  bool found = false;
+  threshold = 0.0;
+  for(int j=0; j<bins-1; j++) {
+    sum += ((double)h->GetFrequency(j)/(double)count);
+     // DD(j);
+     // DD(sum);
+     // DD(threshold);
+     // DD(h->GetBinMin(0,j));
+     // DD(h->GetBinMax(0,j));
+    if ((!found) && (sum > tolerance)) {
+      // We consider as threshold the laste before current, because 
+      if (j==0) 
+        threshold = h->GetBinMin(0,j);
+      else threshold = h->GetBinMin(0,j-1); // FIXME  ? the last before reaching the threshold
+      // DD(threshold);
+      found = true;
+      j = bins;
+    }
+  }
+
+  // Analyze the histogram (reverse)
+  sum = 0.0;
+  found = false;
+  reverseThreshold = 1.0;
+  for(int j=bins-1; j>0; j--) {
+    sum += ((double)h->GetFrequency(j)/(double)count);
+     // DD(j);
+     // DD(sum);
+     // DD(reverseThreshold);
+     // DD(h->GetBinMin(0,j));
+     // DD(h->GetBinMax(0,j));
+    if ((!found) && (sum > tolerance)) {
+      if (j==bins-1) 
+      reverseThreshold = h->GetBinMax(0,j);
+      else reverseThreshold = h->GetBinMax(0,j-1);// FIXME  ? the last before reaching the threshold
+      // DD(reverseThreshold);
+      found = true;
+      j = -1;
+    }
+  }
+
 }
 //--------------------------------------------------------------------