From: dsarrut Date: Tue, 15 Feb 2011 10:44:32 +0000 (+0000) Subject: add findExtrema, jointSlices X-Git-Tag: v1.2.0~256 X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=11b92682c7b52e3920c733aeb2c97721359898e3;p=clitk.git add findExtrema, jointSlices --- diff --git a/itk/clitkSegmentationUtils.h b/itk/clitkSegmentationUtils.h index 3b388cb..77270d1 100644 --- a/itk/clitkSegmentationUtils.h +++ b/itk/clitkSegmentationUtils.h @@ -54,7 +54,8 @@ namespace clitk { SetBackground(const TInternalImageType * input, const TMaskInternalImageType * mask, typename TMaskInternalImageType::PixelType maskBG, - typename TInternalImageType::PixelType outValue); + typename TInternalImageType::PixelType outValue, + bool inPlace); //-------------------------------------------------------------------- @@ -145,17 +146,27 @@ namespace clitk { //-------------------------------------------------------------------- // In a binary image, search for the point belonging to the FG that // is the most exterma in the direction 'direction' (or in the - // opposite if notFlag is given). if 'point' and 'distanceMax' are - // given, do not consider points that are away from 'point' more - // than 'distanceMax' - template - typename SliceType::PointType - FindExtremaPointInAGivenDirection(const SliceType * input, - typename SliceType::PixelType bg, - int direction, - bool notFlag, - typename SliceType::PointType point, - double distanceMax); + // opposite if notFlag is given). + template + bool + FindExtremaPointInAGivenDirection(const ImageType * input, + typename ImageType::PixelType bg, + int direction, bool opposite, + typename ImageType::PointType & p); + + //-------------------------------------------------------------------- + + //-------------------------------------------------------------------- + // Same as above but check that the found point is not more than + // 'distanceMax' away from 'refPoint' + template + bool + FindExtremaPointInAGivenDirection(const ImageType * input, + typename ImageType::PixelType bg, + int direction, bool opposite, + typename ImageType::PointType refPoint, + double distanceMax, + typename ImageType::PointType & p); //-------------------------------------------------------------------- @@ -166,7 +177,114 @@ namespace clitk { int dim, double min, double max, bool autoCrop = false, typename ImageType::PixelType BG=0); + template + typename ImageType::Pointer + CropImageAbove(typename ImageType::Pointer image, + int dim, double min, + bool autoCrop = false, + typename ImageType::PixelType BG=0); + template + typename ImageType::Pointer + CropImageBelow(typename ImageType::Pointer image, + int dim, double max, + bool autoCrop = false, + typename ImageType::PixelType BG=0); + //-------------------------------------------------------------------- + + + //-------------------------------------------------------------------- + template + void + ComputeCentroids(typename ImageType::Pointer image, + typename ImageType::PixelType BG, + std::vector & centroids); + //-------------------------------------------------------------------- + + + //-------------------------------------------------------------------- + template + void + ExtractSlices(typename ImageType::Pointer image, + int dim, + std::vector< typename itk::Image::Pointer > & slices); + //-------------------------------------------------------------------- + + //-------------------------------------------------------------------- + template + typename ImageType::Pointer + JoinSlices(std::vector::Pointer > & slices, + typename ImageType::Pointer input, + int dim); + //-------------------------------------------------------------------- + + + //-------------------------------------------------------------------- + // Set of tools to manage 3D points and 2D points in slices + template + class PointsUtils + { + typedef typename ImageType::PointType PointType3D; + typedef typename ImageType::PixelType PixelType; + typedef typename ImageType::Pointer ImagePointer; + typedef typename ImageType::ConstPointer ImageConstPointer; + typedef itk::Image SliceType; + typedef typename SliceType::PointType PointType2D; + + typedef std::map MapPoint2DType; + typedef std::vector VectorPoint3DType; + public: + static void Convert2DTo3D(const PointType2D & p2D, + ImagePointer image, + const int slice, + PointType3D & p3D); + static void Convert2DTo3DList(const MapPoint2DType & map, + ImagePointer image, + VectorPoint3DType & list); + }; + + //-------------------------------------------------------------------- + template + void + WriteListOfLandmarks(std::vector points, + std::string filename); + //-------------------------------------------------------------------- + + + //-------------------------------------------------------------------- + template + typename ImageType::Pointer + Dilate(typename ImageType::Pointer image, + double radiusInMM, + typename ImageType::PixelType BG, + typename ImageType::PixelType FG, + bool extendSupport); + template + typename ImageType::Pointer + Dilate(typename ImageType::Pointer image, + typename ImageType::SizeType radius, + typename ImageType::PixelType BG, + typename ImageType::PixelType FG, + bool extendSupport); + template + typename ImageType::Pointer + Dilate(typename ImageType::Pointer image, + typename ImageType::PointType radiusInMM, + typename ImageType::PixelType BG, + typename ImageType::PixelType FG, + bool extendSupport); + //-------------------------------------------------------------------- + + //-------------------------------------------------------------------- + template + void ConvertOption(std::string optionName, uint given, + ValueType * values, VectorType & p, + uint dim, bool required); +#define ConvertOptionMacro(OPTIONNAME, VAR, DIM, REQUIRED) \ + ConvertOption(#OPTIONNAME, OPTIONNAME##_given, OPTIONNAME##_arg, VAR, DIM, REQUIRED); + } #include "clitkSegmentationUtils.txx" diff --git a/itk/clitkSegmentationUtils.txx b/itk/clitkSegmentationUtils.txx index c70edd5..94e9154 100644 --- a/itk/clitkSegmentationUtils.txx +++ b/itk/clitkSegmentationUtils.txx @@ -20,12 +20,17 @@ #include "clitkSetBackgroundImageFilter.h" #include "clitkSliceBySliceRelativePositionFilter.h" #include "clitkCropLikeImageFilter.h" +#include "clitkMemoryUsage.h" // itk #include #include #include #include +#include +#include +#include +#include //-------------------------------------------------------------------- template @@ -117,13 +122,17 @@ void clitk::ComputeRegionFromBB(typename ImageType::Pointer image, //-------------------------------------------------------------------- template typename ImageType::Pointer -clitk::SetBackground(//typename ImageType::ConstPointer input, - const ImageType * input, +clitk::SetBackground(const ImageType * input, const TMaskImageType * mask, typename TMaskImageType::PixelType maskBG, - typename ImageType::PixelType outValue) { - typedef clitk::SetBackgroundImageFilter SetBackgroundImageFilterType; - typename SetBackgroundImageFilterType::Pointer setBackgroundFilter = SetBackgroundImageFilterType::New(); + typename ImageType::PixelType outValue, + bool inPlace) { + typedef clitk::SetBackgroundImageFilter + SetBackgroundImageFilterType; + typename SetBackgroundImageFilterType::Pointer setBackgroundFilter + = SetBackgroundImageFilterType::New(); + // if (inPlace) setBackgroundFilter->ReleaseDataFlagOn(); // No seg fault + setBackgroundFilter->SetInPlace(inPlace); // This is important to keep memory low setBackgroundFilter->SetInput(input); setBackgroundFilter->SetInput2(mask); setBackgroundFilter->SetMaskValue(maskBG); @@ -153,6 +162,10 @@ int clitk::GetNumberOfConnectedComponentLabels(typename ImageType::Pointer input //-------------------------------------------------------------------- //-------------------------------------------------------------------- +/* + Warning : in this cas, we consider outputType like inputType, not + InternalImageType. Be sure it fits. + */ template typename ImageType::Pointer clitk::Labelize(const ImageType * input, @@ -165,6 +178,7 @@ clitk::Labelize(const ImageType * input, // Connected Component label typedef itk::ConnectedComponentImageFilter ConnectFilterType; typename ConnectFilterType::Pointer connectFilter = ConnectFilterType::New(); + // connectFilter->ReleaseDataFlagOn(); connectFilter->SetInput(input); connectFilter->SetBackgroundValue(BG); connectFilter->SetFullyConnected(isFullyConnected); @@ -172,13 +186,14 @@ clitk::Labelize(const ImageType * input, // Sort by size and remove too small area. typedef itk::RelabelComponentImageFilter RelabelFilterType; typename RelabelFilterType::Pointer relabelFilter = RelabelFilterType::New(); - relabelFilter->InPlaceOn(); + // relabelFilter->ReleaseDataFlagOn(); // if yes, fail when ExplosionControlledThresholdConnectedImageFilter ??? relabelFilter->SetInput(connectFilter->GetOutput()); relabelFilter->SetMinimumObjectSize(minimalComponentSize); relabelFilter->Update(); // Return result - return relabelFilter->GetOutput(); + typename ImageType::Pointer output = relabelFilter->GetOutput(); + return output; } //-------------------------------------------------------------------- @@ -278,21 +293,21 @@ clitk::SliceBySliceRelativePosition(const MaskImageType * input, std::string orientation, bool uniqueConnectedComponent, double spacing, - bool notflag) + bool inverseflag) { typedef clitk::SliceBySliceRelativePositionFilter SliceRelPosFilterType; typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New(); - sliceRelPosFilter->VerboseStepOff(); - sliceRelPosFilter->WriteStepOff(); + sliceRelPosFilter->VerboseStepFlagOff(); + sliceRelPosFilter->WriteStepFlagOff(); sliceRelPosFilter->SetInput(input); sliceRelPosFilter->SetInputObject(object); sliceRelPosFilter->SetDirection(direction); sliceRelPosFilter->SetFuzzyThreshold(threshold); - sliceRelPosFilter->SetOrientationTypeString(orientation); + sliceRelPosFilter->AddOrientationTypeString(orientation); sliceRelPosFilter->SetResampleBeforeRelativePositionFilter((spacing != -1)); sliceRelPosFilter->SetIntermediateSpacing(spacing); sliceRelPosFilter->SetUniqueConnectedComponentBySlice(uniqueConnectedComponent); - sliceRelPosFilter->SetNotFlag(notflag); + sliceRelPosFilter->SetInverseOrientationFlag(inverseflag); // sliceRelPosFilter->SetAutoCropFlag(true); ?? sliceRelPosFilter->Update(); return sliceRelPosFilter->GetOutput(); @@ -300,44 +315,93 @@ clitk::SliceBySliceRelativePosition(const MaskImageType * input, //-------------------------------------------------------------------- //-------------------------------------------------------------------- -template -typename SliceType::PointType -clitk::FindExtremaPointInAGivenDirection(const SliceType * input, - typename SliceType::PixelType bg, - int direction, - bool notFlag, - typename SliceType::PointType point, - double distanceMax) +template +bool +clitk::FindExtremaPointInAGivenDirection(const ImageType * input, + typename ImageType::PixelType bg, + int direction, bool opposite, + typename ImageType::PointType & point) +{ + typename ImageType::PointType dummy; + return clitk::FindExtremaPointInAGivenDirection(input, bg, direction, + opposite, dummy, 0, point); +} +//-------------------------------------------------------------------- + +//-------------------------------------------------------------------- +template +bool +clitk::FindExtremaPointInAGivenDirection(const ImageType * input, + typename ImageType::PixelType bg, + int direction, bool opposite, + typename ImageType::PointType refpoint, + double distanceMax, + typename ImageType::PointType & point) { /* loop over input pixels, store the index in the fg that is max according to the given direction. */ - typedef itk::ImageRegionConstIteratorWithIndex IteratorType; + typedef itk::ImageRegionConstIteratorWithIndex IteratorType; IteratorType iter(input, input->GetLargestPossibleRegion()); iter.GoToBegin(); - typename SliceType::IndexType max = input->GetLargestPossibleRegion().GetIndex(); - if (notFlag) max = max+input->GetLargestPossibleRegion().GetSize(); + typename ImageType::IndexType max = input->GetLargestPossibleRegion().GetIndex(); + if (opposite) max = max+input->GetLargestPossibleRegion().GetSize(); + bool found=false; while (!iter.IsAtEnd()) { if (iter.Get() != bg) { bool test = iter.GetIndex()[direction] > max[direction]; - if (notFlag) test = !test; + if (opposite) test = !test; if (test) { - typename SliceType::PointType p; + typename ImageType::PointType p; input->TransformIndexToPhysicalPoint(iter.GetIndex(), p); - if ((distanceMax==0) || (p.EuclideanDistanceTo(point) < distanceMax)) { + if ((distanceMax==0) || (p.EuclideanDistanceTo(refpoint) < distanceMax)) { max = iter.GetIndex(); + found = true; } } } ++iter; } - typename SliceType::PointType p; - input->TransformIndexToPhysicalPoint(max, p); - return p; + if (!found) return false; + input->TransformIndexToPhysicalPoint(max, point); + return true; } //-------------------------------------------------------------------- + +//-------------------------------------------------------------------- +template +typename ImageType::Pointer +clitk::CropImageAbove(typename ImageType::Pointer image, + int dim, double min, + bool autoCrop, + typename ImageType::PixelType BG) +{ + return clitk::CropImageAlongOneAxis(image, dim, + image->GetOrigin()[dim], + min, + autoCrop, BG); +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +typename ImageType::Pointer +clitk::CropImageBelow(typename ImageType::Pointer image, + int dim, double max, + bool autoCrop, + typename ImageType::PixelType BG) +{ + typename ImageType::PointType p; + image->TransformIndexToPhysicalPoint(image->GetLargestPossibleRegion().GetIndex()+ + image->GetLargestPossibleRegion().GetSize(), p); + return clitk::CropImageAlongOneAxis(image, dim, max, p[dim], autoCrop, BG); +} +//-------------------------------------------------------------------- + + //-------------------------------------------------------------------- template typename ImageType::Pointer @@ -359,6 +423,7 @@ clitk::CropImageAlongOneAxis(typename ImageType::Pointer image, size[dim] = fabs(end[dim]-start[dim]); region.SetIndex(start); region.SetSize(size); + // Perform Crop typedef itk::RegionOfInterestImageFilter CropFilterType; typename CropFilterType::Pointer cropFilter = CropFilterType::New(); @@ -366,6 +431,7 @@ clitk::CropImageAlongOneAxis(typename ImageType::Pointer image, cropFilter->SetRegionOfInterest(region); cropFilter->Update(); typename ImageType::Pointer result = cropFilter->GetOutput(); + // Auto Crop if (autoCrop) { result = clitk::AutoCrop(result, BG); @@ -373,3 +439,233 @@ clitk::CropImageAlongOneAxis(typename ImageType::Pointer image, return result; } //-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +void +clitk::ComputeCentroids(typename ImageType::Pointer image, + typename ImageType::PixelType BG, + std::vector & centroids) +{ + typedef long LabelType; + static const unsigned int Dim = ImageType::ImageDimension; + typedef itk::ShapeLabelObject< LabelType, Dim > LabelObjectType; + typedef itk::LabelMap< LabelObjectType > LabelMapType; + typedef itk::LabelImageToLabelMapFilter ImageToMapFilterType; + typename ImageToMapFilterType::Pointer imageToLabelFilter = ImageToMapFilterType::New(); + typedef itk::ShapeLabelMapFilter ShapeFilterType; + typename ShapeFilterType::Pointer statFilter = ShapeFilterType::New(); + imageToLabelFilter->SetBackgroundValue(BG); + imageToLabelFilter->SetInput(image); + statFilter->SetInput(imageToLabelFilter->GetOutput()); + statFilter->Update(); + typename LabelMapType::Pointer labelMap = statFilter->GetOutput(); + + centroids.clear(); + typename ImageType::PointType dummy; + centroids.push_back(dummy); // label 0 -> no centroid, use dummy point + for(uint i=1; iGetNumberOfLabelObjects()+1; i++) { + centroids.push_back(labelMap->GetLabelObject(i)->GetCentroid()); + } +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +void +clitk::ExtractSlices(typename ImageType::Pointer image, + int direction, + std::vector::Pointer > & slices) +{ + typedef clitk::ExtractSliceFilter ExtractSliceFilterType; + typedef typename ExtractSliceFilterType::SliceType SliceType; + typename ExtractSliceFilterType::Pointer + extractSliceFilter = ExtractSliceFilterType::New(); + extractSliceFilter->SetInput(image); + extractSliceFilter->SetDirection(direction); + extractSliceFilter->Update(); + extractSliceFilter->GetOutputSlices(slices); +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +typename ImageType::Pointer +clitk::JoinSlices(std::vector::Pointer > & slices, + typename ImageType::Pointer input, + int direction) { + typedef typename itk::Image SliceType; + typedef itk::JoinSeriesImageFilter JoinSeriesFilterType; + typename JoinSeriesFilterType::Pointer joinFilter = JoinSeriesFilterType::New(); + joinFilter->SetOrigin(input->GetOrigin()[direction]); + joinFilter->SetSpacing(input->GetSpacing()[direction]); + for(unsigned int i=0; iPushBackInput(slices[i]); + } + joinFilter->Update(); + return joinFilter->GetOutput(); +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +void +clitk::PointsUtils::Convert2DTo3D(const PointType2D & p, + ImagePointer image, + const int slice, + PointType3D & p3D) +{ + p3D[0] = p[0]; + p3D[1] = p[1]; + p3D[2] = (image->GetLargestPossibleRegion().GetIndex()[2]+slice)*image->GetSpacing()[2] + + image->GetOrigin()[2]; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +void +clitk::PointsUtils::Convert2DTo3DList(const MapPoint2DType & map, + ImagePointer image, + VectorPoint3DType & list) +{ + typename MapPoint2DType::const_iterator iter = map.begin(); + while (iter != map.end()) { + PointType3D p; + Convert2DTo3D(iter->second, image, iter->first, p); + list.push_back(p); + ++iter; + } +} +//-------------------------------------------------------------------- + +//-------------------------------------------------------------------- +template +void +clitk::WriteListOfLandmarks(std::vector points, + std::string filename) +{ + std::ofstream os; + openFileForWriting(os, filename); + os << "LANDMARKS1" << std::endl; + for(uint i=0; i +typename ImageType::Pointer +clitk::Dilate(typename ImageType::Pointer image, + double radiusInMM, + typename ImageType::PixelType BG, + typename ImageType::PixelType FG, + bool extendSupport) +{ + typename ImageType::SizeType r; + for(uint i=0; iGetSpacing()[i]); + return clitk::Dilate(image, r, BG, FG, extendSupport); +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +typename ImageType::Pointer +clitk::Dilate(typename ImageType::Pointer image, + typename ImageType::PointType radiusInMM, + typename ImageType::PixelType BG, + typename ImageType::PixelType FG, + bool extendSupport) +{ + typename ImageType::SizeType r; + for(uint i=0; iGetSpacing()[i]); + return clitk::Dilate(image, r, BG, FG, extendSupport); +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +typename ImageType::Pointer +clitk::Dilate(typename ImageType::Pointer image, + typename ImageType::SizeType radius, + typename ImageType::PixelType BG, + typename ImageType::PixelType FG, + bool extendSupport) +{ + // Create kernel for dilatation + typedef itk::BinaryBallStructuringElement KernelType; + KernelType structuringElement; + structuringElement.SetRadius(radius); + structuringElement.CreateStructuringElement(); + + if (extendSupport) { + typedef itk::ConstantPadImageFilter PadFilterType; + typename PadFilterType::Pointer padFilter = PadFilterType::New(); + padFilter->SetInput(image); + typename ImageType::SizeType lower; + typename ImageType::SizeType upper; + for(uint i=0; i<3; i++) { + lower[i] = upper[i] = 2*(radius[i]+1); + } + padFilter->SetPadLowerBound(lower); + padFilter->SetPadUpperBound(upper); + padFilter->Update(); + image = padFilter->GetOutput(); + } + + // Dilate filter + typedef itk::BinaryDilateImageFilter DilateFilterType; + typename DilateFilterType::Pointer dilateFilter = DilateFilterType::New(); + dilateFilter->SetBackgroundValue(BG); + dilateFilter->SetForegroundValue(FG); + dilateFilter->SetBoundaryToForeground(false); + dilateFilter->SetKernel(structuringElement); + dilateFilter->SetInput(image); + dilateFilter->Update(); + return image = dilateFilter->GetOutput(); +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +void clitk::ConvertOption(std::string optionName, uint given, + ValueType * values, VectorType & p, + uint dim, bool required) +{ + if (required && (given == 0)) { + clitkExceptionMacro("The option --" << optionName << " must be set and have 1 or " + << dim << " values."); + } + if (given == 1) { + for(uint i=0; i