84
80
maskFilter->SetInput( input );
85
81
maskFilter->SetInput2( mask );
86
82
maskFilter->Update();
87
input = maskFilter->GetOutput();
91
InputLineIteratorType inLineIt(input, output->GetRequestedRegion());
83
m_Input = maskFilter->GetOutput();
90
long nbOfThreads = this->GetNumberOfThreads();
91
if( itk::MultiThreader::GetGlobalMaximumNumberOfThreads() != 0 )
93
nbOfThreads = vnl_math_min( this->GetNumberOfThreads(), itk::MultiThreader::GetGlobalMaximumNumberOfThreads() );
95
// number of threads can be constrained by the region size, so call the SplitRequestedRegion
96
// to get the real number of threads which will be used
97
typename TOutputImage::RegionType splitRegion; // dummy region - just to call the following method
98
nbOfThreads = this->SplitRequestedRegion(0, nbOfThreads, splitRegion);
99
// std::cout << "nbOfThreads: " << nbOfThreads << std::endl;
101
// set up the vars used in the threads
102
m_NumberOfLabels.clear();
103
m_NumberOfLabels.resize( nbOfThreads, 0 );
104
m_Barrier = Barrier::New();
105
m_Barrier->Initialize( nbOfThreads );
106
long pixelcount = output->GetRequestedRegion().GetNumberOfPixels();
107
long xsize = output->GetRequestedRegion().GetSize()[0];
108
long linecount = pixelcount/xsize;
109
m_LineMap.resize( linecount );
110
m_FirstLineIdToJoin.resize( nbOfThreads - 1 );
114
template< class TInputImage, class TOutputImage, class TMaskImage >
116
ConnectedComponentImageFilter< TInputImage, TOutputImage, TMaskImage>
117
::ThreadedGenerateData(const RegionType& outputRegionForThread,
120
typename TOutputImage::Pointer output = this->GetOutput();
121
typename TMaskImage::ConstPointer mask = this->GetMaskImage();
123
long nbOfThreads = m_NumberOfLabels.size();
125
// create a line iterator
126
typedef itk::ImageLinearConstIteratorWithIndex<InputImageType>
127
InputLineIteratorType;
128
InputLineIteratorType inLineIt(m_Input, outputRegionForThread);
92
129
inLineIt.SetDirection(0);
94
// Allocate the output
95
this->AllocateOutputs();
97
long int lab = NumericTraits<long int>::Zero;
131
// set the progress reporter to deal with the number of lines
132
long pixelcountForThread = outputRegionForThread.GetNumberOfPixels();
133
long xsizeForThread = outputRegionForThread.GetSize()[0];
134
long linecountForThread = pixelcountForThread/xsizeForThread;
135
ProgressReporter progress(this, threadId, linecountForThread * 2);
137
// find the split axis
138
IndexType outputRegionIdx = output->GetRequestedRegion().GetIndex();
139
IndexType outputRegionForThreadIdx = outputRegionForThread.GetIndex();
140
SizeType outputRegionSize = output->GetRequestedRegion().GetSize();
141
SizeType outputRegionForThreadSize = outputRegionForThread.GetSize();
143
for( int i=0; i<ImageDimension; i++ )
145
if( outputRegionSize[i] != outputRegionForThreadSize[i] )
151
// compute the number of pixels before that threads
152
outputRegionSize[splitAxis] = outputRegionForThreadIdx[splitAxis] - outputRegionIdx[splitAxis];
153
long firstLineIdForThread = RegionType( outputRegionIdx, outputRegionSize ).GetNumberOfPixels() / xsizeForThread;
154
long lineId = firstLineIdForThread;
98
156
OffsetVec LineOffsets;
100
// set the progress reporter to deal with the number of lines
101
long pixelcount = this->GetOutput()->GetRequestedRegion().GetNumberOfPixels();
102
long xsize = this->GetOutput()->GetRequestedRegion().GetSize()[0];
103
long linecount = pixelcount/xsize;
104
ProgressReporter progress(this, 0, linecount * 2);
106
157
SetupLineOffsets(LineOffsets);
108
160
for( inLineIt.GoToBegin();
109
161
!inLineIt.IsAtEnd();
110
inLineIt.NextLine(), ++LineIdx)
162
inLineIt.NextLine() )
112
164
inLineIt.GoToBeginOfLine();
113
165
lineEncoding ThisLine;
116
168
InputPixelType PVal = inLineIt.Get();
117
169
//std::cout << inLineIt.GetIndex() << std::endl;
118
if (PVal != NumericTraits<InputPixelType>::Zero)
170
if (PVal != m_BackgroundValue)
120
172
// We've hit the start of a run
121
173
runLength thisRun;
123
175
IndexType thisIndex;
125
176
thisIndex = inLineIt.GetIndex();
126
177
//std::cout << thisIndex << std::endl;
129
180
while( !inLineIt.IsAtEndOfLine()
130
&& inLineIt.Get() != NumericTraits<InputPixelType>::Zero )
181
&& inLineIt.Get() != m_BackgroundValue )
135
186
// create the run length object to go in the vector
136
187
thisRun.length=length;
188
thisRun.label=0; // will give a real label later
138
189
thisRun.where = thisIndex;
139
190
ThisLine.push_back(thisRun);
146
if (ThisLine.size() != 0)
149
// There are some runs on this line, so insert it into the map.
150
// This conditional insertion "breaks" the full progress report - because
151
// of it, the report will not be 1.0 at the end of the execution if some
152
// lines are empty - but with it, the computation time decrease from
153
// 0.059922 s to 0.0452819 s on the test image
154
// http://voxel.jouy.inra.fr/darcs/contrib-itk/watershed/images/ESCells-markers.tif
156
LineMap[LineIdx] = ThisLine;
198
m_LineMap[lineId] = ThisLine;
158
200
progress.CompletedPixel();
203
m_NumberOfLabels[threadId] = nbOfLabels;
205
// wait for the other threads to complete that part
208
// compute the total number of labels
210
for( int i=0; i<nbOfThreads; i++ )
212
nbOfLabels += m_NumberOfLabels[i];
161
// set up the union find structure
163
// insert all the labels into the structure -- an extra loop but
164
// saves complicating the ones that come later
165
for (long pp = 1; pp <= lab; pp++)
217
// set up the union find structure
218
InitUnion(nbOfLabels);
219
// insert all the labels into the structure -- an extra loop but
220
// saves complicating the ones that come later
221
typename LineMapType::iterator MapBegin, MapEnd, LineIt;
222
MapBegin = m_LineMap.begin();
223
MapEnd = m_LineMap.end();
225
unsigned long label = 1;
226
for (LineIt = MapBegin; LineIt != MapEnd; ++LineIt)
228
typename lineEncoding::iterator cIt;
229
for (cIt = LineIt->begin();cIt != LineIt->end();++cIt)
238
// wait for the other threads to complete that part
169
241
// now process the map and make appropriate entries in an equivalence
173
typename LineMapType::iterator MapBegin, MapEnd, LineIt;
175
MapBegin = LineMap.begin();
176
MapEnd = LineMap.end();
179
//while( LineIt != MapEnd)
180
for (LineIt = MapBegin; LineIt != MapEnd; ++LineIt)
182
//lineEncoding L = LineIt->second;
183
long ThisIdx = LineIt->first;
184
//std::cout << "Line number = " << LineIt->first << std::endl;
185
for (OffsetVec::const_iterator I = LineOffsets.begin();
186
I != LineOffsets.end(); ++I)
188
long NeighIdx = ThisIdx + (*I);
189
// check if the neighbor is in the map
190
typename LineMapType::const_iterator NN = LineMap.find(NeighIdx);
193
// Now check whether they are really neighbors
195
= CheckNeighbors(LineIt->second[0].where, NN->second[0].where);
198
// Compare the two lines
199
CompareLines(LineIt->second, NN->second);
205
unsigned long int totalLabs = CreateConsecutive();
206
m_ObjectCount = totalLabs;
207
// check for overflow exception here
208
if( totalLabs > static_cast<unsigned long int>(
209
NumericTraits<OutputPixelType>::max() ) )
212
<< "Number of objects greater than maximum of output pixel type " );
243
// assert( linecount == m_LineMap.size() );
244
long pixelcount = output->GetRequestedRegion().GetNumberOfPixels();
245
long xsize = output->GetRequestedRegion().GetSize()[0];
246
long linecount = pixelcount/xsize;
248
long lastLineIdForThread = linecount;
249
long nbOfLineIdToJoin = 0;
250
if( threadId != nbOfThreads - 1 )
252
outputRegionForThreadSize = outputRegionForThread.GetSize();
253
outputRegionForThreadSize[splitAxis] -= 1;
254
lastLineIdForThread = firstLineIdForThread + RegionType( outputRegionIdx, outputRegionForThreadSize ).GetNumberOfPixels() / xsizeForThread;
255
m_FirstLineIdToJoin[threadId] = lastLineIdForThread;
256
// found the number of line ids to join
257
nbOfLineIdToJoin = RegionType( outputRegionIdx, outputRegionForThread.GetSize() ).GetNumberOfPixels() / xsizeForThread
258
- RegionType( outputRegionIdx, outputRegionForThreadSize ).GetNumberOfPixels() / xsizeForThread;
261
for(long ThisIdx = firstLineIdForThread; ThisIdx < lastLineIdForThread; ++ThisIdx)
263
if( !m_LineMap[ThisIdx].empty() )
265
for (OffsetVec::const_iterator I = LineOffsets.begin();
266
I != LineOffsets.end(); ++I)
268
long NeighIdx = ThisIdx + (*I);
269
// check if the neighbor is in the map
270
if ( NeighIdx >= 0 && NeighIdx < linecount && !m_LineMap[NeighIdx].empty() )
272
// Now check whether they are really neighbors
274
= CheckNeighbors(m_LineMap[ThisIdx][0].where, m_LineMap[NeighIdx][0].where);
277
// Compare the two lines
278
CompareLines(m_LineMap[ThisIdx], m_LineMap[NeighIdx]);
285
// wait for the other threads to complete that part
288
while( m_FirstLineIdToJoin.size() != 0 )
290
if( threadId * 2 < (int)m_FirstLineIdToJoin.size() )
292
for(long ThisIdx = m_FirstLineIdToJoin[threadId * 2];
293
ThisIdx < m_FirstLineIdToJoin[threadId * 2] + nbOfLineIdToJoin;
296
if( !m_LineMap[ThisIdx].empty() )
298
for (OffsetVec::const_iterator I = LineOffsets.begin();
299
I != LineOffsets.end(); ++I)
301
long NeighIdx = ThisIdx + (*I);
302
// check if the neighbor is in the map
303
if ( NeighIdx >= 0 && NeighIdx < linecount && !m_LineMap[NeighIdx].empty() )
305
// Now check whether they are really neighbors
307
= CheckNeighbors(m_LineMap[ThisIdx][0].where, m_LineMap[NeighIdx][0].where);
310
// Compare the two lines
311
CompareLines(m_LineMap[ThisIdx], m_LineMap[NeighIdx]);
323
// remove the region already joined
324
typename std::vector< long > newFirstLineIdToJoin;
325
for( unsigned int i = 1; i < m_FirstLineIdToJoin.size(); i += 2 )
327
newFirstLineIdToJoin.push_back( m_FirstLineIdToJoin[i] );
329
m_FirstLineIdToJoin = newFirstLineIdToJoin;
338
unsigned long int totalLabs = CreateConsecutive();
339
m_ObjectCount = totalLabs;
340
// check for overflow exception here
341
if( totalLabs > static_cast<unsigned long int>(
342
NumericTraits<OutputPixelType>::max() ) )
345
<< "Number of objects greater than maximum of output pixel type " );
214
351
// create the output
215
352
// A more complex version that is intended to minimize the number of
216
353
// visits to the output image which should improve cache
220
357
// make much difference in practice.
221
358
// Note - this is unnecessary if AllocateOutputs initalizes to zero
223
FillOutput(LineMap, progress);
360
ImageRegionIterator<OutputImageType> oit(output, outputRegionForThread);
361
ImageRegionIterator<OutputImageType> fstart=oit, fend=oit;
365
lastLineIdForThread = firstLineIdForThread + RegionType( outputRegionIdx, outputRegionForThread.GetSize() ).GetNumberOfPixels() / xsizeForThread;
367
for (long ThisIdx = firstLineIdForThread; ThisIdx<lastLineIdForThread; ThisIdx++)
369
// now fill the labelled sections
370
typename lineEncoding::const_iterator cIt;
372
for (cIt = m_LineMap[ThisIdx].begin();cIt != m_LineMap[ThisIdx].end();++cIt)
374
unsigned long Ilab = LookupSet( cIt->label);
375
OutputPixelType lab = m_Consecutive[Ilab];
376
oit.SetIndex(cIt->where);
377
// initialize the non labelled pixels
378
for (; fstart != oit; ++fstart)
380
fstart.Set( m_BackgroundValue );
382
for (long i = 0; i < cIt->length; ++i, ++oit)
389
progress.CompletedPixel();
391
// fill the rest of the image with background value
392
for (; fstart != fend; ++fstart)
394
fstart.Set( m_BackgroundValue );
399
template< class TInputImage, class TOutputImage, class TMaskImage >
401
ConnectedComponentImageFilter< TInputImage, TOutputImage, TMaskImage>
402
::AfterThreadedGenerateData()
404
m_NumberOfLabels.clear();
402
template< class TInputImage, class TOutputImage, class TMaskImage >
404
ConnectedComponentImageFilter< TInputImage, TOutputImage, TMaskImage>
405
::FillOutput(const LineMapType &LineMap,
406
ProgressReporter &progress)
409
typename LineMapType::const_iterator MapBegin, MapEnd, LineIt;
410
typename TOutputImage::Pointer output = this->GetOutput();
411
MapBegin = LineMap.begin();
412
MapEnd = LineMap.end();
415
ImageRegionIterator<OutputImageType> oit(output,
416
output->GetRequestedRegion());
418
ImageRegionIterator<OutputImageType> fstart=oit, fend=oit;
422
for (LineIt = MapBegin; LineIt != MapEnd; ++LineIt)
424
// now fill the labelled sections
425
typename lineEncoding::const_iterator cIt;
427
//std::cout << LineIt->first << std::endl;
429
for (cIt = LineIt->second.begin();cIt != LineIt->second.end();++cIt)
431
unsigned long Ilab = LookupSet( cIt->label);
432
OutputPixelType lab = m_Consecutive[Ilab];
433
oit.SetIndex(cIt->where);
434
// initialize the non labelled pixels
435
for (; fstart != oit; ++fstart)
437
fstart.Set(NumericTraits<OutputPixelType>::Zero );
439
for (long i = 0; i < cIt->length; ++i, ++oit)
446
progress.CompletedPixel();
448
// fill the rest of the image with zeros
449
for (; fstart != fend; ++fstart)
451
fstart.Set(NumericTraits<OutputPixelType>::Zero );
456
585
// union find related functions
457
586
template< class TInputImage, class TOutputImage, class TMaskImage >