21 #ifndef otbComputeHistoFilter_hxx
22 #define otbComputeHistoFilter_hxx
31 template <
class TInputImage,
class TOutputImage>
34 this->DynamicMultiThreadingOff();
35 this->SetNumberOfRequiredOutputs(2);
36 this->SetNthOutput(0, this->MakeOutput(0));
37 this->SetNthOutput(1, this->MakeOutput(1));
38 m_Min = std::numeric_limits<InputPixelType>::quiet_NaN();
39 m_Max = std::numeric_limits<InputPixelType>::quiet_NaN();
41 m_NoData = std::numeric_limits<InputPixelType>::quiet_NaN();
49 template <
class TInputImage,
class TOutputImage>
52 itk::DataObject::Pointer output;
57 output = (OutputImageType::New()).GetPointer();
60 output = (OutputImageType::New()).GetPointer();
63 std::cerr <<
"No output " << idx << std::endl;
70 template <
class TInputImage,
class TOutputImage>
73 return Superclass::MakeOutput(name);
76 template <
class TInputImage,
class TOutputImage>
79 typename Superclass::InputImagePointer inputPtr(
const_cast<InputImageType*
>(this->GetInput()));
80 inputPtr->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());
81 if (inputPtr->GetRequestedRegion().GetNumberOfPixels() == 0)
83 inputPtr->SetRequestedRegionToLargestPossibleRegion();
87 template <
class TInputImage,
class TOutputImage>
90 Superclass::GenerateOutputInformation();
91 typename InputImageType::ConstPointer input(this->GetInput());
92 typename OutputImageType::Pointer output(this->GetHistoOutput());
93 typename OutputImageType::Pointer outImage(this->GetOutput());
95 typename InputImageType::RegionType inputLargestRegion(input->GetLargestPossibleRegion());
96 outImage->SetLargestPossibleRegion(inputLargestRegion);
98 typename OutputImageType::IndexType start;
99 typename OutputImageType::SizeType size;
103 assert(m_ThumbSize[0] != 0);
104 assert(m_ThumbSize[1] != 0);
108 size[0] = std::ceil(inputLargestRegion.GetSize()[0] /
static_cast<double>(m_ThumbSize[0]));
109 size[1] = std::ceil(inputLargestRegion.GetSize()[1] /
static_cast<double>(m_ThumbSize[1]));
111 typename OutputImageType::RegionType region;
112 region.SetSize(size);
113 region.SetIndex(start);
114 output->SetNumberOfComponentsPerPixel(m_NbBin);
115 output->SetLargestPossibleRegion(region);
116 typename InputImageType::SpacingType inputSpacing(input->GetSignedSpacing());
117 typename InputImageType::PointType inputOrigin(input->GetOrigin());
119 typename OutputImageType::SpacingType histoSpacing;
120 histoSpacing[0] = inputSpacing[0] * m_ThumbSize[0];
121 histoSpacing[1] = inputSpacing[1] * m_ThumbSize[1];
122 output->SetSignedSpacing(histoSpacing);
124 typename OutputImageType::PointType histoOrigin;
125 histoOrigin[0] = histoSpacing[0] / 2 + inputOrigin[0] - inputSpacing[0] / 2;
126 histoOrigin[1] = histoSpacing[1] / 2 + inputOrigin[1] - inputSpacing[1] / 2;
127 output->SetOrigin(histoOrigin);
130 template <
class TInputImage,
class TOutputImage>
133 if (GetHistoOutput()->GetRequestedRegion().GetNumberOfPixels() == 0)
135 GetHistoOutput()->SetRequestedRegionToLargestPossibleRegion();
137 typename OutputImageType::Pointer outImage(this->GetOutput());
138 SetRequestedRegion(outImage);
141 template <
class TInputImage,
class TOutputImage>
144 this->AllocateOutputs();
147 typename itk::ImageSource<OutputImageType>::ThreadStruct str;
152 const itk::ImageRegionSplitterBase* splitter(this->GetImageRegionSplitter());
153 m_ValidThreads = splitter->GetNumberOfSplits(outputPtr->GetRequestedRegion(), this->GetNumberOfWorkUnits());
155 this->BeforeThreadedGenerateData();
157 this->GetMultiThreader()->SetNumberOfWorkUnits(m_ValidThreads);
158 this->GetMultiThreader()->SetSingleMethod(this->ThreaderCallback, &str);
160 this->GetMultiThreader()->SingleMethodExecute();
162 this->AfterThreadedGenerateData();
165 template <
class TInputImage,
class TOutputImage>
169 typename OutputImageType::Pointer output(this->GetHistoOutput());
170 typename OutputImageType::PixelType zeroPixel(m_NbBin);
172 output->FillBuffer(zeroPixel);
175 SizeType outSize(output->GetRequestedRegion().GetSize());
176 m_HistoThread.resize(m_ValidThreads * outSize[0] * outSize[1]);
177 m_HistoThread.shrink_to_fit();
178 std::fill(m_HistoThread.begin(), m_HistoThread.end(), zeroPixel);
180 m_Step =
static_cast<double>(m_Max - m_Min) /
static_cast<double>(m_NbBin - 1);
183 template <
class TInputImage,
class TOutputImage>
187 typename InputImageType::ConstPointer input(this->GetInput());
188 typename OutputImageType::Pointer output(this->GetHistoOutput());
191 SizeType outSize(histoRegion.GetSize());
192 IndexType outIndex(histoRegion.GetIndex());
194 typename InputImageType::RegionType region;
196 unsigned int threadIndex(threadId * outSize[0] * outSize[1]), pixel(0);
198 for (
unsigned int nthHisto = 0; nthHisto < outSize[0] * outSize[1]; nthHisto++)
201 start[0] = (outIndex[0] + nthHisto % outSize[0]) * m_ThumbSize[0];
202 start[1] = (outIndex[1] + nthHisto / outSize[0]) * m_ThumbSize[1];
203 region.SetSize(m_ThumbSize);
204 region.SetIndex(start);
206 if (!region.Crop(outputRegionForThread))
209 typename itk::ImageRegionConstIterator<InputImageType> it(input, region);
211 for (it.GoToBegin(); !it.IsAtEnd(); ++it)
213 currentPixel = it.Get();
214 if ((currentPixel == m_NoData && m_NoDataFlag) || currentPixel > m_Max || currentPixel < m_Min)
217 pixel =
static_cast<unsigned int>(std::round((currentPixel - m_Min) / m_Step));
218 ++m_HistoThread[threadIndex + nthHisto][pixel];
223 template <
class TInputImage,
class TOutputImage>
226 typename OutputImageType::Pointer output(this->GetHistoOutput());
227 typename itk::ImageRegionIterator<OutputImageType> oit(output, output->GetRequestedRegion());
229 SizeType outSize(histoRegion.GetSize());
230 IndexType outIndex(histoRegion.GetIndex());
232 unsigned int agreg(0), total(0);
234 for (oit.GoToBegin(); !oit.IsAtEnd(); ++oit)
238 for (
unsigned int i = 0; i < m_NbBin; i++)
242 for (
unsigned int threadId = 0; threadId < m_ValidThreads; threadId++)
244 agreg += m_HistoThread[threadId * outSize[0] * outSize[1] + (oit.GetIndex()[1] - outIndex[1]) * outSize[0] + ((oit.GetIndex()[0] - outIndex[0]))][i];
246 oit.Get()[i] = agreg;
250 ApplyThreshold(oit, total);
254 template <
class TInputImage,
class TOutputImage>
257 unsigned int rest(0);
258 unsigned int height(
static_cast<unsigned int>(m_Threshold * (total / m_NbBin)));
262 for (
unsigned int i = 0; i < m_NbBin; i++)
264 if (
static_cast<unsigned int>(oit.Get()[i]) > height)
266 rest += oit.Get()[i] - height;
267 oit.Get()[i] = height;
270 height = rest / m_NbBin;
271 rest = rest % m_NbBin;
272 for (
unsigned int i = 0; i < m_NbBin; i++)
274 oit.Get()[i] += height;
275 if (i > (m_NbBin - rest) / 2 && i <= (m_NbBin - rest) / 2 + rest)
282 template <
class TInputImage,
class TOutputImage>
285 assert(this->itk::ProcessObject::GetOutput(1));
287 return dynamic_cast<TOutputImage*
>(this->itk::ProcessObject::GetOutput(1));
290 template <
class TInputImage,
class TOutputImage>
296 start[0] = histoRegion.GetIndex()[0] * m_ThumbSize[0];
297 start[1] = histoRegion.GetIndex()[1] * m_ThumbSize[1];
300 size[0] = histoRegion.GetSize()[0] * m_ThumbSize[0];
301 size[1] = histoRegion.GetSize()[1] * m_ThumbSize[1];
303 typename OutputImageType::RegionType outputRequestedRegion;
304 outputRequestedRegion.SetIndex(start);
305 outputRequestedRegion.SetSize(size);
307 outputRequestedRegion.Crop(image->GetLargestPossibleRegion());
308 image->SetRequestedRegion(outputRequestedRegion);
311 template <
class TInputImage,
class TOutputImage>
314 Superclass::PrintSelf(os, indent);
315 os << indent <<
"Is no data activated: " << m_NoDataFlag << std::endl;
316 os << indent <<
"No Data: " << m_NoData << std::endl;
317 os << indent <<
"Minimum: " << m_Min << std::endl;
318 os << indent <<
"Maximum: " << m_Max << std::endl;
319 os << indent <<
"Step: " << m_Step << std::endl;
320 os << indent <<
"Number of bin: " << m_NbBin << std::endl;
321 os << indent <<
"Thumbnail size: " << m_ThumbSize << std::endl;
322 os << indent <<
"Threshold value: " << m_Threshold << std::endl;
void AfterThreadedGenerateData() override
void GenerateOutputInformation() override
virtual void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, itk::ThreadIdType threadId) override
void GenerateData() override
void BeforeThreadedGenerateData() override
virtual itk::ProcessObject::DataObjectPointer MakeOutput(itk::ProcessObject::DataObjectPointerArraySizeType idx) override
OutputImageType::Pointer GetHistoOutput()
InputImageType::InternalPixelType InputPixelType
void PrintSelf(std::ostream &os, itk::Indent indent) const override
void SetRequestedRegion(itk::ImageBase< 2 > *image)
void GenerateInputRequestedRegion() override
InputImageType::IndexType IndexType
InputImageType::SizeType SizeType
TOutputImage OutputImageType
void ApplyThreshold(typename itk::ImageRegionIterator< OutputImageType > oit, unsigned int total)
void GenerateOutputRequestedRegion(itk::DataObject *output) override
OutputImageType::RegionType OutputImageRegionType
TInputImage InputImageType
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.