double Mesh::computeStandardDeviationFromPixelsInside(ImageType::Pointer image) { MeshTypeB::Pointer mesh = MeshTypeB::New(); typedef itk::Point< double, 3 > PointType; PointType pnt; ImageType::IndexType index; CVector3 p, n, min(10000,10000,10000), max; for (unsigned int i=0; i<points_.size(); i++) { p = points_[i]->getPosition(); pnt[0] = p[0]; pnt[1] = p[1]; pnt[2] = p[2]; mesh->SetPoint(i,pnt); image->TransformPhysicalPointToIndex(pnt, index); if (index[0]<min[0]) min[0]=index[0]; if (index[1]<min[1]) min[1]=index[1]; if (index[2]<min[2]) min[2]=index[2]; if (index[0]>max[0]) max[0]=index[0]; if (index[1]>max[1]) max[1]=index[1]; if (index[2]>max[2]) max[2]=index[2]; } 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); } CastFilterType::Pointer castFilter = CastFilterType::New(); castFilter->SetInput(image); BinaryImageType::Pointer im = castFilter->GetOutput(); BinaryImageType::IndexType indexRegion; BinaryImageType::SizeType sizeRegion; sizeRegion[0] = max[0]-min[0]+5; // adding two pixels at each side to be sure sizeRegion[1] = max[1]-min[1]+5; sizeRegion[2] = max[2]-min[2]+5; indexRegion[0] = min[0]-2; indexRegion[1] = min[1]-2; indexRegion[2] = min[2]-2; BinaryImageType::RegionType region(indexRegion,sizeRegion); im->SetRegions(region); MeshFilterType::Pointer meshFilter = MeshFilterType::New(); meshFilter->SetInput(mesh); meshFilter->SetInfoImage(im); /*meshFilter->SetDirection(image->GetDirection()); meshFilter->SetSpacing(image->GetSpacing()); meshFilter->SetOrigin(image->GetOrigin()); meshFilter->SetSize(sizeRegion); meshFilter->SetIndex(indexRegion);*/ 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; } MeshFilterType::OutputImageType::Pointer binary = meshFilter->GetOutput(); vector<double> valueVoxels; typedef ImageType::IndexType IndexType; IndexType ind; ImageIterator it( binary, binary->GetRequestedRegion() ); it.GoToBegin(); while(!it.IsAtEnd()) { if (it.Get()==true) { ind = it.GetIndex(); valueVoxels.push_back(image->GetPixel(ind)); } ++it; } double mean = 0.0, sum = 0.0, std = 0.0, nbVoxels = valueVoxels.size(); for (int i=0; i<nbVoxels; i++) mean += valueVoxels[i]; mean /= nbVoxels; for (int i=0; i<nbVoxels; i++) { sum += valueVoxels[i]*valueVoxels[i]; } std = sqrt(sum/nbVoxels-mean*mean); /*ofstream myfile; myfile.open("StandardDeviation.txt", ios_base::app); myfile << ind[1] << " " << mean << " " << std << endl; myfile.close();*/ return mean; }
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; } }
/* * mexFunction(): entry point for the mex function */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { // interface to deal with input arguments from Matlab enum InputIndexType {IN_TRI, IN_X, IN_RES, IN_SIZE, IN_ORIGIN, InputIndexType_MAX}; MatlabImportFilter::Pointer matlabImport = MatlabImportFilter::New(); matlabImport->ConnectToMatlabFunctionInput(nrhs, prhs); // check the number of input arguments matlabImport->CheckNumberOfArguments(2, InputIndexType_MAX); // register the inputs for this function at the import filter typedef MatlabImportFilter::MatlabInputPointer MatlabInputPointer; MatlabInputPointer inTRI = matlabImport->RegisterInput(IN_TRI, "TRI"); MatlabInputPointer inX = matlabImport->RegisterInput(IN_X, "X"); // (x, y, z) MatlabInputPointer inRES = matlabImport->RegisterInput(IN_RES, "RES"); // (r, c, s) MatlabInputPointer inSIZE = matlabImport->RegisterInput(IN_SIZE, "SIZE"); // (r, c, s) MatlabInputPointer inORIGIN = matlabImport->RegisterInput(IN_ORIGIN, "ORIGIN"); // (x, y, z) // interface to deal with outputs to Matlab enum OutputIndexType {OUT_IM, OutputIndexType_MAX}; MatlabExportFilter::Pointer matlabExport = MatlabExportFilter::New(); matlabExport->ConnectToMatlabFunctionOutput(nlhs, plhs); // check that the number of outputs the user is asking for is valid matlabExport->CheckNumberOfArguments(0, OutputIndexType_MAX); // register the outputs for this function at the export filter typedef MatlabExportFilter::MatlabOutputPointer MatlabOutputPointer; MatlabOutputPointer outIM = matlabExport->RegisterOutput(OUT_IM, "IM"); // if any input point set is empty, the outputs are empty too if (mxIsEmpty(inTRI->pm) || mxIsEmpty(inX->pm)) { matlabExport->CopyEmptyArrayToMatlab(outIM); return; } // get number of rows in inputs X and TRI mwSize nrowsX = mxGetM(inX->pm); mwSize nrowsTRI = mxGetM(inTRI->pm); // instantiate mesh MeshType::Pointer mesh = MeshType::New(); // read vertices PointSetType::Pointer xDef = PointSetType::New(); // default: empty point set PointSetType::Pointer x = PointSetType::New(); x->GetPoints()->CastToSTLContainer() = matlabImport->ReadVectorOfVectorsFromMatlab<PointType::CoordRepType, PointType> (inX, xDef->GetPoints()->CastToSTLContainer()); #ifdef DEBUG std::cout << "Number of X points read = " << x->GetNumberOfPoints() << std::endl; #endif // assertion check if (nrowsX != x->GetNumberOfPoints()) { mexErrMsgTxt(("Input " + inX->name + ": Number of points read different from number of points provided by user").c_str()); } // swap XY coordinates to make them compliant with ITK convention // (see important programming note at the help header above) matlabImport->SwapXYInVectorOfVectors<PointType::CoordRepType, std::vector<PointType> > (x->GetPoints()->CastToSTLContainer(), x->GetNumberOfPoints()); // populate mesh with vertices mesh->SetPoints(x->GetPoints()); // read triangles PointType triDef; triDef.Fill(mxGetNaN()); for (mwIndex i = 0; i < nrowsTRI; ++i) { PointType triangle = matlabImport->ReadRowVectorFromMatlab<CoordType, PointType>(inTRI, i, triDef); // create a triangle cell to read the vertex indices of the current input triangle CellAutoPointer cell; cell.TakeOwnership(new TriangleType); // assign to the 0, 1, 2 elements in the triangle cell the vertex // indices that we have just read. Note that we have to substract // 1 to convert Matlab's index convention 1, 2, 3, ... to C++ // convention 0, 1, 2, ... cell->SetPointId(0, triangle[0] - 1); cell->SetPointId(1, triangle[1] - 1); cell->SetPointId(2, triangle[2] - 1); // insert cell into the mesh mesh->SetCell(i, cell); } #ifdef DEBUG std::cout << "Number of triangles read = " << mesh->GetNumberOfCells() << std::endl; #endif // assertion check if (nrowsTRI != mesh->GetNumberOfCells()) { mexErrMsgTxt(("Input " + inTRI->name + ": Number of triangles read different from number of triangles provided by user").c_str()); } // get user input parameters for the output rasterization ImageType::SpacingType spacingDef; spacingDef.Fill(1.0); ImageType::SpacingType spacing = matlabImport-> ReadRowVectorFromMatlab<ImageType::SpacingValueType, ImageType::SpacingType>(inRES, spacingDef); ImageType::SizeType sizeDef; sizeDef.Fill(10); ImageType::SizeType size = matlabImport-> ReadRowVectorFromMatlab<ImageType::SizeValueType, ImageType::SizeType>(inSIZE, sizeDef); ImageType::PointType originDef; originDef.Fill(0.0); ImageType::PointType origin = matlabImport-> ReadRowVectorFromMatlab<ImageType::PointType::ValueType, ImageType::PointType>(inORIGIN, originDef); // (see important programming note at the help header above) matlabImport->SwapXYInVector<ImageType::PointType::ValueType, ImageType::PointType>(origin); // instantiate rasterization filter MeshFilterType::Pointer meshFilter = MeshFilterType::New(); // smallest voxel side length ImageType::SpacingValueType minSpacing = spacing[0]; for (mwIndex i = 1; i < Dimension; ++i) { minSpacing = std::min(minSpacing, spacing[i]); } // pass input parameters to the filter meshFilter->SetInput(mesh); meshFilter->SetSpacing(spacing); meshFilter->SetSize(size); meshFilter->SetOrigin(origin); meshFilter->SetTolerance(minSpacing / 10.0); meshFilter->SetInsideValue(1); meshFilter->SetOutsideValue(0); ImageType::IndexType start; start.Fill(0); meshFilter->SetIndex(start); // convert image size from itk::Size format to std::vector<mwSize> // so that we can use it in GraftItkImageOntoMatlab std::vector<mwSize> sizeStdVector(Dimension); for (unsigned int i = 0; i < Dimension; ++i) { sizeStdVector[i] = size[i]; } // graft ITK filter output onto Matlab output matlabExport->GraftItkImageOntoMatlab<PixelType, Dimension> (outIM, meshFilter->GetOutput(), sizeStdVector); #ifdef DEBUG std::cout << "Resolution (spacing) = " << meshFilter->GetSpacing() << std::endl; std::cout << "Size = " << meshFilter->GetSize() << std::endl; std::cout << "Origin = " << meshFilter->GetOrigin() << std::endl; #endif // run rasterization meshFilter->Update(); }