17 #ifndef __itkSamplingSchemeQSpaceIMOCEstimationFilter_hxx 18 #define __itkSamplingSchemeQSpaceIMOCEstimationFilter_hxx 29 template<
class TSamplingType >
37 template<
class TSamplingType >
43 if (this->m_FineOrientations->Size()==0)
47 m_FineScheme->SetOrientationsCartesian(m_FineOrientations);
51 m_MinDistanceInFineScheme = m_FineScheme->CalculateMinDistance(0,
true);
52 m_MinDistanceInFineScheme = std::sqrt(2-2*std::cos(m_MinDistanceInFineScheme));
55 m_Sample = SampleType::New();
56 m_Sample->SetMeasurementVectorSize( 3 );
57 unsigned int numberOfSamples = m_FineOrientations->Rows();
59 for (
unsigned int i = 0; i < numberOfSamples; ++i )
61 mv = (*m_FineScheme)[i];
62 m_Sample->PushBack( mv );
63 for (
int j = 0; j < 3; ++j )
65 m_Sample->PushBack( mv );
68 m_TreeGenerator = TreeGeneratorType::New();
69 m_TreeGenerator->SetSample( m_Sample );
70 m_TreeGenerator->SetBucketSize( 16 );
71 m_TreeGenerator->Update();
74 m_KDTree = m_TreeGenerator->GetOutput();
77 template<
class TSamplingType >
82 std::vector<double> euclideanDistances(angles.size()), overlapBallsInnerProduct(angles.size());
83 for (
int i = 0; i < angles.size(); ++i )
85 overlapBallsInnerProduct[i] = std::fabs(std::cos(2*angles[i]));
86 euclideanDistances[i] = std::sqrt(2-2*std::cos(angles[i]));
89 unsigned int numberOfShells = this->m_NumbersInShell.size();
90 unsigned int numberOfSamples = m_FineScheme->GetNumberOfSamples();
91 int totalNumberOfSamples = std::accumulate(this->m_NumbersInShell.begin(), this->m_NumbersInShell.end(), 0);
94 std::vector<int> coverageInShells(numberOfShells,0);
95 bool isSameAngle =
true;
96 for (
int j = 1; j < numberOfShells; ++j )
98 if (std::fabs(angles[0]-angles[j])>1e-4)
104 bool needCoverageInshells = m_ChooseMinimalCoverageShell && !isSameAngle;
107 typedef typename TreeType::InstanceIdentifierVectorType InstanceIdentifierVectorType;
108 InstanceIdentifierVectorType neighbors, neighbors_1, candidates, candidates_1, neighbors_jj;
109 InstanceIdentifierVectorType candidateNumbersInOverlap;
116 typedef utl_unordered_map<int, InstanceIdentifierVectorType> NeighborMapType;
117 typedef typename NeighborMapType::const_iterator NeighborMapIterator;
118 NeighborMapType neighborMap;
121 if (numberOfShells==1)
124 std::set<int> nextCandidateIndices;
126 int currentIndex = -1;
127 if (chosenIndices[0].size()==0)
130 while (chosenIndices[0].size()< this->m_NumbersInShell[0] )
134 hasChosen[currentIndex]=0;
135 chosenIndices[0].push_back(currentIndex);
136 queryPoint = (*m_FineScheme)[currentIndex];
139 indexDistPair=currentIndex;
141 NeighborMapIterator mapIter = neighborMap.find(indexDistPair);
142 if (mapIter==neighborMap.end())
144 m_KDTree->Search( queryPoint, euclideanDistances[0], neighbors );
145 neighborMap[indexDistPair] = neighbors;
148 neighbors = mapIter->second;
149 for (
int i = 0; i < neighbors.size(); ++i )
150 hasChosen[neighbors[i]/2] = 0;
152 m_KDTree->Search( queryPoint, euclideanDistances[0]+1*m_MinDistanceInFineScheme, candidates );
153 utlException(candidates.size()<=neighbors.size(),
"the size of candidates should be larger than the size of neighbors.");
155 for (
int i = 0; i < candidates.size(); ++i )
157 int jj = candidates[i]/2;
158 if (hasChosen[jj] == -1)
159 nextCandidateIndices.insert(jj);
162 int indexMaxOverlap=-1;
163 int sumMaxOverlap=-1;
164 int numberOfCandidates=0, numberSearch=0;
167 for (
typename std::set<int>::iterator iter = nextCandidateIndices.begin(); iter!=nextCandidateIndices.end(); ++iter )
170 if (hasChosen[jj]==-1)
172 queryCandidate = (*m_FineScheme)[jj];
173 bool overlapBall =
true;
174 double innerProduct = 0;
175 for (
int kk = 0; kk < 3; ++kk )
176 innerProduct+= queryPoint[kk]*queryCandidate[kk];
177 if (std::fabs(innerProduct) < overlapBallsInnerProduct[0])
181 if (sumOverlapVec[0][jj]>=0 && !overlapBall)
182 sumOverlap = sumOverlapVec[0][jj];
188 NeighborMapIterator mapIter = neighborMap.find(indexDistPair);
189 if (mapIter==neighborMap.end())
191 m_KDTree->Search( queryCandidate, euclideanDistances[0], neighbors_jj );
192 neighborMap[indexDistPair] = neighbors_jj;
195 neighbors_jj = mapIter->second;
197 for (
int k = 0; k < neighbors_jj.size(); ++k )
199 if (hasChosen[neighbors_jj[k]/2]==0)
202 sumOverlapVec[0][jj]=sumOverlap;
205 if (sumMaxOverlap<sumOverlap)
207 indexMaxOverlap = jj;
208 sumMaxOverlap = sumOverlap;
210 numberOfCandidates++;
216 if (numberOfCandidates==0)
219 currentIndex = indexMaxOverlap;
222 if (chosenIndices[0].size()==this->m_NumbersInShell[0])
224 *indices = chosenIndices;
237 for (
int s = 0; s < numberOfShells; ++s )
240 if (euclideanDistances[s]<= euclideanDistances.back())
245 std::vector<std::set<int> > nextCandidateIndices(numberOfShells+1);
248 int currentIndex = 0;
249 for (
int s = 0; s < numberOfShells; ++s )
251 hasChosen[currentIndex][s]=0;
252 hasChosen[currentIndex][numberOfShells]=s;
254 chosenIndices[s].push_back(currentIndex);
255 queryPoint = (*m_FineScheme)[currentIndex];
260 indexDistPair=currentIndex + s*numberOfSamples;
261 NeighborMapIterator mapIter = neighborMap.find(indexDistPair);
262 if (mapIter==neighborMap.end())
264 m_KDTree->Search( queryPoint, euclideanDistances[s], neighbors );
265 neighborMap[indexDistPair] = neighbors;
268 neighbors = mapIter->second;
269 for (
int i = 0; i < neighbors.size(); ++i )
270 hasChosen[neighbors[i]/2][s] = 0;
272 if (needCoverageInshells)
273 coverageInShells[s] += neighbors.size();
275 indexDistPair=currentIndex + numberOfShells*numberOfSamples;
276 mapIter = neighborMap.find(indexDistPair);
277 if (mapIter==neighborMap.end())
279 m_KDTree->Search( queryPoint, euclideanDistances.back(), neighbors_1 );
280 neighborMap[indexDistPair] = neighbors_1;
283 neighbors_1 = mapIter->second;
284 for (
int i = 0; i < neighbors_1.size(); ++i )
285 hasChosen[neighbors_1[i]/2][numberOfShells] = s;
287 m_KDTree->Search( queryPoint, euclideanDistances[s]+1*m_MinDistanceInFineScheme, candidates );
288 utlException(candidates.size()<=neighbors.size(),
"the size of candidates should be larger than the size of neighbors.");
290 m_KDTree->Search( queryPoint, euclideanDistances.back()+1*m_MinDistanceInFineScheme, candidates_1 );
291 utlException(candidates_1.size()<=neighbors_1.size(),
"the size of candidates should be larger than the size of neighbors.");
293 for (
int i = 0; i < candidates.size(); ++i )
295 int jj = candidates[i]/2;
296 if ( hasChosen[jj][s]==-1 && hasChosen[jj][numberOfShells]==-1)
297 nextCandidateIndices[s].insert(jj);
300 for (
int i = 0; i < candidates_1.size(); ++i )
302 int jj = candidates_1[i]/2;
303 if ( hasChosen[jj][numberOfShells]==-1)
305 for (
int sss = 0; sss < numberOfShells; ++sss )
307 if (sss!=s && hasChosen[jj][sss]==-1)
308 nextCandidateIndices[sss].insert(jj);
310 nextCandidateIndices[numberOfShells].insert(jj);
314 int indexMaxOverlap=-1;
315 int sumMaxOverlap=-1;
316 int numberOfCandidates=0, numberSearch=0;
318 for (
typename std::set<int>::iterator iter = nextCandidateIndices[numberOfShells].begin(); iter!=nextCandidateIndices[numberOfShells].end(); ++iter )
321 if (hasChosen[jj][numberOfShells]==-1)
323 queryCandidate = (*m_FineScheme)[jj];
324 bool overlapBall =
true;
325 double innerProduct = 0;
326 for (
int kk = 0; kk < 3; ++kk )
327 innerProduct+= queryPoint[kk]*queryCandidate[kk];
328 if (std::fabs(innerProduct) < overlapBallsInnerProduct[numberOfShells])
332 if (sumOverlapVec[numberOfShells][jj]>=0 && !overlapBall)
333 sumOverlap = sumOverlapVec[numberOfShells][jj];
338 indexDistPair = jj + numberOfShells*numberOfSamples;
339 mapIter = neighborMap.find(indexDistPair);
340 if (mapIter==neighborMap.end())
342 m_KDTree->Search( queryCandidate, euclideanDistances.back(), neighbors_jj );
343 neighborMap[indexDistPair] = neighbors_jj;
346 neighbors_jj = mapIter->second;
348 for (
int k = 0; k < neighbors_jj.size(); ++k )
350 if (hasChosen[neighbors_jj[k]/2][numberOfShells]>=0)
353 sumOverlapVec[numberOfShells][jj]=sumOverlap;
356 if (sumMaxOverlap<sumOverlap)
358 indexMaxOverlap = jj;
359 sumMaxOverlap = sumOverlap;
361 numberOfCandidates++;
365 currentIndex = indexMaxOverlap;
373 int indexShellMaxOverlap=-1, indexShellMaxOverlapLast=-1, shellIndexMinCoverage=-1;
375 for (
unsigned int n = numberOfShells; n < totalNumberOfSamples; ++n )
379 int indexMaxOverlap=-1;
380 int sumMaxOverlap=-1;
381 int numberOfCandidates=0, numberSearch=0;
383 if (needCoverageInshells)
386 for (
int s = 0; s < numberOfShells; ++s )
388 if (chosenIndices[s].size() >= this->m_NumbersInShell[s])
389 coverageInShells[s] = numberOfSamples;
392 shellIndexMinCoverage =
utl::argmin(coverageInShells.begin(), coverageInShells.end());
395 for (
int s = 0; s < numberOfShells; ++s )
398 if (needCoverageInshells && shellIndexMinCoverage!=s)
404 if (chosenIndices[s].size() < this->m_NumbersInShell[s])
407 for (
typename std::set<int>::iterator iter = nextCandidateIndices[s].begin(); iter!=nextCandidateIndices[s].end(); ++iter )
410 if (hasChosen[jj][s]==-1 && hasChosen[jj][numberOfShells]==-1)
412 queryCandidate = (*m_FineScheme)[jj];
413 bool overlapBall =
true;
414 if (n>numberOfShells)
416 double innerProduct = 0;
417 for (
int kk = 0; kk < 3; ++kk )
418 innerProduct+= queryPointLast[kk]*queryCandidate[kk];
421 if ( std::fabs(innerProduct) < overlapBallsInnerProduct[s] )
426 if (sumOverlapVec[s][jj]>=0 && !overlapBall)
427 sumOverlap = sumOverlapVec[s][jj];
431 indexDistPair=jj + s*numberOfSamples;
432 NeighborMapIterator mapIter = neighborMap.find(indexDistPair);
433 if (mapIter==neighborMap.end())
435 m_KDTree->Search( queryCandidate, euclideanDistances[s], neighbors_jj );
436 neighborMap[indexDistPair] = neighbors_jj;
439 neighbors_jj = mapIter->second;
441 for (
int k = 0; k < neighbors_jj.size(); ++k )
443 if (hasChosen[neighbors_jj[k]/2][s]>=0 || hasChosen[neighbors_jj[k]/2][numberOfShells]>=0)
446 sumOverlapVec[s][jj]=sumOverlap;
450 if (sumMaxOverlap<sumOverlap)
452 indexShellMaxOverlap = s;
453 indexMaxOverlap = jj;
454 sumMaxOverlap = sumOverlap;
456 numberOfCandidates++;
463 if (numberOfCandidates==0)
466 currentIndex = indexMaxOverlap;
467 indexShellMaxOverlapLast = indexMaxOverlap;
469 hasChosen[currentIndex][indexShellMaxOverlap]=0;
470 hasChosen[currentIndex][numberOfShells]=indexShellMaxOverlap;
471 chosenIndices[indexShellMaxOverlap].push_back(currentIndex);
472 queryPoint = (*m_FineScheme)[currentIndex];
473 queryPointLast = queryPoint;
475 indexDistPair=currentIndex+indexShellMaxOverlap*numberOfSamples;
476 NeighborMapIterator mapIter = neighborMap.find(indexDistPair);
477 if (mapIter==neighborMap.end())
479 m_KDTree->Search( queryPoint, euclideanDistances[indexShellMaxOverlap], neighbors );
480 neighborMap[indexDistPair] = neighbors;
483 neighbors = mapIter->second;
484 for (
int i = 0; i < neighbors.size(); ++i )
487 if (needCoverageInshells)
489 if (hasChosen[neighbors[i]/2][indexShellMaxOverlap]==-1)
490 coverageInShells[indexShellMaxOverlap]++;
492 hasChosen[neighbors[i]/2][indexShellMaxOverlap] = 0;
495 indexDistPair=currentIndex+numberOfShells*numberOfSamples;
496 mapIter = neighborMap.find(indexDistPair);
497 if (mapIter==neighborMap.end())
499 m_KDTree->Search( queryPoint, euclideanDistances.back(), neighbors_1 );
500 neighborMap[indexDistPair] = neighbors_1;
503 neighbors_1 = mapIter->second;
504 for (
int i = 0; i < neighbors_1.size(); ++i )
505 hasChosen[neighbors_1[i]/2][numberOfShells] = indexShellMaxOverlap;
507 m_KDTree->Search( queryPoint, euclideanDistances[indexShellMaxOverlap]+1*m_MinDistanceInFineScheme, candidates );
508 utlException(candidates.size()<=neighbors.size(),
"the size of candidates should be larger than the size of neighbors.");
510 m_KDTree->Search( queryPoint, euclideanDistances.back()+1*m_MinDistanceInFineScheme, candidates_1 );
511 utlException(candidates_1.size()<=neighbors_1.size(),
"the size of candidates should be larger than the size of neighbors.");
513 for (
int i = 0; i < candidates.size(); ++i )
515 int jj = candidates[i]/2;
516 if ( hasChosen[jj][indexShellMaxOverlap]==-1 && hasChosen[jj][numberOfShells]==-1)
517 nextCandidateIndices[indexShellMaxOverlap].insert(jj);
520 for (
int i = 0; i < candidates_1.size(); ++i )
522 int jj = candidates_1[i]/2;
523 if ( hasChosen[jj][numberOfShells]==-1)
525 for (
int sss = 0; sss < numberOfShells; ++sss )
527 if (sss!=indexShellMaxOverlap && hasChosen[jj][sss]==-1)
528 nextCandidateIndices[sss].insert(jj);
530 nextCandidateIndices[numberOfShells].insert(jj);
538 for (
int i = 0; i < chosenIndices.size(); ++i )
540 if (chosenIndices[i].size()!=this->m_NumbersInShell[i])
543 *indices = chosenIndices;
551 template<
class TSamplingType >
556 utlGlobalException(this->m_CriteriaType!=Self::DISTANCE,
"m_CriteriaType should be DISTANCE");
562 int numberOfShells = this->m_NumbersInShell.size();
563 int totalNumberOfSamples = std::accumulate(this->m_NumbersInShell.begin(), this->m_NumbersInShell.end(), 0);
564 int angleSize = numberOfShells==1?1:(numberOfShells+1);
565 std::vector<double> angles(angleSize,-1.0), anglesUpperBound(angleSize,-1.0), anglesLowerBound(angleSize,0.0);
566 std::vector<std::vector<double> > anglesTest(angleSize);
568 for (
int i = 0; i < numberOfShells; ++i )
569 anglesUpperBound[i] = SamplingType::CalculateMinDistanceUpperBound(2*this->m_NumbersInShell[i]);
570 if (numberOfShells>1)
571 anglesUpperBound[numberOfShells] = SamplingType::CalculateMinDistanceUpperBound(2*totalNumberOfSamples);
573 if (numberOfShells==1)
575 double angle_0=0, angle_1=anglesUpperBound[0];
576 while (angle_0<angle_1)
578 angles[0]= (angle_0+angle_1)*0.5;
579 bool successAngles = IsSatisfiedSeparationAngles(angles);
585 anglesTest[0].push_back(angles[0]);
589 if (anglesTest[0].size()>=2 && std::fabs(anglesTest[0].back()-anglesTest[0][anglesTest[0].size()-2])/anglesTest[0][anglesTest[0].size()-2]<m_AngleMinChange )
591 this->m_OutputOrientations = m_FineScheme;
600 std::vector<double> angle_0(anglesLowerBound), angle_1(anglesUpperBound);
603 for (
int i = 0; i < angleSize; ++i )
604 angles[i] = (angle_0[i]+angle_1[i])*0.5;
605 bool successAngles = IsSatisfiedSeparationAngles(angles);
611 for (
int i = 0; i < angleSize; ++i )
613 angle_0[i] = angles[i];
614 anglesTest[i].push_back(angles[i]);
619 for (
int i = 0; i < angleSize; ++i )
620 angle_1[i] = angles[i];
623 bool minAngleStop =
true;
624 for (
int i = 0; i < angleSize; ++i )
626 if (anglesTest[i].size()<2 || std::fabs(anglesTest[i].back()-anglesTest[i][anglesTest[i].size()-2])/anglesTest[i][anglesTest[i].size()-2]>=m_AngleMinChange )
628 minAngleStop =
false;
634 this->m_OutputOrientations = m_FineScheme;
unsigned int argmin(Iterator i1, Iterator i2)
helper functions specifically used in dmritool
itk::Point< double, 3 > MeasurementVectorType
SamplingSchemeQSpaceIMOCEstimationFilter()
#define utlException(cond, expout)
void Initialization() ITK_OVERRIDE
bool IsSatisfiedSeparationAngles(const std::vector< double > &angles)
#define utlGlobalException(cond, expout)
void GenerateData() ITK_OVERRIDE
SamplingType::Index2DVectorType Index2DVectorType
LightProcessObject Superclass
SamplingType::IndexVectorType IndexVectorType
SamplingType::Index2DVectorPointer Index2DVectorPointer
SamplingType::MatrixType MatrixType