Beispiel #1
0
    void LoadFiles(int argc, char* argv[]) {
        itkcmds::itkImageIO<ImageType> io;
        itkcmds::itkImageIO<LabelType> io2;
        _src = io.ReadImageT(argv[1]);
        _dst = io.ReadImageT(argv[2]);
        _dstLabel = io2.ReadImageT(argv[3]);
        _transformOut = argv[4];
        _resampledOut = argv[5];

        cout << "Transform Output: " << _transformOut << endl;
        cout << "Resampled Output: " << _resampledOut << endl;

        ImageType::SizeType szDst = _dst->GetBufferedRegion().GetSize();
        itk::ContinuousIndex<double,3> szIdx;
        for (int i = 0; i < 3; i++) {
            szIdx[i] = szDst[i] / 2.0;
        }
        _dst->TransformContinuousIndexToPhysicalPoint(szIdx, _dstCenter);

        itk::ImageRegionConstIteratorWithIndex<LabelType> labelIter(_dstLabel, _dstLabel->GetBufferedRegion());
        for (labelIter.GoToBegin(); !labelIter.IsAtEnd(); ++labelIter) {
            LabelType::PixelType label = labelIter.Get();
            if (label > 0) {
                _labelIndexes.push_back(labelIter.GetIndex());
            }
        }

        _centerOfRotation.SetSize(ImageType::ImageDimension);
        for (int i = 0; i < 3; i++) {
            _centerOfRotation[i] = _dstCenter[i];
        }
    }
Beispiel #2
0
FuzzyCMeans::FuzzyCMeans(QVector<ClusterPoint2D> &points, QVector<ClusterCentroid2D> &clusters, float fuzzy, imageType::Pointer myImage, int numCluster)
{
    this->Eps = std::pow(10, -5);
        this->isConverged=false;
        this->Points = points;
        this->Clusters = clusters;
        this->myImageHeight = myImage->GetBufferedRegion().GetSize()[0];
        this->myImageWidth = myImage->GetBufferedRegion().GetSize()[1];
        this->myImage = myImage;
        U= boost::numeric::ublas::matrix<double>(Points.size(),Clusters.size());
        this->Fuzzyness = fuzzy;

        double diff;


        imageType::SizeType size;
        size[0]=myImageWidth; // x axis
        size[1]=myImageHeight; // y
        imageType::RegionType region;
        region.SetSize(size);
        imageType::Pointer image = imageType::New();
        image->SetRegions(region);
        image->Allocate(); // immagine create

        // Iterate through all points to create initial U matrix
        for (int i = 0; i < Points.size()-1; i++)
        {
            ClusterPoint2D p = Points.at(i);
            double sum = 0.0;

            for (int j = 0; j < Clusters.size()-1; j++)
            {
                ClusterCentroid2D c = Clusters.at(j);
                diff = std::sqrt(std::pow(CalculateEuclideanDistance(p, c), 2.0));
                //U(i, j) = (diff == 0) ? Eps : diff;
                if (diff==0){
                    U(i,j)=Eps;
                }
                else{
                    U(i,j)=diff;
                }
                sum += U(i, j);
            }
         }

        this->RecalculateClusterMembershipValues();
}
Beispiel #3
0
static void createPhantomParticles(ImageType::Pointer edgeImg) {
    PointVectorType phantoms;
    itk::ImageRegionConstIteratorWithIndex<ImageType> iter(edgeImg, edgeImg->GetBufferedRegion());
    for (iter.GoToBegin(); !iter.IsAtEnd(); ++iter) {
        if (iter.Get() > 0) {
            phantoms.push_back(iter.GetIndex()[0]);
            phantoms.push_back(iter.GetIndex()[1]);
        }
    }
    g_phantomParticles.push_back(phantoms);
}
    void LoadFiles(int argc, char* argv[]) {
        itkcmds::itkImageIO<ImageType> io;
        itkcmds::itkImageIO<LabelType> io2;
        _src = io.ReadImageT(argv[2]);
        _dst = io.ReadImageT(argv[3]);
        _dstLabel = io2.ReadImageT(argv[4]);
        _transformOut = argv[5];
        _resampledOut = argv[6];

        cout << "Transform Output: " << _transformOut << endl;
        cout << "Resampled Output: " << _resampledOut << endl;

        ImageType::SizeType szDst = _dst->GetBufferedRegion().GetSize();
        itk::ContinuousIndex<double,3> szIdx;
        for (int i = 0; i < 3; i++) {
            szIdx[i] = szDst[i] / 2.0;
        }
        _dst->TransformContinuousIndexToPhysicalPoint(szIdx, _dstCenter);
    }
