21 #ifndef otbLineDetectorImageFilterBase_hxx
22 #define otbLineDetectorImageFilterBase_hxx
26 #include "itkDataObject.h"
28 #include "itkConstantPadImageFilter.h"
29 #include "itkConstNeighborhoodIterator.h"
30 #include "itkNeighborhoodInnerProduct.h"
31 #include "itkImageRegionIterator.h"
32 #include "itkNeighborhoodAlgorithm.h"
33 #include "itkProgressReporter.h"
43 template <
class TInputImage,
class TOutputImage,
class TOutputImageDirection,
class InterpolatorType>
46 this->SetNumberOfRequiredOutputs(2);
47 this->SetNumberOfRequiredOutputs(1);
52 m_NumberOfDirections = 4;
60 template <
class TInputImage,
class TOutputImage,
class TOutputImageDirection,
class InterpolatorType>
64 Superclass::GenerateInputRequestedRegion();
70 if (!inputPtr || !outputPtr)
77 typename TInputImage::RegionType inputRequestedRegion;
78 inputRequestedRegion = inputPtr->GetRequestedRegion();
81 m_Radius[1] =
static_cast<unsigned int>(3 * (2 * m_WidthLine + 1) + 2);
82 m_Radius[0] = 2 * m_LengthLine + 1;
85 m_FaceList[0] =
static_cast<unsigned int>(std::sqrt(
static_cast<double>((m_Radius[0] * m_Radius[0]) + (m_Radius[1] * m_Radius[1]))) + 1);
86 m_FaceList[1] = m_FaceList[0];
88 otbMsgDevMacro(<<
"Radius : " << m_Radius[0] <<
" " << m_Radius[1]);
89 otbMsgDevMacro(<<
"-> FaceList : " << m_FaceList[0] <<
" " << m_FaceList[1]);
92 inputRequestedRegion.PadByRadius(m_FaceList);
95 if (inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()))
97 inputPtr->SetRequestedRegion(inputRequestedRegion);
106 inputPtr->SetRequestedRegion(inputRequestedRegion);
109 itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
110 std::ostringstream msg;
111 msg << static_cast<const char*>(this->GetNameOfClass()) <<
"::GenerateInputRequestedRegion()";
112 e.SetLocation(msg.str());
113 e.SetDescription(
"Requested region is (at least partially) outside the largest possible region.");
114 e.SetDataObject(inputPtr);
124 template <
class TInputImage,
class TOutputImage,
class TOutputImageDirection,
class InterpolatorType>
127 typename OutputImageType::Pointer output = this->GetOutput();
128 output->FillBuffer(0);
129 typename OutputImageType::Pointer outputDirection = this->GetOutputDirection();
130 outputDirection->FillBuffer(0);
133 template <
class TInputImage,
class TOutputImage,
class TOutputImageDirection,
class InterpolatorType>
138 typename InputImageType::ConstPointer input = this->GetInput();
141 interpolator2->SetInputImage(input);
143 itk::ZeroFluxNeumannBoundaryCondition<InputImageType> nbc;
144 itk::ConstNeighborhoodIterator<InputImageType> bit, cit;
145 typename itk::ConstNeighborhoodIterator<InputImageType>::OffsetType off;
146 itk::ImageRegionIterator<OutputImageType> it;
147 itk::ImageRegionIterator<OutputImageType> itdir;
150 typename OutputImageType::Pointer output = this->GetOutput();
151 typename OutputImageType::Pointer outputDir = this->GetOutputDirection();
154 typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType>::FaceListType faceList;
155 typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType>::FaceListType::iterator fit;
157 itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType> bC;
158 faceList = bC(input, outputRegionForThread, m_FaceList);
161 typename TInputImage::IndexType bitIndex;
162 typename InterpolatorType::ContinuousIndexType Index;
167 const unsigned int NB_DIR = this->GetNumberOfDirections();
169 const int NB_ZONE = 3;
173 double* Theta =
new double[NB_DIR];
176 for (
unsigned int i = 0; i < NB_DIR; ++i)
178 Theta[i] = (
CONST_PI * (i / double(NB_DIR)));
192 double Direction = 0.;
207 otbMsgDevMacro(<<
"Theta : " << Theta[0] <<
" " << Theta[1] <<
" " << Theta[2] <<
" " << Theta[3]);
214 for (fit = faceList.begin(); fit != faceList.end(); ++fit)
216 bit = itk::ConstNeighborhoodIterator<InputImageType>(m_Radius, input, *fit);
217 cit = itk::ConstNeighborhoodIterator<InputImageType>(m_FaceList, input, *fit);
219 it = itk::ImageRegionIterator<OutputImageType>(output, *fit);
220 itdir = itk::ImageRegionIterator<OutputImageType>(outputDir, *fit);
222 bit.OverrideBoundaryCondition(&nbc);
224 cit.OverrideBoundaryCondition(&nbc);
227 otbMsgDevMacro(<<
" ------------------- FaceList --------------------------");
229 while ((!bit.IsAtEnd()) && (!cit.IsAtEnd()))
231 InterpolatorPointer interpolator = InterpolatorType::New();
234 bitIndex = bit.GetIndex(off);
248 typename InputImageType::RegionType tempRegion;
249 typename InputImageType::SizeType tempSize;
250 tempSize[0] = 2 * m_FaceList[0] + 1;
251 tempSize[1] = 2 * m_FaceList[1] + 1;
252 tempRegion.SetSize(tempSize);
253 typename itk::ConstNeighborhoodIterator<InputImageType>::OffsetType tempIndex;
254 tempIndex[0] = off[0] - m_FaceList[0];
255 tempIndex[1] = off[1] - m_FaceList[1];
256 tempRegion.SetIndex(cit.GetIndex(tempIndex));
257 typename InputImageType::Pointer tempImage = InputImageType::New();
258 tempImage->SetRegions(tempRegion);
259 tempImage->Allocate();
261 for (
unsigned int p = 0; p <= 2 * m_FaceList[0]; ++p)
263 for (
unsigned int q = 0; q <= 2 * m_FaceList[1]; q++)
265 typename itk::ConstNeighborhoodIterator<InputImageType>::OffsetType index;
266 index[0] = p - m_FaceList[0];
267 index[1] = q - m_FaceList[1];
268 tempImage->SetPixel(cit.GetIndex(index), cit.GetPixel(index));
271 interpolator->SetInputImage(tempImage);
275 Yc12 = Yc - m_WidthLine - 1;
278 Yc13 = Yc + m_WidthLine + 1;
283 std::vector<double>** PixelValues =
nullptr;
284 PixelValues =
new std::vector<double>*[NB_DIR];
285 for (
unsigned int i = 0; i < NB_DIR; ++i)
287 PixelValues[i] =
nullptr;
288 PixelValues[i] =
new std::vector<double>[NB_ZONE];
292 for (
unsigned int i = 0; i < m_Radius[0]; ++i)
293 for (
unsigned int j = 0; j < m_Radius[1]; ++j)
296 off[0] = i - m_Radius[0] / 2;
297 off[1] = j - m_Radius[1] / 2;
299 bitIndex = bit.GetIndex(off);
306 else if ((Yc12 < Y) && (Y < Yc13))
314 for (
unsigned int dir = 0; dir < NB_DIR; ++dir)
318 xout = (X - Xc) * std::cos(Theta[dir]) - (Y - Yc) * std::sin(Theta[dir]);
319 yout = (X - Xc) * std::sin(Theta[dir]) + (Y - Yc) * std::cos(Theta[dir]);
321 Index[0] =
static_cast<CoordRepType
>(xout + Xc);
322 Index[1] =
static_cast<CoordRepType
>(yout + Yc);
324 PixelValues[dir][zone].push_back(
static_cast<double>(interpolator->EvaluateAtContinuousIndex(Index)));
333 for (
unsigned int dir = 0; dir < NB_DIR; ++dir)
336 double Rtemp = this->ComputeMeasure(&PixelValues[dir][0], &PixelValues[dir][1], &PixelValues[dir][2]);
341 Direction = Theta[dir];
347 if (R >= this->GetThreshold())
351 it.Set(
static_cast<OutputPixelType
>(R));
354 itdir.Set(
static_cast<OutputPixelType
>(Direction));
359 it.Set(itk::NumericTraits<OutputPixelType>::Zero);
361 itdir.Set(
static_cast<OutputPixelType
>(0));
369 for (
unsigned int i = 0; i < NB_DIR; ++i)
371 delete[] PixelValues[i];
372 PixelValues[i] =
nullptr;
374 delete[] PixelValues;
375 PixelValues =
nullptr;
381 template <
class TInputImage,
class TOutputImage,
class TOutputImageDirection,
class InterpolatorType>
383 std::vector<double>* itkNotUsed(m2),
384 std::vector<double>* itkNotUsed(m3))
392 template <
class TInputImage,
class TOutputImage,
class TOutputImageDirection,
class InterpolatorType>
395 Superclass::PrintSelf(os, indent);
396 os << indent <<
"Length: " << m_LengthLine << std::endl;
397 os << indent <<
"Width: " << m_WidthLine << std::endl;
OutputImageType::Pointer OutputImagePointer
OutputImageType::RegionType OutputImageRegionType
InputImageType::Pointer InputImagePointer
void BeforeThreadedGenerateData() override
void GenerateInputRequestedRegion() override
virtual double ComputeMeasure(std::vector< double > *m1, std::vector< double > *m2, std::vector< double > *m3)
void PrintSelf(std::ostream &os, itk::Indent indent) const override
void DynamicThreadedGenerateData(const OutputImageRegionType &outputRegionForThread) override
LineDetectorImageFilterBase()
InterpolatorType::Pointer InterpolatorPointer
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
constexpr double CONST_PI
#define otbMsgDevMacro(x)