diff --git a/Applications/DisparityMap/otbPixelWiseBlockMatching.cxx b/Applications/DisparityMap/otbPixelWiseBlockMatching.cxx index 6fd1fa60dc78e6a805325456dda092a02be894b3..3a9f47c965f2920a9a8879eda7387ca11afc4762 100644 --- a/Applications/DisparityMap/otbPixelWiseBlockMatching.cxx +++ b/Applications/DisparityMap/otbPixelWiseBlockMatching.cxx @@ -40,6 +40,7 @@ public: typedef otb::Functor::SSDBlockMatching<FloatImageType,FloatImageType> SSDBlockMatchingFunctorType; typedef otb::Functor::NCCBlockMatching<FloatImageType,FloatImageType> NCCBlockMatchingFunctorType; + typedef otb::Functor::LPBlockMatching<FloatImageType,FloatImageType> LPBlockMatchingFunctorType; typedef otb::PixelWiseBlockMatchingImageFilter<FloatImageType, FloatImageType, @@ -53,6 +54,12 @@ public: FloatImageType, NCCBlockMatchingFunctorType> NCCBlockMatchingFilterType; + typedef otb::PixelWiseBlockMatchingImageFilter<FloatImageType, + FloatImageType, + FloatImageType, + FloatImageType, + LPBlockMatchingFunctorType> LPBlockMatchingFilterType; + typedef otb::VarianceImageFilter<FloatImageType,FloatImageType> VarianceFilterType; @@ -77,6 +84,7 @@ private: // Initialize filters m_SSDBlockMatcher = SSDBlockMatchingFilterType::New(); m_NCCBlockMatcher = NCCBlockMatchingFilterType::New(); + m_LPBlockMatcher = LPBlockMatchingFilterType::New(); m_VarianceFilter = VarianceFilterType::New(); m_BandMathFilter = BandMathFilterType::New(); m_OutputImageList = ImageListType::New(); @@ -154,6 +162,14 @@ private: AddChoice("bm.metric.ncc","Normalized Cross-Correlation"); SetParameterDescription("bm.metric.ncc","Normalized Cross-Correlation between the left and right windows"); + AddChoice("bm.metric.lp","Lp pseudo-norm"); + SetParameterDescription("bm.metric.lp","Lp pseudo-norm between the left and right windows"); + + AddParameter(ParameterType_Float,"bm.metric.lp.p","p value" ); + SetParameterDescription("bm.metric.lp.p", "Value of the p parameter in Lp pseudo-norm (must be positive)"); + SetDefaultParameterFloat("bm.metric.lp.p", 1.0); + SetMinimumParameterFloatValue("bm.metric.lp.p", 0.0); + AddParameter(ParameterType_Int,"bm.radius","Radius of blocks"); SetParameterDescription("bm.radius","The radius (in pixels) of blocks in Block-Matching"); SetDefaultParameterInt("bm.radius",3); @@ -392,7 +408,7 @@ private: metricImage = m_SSDBlockMatcher->GetMetricOutput(); } // NCC case - else + else if (GetParameterInt("bm.metric") == 1) { m_NCCBlockMatcher->SetLeftInput(leftImage); m_NCCBlockMatcher->SetRightInput(rightImage); @@ -431,6 +447,46 @@ private: vdispImage = m_NCCBlockMatcher->GetVerticalDisparityOutput(); metricImage = m_NCCBlockMatcher->GetMetricOutput(); } + // Lp case + else + { + m_LPBlockMatcher->SetLeftInput(leftImage); + m_LPBlockMatcher->SetRightInput(rightImage); + m_LPBlockMatcher->SetRadius(radius); + m_LPBlockMatcher->GetFunctor().SetP(static_cast<double>(GetParameterFloat("bm.metric.lp.p"))); + m_LPBlockMatcher->SetMinimumHorizontalDisparity(minhdisp); + m_LPBlockMatcher->SetMaximumHorizontalDisparity(maxhdisp); + m_LPBlockMatcher->SetMinimumVerticalDisparity(minvdisp); + m_LPBlockMatcher->SetMaximumVerticalDisparity(maxvdisp); + AddProcess(m_LPBlockMatcher,"Lp block matching"); + + if(masking) + { + m_LPBlockMatcher->SetLeftMaskInput(m_BandMathFilter->GetOutput()); + } + if(useInitialDispUniform) + { + FloatImageType::SizeType expRadius; + expRadius[0] = GetParameterInt("bm.initdisp.uniform.hrad"); + expRadius[1] = GetParameterInt("bm.initdisp.uniform.vrad"); + m_LPBlockMatcher->SetExplorationRadius(expRadius); + m_LPBlockMatcher->SetInitHorizontalDisparity(GetParameterInt("bm.initdisp.uniform.hdisp")); + m_LPBlockMatcher->SetInitVerticalDisparity(GetParameterInt("bm.initdisp.uniform.vdisp")); + } + if(useInitialDispMap) + { + FloatImageType::SizeType expRadius; + expRadius[0] = GetParameterInt("bm.initdisp.maps.hrad"); + expRadius[1] = GetParameterInt("bm.initdisp.maps.vrad"); + m_LPBlockMatcher->SetExplorationRadius(expRadius); + m_LPBlockMatcher->SetHorizontalDisparityInput(GetParameterFloatImage("bm.initdisp.maps.hmap")); + m_LPBlockMatcher->SetVerticalDisparityInput(GetParameterFloatImage("bm.initdisp.maps.vmap")); + } + + hdispImage = m_LPBlockMatcher->GetHorizontalDisparityOutput(); + vdispImage = m_LPBlockMatcher->GetVerticalDisparityOutput(); + metricImage = m_LPBlockMatcher->GetMetricOutput(); + } m_OutputImageList->Clear(); @@ -453,12 +509,15 @@ private: } } - // SSD Block matching functor + // SSD Block matching filter SSDBlockMatchingFilterType::Pointer m_SSDBlockMatcher; - // NCC Block matching functor + // NCC Block matching filter NCCBlockMatchingFilterType::Pointer m_NCCBlockMatcher; + // Lp Block matching filter + LPBlockMatchingFilterType::Pointer m_LPBlockMatcher; + // Variance filter VarianceFilterType::Pointer m_VarianceFilter; diff --git a/Code/DisparityMap/otbPixelWiseBlockMatchingImageFilter.h b/Code/DisparityMap/otbPixelWiseBlockMatchingImageFilter.h index 14eb653bde1564c73017c5ba48e123d6d3a91395..315fd2c52808b7117f2155694567a109b1b60ba5 100644 --- a/Code/DisparityMap/otbPixelWiseBlockMatchingImageFilter.h +++ b/Code/DisparityMap/otbPixelWiseBlockMatchingImageFilter.h @@ -116,6 +116,57 @@ public: } }; +/** \class LPBlockMatching + * \brief Functor to perform block-matching based on the L^p pseudo-norm + * + * This functor is designed to work with the + * PixelWiseBlockMatchingImageFilter. It performs a distance computation between + * two windows based on the L^p pseudo norm (p greater than 0). The functor is + * templated by the type of inputs images and output metric image, + * and is using two neighborhood iterators as inputs. + */ +template <class TInputImage, class TOutputMetricImage> +ITK_EXPORT class LPBlockMatching +{ +public: + typedef itk::ConstNeighborhoodIterator<TInputImage> ConstNeigghborhoodIteratorType; + typedef typename TOutputMetricImage::ValueType MetricValueType; + + LPBlockMatching(): m_P(0) + { + } + + void SetP(double p) + { + if (p > 0.0) + { + m_P = p; + } + else + { + m_P = 1.0; + } + } + + // Implement the Lp metric + inline MetricValueType operator()(ConstNeigghborhoodIteratorType & a, ConstNeigghborhoodIteratorType & b) const + { + MetricValueType score(0); + + // For some reason, iterators do not work on neighborhoods + for(unsigned int i = 0; i<a.Size(); ++i) + { + score += vcl_pow( vcl_abs(static_cast<double>(a.GetPixel(i)-b.GetPixel(i))) , m_P); + } + + return score; + } + +private: + + double m_P; +}; + } // End Namespace Functor /** \class PixelWiseBlockMatchingImageFilter