/* * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) * * This file is part of Orfeo Toolbox * * https://www.orfeo-toolbox.org/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef otbLineSegmentDetector_h #define otbLineSegmentDetector_h #include "otbImage.h" #include "otbVectorDataSource.h" #include "otbVectorData.h" #include "itkUnaryFunctorImageFilter.h" #include "itkGradientRecursiveGaussianImageFilter.h" #include "itkGradientImageFilter.h" namespace otb { namespace Functor { /** \class MagnitudeFunctor * \brief This functor computes the magnitude of a covariant vector. * * \ingroup OTBEdge */ template class MagnitudeFunctor { public: inline TOutputPixel operator()(const TInputPixel& input) { return static_cast(2 * std::sqrt(input[0] * input[0] + input[1] * input[1])); } }; /** \class OrientationFunctor * \brief This functor computes the orientation of a covariant vector
* Orientation values lies between -Pi and Pi. * * \ingroup OTBEdge */ template class OrientationFunctor { public: inline TOutputPixel operator()(const TInputPixel& input) { return static_cast(std::atan2(input[0], -input[1])); } }; } // end namespace Functor /** \class LineSegmentDetector * \brief this class implement a fast line detector with false detection control using * the a contrario method * * The implementation is based on the online version of the lsd * documentation and code lsd 1.5. The OTB version use a 3x3 filter * to compute the gradient(vs. 2x2 in the original implementation) * and implements the density control, the NOTINIT status and the * incremental rectangle optimisation. * * \sa StreamingLineSegmentDetector (streamed version) * \ingroup FeatureExtraction * * See Publication : * " LSD: A line segment detector ", R. Grompone, J.Jackubowicz, J-M.Morel, G.Randall * And Website : * http://www.ipol.im/pub/algo/gjmr_line_segment_detector/ * * * \ingroup OTBEdge */ template class ITK_EXPORT LineSegmentDetector : public VectorDataSource> { public: /** typedef for the classes standards. */ typedef LineSegmentDetector Self; typedef VectorDataSource> Superclass; typedef itk::SmartPointer Pointer; typedef itk::SmartPointer ConstPointer; /** Method for management of the object factory. */ itkNewMacro(Self); /** Return the name of the class. */ itkTypeMacro(LineSegmentDetector, VectorDataSource); /** Definition of the input image */ typedef TInputImage InputImageType; typedef typename InputImageType::PixelType InputPixelType; typedef typename InputImageType::IndexType InputIndexType; typedef typename InputImageType::SizeType SizeType; typedef typename InputImageType::RegionType RegionType; typedef typename InputImageType::SpacingType SpacingType; typedef typename InputImageType::PointType OriginType; /** Definition of the output vector data. */ typedef VectorData VectorDataType; typedef typename VectorDataType::DataNodeType DataNodeType; typedef typename VectorDataType::LineType LineType; typedef typename VectorDataType::PointType PointType; typedef typename LineType::VertexType VertexType; /** Definition of temporary image ised to store LABELS*/ typedef Image OutputImageType; typedef typename OutputImageType::PixelType OutputPixelType; typedef typename OutputImageType::IndexType OutputIndexType; typedef typename OutputImageType::SizeType OutputSizeType; /** Histogram to store the coordinate of ordered pixels*/ typedef std::vector IndexVectorType; typedef typename IndexVectorType::iterator IndexVectorIteratorType; typedef std::vector CoordinateHistogramType; typedef typename CoordinateHistogramType::iterator CoordinateHistogramIteratorType; /** typedef structure to store REGION*/ typedef std::vector VectorOfIndexVectorType; typedef std::vector DirectionVectorType; typedef typename DirectionVectorType::iterator DirectionVectorIteratorType; /** */ typedef itk::GradientRecursiveGaussianImageFilter GradientFilterType; typedef typename GradientFilterType::Pointer GradientFilterPointerType; typedef typename GradientFilterType::OutputImageType GradientOutputImageType; typedef itk::UnaryFunctorImageFilter> MagnitudeFilterType; typedef typename MagnitudeFilterType::Pointer MagnitudeFilterPointerType; typedef typename MagnitudeFilterType::OutputImageType::PixelType MagnitudePixelType; typedef typename MagnitudeFilterType::OutputImageType MagnitudeImageType; typedef typename MagnitudeImageType::Pointer MagnitudeImagePointerType; typedef itk::UnaryFunctorImageFilter> OrientationFilterType; typedef typename OrientationFilterType::Pointer OrientationFilterPointerType; typedef typename OrientationFilterType::OutputImageType OutputImageDirType; typedef typename OutputImageDirType::RegionType OutputImageDirRegionType; /** Create an image to store the label USED(255), NOTINI(127) or NOTUSED (0)*/ typedef otb::Image LabelImageType; typedef typename LabelImageType::Pointer LabelImagePointerType; /** Vector to store the rectangle characteization center, width, orientation , ( begin , end ) of the central line*/ typedef std::vector RectangleType; typedef typename RectangleType::iterator RectangleIteratorType; typedef std::vector RectangleListType; typedef typename RectangleListType::iterator RectangleListTypeIterator; /** Set/Get the input image of this process object. */ using Superclass::SetInput; virtual void SetInput(const InputImageType* input); virtual const InputImageType* GetInput(void); /** Custom Get methods to access intermediate data*/ LabelImagePointerType GetMap() { return m_UsedPointImage; } MagnitudeImagePointerType GetGradMod() { return m_MagnitudeFilter->GetOutput(); } typename OutputImageDirType::Pointer GetGradOri() { return m_OrientationFilter->GetOutput(); } protected: LineSegmentDetector(); ~LineSegmentDetector() override { } void GenerateInputRequestedRegion() override; /** Generate Data method*/ void GenerateData() override; /** Sort the image and store the coordinates in a histogram * this method is used to determine the seeds where to begin the search segments * Points with large gradient modulus are more able to belong to a segment */ virtual CoordinateHistogramType SortImageByModulusValue(MagnitudeImagePointerType modulusImage); /** */ virtual void LineSegmentDetection(CoordinateHistogramType& CoordinateHistogram); /** Return true if the pixel status is NOTUSED*/ virtual bool IsNotUsed(InputIndexType& index) const; /** Return true if the pixel status is USED*/ virtual bool IsUsed(InputIndexType& index) const; /** Return true if the pixel status is NOTINI*/ virtual bool IsNotIni(InputIndexType& index) const; /** Set Pixel flag to USED*/ virtual void SetPixelToUsed(InputIndexType index); /** Set Pixel flag to NOTINI*/ virtual void SetPixelToNotIni(InputIndexType index); /** Set Pixels flag to NOTINI*/ virtual void SetRegionToNotIni(IndexVectorType region); /** search for a segment which begins from a seed "index "*/ virtual bool GrowRegion(InputIndexType index, IndexVectorType& region, double& regionAngle); /** Define if two are aligned */ virtual bool IsAligned(double Angle, double regionAngle, double prec) const; /** For each region of the region List it builds a rectangle */ virtual int ComputeRectangles(); /** */ virtual RectangleType Region2Rectangle(IndexVectorType region, double regionAngle); /** */ virtual double ComputeRegionOrientation(IndexVectorType region, double x, double y, double angleRegion) const; /** */ virtual double angle_diff(double a, double b) const; /** Compute the Number Of False Alarm for a rectangle*/ virtual double ComputeRectNFA(const RectangleType& rec) const; /** */ virtual double ImproveRectangle(RectangleType& rectangle) const; /** NFA For a rectangle*/ virtual double NFA(int n, int k, double p, double logNT) const; /** Create a copy of a rectangle*/ virtual void CopyRectangle(RectangleType& rDst, RectangleType& rSrc) const; /** Printself method*/ void PrintSelf(std::ostream& os, itk::Indent indent) const override; private: LineSegmentDetector(const Self&) = delete; void operator=(const Self&) = delete; VectorOfIndexVectorType m_RegionList; DirectionVectorType m_DirectionVector; LabelImagePointerType m_UsedPointImage; RectangleListType m_RectangleList; double m_Threshold; double m_Prec; double m_DirectionsAllowed; unsigned int m_MinimumRegionSize; /** Gradient filter */ GradientFilterPointerType m_GradientFilter; /** Magnitude filter */ MagnitudeFilterPointerType m_MagnitudeFilter; /** Orientation filter */ OrientationFilterPointerType m_OrientationFilter; }; } // end namespace otb #ifndef OTB_MANUAL_INSTANTIATION #include "otbLineSegmentDetector.hxx" #endif #endif