21 #ifndef otbComputeHistoFilter_hxx
22 #define otbComputeHistoFilter_hxx
31 template <
class TInputImage,
class TOutputImage>
34 this->SetNumberOfRequiredOutputs(2);
35 this->SetNthOutput(0, this->MakeOutput(0));
36 this->SetNthOutput(1, this->MakeOutput(1));
37 m_Min = std::numeric_limits<InputPixelType>::quiet_NaN();
38 m_Max = std::numeric_limits<InputPixelType>::quiet_NaN();
40 m_NoData = std::numeric_limits<InputPixelType>::quiet_NaN();
48 template <
class TInputImage,
class TOutputImage>
51 itk::DataObject::Pointer output;
56 output = (OutputImageType::New()).GetPointer();
59 output = (OutputImageType::New()).GetPointer();
62 std::cerr <<
"No output " << idx << std::endl;
69 template <
class TInputImage,
class TOutputImage>
72 return Superclass::MakeOutput(name);
75 template <
class TInputImage,
class TOutputImage>
78 typename Superclass::InputImagePointer inputPtr(
const_cast<InputImageType*
>(this->GetInput()));
79 inputPtr->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());
80 if (inputPtr->GetRequestedRegion().GetNumberOfPixels() == 0)
82 inputPtr->SetRequestedRegionToLargestPossibleRegion();
86 template <
class TInputImage,
class TOutputImage>
89 Superclass::GenerateOutputInformation();
90 typename InputImageType::ConstPointer input(this->GetInput());
91 typename OutputImageType::Pointer output(this->GetHistoOutput());
92 typename OutputImageType::Pointer outImage(this->GetOutput());
94 typename InputImageType::RegionType inputLargestRegion(input->GetLargestPossibleRegion());
95 outImage->SetLargestPossibleRegion(inputLargestRegion);
97 typename OutputImageType::IndexType start;
98 typename OutputImageType::SizeType size;
102 assert(m_ThumbSize[0] != 0);
103 assert(m_ThumbSize[1] != 0);
107 size[0] = std::ceil(inputLargestRegion.GetSize()[0] /
static_cast<double>(m_ThumbSize[0]));
108 size[1] = std::ceil(inputLargestRegion.GetSize()[1] /
static_cast<double>(m_ThumbSize[1]));
110 typename OutputImageType::RegionType region;
111 region.SetSize(size);
112 region.SetIndex(start);
113 output->SetNumberOfComponentsPerPixel(m_NbBin);
114 output->SetLargestPossibleRegion(region);
115 typename InputImageType::SpacingType inputSpacing(input->GetSignedSpacing());
116 typename InputImageType::PointType inputOrigin(input->GetOrigin());
118 typename OutputImageType::SpacingType histoSpacing;
119 histoSpacing[0] = inputSpacing[0] * m_ThumbSize[0];
120 histoSpacing[1] = inputSpacing[1] * m_ThumbSize[1];
121 output->SetSignedSpacing(histoSpacing);
123 typename OutputImageType::PointType histoOrigin;
124 histoOrigin[0] = histoSpacing[0] / 2 + inputOrigin[0] - inputSpacing[0] / 2;
125 histoOrigin[1] = histoSpacing[1] / 2 + inputOrigin[1] - inputSpacing[1] / 2;
126 output->SetOrigin(histoOrigin);
129 template <
class TInputImage,
class TOutputImage>
132 if (GetHistoOutput()->GetRequestedRegion().GetNumberOfPixels() == 0)
134 GetHistoOutput()->SetRequestedRegionToLargestPossibleRegion();
136 typename OutputImageType::Pointer outImage(this->GetOutput());
137 SetRequestedRegion(outImage);
140 template <
class TInputImage,
class TOutputImage>
143 this->AllocateOutputs();
146 typename itk::ImageSource<OutputImageType>::ThreadStruct str;
151 const itk::ImageRegionSplitterBase* splitter(this->GetImageRegionSplitter());
152 m_ValidThreads = splitter->GetNumberOfSplits(outputPtr->GetRequestedRegion(), this->GetNumberOfThreads());
154 this->BeforeThreadedGenerateData();
156 this->GetMultiThreader()->SetNumberOfThreads(m_ValidThreads);
157 this->GetMultiThreader()->SetSingleMethod(this->ThreaderCallback, &str);
159 this->GetMultiThreader()->SingleMethodExecute();
161 this->AfterThreadedGenerateData();
164 template <
class TInputImage,
class TOutputImage>
168 typename OutputImageType::Pointer output(this->GetHistoOutput());
169 typename OutputImageType::PixelType zeroPixel(m_NbBin);
171 output->FillBuffer(zeroPixel);
174 SizeType outSize(output->GetRequestedRegion().GetSize());
175 m_HistoThread.resize(m_ValidThreads * outSize[0] * outSize[1]);
176 m_HistoThread.shrink_to_fit();
177 std::fill(m_HistoThread.begin(), m_HistoThread.end(), zeroPixel);
179 m_Step =
static_cast<double>(m_Max - m_Min) /
static_cast<double>(m_NbBin - 1);
182 template <
class TInputImage,
class TOutputImage>
190 typename InputImageType::ConstPointer input(this->GetInput());
191 typename OutputImageType::Pointer output(this->GetHistoOutput());
194 SizeType outSize(histoRegion.GetSize());
195 IndexType outIndex(histoRegion.GetIndex());
197 typename InputImageType::RegionType region;
199 unsigned int threadIndex(threadId * outSize[0] * outSize[1]), pixel(0);
201 for (
unsigned int nthHisto = 0; nthHisto < outSize[0] * outSize[1]; nthHisto++)
204 start[0] = (outIndex[0] + nthHisto % outSize[0]) * m_ThumbSize[0];
205 start[1] = (outIndex[1] + nthHisto / outSize[0]) * m_ThumbSize[1];
206 region.SetSize(m_ThumbSize);
207 region.SetIndex(start);
209 if (!region.Crop(outputRegionForThread))
212 typename itk::ImageRegionConstIterator<InputImageType> it(input, region);
214 for (it.GoToBegin(); !it.IsAtEnd(); ++it)
216 currentPixel = it.Get();
217 if ((currentPixel == m_NoData && m_NoDataFlag) || currentPixel > m_Max || currentPixel < m_Min)
220 pixel =
static_cast<unsigned int>(std::round((currentPixel - m_Min) / m_Step));
221 ++m_HistoThread[threadIndex + nthHisto][pixel];
226 template <
class TInputImage,
class TOutputImage>
229 typename OutputImageType::Pointer output(this->GetHistoOutput());
230 typename itk::ImageRegionIterator<OutputImageType> oit(output, output->GetRequestedRegion());
232 SizeType outSize(histoRegion.GetSize());
233 IndexType outIndex(histoRegion.GetIndex());
235 unsigned int agreg(0), total(0);
237 for (oit.GoToBegin(); !oit.IsAtEnd(); ++oit)
241 for (
unsigned int i = 0; i < m_NbBin; i++)
245 for (
unsigned int threadId = 0; threadId < m_ValidThreads; threadId++)
247 agreg += m_HistoThread[threadId * outSize[0] * outSize[1] + (oit.GetIndex()[1] - outIndex[1]) * outSize[0] + ((oit.GetIndex()[0] - outIndex[0]))][i];
249 oit.Get()[i] = agreg;
253 ApplyThreshold(oit, total);
257 template <
class TInputImage,
class TOutputImage>
260 unsigned int rest(0);
261 unsigned int height(
static_cast<unsigned int>(m_Threshold * (total / m_NbBin)));
265 for (
unsigned int i = 0; i < m_NbBin; i++)
267 if (
static_cast<unsigned int>(oit.Get()[i]) > height)
269 rest += oit.Get()[i] - height;
270 oit.Get()[i] = height;
273 height = rest / m_NbBin;
274 rest = rest % m_NbBin;
275 for (
unsigned int i = 0; i < m_NbBin; i++)
277 oit.Get()[i] += height;
278 if (i > (m_NbBin - rest) / 2 && i <= (m_NbBin - rest) / 2 + rest)
285 template <
class TInputImage,
class TOutputImage>
288 assert(this->itk::ProcessObject::GetOutput(1));
290 return dynamic_cast<TOutputImage*
>(this->itk::ProcessObject::GetOutput(1));
293 template <
class TInputImage,
class TOutputImage>
299 start[0] = histoRegion.GetIndex()[0] * m_ThumbSize[0];
300 start[1] = histoRegion.GetIndex()[1] * m_ThumbSize[1];
303 size[0] = histoRegion.GetSize()[0] * m_ThumbSize[0];
304 size[1] = histoRegion.GetSize()[1] * m_ThumbSize[1];
306 typename OutputImageType::RegionType outputRequestedRegion;
307 outputRequestedRegion.SetIndex(start);
308 outputRequestedRegion.SetSize(size);
310 outputRequestedRegion.Crop(image->GetLargestPossibleRegion());
311 image->SetRequestedRegion(outputRequestedRegion);
314 template <
class TInputImage,
class TOutputImage>
317 Superclass::PrintSelf(os, indent);
318 os << indent <<
"Is no data activated: " << m_NoDataFlag << std::endl;
319 os << indent <<
"No Data: " << m_NoData << std::endl;
320 os << indent <<
"Minimum: " << m_Min << std::endl;
321 os << indent <<
"Maximum: " << m_Max << std::endl;
322 os << indent <<
"Step: " << m_Step << std::endl;
323 os << indent <<
"Number of bin: " << m_NbBin << std::endl;
324 os << indent <<
"Thumbnail size: " << m_ThumbSize << std::endl;
325 os << indent <<
"Threshold value: " << m_Threshold << std::endl;