17 #ifndef __itkWatershedSegmenter_txx
18 #define __itkWatershedSegmenter_txx
39 template <
class TInputImage>
42 if (m_Connectivity.index != 0)
44 delete[] m_Connectivity.index;
46 if (m_Connectivity.direction !=0 )
48 delete[] m_Connectivity.direction;
53 template <
class TInputImage>
63 this->UpdateProgress(0.0);
64 if (m_DoBoundaryAnalysis ==
false)
66 this->GetSegmentTable()->Clear();
67 this->SetCurrentLabel(1);
72 typename InputImageType::Pointer input = this->GetInputImage();
99 ImageRegionType largestPossibleRegion = this->GetLargestPossibleRegion();
102 = this->GetLargestPossibleRegion();
105 typename ImageRegionType::IndexType tidx= thresholdImageRegion.GetIndex();
106 typename ImageRegionType::SizeType tsz = thresholdImageRegion.GetSize();
107 typename ImageRegionType::IndexType tlidx= thresholdLargestPossibleRegion.GetIndex();
108 typename ImageRegionType::SizeType tlsz = thresholdLargestPossibleRegion.GetSize();
109 for (i = 0; i < ImageDimension; ++i)
112 typename ImageRegionType::IndexType idx = regionToProcess.GetIndex();
113 typename ImageRegionType::SizeType sz = regionToProcess.GetSize();
116 idx[i] = regionToProcess.GetIndex()[i];
121 if (reg.GetIndex()[i] == largestPossibleRegion.GetIndex()[i])
129 boundary->SetValid(
false, i, 0);
135 boundary->SetValid(
true, i, 0);
139 idx[i] = (regionToProcess.GetIndex()[i]+regionToProcess.GetSize()[i]) - 1;
142 if ( (reg.GetIndex()[i] + reg.GetSize()[i])
143 == (largestPossibleRegion.GetIndex()[i]
144 + largestPossibleRegion.GetSize()[i]) )
149 boundary->SetValid(
false, i, 1);
155 boundary->SetValid(
true, i, 1);
158 thresholdImageRegion.SetSize(tsz);
159 thresholdImageRegion.SetIndex(tidx);
160 thresholdLargestPossibleRegion.SetSize(tlsz);
161 thresholdLargestPossibleRegion.SetIndex(tlidx);
166 typename InputImageType::Pointer thresholdImage = InputImageType::New();
168 thresholdImage->SetLargestPossibleRegion(thresholdLargestPossibleRegion);
169 thresholdImage->SetBufferedRegion(thresholdImageRegion);
170 thresholdImage->SetRequestedRegion(thresholdImageRegion);
171 thresholdImage->Allocate();
184 Self::MinMax(input, regionToProcess, minimum, maximum);
187 if (NumericTraits<InputPixelType>::is_integer
188 && maximum == NumericTraits<InputPixelType>::max())
190 maximum -= NumericTraits<InputPixelType>::One;
193 Self::Threshold(thresholdImage, input, regionToProcess, regionToProcess,
194 static_cast<InputPixelType>((m_Threshold * (maximum - minimum)) + minimum));
202 typename ImageRegionType::SizeType irsz;
203 typename ImageRegionType::IndexType iridx;
204 for (i = 0; i < ImageDimension; ++i)
206 irsz[i] = thresholdImageRegion.GetSize()[i] - 2;
207 iridx[i] = thresholdImageRegion.GetIndex()[i] + 1;
209 regionToProcess.SetIndex(iridx);
210 regionToProcess.SetSize(irsz);
216 this->GenerateConnectivity();
223 thresholdImage->SetRequestedRegion(regionToProcess);
224 this->ReleaseInputs();
230 output->SetBufferedRegion(thresholdImage->GetBufferedRegion());
232 Self::SetOutputImageValues(output, output->GetBufferedRegion(), Self::NULL_LABEL);
241 typename ImageRegionType::IndexType idx_b;
242 typename ImageRegionType::SizeType sz_b;
244 for (b_idx.first = 0; b_idx.first < ImageDimension; ++b_idx.first)
246 for (b_idx.second = 0; b_idx.second < 2; ++b_idx.second)
248 if (boundary->GetValid(b_idx) ==
false)
continue;
249 idx_b = thresholdImage->GetRequestedRegion().GetIndex();
250 sz_b = thresholdImage->GetRequestedRegion().GetSize();
252 if (b_idx.second == 1)
253 idx_b[b_idx.first] += sz_b[b_idx.first] - 1;
255 sz_b[b_idx.first] = 1;
257 reg_b.SetIndex(idx_b);
260 boundary->GetFace(b_idx)->SetLargestPossibleRegion(reg_b);
261 boundary->GetFace(b_idx)->SetRequestedRegion(reg_b);
262 boundary->GetFace(b_idx)->SetBufferedRegion(reg_b);
263 boundary->GetFace(b_idx)->Allocate();
266 this->UpdateProgress(0.1);
275 if (m_DoBoundaryAnalysis ==
true)
277 this->InitializeBoundary();
278 this->AnalyzeBoundaryFlow(thresholdImage, flatRegions, maximum +
279 NumericTraits<InputPixelType>::One);
282 this->UpdateProgress(0.2);
291 this->BuildRetainingWall( thresholdImage,
292 thresholdImage->GetBufferedRegion(),
293 maximum + NumericTraits<InputPixelType>::One );
300 this->LabelMinima(thresholdImage, thresholdImage->GetRequestedRegion(),
301 flatRegions, maximum + NumericTraits<InputPixelType>::One);
302 this->UpdateProgress(0.3);
304 this->GradientDescent(thresholdImage, thresholdImage->GetRequestedRegion());
305 this->UpdateProgress(0.4);
307 this->DescendFlatRegions(flatRegions, thresholdImage->GetRequestedRegion());
308 this->UpdateProgress(0.5);
310 this->UpdateSegmentTable(thresholdImage, thresholdImage->GetRequestedRegion());
311 this->UpdateProgress(0.6);
313 if (m_DoBoundaryAnalysis ==
true)
314 { this->CollectBoundaryInformation(flatRegions); }
315 this->UpdateProgress(0.7);
317 if (m_SortEdgeLists ==
true)
318 { this->GetSegmentTable()->SortEdgeLists(); }
319 this->UpdateProgress(0.8);
321 this->GetSegmentTable()->SetMaximumDepth(maximum - minimum);
322 this->UpdateProgress(1.0);
326 template <
class TInputImage>
339 typename BoundaryType::flat_hash_t::iterator flats_it;
341 typename flat_region_table_t::iterator flrt_it;
346 for (idx.first = 0; idx.first < ImageDimension; (idx.first)++)
348 for (idx.second = 0; idx.second < 2; (idx.second)++)
350 if (boundary->GetValid(idx) ==
false)
continue;
352 face = boundary->GetFace(idx);
353 flats = boundary->GetFlatHash(idx);
354 region = face->GetRequestedRegion();
360 faceIt = faceIt.
Begin();
361 labelIt = labelIt.
Begin();
364 faceIt.
Value().label = labelIt.
Get();
367 flrt_it = flatRegions.
find(labelIt.
Get());
368 if ( faceIt.
Get().flow != NULL_FLOW
369 && flrt_it != flatRegions.
end() )
373 flats_it = flats->
find(labelIt.
Get());
374 if (flats_it == flats->
end())
376 flr.
bounds_min = (*flrt_it).second.bounds_min;
377 flr.
min_label = *((*flrt_it).second.min_label_ptr);
378 flr.
value = (*flrt_it).second.value;
380 face->ComputeOffset(faceIt.
GetIndex()));
387 (*flats_it).second.offset_list.push_back(face->ComputeOffset(faceIt.
GetIndex()));
398 template <
class TInputImage>
407 fps.
flow = NULL_FLOW;
408 fps.
label = NULL_LABEL;
410 for (idx.first = 0; idx.first < ImageDimension; ++(idx.first))
412 for (idx.second = 0; idx.second < 2; ++(idx.second))
414 if (this->GetBoundary()->GetValid(idx) ==
false)
continue;
415 this->GetBoundary()->GetFlatHash(idx)->clear();
416 face = this->GetBoundary()->GetFace(idx);
418 (face, face->GetBufferedRegion());
419 for (faceIt = faceIt.
Begin(); ! faceIt.
IsAtEnd(); ++faceIt)
425 template <
class TInputImage>
435 unsigned int nCenter, i, nPos, cPos;
451 for (i = 0; i < ImageDimension; ++i)
455 fps.
label = NULL_LABEL;
461 for (idx.first = 0; idx.first < ImageDimension; ++(idx.first))
463 for (idx.second = 0; idx.second < 2; ++(idx.second))
466 if (boundary->GetValid(idx) ==
false)
continue;
469 region = face->GetRequestedRegion();
476 nCenter = searchIt.
Size() / 2;
480 if ((idx).second == 0)
483 cPos = m_Connectivity.index[(idx).first];
488 cPos = m_Connectivity.index[(ImageDimension - 1)
489 + (ImageDimension - (idx).first)];
499 fps.
flow =
static_cast<short>(cPos);
504 bool _labeled =
false;
505 bool _connected =
false;
506 for ( i=0; i <m_Connectivity.size; i++)
508 nPos = m_Connectivity.index[i];
510 && labelIt.
GetPixel(nPos) != Self::NULL_LABEL
515 if (_labeled ==
false)
517 labelIt.SetPixel(nCenter,
527 if (_connected ==
false )
529 labelIt.SetPixel(nCenter, m_CurrentLabel);
534 output->ComputeOffset(labelIt.
GetIndex());
537 flatRegions[m_CurrentLabel] = tempFlatRegion;
547 for (i = 0; i < m_Connectivity.size; i++)
549 nPos = m_Connectivity.index[i];
557 else isSteepest =
false;
559 if (isSteepest ==
true)
563 labelIt.SetPixel(nCenter, m_CurrentLabel);
567 fps.
flow =
static_cast<short>(cPos);
574 for (i = 0; i < m_Connectivity.size; i++)
576 nPos = m_Connectivity.index[i];
582 output->GetBufferPointer() +
583 output->ComputeOffset(labelIt.
GetIndex());
584 tempFlatRegion.
value =
587 flatRegions[m_CurrentLabel] = tempFlatRegion;
605 for (idx.first = 0; idx.first < ImageDimension; ++(idx.first))
607 for (idx.second = 0; idx.second < 2; ++(idx.second))
610 if (boundary->GetValid(idx) ==
false)
continue;
613 region = face->GetRequestedRegion();
615 Self::RelabelImage(output, region, eqTable);
620 Self::MergeFlatRegions(flatRegions, eqTable);
623 template <
class TInputImage>
627 unsigned int i, j, nSize, nCenter, stride;
642 for (i = 0; i < ImageDimension; ++i)
647 this->GetInputImage()->GetRequestedRegion());
649 nCenter = nSize >> 1;
652 for (i =0; i < m_Connectivity.size; i++)
654 for (j =0; j < ImageDimension; j++)
656 m_Connectivity.direction[i][j] = 0;
660 for (d = ImageDimension-1; d >=0; d--)
663 m_Connectivity.index[i] = nCenter - stride;
664 m_Connectivity.direction[i][d] = -1;
667 for (d = 0; d < static_cast<int>(ImageDimension); d++)
670 m_Connectivity.index[i] = nCenter + stride;
671 m_Connectivity.direction[i][d] = 1;
676 template <
class TInputImage>
681 unsigned int i, nSize, nCenter, nPos = 0;
682 bool foundSinglePixelMinimum, foundFlatRegion;
686 typename flat_region_table_t::iterator flatPtr;
695 for (i = 0; i < ImageDimension; ++i)
701 nSize = searchIt.
Size();
702 nCenter = nSize >> 1;
707 ! searchIt.
IsAtEnd(); ++searchIt, ++labelIt)
709 foundSinglePixelMinimum =
true;
710 foundFlatRegion =
false;
714 if ( labelIt.
GetPixel(nCenter) != Self::NULL_LABEL )
continue;
717 currentValue = searchIt.
GetPixel(nCenter);
719 for (i = 0; i < m_Connectivity.size; ++i)
721 nPos = m_Connectivity.index[i];
722 if ( currentValue == searchIt.
GetPixel(nPos) )
724 foundFlatRegion =
true;
727 else if ( currentValue > searchIt.
GetPixel(nPos) )
729 foundSinglePixelMinimum =
false;
735 if ( labelIt.
GetPixel(nPos) != Self::NULL_LABEL )
741 labelIt.
SetPixel(nCenter, m_CurrentLabel);
742 nPos = m_Connectivity.index[0];
746 tempFlatRegion.
value = currentValue;
747 flatRegions[m_CurrentLabel] = tempFlatRegion;
748 m_CurrentLabel = m_CurrentLabel + 1;
753 for ( i++; i <m_Connectivity.size; ++i)
755 nPos = m_Connectivity.index[i];
757 && labelIt.
GetPixel(nPos) != Self::NULL_LABEL
761 equivalentLabels->Add(labelIt.
GetPixel(nCenter),
766 else if (foundSinglePixelMinimum)
768 labelIt.
SetPixel(nCenter, m_CurrentLabel);
769 m_CurrentLabel = m_CurrentLabel + 1;
774 Self::MergeFlatRegions(flatRegions, equivalentLabels);
777 Self::RelabelImage(output, region, equivalentLabels);
779 equivalentLabels->Clear();
784 ! searchIt.
IsAtEnd(); ++searchIt, ++labelIt)
786 flatPtr = flatRegions.
find( labelIt.
GetPixel(nCenter) );
787 if ( flatPtr != flatRegions.
end() )
790 for (i = 0; i < m_Connectivity.size; ++i)
792 nPos = m_Connectivity.index[i];
795 searchIt.
GetPixel(nPos) < (*flatPtr).second.bounds_min )
798 (*flatPtr).second.bounds_min = searchIt.
GetPixel(nPos);
799 (*flatPtr).second.min_label_ptr = labelIt[nPos];
803 if ( labelIt.
GetPixel(nPos) != NULL_LABEL )
806 equivalentLabels->Add(labelIt.
GetPixel(nCenter),
813 else itkDebugMacro(
"An unexpected but non-fatal error has occurred.");
822 Self::MergeFlatRegions(flatRegions, equivalentLabels);
825 Self::RelabelImage(output, region, equivalentLabels);
828 template <
class TInputImage>
836 unsigned int i, nPos;
837 typename InputImageType::OffsetType moveIndex;
838 unsigned long newLabel;
839 std::stack< unsigned long * > updateStack;
846 for (i = 0; i < ImageDimension; ++i)
852 valueIt(rad, img, region);
854 labelIt(zeroRad, output, region);
863 if ( it.
Get() == NULL_LABEL )
867 newLabel = NULL_LABEL;
868 while( newLabel == NULL_LABEL )
871 minVal = valueIt.
GetPixel(m_Connectivity.index[0]);
872 moveIndex = m_Connectivity.direction[0];
873 for (
unsigned int ii = 1; ii < m_Connectivity.size; ++ii)
875 nPos = m_Connectivity.index[ii];
876 if ( valueIt.
GetPixel(nPos) < minVal)
879 moveIndex = m_Connectivity.direction[ii];
882 valueIt += moveIndex;
883 labelIt += moveIndex;
887 while( ! updateStack.empty() )
889 *(updateStack.top()) = newLabel;
897 template <
class TInputImage>
910 for (
typename flat_region_table_t::const_iterator region = flatRegionTable.
begin();
911 region != flatRegionTable.
end(); ++region)
913 if ( ((*region).second.bounds_min < (*region).second.value)
914 && (! (*region).second.is_on_boundary) )
916 equivalentLabels->Add((*region).first, *((*region).second.min_label_ptr));
920 equivalentLabels->Flatten();
921 Self::RelabelImage(output, imageRegion, equivalentLabels);
925 template <
class TInputImage>
932 typename edge_table_hash_t::iterator edge_table_entry_ptr;
933 typename edge_table_t::iterator edge_ptr;
935 unsigned int i, nPos;
939 unsigned long segment_label;
948 for (i = 0; i < ImageDimension; i++)
955 unsigned long hoodCenter = searchIt.
Size() >> 1;
958 ++searchIt, ++labelIt)
960 segment_label = labelIt.
GetPixel(hoodCenter);
964 segment_ptr = segments->Lookup(segment_label);
965 edge_table_entry_ptr = edgeHash.
find(segment_label);
966 if (segment_ptr == 0)
969 segments->Add(segment_label, temp_segment);
971 edgeHash.
insert(ValueType(segment_label,
974 edge_table_entry_ptr = edgeHash.
find(segment_label);
976 else if (searchIt.
GetPixel(hoodCenter) < segment_ptr->
min)
986 for (i = 0; i < m_Connectivity.size; ++i)
988 nPos = m_Connectivity.index[i];
989 if (labelIt.
GetPixel(nPos) != segment_label
990 && labelIt.
GetPixel(nPos) != NULL_LABEL)
993 lowest_edge = searchIt.
GetPixel(hoodCenter);
994 else lowest_edge = searchIt.
GetPixel(nPos);
997 edge_ptr = (*edge_table_entry_ptr).second.find(labelIt.
GetPixel(nPos));
998 if ( edge_ptr == (*edge_table_entry_ptr).second.end() )
1001 (*edge_table_entry_ptr).second.insert(
1002 ValueType(labelIt.
GetPixel(nPos), lowest_edge) );
1004 else if (lowest_edge < (*edge_ptr).second)
1006 (*edge_ptr).second = lowest_edge;
1017 unsigned long listsz;
1018 typename SegmentTableType::edge_list_t::iterator list_ptr;
1019 for (edge_table_entry_ptr = edgeHash.
begin();
1020 edge_table_entry_ptr != edgeHash.
end();
1021 edge_table_entry_ptr++)
1024 segment_ptr = segments->Lookup((*edge_table_entry_ptr).first);
1025 if ( segment_ptr == 0 )
1027 itkGenericExceptionMacro ( <<
"UpdateSegmentTable:: An unexpected and fatal error has occurred.");
1031 listsz =
static_cast<unsigned long>( (*edge_table_entry_ptr).second.size() );
1033 edge_ptr = (*edge_table_entry_ptr).second.begin();
1034 list_ptr = segment_ptr->
edge_list.begin();
1035 while ( edge_ptr != (*edge_table_entry_ptr).second.end() )
1037 list_ptr->label = (*edge_ptr).first;
1038 list_ptr->height= (*edge_ptr).second;
1044 (*edge_table_entry_ptr).second.clear();
1048 template <
class TInputImage>
1055 typename ImageRegionType::SizeType sz;
1056 typename ImageRegionType::IndexType idx;
1060 for (i = 0; i < ImageDimension; ++i)
1062 idx = region.GetIndex();
1063 sz = region.GetSize();
1068 idx[i] = region.GetSize()[i] + region.GetIndex()[i] - 1;
1079 template <
class TInputImage>
1095 template <
class TInputImage>
1099 unsigned long value)
1110 template <
class TInputImage>
1121 if (it.
Get() > max) max = it.
Get();
1122 if (it.
Get() < min) min = it.
Get();
1127 template <
class TInputImage>
1139 typename flat_region_table_t::iterator a, b;
1141 it != eqTable->End(); ++it)
1143 if ( ((a = regions.
find((*it).first)) == regions.
end())
1144 || ((b = regions.
find((*it).second)) == regions.
end()) )
1146 itkGenericExceptionMacro ( <<
"MergeFlatRegions:: An unexpected and fatal error has occurred.");
1149 if ((*a).second.bounds_min < (*b).second.bounds_min)
1151 (*b).second.bounds_min = (*a).second.bounds_min;
1152 (*b).second.min_label_ptr = (*a).second.min_label_ptr;
1159 template <
class TInputImage>
1173 temp = eqTable->Lookup(it.
Get());
1174 if (temp != it.
Get()) { it.
Set(temp);}
1179 template <
class TInputImage>
1195 if (NumericTraits<InputPixelType>::is_integer)
1205 if ( tmp < threshold )
1209 else if (tmp == NumericTraits<InputPixelType>::max())
1211 dIt.
Set(tmp - NumericTraits<InputPixelType>::One);
1226 if ( sIt.
Get() < threshold )
1245 template<
class TInputImage>
1251 {
return static_cast<DataObject*
>(OutputImageType::New().GetPointer());}
1253 {
return static_cast<DataObject*
>(SegmentTableType::New().GetPointer());}
1255 {
return static_cast<DataObject*
>(BoundaryType::New().GetPointer());}
1260 template <
class TInputImage>
1266 Superclass::UpdateOutputInformation();
1269 typename InputImageType::Pointer inputPtr = this->GetInputImage();
1272 if ( !inputPtr || !outputPtr )
1278 const typename InputImageType::SizeType& inputSize
1279 = inputPtr->GetLargestPossibleRegion().GetSize();
1280 const typename InputImageType::IndexType& inputStartIndex
1281 = inputPtr->GetLargestPossibleRegion().GetIndex();
1286 for (i = 0; i < OutputImageType::ImageDimension; i++)
1288 outputSize[i] = inputSize[i];
1289 outputStartIndex[i] = inputStartIndex[i];
1293 outputLargestPossibleRegion.SetSize( outputSize );
1294 outputLargestPossibleRegion.
SetIndex( outputStartIndex );
1296 outputPtr->SetLargestPossibleRegion( outputLargestPossibleRegion );
1299 template <
class TInputImage>
1303 Superclass::GenerateInputRequestedRegion();
1306 typename InputImageType::Pointer inputPtr = this->GetInputImage();
1309 if ( !inputPtr || !outputPtr )
1318 inputPtr->SetRequestedRegion( outputPtr->GetRequestedRegion() );
1322 template <
class TInputImage>
1332 typename TInputImage::RegionType c_reg;
1336 std::vector<ProcessObject::DataObjectPointer>::size_type idx;
1337 for (idx = 0; idx < this->GetOutputs().size(); ++idx)
1339 if (this->GetOutputs()[idx] && this->GetOutputs()[idx] != output)
1342 *
>(this->GetOutputs()[idx].GetPointer());
1350 template <
class TInputImage>
1355 m_MaximumFloodLevel = 1.0;
1357 m_DoBoundaryAnalysis =
false;
1358 m_SortEdgeLists =
true;
1359 m_Connectivity.direction = 0;
1360 m_Connectivity.index = 0;
1366 =
static_cast<BoundaryType*
>(this->MakeOutput(2).GetPointer());
1367 this->SetNumberOfRequiredOutputs(3);
1373 m_Connectivity.size = 2 * ImageDimension;
1374 m_Connectivity.index =
new unsigned int[m_Connectivity.size];
1375 m_Connectivity.direction
1376 =
new typename InputImageType::OffsetType[m_Connectivity.size];
1379 template<
class TInputImage>
1384 Superclass::PrintSelf(os,indent);
1385 os << indent <<
"SortEdgeLists: " << m_SortEdgeLists << std::endl;
1386 os << indent <<
"DoBoundaryAnalysis: " << m_DoBoundaryAnalysis << std::endl;
1387 os << indent <<
"Threshold: " << m_Threshold << std::endl;
1388 os << indent <<
"MaximumFloodLevel: " << m_MaximumFloodLevel << std::endl;
1389 os << indent <<
"CurrentLabel: " << m_CurrentLabel << std::endl;