void Initialisation::setInputImage(ImageType::Pointer image)
{
    OrientImage<ImageType> orientationFilter;
    orientationFilter.setInputImage(image);
    orientationFilter.orientation(itk::SpatialOrientation::ITK_COORDINATE_ORIENTATION_AIL);
    inputImage_ = orientationFilter.getOutputImage();
    orientation_ = orientationFilter.getInitialImageOrientation();
}
Initialisation::Initialisation(ImageType::Pointer image, double imageFactor, double gap)
{
	OrientImage<ImageType> orientationFilter;
    orientationFilter.setInputImage(image);
    orientationFilter.orientation(itk::SpatialOrientation::ITK_COORDINATE_ORIENTATION_AIL);
    inputImage_ = orientationFilter.getOutputImage();
    orientation_ = orientationFilter.getInitialImageOrientation();
    
	typeImageFactor_ = imageFactor;
    gap_ = gap;
    startSlice_ = -1.0;
    numberOfSlices_ = 5;
    radius_ = 4.0;

	verbose_ = false;
}
Пример #3
0
void Image3D::TransformMeshToBinaryImage(Mesh* m, string filename, OrientationType orient, bool sub_segmentation, bool cropUpDown, CVector3* upperSlicePoint, CVector3* upperSliceNormal, CVector3* downSlicePoint, CVector3* downSliceNormal)
{
    //m->subdivision(2);
    MeshTypeB::Pointer mesh;
    MeshFilterType::Pointer meshFilter = MeshFilterType::New();
    if (cropUpDown)
    {
        mesh = MeshTypeB::New();
        vtkSmartPointer<vtkPolyData> polyData;
        try {
            polyData = m->reduceMeshUpAndDown(*upperSlicePoint, *upperSliceNormal, *downSlicePoint, *downSliceNormal);
        }
        catch (const exception& e) {
            cout << e.what() << endl;
        }

        vtkSmartPointer<vtkFillHolesFilter> fillHolesFilter = vtkSmartPointer<vtkFillHolesFilter>::New();
        fillHolesFilter->SetInputData(polyData);
        fillHolesFilter->SetHoleSize(1000.0);
        fillHolesFilter->Update();

        // Make the triangle windong order consistent
        vtkSmartPointer<vtkPolyDataNormals> normals = vtkSmartPointer<vtkPolyDataNormals>::New();
        normals->SetInputData(fillHolesFilter->GetOutput());
        normals->ConsistencyOn();
        normals->SplittingOff();
        normals->Update();

        // Restore the original normals
        normals->GetOutput()->GetPointData()->SetNormals(polyData->GetPointData()->GetNormals());
        polyData = normals->GetOutput();

        //
        // Transfer the points from the vtkPolyData into the itk::Mesh
        //
        const unsigned int numberOfPoints = polyData->GetNumberOfPoints();
        vtkPoints * vtkpoints = polyData->GetPoints();
        mesh->GetPoints()->Reserve( numberOfPoints );
        for(unsigned int p =0; p < numberOfPoints; p++)
        {
            double * apoint = vtkpoints->GetPoint( p );
            mesh->SetPoint( p, MeshTypeB::PointType( apoint ));
        }

        //
        // Transfer the cells from the vtkPolyData into the itk::Mesh
        //
        vtkCellArray * triangleStrips = polyData->GetStrips();
        vtkIdType  * cellPoints;
        vtkIdType    numberOfCellPoints;

        //
        // First count the total number of triangles from all the triangle strips.
        //
        unsigned int numberOfTriangles = 0;
        triangleStrips->InitTraversal();
        while( triangleStrips->GetNextCell( numberOfCellPoints, cellPoints ) )
        {
            numberOfTriangles += numberOfCellPoints-2;
        }

        vtkCellArray * polygons = polyData->GetPolys();
        polygons->InitTraversal();
        while( polygons->GetNextCell( numberOfCellPoints, cellPoints ) )
        {
            if( numberOfCellPoints == 3 )
            {
                numberOfTriangles ++;
            }
        }

        //
        // Reserve memory in the itk::Mesh for all those triangles
        //
        mesh->GetCells()->Reserve( numberOfTriangles );

        //
        // Copy the triangles from vtkPolyData into the itk::Mesh
        //
        //
        typedef MeshTypeB::CellType   CellType;
        typedef itk::TriangleCell< CellType > TriangleCellType;
        int cellId = 0;

        // first copy the triangle strips
        triangleStrips->InitTraversal();
        while( triangleStrips->GetNextCell( numberOfCellPoints, cellPoints ) )
        {
            unsigned int numberOfTrianglesInStrip = numberOfCellPoints - 2;

            unsigned long pointIds[3];
            pointIds[0] = cellPoints[0];
            pointIds[1] = cellPoints[1];
            pointIds[2] = cellPoints[2];

            for( unsigned int t=0; t < numberOfTrianglesInStrip; t++ )
            {
                MeshTypeB::CellAutoPointer c;
                TriangleCellType * tcell = new TriangleCellType;
                tcell->SetPointIds( pointIds );
                c.TakeOwnership( tcell );
                mesh->SetCell( cellId, c );
                cellId++;
                pointIds[0] = pointIds[1];
                pointIds[1] = pointIds[2];
                pointIds[2] = cellPoints[t+3];
            }
        }

        // then copy the normal triangles
        polygons->InitTraversal();
        while( polygons->GetNextCell( numberOfCellPoints, cellPoints ) )
        {
            if( numberOfCellPoints !=3 ) // skip any non-triangle.
            {
                continue;
            }
            MeshTypeB::CellAutoPointer c;
            TriangleCellType * t = new TriangleCellType;
            t->SetPointIds( (unsigned long*)cellPoints );
            c.TakeOwnership( t );
            mesh->SetCell( cellId, c );
            cellId++;
        }

        meshFilter->SetInput(mesh);
    }
    else
    {
        mesh = MeshTypeB::New();
        vector<Vertex*> points = m->getListPoints();
        PointType pnt;
        CVector3 p, n;
        for (unsigned int i=0; i<points.size(); i++) {
            p = points[i]->getPosition();
            n = points[i]->getNormal();
            pnt[0] = p[0]; pnt[1] = p[1]; pnt[2] = p[2];
            mesh->SetPoint(i,pnt);
        }
        vector<int> triangles = m->getListTriangles();
        for (unsigned int i=0; i<triangles.size(); i+=3)
        {
            CellTypeB::CellAutoPointer triangle;
            triangle.TakeOwnership(new CellTypeB);
            triangle->SetPointId(0,triangles[i]);
            triangle->SetPointId(1,triangles[i+1]);
            triangle->SetPointId(2,triangles[i+2]);
            mesh->SetCell((int)(i+1)/3,triangle);
        }
        meshFilter->SetInput(mesh);
    }

    meshFilter->SetOrigin(imageOriginale_->GetOrigin());
    meshFilter->SetSpacing(imageOriginale_->GetSpacing());
    meshFilter->SetSize(imageOriginale_->GetLargestPossibleRegion().GetSize());
    meshFilter->SetDirection(imageOriginale_->GetDirection());
    meshFilter->SetIndex(imageOriginale_->GetLargestPossibleRegion().GetIndex());
    //meshFilter->SetTolerance(1.0);
    meshFilter->SetInsideValue(1.0);
    meshFilter->SetOutsideValue(0.0);
    try {
        meshFilter->Update();
    }
    catch( itk::ExceptionObject & e )
    {
        cout << "Exception thrown ! " << endl;
        cout << "An error ocurred during creating binary image" << endl;
        cout << "Location    = " << e.GetLocation()    << endl;
        cout << "Description = " << e.GetDescription() << endl;
    }
    
    BinaryImageType::Pointer im = meshFilter->GetOutput();
    
    if (!sub_segmentation)
    {
        imageSegmentation_ = im;
    }
    else
    {
        BinaryImageType::RegionType region = im->GetLargestPossibleRegion();
        itk::ImageRegionConstIterator<BinaryImageType> imageIterator(im,region);
        unsigned char pixel, pixel_seg;
        BinaryIndexType index;
        while(!imageIterator.IsAtEnd())
        {
            index = imageIterator.GetIndex();
            pixel = imageIterator.Get();
            
            pixel_seg = imageSegmentation_->GetPixel(index);
            im->SetPixel(index,pixel && !pixel_seg);
            ++imageIterator;
        }
    }
    
    OrientImage<BinaryImageType> orientationFilter;
    orientationFilter.setInputImage(im);
    orientationFilter.orientation(orient);
    im = orientationFilter.getOutputImage();
    
    // Write the image
    typedef itk::ImageFileWriter< BinaryImageType >     WriterType;
    WriterType::Pointer writer = WriterType::New();
    itk::NiftiImageIO::Pointer io = itk::NiftiImageIO::New();
    writer->SetImageIO(io);
    writer->SetFileName(filename);
    writer->SetInput(im);
    try {
        writer->Update();
    }
    catch( itk::ExceptionObject & e )
    {
        cout << "Exception thrown ! " << endl;
        cout << "An error ocurred during Writing" << endl;
        cout << "Location    = " << e.GetLocation()    << endl;
        cout << "Description = " << e.GetDescription() << endl;
    }
}
Пример #4
0
vector<CVector3> extractCenterline(string filename)
{
    vector<CVector3> result;
    
    string nii=".nii", niigz=".nii.gz", txt=".txt", suffix="";
    size_t pos_niigz = filename.find(niigz), pos_nii = filename.find(nii), pos_txt = filename.find(txt);
    if (pos_niigz != string::npos || pos_nii != string::npos)
    {
        ReaderType::Pointer reader = ReaderType::New();
        itk::NiftiImageIO::Pointer io = itk::NiftiImageIO::New();
        reader->SetImageIO(io);
        reader->SetFileName(filename);
        try {
            reader->Update();
        } catch( itk::ExceptionObject & e ) {
            cerr << "Exception caught while reading centerline input image " << endl;
            cerr << e << endl;
        }
        ImageType::Pointer image_centerline = reader->GetOutput();
        
        OrientImage<ImageType> orientationFilter;
        orientationFilter.setInputImage(image_centerline);
        orientationFilter.orientation(itk::SpatialOrientation::ITK_COORDINATE_ORIENTATION_AIL);
        image_centerline = orientationFilter.getOutputImage();
        
        ImageType::IndexType ind;
        itk::Point<double,3> point;
        ImageIterator it( image_centerline, image_centerline->GetRequestedRegion() );
        it.GoToBegin();
        while(!it.IsAtEnd())
        {
            if (it.Get()!=0)
            {
                ind = it.GetIndex();
                image_centerline->TransformIndexToPhysicalPoint(ind, point);
                bool added = false;
                if (result.size() == 0) {
                    result.push_back(CVector3(point[0],point[1],point[2]));
                    added = true;
                }
                else {
                    for (vector<CVector3>::iterator it=result.begin(); it!=result.end(); it++) {
                        if (point[2] < (*it)[2]) {
                            result.insert(it, CVector3(point[0],point[1],point[2]));
                            added = true;
                            break;
                        }
                    }
                }
                if (!added) result.push_back(CVector3(point[0],point[1],point[2]));
            }
            ++it;
        }
        
        /*// spline approximation to produce correct centerline
        
        double range = result.size()/4.0 ;
        const unsigned int ParametricDimension = 1; const unsigned int DataDimension = 3;
        typedef double RealType;
        typedef itk::Vector<RealType, DataDimension> VectorType; typedef itk::Image<VectorType, ParametricDimension> ImageType;
        typedef itk::PointSet <VectorType , ParametricDimension > PointSetType; PointSetType::Pointer pointSet = PointSetType::New();
        // Sample the helix.
        int nb = result.size();
        for (unsigned long i=0; i<nb; i++) {
            PointSetType::PointType point; point[0] = (double)i/(double)(nb-1);
            pointSet ->SetPoint( i, point );
            VectorType V;
            V[0] = result[i][0]; V[1] = result[i][1]; V[2] = result[i][2];
            pointSet ->SetPointData( i, V );
        }
        
        typedef itk::BSplineScatteredDataPointSetToImageFilter <PointSetType , ImageType > FilterType;
        FilterType::Pointer filter = FilterType::New();
        ImageType::SpacingType spacing; spacing.Fill( 1.0 ); ImageType::SizeType size; size.Fill( 2.0); ImageType::PointType origin; origin.Fill( 0.0 );
        ImageType::RegionType region(size); FilterType::ArrayType closedim; closedim.Fill(0);
        filter->SetSize( size ); filter->SetOrigin( origin ); filter->SetSpacing( spacing ); filter->SetInput( pointSet );
        int splineOrder = 3; filter->SetSplineOrder( splineOrder ); FilterType::ArrayType ncps;
        ncps.Fill( splineOrder + 1 ); filter->SetNumberOfControlPoints( ncps ); filter->SetNumberOfLevels( 5 ); filter->SetGenerateOutputImage( false );
        try
        { filter->Update();
        } catch( itk::ExceptionObject & e ) {
            std::cerr << "Exception caught while reading input image " << std::endl;
            std::cerr << e << std::endl;
        }
        
        typedef itk::BSplineControlPointImageFunction < ImageType, double > BSplineType;
        BSplineType::Pointer bspline = BSplineType::New();
        bspline->SetSplineOrder(filter->GetSplineOrder());
        bspline->SetOrigin(origin);
        bspline->SetSpacing(spacing);
        bspline->SetSize(size);
        bspline->SetInputImage(filter->GetPhiLattice());
        
        result.clear();
        for (double i=0; i<=2.0*range; i++) {
            PointSetType::PointType point; point[0] = i/(2.0*range);
            VectorType V = bspline->Evaluate( point );
            result.push_back(CVector3(V[0],V[1],V[2]));
        }*/
        
    }
    else if (pos_txt != string::npos)
    {
        ifstream myfile;
        string l;
        double x, y, z;
        CVector3 point, pointPrecedent;
        int i = 0;
        myfile.open(filename.c_str());
        if (myfile.is_open())
        {
            while (myfile.good())
            {
                getline(myfile,l);
                stringstream ss(l);
                ss >> x >> z >> y;
                point = CVector3(x,y,z);
                if ((point-pointPrecedent).Norm() > 0) {
                    pointPrecedent = point;
                    //point[1] = -point[1];
                    result.push_back(point);
                }
                i++;
            }
        }
        myfile.close();
    }
Пример #5
0
int main(int argc, char *argv[])
{
    srand (time(NULL));
    
	if (argc == 1)
    {
        help();
        return EXIT_FAILURE;
    }
    string inputFilename = "", outputPath = "", outputFilenameBinary = "", outputFilenameMesh = "", outputFilenameBinaryCSF = "", outputFilenameMeshCSF = "", outputFilenameAreas = "", outputFilenameAreasCSF = "", outputFilenameCenterline = "", outputFilenameCenterlineBinary = "", inputCenterlineFilename = "", initMaskFilename = "";
    double typeImageFactor = 0.0, initialisation = 0.5;
    int downSlice = -10000, upSlice = 10000;
    string suffix;
	bool input_dicom = false, output_detection = false, output_mesh = false, output_centerline_binary = false, output_centerline_coord = false, output_cross = false, init_with_centerline = false, init_with_mask = false, verbose = false, output_init_tube = false, completeCenterline = false, init_validation = false, low_res_mesh = false, CSF_segmentation = false;
	int gapInterSlices = 4, nbSlicesInitialisation = 5;
	double radius = 4.0;
    int numberOfPropagationIteration = 200;
    double maxDeformation = 0.0, maxArea = 0.0, minContrast = 50.0, tradeoff_d;
	bool tradeoff_d_bool = false;
    for (int i = 0; i < argc; ++i) {
        if (strcmp(argv[i],"-i")==0) {
            i++;
            inputFilename = argv[i];
        }
        else if (strcmp(argv[i],"-i-dicom")==0) {
            i++;
            //inputFilename = argv[i];
            //input_dicom = true;
        }
        else if (strcmp(argv[i],"-o")==0) {
            i++;
            outputPath = argv[i];
        }
        else if (strcmp(argv[i],"-t")==0) {
            i++;
            if (strcmp(argv[i],"t1")==0) {
				typeImageFactor = -1.0;
				if (verbose) cout << endl << "WARNING: be sure your image is a T1-weighted image." << endl << endl;
			}
            else if (strcmp(argv[i],"t2")==0) {
				typeImageFactor = 1.0;
				if (verbose) cout << endl << "WARNING: be sure your image is a T2-weighted image." << endl << endl;
			}
            else {
				cout << "Error: Invalid type or image (need to be \"t1\" or \"t2\")" << endl << endl;
				help();
                return EXIT_FAILURE;
			}
        }
        else if (strcmp(argv[i],"-init")==0) {
            i++;
            initialisation = atof(argv[i]);
        }
        else if (strcmp(argv[i],"-down")==0) {
            i++;
            downSlice = atoi(argv[i]);
        }
        else if (strcmp(argv[i],"-up")==0) {
            i++;
            upSlice = atoi(argv[i]);
        }
		else if (strcmp(argv[i],"-detect-display")==0) {
            output_detection = true;
        }
		else if (strcmp(argv[i],"-mesh")==0) {
            output_mesh = true;
        }
		else if (strcmp(argv[i],"-centerline-binary")==0) {
            output_centerline_binary = true;
        }
		else if (strcmp(argv[i],"-centerline-coord")==0) {
            output_centerline_coord = true;
        }
		else if (strcmp(argv[i],"-cross")==0) {
            output_cross = true;
        }
		else if (strcmp(argv[i],"-detect-n")==0) {
            i++;
            nbSlicesInitialisation = atoi(argv[i]);
        }
		else if (strcmp(argv[i],"-detect-gap")==0) {
            i++;
            gapInterSlices = atoi(argv[i]);
        }
		else if (strcmp(argv[i],"-detect-radius")==0) {
            i++;
            radius = atof(argv[i]);
        }
		else if (strcmp(argv[i],"-init-centerline")==0) {
            i++;
            inputCenterlineFilename = argv[i];
            init_with_centerline = true;
        }
        else if (strcmp(argv[i],"-nbiter")==0) {
            i++;
            numberOfPropagationIteration = atoi(argv[i]);
        }
        else if (strcmp(argv[i],"-init-mask")==0) {
            i++;
            initMaskFilename = argv[i];
            init_with_mask = true;
        }
        else if (strcmp(argv[i],"-init-tube")==0) {
            output_init_tube = true;
        }
		else if (strcmp(argv[i],"-init-validation")==0) {
            init_validation = true;
        }
        else if (strcmp(argv[i],"-low-resolution-mesh")==0) {
            low_res_mesh = true;
        }
        else if (strcmp(argv[i],"-max-deformation")==0) {
            i++;
            maxDeformation = atof(argv[i]);
        }
        else if (strcmp(argv[i],"-max-area")==0) {
            i++;
            maxArea = atof(argv[i]);
        }
        else if (strcmp(argv[i],"-min-contrast")==0) {
            i++;
            minContrast = atof(argv[i]);
        }
		else if (strcmp(argv[i],"-d")==0) {
            i++;
            tradeoff_d = atof(argv[i]);
			tradeoff_d_bool = true;
        }
        else if (strcmp(argv[i],"-CSF")==0) {
            CSF_segmentation = true;
            if (maxArea == 0.0) maxArea = 120;
            if (maxDeformation == 0.0) maxDeformation = 2.5;
        }
		else if (strcmp(argv[i],"-verbose")==0) {
            verbose = true;
        }
        else if (strcmp(argv[i],"-help")==0) {
            help();
            return EXIT_FAILURE;
        }
    }
    if (inputFilename == "")
    {
        cerr << "Input filename or folder (if DICOM) not provided" << endl;
		help();
        return EXIT_FAILURE;
    }
    if (typeImageFactor == 0)
    {
        cerr << "Error: The type of contrast not provided (option -t)" << endl;
		help();
        return EXIT_FAILURE;
    }
    
    // output files must have the same extension as input file
    string nii=".nii", niigz=".nii.gz"; suffix=niigz;
    size_t pos = inputFilename.find(niigz);
    if (pos == string::npos) {
        pos = inputFilename.find(nii);
        suffix = nii;
    }
    if (outputPath!="" && outputPath.compare(outputPath.length()-1,1,"/")) outputPath += "/"; // add "/" if missing
    outputFilenameBinary = outputPath+"segmentation_binary"+suffix;
    outputFilenameMesh = outputPath+"segmentation_mesh.vtk";
    outputFilenameBinaryCSF = outputPath+"segmentation_CSF_binary"+suffix;
    outputFilenameMeshCSF = outputPath+"segmentation_CSF_mesh.vtk";
    outputFilenameAreas = outputPath+"cross_sectional_areas.txt";
    outputFilenameAreasCSF = outputPath+"cross_sectional_areas_CSF.txt";
    outputFilenameCenterline = outputPath+"segmentation_centerline.txt";
    outputFilenameCenterlineBinary = outputPath+"segmentation_centerline_binary"+suffix;
    // if output path doesn't exist, we create it
    if (outputPath!="") itk::FileTools::CreateDirectory(outputPath.c_str());
    
    // Image reading - image can be T1 or T2 (or Tx-like) depending on contrast between spinal cord and CSF
	// typeImageFactor depend of contrast type and is equal to +1 when CSF is brighter than spinal cord and equal to -1 inversely
    ImageType::Pointer initialImage, image = ImageType::New();
    
    if (input_dicom)
    {
        /*ImageIOType::Pointer gdcmIO = ImageIOType::New();
        InputNamesGeneratorType::Pointer inputNames = InputNamesGeneratorType::New();
        inputNames->SetInputDirectory( inputFilename );
        
        const DICOMReaderType::FileNamesContainer & filenames = inputNames->GetInputFileNames();
        
        DICOMReaderType::Pointer reader = DICOMReaderType::New();
        reader->SetImageIO( gdcmIO );
        reader->SetFileNames( filenames );
        try
        {
            reader->Update();
        } catch (itk::ExceptionObject &excp) {
            std::cerr << "Exception thrown while reading the DICOM series" << std::endl;
            std::cerr << excp << std::endl;
            return EXIT_FAILURE;
        }
        initialImage = reader->GetOutput();*/
    }
    else
    {
        ReaderType::Pointer reader = ReaderType::New();
        itk::NiftiImageIO::Pointer io = itk::NiftiImageIO::New();
        reader->SetImageIO(io);
        reader->SetFileName(inputFilename);
        try {
            reader->Update();
        } catch( itk::ExceptionObject & e ) {
            cerr << "Exception caught while reading input image" << endl;
            cerr << e << endl;
            return EXIT_FAILURE;
        }
        initialImage = reader->GetOutput();
    }
    
    // Change orientation of input image to AIL. Output images will have the same orientation as input image
    OrientImage<ImageType> orientationFilter;
    orientationFilter.setInputImage(initialImage);
    orientationFilter.orientation(itk::SpatialOrientation::ITK_COORDINATE_ORIENTATION_AIL);
    initialImage = orientationFilter.getOutputImage();
	
	// Crop image if it is too large in left-right direction. No need to compute the initialization on the whole image. We assume the spinal cord is included in a 5cm large region.
	ImageType::SizeType desiredSize = initialImage->GetLargestPossibleRegion().GetSize();
    ImageType::SpacingType spacingI = initialImage->GetSpacing();
	if (desiredSize[2]*spacingI[2] > 60 && !init_with_mask && !init_with_centerline)
	{
		SymmetricalCropping symCroppingFilter;
        symCroppingFilter.setInputImage(initialImage);
		symCroppingFilter.setInitSlice(initialisation);
		int crop_slice = -1;
		try {
			crop_slice = symCroppingFilter.symmetryDetection();
		} catch(exception & e) {
		    cerr << "Exception caught while computing symmetry" << endl;
            cerr << e.what() << endl;
            return EXIT_FAILURE;
		}
		if (crop_slice != -1) {
			if (verbose) cout << "Cropping input image in left-right direction around slice = " << crop_slice << endl;
			image = symCroppingFilter.cropping();
		} else {
			if (verbose) cout << "Image non cropped for symmetry" << endl;
			image = initialImage;
		}
	}
	else image = initialImage;
    
	// Intensity normalization
	RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New();
	rescaleFilter->SetInput(image);
	rescaleFilter->SetOutputMinimum(0);
	rescaleFilter->SetOutputMaximum(1000);
    try {
        rescaleFilter->Update();
    } catch( itk::ExceptionObject & e ) {
        cerr << "Exception caught while normalizing input image " << endl;
        cerr << e << endl;
        return EXIT_FAILURE;
    }
	image = rescaleFilter->GetOutput();
	
	// computing magnitude and direction of gradient image
	GradientMFilterType::Pointer gradientMagnitudeFilter = GradientMFilterType::New();
	gradientMagnitudeFilter->SetInput(image);
	try {
		gradientMagnitudeFilter->Update();
	} catch( itk::ExceptionObject & e ) {
		cerr << "Exception caught while updating gradientMagnitudeFilter " << endl;
		cerr << e << endl;
        return EXIT_FAILURE;
	}
	ImageType::Pointer imageGradient = gradientMagnitudeFilter->GetOutput();
    
	VectorGradientFilterType::Pointer gradientMapFilter = VectorGradientFilterType::New();
	gradientMapFilter->SetInput( image );
	try {
		gradientMapFilter->Update();
	} catch( itk::ExceptionObject & e ) {
		cerr << "Exception caught while updating gradientMapFilter " << endl;
		cerr << e << endl;
        return EXIT_FAILURE;
	}
	GradientImageType::Pointer imageVectorGradient = gradientMapFilter->GetOutput();
    
	// Creation of 3D image with origin, orientation and scaling, containing original image, gradient image, vector gradient image
	ImageType::SizeType regionSize = image->GetLargestPossibleRegion().GetSize();
	ImageType::PointType origineI = image->GetOrigin();
	CVector3 origine = CVector3(origineI[0],origineI[1],origineI[2]);
	ImageType::DirectionType directionI = image->GetInverseDirection();
	CVector3	directionX = CVector3(directionI[0][0],directionI[0][1],directionI[0][2]),
    directionY = CVector3(directionI[1][0],directionI[1][1],directionI[1][2]),
    directionZ = CVector3(directionI[2][0],directionI[2][1],directionI[2][2]);
	CVector3 spacing = CVector3(spacingI[0],spacingI[1],spacingI[2]);
	Image3D* image3DGrad = new Image3D(imageVectorGradient,regionSize[0],regionSize[1],regionSize[2],origine,directionX,directionY,directionZ,spacing,typeImageFactor);
	image3DGrad->setImageOriginale(initialImage);
	image3DGrad->setCroppedImageOriginale(image);
	image3DGrad->setImageMagnitudeGradient(imageGradient);
    
    
	/******************************************
     // Initialization of Propagated Deformable Model of Spinal Cord
     ******************************************/
	int radialResolution, axialResolution, numberOfDeformIteration = 3;
	double axialStep, propagationLength = 800.0;
	// Definition of parameters for T1 and T2 images. T1 need better resolution to provide accurate segmentation.
    if (typeImageFactor == 1.0) { // T2
        radialResolution = 15;
        axialResolution = 3;
        axialStep = 6.0;
    }
    else { // T1
        radialResolution = 20; //30
        axialResolution = 3; //5
        axialStep = 6.0; //8
    }
    
    CVector3 point, normal1, normal2; // normal1 and normal2 and normals in both direction from initial point
    double stretchingFactor = 1.0;
    vector<CVector3> centerline;
    
    if (init_with_centerline)
    {
        if (verbose) cout << "Initialization - using given centerline" << endl;
        centerline = extractCenterline(inputCenterlineFilename);
        if (centerline.size() == 0) return EXIT_FAILURE;
    }
    else if (init_with_mask)
    {
        if (verbose) cout << "Initialization - using given mask" << endl;
        bool result_init = extractPointAndNormalFromMask(initMaskFilename, point, normal1, normal2);
        if (!result_init) return EXIT_FAILURE;
        if (verbose) {
            cout << "Point = " << point << endl;
            cout << "Normal 1 = " << normal1 << endl;
            cout << "Normal 2 = " << normal2 << endl;
        }
    }
    else
    {
        bool isSpinalCordDetected = false;
        int countFailure = 0;
        double step = 0.025; // step of displacement in pourcentage of the image
        do
        {
            if (verbose) cout << "Initialization - spinal cord detection on axial slices" << endl;
            Initialisation init(image,typeImageFactor);
            init.setVerbose(verbose);
            init.setGap(gapInterSlices); // gap between slices is necessary to provide good normals
            init.setRadius(radius); // approximate radius of spinal cord. This parameter is used to initiate Hough transform
            init.setNumberOfSlices(nbSlicesInitialisation);
            
            // if the initialization fails at the first position in the image, an other spinal cord detection process is launch higher.
            int d = rand() % 2; if (d==0) d = -1;
            isSpinalCordDetected = init.computeInitialParameters(initialisation+(double)countFailure*step*(double)d);
            //if (!isSpinalCordDetected) isSpinalCordDetected = init.computeInitialParameters(0.7);
            if(isSpinalCordDetected)
            {
                if (output_detection) init.savePointAsAxialImage(image,outputPath+"result_detection.png");
                
                init.getPoints(point,normal1,normal2,radius,stretchingFactor);
                if (normal2 == CVector3::ZERO) normal2 = -normal1;
                if (verbose) {
                    cout << "Initialization - Spinal Cord Detection:" << endl;
                    cout << "Point = " << point << endl;
                    cout << "Normal 1 = " << normal1 << endl;
                    cout << "Normal 2 = " << normal2 << endl;
                    cout << "Radius = " << radius << endl;
                }
                
				if(init_validation)
				{
					// Definition of discrimination surface for the validation of the spinal cord detection module
					double K_T1 = 15.7528, K_T2 = 3.2854;
					CVector3 L_T1 = CVector3(-0.0762,-2.5921,0.3472), L_T2 = CVector3(-0.0022,-1.2995,0.4909);
					CMatrix3x3 Q_T1, Q_T2;
					Q_T1[0] = 0.0; Q_T1[1] = 0.0; Q_T1[2] = 0.0; Q_T1[3] = 0.0; Q_T1[4] = 0.1476; Q_T1[5] = 0.0; Q_T1[6] = 0.0; Q_T1[7] = 0.0; Q_T1[8] = 0.6082;
					Q_T2[0] = 0.0; Q_T2[1] = 0.0; Q_T2[2] = 0.0; Q_T2[3] = 0.0; Q_T2[4] = 0.0687; Q_T2[5] = 0.0; Q_T2[6] = 0.0; Q_T2[7] = 0.0; Q_T2[8] = 0.3388;
					double contrast = 0.0, mean_distance = 0.0, std_distance = 0.0;
                
					// validation of the spinal cord detetion
					int *sizeDesired = new int[3];
					double *spacingDesired = new double[3];
					sizeDesired[0] = 61; sizeDesired[1] = 61; sizeDesired[2] = 11;
					spacingDesired[0] = 0.5; spacingDesired[1] = 0.5; spacingDesired[2] = 0.5;
					SCRegion* spinal_cord_verif = new SCRegion();
					spinal_cord_verif->setSize(sizeDesired);
					spinal_cord_verif->setSpacing(spacingDesired);
					spinal_cord_verif->setOrigin(point[0],point[1],point[2]);
					spinal_cord_verif->setNormal(normal1[0],normal1[1],normal1[2]);
					spinal_cord_verif->setFactor(typeImageFactor);
					try {
						spinal_cord_verif->readImage(initialImage);
						spinal_cord_verif->createImage();
						contrast = spinal_cord_verif->computeContrast(mean_distance,std_distance,15);
					} catch (string const& e) {
						cerr << e << endl;
						contrast = -1.0;
					}
                
					CVector3 vec = CVector3(contrast,mean_distance,std_distance);
					double discrim = 0.0;
					if (typeImageFactor == -1) // if T1
					{
						CVector3 temp = vec*Q_T1;
						double quad = 0.0;
						for(int r=0; r<3; r++) {
							quad += temp[r]*vec[r];
						}
						discrim = K_T1 + vec*L_T1 + quad;
					}
					else{
						CVector3 temp = vec*Q_T2;
						double quad = 0.0;
						for(int r=0; r<3; r++) {
							quad += temp[r]*vec[r];
						}
						discrim = K_T2 + vec*L_T2 + quad;
					}
                
					if (discrim > 0.0)
					{
						countFailure++;
						isSpinalCordDetected = false;
						if (verbose) cout << "WARNING: Bad initialization. Attempt to locate spinal cord at an other level." << endl << endl;
					}
					else
					{
						isSpinalCordDetected = true;
					}
					delete sizeDesired, spacingDesired, spinal_cord_verif;
				}
				else {
					isSpinalCordDetected = true;
				}
            } else {
                countFailure++;
            }
        }
        while (!isSpinalCordDetected && countFailure<10);
        if (!isSpinalCordDetected)
        {
            cerr << "Error: Enable to detect the spinal cord. Please provide the initial position and orientation of the spinal cord (-init, -init-mask)" << endl;
            return EXIT_FAILURE;
        }
    }
    
	/******************************************
     // Launch of Propagated Deformable Model of Spinal Cord. Propagation have to be done in both direction
     ******************************************/
	PropagatedDeformableModel* prop = new PropagatedDeformableModel(radialResolution,axialResolution,radius,numberOfDeformIteration,numberOfPropagationIteration,axialStep,propagationLength);
    if (maxDeformation != 0.0) prop->setMaxDeformation(maxDeformation);
    if (maxArea != 0.0) prop->setMaxArea(maxArea);
    prop->setMinContrast(minContrast);
	prop->setInitialPointAndNormals(point,normal1,normal2);
    prop->setStretchingFactor(stretchingFactor);
	prop->setUpAndDownLimits(downSlice,upSlice);
	prop->setImage3D(image3DGrad);
    if (init_with_centerline) {
        prop->propagationWithCenterline();
        for (unsigned int k=0; k<centerline.size(); k++) prop->addPointToCenterline(centerline[k]);
        if (initialisation <= 1) prop->setInitPosition(initialisation);
    }
	if (tradeoff_d_bool) {
		prop->setTradeOffDistanceFeature(tradeoff_d);
	}
    prop->setVerbose(verbose);
	prop->computeMeshInitial();
    if (output_init_tube) {
        SpinalCord *tube1 = prop->getInitialMesh(), *tube2 = prop->getInverseInitialMesh();
        tube1->save(outputPath+"InitialTube1.vtk");
        tube2->save(outputPath+"InitialTube2.vtk");
    }
	
	prop->adaptationGlobale(); // Propagation
	// Saving low resolution mesh
	if (low_res_mesh)
    {
        SpinalCord *meshOutputLowResolution = prop->getOutput();
        meshOutputLowResolution->save(outputPath+"segmentation_mesh_low_resolution.vtk",initialImage);
        //meshOutput->computeCenterline(true,path+"LowResolution");
        //meshOutput->computeCrossSectionalArea(true,path+"LowResolution");
        //image3DGrad->TransformMeshToBinaryImage(meshOutput,path+"LowResolution",orientationFilter.getInitialImageOrientation());
        //meshOutput->saveCenterlineAsBinaryImage(initialImage,path+"LowResolution",orientationFilter.getInitialImageOrientation());
    }
    
	/******************************************
     // High Resolution Deformation
     ******************************************/
    prop->rafinementGlobal();
	SpinalCord* meshOutputFinal = prop->getOutputFinal();
	if (output_mesh) meshOutputFinal->save(outputFilenameMesh,initialImage);
	if (output_centerline_coord) meshOutputFinal->computeCenterline(true,outputFilenameCenterline,true);
	if (output_cross) meshOutputFinal->computeCrossSectionalArea(true,outputFilenameAreas,true,image3DGrad);
	image3DGrad->TransformMeshToBinaryImage(meshOutputFinal,outputFilenameBinary,orientationFilter.getInitialImageOrientation());
	if (output_centerline_binary) meshOutputFinal->saveCenterlineAsBinaryImage(initialImage,outputFilenameCenterlineBinary,orientationFilter.getInitialImageOrientation());
    
	if (verbose) {
		double lengthPropagation = meshOutputFinal->getLength();
		cout << "Total propagation length = " << lengthPropagation << " mm" << endl;
	}
    
    
    
    if (CSF_segmentation)
    {
        /******************************************
         // Launch of Propagated Deformable Model on the CSF. Propagation have to be done in both direction
         ******************************************/
        double factor_CSF = 2;
        PropagatedDeformableModel* prop_CSF = new PropagatedDeformableModel(radialResolution,axialResolution,radius*factor_CSF,numberOfDeformIteration,numberOfPropagationIteration,axialStep,propagationLength);
        if (maxDeformation != 0.0) prop_CSF->setMaxDeformation(maxDeformation*factor_CSF);
        if (maxArea != 0.0) prop_CSF->setMaxArea(maxArea*factor_CSF*2);
        prop->setMinContrast(minContrast);
        prop_CSF->setInitialPointAndNormals(point,normal1,normal2);
        prop_CSF->setStretchingFactor(stretchingFactor);
        prop_CSF->setUpAndDownLimits(downSlice,upSlice);
        image3DGrad->setTypeImageFactor(-image3DGrad->getTypeImageFactor());
        prop_CSF->setImage3D(image3DGrad);
        if (init_with_centerline) {
            prop_CSF->propagationWithCenterline();
            for (unsigned int k=0; k<centerline.size(); k++) prop->addPointToCenterline(centerline[k]);
            if (initialisation <= 1) prop->setInitPosition(initialisation);
        }
        prop_CSF->setVerbose(verbose);
        prop_CSF->computeMeshInitial();
        if (output_init_tube) {
            SpinalCord *tube1 = prop_CSF->getInitialMesh(), *tube2 = prop_CSF->getInverseInitialMesh();
            tube1->save(outputPath+"InitialTubeCSF1.vtk");
            tube2->save(outputPath+"InitialTubeCSF2.vtk");
        }
        
        prop_CSF->adaptationGlobale(); // Propagation
        // Saving low resolution mesh
        if (low_res_mesh)
        {
            SpinalCord *meshOutputLowResolution = prop_CSF->getOutput();
            meshOutputLowResolution->save(outputPath+"segmentation_CSF_mesh_low_resolution.vtk",initialImage);
            //meshOutput->computeCenterline(true,path+"LowResolution");
            //meshOutput->computeCrossSectionalArea(true,path+"LowResolution");
            //image3DGrad->TransformMeshToBinaryImage(meshOutput,path+"LowResolution",orientationFilter.getInitialImageOrientation());
            //meshOutput->saveCenterlineAsBinaryImage(initialImage,path+"LowResolution",orientationFilter.getInitialImageOrientation());
        }
        
        /******************************************
         // High Resolution Deformation
         ******************************************/
        prop_CSF->rafinementGlobal();
        SpinalCord* meshOutputFinal = prop_CSF->getOutputFinal();
        if (output_mesh) meshOutputFinal->save(outputFilenameMeshCSF,initialImage);
        if (output_cross) meshOutputFinal->computeCrossSectionalArea(true,outputFilenameAreasCSF,true,image3DGrad);
        image3DGrad->TransformMeshToBinaryImage(meshOutputFinal,outputFilenameBinaryCSF,orientationFilter.getInitialImageOrientation());
        
        if (verbose) {
            double lengthPropagation = meshOutputFinal->getLength();
            cout << "Total propagation length = " << lengthPropagation << " mm" << endl;
        }
        delete prop_CSF;
    }
    
    
	
	delete image3DGrad, prop;
    return EXIT_SUCCESS;
}
Пример #6
0
int changeOrientationMethod(string inputFilename, string outputFilename, OrientationType orientation, bool changeOrientation, bool displayInitialOrientation, bool displayAvailableOrientation)
{
    typedef itk::Image< TPixelType, N >	ImageType;
    typedef itk::ImageFileReader<ImageType> ReaderType;
    typedef itk::ImageFileWriter<ImageType> WriterType;
    
    typename ReaderType::Pointer reader = ReaderType::New();
	itk::NiftiImageIO::Pointer io = itk::NiftiImageIO::New();
	reader->SetImageIO(io);
	reader->SetFileName(inputFilename);
    
    OrientImage<ImageType> orientationFilter;
    orientationFilter.setInputImage(reader->GetOutput());
    
	if (displayInitialOrientation)
    {
        try {
            io->SetFileName(inputFilename);
            io->ReadImageInformation();
            //reader->Update();
        } catch( itk::ExceptionObject & e ) {
            std::cerr << "Exception caught while reading input image " << std::endl;
            std::cerr << e << std::endl;
        }
        
        typename ImageType::DirectionType direction;
        vector<double> dir0 = io->GetDirection(0);
        for (int i=0; i<dir0.size(); i++)
            direction(i,0) = dir0[i];
        vector<double> dir1 = io->GetDirection(1);
        for (int i=0; i<dir1.size(); i++)
            direction(i,1) = dir1[i];
        vector<double> dir2 = io->GetDirection(2);
        for (int i=0; i<dir2.size(); i++)
            direction(i,2) = dir2[i];
        cout << direction << endl;
        cout << "Input image orientation : " << FlagToString(orientationFilter.getOrientationFromDirection(direction)) << endl;
    }
    
	if (changeOrientation)
	{
        try {
            io->SetFileName(inputFilename);
            io->ReadImageInformation();
            //reader->Update();
        } catch( itk::ExceptionObject & e ) {
            std::cerr << "Exception caught while reading input image " << std::endl;
            std::cerr << e << std::endl;
        }
        
		orientationFilter.orientation(orientation);
        
		typename WriterType::Pointer writer = WriterType::New();
		writer->SetImageIO(io);
		writer->SetFileName(outputFilename);
		writer->SetInput(orientationFilter.getOutputImage());
		try {
			writer->Write();
		} catch( itk::ExceptionObject & e ) {
			std::cerr << "Exception caught while writing output image " << std::endl;
			std::cerr << e << std::endl;
		}
	}
    return EXIT_SUCCESS;
}
void Initialisation::savePointAsBinaryImage(ImageType::Pointer initialImage, string filename, OrientationType orientation)
{
    if (points_.size() > 0)
    {
        typedef itk::Image< unsigned char, 3 > BinaryImageType;
        BinaryImageType::Pointer binary = BinaryImageType::New();
        ImageType::RegionType region;
        ImageType::IndexType start;
        start[0] = 0; start[1] = 0; start[2] = 0;
        ImageType::SizeType size, imSize = initialImage->GetLargestPossibleRegion().GetSize();
        size[0] = imSize[0]; size[1] = imSize[1]; size[2] = imSize[2];
        region.SetSize(size);
        region.SetIndex(start);
        binary->CopyInformation(initialImage);
        binary->SetRegions(region);
        binary->Allocate();
        binary->FillBuffer(false);
        
        typedef ImageType::IndexType IndexType;
        ContinuousIndex ind;
        IndexType ind2;
        unsigned int pSize = points_.size();
        unsigned int indexMiddle = 0;
        for (unsigned int i=0; i<pSize; i++) {
            if (points_[i][1] == startSlice_)
                indexMiddle = i;
        }
        ind[0] = points_[indexMiddle][0]; ind[1] = points_[indexMiddle][1]; ind[2] = points_[indexMiddle][2];
        PointType pt;
        inputImage_->TransformContinuousIndexToPhysicalPoint(ind, pt);
        initialImage->TransformPhysicalPointToIndex(pt, ind2);
        binary->SetPixel(ind2,true);
        
        OrientImage<BinaryImageType> orientationFilter;
        orientationFilter.setInputImage(binary);
        orientationFilter.orientation(orientation);
        binary = orientationFilter.getOutputImage();
        
        ImageIterator it( binary, binary->GetRequestedRegion() );
        it.GoToBegin();
        while(!it.IsAtEnd())
        {
            if (it.Get()==true)
            {
                ind2 = it.GetIndex();
                break;
            }
            ++it;
        }
        if (verbose_) cout << "Center of spinal cord saved on pixel : " << ind2 << endl;
        
        WriterBinaryType::Pointer writer = WriterBinaryType::New();
        itk::NiftiImageIO::Pointer io = itk::NiftiImageIO::New();
        writer->SetImageIO(io);
        writer->SetFileName(filename);
        writer->SetInput(binary);
        try {
            writer->Write();
        } catch( itk::ExceptionObject & e ) {
            std::cerr << "Exception caught while writing image " << std::endl;
            std::cerr << e << std::endl;
        }
    }
    else cout << "Error: Spinal cord center not detected" << endl;
}