void VglPlus::generateBox(const vgl_point_3d<double> & center, const vnl_vector_fixed<double, 3> & xyz_size, vcl_vector<vgl_point_3d<double> > & vertex) { int sign[][3] = {-1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1}; double x_s = xyz_size[0]; double y_s = xyz_size[1]; double z_s = xyz_size[2]; for (int i = 0; i<8; i++) { double x = center.x() + sign[i][0] * 0.5 * x_s; double y = center.y() + sign[i][1] * 0.5 * y_s; double z = center.z() + sign[i][2] * 0.5 * z_s; vertex.push_back(vgl_point_3d<double>(x, y, z)); } assert(vertex.size() == 8); }
vnl_vector_fixed<float,3> TrackingHandlerPeaks::GetMatchingDirection(itk::Index<3> idx3, vnl_vector_fixed<float,3>& oldDir) { vnl_vector_fixed<float,3> out_dir; out_dir.fill(0); float angle = 0; float mag = oldDir.magnitude(); if (mag<mitk::eps) { bool found = false; if (m_Random) { // try m_NumDirs times to get a non-zero random direction for (int j=0; j<m_NumDirs; j++) { int i = 0; #pragma omp critical i = m_RngItk->GetIntegerVariate(m_NumDirs-1); out_dir = GetDirection(idx3, i); if (out_dir.magnitude()>mitk::eps) { oldDir[0] = out_dir[0]; oldDir[1] = out_dir[1]; oldDir[2] = out_dir[2]; found = true; break; } } } if (!found) { // if you didn't find a non-zero random direction, take first non-zero direction you find for (int i=0; i<m_NumDirs; i++) { out_dir = GetDirection(idx3, i); if (out_dir.magnitude()>mitk::eps) { oldDir[0] = out_dir[0]; oldDir[1] = out_dir[1]; oldDir[2] = out_dir[2]; break; } } } } else { for (int i=0; i<m_NumDirs; i++) { vnl_vector_fixed<float,3> dir = GetDirection(idx3, i); mag = dir.magnitude(); if (mag>mitk::eps) dir.normalize(); float a = dot_product(dir, oldDir); if (fabs(a)>angle) { angle = fabs(a); if (a<0) out_dir = -dir; else out_dir = dir; out_dir *= mag; out_dir *= angle; // shrink contribution of direction if is less parallel to previous direction } } } return out_dir; }
static bool CompareVectors(const vnl_vector_fixed< double, 3 >& v1, const vnl_vector_fixed< double, 3 >& v2) { return (v1.magnitude()>v2.magnitude()); }
double MLBSTrackingFilter< NumImageFeatures >::FollowStreamline(ThreadIdType threadId, itk::Point<double, 3> pos, vnl_vector_fixed<double,3> dir, FiberType* fib, double tractLength, bool front) { vnl_vector_fixed<double,3> dirOld = dir; dirOld = dir; for (int step=0; step< m_MaxLength/2; step++) { while (m_PauseTracking){} if (m_DemoMode) { m_Mutex.Lock(); m_BuildFibersReady++; m_Tractogram.push_back(*fib); BuildFibers(true); m_Stop = true; m_Mutex.Unlock(); while (m_Stop){} } // get new position CalculateNewPosition(pos, dir); // is new position inside of image and mask if (!IsValidPosition(pos) || m_AbortTracking) // if not end streamline { return tractLength; } else // if yes, add new point to streamline { tractLength += m_StepSize; if (front) fib->push_front(pos); else fib->push_back(pos); if (m_AposterioriCurvCheck) { int curv = CheckCurvature(fib, front); // TODO: Move into classification ??? if (curv>0) { tractLength -= m_StepSize*curv; while (curv>0) { if (front) fib->pop_front(); else fib->pop_back(); curv--; } return tractLength; } } if (tractLength>m_MaxTractLength) return tractLength; } dir = GetNewDirection(pos, dirOld); if (dir.magnitude()<0.0001) return tractLength; } return tractLength; }
vnl_vector_fixed<double,3> MLBSTrackingFilter< NumImageFeatures >::GetNewDirection(itk::Point<double, 3> &pos, vnl_vector_fixed<double, 3>& olddir) { vnl_vector_fixed<double,3> direction; direction.fill(0); ItkUcharImgType::IndexType idx; m_StoppingRegions->TransformPhysicalPointToIndex(pos, idx); if (m_StoppingRegions->GetPixel(idx)>0) return direction; if (olddir.magnitude()>0) olddir.normalize(); int candidates = 0; // number of directions with probability > 0 double prob = 0; direction = Classify(pos, candidates, olddir, m_AngularThreshold, prob); // sample neighborhood direction *= prob; itk::OrientationDistributionFunction< double, 50 > probeVecs; for (int i=0; i<m_NumberOfSamples; i++) { vnl_vector_fixed<double,3> d; // probe[0] = GetRandDouble()*m_SamplingDistance; // probe[1] = GetRandDouble()*m_SamplingDistance; // probe[2] = GetRandDouble()*m_SamplingDistance; d = probeVecs.GetDirection(i)*m_SamplingDistance; itk::Point<double, 3> sample_pos; sample_pos[0] = pos[0] + d[0]; sample_pos[1] = pos[1] + d[1]; sample_pos[2] = pos[2] + d[2]; candidates = 0; vnl_vector_fixed<double,3> tempDir = Classify(sample_pos, candidates, olddir, m_AngularThreshold, prob); // sample neighborhood if (candidates>0 && tempDir.magnitude()>0.001) { direction += tempDir*prob; } else if (m_AvoidStop && candidates==0 && olddir.magnitude()>0) // out of white matter { double dot = dot_product(d, olddir); if (dot >= 0.0) // in front of plane defined by pos and olddir d = -d + 2*dot*olddir; // reflect else d = -d; // invert // look a bit further into the other direction sample_pos[0] = pos[0] + d[0]*2; sample_pos[1] = pos[1] + d[1]*2; sample_pos[2] = pos[2] + d[2]*2; candidates = 0; vnl_vector_fixed<double,3> tempDir = Classify(sample_pos, candidates, olddir, m_AngularThreshold, prob, true); // sample neighborhood if (candidates>0 && tempDir.magnitude()>0.001) // are we back in the white matter? { direction += d; // go into the direction of the white matter direction += tempDir*prob; // go into the direction of the white matter direction at this location } } } if (direction.magnitude()>0.001) { direction.normalize(); olddir[0] = direction[0]; olddir[1] = direction[1]; olddir[2] = direction[2]; } else direction.fill(0); return direction; }
vnl_vector_fixed<double,3> MLBSTrackingFilter< NumImageFeatures >::Classify(itk::Point<double, 3>& pos, int& candidates, vnl_vector_fixed<double,3>& olddir, double angularThreshold, double& prob, bool avoidStop) { vnl_vector_fixed<double,3> direction; direction.fill(0); vigra::MultiArray<2, double> featureData; if(m_UseDirection) featureData = vigra::MultiArray<2, double>( vigra::Shape2(1,NumImageFeatures+3) ); else featureData = vigra::MultiArray<2, double>( vigra::Shape2(1,NumImageFeatures) ); typename FeatureImageType::PixelType featurePixel = GetImageValues(pos); // pixel values for (unsigned int f=0; f<NumImageFeatures; f++) featureData(0,f) = featurePixel[f]; // direction features int c = 0; if (m_UseDirection) { vnl_vector_fixed<double,3> ref; ref.fill(0); ref[0]=1; for (unsigned int f=NumImageFeatures; f<NumImageFeatures+3; f++) { if (dot_product(ref, olddir)<0) featureData(0,f) = -olddir[c]; else featureData(0,f) = olddir[c]; c++; } } vigra::MultiArray<2, double> probs(vigra::Shape2(1, m_DecisionForest->class_count())); m_DecisionForest->predictProbabilities(featureData, probs); double outProb = 0; prob = 0; candidates = 0; // directions with probability > 0 for (int i=0; i<m_DecisionForest->class_count(); i++) { if (probs(0,i)>0) { int classLabel = 0; m_DecisionForest->ext_param_.to_classlabel(i, classLabel); if (classLabel<m_DirectionIndices.size()) { candidates++; vnl_vector_fixed<double,3> d = m_ODF.GetDirection(m_DirectionIndices.at(classLabel)); double dot = dot_product(d, olddir); if (olddir.magnitude()>0) { if (fabs(dot)>angularThreshold) { if (dot<0) d *= -1; dot = fabs(dot); direction += probs(0,i)*dot*d; prob += probs(0,i)*dot; } } else { direction += probs(0,i)*d; prob += probs(0,i); } } else outProb += probs(0,i); } } ItkDoubleImgType::IndexType idx; m_NotWmImage->TransformPhysicalPointToIndex(pos, idx); if (m_NotWmImage->GetLargestPossibleRegion().IsInside(idx)) { m_NotWmImage->SetPixel(idx, m_NotWmImage->GetPixel(idx)+outProb); m_WmImage->SetPixel(idx, m_WmImage->GetPixel(idx)+prob); } if (outProb>prob && prob>0) { candidates = 0; prob = 0; direction.fill(0.0); } if (avoidStop && m_AvoidStopImage->GetLargestPossibleRegion().IsInside(idx) && candidates>0 && direction.magnitude()>0.001) m_AvoidStopImage->SetPixel(idx, m_AvoidStopImage->GetPixel(idx)+0.1); return direction; }
vnl_vector_fixed<double,3> MLBSTrackingFilter< ShOrder, NumImageFeatures >::GetNewDirection(itk::Point<double, 3> &pos, vnl_vector_fixed<double, 3>& olddir) { if (m_DemoMode) { m_SamplingPointset->Clear(); m_AlternativePointset->Clear(); } vnl_vector_fixed<double,3> direction; direction.fill(0); ItkUcharImgType::IndexType idx; m_StoppingRegions->TransformPhysicalPointToIndex(pos, idx); if (m_StoppingRegions->GetLargestPossibleRegion().IsInside(idx) && m_StoppingRegions->GetPixel(idx)>0) return direction; if (m_MaskImage.IsNotNull() && ((m_MaskImage->GetLargestPossibleRegion().IsInside(idx) && m_MaskImage->GetPixel(idx)<=0) || !m_MaskImage->GetLargestPossibleRegion().IsInside(idx)) ) return direction; if (olddir.magnitude()>0) olddir.normalize(); int candidates = 0; // number of directions with probability > 0 double w = 0; // weight of the direction predicted at each sampling point if (IsValidPosition(pos)) { direction = m_ForestHandler.Classify(pos, candidates, olddir, m_AngularThreshold, w, m_MaskImage); // get direction proposal at current streamline position direction *= w; // HERE WE ARE WEIGHTING AGAIN EVEN THOUGH THE OUTPUT DIRECTIONS ARE ALREADY WEIGHTED!!! THE EFFECT OF THIS HAS YET TO BE EVALUATED. } itk::OrientationDistributionFunction< double, 50 > probeVecs; itk::Point<double, 3> sample_pos; int alternatives = 1; for (int i=0; i<m_NumberOfSamples; i++) { vnl_vector_fixed<double,3> d; if (m_RandomSampling) { d[0] = GetRandDouble(); d[1] = GetRandDouble(); d[2] = GetRandDouble(); d.normalize(); d *= GetRandDouble(0,m_SamplingDistance); } else { d = probeVecs.GetDirection(i)*m_SamplingDistance; } sample_pos[0] = pos[0] + d[0]; sample_pos[1] = pos[1] + d[1]; sample_pos[2] = pos[2] + d[2]; if(m_DemoMode) m_SamplingPointset->InsertPoint(i, sample_pos); candidates = 0; vnl_vector_fixed<double,3> tempDir; tempDir.fill(0.0); if (IsValidPosition(sample_pos)) tempDir = m_ForestHandler.Classify(sample_pos, candidates, olddir, m_AngularThreshold, w, m_MaskImage); // sample neighborhood if (candidates>0 && tempDir.magnitude()>0.001) { direction += tempDir*w; } else if (m_AvoidStop && candidates==0 && olddir.magnitude()>0) // out of white matter { double dot = dot_product(d, olddir); if (dot >= 0.0) // in front of plane defined by pos and olddir d = -d + 2*dot*olddir; // reflect else d = -d; // invert // look a bit further into the other direction sample_pos[0] = pos[0] + d[0]; sample_pos[1] = pos[1] + d[1]; sample_pos[2] = pos[2] + d[2]; if(m_DemoMode) m_AlternativePointset->InsertPoint(alternatives, sample_pos); alternatives++; candidates = 0; vnl_vector_fixed<double,3> tempDir; tempDir.fill(0.0); if (IsValidPosition(sample_pos)) tempDir = m_ForestHandler.Classify(sample_pos, candidates, olddir, m_AngularThreshold, w, m_MaskImage); // sample neighborhood if (candidates>0 && tempDir.magnitude()>0.001) // are we back in the white matter? { direction += d; // go into the direction of the white matter direction += tempDir*w; // go into the direction of the white matter direction at this location } } } if (direction.magnitude()>0.001) { direction.normalize(); olddir[0] = direction[0]; olddir[1] = direction[1]; olddir[2] = direction[2]; } else direction.fill(0); return direction; }