Beispiel #5
0
void loadMask(QString f) {
    itkcmds::itkImageIO<ImageType> io;
    ImageType::Pointer img = io.ReadImageT(f.toAscii().data());
    g_boundaryMapList.push_back(img);

    ScalarToRGBFilter::Pointer rgbFilter1 = ScalarToRGBFilter::New();
    rgbFilter1->SetInput(img);
    rgbFilter1->SetAlphaValue(128);
    rgbFilter1->Update();
    BitmapType::Pointer maskBitmap = rgbFilter1->GetOutput();
    g_maskBitmapList.push_back(maskBitmap);

    DistanceMapFilter::Pointer distmapFilter = DistanceMapFilter::New();
    distmapFilter->SetInput(img);
    distmapFilter->Update();
    ImageType::Pointer distImg = distmapFilter->GetOutput();
    g_distanceMapList.push_back(distmapFilter->GetOutput());
    
    DistanceVectorImageType::Pointer distVector = distmapFilter->GetVectorDistanceMap();
    g_distanceVectorList.push_back(distVector);

    ScalarToRGBFilter::Pointer rgbFilter = ScalarToRGBFilter::New();
    rgbFilter->SetInput(distImg);
    rgbFilter->SetNumberOfThreads(8);
    rgbFilter->Update();
    BitmapType::Pointer rgbImage = rgbFilter->GetOutput();
    g_distanceMapBitmapList.push_back(rgbImage);

    EdgeDetectionFilterType::Pointer edgeFilter = EdgeDetectionFilterType::New();
    edgeFilter->SetInput(img);
    edgeFilter->Update();
    ImageType::Pointer edgeImg = edgeFilter->GetOutput();

    PointVectorType phantoms;
    itk::ImageRegionConstIteratorWithIndex<ImageType> iter(edgeImg, edgeImg->GetBufferedRegion());
    for (iter.GoToBegin(); !iter.IsAtEnd(); ++iter) {
        if (iter.Get() > 0) {
            phantoms.push_back(iter.GetIndex()[0]);
            phantoms.push_back(iter.GetIndex()[1]);
        }
    }
    g_phantomParticles.push_back(phantoms);}
        virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
        {
            std::string ext = osgDB::getLowerCaseFileExtension(file);
            if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;

            std::string fileName = osgDB::findDataFile( file, options );
            if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;

            notice()<<"Reading DICOM file "<<fileName<<std::endl;

            typedef unsigned short PixelType;
            const unsigned int Dimension = 3;
            typedef itk::Image< PixelType, Dimension > ImageType;


            typedef itk::ImageFileReader< ImageType > ReaderType;
            ReaderType::Pointer reader = ReaderType::New();
            reader->SetFileName( fileName.c_str() );

            typedef itk::GDCMImageIO           ImageIOType;
            ImageIOType::Pointer gdcmImageIO = ImageIOType::New();
            reader->SetImageIO( gdcmImageIO );

            try
            {
                reader->Update();
            }
            catch (itk::ExceptionObject & e)
            {
                std::cerr << "exception in file reader " << std::endl;
                std::cerr << e.GetDescription() << std::endl;
                std::cerr << e.GetLocation() << std::endl;
                return ReadResult::ERROR_IN_READING_FILE;
            }
            
            ImageType::Pointer inputImage = reader->GetOutput();
            
            ImageType::RegionType region = inputImage->GetBufferedRegion();
            ImageType::SizeType size = region.GetSize();
            ImageType::IndexType start = region.GetIndex();
            
            //inputImage->GetSpacing();
            //inputImage->GetOrigin();
            
            unsigned int width = size[0];
            unsigned int height = size[1];
            unsigned int depth = size[2];
            
            osg::RefMatrix* matrix = new osg::RefMatrix;
            
            notice()<<"width = "<<width<<" height = "<<height<<" depth = "<<depth<<std::endl;
            for(unsigned int i=0; i<Dimension; ++i)
            {
                (*matrix)(i,i) = inputImage->GetSpacing()[i];
                (*matrix)(3,i) = inputImage->GetOrigin()[i];
            }
            
            osg::Image* image = new osg::Image;
            image->allocateImage(width, height, depth, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1);

            unsigned char* data = image->data();            
            typedef itk::ImageRegionConstIterator< ImageType > IteratorType;
            IteratorType it(inputImage, region);
            
            it.GoToBegin();
            while (!it.IsAtEnd())
            {
                *data = it.Get();
                ++data;
                ++it;
            }
            
            image->setUserData(matrix);
            
            matrix->preMult(osg::Matrix::scale(double(image->s()), double(image->t()), double(image->r())));

            return image;
        }
