4 #include <vtkPolyLine.h>
5 #include <vtkCellArray.h>
6 #include <vtkCellData.h>
9 #include <itkTimeProbe.h>
10 #include <itkImageRegionIterator.h>
13 #define _USE_MATH_DEFINES
15 #include <boost/progress.hpp>
20 static bool CompareVectorLengths(
const vnl_vector_fixed< double, 3 >& v1,
const vnl_vector_fixed< double, 3 >& v2)
22 return (v1.magnitude()>v2.magnitude());
25 template<
class PixelType >
27 m_AngularThreshold(0.7),
30 m_NormalizeVectors(false),
31 m_UseWorkingCopy(true),
32 m_MaxNumDirections(3),
34 m_NumDirectionsImage(NULL),
35 m_CreateDirectionImages(true)
37 this->SetNumberOfRequiredOutputs(1);
41 template<
class PixelType >
47 template<
class PixelType >
50 vnl_vector_fixed<double, 3> vnlVector;
51 vnlVector[0] = point[0];
52 vnlVector[1] = point[1];
53 vnlVector[2] = point[2];
58 template<
class PixelType >
61 itk::Point<double, 3> itkPoint;
62 itkPoint[0] = point[0];
63 itkPoint[1] = point[1];
64 itkPoint[2] = point[2];
68 template<
class PixelType >
74 itk::Vector<double> spacing;
75 itk::Point<double> origin;
76 itk::Matrix<double, 3, 3> direction;
77 ImageRegion<3> imageRegion;
78 if (!m_MaskImage.IsNull())
80 spacing = m_MaskImage->GetSpacing();
81 imageRegion = m_MaskImage->GetLargestPossibleRegion();
82 origin = m_MaskImage->GetOrigin();
83 direction = m_MaskImage->GetDirection();
87 spacing = geometry->GetSpacing();
88 origin = geometry->GetOrigin();
90 origin[0] += bounds.GetElement(0);
91 origin[1] += bounds.GetElement(2);
92 origin[2] += bounds.GetElement(4);
94 for (
int i=0; i<3; i++)
95 for (
int j=0; j<3; j++)
96 direction[j][i] = geometry->GetMatrixColumn(i)[j];
97 imageRegion.SetSize(0, geometry->GetExtent(0));
98 imageRegion.SetSize(1, geometry->GetExtent(1));
99 imageRegion.SetSize(2, geometry->GetExtent(2));
103 m_MaskImage->SetSpacing( spacing );
104 m_MaskImage->SetOrigin( origin );
105 m_MaskImage->SetDirection( direction );
106 m_MaskImage->SetRegions( imageRegion );
107 m_MaskImage->Allocate();
108 m_MaskImage->FillBuffer(1);
110 OutputImageType::RegionType::SizeType outImageSize = imageRegion.GetSize();
111 m_OutImageSpacing = m_MaskImage->GetSpacing();
116 m_NumDirectionsImage->SetSpacing( spacing );
117 m_NumDirectionsImage->SetOrigin( origin );
118 m_NumDirectionsImage->SetDirection( direction );
119 m_NumDirectionsImage->SetRegions( imageRegion );
120 m_NumDirectionsImage->Allocate();
121 m_NumDirectionsImage->FillBuffer(0);
127 double minSpacing = 1;
128 if(m_OutImageSpacing[0]<m_OutImageSpacing[1] && m_OutImageSpacing[0]<m_OutImageSpacing[2])
129 minSpacing = m_OutImageSpacing[0];
130 else if (m_OutImageSpacing[1] < m_OutImageSpacing[2])
131 minSpacing = m_OutImageSpacing[1];
133 minSpacing = m_OutImageSpacing[2];
135 if (m_UseWorkingCopy)
136 m_FiberBundle = m_FiberBundle->GetDeepCopy();
139 m_FiberBundle->ResampleSpline(minSpacing/10);
142 vtkSmartPointer<vtkPolyData> fiberPolyData = m_FiberBundle->GetFiberPolyData();
143 int numFibers = m_FiberBundle->GetNumFibers();
146 VectorContainer< unsigned int, std::vector< double > >
::Pointer peakLengths = VectorContainer< unsigned int, std::vector< double > >
::New();
148 MITK_INFO <<
"Generating directions from tractogram";
149 boost::progress_display disp(numFibers);
150 for(
int i=0; i<numFibers; i++ )
153 vtkCell* cell = fiberPolyData->GetCell(i);
154 int numPoints = cell->GetNumberOfPoints();
155 vtkPoints* points = cell->GetPoints();
159 vnl_vector_fixed<double, 3> dir;
160 itk::Point<double, 3> worldPos;
161 vnl_vector<double> v;
164 float fiberWeight = m_FiberBundle->GetFiberWeight(i);
166 for(
int j=0; j<numPoints-1; j++)
169 double* temp = points->GetPoint(j);
170 worldPos = GetItkPoint(temp);
172 m_MaskImage->TransformPhysicalPointToIndex(worldPos, index);
173 if (!m_MaskImage->GetLargestPossibleRegion().IsInside(index) || m_MaskImage->GetPixel(index)==0)
177 v = GetVnlVector(temp);
178 dir = GetVnlVector(points->GetPoint(j+1))-v;
184 unsigned int idx = index[0] + outImageSize[0]*(index[1] + outImageSize[1]*index[2]);
186 if (m_DirectionsContainer->IndexExists(idx))
188 peakLengths->ElementAt(idx).push_back(fiberWeight);
190 dirCont = m_DirectionsContainer->GetElement(idx);
191 if (dirCont.IsNull())
194 dirCont->push_back(dir);
195 m_DirectionsContainer->InsertElement(idx, dirCont);
198 dirCont->push_back(dir);
203 dirCont->push_back(dir);
204 m_DirectionsContainer->InsertElement(idx, dirCont);
206 std::vector< double > lengths; lengths.push_back(fiberWeight);
207 peakLengths->InsertElement(idx, lengths);
215 itk::ImageRegionIterator<ItkUcharImgType> dirIt(m_NumDirectionsImage, m_NumDirectionsImage->GetLargestPossibleRegion());
218 boost::progress_display disp2(outImageSize[0]*outImageSize[1]*outImageSize[2]);
219 while(!dirIt.IsAtEnd())
222 OutputImageType::IndexType index = dirIt.GetIndex();
223 int idx = index[0]+(index[1]+index[2]*outImageSize[1])*outImageSize[0];
225 if (!m_DirectionsContainer->IndexExists(idx))
231 if (dirCont.IsNull() || dirCont->empty())
239 if (m_MaxNumDirections>0)
241 directions = FastClustering(dirCont, peakLengths->GetElement(idx));
245 directions = dirCont;
247 unsigned int numDir = directions->size();
248 if (m_MaxNumDirections>0 && numDir>m_MaxNumDirections)
249 numDir = m_MaxNumDirections;
252 for (
unsigned int i=0; i<numDir; i++)
255 itk::ContinuousIndex<double, 3> center;
256 center[0] = index[0];
257 center[1] = index[1];
258 center[2] = index[2];
259 itk::Point<double> worldCenter;
260 m_MaskImage->TransformContinuousIndexToPhysicalPoint( center, worldCenter );
263 if (dir.magnitude()<m_SizeThreshold)
265 if (m_NormalizeVectors)
269 if (m_CreateDirectionImages && i<10)
271 if (i==m_DirectionImageContainer->size())
274 directionImage->SetSpacing( spacing );
275 directionImage->SetOrigin( origin );
276 directionImage->SetDirection( direction );
277 directionImage->SetRegions( imageRegion );
278 directionImage->Allocate();
280 directionImage->FillBuffer(nullVec);
281 m_DirectionImageContainer->InsertElement(i, directionImage);
287 pixel.SetElement(0, dir[0]);
288 pixel.SetElement(1, dir[1]);
289 pixel.SetElement(2, dir[2]);
290 directionImage->SetPixel(index, pixel);
294 itk::Point<double> worldStart;
295 worldStart[0] = worldCenter[0]-dir[0]/2*minSpacing;
296 worldStart[1] = worldCenter[1]-dir[1]/2*minSpacing;
297 worldStart[2] = worldCenter[2]-dir[2]/2*minSpacing;
298 vtkIdType
id = m_VtkPoints->InsertNextPoint(worldStart.GetDataPointer());
299 container->GetPointIds()->InsertNextId(
id);
300 itk::Point<double> worldEnd;
301 worldEnd[0] = worldCenter[0]+dir[0]/2*minSpacing;
302 worldEnd[1] = worldCenter[1]+dir[1]/2*minSpacing;
303 worldEnd[2] = worldCenter[2]+dir[2]/2*minSpacing;
304 id = m_VtkPoints->InsertNextPoint(worldEnd.GetDataPointer());
305 container->GetPointIds()->InsertNextId(
id);
306 m_VtkCellArray->InsertNextCell(container);
313 directionsPolyData->SetPoints(m_VtkPoints);
314 directionsPolyData->SetLines(m_VtkCellArray);
319 template<
class PixelType >
323 if (inDirs->size()<2)
327 std::vector< int > touched;
330 touched.resize(inDirs->size(), 0);
332 currentMean = inDirs->at(0);
333 currentMean.normalize();
334 double length = lengths.at(0);
336 std::vector< double > newLengths;
337 bool meanChanged =
false;
347 while (fabs(dot_product(currentMean, oldMean))<0.99)
349 oldMean = currentMean;
350 currentMean.fill(0.0);
351 for (
unsigned int i=0; i<inDirs->size(); i++)
353 angle = dot_product(oldMean, inDirs->at(i));
354 if (angle>=m_AngularThreshold)
356 currentMean += inDirs->at(i);
358 length += lengths.at(i);
362 else if (-angle>=m_AngularThreshold)
364 currentMean -= inDirs->at(i);
366 length += lengths.at(i);
372 currentMean = oldMean;
374 currentMean.normalize();
378 outDirs->push_back(currentMean);
379 newLengths.push_back(length);
385 for (
unsigned int i=0; i<touched.size(); i++)
388 currentMean = inDirs->at(i);
391 length = lengths.at(i);
397 if (inDirs->size()==outDirs->size())
400 for (
unsigned int i=0; i<outDirs->size(); i++)
401 outDirs->SetElement(i, outDirs->at(i)*newLengths.at(i)/
max);
405 return FastClustering(outDirs, newLengths);
itk::SmartPointer< Self > Pointer
BoundingBoxType::BoundsArrayType BoundsArrayType
TractsToVectorImageFilter()
virtual ~TractsToVectorImageFilter()
vnl_vector_fixed< double, 3 > GetVnlVector(double point[3])
vnl_vector_fixed< double, 3 > DirectionType
itk::Point< double, 3 > GetItkPoint(double point[3])
void GenerateData() override
A version of GenerateData() specific for image processing filters.
static bool CompareVectorLengths(const vnl_vector_fixed< double, 3 > &v1, const vnl_vector_fixed< double, 3 > &v2)
Extracts the voxel-wise main directions of the input fiber bundle.
DirectionContainerType::Pointer FastClustering(DirectionContainerType::Pointer inDirs, std::vector< double > lengths)
cluster fiber directions
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.