int main(int argc, char *argv[])
{

  //check that the user specified the right number of command line arguments
  if(argc < 3)
    {
    cerr << argv[0] << " <input file> <output file>" << endl;
    cerr << argv[0] << " <raw input file> <sizeX> <sizeY> <sizeZ> <output file>"
         << endl;
    return EXIT_FAILURE;
    }

  //check if the input image is .raw
  bool rawInput = false;
  string inputFileName = argv[1];
  const char *outputFileName;
  //double space[3]={1,1,1};
  if(inputFileName.rfind(".raw") != string::npos)
    {
    //if so, the user is also required to pass in image dimensions
    if(argc < 6)
      {
      cerr << "Usage: <raw input file> <sizeX> <sizeY> <sizeZ> <output file>" << endl;
      return EXIT_FAILURE;
      }
    rawInput = true;
    sizeX = atoi(argv[2]);
    sizeY = atoi(argv[3]);
    sizeZ = atoi(argv[4]);
    outputFileName = argv[5];
    }
  else
    {
    outputFileName = argv[2];
    }

  FILE *infile = 0;
  FILE *outfile;
  int i,j,k;
  int ii, jj, kk;
  DATATYPEOUT *volout;
  long idx;

 
  int sizeExpand = 0;
  DATATYPEOUT blockMax;
  int timesDilate;
  int border;
  unsigned short *GraphcutResults;

  cout << "Volume Processing..." << endl;
  //make sure we can write to the output file
  if((outfile=fopen(outputFileName, "wb")) == NULL)
    {
    cerr << "Output file open error!" << endl;
    return EXIT_FAILURE;
    }

 
    typedef float     PixelType;
    const   unsigned int      Dimension = 3;
    typedef itk::Image< PixelType, Dimension >    ImageType;
    ImageType::Pointer inputImage;

   if(rawInput)
    {
    if((infile=fopen(inputFileName.c_str(), "rb"))==NULL)
      {
      cout << "Input file open error!" << endl;
      return EXIT_FAILURE;
      }

    volin = (DATATYPEIN*)malloc(sizeX*sizeY*(sizeZ+sizeExpand*2)*sizeof(DATATYPEIN));

    if (fread(volin, sizeof(DATATYPEIN), sizeX*sizeY*sizeZ, infile) < (unsigned int)(sizeX*sizeY*sizeZ))
      {
      cerr << "File size is not the same as volume size" << endl;
      return EXIT_FAILURE;
      }
    
	inputImage = ImageType::New();

	ImageType::PointType origin;
    origin[0] = 0.; 
    origin[1] = 0.;    
    origin[2] = 0.;    
	inputImage->SetOrigin( origin );

	ImageType::IndexType start;
    start[0] =   0;  
    start[1] =   0;  
	start[2] =   0;  

	ImageType::SizeType  size;
    size[0]  = sizeX;  
    size[1]  = sizeY;  
	size[2]  = sizeZ;  

    ImageType::RegionType region;
    region.SetSize( size );
    region.SetIndex( start );
    
    inputImage->SetRegions( region );
    inputImage->Allocate();
    inputImage->FillBuffer(0);
	inputImage->Update();
	
	typedef itk::ImageRegionIteratorWithIndex< ImageType > IteratorType;
	IteratorType iterator1(inputImage,inputImage->GetRequestedRegion());
	int lng = sizeX*sizeY*sizeZ;
	
	for(int i=0; i<lng; i++)
	{
	 iterator1.Set((float)volin[i]);
	 ++iterator1;	
	}
  } // end if(rawInput)

   else
    {
  
    typedef itk::ImageFileReader< ImageType >  ReaderType;
    ReaderType::Pointer reader = ReaderType::New();

    inputImage = reader->GetOutput();
    reader->SetFileName( inputFileName.c_str()  );
    try 
      { 
      reader->Update(); 
      } 
    catch( itk::ExceptionObject & err ) 
      { 
      cerr << "ExceptionObject caught!" << endl; 
      cerr << err << endl; 
      return EXIT_FAILURE;
      } 
	} // end of itk image read 

 
	 // ---------------Linear Mapping --------------------//
    typedef itk::RescaleIntensityImageFilter<
               ImageType, ImageType>  RescaleFilterType;
    RescaleFilterType::Pointer    rescaleFilter    = RescaleFilterType::New();
    rescaleFilter->SetInput(inputImage);
	rescaleFilter->SetOutputMinimum(  0 );
    rescaleFilter->SetOutputMaximum( 255 );
	
	try 
      { 
       rescaleFilter->Update();
      } 
    catch( itk::ExceptionObject & err ) 
      { 
      cerr << "ExceptionObject caught!" << endl; 
      cerr << err << endl; 
      return EXIT_FAILURE;
      }

	inputImage = rescaleFilter->GetOutput();
	cout << "The Linear Mapping is done\n";

    # if Curvature_Anistropic_Diffusion 
	{
     cout << "The Curvature Diffusion is doing\n"; 
	 typedef itk::CurvatureAnisotropicDiffusionImageFilter<
               ImageType, ImageType >  MCD_FilterType;

     MCD_FilterType::Pointer MCDFilter = MCD_FilterType::New();
    
     //Initialnization,  using the paper's optimal parameters
     const unsigned int numberOfIterations = 5;
     const double       timeStep = 0.0425;
     const double       conductance = 3;
     MCDFilter->SetNumberOfIterations(numberOfIterations);
     MCDFilter->SetTimeStep( timeStep );
     MCDFilter->SetConductanceParameter( conductance );
     MCDFilter->SetInput(inputImage);
	 try 
      { 
       MCDFilter->Update();
      } 
     catch( itk::ExceptionObject & err ) 
      { 
      cerr << "ExceptionObject caught!" << endl; 
      cerr << err << endl; 
      return EXIT_FAILURE;
      } 
     inputImage=MCDFilter->GetOutput(); 
     cout << "The Curvature Diffusion is done\n";
	}
	#endif

    ImageType::RegionType region = inputImage->GetBufferedRegion();
    ImageType::SizeType  size = region.GetSize();
    cout << "input image size: " << size << endl;
    sizeX = size[0];
    sizeY = size[1];
    sizeZ = size[2];
    itk::ImageRegionIterator< ImageType >
      itr( inputImage, inputImage->GetBufferedRegion() );
    itr.GoToBegin();
    idx = 0;
    volin = (DATATYPEIN*)malloc(sizeX*sizeY*(sizeZ+sizeExpand*2)*sizeof(DATATYPEIN));
    while( ! itr.IsAtEnd() )
      {
      volin[idx] = itr.Get();
      ++itr;
      ++idx;
      }
  //allocate memory for the output image
  volout = (DATATYPEOUT*)malloc(sizeX*sizeY*(sizeZ+sizeExpand*2)*sizeof(DATATYPEOUT));
  
  // one pre-processing  scheme 
  
  GraphcutResults = (unsigned short*)malloc(sizeX*sizeY*(sizeZ+sizeExpand*2)*sizeof(unsigned short));
  Neuron_Binarization_3D(volin,GraphcutResults,sizeX,sizeY,sizeZ,0,1);
  
  for (k=0; k<(sizeZ+sizeExpand*2); k++)
      for (j=0; j<sizeY; j++)
        for (i=0; i<sizeX; i++) {
          volout[k *sizeX*sizeY + j *sizeX + i] = 0; 
        }  //initial to zeros
   
  
  std::cout << "Do you think we need the distance transform to make the centerline of image become bright with higher intensity?";
  
  char tmpAnswer = 'n';
  //tmpAnswer = getchar();
  if (tmpAnswer =='Y' || tmpAnswer =='y')
  {
  unsigned char *GraphcutResultsTmp;
  GraphcutResultsTmp = (unsigned char*)malloc(sizeX*sizeY*(sizeZ+sizeExpand*2)*sizeof(unsigned char));
  for (k=0; k<(sizeZ+sizeExpand*2); k++)
      for (j=0; j<sizeY; j++)
        for (i=0; i<sizeX; i++) 
		{
          GraphcutResultsTmp[k *sizeX*sizeY + j *sizeX + i] = (unsigned char) GraphcutResults[k *sizeX*sizeY + j *sizeX + i]; 
        }  //initial to zeros

  distTransform(GraphcutResultsTmp,sizeX,sizeY,sizeZ);
  
  for (k=0; k<sizeZ; k++)
    {
    // threshold first
     for (j=0; j<sizeY; j++)
       {
       for (i=0; i<sizeX; i++)
        {
        idx = k *sizeX*sizeY + j *sizeX + i;
        volin[idx] = GraphcutResultsTmp [idx];
        } // end for 
      } // end for 
    } // end for 
  
  free(GraphcutResultsTmp);
  GraphcutResultsTmp=NULL;
  } // end if 

  else {
 
   for (k=0; k<sizeZ; k++)
    {
    // threshold first
     for (j=0; j<sizeY; j++)
       {
       for (i=0; i<sizeX; i++)
        {
        idx = k *sizeX*sizeY + j *sizeX + i;
		
        if (GraphcutResults [idx] == 0) 
          {
          volin[idx] = 0;
          }
        }
      }
    }   

 } // end else

 free(GraphcutResults);
 GraphcutResults=NULL;

  // the secpnd Pre-Processing method, corresponding to the old version MDL 
  /*
  double threshold; 
  // by xiao liang, using 3 sigma theory to estimate threshold;
  double meanValue =0.0, VarianceValue =  0.0;

  // threshold first
  for (k=0; k<sizeZ; k++)
    {
    for (j=0; j<sizeY; j++) 
      {
      for (i=0; i<sizeX; i++)
        {
        idx = k *sizeX*sizeY + j *sizeX + i;
        meanValue += volin[idx];
        }
      }
    }

  meanValue = meanValue/(double)(sizeX*sizeY*sizeZ);
  // threshold first
  for (k=0; k<sizeZ; k++)
    {
    for (j=0; j<sizeY; j++) 
      {
      for (i=0; i<sizeX; i++)
        {
        idx = k *sizeX*sizeY + j *sizeX + i;
        VarianceValue += (volin[idx]-meanValue)*(volin[idx]-meanValue);
        }
      }
    }

  VarianceValue =  VarianceValue/(double)(sizeX*sizeY*sizeZ);
  VarianceValue = sqrt(VarianceValue);

  double m_threshold=OtsuThreshold (sizeX,sizeY,sizeZ);
  if (m_threshold > 7 || m_threshold < 0)
    {
    threshold =(meanValue-VarianceValue/30); 
    }
  else
    {
    threshold = m_threshold;
    }

  //threshold =7;
  cout << "OTSU optimal threshold " << threshold << endl;

     for (k=0; k<(sizeZ+sizeExpand*2); k++)
      for (j=0; j<sizeY; j++)
        for (i=0; i<sizeX; i++) {

          volout[k *sizeX*sizeY + j *sizeX + i] = 0; 
        }  //initial to zeros

  for (k=0; k<sizeZ; k++)
    {
    // threshold first
    for (j=0; j<sizeY; j++)
      {
      for (i=0; i<sizeX; i++)
        {
        idx = k *sizeX*sizeY + j *sizeX + i;
        if (volin[idx] < threshold) 
          {
          volin[idx] = 0;
          }
        }
      }
    }   
  */
  // Method 2: Dilation of the object
  timesDilate = 1;
  border = 3;
  while (timesDilate >0 )
    {
    for (k=border; k<sizeZ-border; k++)
      {
      for (j=border; j<sizeY-border; j++)
        {
        for (i=border; i<sizeX-border; i++)
          {
          blockMax = volin[k *sizeX*sizeY + j *sizeX + i];
          for (kk=-1; kk<=1; kk++)
            {
            for (jj=-1; jj<=1; jj++)
              {
              for (ii=-1; ii<=1; ii++)
                {
                if(volin[(k+kk)*sizeX*sizeY + (j+jj)*sizeX + (i+ii)] > blockMax) 
                  {
                  blockMax = volin[(k+kk)*sizeX*sizeY + (j+jj)*sizeX + (i+ii)];
                  }
                }
              }
            }
          // Keep the peak of the original intensity
          if (blockMax == volin[k *sizeX*sizeY + j *sizeX + i] && blockMax != 0)
            {
            blockMax = blockMax + 1;
            //if (blockMax > 255)   blockMax = 255;
            }
          volout[k *sizeX*sizeY + j *sizeX + i] = blockMax;
          }
        }
      }

    // copy volout back to volin for the next dilation
    for (k=0; k<sizeZ; k++) 
      {
      for (j=0; j<sizeY; j++) 
        {
        for (i=0; i<sizeX; i++)
          {
          volin[k *sizeX*sizeY + j *sizeX + i] = volout[k *sizeX*sizeY + j *sizeX + i];
          }
        }
      }
    timesDilate--;
    }

  //-----  Image write 
   /*
    typedef itk::ImageRegionIteratorWithIndex< ImageType > IteratorType;
	IteratorType iterator1(inputImage,inputImage->GetRequestedRegion());
	int lng = sizeX*sizeY*sizeZ;
	
	for(int i=0; i<lng; i++)
	{
	 iterator1.Set((float)volin[i]);
	 ++iterator1;	
	}
   */
  //write the output image and free memory
  fwrite(volout, sizeX*sizeY*sizeZ, sizeof(DATATYPEOUT), outfile);
  FILE *mhdfile;
  
  if((mhdfile=fopen("volume_Processed.mhd","w"))==NULL)
    {
    cerr << "output file open error!" << endl;
    return -1;
    }
  fprintf (mhdfile,"ObjectType = Image\n");
  fprintf (mhdfile,"NDims = 3\n");
  fprintf (mhdfile,"BinaryData = True\n");
  fprintf (mhdfile,"BinaryDataByteOrderMSB = False\n");
  fprintf (mhdfile,"CompressedData = False\n");
  fprintf (mhdfile,"TransformMatrix = 1 0 0 0 1 0 0 0 1\n");
  fprintf (mhdfile,"Offset = 0 0 0\n");
  fprintf (mhdfile,"CenterOfRotation = 0 0 0\n");
  fprintf (mhdfile,"AnatomicalOrientation = RAI\n");
  fprintf (mhdfile,"ElementSpacing = 1 1 1\n");
  fprintf (mhdfile,"DimSize = %d %d %d\n",sizeX,sizeY,sizeZ);
  fprintf (mhdfile,"ElementType = MET_UCHAR\n");
  fprintf (mhdfile,"ElementDataFile = volume_Processed.raw\n");
  fclose(mhdfile);

  if (rawInput)
	  fclose(infile);
  fclose(outfile);

  free(volin);  // by xiao
  free(volout); // by xiao
  volin=NULL;
  volout=NULL;

  //cout << "Done" << endl;
  return 0;
}
    void RunRegistration() {
        _transform = TransformType::New();
        OptiReporter::Pointer optiReporter = OptiReporter::New();
        Metric::Pointer metric = Metric::New();
        metric->SetFixedImage(_dst);
        bool useIndexes = false;
        if (useIndexes) {
            _centerOfRotation.SetSize(ImageType::ImageDimension);
            for (int i = 0; i < ImageType::ImageDimension; i++) {
                _centerOfRotation[i] = i;
            }
            itk::ImageRegionConstIteratorWithIndex<LabelType> labelIter(_dstLabel, _dstLabel->GetBufferedRegion());
            int nPixels = 0;
            for (labelIter.GoToBegin(); !labelIter.IsAtEnd(); ++labelIter) {
                LabelType::PixelType label = labelIter.Get();
                if (label > 0) {
                    _labelIndexes.push_back(labelIter.GetIndex());
                    for (int i = 0; i < ImageType::ImageDimension; i++) {
                        _centerOfRotation[i] += labelIter.GetIndex()[i];
                    }
                    nPixels ++;
                }
            }
            for (int i = 0; i < ImageType::ImageDimension; i++) {
                _centerOfRotation[i] /= nPixels;
            }
            metric->SetFixedImageIndexes(_labelIndexes);
            _transform->SetFixedParameters(_centerOfRotation);
        } else {
            metric->SetFixedImageRegion(_dst->GetBufferedRegion());
            metric->SetUseAllPixels(true);
            _centerOfRotation.SetSize(ImageType::ImageDimension);
            for (int i = 0; i < 3; i++) {
                _centerOfRotation[i] = _dstCenter[i];
            }
            _transform->SetFixedParameters(_centerOfRotation);
        }

        cout << "Fixed Parameters: " << _centerOfRotation << endl;

        metric->SetMovingImage(_src);
        metric->SetInterpolator(Interpolator::New());
        metric->SetTransform(_transform);
        metric->Initialize();

        Optimizer::Pointer opti = Optimizer::New();
        opti->SetCostFunction(metric);
        Optimizer::ScalesType scales;
        scales.SetSize(TransformType::ParametersDimension);
        scales.Fill(1);
        if (_method == "affine") {
            cout << "apply affine scaling ..." << endl;
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    if (i == j) {
                        scales[3*i+j] = 160;
                    } else {
                        scales[3*i+j] = 30;
                    }
                }
            }
            scales[9] = scales[10] = scales[11] = 0.1;
        } else if (_method == "scale") {
            scales[0] = scales[1] = scales[2] = 30;
            scales[3] = scales[4] = scales[5] = .5;
            scales[6] = scales[7] = scales[8] = 100;
        } else if (_method == "similar") {
            scales[0] = scales[1] = scales[2] = 10;
            scales[3] = scales[4] = scales[5] = 0.5;
            scales[6] = 100;
        }
        opti->SetScales(scales);

        const int maxIters = 100;
#ifdef USE_CG_OPTIMIZER
        opti->SetMaximumIteration(maxIters);
        opti->SetMaximumLineIteration(10);
        opti->SetUseUnitLengthGradient(true);
        opti->SetStepLength(1);
        opti->SetToFletchReeves();
#endif

#ifdef USE_GD_OPTIMIZER
        opti->SetNumberOfIterations(maxIters);
        opti->SetMinimumStepLength(1e-4);
        opti->SetMaximumStepLength(3);
        opti->SetRelaxationFactor(.5);
        opti->SetGradientMagnitudeTolerance(1e-4);
#endif

        opti->SetInitialPosition(_transform->GetParameters());
        opti->AddObserver(itk::StartEvent(), optiReporter);
        opti->AddObserver(itk::IterationEvent(), optiReporter);
        opti->StartOptimization();
        cout << "Current Cost: " << opti->GetValue() << endl;
        _transformResult = opti->GetCurrentPosition();
        _transform->SetParameters(opti->GetCurrentPosition());
    }
//calculate segmentation values
bool CTImageTreeItem::internalGetSegmentationValues( SegmentationValues &values) const {
	
	//get ITK image
	ImageType::Pointer image = getITKImage();
	if (image.IsNull()) 
		return false;

	//get buffered region of the image
	ImageType::RegionType ctregion = image->GetBufferedRegion();
	//define an iterator for the binary segment
	typedef itk::ImageRegionConstIteratorWithIndex< BinaryImageType > BinaryIteratorType;
	//get binary segment
	BinaryImageTreeItem::ImageType::Pointer segment = values.m_segment->getITKImage();
	if (segment.IsNull()) 
		return false;

/*	typedef itk::ImageFileWriter< ImageType >  WriterType;
	WriterType::Pointer writer = WriterType::New();
	writer->SetFileName( "test.dcm" );

	writer->SetInput( image );
		try 
		{
			writer->Update();
		}
		catch( itk::ExceptionObject & excep )
		{
			std::cerr << "Exception catched !" << std::endl;
			std::cerr << excep << std::endl;
		}
*/
	//create a binary iterator for the segment and its buffered region
	BinaryIteratorType binIter( segment, segment->GetBufferedRegion() );
	ImageType::PointType point;
  
	//The Accumulators Framework is framework for performing incremental calculations
	using namespace boost::accumulators;
	//http://boost-sandbox.sourceforge.net/libs/accumulators/doc/html/accumulators/user_s_guide.html#accumulators.user_s_guide.the_accumulators_framework
	accumulator_set<double,features<tag::count, tag::min, tag::mean, tag::max, tag::variance> > acc;  
  
	//check selected accuracy
	if (values.m_accuracy == SegmentationValues::SimpleAccuracy) {
		ImageType::IndexType index;
		//iterate over the pixel of the binary segment
		for(binIter.GoToBegin(); !binIter.IsAtEnd(); ++binIter) {
			//if actual value = 255
			if (binIter.Value() == BinaryPixelOn) {
				//transforms the index to a physical point in the binary segment
				segment->TransformIndexToPhysicalPoint(binIter.GetIndex(),point);
				//transform that point to an index of the CT image
				image->TransformPhysicalPointToIndex(point, index);
				//check if that index is inside the CT region
				if (ctregion.IsInside(index)) {
					//get the pixel value at the index
					int t = image->GetPixel(index);
					//check if pixel value != -2048
					if (isRealHUvalue(t)) {
						//accumulate pixel value
						acc( t );
					}
				}
			}
		}
	//check selected accuracy
	} else if (values.m_accuracy == SegmentationValues::PreventDoubleSamplingAccuracy) {
		ImageType::IndexType index;
		//definition for a set of indices, which can be compared
		typedef std::set< ImageType::IndexType, IndexCompareFunctor > IndexSetType;
		IndexSetType indexSet;
		//iterate over the pixel of the binary segment
		for(binIter.GoToBegin(); !binIter.IsAtEnd(); ++binIter) {
			//if actual value = 255
			if (binIter.Value() == BinaryPixelOn) {
				//transforms the index to a physical point in the binary segment
				segment->TransformIndexToPhysicalPoint(binIter.GetIndex(),point);
				//transform that point to an index of the CT image
				image->TransformPhysicalPointToIndex(point, index);
				//check if that index is inside the CT region
				if (ctregion.IsInside(index)) {

					std::pair<IndexSetType::iterator,IndexSetType::iterator> ret;
					//
					ret = indexSet.equal_range(index);
					//If x does not match any key in the container, the range returned has a length of zero, 
					//with both iterators pointing to the nearest value greater than x, if any, 
					//or to set::end if x is greater than all the elements in the container.
					if (ret.first == ret.second) {
						indexSet.insert(ret.first, index);
						//get the pixel value at the index
						int t = image->GetPixel(index);
						//check if pixel value != -2048
						if (isRealHUvalue(t)) {
							//accumulate pixel value
							acc( t );
						}
					}
				}
			}
		}
	//check selected accuracy
	} else if (values.m_accuracy == SegmentationValues::InterpolatedAccuracy) {
		//define an interpolate function
		typedef  itk::LinearInterpolateImageFunction< CTImageType > InterpolatorType;
		InterpolatorType::Pointer interpolator = InterpolatorType::New();
		//set input to the interpolator
		interpolator->SetInputImage( image );
		InterpolatorType::ContinuousIndexType index;
		//iterate over the pixel of the binary segment
		for(binIter.GoToBegin(); !binIter.IsAtEnd(); ++binIter) {
			//if actual value = 255
			if (binIter.Value() == BinaryPixelOn) {
				//transforms the index to a physical point in the binary segment
				segment->TransformIndexToPhysicalPoint(binIter.GetIndex(),point);
				//transform that point to an index of the CT image
				image->TransformPhysicalPointToContinuousIndex(point, index);
				//check if the index is inside the buffer of the interpolator
				if (interpolator->IsInsideBuffer(index)) {
					//Returns the linearly interpolated image intensity
					int t = interpolator->EvaluateAtContinuousIndex(index);
					//check if pixel value != -2048
					if (isRealHUvalue(t)) {
						//accumulate pixel value
						acc( t );
					}
				}
			}
		}  
	}
	//set sample count, min, mean, max and standard deviation
	//from the accumulated intensities
	values.m_sampleCount = count( acc );
	values.m_min = min( acc );
	values.m_mean = mean( acc );
	values.m_max = max( acc );
	values.m_stddev = std::sqrt( variance( acc ) );
	//set the image modification time
	values.m_mtime = segment->GetMTime();
	const_cast<CTImageTreeItem*>(this)->m_segmentationValueCache[ values.m_segment ] = values;
	return values.m_sampleCount > 0;
}    
Beispiel #10
0
int main( int argc, char* argv[] )
{
    if( argc != 3 )
    {
        std::cerr << "Usage: "<< std::endl;
        std::cerr << argv[0];
        std::cerr << " <InputFileName> n";
        std::cerr << std::endl;
        return EXIT_FAILURE;
    }



    int operations = atoi(argv[2]);
    //sscanf(&operations,"%d",argv[2]);
    //printf("%d\n", operations);

    itk::TimeProbe itkClock;
    double t0 = 0.0;
    double tf = 0.0;

    itk::MultiThreader::SetGlobalDefaultNumberOfThreads(1);

    // Loading file
    ReaderType::Pointer reader = ReaderType::New();
    reader->SetFileName( argv[1] );
    reader->Update();
    ImageType::Pointer image = reader->GetOutput();

#ifdef GPU
    GPUReaderType::Pointer gpureader = GPUReaderType::New();
    gpureader->SetFileName( argv[1] );
    gpureader->Update();
    GPUImageType::Pointer gpuImage = gpureader->GetOutput();
#endif


    saveFile((char*) "/tmp/itk_input.dcm", image);

    // Allocate output image
    ImageType::Pointer output = ImageType::New();
    ImageType::RegionType region = image->GetBufferedRegion();
    output->SetRegions( region );
    output->SetOrigin(  image->GetOrigin()  );
    output->SetSpacing( image->GetSpacing() );
    output->Allocate();


    // Negative
    typedef itk::UnaryFunctorImageFilter<ImageType,ImageType,
                  Negate<ImageType::PixelType,ImageType::PixelType> > NegateImageFilterType;
 
    NegateImageFilterType::Pointer negateFilter = NegateImageFilterType::New();

    negateFilter = NegateImageFilterType::New();
    negateFilter->SetInput(image);
#ifndef GPU_only
    itkClock.Start();
    TimerStart();
    for(int n = 0; n < operations; n++)
    {
      negateFilter->Modified();
      negateFilter->Update();    
    }
    itkClock.Stop();
    printf("Tempo gasto para fazer %d negative: %s\n",operations, getTimeElapsedInSeconds());
    tf = itkClock.GetTotal();
    std::cout << "My: "    << (tf - t0) << std::endl;
    t0 = tf;
#endif
    // Saving Not result
    saveFile((char*) "/tmp/itk_not.dcm", negateFilter->GetOutput());


#ifdef GPU
    // GPU Negative
    typedef itk::GPUUnaryFunctorImageFilter<ImageType,ImageType,
                  Negate<ImageType::PixelType,ImageType::PixelType> > GPUNegateImageFilterType;
 
    GPUNegateImageFilterType::Pointer gpuNegateFilter = GPUNegateImageFilterType::New();
    gpuNegateFilter->SetInput(gpureader->GetOutput());
    gpuNegateFilter->Update();    
    // Saving Not result
    //saveFile("/tmp/itk_gpu_not.dcm", gpuNegateFilter->GetOutput());
#endif

    // Common Threshold
    int lowerThreshold = 100;
    int upperThreshold = 200;


    // Threshold
    typedef itk::BinaryThresholdImageFilter <ImageType, ImageType>
       BinaryThresholdImageFilterType;
    
    BinaryThresholdImageFilterType::Pointer thresholdFilter
      = BinaryThresholdImageFilterType::New();

    thresholdFilter = BinaryThresholdImageFilterType::New();
    thresholdFilter->SetInput(reader->GetOutput());
    thresholdFilter->SetLowerThreshold(lowerThreshold);
    thresholdFilter->SetUpperThreshold(upperThreshold);
    thresholdFilter->SetInsideValue(255);
    thresholdFilter->SetOutsideValue(0);
#ifndef GPU_only
    itkClock.Start();
    TimerStart();
    for(int n = 0; n < operations; n++)
    {
	thresholdFilter->Modified();
	thresholdFilter->Update();
    }
    itkClock.Stop();
    printf("Tempo gasto para fazer %d threshold: %s\n",operations, getTimeElapsedInSeconds());
    tf = itkClock.GetTotal();
    std::cout << "My: "    << (tf - t0) << std::endl;
    t0 = tf;
    // Saving Threshold result
    saveFile((char*) "/tmp/itk_thresh.dcm", thresholdFilter->GetOutput());
#endif


#ifdef GPU
    // GPU Threshold

    typedef itk::GPUBinaryThresholdImageFilter <GPUImageType, GPUImageType> 
			GPUBinaryThresholdImageFilterType;
    
    GPUBinaryThresholdImageFilterType::Pointer gpuThresholdFilter
      = GPUBinaryThresholdImageFilterType::New();

    gpuThresholdFilter->SetInput(gpureader->GetOutput());
    gpuThresholdFilter->SetLowerThreshold(lowerThreshold);
    gpuThresholdFilter->SetUpperThreshold(upperThreshold);
    gpuThresholdFilter->SetInsideValue(255);
    gpuThresholdFilter->SetOutsideValue(0);

    itkClock.Start();
    TimerStart();
    for(int n = 0; n < operations; n++)
    {
      gpuThresholdFilter->Modified();
      gpuThresholdFilter->Update();
    }
    itkClock.Stop();
    printf("Tempo gasto para fazer %d GPU threshold: %s\n",operations, getTimeElapsedInSeconds());
    tf = itkClock.GetTotal();
    std::cout << "My: "    << (tf - t0) << std::endl;
    t0 = tf;
    // Saving GPU Threshold result
    gpuThresholdFilter->GetOutput()->UpdateBuffers();
    saveFile((char*) "/tmp/itk_gpu_thresh.dcm", gpuThresholdFilter->GetOutput());
#endif

    // Mean
    typedef itk::MeanImageFilter< ImageType, ImageType > MeanFilterType;
    MeanFilterType::Pointer meanFilter = MeanFilterType::New();

    meanFilter = MeanFilterType::New();
    meanFilter->SetInput( image );
    meanFilter->SetRadius( 1 );
#ifndef GPU_only
    itkClock.Start();
    TimerStart();
    for(int n = 0; n < operations; n++)
    {
       meanFilter->Modified();
       meanFilter->Update();
    }
    itkClock.Stop();
    printf("Tempo gasto para fazer %d mean blur: %s\n",operations, getTimeElapsedInSeconds());
    tf = itkClock.GetTotal();
    std::cout << "My: "    << (tf - t0) << std::endl;
    t0 = tf;
    // Saving Convolution result
    saveFile((char*) "/tmp/itk_mean3x3.dcm", meanFilter->GetOutput());
#endif

    // Binomial Blur (aproximation of gaussian blur)
    typedef itk::BinomialBlurImageFilter<ImageType, ImageType> BinomialBlurImageFilterType;
 
    int repetitions = 1;
    BinomialBlurImageFilterType::Pointer blurFilter = BinomialBlurImageFilterType::New();

    blurFilter = BinomialBlurImageFilterType::New();
    blurFilter->SetInput( reader->GetOutput() );
    blurFilter->SetRepetitions( repetitions );
#ifndef GPU_only
    itkClock.Start();
    TimerStart();
    for(int n = 0; n < operations; n++)
    {
      blurFilter->Modified();
      blurFilter->Update();
    }
    itkClock.Stop();
    printf("Tempo gasto para fazer %d blur: %s\n",operations, getTimeElapsedInSeconds());
    tf = itkClock.GetTotal();
    std::cout << "My: "    << (tf - t0) << std::endl;
    t0 = tf;
    // Saving Blur result
    saveFile((char*) "/tmp/itk_blur.dcm", blurFilter->GetOutput());
#endif


#ifdef GPU
    // GPU Blur
    typedef itk::BoxImageFilter< GPUImageType, GPUImageType > BoxImageFilterType;
    typedef itk::GPUBoxImageFilter< GPUImageType, GPUImageType, BoxImageFilterType > GPUBoxImageFilterType;

    GPUBoxImageFilterType::Pointer GPUBlurFilter = GPUBoxImageFilterType::New();

	//ImageType::SizeType indexRadius;
	//indexRadius[0] = 2;
	//indexRadius[1] = 2;
	//indexRadius[2] = 2;

    GPUBlurFilter->SetInput(gpureader->GetOutput());
	//GPUBlurFilter->SetRadius(indexRadius);
    itkClock.Start();
    TimerStart();
    for(int n = 0; n < operations; n++)
    {
        GPUBlurFilter->Update();
        GPUBlurFilter->Modified();
    }
    itkClock.Stop();
    printf("Tempo gasto para fazer %d gpu blur: %s\n",operations, getTimeElapsedInSeconds());
    tf = itkClock.GetTotal();
    std::cout << "My: "    << (tf - t0) << std::endl;
    t0 = tf;
    GPUBlurFilter->GetOutput()->UpdateBuffers();
    // Saving GPU Blur result
    saveFile((char*) "/tmp/itk_gpu_blur.dcm", GPUBlurFilter->GetOutput());

#endif


    //Erosion Common
    typedef itk::BinaryBallStructuringElement<
      ImageType::PixelType, 3>                  StructuringElementType;
    typedef itk::GrayscaleErodeImageFilter <ImageType, ImageType, StructuringElementType>
      GrayscaleErodeImageFilterType;
    unsigned int radius;

    // Erosion 3x3
    StructuringElementType structuringElement3x3;
    radius = 1;
    structuringElement3x3.SetRadius(radius);
    structuringElement3x3.CreateStructuringElement();

    GrayscaleErodeImageFilterType::Pointer erodeFilter3x3;

    erodeFilter3x3= GrayscaleErodeImageFilterType::New();
    erodeFilter3x3->SetInput(reader->GetOutput());
    erodeFilter3x3->SetKernel(structuringElement3x3);
#ifndef GPU_only
    itkClock.Start();
    TimerStart();
    for(int n = 0; n < operations; n++)
    {
        erodeFilter3x3->Modified();
        erodeFilter3x3->Update();
    }
    itkClock.Stop();
    printf("Tempo gasto para fazer %d erosion 3x3: %s\n",operations, getTimeElapsedInSeconds());
    tf = itkClock.GetTotal();
    std::cout << "My: "    << (tf - t0) << std::endl;
    t0 = tf;

    // Saving Erosion result
    saveFile((char*) "/tmp/itk_erode3x3.dcm", erodeFilter3x3->GetOutput());
#endif

    // Erosion 5x5
    StructuringElementType structuringElement5x5;
    radius = 2;
    structuringElement5x5.SetRadius(radius);
    structuringElement5x5.CreateStructuringElement();

    GrayscaleErodeImageFilterType::Pointer erodeFilter5x5;

    erodeFilter5x5 = GrayscaleErodeImageFilterType::New();
    erodeFilter5x5->SetInput(reader->GetOutput());
    erodeFilter5x5->SetKernel(structuringElement5x5);
#ifndef GPU_only
    itkClock.Start();
    TimerStart();
    for(int n = 0; n < operations; n++)
    {
      erodeFilter5x5->Modified();
      erodeFilter5x5->Update();
    }
    itkClock.Stop();
    printf("Tempo gasto para fazer %d erosion 5x5: %s\n",operations, getTimeElapsedInSeconds());
    tf = itkClock.GetTotal();
    std::cout << "My: "    << (tf - t0) << std::endl;
    t0 = tf;

    // Saving Erosion result
    saveFile((char*) "/tmp/itk_erode5x5.dcm", erodeFilter5x5->GetOutput());
#endif

    // Copy
    typedef itk::ImageDuplicator< ImageType > DuplicatorType;
    DuplicatorType::Pointer duplicator;

    duplicator = DuplicatorType::New();
    duplicator->SetInputImage(image);
#ifndef GPU_only
    itkClock.Start();
    TimerStart();
    for(int n = 0; n < operations; n++)
    { 
       duplicator->Modified();
       duplicator->Update();
    }
    itkClock.Stop();
    printf("Tempo gasto para fazer %d copias cpu: %s\n",operations, getTimeElapsedInSeconds());
    tf = itkClock.GetTotal();
    std::cout << "My: "    << (tf - t0) << std::endl;
    t0 = tf;
    // Saving Copy result
    saveFile((char*) "/tmp/itk_copy.dcm", duplicator->GetOutput());
#endif

    // Convolution common
    typedef itk::ConvolutionImageFilter<ImageType> ConvolutionImageFilterType;

    ConvolutionImageFilterType::Pointer convolutionFilter;

    convolutionFilter = ConvolutionImageFilterType::New();
    convolutionFilter->SetInput(reader->GetOutput());
    int convWidth;

    // Convolution 3x3
    ImageType::Pointer kernel3x3 = ImageType::New();
    convWidth = 3;
    CreateKernel(kernel3x3, convWidth);

    convolutionFilter->SetKernelImage(kernel3x3);
#ifndef GPU_only
    itkClock.Start();
    TimerStart();
    for(int n = 0; n < operations; n++)
    {  
       convolutionFilter->Modified();
       convolutionFilter->Update();
    }
    itkClock.Stop();
    printf("Tempo gasto para fazer %d convolucoes 3x3 cpu: %s\n",operations, getTimeElapsedInSeconds());
    tf = itkClock.GetTotal();
    std::cout << "My: "    << (tf - t0) << std::endl;
    t0 = tf;
    // Saving Convolution result
    saveFile((char*) "/tmp/itk_convolution3x3.dcm", convolutionFilter->GetOutput());
#endif

    // Convolution 5x5
    ImageType::Pointer kernel5x5 = ImageType::New();
    convWidth = 5;
    CreateKernel(kernel5x5, convWidth);

    convolutionFilter->SetKernelImage(kernel5x5);
#ifndef GPU_only
    itkClock.Start();
    TimerStart();
    for(int n = 0; n < operations; n++)
    {  
       convolutionFilter->Modified();
       convolutionFilter->Update();
    }
    itkClock.Stop();
    printf("Tempo gasto para fazer %d convolucoes 5x5 cpu: %s\n",operations, getTimeElapsedInSeconds());
    tf = itkClock.GetTotal();
    std::cout << "My: "    << (tf - t0) << std::endl;
    t0 = tf;
    // Saving Convolution result
    saveFile((char*) "/tmp/itk_convolution5x5.dcm", convolutionFilter->GetOutput());
#endif

#ifdef GPU

    // GPU Mean
    typedef itk::GPUMeanImageFilter<GPUImageType, GPUImageType> GPUMeanFilterType;
	GPUMeanFilterType::Pointer GPUMean = GPUMeanFilterType::New();
	GPUMean->SetInput(gpureader->GetOutput());
	GPUMean->SetRadius( 1 );
	TimerStart();
	for(int n = 0; n < operations; n++)
	{
	   GPUMean->Update();
	   GPUMean->Modified();
	}
    itkClock.Stop();
    printf("Tempo gasto para fazer %d GPU mean blur: %s\n",operations, getTimeElapsedInSeconds());
    tf = itkClock.GetTotal();
    std::cout << "My: "    << (tf - t0) << std::endl;
    t0 = tf;
	GPUMean->GetOutput()->UpdateBuffers();
    saveFile((char*) "/tmp/itk_gpu_blurmean.dcm", GPUMean->GetOutput());
#endif

    // Visualize
    /*
    QuickView viewer;
    viewer.AddImage<ImageType>(
      image,true,
      itksys::SystemTools::GetFilenameName(argv[1]));  
    std::stringstream desc;
    desc << "ITK QuickView: " 
         << argv[1];
    viewer.Visualize();
    */

    // Saving input image as is
    saveFile((char*) "/tmp/itk_input.dcm", image);


    return EXIT_SUCCESS;
}
// This function is designed to compute the optimal threshold using OTSU method;
// this algoritm is implemented by xiao liang based on ITK's OTSU algorithm
double VolumeProcess::getXiaoLiangOtsuThreshold(ImageType::Pointer img)
{
	if(!img)
		return 0;

	double threshold = 0;
	unsigned char m_min = 255;
	unsigned char m_max = 0;
	double m_mean = 0.0;
	double m_variance = 0.0;

	ImageType::RegionType region = img->GetBufferedRegion();
	double numPix = region.GetSize(2)*region.GetSize(1)*region.GetSize(0);

	//Get min, max, and mean:
	itk::ImageRegionIterator< ImageType > itr( img, region );
	for(itr.GoToBegin(); !itr.IsAtEnd(); ++itr)
	{
		double val = itr.Get();
		if(val > m_max) m_max = val;
		if(val < m_min) m_min = val;
		m_mean += itr.Get();
	}
	m_mean  = m_mean/numPix;

	if(debug)
		std::cerr << "Max = " << (int)m_max << ", Min = " << (int)m_min << std::endl;

	//Do a sanity check
	if ( m_min >= m_max)
    {
		threshold=m_min;
		return threshold;
    }

	//Get the variance:
	for(itr.GoToBegin(); !itr.IsAtEnd(); ++itr)
	{
		double val = (double)itr.Get();
		m_variance += (val-m_mean)*(val-m_mean);
	}
	//These were not Xiao Liang's version:
	//m_variance = m_variance / numPix;
	//m_variance = sqrt(m_variance);

	threshold = m_mean - (m_variance/30); 
    // this step is only initialized a good experimental value for m_Threshold, because the 3D image
    // is sparse, there are lots of zero values; 

	//Create a histogram & init to zero
	double relativeFrequency[m_NumberOfHistogramBins];
	for ( unsigned char j = 0; j < m_NumberOfHistogramBins; j++ )
    {
       relativeFrequency[j] = 0.0;
    }

	double binMultiplier = (double)m_NumberOfHistogramBins/(double)(m_max-m_min);
	if(debug)
		std::cerr << "binMultiplier = " << binMultiplier << std::endl;

	unsigned int binNumber;
	for(itr.GoToBegin(); !itr.IsAtEnd(); ++itr)
	{
		double val = itr.Get();
		if ( val == m_min ) 
		{
			binNumber = 0;
		}
		else
		{
			binNumber = (unsigned int)(((val-m_min)*binMultiplier) - 1);
			if ( binNumber == m_NumberOfHistogramBins ) // in case of rounding errors
			{
				binNumber -= 1;
			}
		}
		relativeFrequency[binNumber] += 1.0;
	}

	// normalize the frequencies
	double totalMean = 0.0;
	for ( unsigned char j = 0; j < m_NumberOfHistogramBins; j++ )
    {
		relativeFrequency[j] /= numPix;
		totalMean += (j+1) * relativeFrequency[j];
    }

	// compute Otsu's threshold by maximizing the between-class variance
	double freqLeft = relativeFrequency[0];
	double meanLeft = 1.0;
	double meanRight = ( totalMean - freqLeft ) / ( 1.0 - freqLeft );

	double maxVarBetween = freqLeft * ( 1.0 - freqLeft ) * sqrt( meanLeft - meanRight );
	int maxBinNumber = 0;

	double freqLeftOld = freqLeft;
	double meanLeftOld = meanLeft;

	for ( unsigned char j = 1; j < m_NumberOfHistogramBins; j++ )
    {
		freqLeft += relativeFrequency[j];
		meanLeft = ( ((meanLeftOld * freqLeftOld)+(j+1)) * relativeFrequency[j] ) / freqLeft;
		if (freqLeft == 1.0)
		{
			meanRight = 0.0;
		}
		else
		{
			meanRight = ( totalMean - meanLeft * freqLeft ) / ( 1.0 - freqLeft );
		}
		
		double varBetween = freqLeft * ( 1.0 - freqLeft ) * sqrt( meanLeft - meanRight );
		if ( varBetween > maxVarBetween )
		{
			maxVarBetween = varBetween;
			maxBinNumber = j;
		}

		// cache old values
		freqLeftOld = freqLeft;
		meanLeftOld = meanLeft; 
    } 

	threshold = double( m_min + ( maxBinNumber + 1 ) / binMultiplier );
	return threshold; 
}