├── CMakeLists.txt ├── copyright ├── app └── CMakeLists.txt ├── mosaic.remote.cmake ├── otb-module.cmake ├── include ├── otbSummingFilter.txx ├── otbStreamingSimpleMosaicFilter.h ├── otbStreamingMosaicFilterWithBlendingBase.txx ├── otbStreamingSimpleMosaicFilter.txx ├── otbSummingFilter.h ├── otbMosaicFunctors.h ├── otbPersistentMosaicFilter.h ├── otbMosaicFromDirectoryHandler.h ├── otbMosaicFromDirectoryHandler.txx ├── otbStreamingMosaicFilterWithBlendingBase.h ├── otbStreamingLargeFeatherMosaicFilter.h ├── otbQuadraticallyConstrainedSimpleSolver.h ├── otbStreamingLargeFeatherMosaicFilter.txx ├── otbStreamingFeatherMosaicFilter.h ├── otbStreamingFeatherMosaicFilter.txx ├── otbStreamingMultibandFeatherMosaicFilter.h ├── otbQuadraticallyConstrainedSimpleSolver.txx ├── otbStreamingMosaicFilterBase.h ├── otbStreamingMultibandFeatherMosaicFilter.txx ├── otbStreamingStatisticsMosaicFilter.txx ├── otbStreamingStatisticsMosaicFilter.h └── otbStreamingMosaicFilterBase.txx ├── test └── CMakeLists.txt ├── README.md └── LICENCE /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(Mosaic) 2 | otb_module_impl() 3 | -------------------------------------------------------------------------------- /copyright: -------------------------------------------------------------------------------- 1 | author: Remi Cresson 2 | 3 | Copyright (c) IRSTEA. All rights reserved. 4 | -------------------------------------------------------------------------------- /app/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | 3 | OTB_CREATE_APPLICATION(NAME Mosaic 4 | SOURCES otbMosaic.cxx 5 | LINK_LIBRARIES ${${otb-module}_LIBRARIES}) 6 | 7 | -------------------------------------------------------------------------------- /mosaic.remote.cmake: -------------------------------------------------------------------------------- 1 | #Contact: Rémi Cresson 2 | otb_fetch_module(Mosaic 3 | "images mosaicking" 4 | GIT_REPOSITORY https://github.com/remicres/otb-mosaic.git 5 | GIT_TAG 5b180a274b731bfd366f731cb829797e6d1ec756 6 | ) 7 | -------------------------------------------------------------------------------- /otb-module.cmake: -------------------------------------------------------------------------------- 1 | set(DOCUMENTATION "Mosaic generation of remote sensing images") 2 | 3 | otb_module(Mosaic 4 | DEPENDS 5 | OTBCommon 6 | OTBApplicationEngine 7 | OTBConversion 8 | OTBFunctor 9 | TEST_DEPENDS 10 | OTBTestKernel 11 | OTBCommandLine 12 | DESCRIPTION 13 | "Mosaic images" 14 | ) 15 | -------------------------------------------------------------------------------- /include/otbSummingFilter.txx: -------------------------------------------------------------------------------- 1 | #ifndef __SummingFilter_txx 2 | #define __SummingFilter_txx 3 | 4 | #include "otbSummingFilter.h" 5 | #include "itkProgressReporter.h" 6 | 7 | namespace otb { 8 | 9 | /** 10 | * Generates output information: 11 | */ 12 | template 13 | void SummingFilter 14 | ::GenerateOutputInformation(void) 15 | { 16 | itkDebugMacro( << "Generate output informations" ); 17 | Superclass::GenerateOutputInformation(); 18 | 19 | } 20 | 21 | /** 22 | * Processing. 23 | */ 24 | template 25 | void SummingFilter 26 | ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, 27 | itk::ThreadIdType threadId ) 28 | { 29 | 30 | // Debug info 31 | itkDebugMacro(<<"Actually executing thread " << threadId 32 | << " in region " << outputRegionForThread); 33 | 34 | // Support progress methods/callbacks 35 | itk::ProgressReporter progress(this, threadId, 36 | outputRegionForThread.GetNumberOfPixels() ); 37 | 38 | // Iterate through the thread region 39 | OutputIteratorType outputIt(this->GetOutput(), outputRegionForThread); 40 | 41 | // Prepare input iterators 42 | unsigned int nbInputImages = this->GetNumberOfInputs(); 43 | unsigned int nbInputBands; 44 | 45 | InputIteratorType inputIt[nbInputImages]; 46 | for (unsigned int i = 0 ; i < nbInputImages ; i++) 47 | { 48 | InputImageType * currentImage = const_cast(this->GetInput(i) ); 49 | inputIt[i] = InputIteratorType(currentImage, outputRegionForThread); 50 | nbInputBands = currentImage->GetNumberOfComponentsPerPixel(); 51 | } 52 | 53 | OutputImagePixelType pix; 54 | pix.SetSize(nbInputBands); 55 | 56 | // Sum images 57 | for ( outputIt.GoToBegin(); !outputIt.IsAtEnd(); ++outputIt ) 58 | { 59 | pix.Fill(0.0); 60 | for (unsigned int i = 0 ; i < nbInputImages ; i++) 61 | { 62 | 63 | for (unsigned int band = 0 ; band < nbInputBands ; band++) 64 | { 65 | pix[band] += inputIt[i].Get()[band]; 66 | 67 | } 68 | ++inputIt[i]; 69 | } 70 | outputIt.Set(pix); 71 | 72 | // Update process 73 | progress.CompletedPixel(); 74 | } 75 | 76 | } 77 | 78 | } 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /include/otbStreamingSimpleMosaicFilter.h: -------------------------------------------------------------------------------- 1 | #ifndef __StreamingSimpleMosaicFilter_H 2 | #define __StreamingSimpleMosaicFilter_H 3 | 4 | #include "otbStreamingMosaicFilterBase.h" 5 | 6 | namespace otb 7 | { 8 | /** \class StreamingSimpleMosaicFilter 9 | * \brief Computes the mosaic of an input images set. 10 | * The output pixel value is equal to the first input pixel of the stack 11 | * which is different from the Superclass::GetNoDataInputPixel() 12 | * 13 | * Support streaming 14 | * 15 | * The pixels must support the operator ==, +, /, etc. 16 | * The "no data value", output spacing, interpolator can be chosen. 17 | * The behavior of the filter is to put layers in the same order 18 | * as they are in input 19 | * 20 | * \ingroup OTBMosaic 21 | */ 22 | template 23 | class ITK_EXPORT StreamingSimpleMosaicFilter : public otb::StreamingMosaicFilterBase 25 | { 26 | public: 27 | 28 | /** Standard Self typedef */ 29 | typedef StreamingSimpleMosaicFilter Self; 30 | typedef otb::StreamingMosaicFilterBase Superclass; 31 | typedef itk::SmartPointer Pointer; 32 | typedef itk::SmartPointer ConstPointer; 33 | 34 | /** Method for creation through the object factory. */ 35 | itkNewMacro(Self); 36 | 37 | /** Runtime information support. */ 38 | itkTypeMacro(StreamingSimpleMosaicFilter, StreamingMosaicFilterBase); 39 | 40 | /** Input image typedefs. */ 41 | typedef typename Superclass::InputImageType InputImageType; 42 | typedef typename Superclass::InputImagePixelType InputImagePixelType; 43 | typedef typename Superclass::IteratorType IteratorType; 44 | typedef typename Superclass::InterpolatorPointerType InterpolatorPointerType; 45 | typedef typename Superclass::InputImageRegionType InputImageRegionType; 46 | 47 | /** Output image typedefs. */ 48 | typedef typename Superclass::OutputImageType OutputImageType; 49 | typedef typename Superclass::OutputImagePointType OutputImagePointType; 50 | typedef typename Superclass::OutputImagePixelType OutputImagePixelType; 51 | typedef typename Superclass::OutputImageInternalPixelType OutputImageInternalPixelType; 52 | typedef typename Superclass::OutputImageRegionType OutputImageRegionType; 53 | 54 | /** Internal computing typedef support. */ 55 | typedef typename Superclass::InternalValueType InternalValueType; 56 | typedef typename Superclass::InternalPixelType InternalPixelType; 57 | 58 | protected: 59 | StreamingSimpleMosaicFilter() { 60 | } 61 | 62 | virtual ~StreamingSimpleMosaicFilter() { 63 | } 64 | 65 | /** Overrided methods */ 66 | virtual void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId ); 67 | 68 | private: 69 | StreamingSimpleMosaicFilter(const Self&); //purposely not implemented 70 | void operator=(const Self&); //purposely not implemented 71 | 72 | }; // end of class 73 | 74 | } // end namespace otb 75 | 76 | #ifndef OTB_MANUAL_INSTANTIATION 77 | #include "otbStreamingSimpleMosaicFilter.txx" 78 | #endif 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /include/otbStreamingMosaicFilterWithBlendingBase.txx: -------------------------------------------------------------------------------- 1 | #ifndef __StreamingMosaicFilterWithBlendingBase_txx 2 | #define __StreamingMosaicFilterWithBlendingBase_txx 3 | 4 | #include "otbStreamingMosaicFilterWithBlendingBase.h" 5 | 6 | namespace otb { 7 | 8 | template 9 | StreamingMosaicFilterWithBlendingBase 10 | ::StreamingMosaicFilterWithBlendingBase() 11 | { 12 | 13 | // Default distance offset 14 | m_DistanceOffset = 0.0; 15 | 16 | // Default interpolator 17 | typename DistanceImageDefaultInterpolatorType::Pointer interp = DistanceImageDefaultInterpolatorType::New(); 18 | m_DistanceInterpolator = static_cast( interp.GetPointer() ); 19 | 20 | } 21 | 22 | /* 23 | * This method is overrided because one index on two is not an input image, but 24 | * an input distance image 25 | */ 26 | template 27 | void 28 | StreamingMosaicFilterWithBlendingBase 29 | ::AddUsedInputImageIndex(unsigned int inputImageIndex) 30 | { 31 | // Add this index only if input is an inputImage (i.e. not a distanceImage) 32 | if (inputImageIndex % 2 == 0) 33 | { 34 | itkDebugMacro(<<"Input #" << inputImageIndex << " is an InputImage and will be used"); 35 | Superclass::AddUsedInputImageIndex(inputImageIndex); 36 | } 37 | else 38 | { 39 | itkDebugMacro(<<"Input #" << inputImageIndex << " is an DistanceImage and will NOT be used"); 40 | } 41 | 42 | } 43 | 44 | /* 45 | * This method is overrided because there is twice less input images 46 | * (1 input image on 2 is a DistanceImage) 47 | */ 48 | template 49 | unsigned int 50 | StreamingMosaicFilterWithBlendingBase 51 | ::GetNumberOfInputImages() 52 | { 53 | return 0.5 * this->GetNumberOfInputs(); 54 | } 55 | 56 | /* 57 | * Prepare: 58 | * 1 image pointer 59 | * 1 image interpolator 60 | * 1 image region, which correspond to the buffered region which can be used by the interpolator 61 | */ 62 | template 63 | void 64 | StreamingMosaicFilterWithBlendingBase 65 | ::PrepareDistanceImageAccessors(typename std::vector& currentDistanceImage, 66 | typename std::vector& distanceInterpolator){ 67 | 68 | // Get number of used input images 69 | const unsigned int n = Superclass::GetNumberOfUsedInputImages(); 70 | 71 | currentDistanceImage.reserve(n); 72 | distanceInterpolator.reserve(n); 73 | 74 | // Loop on input images 75 | for (unsigned int i = 0 ; i < n ; i++) 76 | { 77 | // Input distance image i 78 | currentDistanceImage.push_back( static_cast( 79 | Superclass::ProcessObject::GetInput(Superclass::GetUsedInputImageIndice(i)+1) ) ); 80 | 81 | // Distance interpolator i 82 | distanceInterpolator.push_back( static_cast( 83 | (m_DistanceInterpolator->CreateAnother() ).GetPointer() ) ); 84 | distanceInterpolator[i]->SetInputImage(currentDistanceImage[i]); 85 | } 86 | } 87 | 88 | } // end namespace otb 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | otb_module_test() 2 | 3 | otb_test_application(NAME MosaicTestLargeFeathering 4 | APP Mosaic 5 | OPTIONS -il ${INPUTDATA}/SP67_FR_subset_1.tif ${INPUTDATA}/SP67_FR_subset_2.tif 6 | -out ${TEMP}/apTvMosaicTestLargeFeathering.tif uint8 7 | -comp.feather large 8 | VALID --compare-image ${EPSILON_8} 9 | ${BASELINE}/apTvMosaicTestLargeFeathering.tif 10 | ${TEMP}/apTvMosaicTestLargeFeathering.tif) 11 | 12 | 13 | otb_test_application(NAME MosaicTestSlimFeathering 14 | APP Mosaic 15 | OPTIONS -il ${INPUTDATA}/SP67_FR_subset_1.tif ${INPUTDATA}/SP67_FR_subset_2.tif 16 | -out ${TEMP}/apTvMosaicTestSlimFeathering.tif uint8 17 | -comp.feather slim 18 | -comp.feather.slim.lenght 100 19 | VALID --compare-image ${EPSILON_8} 20 | ${BASELINE}/apTvMosaicTestSlimFeathering.tif 21 | ${TEMP}/apTvMosaicTestSlimFeathering.tif) 22 | 23 | 24 | otb_test_application(NAME MosaicTestSimpleWithHarmoBandRmse 25 | APP Mosaic 26 | OPTIONS -il ${INPUTDATA}/SP67_FR_subset_1.tif ${INPUTDATA}/SP67_FR_subset_2.tif 27 | -out ${TEMP}/apTvMosaicTestSimpleWithHarmoBandRmse.tif uint8 28 | -harmo.method band 29 | -harmo.cost rmse 30 | VALID --compare-image ${EPSILON_8} 31 | ${BASELINE}/apTvMosaicTestSimpleWithHarmoBandRmse.tif 32 | ${TEMP}/apTvMosaicTestSimpleWithHarmoBandRmse.tif) 33 | 34 | otb_test_application(NAME MosaicTestSimpleWithHarmoRgbRmse 35 | APP Mosaic 36 | OPTIONS -il ${INPUTDATA}/SP67_FR_subset_1.tif ${INPUTDATA}/SP67_FR_subset_2.tif 37 | -out ${TEMP}/apTvMosaicTestSimpleWithHarmoRgbRmse.tif uint8 38 | -harmo.method rgb 39 | -harmo.cost rmse 40 | VALID --compare-image ${EPSILON_8} 41 | ${BASELINE}/apTvMosaicTestSimpleWithHarmoRgbRmse.tif 42 | ${TEMP}/apTvMosaicTestSimpleWithHarmoRgbRmse.tif) 43 | 44 | otb_test_application(NAME MosaicTestSimpleWithCutline 45 | APP Mosaic 46 | OPTIONS -il ${INPUTDATA}/SP67_FR_subset_1.tif ${INPUTDATA}/SP67_FR_subset_2.tif 47 | -out ${TEMP}/apTvMosaicTestSimpleWithCutline.tif uint8 48 | -vdcut ${INPUTDATA}/SP67_FR_subset_1_cutline.shp ${INPUTDATA}/SP67_FR_subset_2_cutline.shp 49 | VALID --compare-image ${EPSILON_8} 50 | ${BASELINE}/apTvMosaicTestSimpleWithCutline.tif 51 | ${TEMP}/apTvMosaicTestSimpleWithCutline.tif) 52 | 53 | otb_test_application(NAME MosaicTestSimpleWithVdstats 54 | APP Mosaic 55 | OPTIONS -il ${INPUTDATA}/SP67_FR_subset_1.tif ${INPUTDATA}/SP67_FR_subset_2.tif 56 | -out ${TEMP}/apTvMosaicTestSimpleWithVdstats.tif uint8 57 | -vdstats ${INPUTDATA}/SP67_FR_subset_1_cutline.shp ${INPUTDATA}/SP67_FR_subset_2_cutline.shp 58 | VALID --compare-image ${EPSILON_8} 59 | ${BASELINE}/apTvMosaicTestSimpleWithVdstats.tif 60 | ${TEMP}/apTvMosaicTestSimpleWithVdstats.tif) 61 | -------------------------------------------------------------------------------- /include/otbStreamingSimpleMosaicFilter.txx: -------------------------------------------------------------------------------- 1 | #ifndef __StreamingSimpleMosaicFilter_txx 2 | #define __StreamingSimpleMosaicFilter_txx 3 | 4 | #include "otbStreamingSimpleMosaicFilter.h" 5 | 6 | namespace otb { 7 | 8 | /** 9 | * Processing 10 | */ 11 | template 12 | void 13 | StreamingSimpleMosaicFilter 14 | ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) 15 | { 16 | 17 | // Debug info 18 | itkDebugMacro(<<"Actually executing thread " << threadId << " in region " << outputRegionForThread); 19 | 20 | // Support progress methods/callbacks 21 | itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels() ); 22 | 23 | // Get output pointer 24 | OutputImageType * mosaicImage = this->GetOutput(); 25 | 26 | // Get number of used inputs 27 | const unsigned int nbOfUsedInputImages = Superclass::GetNumberOfUsedInputImages(); 28 | 29 | // Get number of bands 30 | const unsigned int nBands = Superclass::GetNumberOfBands(); 31 | 32 | // Iterate through the thread region 33 | IteratorType outputIt(mosaicImage, outputRegionForThread); 34 | 35 | // Prepare interpolated pixel 36 | InternalPixelType interpolatedMathPixel; 37 | interpolatedMathPixel.SetSize(nBands); 38 | 39 | // Prepare input pointers, interpolators, and valid regions (input images) 40 | typename std::vector currentImage; 41 | typename std::vector interp; 42 | Superclass::PrepareImageAccessors(currentImage, interp); 43 | 44 | // Container for geo coordinates 45 | OutputImagePointType geoPoint; 46 | 47 | for ( outputIt.GoToBegin(); !outputIt.IsAtEnd(); ++outputIt ) 48 | { 49 | // Prepare output pixel 50 | OutputImagePixelType outputPixel(Superclass::GetNoDataOutputPixel() ); 51 | 52 | // Current pixel --> Geographical point 53 | mosaicImage->TransformIndexToPhysicalPoint (outputIt.GetIndex(), geoPoint) ; 54 | 55 | // Loop on used input images 56 | for (unsigned int i = 0 ; i < nbOfUsedInputImages ; i++) 57 | { 58 | // Get the input image pointer 59 | unsigned int imgIndex = Superclass::GetUsedInputImageIndice(i); 60 | 61 | // Check if the point is inside the transformed thread region 62 | // (i.e. the region in the current input image which match the thread 63 | // region) 64 | if (interp[i]->IsInsideBuffer(geoPoint) ) 65 | { 66 | 67 | // Compute the interpolated pixel value 68 | InputImagePixelType interpolatedPixel = interp[i]->Evaluate(geoPoint); 69 | 70 | // Check that interpolated pixel is not empty 71 | if (Superclass::IsPixelNotEmpty(interpolatedPixel) ) 72 | { 73 | // Update the output pixel 74 | for (unsigned int band = 0 ; band < nBands ; band++) 75 | { 76 | if (this->GetShiftScaleInputImages() ) 77 | { 78 | InternalValueType pixelValue = static_cast(interpolatedPixel[band]); 79 | this->ShiftScaleValue(pixelValue, imgIndex, band); 80 | outputPixel[band] = static_cast(pixelValue); 81 | } 82 | else 83 | { 84 | outputPixel[band] = static_cast(interpolatedPixel[band]); 85 | } 86 | } 87 | } // Interpolated pixel is not empty 88 | } // point inside buffer 89 | } // next image 90 | 91 | // Update output pixel value 92 | outputIt.Set(outputPixel); 93 | 94 | // Update progress 95 | progress.CompletedPixel(); 96 | 97 | } // next output pixel 98 | 99 | } 100 | 101 | } // end namespace gtb 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /include/otbSummingFilter.h: -------------------------------------------------------------------------------- 1 | #ifndef __SummingFilter_H 2 | #define __SummingFilter_H 3 | 4 | #include "itkImageToImageFilter.h" 5 | #include "itkImageRegionIterator.h" 6 | namespace otb 7 | { 8 | /** \class SummingFilter 9 | * \brief Computes the sum of the input images pixels 10 | * 11 | * Support streaming 12 | * 13 | * The pixels must support the operator ==, +, /, etc. 14 | * The "no data value" can be chose. 15 | * 16 | * \ingroup OTBMosaic 17 | */ 18 | template 19 | class ITK_EXPORT SummingFilter : public itk::ImageToImageFilter 20 | { 21 | public: 22 | 23 | /** Standard Self typedef */ 24 | typedef SummingFilter Self; 25 | typedef itk::ImageToImageFilter Superclass; 26 | typedef itk::SmartPointer Pointer; 27 | typedef itk::SmartPointer ConstPointer; 28 | 29 | /** Method for creation through the object factory. */ 30 | itkNewMacro(Self); 31 | 32 | /** Runtime information support. */ 33 | itkTypeMacro(SummingFilter, ImageToImageFilter); 34 | 35 | /** Some additional typedefs. */ 36 | typedef TInputImage InputImageType; 37 | typedef typename InputImageType::RegionType InputImageRegionType; 38 | typedef typename InputImageType::PixelType InputImagePixelType; 39 | typedef typename InputImageType::PointType InputImagePointType; 40 | typedef typename InputImageType::IndexType InputImageIndexType; 41 | typedef typename InputImageType::SizeType InputImageSizeType; 42 | typedef typename InputImageType::SpacingType InputImageSpacingType; 43 | typedef typename InputImageType::InternalPixelType InputImageInternalPixelType; 44 | 45 | /** Some additional typedefs. */ 46 | typedef TOutputImage OutputImageType; 47 | typedef typename OutputImageType::Pointer OutputImagePointer; 48 | typedef typename OutputImageType::RegionType OutputImageRegionType; 49 | typedef typename OutputImageType::IndexType OutputImageIndexType; 50 | typedef typename OutputImageType::PointType OutputImagePointType; 51 | typedef typename OutputImageType::SizeType OutputImageSizeType; 52 | typedef typename OutputImageType::SpacingType OutputImageSpacingType; 53 | typedef typename OutputImageType::PixelType OutputImagePixelType; 54 | typedef typename OutputImageType::InternalPixelType OutputImageInternalPixelType; 55 | 56 | /** Iterators */ 57 | typedef itk::ImageRegionIterator< OutputImageType > OutputIteratorType; 58 | typedef itk::ImageRegionConstIterator InputIteratorType; 59 | 60 | protected: 61 | SummingFilter() { 62 | } 63 | 64 | virtual ~SummingFilter() { 65 | } 66 | 67 | /** SummingFilter can be implemented as a multithreaded filter. 68 | * Therefore, this implementation provides a ThreadedGenerateData() routine 69 | * which is called for each processing thread. The output image data is 70 | * allocated automatically by the superclass prior to calling 71 | * ThreadedGenerateData(). ThreadedGenerateData can only write to the 72 | * portion of the output image specified by the parameter 73 | * "outputRegionForThread" 74 | * 75 | * \sa ImageToImageFilter::ThreadedGenerateData(), 76 | * ImageToImageFilter::GenerateData() */ 77 | 78 | /** Overrided methods */ 79 | virtual void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId); 80 | 81 | virtual void GenerateOutputInformation(void); 82 | 83 | private: 84 | SummingFilter(const Self&); //purposely not implemented 85 | void operator=(const Self&); //purposely not implemented 86 | 87 | }; // end of class 88 | 89 | } 90 | 91 | #ifndef OTB_MANUAL_INSTANTIATION 92 | #include "otbSummingFilter.txx" 93 | #endif 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **This repository is archived** since Mosaic is now part of the Orfeo ToolBox releases. 2 | 3 | Summary 4 | ======= 5 | 6 | This module provides one application dedicated to images mosaicking. 7 | 8 | # Compositing 9 | 10 | ## Methods 11 | 12 | * Simple compositing technique (__-comp.feather none__): Copies the last image over earlier ones in areas of overlap (Default) 13 | * Feathering technique (__-comp.feather large__): Blends all images on the maximum overlapping areas (this produces seamless mosaics, but can cause blur effect where images are not perfectly aligned). 14 | * Feathering technique (__-comp.feather slim__): Blends the last image over earlier ones in areas of overlap, on a given transition distance (seam can be visible from a certain zoom level, but it does not cause blur effect when images are not perfectly aligned) 15 | 16 | ## Performance tuning: Distance map images sampling ratio 17 | 18 | For performance issues, distance map images (used by feathering methods) size can be reduced using __-distancemap.sr__. Indeed, distance map images are computed into a temporary file before the compositing process, because it couldn't be done in a streamable way. That is, the RAM must be enough to compute the entire distance map image from each single input image. Thus, the application provides an option to reduce the size of the distance map images. Setting -distancemap.sr 10 will induce a 0.1x wider distance map image, and will save 100x less RAM. To keep the original input size, just set -alphamasks.spacing 1.0 (Default distance map images size reduction ratio is 10.) 19 | 20 | ## Interpolator 21 | 22 | Supported interpolators are 23 | * Nearest Neighborhood (__-interpolator nn__) (Default) 24 | * Bicubic (__-interpolator bco__) 25 | * Linear (__-interpolator linear__) 26 | 27 | ## Output spacing 28 | 29 | Spacing of the output mosaic can be changed using __-output.spacingx__ and __-output.spacingy__ 30 | 31 | ## No-data value 32 | 33 | The no-data value, used in both harmonization process and compositing process, can be changed using the __-nodata__ parameter 34 | 35 | ## Cutline (vector data) 36 | 37 | Input vector data can additionaly feed the process for cutline selection using __-vdcut__. One vector data is required for each input image, and must appear in the same order. 38 | 39 | # Radiometric/Colorimetric harmonization 40 | 41 | More information about the method can be found in the paper "_Natural Color Satellite Image Mosaicking Using Quadratic Programming in Decorrelated Color Space_" Cresson & Saint-Geours, July 2015, IEEE JSTARS Volume 8 Issue 8 (https://doi.org/10.1109/JSTARS.2015.2449233) 42 | 43 | ## Methods 44 | 45 | * None (__-harmo.method none__): No harmonization. Images pixels values are untouched.(Default) 46 | * Band-by-band (__-harmo.method none__): Consists in minimizing a cost function based on images statistics in overlapping areas, for each band independently. 47 | * True color harmonization (__-harmo.method rgb__): Consists in minimizing a cost function based on images statistics in overlapping areas, in a decorreleted color space suitable for true color processing (works only on true color images, i.e. RGB). Only the first 3 bands are processed by this method. 48 | 49 | ## Cost function 50 | 51 | Various cost function can be used for harmonization 52 | * rmse (__-harmo.cost rmse__): Root mean squared error based cost function 53 | * musig (__-harmo.cost musig__): Mean and Standard deviation based cost function 54 | * mu (__-harmo.cost mu__): Mean based cost function 55 | 56 | ## Masks for statistics (vector data) 57 | 58 | Input vector data can additionaly feed the process for statistics computation, e.g. to mask clouds or water, using __-vdstats__. One vector data is required for each input image, and must appear in the same order. 59 | 60 | ## Temporary files 61 | 62 | Distance map images, and binary masks are temporary stored in the temporary directory specified by parameter __-tmpdir__ (Default is application directory). 63 | 64 | How to use it? 65 | ======= 66 | 67 | Mosaic can be used as any OTB application (gui, command line, python, c++, ...). 68 | 69 | Licence 70 | ======= 71 | 72 | This code is provided under the CeCILL-B free software license agreement. 73 | 74 | Contact 75 | ======= 76 | 77 | For any issues regarding this module please contact Rémi Cresson. 78 | 79 | remi.cresson at irstea.fr 80 | 81 | Irstea ((French) National Research Institute of Science and Technology for Environment and Agriculture) 82 | www.irstea.fr 83 | -------------------------------------------------------------------------------- /include/otbMosaicFunctors.h: -------------------------------------------------------------------------------- 1 | /* 2 | * otbMosaicFunctors.h 3 | * 4 | * Created on: 16 août 2017 5 | * Author: cresson 6 | */ 7 | 8 | #ifndef MODULES_REMOTE_MOSAIC_INCLUDE_OTBMOSAICFUNCTORS_H_ 9 | #define MODULES_REMOTE_MOSAIC_INCLUDE_OTBMOSAICFUNCTORS_H_ 10 | 11 | #include "vnl/vnl_matrix.h" 12 | #include "vcl_compiler.h" 13 | 14 | namespace otb{ 15 | 16 | namespace Functor{ 17 | 18 | /** 19 | * \class RGB2LAB Functor 20 | * \brief Base class for converting RGB into LAB color space (Ruderman et al.) 21 | * 22 | * \ingroup OTBMosaic 23 | */ 24 | template< class TInput, class TOutput> 25 | class RGB2LAB 26 | { 27 | public: 28 | RGB2LAB() { 29 | M.set_size(3,3); 30 | M[0][0] = 0.3811; M[0][1] = 0.5783; M[0][2] = 0.0406; 31 | M[1][0] = 0.1967; M[1][1] = 0.7244; M[1][2] = 0.0790; 32 | M[2][0] = 0.0241; M[2][1] = 0.1288; M[2][2] = 0.8531; 33 | 34 | D1.set_size(3,3); 35 | D1.fill(0.0); 36 | D1[0][0] = 1.0 / vcl_sqrt(3.0); 37 | D1[1][1] = 1.0 / vcl_sqrt(6.0); 38 | D1[2][2] = 1.0 / vcl_sqrt(2.0); 39 | 40 | D2.set_size(3,3); 41 | D2.fill(1.0); 42 | D2[1][2] = -2.0; 43 | D2[2][1] = -1.0; 44 | D2[2][2] = 0.0; 45 | 46 | } 47 | 48 | ~RGB2LAB() { 49 | } 50 | 51 | bool operator!=( const RGB2LAB & ) const { 52 | return false; 53 | } 54 | 55 | bool operator==( const RGB2LAB & other ) const { 56 | return !(*this != other); 57 | } 58 | 59 | inline TOutput operator()( const TInput & A ) const 60 | { 61 | TOutput output; 62 | 63 | output.SetSize(3); 64 | if (A[0] == 0 && A[1] == 0 && A[2] == 0) 65 | { 66 | output.Fill(0); 67 | return output; 68 | } 69 | 70 | // RGB 71 | vnl_matrix rgb(3,1); 72 | rgb[0][0] = A[0]; 73 | rgb[1][0] = A[1]; 74 | rgb[2][0] = A[2]; 75 | 76 | // LMS 77 | vnl_matrix lms(3,1); 78 | lms = M*rgb; 79 | 80 | // LMS (log10) 81 | const double log10 = vcl_log(10); 82 | lms[0][0] = vcl_log( lms[0][0] ) / log10; 83 | lms[1][0] = vcl_log( lms[1][0] ) / log10; 84 | lms[2][0] = vcl_log( lms[2][0] ) / log10; 85 | 86 | // LAB 87 | vnl_matrix lab(3,1); 88 | lab = D1*(D2*lms); 89 | 90 | output[0] = lab[0][0]; 91 | output[1] = lab[1][0]; 92 | output[2] = lab[2][0]; 93 | 94 | return output; 95 | } 96 | 97 | size_t OutputSize(const std::array &) const { 98 | return 3; 99 | } 100 | 101 | private: 102 | vnl_matrix M; 103 | vnl_matrix D1; 104 | vnl_matrix D2; 105 | 106 | }; 107 | 108 | /** 109 | * \class LAB2RGB Functor 110 | * \brief Base class for converting LAB into RGB color space (Ruderman et al.) 111 | * 112 | * TODO: invert the function RGB2LAB than using the hardcoded one 113 | * 114 | * \ingroup OTBMosaic 115 | */ 116 | template< class TInput, class TOutput> 117 | class LAB2RGB 118 | { 119 | public: 120 | LAB2RGB() { 121 | M.set_size(3,3); 122 | M[0][0] = 4.4687; M[0][1] = -3.5887; M[0][2] = 0.1197; 123 | M[1][0] = -1.2197; M[1][1] = 2.3831; M[1][2] = -0.1626; 124 | M[2][0] = 0.0579; M[2][1] = -0.2584; M[2][2] = 1.1934; 125 | 126 | D1.set_size(3,3); 127 | D1.fill(0.0); 128 | D1[0][0] = 1.0 / vcl_sqrt(3.0); 129 | D1[1][1] = 1.0 / vcl_sqrt(6.0); 130 | D1[2][2] = 1.0 / vcl_sqrt(2.0); 131 | 132 | D2.set_size(3,3); 133 | D2.fill(1.0); 134 | D2[1][2] = -1.0; 135 | D2[2][1] = -2.0; 136 | D2[2][2] = 0.0; 137 | 138 | } 139 | 140 | ~LAB2RGB() { 141 | } 142 | 143 | bool operator!=( const LAB2RGB & ) const 144 | { 145 | return false; 146 | } 147 | 148 | bool operator==( const LAB2RGB & other ) const 149 | { 150 | return !(*this != other); 151 | } 152 | 153 | inline TOutput operator()( const TInput & A ) const 154 | { 155 | TOutput output; 156 | 157 | output.SetSize(3); 158 | 159 | if (A[0] == 0 && A[1] == 0 && A[2] == 0) 160 | { 161 | output.Fill(0); 162 | return output; 163 | } 164 | // LAB 165 | vnl_matrix lab(3,1); 166 | lab[0][0] = A[0]; 167 | lab[1][0] = A[1]; 168 | lab[2][0] = A[2]; 169 | 170 | // LMS 171 | vnl_matrix lms(3,1); 172 | lms = D2*(D1*lab); 173 | lms[0][0] = vcl_pow(10.0, lms[0][0]); 174 | lms[1][0] = vcl_pow(10.0, lms[1][0]); 175 | lms[2][0] = vcl_pow(10.0, lms[2][0]); 176 | 177 | // RGB 178 | vnl_matrix rgb(3,1); 179 | rgb = M*lms; 180 | 181 | output[0] = rgb[0][0]; 182 | output[1] = rgb[1][0]; 183 | output[2] = rgb[2][0]; 184 | 185 | return output; 186 | } 187 | 188 | inline size_t OutputSize(const std::array &) const { 189 | return 3; 190 | } 191 | 192 | private: 193 | vnl_matrix M; 194 | vnl_matrix D1; 195 | vnl_matrix D2; 196 | 197 | }; 198 | 199 | } // namespace functor 200 | } // namespace otb 201 | #endif /* MODULES_REMOTE_MOSAIC_INCLUDE_OTBMOSAICFUNCTORS_H_ */ 202 | -------------------------------------------------------------------------------- /include/otbPersistentMosaicFilter.h: -------------------------------------------------------------------------------- 1 | #ifndef MODULES_REMOTE_MOSAIC_INCLUDE_OTBPERSISTENTMOSAICFILTER_H_ 2 | #define MODULES_REMOTE_MOSAIC_INCLUDE_OTBPERSISTENTMOSAICFILTER_H_ 3 | 4 | #include "otbStreamingMosaicFilterBase.h" 5 | 6 | namespace otb 7 | { 8 | /** \class PersistentMosaicFilter 9 | * \brief This filter is the base class for all mosaic filter persisting data through multiple 10 | * update. 11 | * For instance, a filter computing global statistics on an mosaic with streaming 12 | * capabilities will have to keep the temporary results for each streamed piece of the 13 | * image in order to synthesize the global statistics at the end. This filter is an 14 | * itk::ImageToImageFilter, providing two additional methods. The first one, Synthetize(), 15 | * allows the user to synthesize temporary data produced by the multiple updates on different 16 | * pieces of the image to the global result. The second one, Reset(), allows the user to 17 | * reset the temporary data for a new input image for instance. 18 | * 19 | * \note This class contains pure virtual method, and can not be instantiated. 20 | * 21 | * \sa PersistentMosaicFilter 22 | * \sa StreamingStatisticsMosaicFilter 23 | * 24 | * \ingroup OTBMosaic 25 | */ 26 | template 27 | class ITK_EXPORT PersistentMosaicFilter : public otb::StreamingMosaicFilterBase 28 | { 29 | public: 30 | /** Standard typedefs */ 31 | typedef PersistentMosaicFilter Self; 32 | typedef otb::StreamingMosaicFilterBase Superclass; 33 | typedef itk::SmartPointer Pointer; 34 | typedef itk::SmartPointer ConstPointer; 35 | 36 | /** Creation through object factory macro */ 37 | itkTypeMacro(PersistentMosaicFilter, StreamingMosaicFilterBase); 38 | 39 | /** Input image typedefs. */ 40 | typedef typename Superclass::InputImageType InputImageType; 41 | typedef typename Superclass::InputImagePointer InputImagePointer; 42 | typedef typename Superclass::InputImagePointType InputImagePointType; 43 | typedef typename Superclass::InputImagePixelType InputImagePixelType; 44 | typedef typename Superclass::InputImageIndexType InputImageIndexType; 45 | typedef typename Superclass::InputImageSizeType InputImageSizeType; 46 | typedef typename Superclass::InputImageSpacingType InputImageSpacingType; 47 | typedef typename Superclass::InputImageInternalPixelType InputImageInternalPixelType; 48 | typedef typename Superclass::InputImageRegionType InputImageRegionType; 49 | 50 | /** Output image typedefs. */ 51 | typedef typename Superclass::OutputImageType OutputImageType; 52 | typedef typename Superclass::OutputImagePointer OutputImagePointer; 53 | typedef typename Superclass::OutputImagePointType OutputImagePointType; 54 | typedef typename Superclass::OutputImagePixelType OutputImagePixelType; 55 | typedef typename Superclass::OutputImageIndexType OutputImageIndexType; 56 | typedef typename Superclass::OutputImageSizeType OutputImageSizeType; 57 | typedef typename Superclass::OutputImageSpacingType OutputImageSpacingType; 58 | typedef typename Superclass::OutputImageInternalPixelType OutputImageInternalPixelType; 59 | typedef typename Superclass::OutputImageRegionType OutputImageRegionType; 60 | 61 | /** Internal computing typedef support. */ 62 | typedef typename Superclass::InternalValueType InternalValueType; 63 | typedef typename Superclass::ContinuousIndexType ContinuousIndexType; 64 | typedef typename Superclass::InterpolatorType InterpolatorType; 65 | typedef typename Superclass::InterpolatorPointerType InterpolatorPointerType; 66 | typedef typename Superclass::DefaultInterpolatorType DefaultInterpolatorType; 67 | typedef typename Superclass::InternalImageType InternalImageType; 68 | typedef typename Superclass::InternalPixelType InternalPixelType; 69 | typedef typename Superclass::IteratorType IteratorType; 70 | typedef typename Superclass::ConstIteratorType ConstIteratorType; 71 | typedef typename Superclass::StreamingTraitsType StreamingTraitsType; 72 | 73 | /** 74 | * Reset the persistent data of the filter. 75 | */ 76 | virtual void Reset(void) = 0; 77 | /** 78 | * Synthesize the persistent data of the filter. 79 | */ 80 | virtual void Synthetize(void) = 0; 81 | 82 | protected: 83 | /** Constructor */ 84 | PersistentMosaicFilter() {} 85 | /** Destructor */ 86 | ~PersistentMosaicFilter() ITK_OVERRIDE {} 87 | /**PrintSelf method */ 88 | void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE 89 | { 90 | Superclass::PrintSelf(os, indent); 91 | } 92 | 93 | private: 94 | PersistentMosaicFilter(const Self &); //purposely not implemented 95 | void operator =(const Self&); //purposely not implemented 96 | }; 97 | } // End namespace otb 98 | 99 | 100 | 101 | #endif /* MODULES_REMOTE_MOSAIC_INCLUDE_OTBPERSISTENTMOSAICFILTER_H_ */ 102 | -------------------------------------------------------------------------------- /include/otbMosaicFromDirectoryHandler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * otbMosaicFromDirectoryHandler.h 3 | * 4 | * Created on: 24 mars 2016 5 | * Author: cresson 6 | */ 7 | 8 | #ifndef MODULES_REMOTE_OTB_MosaicFromDirectoryHandler_INCLUDE_OTBMosaicFromDirectoryHandler_H_ 9 | #define MODULES_REMOTE_OTB_MosaicFromDirectoryHandler_INCLUDE_OTBMosaicFromDirectoryHandler_H_ 10 | 11 | #include "itkImageSource.h" 12 | #include "itkExceptionObject.h" 13 | #include "itkImageRegion.h" 14 | 15 | #include "otbStreamingSimpleMosaicFilter.h" 16 | 17 | #include "otbImageFileReader.h" 18 | #include "itkDirectory.h" 19 | #include "otbImageIOBase.h" 20 | #include "otbImageIOFactory.h" 21 | 22 | #include "otbMultiToMonoChannelExtractROI.h" 23 | #include "otbGenericRSResampleImageFilter.h" 24 | #include "itkNearestNeighborInterpolateImageFunction.h" 25 | 26 | namespace otb 27 | { 28 | /** \class MosaicFromDirectoryHandler 29 | * \brief This ImageSource produces an otb::image from multiple rasters 30 | * stored in the m_Directory. 31 | * TODO: Currently only .tif extension is supported. Might be nice to change it. 32 | * 33 | * 34 | * \ingroup OTBMosaic 35 | * 36 | */ 37 | template 38 | class ITK_EXPORT MosaicFromDirectoryHandler : public itk::ImageSource 39 | { 40 | public: 41 | /** Standard class typedefs. */ 42 | typedef MosaicFromDirectoryHandler Self; 43 | typedef itk::ImageSource Superclass; 44 | typedef itk::SmartPointer Pointer; 45 | 46 | /** Method for creation through the object factory. */ 47 | itkNewMacro(Self); 48 | 49 | /** Run-time type information (and related methods). */ 50 | itkTypeMacro(MosaicFromDirectoryHandler, ImageSource); 51 | 52 | /** Typedefs for output image */ 53 | typedef typename TOutputImage::SizeType SizeType; 54 | typedef typename TOutputImage::IndexType IndexType; 55 | typedef typename TOutputImage::SpacingType SpacingType; 56 | typedef typename TOutputImage::PointType PointType; 57 | typedef typename TOutputImage::RegionType ImageRegionType; 58 | typedef typename TOutputImage::InternalPixelType OutputImagePixelType; 59 | 60 | /** Typedefs for mosaic filter */ 61 | typedef otb::VectorImage InternalMaskImageType; 62 | typedef otb::StreamingSimpleMosaicFilter< 63 | InternalMaskImageType> MosaicFilterType; 64 | typedef typename MosaicFilterType::Pointer MosaicFilterPointerType; 65 | 66 | /** Typedefs for image reader */ 67 | typedef otb::ImageFileReader ReaderType; 68 | typedef typename ReaderType::Pointer ReaderPointerType; 69 | 70 | /** Typedefs for casting the image */ 71 | typedef otb::MultiToMonoChannelExtractROI< 72 | OutputImagePixelType, OutputImagePixelType> CastFilterType; 73 | typedef typename CastFilterType::Pointer CastFilterPointerType; 74 | 75 | /** Typedefs for image reprojection */ 76 | typedef otb::GenericRSResampleImageFilter< 77 | InternalMaskImageType, InternalMaskImageType> ResamplerType; 78 | typedef typename ResamplerType::Pointer ResamplerPointerType; 79 | typedef itk::NearestNeighborInterpolateImageFunction< 80 | InternalMaskImageType, double> NNInterpolatorType; 81 | 82 | /** Input directory accessors */ 83 | itkGetMacro(Directory, std::string); 84 | itkSetMacro(Directory, std::string); 85 | 86 | /** Output parameters setters */ 87 | itkSetMacro(OutputSpacing, SpacingType); 88 | itkSetMacro(OutputSize, SizeType); 89 | itkSetMacro(OutputOrigin, PointType); 90 | void SetReferenceImage(TReferenceImage * ptr){m_RefImagePtr = ptr;} 91 | itkSetMacro(UseReferenceImage, bool); 92 | 93 | /** Prepare image allocation at the first call of the pipeline processing */ 94 | virtual void GenerateOutputInformation(void); 95 | 96 | /** Does the real work. */ 97 | virtual void GenerateData(); 98 | 99 | protected: 100 | MosaicFromDirectoryHandler(); 101 | virtual ~MosaicFromDirectoryHandler(); 102 | 103 | // Masks directory 104 | std::string m_Directory; 105 | 106 | // Output parameters 107 | SpacingType m_OutputSpacing; 108 | SizeType m_OutputSize; 109 | PointType m_OutputOrigin; 110 | 111 | // Internal filters 112 | MosaicFilterPointerType mosaicFilter; 113 | CastFilterPointerType castFilter; 114 | std::vector readers; 115 | std::vector resamplers; 116 | 117 | // Reference image pointer 118 | bool m_UseReferenceImage; 119 | TReferenceImage * m_RefImagePtr; 120 | 121 | private: 122 | 123 | MosaicFromDirectoryHandler(const Self &); //purposely not implemented 124 | void operator =(const Self&); //purposely not implemented 125 | 126 | }; 127 | 128 | } //namespace otb 129 | 130 | #ifndef OTB_MANUAL_INSTANTIATION 131 | #include 132 | #endif 133 | 134 | #endif /* MODULES_REMOTE_OTB_MosaicFromDirectoryHandler_INCLUDE_OTBMosaicFromDirectoryHandler_H_ */ 135 | -------------------------------------------------------------------------------- /include/otbMosaicFromDirectoryHandler.txx: -------------------------------------------------------------------------------- 1 | /* 2 | * otbMosaicFromDirectoryHandler.hxx 3 | * 4 | * Created on: 24 mars 2016 5 | * Author: cresson 6 | */ 7 | 8 | #ifndef MODULES_REMOTE_OTB_MosaicFromDirectoryHandler_INCLUDE_OTBMosaicFromDirectoryHandler_HXX_ 9 | #define MODULES_REMOTE_OTB_MosaicFromDirectoryHandler_INCLUDE_OTBMosaicFromDirectoryHandler_HXX_ 10 | 11 | #include "otbMosaicFromDirectoryHandler.h" 12 | #include "otbImageFileWriter.h" 13 | 14 | namespace otb 15 | { 16 | 17 | template 18 | MosaicFromDirectoryHandler 19 | ::MosaicFromDirectoryHandler() 20 | { 21 | mosaicFilter = MosaicFilterType::New(); 22 | castFilter = CastFilterType::New(); 23 | m_UseReferenceImage = false; 24 | m_RefImagePtr = 0; 25 | } 26 | 27 | template 28 | MosaicFromDirectoryHandler 29 | ::~MosaicFromDirectoryHandler() 30 | { 31 | } 32 | 33 | template 34 | void 35 | MosaicFromDirectoryHandler 36 | ::GenerateOutputInformation() 37 | { 38 | if (m_Directory[m_Directory.size()-1] != '/') 39 | { 40 | // If not, we add the separator 41 | m_Directory.append("/"); 42 | } 43 | 44 | // Get the list of files in the directory 45 | itk::Directory::Pointer dir = itk::Directory::New(); 46 | if (!dir->Load(m_Directory.c_str())) 47 | { 48 | itkExceptionMacro(<< "Unable to browse directory " << m_Directory); 49 | } 50 | 51 | // Instanciate a new mosaic filter 52 | mosaicFilter = MosaicFilterType::New(); 53 | mosaicFilter->SetGlobalWarningDisplay(false); 54 | readers.clear(); 55 | resamplers.clear(); 56 | 57 | // Browse the directory 58 | for (unsigned int i = 0; i < dir->GetNumberOfFiles(); i++) 59 | { 60 | const char *filename = dir->GetFile(i); 61 | std::string sfilename(filename); 62 | sfilename = m_Directory + sfilename; 63 | 64 | // Try to read the file 65 | otb::ImageIOBase::Pointer imageIO = 66 | otb::ImageIOFactory::CreateImageIO(sfilename.c_str(),otb::ImageIOFactory::ReadMode); 67 | if( imageIO.IsNotNull() ) 68 | { 69 | // create reader 70 | ReaderPointerType reader = ReaderType::New(); 71 | reader->SetFileName(sfilename); 72 | reader->UpdateOutputInformation(); 73 | 74 | readers.push_back(reader); 75 | 76 | if (m_UseReferenceImage) 77 | { 78 | ResamplerPointerType resampler = ResamplerType::New(); 79 | resampler->SetInput(reader->GetOutput()); 80 | 81 | // Setup transform through projRef and Keywordlist 82 | SpacingType defSpacing = m_RefImagePtr->GetSignedSpacing(); 83 | defSpacing[0] *= 10; 84 | defSpacing[1] *= 10; 85 | resampler->SetDisplacementFieldSpacing(defSpacing); 86 | resampler->SetInputKeywordList(reader->GetOutput()->GetImageKeywordlist()); 87 | resampler->SetInputProjectionRef(reader->GetOutput()->GetProjectionRef()); 88 | resampler->SetOutputKeywordList(m_RefImagePtr->GetImageKeywordlist()); 89 | resampler->SetOutputProjectionRef(m_RefImagePtr->GetProjectionRef()); 90 | resampler->SetOutputOrigin(m_RefImagePtr->GetOrigin()); 91 | resampler->SetOutputSpacing(m_RefImagePtr->GetSignedSpacing()); 92 | resampler->SetOutputSize(m_RefImagePtr->GetLargestPossibleRegion().GetSize()); 93 | resampler->SetOutputStartIndex(m_RefImagePtr->GetLargestPossibleRegion().GetIndex()); 94 | 95 | typename NNInterpolatorType::Pointer interpolator = NNInterpolatorType::New(); 96 | resampler->SetInterpolator(interpolator); 97 | 98 | resamplers.push_back(resampler); 99 | 100 | mosaicFilter->PushBackInput(resampler->GetOutput()); 101 | } 102 | else 103 | { 104 | mosaicFilter->PushBackInput(reader->GetOutput()); 105 | } 106 | } 107 | else 108 | { 109 | // itkWarningMacro(<<"Unable to read file " << sfilename); 110 | } 111 | 112 | } 113 | 114 | if (m_UseReferenceImage) 115 | { 116 | mosaicFilter->SetOutputOrigin(m_RefImagePtr->GetOrigin()); 117 | mosaicFilter->SetOutputSpacing(m_RefImagePtr->GetSignedSpacing()); 118 | mosaicFilter->SetOutputSize(m_RefImagePtr->GetLargestPossibleRegion().GetSize()); 119 | } 120 | else 121 | { 122 | mosaicFilter->SetOutputOrigin(m_OutputOrigin); 123 | mosaicFilter->SetOutputSpacing(m_OutputSpacing); 124 | mosaicFilter->SetOutputSize(m_OutputSize); 125 | } 126 | mosaicFilter->SetAutomaticOutputParametersComputation(false); 127 | 128 | castFilter->SetInput(mosaicFilter->GetOutput()); 129 | 130 | castFilter->GraftOutput( this->GetOutput() ); 131 | castFilter->UpdateOutputInformation(); 132 | this->GraftOutput( castFilter->GetOutput() ); 133 | } 134 | 135 | template 136 | void 137 | MosaicFromDirectoryHandler 138 | ::GenerateData() 139 | { 140 | castFilter->GraftOutput( this->GetOutput() ); 141 | castFilter->Update(); 142 | this->GraftOutput( castFilter->GetOutput() ); 143 | } 144 | 145 | } // end namespace otb 146 | 147 | #endif /* MODULES_REMOTE_OTB_MosaicFromDirectoryHandler_INCLUDE_OTBMosaicFromDirectoryHandler_HXX_ */ 148 | -------------------------------------------------------------------------------- /include/otbStreamingMosaicFilterWithBlendingBase.h: -------------------------------------------------------------------------------- 1 | #ifndef __StreamingMosaicFilterWithBlendingBase_H 2 | #define __StreamingMosaicFilterWithBlendingBase_H 3 | 4 | #include "otbStreamingMosaicFilterBase.h" 5 | #include "itkNearestNeighborInterpolateImageFunction.h" 6 | #include "otbStreamingTraits.h" 7 | 8 | namespace otb 9 | { 10 | /** \class StreamingMosaicFilterWithBlendingBase 11 | * \brief Base class for mosaic filters with blending 12 | * 13 | * Input must be couples of images: one image (e.g. otb::VectorImage) and 14 | * one distance image (e.g. otb::Image) which represents the distance between 15 | * a pixel an the edge of the image. 16 | * This distance image will be then used to compute the blending of the input images. 17 | * Two parameters can be set: 18 | * -Distance image interpolator: explicit 19 | * -Distance image offset: this value is added to the interpolated distance image 20 | * value, which allows to create a margin around the edges 21 | * of the image (i.e. around the 0-value distance image contour) 22 | * 23 | * Support streaming 24 | * 25 | * \ingroup OTBMosaic 26 | */ 27 | template 28 | class ITK_EXPORT StreamingMosaicFilterWithBlendingBase : public otb::StreamingMosaicFilterBase 31 | { 32 | public: 33 | 34 | /** Standard class typedef */ 35 | typedef StreamingMosaicFilterWithBlendingBase Self; 36 | typedef otb::StreamingMosaicFilterBase Superclass; 37 | typedef itk::SmartPointer Pointer; 38 | typedef itk::SmartPointer ConstPointer; 39 | 40 | /** Runtime information support. */ 41 | itkTypeMacro(StreamingMosaicFilterWithBlendingBase, StreamingMosaicFilterBase); 42 | 43 | /** Distance image typedefs */ 44 | typedef TDistanceImage DistanceImageType; 45 | typedef typename DistanceImageType::Pointer DistanceImagePointer; 46 | typedef typename DistanceImageType::ConstPointer DistanceImageConstPointer; 47 | typedef typename DistanceImageType::PointType DistanceImagePointType; 48 | typedef typename DistanceImageType::PixelType DistanceImagePixelType; 49 | typedef typename DistanceImageType::InternalPixelType 50 | DistanceImageInternalPixelType; 51 | typedef typename itk::InterpolateImageFunction 52 | DistanceImageInterpolatorType; 53 | typedef typename itk::LinearInterpolateImageFunction 54 | DistanceImageDefaultInterpolatorType; 55 | typedef typename DistanceImageInterpolatorType::Pointer 56 | DistanceImageInterpolatorPointer; 57 | typedef typename DistanceImageType::RegionType DistanceImageRegionType; 58 | 59 | /** Distance offset accessors */ 60 | itkSetMacro(DistanceOffset, DistanceImageInternalPixelType); 61 | itkGetMacro(DistanceOffset, DistanceImageInternalPixelType); 62 | 63 | /** Set/Get the distance interpolator function. */ 64 | itkSetObjectMacro(DistanceInterpolator, DistanceImageInterpolatorType ); 65 | itkGetObjectMacro(DistanceInterpolator, DistanceImageInterpolatorType ); 66 | 67 | /** Method to add one image 68 | * Two images are required 69 | * -1 input image (must be TInputImage type) 70 | * -1 input distance image (must be TDistanceImage: distance to the edges of the image) 71 | */ 72 | void PushBackInputs(const TInputImage * image, const TDistanceImage * distance) 73 | { 74 | this->PushBackInput(const_cast(image) ); 75 | this->PushBackInput(const_cast(distance) ); 76 | } 77 | 78 | /** Prepare interpolators, valid regions, and input images pointers */ 79 | virtual void PrepareDistanceImageAccessors(typename std::vector& currentDistanceImage, 80 | typename std::vector& distanceInterpolator); 81 | 82 | protected: 83 | StreamingMosaicFilterWithBlendingBase(); 84 | ~StreamingMosaicFilterWithBlendingBase() { 85 | } 86 | 87 | /* Overrided methods */ 88 | virtual void AddUsedInputImageIndex(unsigned int inputImageIndex); 89 | 90 | virtual unsigned int GetNumberOfInputImages(); 91 | 92 | virtual unsigned int GetUsedInputImageIndice(unsigned int i){ 93 | return 0.5 * Superclass::GetUsedInputImageIndice(i); 94 | } 95 | 96 | private: 97 | 98 | StreamingMosaicFilterWithBlendingBase(const Self&); //purposely not 99 | // implemented 100 | void operator=(const Self&); //purposely not 101 | // implemented 102 | 103 | DistanceImageInternalPixelType m_DistanceOffset; // distance offset 104 | DistanceImageInterpolatorPointer m_DistanceInterpolator; // distance image 105 | // interpolator 106 | 107 | }; // end of class 108 | 109 | } // end namespace itk 110 | 111 | #ifndef OTB_MANUAL_INSTANTIATION 112 | #include "otbStreamingMosaicFilterWithBlendingBase.txx" 113 | #endif 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /include/otbStreamingLargeFeatherMosaicFilter.h: -------------------------------------------------------------------------------- 1 | #ifndef __StreamingLargeFeatherMosaicFilter_H 2 | #define __StreamingLargeFeatherMosaicFilter_H 3 | 4 | #include "otbStreamingMosaicFilterWithBlendingBase.h" 5 | #include "itkLinearInterpolateImageFunction.h" 6 | 7 | namespace otb 8 | { 9 | /** \class StreamingLargeFeatherMosaicFilter 10 | * \brief Computes the mosaic of an input images set using feathering technique. 11 | * The output is a nice seamless mosaic. Images are all added-weighted on all 12 | * overlapping areas. This could give nice results for perfectly aligned 13 | * images but can also cause blur on misaligned overlaps. 14 | * 15 | * Inputs are images and distance images. Both needs to be added with the PushBackInputs() method. 16 | * 17 | * Support streaming 18 | * 19 | * The pixels must support the operator ==, +, /, etc. 20 | * The "no data value", output spacing, interpolator can be chosen. 21 | * 22 | * TODO: 23 | * -maybe change containers from std::vector to itk::something? 24 | * 25 | * \ingroup OTBMosaic 26 | */ 27 | template 28 | class ITK_EXPORT StreamingLargeFeatherMosaicFilter : 29 | public StreamingMosaicFilterWithBlendingBase 30 | { 31 | public: 32 | 33 | /** Standard Self typedef */ 34 | typedef StreamingLargeFeatherMosaicFilter Self; 35 | typedef StreamingMosaicFilterWithBlendingBase Superclass; 37 | typedef itk::SmartPointer Pointer; 38 | typedef itk::SmartPointer 39 | ConstPointer; 40 | 41 | /** Method for creation through the object factory. */ 42 | itkNewMacro(Self); 43 | 44 | /** Runtime information support. */ 45 | itkTypeMacro(StreamingLargeFeatherMosaicFilter, StreamingMosaicFilterBlendingBase); 46 | 47 | /** Input image typedefs. */ 48 | typedef typename Superclass::InputImageType InputImageType; 49 | typedef typename Superclass::InputImagePointer InputImagePointer; 50 | typedef typename Superclass::InputImagePointType InputImagePointType; 51 | typedef typename Superclass::InputImagePixelType InputImagePixelType; 52 | typedef typename Superclass::InputImageIndexType InputImageIndexType; 53 | typedef typename Superclass::InputImageSizeType InputImageSizeType; 54 | typedef typename Superclass::InputImageSpacingType InputImageSpacingType; 55 | typedef typename Superclass::InputImageInternalPixelType InputImageInternalPixelType; 56 | typedef typename Superclass::InputImageRegionType InputImageRegionType; 57 | 58 | /** Output image typedefs. */ 59 | typedef typename Superclass::OutputImageType OutputImageType; 60 | typedef typename Superclass::OutputImagePointer OutputImagePointer; 61 | typedef typename Superclass::OutputImagePointType OutputImagePointType; 62 | typedef typename Superclass::OutputImagePixelType OutputImagePixelType; 63 | typedef typename Superclass::OutputImageIndexType OutputImageIndexType; 64 | typedef typename Superclass::OutputImageSizeType OutputImageSizeType; 65 | typedef typename Superclass::OutputImageSpacingType OutputImageSpacingType; 66 | typedef typename Superclass::OutputImageInternalPixelType OutputImageInternalPixelType; 67 | typedef typename Superclass::OutputImageRegionType OutputImageRegionType; 68 | 69 | /** Internal computing typedef support. */ 70 | typedef typename Superclass::InternalValueType InternalValueType; 71 | typedef typename Superclass::ContinuousIndexType ContinuousIndexType; 72 | typedef typename Superclass::InterpolatorType InterpolatorType; 73 | typedef typename Superclass::InterpolatorPointerType InterpolatorPointerType; 74 | typedef typename Superclass::DefaultInterpolatorType DefaultInterpolatorType; 75 | typedef typename Superclass::InternalImageType InternalImageType; 76 | typedef typename Superclass::InternalPixelType InternalPixelType; 77 | typedef typename Superclass::IteratorType IteratorType; 78 | typedef typename Superclass::ConstIteratorType ConstIteratorType; 79 | typedef typename Superclass::StreamingTraitsType StreamingTraitsType; 80 | 81 | /** Distance image typedefs */ 82 | typedef TDistanceImage DistanceImageType; 83 | typedef typename Superclass::DistanceImagePointer DistanceImagePointer; 84 | typedef typename Superclass::DistanceImageConstPointer DistanceImageConstPointer; 85 | typedef typename Superclass::DistanceImagePointType DistanceImagePointType; 86 | typedef typename Superclass::DistanceImagePixelType DistanceImagePixelType; 87 | typedef typename Superclass::DistanceImageInternalPixelType DistanceImageInternalPixelType; 88 | typedef typename Superclass::DistanceImageInterpolatorType DistanceImageInterpolatorType; 89 | typedef typename Superclass::DistanceImageDefaultInterpolatorType DistanceImageDefaultInterpolatorType; 90 | typedef typename Superclass::DistanceImageInterpolatorPointer DistanceImageInterpolatorPointer; 91 | 92 | protected: 93 | StreamingLargeFeatherMosaicFilter() { 94 | } 95 | 96 | virtual ~StreamingLargeFeatherMosaicFilter() { 97 | } 98 | 99 | /** Overrided method */ 100 | virtual void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId ); 101 | 102 | }; // end of class 103 | 104 | } // end namespace otb 105 | 106 | #ifndef OTB_MANUAL_INSTANTIATION 107 | #include "otbStreamingLargeFeatherMosaicFilter.txx" 108 | #endif 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /include/otbQuadraticallyConstrainedSimpleSolver.h: -------------------------------------------------------------------------------- 1 | #ifndef QuadraticallyConstrainedSimpleSolver_H_ 2 | #define QuadraticallyConstrainedSimpleSolver_H_ 3 | 4 | #include "itkObjectFactory.h" 5 | #include "itkLightObject.h" 6 | #include "itkNumericTraits.h" 7 | #include 8 | #include "vnl/algo/vnl_solve_qp.h" 9 | 10 | namespace otb { 11 | 12 | /** 13 | * \class QuadraticallyConstrainedSimpleSolver 14 | * \brief Solves the optimisation problem for radiometric harmonisation of multiple 15 | * overlapping images. 16 | * 17 | * This solver inputs statistics of the overlapping images, and produces a 18 | * zero-y intercept linear correction model. Various cost functions can be 19 | * employed: RMSE based, Mean based, Mean+Standard deviation based, and Mean 20 | * + weighted Standard deviation bases. 21 | * 22 | * Inputs: 23 | * -N x N Matrix of mean of overlaps ij 24 | * -N x N Matrix of standard deviation of overlaps ij 25 | * -N x N Matrix of area of overlaps ij 26 | * -N x N Matrix of mean of pixels products of overlaps ij 27 | * 28 | * For all i and j, m_{ij} = stats of image i in overlap ij 29 | * 30 | * Output: 31 | * N x 1 Vector of scales to apply to images 32 | * 33 | * For more details, see Cresson, Remi, and Nathalie Saint-Geours. 34 | * "Natural color satellite image mosaicking using quadratic programming in decorrelated color space." 35 | * IEEE Journal of Selected Topics in Applied Earth Observations and Remote Sensing 8.8 (2015): 4151-4162. 36 | * 37 | * https://doi.org/10.1109/JSTARS.2015.2449233 38 | * https://hal.archives-ouvertes.fr/hal-01373314/file/cresson2015.pdf 39 | * 40 | * \ingroup OTBMosaic 41 | */ 42 | 43 | template 44 | class ITK_EXPORT QuadraticallyConstrainedSimpleSolver : public itk::LightObject 45 | { 46 | public: 47 | 48 | /** Standard class typedef */ 49 | typedef QuadraticallyConstrainedSimpleSolver Self; 50 | typedef itk::LightObject Superclass; 51 | typedef itk::SmartPointer Pointer; 52 | typedef itk::SmartPointer ConstPointer; 53 | 54 | /** Runtime information support. */ 55 | itkTypeMacro(QuadraticallyConstrainedSimpleSolver, LightObject); 56 | 57 | /** Method for creation through the object factory. */ 58 | itkNewMacro(Self); 59 | 60 | /** Typedefs */ 61 | typedef vnl_matrix RealMatrixType; 62 | typedef vnl_vector RealVectorType; 63 | typedef vnl_matrix DoubleMatrixType; 64 | typedef vnl_vector DoubleVectorType; 65 | typedef std::vector ListIndexType; 66 | 67 | /** Enum for objective function type */ 68 | enum ObjectiveFunctionType 69 | { 70 | Cost_Function_rmse, // Root mean square error based 71 | Cost_Function_musig, // Mean and standard deviation based 72 | Cost_Function_mu, // Mean based 73 | Cost_Function_weighted_musig // Mean and weighted standard deviation based 74 | }; 75 | 76 | /** Mean-in-overlaps matrix */ 77 | void SetMeanInOverlaps(const RealMatrixType & matrix) { m_MeanInOverlaps = RealMatrixType(matrix); } 78 | const RealMatrixType GetMeanInOverlaps() { return m_MeanInOverlaps; } 79 | 80 | /** Standard-deviation-in-overlaps matrix */ 81 | void SetStandardDeviationInOverlaps(const RealMatrixType & matrix) { m_StandardDeviationInOverlaps = RealMatrixType(matrix); } 82 | const RealMatrixType GetStandardDeviationInOverlaps() { return m_StandardDeviationInOverlaps; } 83 | 84 | /** Area-in-overlaps matrix */ 85 | void SetAreaInOverlaps(const RealMatrixType & matrix) { m_AreaInOverlaps = RealMatrixType(matrix); } 86 | const RealMatrixType GetAreaInOverlaps() { return m_AreaInOverlaps; } 87 | 88 | /** Mean-of-pixels-products-in-overlaps matrix */ 89 | void SetMeanOfProductsInOverlaps(const RealMatrixType & matrix) { m_MeanOfProductsInOverlaps = RealMatrixType(matrix); } 90 | const RealMatrixType GetMeanOfProductsInOverlaps() { return m_MeanOfProductsInOverlaps; } 91 | 92 | /** Output correction model */ 93 | const RealVectorType GetOutputCorrectionModel() { return m_OutputCorrectionModel; } 94 | 95 | /** 96 | * STD weight in harmonization 97 | * if value is near 0, importance is accorded to MEAN 98 | * if value is 1, importance is the same than MEAN 99 | * if value is higher than 1, importance is accorder to STD 100 | */ 101 | void SetWeightOfStandardDeviationTerm(ValueType weight) { m_WeightOfStandardDeviationTerm = weight; } 102 | ValueType GetWeightOfStandardDeviationTerm() { return m_WeightOfStandardDeviationTerm; } 103 | 104 | /** Solving routine */ 105 | void Solve(); 106 | 107 | /** Set the cost function type */ 108 | void SetMeanBased() { oft = Cost_Function_mu; } 109 | void SetMeanAndStandardDeviationBased() { oft = Cost_Function_musig; } 110 | void SetRMSEBased() { oft = Cost_Function_rmse; } 111 | void SetWeightedMeanAndStandardDeviationBased() { oft = Cost_Function_weighted_musig; } 112 | 113 | protected: 114 | 115 | QuadraticallyConstrainedSimpleSolver(); 116 | virtual ~QuadraticallyConstrainedSimpleSolver(); 117 | 118 | private: 119 | 120 | // Check inputs 121 | void CheckInputs(void) const; 122 | 123 | // Deep First Search 124 | void DFS(std::vector & marked, unsigned int s) const; 125 | 126 | // Compute the objective matrix 127 | const DoubleMatrixType GetQuadraticObjectiveMatrix(const DoubleMatrixType & areas, 128 | const DoubleMatrixType & means, const DoubleMatrixType & stds, const DoubleMatrixType & mops); 129 | 130 | // Extract a sub matrix from indices list 131 | const DoubleMatrixType ExtractMatrix(const RealMatrixType & mat, const ListIndexType & idx); 132 | 133 | // Input 134 | RealMatrixType m_MeanInOverlaps; 135 | RealMatrixType m_StandardDeviationInOverlaps; 136 | RealMatrixType m_AreaInOverlaps; 137 | RealMatrixType m_MeanOfProductsInOverlaps; 138 | 139 | // Params 140 | ValueType m_WeightOfStandardDeviationTerm; // could be manually tuned for different results 141 | 142 | // Output correction models 143 | RealVectorType m_OutputCorrectionModel; 144 | 145 | // objective funciton type (enum) 146 | ObjectiveFunctionType oft; 147 | 148 | }; 149 | 150 | } /* namespace otb */ 151 | #ifndef OTB_MANUAL_INSTANTIATION 152 | #include "otbQuadraticallyConstrainedSimpleSolver.txx" 153 | #endif 154 | #endif /* QuadraticallyConstrainedSimpleSolver_H_ */ 155 | -------------------------------------------------------------------------------- /include/otbStreamingLargeFeatherMosaicFilter.txx: -------------------------------------------------------------------------------- 1 | #ifndef __StreamingLargeFeatherMosaicFilter_txx 2 | #define __StreamingLargeFeatherMosaicFilter_txx 3 | 4 | #include "otbStreamingLargeFeatherMosaicFilter.h" 5 | 6 | namespace otb { 7 | 8 | /** 9 | * Processing 10 | */ 11 | template 12 | void 13 | StreamingLargeFeatherMosaicFilter 14 | ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) 15 | { 16 | 17 | // Debug info 18 | itkDebugMacro(<<"Actually executing thread " << threadId << " in region " << outputRegionForThread); 19 | 20 | // Support progress methods/callbacks 21 | itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels() ); 22 | 23 | // Get output pointer 24 | OutputImageType * mosaicImage = this->GetOutput(); 25 | 26 | // Get number of used inputs 27 | const unsigned int nbOfUsedInputImages = Superclass::GetNumberOfUsedInputImages(); 28 | 29 | // Get number of bands 30 | const unsigned int nBands = Superclass::GetNumberOfBands(); 31 | 32 | // Iterate through the thread region 33 | IteratorType outputIt(mosaicImage, outputRegionForThread); 34 | 35 | // Prepare input pointers, interpolators, and valid regions (input images) 36 | typename std::vector currentImage; 37 | typename std::vector interp; 38 | Superclass::PrepareImageAccessors(currentImage, interp); 39 | 40 | // Prepare input pointers, interpolators, and valid regions (distances images) 41 | typename std::vector currentDistanceImage; 42 | typename std::vector distanceInterpolator; 43 | Superclass::PrepareDistanceImageAccessors(currentDistanceImage, distanceInterpolator); 44 | 45 | // Temporary thread region (from input) 46 | InputImageRegionType threadRegionInCurrentImage; 47 | 48 | // Temporary pixels 49 | InternalPixelType interpolatedMathPixel, tempOutputPixel; 50 | interpolatedMathPixel.SetSize(nBands); 51 | tempOutputPixel.SetSize(nBands); 52 | 53 | InputImagePixelType interpolatedPixel; 54 | InternalValueType pixelValue, distanceImagePixel, sumDistances; 55 | bool isDataInCurrentOutputPixel; 56 | 57 | // Temporary coordinates 58 | OutputImagePointType geoPoint; 59 | 60 | unsigned int band, i; 61 | 62 | for ( outputIt.GoToBegin(); !outputIt.IsAtEnd(); ++outputIt ) 63 | { 64 | // Current pixel --> Geographical point 65 | mosaicImage->TransformIndexToPhysicalPoint (outputIt.GetIndex(), geoPoint) ; 66 | 67 | // Presence of at least one non-null pixel of the used input images 68 | isDataInCurrentOutputPixel = false; 69 | sumDistances = 0.0; 70 | 71 | // Transition pixels 72 | tempOutputPixel.Fill(0.0); 73 | 74 | // Loop on used input images 75 | for (i = 0 ; i < nbOfUsedInputImages ; i++) 76 | { 77 | 78 | // Check if the point is inside the transformed thread region 79 | // (i.e. the region in the current input image which match the thread 80 | // region) 81 | if (interp[i]->IsInsideBuffer(geoPoint) ) 82 | { 83 | // Compute the interpolated pixel value 84 | interpolatedPixel = interp[i]->Evaluate(geoPoint); 85 | 86 | // Check that interpolated pixel is not empty 87 | if (Superclass::IsPixelNotEmpty(interpolatedPixel) ) 88 | { 89 | // Get the alpha channel pixel value for this channel 90 | if (distanceInterpolator[i]->IsInsideBuffer(geoPoint) ) 91 | { 92 | distanceImagePixel = distanceInterpolator[i]->Evaluate(geoPoint); 93 | distanceImagePixel -= Superclass::GetDistanceOffset(); 94 | 95 | if (distanceImagePixel>0 ) 96 | { 97 | // Update the presence of data for this pixel 98 | isDataInCurrentOutputPixel = true; 99 | 100 | // sum coef 101 | sumDistances += distanceImagePixel; 102 | 103 | /* 104 | * 1. Cast the interpolated pixel into math pixel type 105 | * 2. Multiply by feather coef 106 | * 3. Compute sum 107 | */ 108 | const unsigned int inputImageIndex = Superclass::GetUsedInputImageIndice(i); 109 | for (band = 0 ; band < nBands ; band++) 110 | { 111 | // Cast the interpolated pixel to a internal pixel type 112 | interpolatedMathPixel[band] = static_cast(interpolatedPixel[band]); 113 | 114 | // Shift-scale the value 115 | if (this->GetShiftScaleInputImages() ) 116 | { 117 | this->ShiftScaleValue(interpolatedMathPixel[band], inputImageIndex, band); 118 | } 119 | 120 | // Multiply by Feather coef 121 | interpolatedMathPixel[band] *= distanceImagePixel; 122 | 123 | // Summing 124 | tempOutputPixel[band] += interpolatedMathPixel[band]; 125 | 126 | } // loop on pixel bands 127 | 128 | } // distance > 0 129 | } // Interpolated distance pixel not empty 130 | else 131 | { 132 | itkWarningMacro(<<"Unable to evaluate distance at point " << geoPoint); 133 | } 134 | } // Interpolated pixel is not empty 135 | } // point inside buffer 136 | } // next image 137 | 138 | // Prepare output pixel 139 | OutputImagePixelType outputPixel(Superclass::GetNoDataOutputPixel() ); 140 | 141 | if (isDataInCurrentOutputPixel) 142 | { 143 | 144 | // Compute output pixel 145 | for (band = 0 ; band < nBands ; band++) 146 | { 147 | 148 | // Normalize & cast 149 | pixelValue = tempOutputPixel[band] / sumDistances; 150 | Superclass::NormalizePixelValue(pixelValue); 151 | outputPixel[band] = static_cast(pixelValue); 152 | } 153 | 154 | } // if data presence 155 | 156 | // Update output pixel value 157 | outputIt.Set(outputPixel); 158 | 159 | // Update progress 160 | progress.CompletedPixel(); 161 | 162 | } // next output pixel 163 | 164 | } 165 | 166 | } // end namespace gtb 167 | 168 | #endif 169 | -------------------------------------------------------------------------------- /include/otbStreamingFeatherMosaicFilter.h: -------------------------------------------------------------------------------- 1 | #ifndef __StreamingFeatherMosaicFilter_H 2 | #define __StreamingFeatherMosaicFilter_H 3 | 4 | #include "otbStreamingMosaicFilterWithBlendingBase.h" 5 | #include "itkLinearInterpolateImageFunction.h" 6 | 7 | namespace otb 8 | { 9 | /** \class StreamingFeatherMosaicFilter 10 | * \brief Computes the mosaic of an input images set using 11 | * feathering technique. The output is a nice seamless mosaic. 12 | * 13 | * Images are added-weighted in a one-by-one fashion, blended 14 | * from the images boundaries to a specified transition distance. 15 | * The smoothness of the transition curve can be set (exponent). 16 | * Feathering is performed with respect to the input images order. 17 | * 18 | * Inputs are images and distance images. Both needs to be added with the PushBackInputs() method. 19 | * 20 | * Support streaming 21 | * 22 | * The pixels must support the operator ==, +, /, etc. 23 | * The "no data value", output spacing, interpolator can be chosen. 24 | * 25 | * TODO: 26 | * -change containers from std::vector to itk::something 27 | * -move container class to private 28 | * -create accessors 29 | * 30 | * \ingroup OTBMosaic 31 | */ 32 | template 33 | class ITK_EXPORT StreamingFeatherMosaicFilter : 34 | public StreamingMosaicFilterWithBlendingBase 35 | { 36 | public: 37 | 38 | /** Standard Self typedef */ 39 | typedef StreamingFeatherMosaicFilter Self; 40 | typedef StreamingMosaicFilterWithBlendingBase Superclass; 42 | typedef itk::SmartPointer Pointer; 43 | typedef itk::SmartPointer 44 | ConstPointer; 45 | 46 | /** Method for creation through the object factory. */ 47 | itkNewMacro(Self); 48 | 49 | /** Runtime information support. */ 50 | itkTypeMacro(StreamingFeatherMosaicFilter, StreamingMosaicFilterWithBlendingBase); 51 | 52 | /** Input image typedefs. */ 53 | typedef typename Superclass::InputImageType InputImageType; 54 | typedef typename Superclass::InputImagePointer InputImagePointer; 55 | typedef typename Superclass::InputImagePointType InputImagePointType; 56 | typedef typename Superclass::InputImagePixelType InputImagePixelType; 57 | typedef typename Superclass::InputImageIndexType InputImageIndexType; 58 | typedef typename Superclass::InputImageSizeType InputImageSizeType; 59 | typedef typename Superclass::InputImageSpacingType InputImageSpacingType; 60 | typedef typename Superclass::InputImageInternalPixelType InputImageInternalPixelType; 61 | typedef typename Superclass::InputImageRegionType InputImageRegionType; 62 | 63 | /** Output image typedefs. */ 64 | typedef typename Superclass::OutputImageType OutputImageType; 65 | typedef typename Superclass::OutputImagePointer OutputImagePointer; 66 | typedef typename Superclass::OutputImagePointType OutputImagePointType; 67 | typedef typename Superclass::OutputImagePixelType OutputImagePixelType; 68 | typedef typename Superclass::OutputImageIndexType OutputImageIndexType; 69 | typedef typename Superclass::OutputImageSizeType OutputImageSizeType; 70 | typedef typename Superclass::OutputImageSpacingType OutputImageSpacingType; 71 | typedef typename Superclass::OutputImageInternalPixelType OutputImageInternalPixelType; 72 | typedef typename Superclass::OutputImageRegionType OutputImageRegionType; 73 | 74 | /** Internal computing typedef support. */ 75 | typedef typename Superclass::InternalValueType InternalValueType; 76 | typedef typename Superclass::ContinuousIndexType ContinuousIndexType; 77 | typedef typename Superclass::InterpolatorType InterpolatorType; 78 | typedef typename Superclass::InterpolatorPointerType InterpolatorPointerType; 79 | typedef typename Superclass::DefaultInterpolatorType DefaultInterpolatorType; 80 | typedef typename Superclass::InternalImageType InternalImageType; 81 | typedef typename Superclass::InternalPixelType InternalPixelType; 82 | typedef typename Superclass::IteratorType IteratorType; 83 | typedef typename Superclass::ConstIteratorType ConstIteratorType; 84 | typedef typename Superclass::StreamingTraitsType StreamingTraitsType; 85 | 86 | /** Distance image typedefs */ 87 | typedef TDistanceImage DistanceImageType; 88 | typedef typename DistanceImageType::Pointer DistanceImagePointer; 89 | typedef typename DistanceImageType::ConstPointer DistanceImageConstPointer; 90 | typedef typename DistanceImageType::PointType DistanceImagePointType; 91 | typedef typename DistanceImageType::PixelType DistanceImagePixelType; 92 | typedef typename DistanceImageType::InternalPixelType DistanceImageInternalPixelType; 93 | typedef typename DistanceImageType::RegionType DistanceImageRegionType; 94 | typedef typename itk::InterpolateImageFunction 95 | DistanceImageInterpolatorType; 96 | typedef typename itk::LinearInterpolateImageFunction 97 | DistanceImageDefaultInterpolatorType; 98 | typedef typename DistanceImageInterpolatorType::Pointer DistanceImageInterpolatorPointer; 99 | 100 | /** Feathering transition distance accessors */ 101 | itkSetMacro(FeatheringTransitionDistance, InternalValueType); 102 | itkGetMacro(FeatheringTransitionDistance, InternalValueType); 103 | 104 | /** Feathering transition smoothness accessors */ 105 | itkSetMacro(FeatheringSmoothness, InternalValueType); 106 | itkGetMacro(FeatheringSmoothness, InternalValueType); 107 | 108 | protected: 109 | StreamingFeatherMosaicFilter(); 110 | virtual ~StreamingFeatherMosaicFilter() { 111 | } 112 | 113 | /** Overrided methods */ 114 | virtual void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId ); 115 | 116 | private: 117 | InternalValueType m_FeatheringTransitionDistance; // feathering transition 118 | // distance 119 | InternalValueType m_FeatheringSmoothness; // feathering exponent 120 | 121 | }; // end of class 122 | 123 | } // end namespace otb 124 | 125 | #ifndef OTB_MANUAL_INSTANTIATION 126 | #include "otbStreamingFeatherMosaicFilter.txx" 127 | #endif 128 | 129 | #endif 130 | -------------------------------------------------------------------------------- /include/otbStreamingFeatherMosaicFilter.txx: -------------------------------------------------------------------------------- 1 | #ifndef __StreamingFeatherMosaicFilter_txx 2 | #define __StreamingFeatherMosaicFilter_txx 3 | 4 | #include "otbStreamingFeatherMosaicFilter.h" 5 | 6 | namespace otb { 7 | 8 | template 9 | StreamingFeatherMosaicFilter 10 | ::StreamingFeatherMosaicFilter(){ 11 | m_FeatheringTransitionDistance = 500; 12 | m_FeatheringSmoothness = 1.5; 13 | } 14 | 15 | /** 16 | * Processing 17 | */ 18 | template 19 | void 20 | StreamingFeatherMosaicFilter 21 | ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) 22 | { 23 | 24 | // Debug info 25 | itkDebugMacro(<<"Actually executing thread " << threadId << " in region " << outputRegionForThread); 26 | 27 | // Support progress methods/callbacks 28 | itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels() ); 29 | 30 | // Get output pointer 31 | OutputImageType * mosaicImage = this->GetOutput(); 32 | 33 | // Get number of used inputs 34 | const unsigned int nbOfUsedInputImages = Superclass::GetNumberOfUsedInputImages(); 35 | 36 | // Get number of bands 37 | const unsigned int nBands = Superclass::GetNumberOfBands(); 38 | 39 | // Iterate through the thread region 40 | IteratorType outputIt(mosaicImage, outputRegionForThread); 41 | 42 | // Prepare input pointers, interpolators, and valid regions (input images) 43 | typename std::vector currentImage; 44 | typename std::vector interp; 45 | Superclass::PrepareImageAccessors(currentImage, interp); 46 | 47 | // Prepare input pointers, interpolators, and valid regions (distances images) 48 | typename std::vector currentDistanceImage; 49 | typename std::vector distanceInterpolator; 50 | Superclass::PrepareDistanceImageAccessors(currentDistanceImage, distanceInterpolator); 51 | 52 | // Temporary pixels 53 | InternalPixelType interpolatedMathPixel, tempOutputPixel; 54 | interpolatedMathPixel.SetSize(nBands); 55 | tempOutputPixel.SetSize(nBands); 56 | 57 | InputImagePixelType interpolatedPixel; 58 | InternalValueType pixelValue, distanceImagePixel; 59 | bool isDataInCurrentOutputPixel; 60 | 61 | // Temporary coordinates 62 | OutputImagePointType geoPoint; 63 | 64 | unsigned int band, i; 65 | 66 | for ( outputIt.GoToBegin(); !outputIt.IsAtEnd(); ++outputIt ) 67 | { 68 | // Current pixel --> Geographical point 69 | mosaicImage->TransformIndexToPhysicalPoint (outputIt.GetIndex(), geoPoint) ; 70 | 71 | // Presence of at least one non-null pixel of the used input images 72 | isDataInCurrentOutputPixel = false; 73 | 74 | // Transition pixels 75 | tempOutputPixel.Fill(0.0); 76 | 77 | // Loop on used input images 78 | for (i = 0 ; i < nbOfUsedInputImages ; i++) 79 | { 80 | 81 | // Check if the point is inside the transformed thread region 82 | // (i.e. the region in the current input image which match the thread 83 | // region) 84 | if (interp[i]->IsInsideBuffer(geoPoint) ) 85 | { 86 | 87 | // Compute the interpolated pixel value 88 | interpolatedPixel = interp[i]->Evaluate(geoPoint); 89 | 90 | // Check that interpolated pixel is not empty 91 | if (Superclass::IsPixelNotEmpty(interpolatedPixel) ) 92 | { 93 | 94 | // Geographical point (current pixel) --> Continuous index (from 95 | // current input image) 96 | if (distanceInterpolator[i]->IsInsideBuffer(geoPoint) ) 97 | { 98 | distanceImagePixel = distanceInterpolator[i]->Evaluate(geoPoint); 99 | distanceImagePixel -= Superclass::GetDistanceOffset(); 100 | 101 | // Check that the distance is positive (i.e. we are inside the valid 102 | // area of the image) 103 | if (distanceImagePixel> 0 || !isDataInCurrentOutputPixel) 104 | { 105 | 106 | // Two possibility: distance < buffer or not 107 | InternalValueType coef1, coef2; 108 | if (distanceImagePixel(interpolatedPixel[band]); 128 | 129 | // Shift-scale the input pixel value 130 | if (this->GetShiftScaleInputImages() ) 131 | { 132 | this->ShiftScaleValue(interpolatedMathPixel[band], inputImageIndex, band); 133 | } 134 | 135 | // Average-Weight 136 | tempOutputPixel[band] = coef1*interpolatedMathPixel[band] + 137 | coef2*tempOutputPixel[band]; 138 | 139 | } // loop on pixels band 140 | 141 | // Update the presence of data for this pixel 142 | isDataInCurrentOutputPixel = true; 143 | 144 | } // Distance value is positive 145 | 146 | } // Interpolated distance pixel not empty 147 | 148 | else 149 | { 150 | itkWarningMacro(<<"Unable to evaluate distance at point " << geoPoint); 151 | distanceImagePixel = 0; 152 | } 153 | 154 | } // Interpolated pixel is not empty 155 | } // point inside buffer 156 | } // next image 157 | 158 | // Prepare output pixel 159 | OutputImagePixelType outputPixel(Superclass::GetNoDataOutputPixel() ); 160 | 161 | if (isDataInCurrentOutputPixel) 162 | { 163 | 164 | // Compute output pixel 165 | for (band = 0 ; band < nBands ; band++) 166 | { 167 | 168 | // Normalize & cast 169 | pixelValue = tempOutputPixel[band]; 170 | Superclass::NormalizePixelValue(pixelValue); 171 | outputPixel[band] = static_cast(pixelValue); 172 | } 173 | 174 | } // if data presence 175 | 176 | // Update output pixel value 177 | outputIt.Set(outputPixel); 178 | 179 | // Update progress 180 | progress.CompletedPixel(); 181 | 182 | } // next output pixel 183 | 184 | } 185 | 186 | } // end namespace gtb 187 | 188 | #endif 189 | -------------------------------------------------------------------------------- /include/otbStreamingMultibandFeatherMosaicFilter.h: -------------------------------------------------------------------------------- 1 | #ifndef StreamingMultibandFeatherMosaicFilter_H_ 2 | #define StreamingMultibandFeatherMosaicFilter_H_ 3 | 4 | #include "itkImageToImageFilter.h" 5 | #include "otbStreamingMosaicFilterBase.h" 6 | #include "otbStreamingFeatherMosaicFilter.h" 7 | #include "itkSubtractImageFilter.h" 8 | #include "otbSummingFilter.h" 9 | #include "itkMacro.h" 10 | 11 | // For gaussian filtering 12 | #include "itkDiscreteGaussianImageFilter.h" 13 | //#include "itkGPUDiscreteGaussianImageFilter.h" // TODO: Make this happen 14 | #include "otbPerBandVectorImageFilter.h" 15 | 16 | namespace otb 17 | { 18 | 19 | /** \class StreamingMultibandFeatherMosaicFilter 20 | * \brief Computes a nice seamless mosaic using multiband strategy 21 | * 22 | * The filter implements the multiband blending strategy. Laplacian 23 | * of input images is computed, then each frequency is mosaiced using 24 | * a StreamingFeatherMosaicFilter. Finaly the summing of all frequencies 25 | * is performed to get the final mosaic image. 26 | * 27 | * Mandatory inputs : images to mosaic + alpha channels 28 | * 29 | * Output: nice mosaic 30 | * 31 | * \ingroup OTBMosaic 32 | * 33 | */ 34 | template 35 | class ITK_EXPORT StreamingMultibandFeatherMosaicFilter : public otb::StreamingFeatherMosaicFilter 38 | { 39 | public: 40 | 41 | /** Standard Self typedef */ 42 | typedef StreamingMultibandFeatherMosaicFilter Self; 43 | typedef otb::StreamingFeatherMosaicFilter Superclass; 44 | typedef itk::SmartPointer Pointer; 45 | typedef itk::SmartPointer ConstPointer; 46 | 47 | /** Method for creation through the object factory. */ 48 | itkNewMacro(Self); 49 | 50 | /** Runtime information support. */ 51 | itkTypeMacro(StreamingMultibandFeatherMosaicFilter, StreamingFeatherMosaicFilter); 52 | 53 | /** Images typedefs */ 54 | typedef TInputImage ImageType; 55 | typedef typename ImageType::ConstPointer ImageConstPointer; 56 | typedef TDistanceImage DistanceImageType; 57 | typedef typename DistanceImageType::ConstPointer DistanceImageConstPointer; 58 | typedef typename DistanceImageType::PixelType DistanceImageValueType; 59 | typedef TOutputImage OutputImage; 60 | typedef typename OutputImage::SpacingType OutputImageSpacingType; 61 | 62 | /** Gaussian filter typedefs */ 63 | typedef typename TInputImage::InternalPixelType InputImageInternalValueType; 64 | typedef otb::Image SingleImageType; 65 | typedef itk::DiscreteGaussianImageFilter DiscreteGaussianFilterType; 66 | typedef typename DiscreteGaussianFilterType::Pointer DiscreteGaussianFilterPointer; 67 | typedef otb::PerBandVectorImageFilter PerBandFilterType; 68 | typedef typename PerBandFilterType::Pointer PerBandFilterPointer; 69 | 70 | /** Other filters typedefs */ 71 | typedef itk::SubtractImageFilter SubImageFilterType; 72 | typedef typename SubImageFilterType::Pointer SubImageFilterPointer; 73 | typedef otb::StreamingFeatherMosaicFilter MosaicFilterType; 74 | typedef typename MosaicFilterType::Pointer MosaicFilterPointer; 75 | typedef otb::SummingFilter SummingFilterType; 76 | typedef typename SummingFilterType::Pointer SummingFilterPointer; 77 | 78 | /** Accessors for the number of levels */ 79 | itkSetMacro(NumberOfLevels, unsigned int); 80 | itkGetMacro(NumberOfLevels, unsigned int); 81 | 82 | /** Accessors for the first level variance & transition distance */ 83 | itkSetMacro(FirstLevelTransitionDistance, DistanceImageValueType); 84 | itkGetMacro(FirstLevelTransitionDistance, DistanceImageValueType); 85 | itkSetMacro(FirstLevelVariance, double); 86 | itkGetMacro(FirstLevelVariance, double); 87 | 88 | protected: 89 | StreamingMultibandFeatherMosaicFilter(); 90 | virtual ~StreamingMultibandFeatherMosaicFilter() { 91 | } 92 | 93 | virtual void Modified(); 94 | 95 | /** Overrided methods */ 96 | virtual void GenerateData(); 97 | 98 | virtual void GenerateOutputInformation() 99 | { 100 | itkDebugMacro("GenerateOutputInformation"); 101 | 102 | Superclass::GenerateOutputInformation(); 103 | this->Modified(); 104 | } 105 | 106 | private: 107 | StreamingMultibandFeatherMosaicFilter(const Self&); //purposely not 108 | // implemented 109 | void operator=(const Self&); //purposely not 110 | // implemented 111 | 112 | unsigned int m_NumberOfLevels; // number of scales 113 | 114 | /* Variances */ 115 | double m_FirstLevelVariance; // variance of first scale 116 | std::vector m_Variances; // variances values 117 | 118 | /* Transitions parameters */ 119 | DistanceImageValueType m_FirstLevelTransitionDistance; // transition 120 | // distance 121 | // of the 122 | // first 123 | // scale 124 | std::vector m_TransitionDistances; // transition 125 | // distances 126 | // for 127 | // each 128 | // scale 129 | std::vector m_TransitionOffsets; // transition 130 | // offsets 131 | // for 132 | // each 133 | // scale 134 | 135 | /* Internal filters */ 136 | std::vector > m_SubImageFilter; // subtract 137 | // filter 138 | // array 139 | // (2D) 140 | std::vector > m_Filter; // smoothing 141 | // filter 142 | // array 143 | // (2D) 144 | std::vector > m_SingleFilter; // smoothing 145 | // filter 146 | // (per 147 | // band) 148 | // array 149 | // (2D) 150 | std::vector m_MosaicFilter; // mosaicking 151 | // filter 152 | // array 153 | // (1D) 154 | SummingFilterPointer m_SummingFilter; // Summing 155 | // filter 156 | 157 | }; 158 | 159 | } // end namespace gtb 160 | 161 | #include "otbStreamingMultibandFeatherMosaicFilter.txx" 162 | 163 | #endif /* StreamingMultibandFeatherMosaicFilter_H_ */ 164 | -------------------------------------------------------------------------------- /include/otbQuadraticallyConstrainedSimpleSolver.txx: -------------------------------------------------------------------------------- 1 | #ifndef QuadraticallyConstrainedSimpleSolver_txx_ 2 | #define QuadraticallyConstrainedSimpleSolver_txx_ 3 | 4 | #include "otbQuadraticallyConstrainedSimpleSolver.h" 5 | 6 | namespace otb { 7 | 8 | template QuadraticallyConstrainedSimpleSolver 9 | ::QuadraticallyConstrainedSimpleSolver() { 10 | m_WeightOfStandardDeviationTerm = 1.0; 11 | oft = Cost_Function_rmse; 12 | } 13 | 14 | template QuadraticallyConstrainedSimpleSolver 15 | ::~QuadraticallyConstrainedSimpleSolver() { 16 | } 17 | 18 | /* 19 | * Used to check layout topology consistency (Deep First Search) 20 | * 21 | * "m_AreaInOverlaps[i][j]>0" is equivalent to "images i and j are 22 | * overlapping with a non empty intersection (i.e. non null data)" 23 | */ 24 | template 25 | void QuadraticallyConstrainedSimpleSolver 26 | ::DFS(std::vector & marked, unsigned int s) const 27 | { 28 | 29 | // mark the s vertex 30 | marked[s] = true; 31 | 32 | // Get neighborhood 33 | for (unsigned int i = 0 ; i < m_AreaInOverlaps.rows() ; i++) 34 | { 35 | if (s!=i && m_AreaInOverlaps[s][i]>0 && !marked[i]) 36 | { 37 | DFS(marked, i); 38 | } 39 | } 40 | 41 | } 42 | 43 | /* 44 | * Check input matrices dimensions, and layout consistency 45 | */ 46 | template 47 | void QuadraticallyConstrainedSimpleSolver 48 | ::CheckInputs() const { 49 | 50 | // Check area matrix is non empty 51 | const unsigned int n = m_AreaInOverlaps.cols(); 52 | if (n == 0) 53 | { 54 | itkExceptionMacro( << "Input area matrix has 0 elements"); 55 | } 56 | 57 | bool inputMatricesAreValid = true; 58 | 59 | // Check "areas" and "means" matrices size 60 | if ((n != m_AreaInOverlaps.rows()) || (n != m_MeanInOverlaps.cols()) || (n != m_MeanInOverlaps.rows())) 61 | { 62 | inputMatricesAreValid = false; 63 | } 64 | 65 | // Check "std" matrix size 66 | if ((oft == Cost_Function_musig) || (oft==Cost_Function_weighted_musig) || (oft==Cost_Function_rmse)) 67 | { 68 | if ((n != m_StandardDeviationInOverlaps.cols()) || (n != m_StandardDeviationInOverlaps.rows())) 69 | { 70 | inputMatricesAreValid = false; 71 | } 72 | } 73 | 74 | // Check "means of products" matrix size 75 | if (oft == Cost_Function_musig) 76 | { 77 | if ((n != m_MeanOfProductsInOverlaps.cols()) || (n != m_MeanOfProductsInOverlaps.rows())) 78 | { 79 | inputMatricesAreValid = false; 80 | } 81 | } 82 | 83 | if (!inputMatricesAreValid) 84 | { 85 | itkExceptionMacro( << "Input matrices must be square and have the same number of elements."); 86 | } 87 | 88 | 89 | } 90 | 91 | /* 92 | * Compute the objective function 93 | * 94 | * VNL is not sufficient: it has weak solving routines, and can not deal with QP subject to 95 | * a linear equality constraint plus lower limits (that is < and = linear constraints) 96 | * With vnl, we keep it simple and solve only the zero-y intercept linear case 97 | * but sometimes it fails because numerical instabilities. (vnl quadratic routines are not very reliable) 98 | * 99 | * With a good quadratic solver, we could e.g. use a general linear model (Xout = Xin*a+b) 100 | * Unfortunately it can be done with VNL so far. Tested & implemented successfully with 101 | * OOQP (Fastest, o(n)) and Quadprog++ (Fast, o(n)), and CGAL exact type solver (very slow, o(n^a) with a>1) 102 | * but has to rely on external dependencies... 103 | * 104 | */ 105 | template 106 | const typename QuadraticallyConstrainedSimpleSolver::DoubleMatrixType 107 | QuadraticallyConstrainedSimpleSolver 108 | ::GetQuadraticObjectiveMatrix(const DoubleMatrixType & areas, const DoubleMatrixType & means, 109 | const DoubleMatrixType & stds, const DoubleMatrixType & mops) 110 | { 111 | // Set STD matrix weight 112 | ValueType w; 113 | 114 | if (oft == Cost_Function_mu) 115 | { 116 | w = 0.0; 117 | } 118 | if (oft == Cost_Function_musig) 119 | { 120 | w = 1.0; 121 | } 122 | if (oft == Cost_Function_weighted_musig) 123 | { 124 | w = (ValueType) m_WeightOfStandardDeviationTerm; 125 | } 126 | 127 | const unsigned int n = areas.cols(); 128 | 129 | // Temporary matrices H, K, L 130 | DoubleMatrixType H(n,n,0), K(n,n,0), L(n,n,0); 131 | DoubleMatrixType H_RMSE(n,n,0); 132 | for (unsigned int i = 0 ; i < n ; i++) 133 | { 134 | for (unsigned int j = 0 ; j < n ; j++) 135 | { 136 | if (i==j) 137 | { 138 | // Diag (i=j) 139 | for (unsigned int k = 0 ; k < n ; k++) 140 | { 141 | if (i!=k) 142 | { 143 | H[i][j] += areas[i][k] * 144 | (means[i][k]*means[i][k] + w*stds[i][k]* 145 | stds[i][k]); 146 | K[i][j] += areas[i][k] * means[i][k]; 147 | L[i][j] += areas[i][k]; 148 | H_RMSE[i][j] += areas[i][k]* 149 | (means[i][k]*means[i][k]+stds[i][k]* 150 | stds[i][k]); 151 | } 152 | } 153 | } 154 | else 155 | { 156 | // Other than diag (i!=j) 157 | H[i][j] = -areas[i][j] * 158 | (means[i][j]*means[j][i] + w*stds[i][j]* 159 | stds[j][i]); 160 | K[i][j] = -areas[i][j] * means[i][j]; 161 | L[i][j] = -areas[i][j]; 162 | H_RMSE[i][j] = -areas[i][j] * mops[i][j]; 163 | } 164 | } 165 | } 166 | 167 | if (oft == Cost_Function_rmse) 168 | { 169 | H = H_RMSE; 170 | } 171 | 172 | return H; 173 | 174 | } 175 | 176 | /* 177 | * Returns the sub-matrix of mat, composed only by rows/cols in idx 178 | */ 179 | template 180 | const typename QuadraticallyConstrainedSimpleSolver::DoubleMatrixType 181 | QuadraticallyConstrainedSimpleSolver 182 | ::ExtractMatrix(const RealMatrixType & mat, const ListIndexType & idx) 183 | { 184 | unsigned int n = idx.size(); 185 | DoubleMatrixType newMat(n,n,0); 186 | for (unsigned int i = 0 ; i < n ; i++) 187 | { 188 | for (unsigned int j = 0 ; j < n ; j++) 189 | { 190 | unsigned int mat_i = idx[i]; 191 | unsigned int mat_j = idx[j]; 192 | newMat[i][j] = mat[mat_i][mat_j]; 193 | } 194 | } 195 | return newMat; 196 | } 197 | 198 | /* 199 | * QP Solving using vnl 200 | */ 201 | template 202 | void 203 | QuadraticallyConstrainedSimpleSolver 204 | ::Solve() 205 | { 206 | // Check matrices dimensions 207 | CheckInputs(); 208 | 209 | // Display a warning if overlap matrix is null 210 | if (m_AreaInOverlaps.max_value() == 0) 211 | { 212 | itkExceptionMacro("No overlap in images!"); 213 | } 214 | 215 | // Identify the connected components 216 | unsigned int nbOfComponents = m_AreaInOverlaps.rows(); 217 | unsigned int nextVertex = 0; 218 | std::vector< ListIndexType > connectedComponentsIndices; 219 | std::vector markedVertices (nbOfComponents, false); 220 | bool allMarked = false; 221 | while (!allMarked) 222 | { 223 | // Depth First Search starting from nextVertex 224 | std::vector marked (nbOfComponents, false); 225 | DFS(marked, nextVertex); 226 | 227 | // Id the connected component 228 | ListIndexType list; 229 | for (unsigned int i = 0 ; i < nbOfComponents ; i++) 230 | { 231 | if (marked[i]) 232 | { 233 | // Tag the connected component index 234 | list.push_back(i); 235 | markedVertices[i] = true; 236 | } 237 | else if (!markedVertices[i]) 238 | { 239 | // if the i-th vertex is not marked, DFS will start from it next 240 | nextVertex = i; 241 | break; 242 | } 243 | } 244 | connectedComponentsIndices.push_back(list); 245 | 246 | // Check if vertices are all marked 247 | allMarked = true; 248 | for (unsigned int i = 0 ; i < nbOfComponents ; i++) 249 | if (!markedVertices[i]) 250 | allMarked = false; 251 | } 252 | 253 | // Prepare output model 254 | m_OutputCorrectionModel.set_size(nbOfComponents); 255 | m_OutputCorrectionModel.fill(itk::NumericTraits::One); 256 | 257 | // Extract and solve all connected components one by one 258 | if (connectedComponentsIndices.size() > 1) 259 | itkWarningMacro("Seems to be more that one group of overlapping images. Trying to harmonize groups separately."); 260 | 261 | for (unsigned int component = 0 ; component < connectedComponentsIndices.size() ; component++) 262 | { 263 | // Indices list 264 | ListIndexType list = connectedComponentsIndices[component]; 265 | const unsigned int n = list.size(); 266 | 267 | // Extract matrices 268 | DoubleMatrixType sub_areas = ExtractMatrix(m_AreaInOverlaps, list); 269 | DoubleMatrixType sub_means = ExtractMatrix(m_MeanInOverlaps, list); 270 | DoubleMatrixType sub_stdev = ExtractMatrix(m_StandardDeviationInOverlaps, list); 271 | DoubleMatrixType sub_mOfPr = ExtractMatrix(m_MeanOfProductsInOverlaps, list); 272 | 273 | // Objective function 274 | DoubleMatrixType Q = GetQuadraticObjectiveMatrix( 275 | sub_areas, 276 | sub_means, 277 | sub_stdev, 278 | sub_mOfPr); 279 | DoubleVectorType g(n,0); 280 | 281 | // Constraint (Energy conservation) 282 | DoubleMatrixType A(1,n); 283 | DoubleVectorType b(1,0); 284 | for (unsigned int i = 0 ; i < n ; i++) 285 | { 286 | double energy = sub_areas[i][i] * sub_means[i][i]; 287 | b[0] += energy; 288 | A[0][i] = energy; 289 | } 290 | 291 | // Solution 292 | DoubleVectorType x(n,1); 293 | 294 | // Change tol. to 0.01 is a quick hack to avoid numerical instability... 295 | bool solv = vnl_solve_qp_with_non_neg_constraints(Q,g,A,b,x,0.01); 296 | if (solv) 297 | { 298 | for (unsigned int i = 0 ; i < n ; i++) 299 | { 300 | m_OutputCorrectionModel[list[i]] = static_cast( x[i] ); 301 | } 302 | } 303 | else 304 | { 305 | itkWarningMacro( "vnl_solve_qp_with_non_neg_constraints failed for component #" << component ); 306 | } 307 | 308 | } 309 | 310 | } 311 | 312 | } 313 | 314 | #endif 315 | -------------------------------------------------------------------------------- /include/otbStreamingMosaicFilterBase.h: -------------------------------------------------------------------------------- 1 | #ifndef __StreamingMosaicFilterBase_H 2 | #define __StreamingMosaicFilterBase_H 3 | 4 | #include "itkImageToImageFilter.h" 5 | #include "itkNearestNeighborInterpolateImageFunction.h" 6 | #include "otbStreamingTraits.h" 7 | 8 | // No data 9 | #include "otbNoDataHelper.h" 10 | 11 | namespace otb 12 | { 13 | /** \class StreamingMosaicFilterBase 14 | * \brief Base class for mosaic filters. Computes the total extent of 15 | * multiple inputs, and provide routines to compute whether or 16 | * not an input image region must be requested 17 | * 18 | * The otb::StreamingMosaicFilterBase allows to compute what the final 19 | * mosaic of multiple input of otb::VectorImage is, and provide the requested 20 | * regions of input images. There is a shift-scale mode which allows 21 | * to shift-scale input images, which can be usefull e.g. color or 22 | * radiometric harmonization of input set of images. The output 23 | * spacing (SetOuputSpacing()), the start index (SetOutputIndex()) and 24 | * the interpolator (SetInterpolator()) and the origin (SetOrigin()) 25 | * can be set using the method between brackets. 26 | * 27 | * 28 | * \ingroup OTBMosaic 29 | * 30 | **/ 31 | 32 | template 33 | class ITK_EXPORT StreamingMosaicFilterBase : public itk::ImageToImageFilter 34 | { 35 | public: 36 | 37 | /** Standard class typedef */ 38 | typedef StreamingMosaicFilterBase Self; 39 | typedef itk::ImageToImageFilter Superclass; 40 | typedef itk::SmartPointer Pointer; 41 | typedef itk::SmartPointer ConstPointer; 42 | 43 | /** Runtime information support. */ 44 | itkTypeMacro(StreamingMosaicFilterBase, ImageToImageFilter); 45 | 46 | /** Input image typedefs. */ 47 | typedef TInputImage InputImageType; 48 | typedef typename InputImageType::ConstPointer InputImagePointer; 49 | typedef typename InputImageType::RegionType InputImageRegionType; 50 | typedef typename InputImageType::PixelType InputImagePixelType; 51 | typedef typename InputImageType::PointType InputImagePointType; 52 | typedef typename InputImageType::IndexType InputImageIndexType; 53 | typedef typename InputImageType::SizeType InputImageSizeType; 54 | typedef typename InputImageType::SpacingType InputImageSpacingType; 55 | typedef typename InputImageType::InternalPixelType InputImageInternalPixelType; 56 | 57 | /** Output image typedefs typedefs. */ 58 | typedef TOutputImage OutputImageType; 59 | typedef typename OutputImageType::Pointer OutputImagePointer; 60 | typedef typename OutputImageType::RegionType OutputImageRegionType; 61 | typedef typename OutputImageType::IndexType OutputImageIndexType; 62 | typedef typename OutputImageType::PointType OutputImagePointType; 63 | typedef typename OutputImageType::SizeType OutputImageSizeType; 64 | typedef typename OutputImageType::SpacingType OutputImageSpacingType; 65 | typedef typename OutputImageType::PixelType OutputImagePixelType; 66 | typedef typename OutputImageType::InternalPixelType OutputImageInternalPixelType; 67 | 68 | /** Internal computing typedefs */ 69 | typedef TInternalValueType InternalValueType; 70 | typedef typename itk::ContinuousIndex ContinuousIndexType; 71 | typedef itk::InterpolateImageFunction 72 | InterpolatorType; 73 | typedef typename InterpolatorType::Pointer InterpolatorPointerType; 74 | typedef itk::NearestNeighborInterpolateImageFunction 75 | DefaultInterpolatorType; 76 | typedef typename otb::VectorImage InternalImageType; 77 | typedef typename InternalImageType::PixelType InternalPixelType; 78 | typedef itk::ImageRegionIterator IteratorType; 79 | typedef itk::ImageRegionConstIterator ConstIteratorType; 80 | typedef otb::StreamingTraits StreamingTraitsType; 81 | 82 | /** Typedef for input images indices 83 | * TODO maybe use a itk class instead of std::vector ?*/ 84 | typedef std::vector IndicesListType; 85 | 86 | /** Typedef for matrices */ 87 | typedef vnl_matrix MatrixType; 88 | 89 | /** Set/Get the interpolator function. */ 90 | itkSetObjectMacro(Interpolator, InterpolatorType ); 91 | itkGetObjectMacro(Interpolator, InterpolatorType ); 92 | 93 | /** Set/Get the output no data value */ 94 | itkSetMacro(NoDataOutputPixel, OutputImagePixelType); 95 | itkGetMacro(NoDataOutputPixel, OutputImagePixelType); 96 | 97 | /** Set/Get the input no data value */ 98 | itkSetMacro(NoDataInputPixel, InputImagePixelType); 99 | itkGetMacro(NoDataInputPixel, InputImagePixelType); 100 | 101 | /** Set/Get output spacing */ 102 | itkSetMacro(OutputSpacing, OutputImageSpacingType); 103 | itkGetMacro(OutputSpacing, OutputImageSpacingType); 104 | 105 | /** Set/Get output origin */ 106 | itkSetMacro(OutputOrigin, OutputImagePointType); 107 | itkGetMacro(OutputOrigin, OutputImagePointType); 108 | 109 | /** Set/Get output size */ 110 | itkSetMacro(OutputSize, OutputImageSizeType); 111 | itkGetMacro(OutputSize, OutputImageSizeType); 112 | 113 | /** Set/Get automatic compute output parameters mode */ 114 | itkSetMacro(AutomaticOutputParametersComputation, bool); 115 | itkGetMacro(AutomaticOutputParametersComputation, bool); 116 | 117 | /** Set shift-scale mode */ 118 | itkSetMacro(ShiftScaleInputImages,bool); 119 | itkGetMacro(ShiftScaleInputImages,bool); 120 | itkBooleanMacro(ShiftScaleInputImages); 121 | 122 | /** Set the shift-scale matrices */ 123 | virtual void SetShiftMatrix(MatrixType shiftMatrix) { 124 | m_ShiftMatrix = MatrixType(shiftMatrix); 125 | } 126 | 127 | virtual void SetScaleMatrix(MatrixType scaleMatrix) { 128 | m_ScaleMatrix = MatrixType(scaleMatrix); 129 | } 130 | 131 | virtual MatrixType GetShiftMatrix() { 132 | return m_ShiftMatrix; 133 | } 134 | 135 | virtual MatrixType GetScaleMatrix() { 136 | return m_ScaleMatrix; 137 | } 138 | 139 | protected: 140 | StreamingMosaicFilterBase(); 141 | ~StreamingMosaicFilterBase() { 142 | } 143 | 144 | /** 145 | * Methods 146 | */ 147 | virtual void GenerateOutputInformation(void); 148 | 149 | virtual void GenerateInputRequestedRegion(void); 150 | 151 | virtual void AfterThreadedGenerateData(); 152 | 153 | virtual void BeforeThreadedGenerateData(); 154 | 155 | /** Image extent computing */ 156 | virtual void ImageToExtent(InputImageType* image, InputImagePointType &extentInf, InputImagePointType &extentSup); 157 | 158 | /** Requested region computing */ 159 | virtual bool OutputRegionToInputRegion(const OutputImageRegionType &mosaicRegion, 160 | InputImageRegionType &inputRegion, InputImageType* &inputImage); 161 | 162 | /** normalize pixel value, according to numeric type **/ 163 | virtual void NormalizePixelValue(InternalValueType& pixelValue); 164 | 165 | /** Check if the given pixel is empty */ 166 | virtual bool IsPixelNotEmpty(InputImagePixelType& inputPixel); 167 | 168 | /** Get the used input images indices */ 169 | virtual void AddUsedInputImageIndex(unsigned int index){ 170 | usedInputIndices.push_back(index); 171 | } 172 | 173 | virtual unsigned int GetUsedInputImageIndice(unsigned int i){ 174 | return usedInputIndices[i]; 175 | } 176 | 177 | virtual unsigned int GetNumberOfUsedInputImages() { 178 | return usedInputIndices.size(); 179 | } 180 | 181 | /** Compute output mosaic parameters (size, spacing, origin, ...) */ 182 | virtual void ComputeOutputParameters(); 183 | 184 | /** Get the number of input images */ 185 | virtual unsigned int GetNumberOfInputImages() { 186 | return this->GetNumberOfInputs(); 187 | } 188 | 189 | /** Get number of bands */ 190 | virtual unsigned int GetNumberOfBands() { 191 | return nbOfBands; 192 | } 193 | 194 | /** Compute the requested region of a given input image */ 195 | virtual void ComputeRequestedRegionOfInputImage(unsigned int inputImageIndex); 196 | 197 | /** Shift-Scale a value */ 198 | virtual void ShiftScaleValue(InternalValueType& value, const unsigned int& imageIndex, unsigned int& band ) 199 | { 200 | value *= m_ScaleMatrix[imageIndex][band]; 201 | value += m_ShiftMatrix[imageIndex][band]; 202 | } 203 | 204 | /** Check the shift scale matrices */ 205 | virtual void CheckShiftScaleMatrices(); 206 | 207 | /** Prepare interpolators, valid regions, and input images pointers */ 208 | virtual void PrepareImageAccessors(typename std::vector& image, 209 | typename std::vector& interpolator); 210 | 211 | private: 212 | 213 | StreamingMosaicFilterBase(const Self&); //purposely not implemented 214 | void operator=(const Self&); //purposely not implemented 215 | 216 | InterpolatorPointerType m_Interpolator; // Interpolator 217 | OutputImagePixelType m_NoDataOutputPixel; // No data (output) 218 | InputImagePixelType m_NoDataInputPixel; // No data (input) 219 | 220 | OutputImageSpacingType m_OutputSpacing; // Output spacing 221 | OutputImagePointType m_OutputOrigin; // Output origin 222 | OutputImageSizeType m_OutputSize; // Output size 223 | 224 | bool m_AutomaticOutputParametersComputation; // Output parameters auto on/off 225 | bool m_ShiftScaleInputImages; // Shift-scale mode on/off 226 | 227 | MatrixType m_ShiftMatrix; // matrix of shifts 228 | MatrixType m_ScaleMatrix; // matrix of scales 229 | 230 | /** Internal */ 231 | unsigned int nbOfBands; // number of bands 232 | unsigned int interpolatorRadius; // interpolator padding radius 233 | IndicesListType usedInputIndices; // requested input image indices 234 | InternalValueType minOutputPixelValue; 235 | InternalValueType maxOutputPixelValue; 236 | 237 | }; // end of class 238 | 239 | } // end namespace itk 240 | 241 | #ifndef OTB_MANUAL_INSTANTIATION 242 | #include "otbStreamingMosaicFilterBase.txx" 243 | #endif 244 | 245 | #endif 246 | -------------------------------------------------------------------------------- /include/otbStreamingMultibandFeatherMosaicFilter.txx: -------------------------------------------------------------------------------- 1 | #ifndef __StreamingMultibandFeatherMosaicFilter_txx 2 | #define __StreamingMultibandFeatherMosaicFilter_txx 3 | 4 | #include "otbStreamingMultibandFeatherMosaicFilter.h" 5 | #include "itkProgressReporter.h" 6 | 7 | namespace otb 8 | { 9 | 10 | /** 11 | * Constructor: set default values 12 | */ 13 | template 14 | StreamingMultibandFeatherMosaicFilter 15 | ::StreamingMultibandFeatherMosaicFilter() 16 | { 17 | m_NumberOfLevels = 2; 18 | m_FirstLevelTransitionDistance = 3; 19 | m_FirstLevelVariance = 1; 20 | } 21 | 22 | template 23 | void 24 | StreamingMultibandFeatherMosaicFilter 25 | ::Modified() 26 | { 27 | 28 | // Clear scales parameters 29 | m_TransitionDistances.clear(); 30 | m_TransitionOffsets.clear(); 31 | m_Variances.clear(); 32 | 33 | // Clear internal filters 34 | m_SubImageFilter.clear(); 35 | m_Filter.clear(); 36 | m_SingleFilter.clear(); 37 | m_MosaicFilter.clear(); 38 | 39 | // Compute transition distances 40 | for (unsigned int level = 0 ; level <= m_NumberOfLevels ; level++) 41 | { 42 | DistanceImageValueType distance = std::pow( (DistanceImageValueType) level+1, 2.0)*m_FirstLevelTransitionDistance; 43 | m_TransitionDistances.push_back(distance); 44 | } 45 | 46 | // Transition offsets are here to center the blending effect 47 | for (unsigned int level = 0 ; level <= m_NumberOfLevels ; level++) 48 | { 49 | DistanceImageValueType offset = 0.5*(m_TransitionDistances.at(m_NumberOfLevels) 50 | -m_TransitionDistances.at(level) ); 51 | m_TransitionOffsets.push_back(offset); 52 | } 53 | 54 | // // When LF transition distance is manually set, change corresponding 55 | // offset 56 | // if (transitionDistanceLF>transitionsDistances[numberOfLevels]) 57 | // { 58 | // // Set new LF transition distance 59 | // transitionsDistances[numberOfLevels] = transitionDistanceLF; 60 | // // Reset offset value same as level before 61 | // transitionOffset[numberOfLevels] = transitionOffset[numberOfLevels-1]; 62 | // } 63 | 64 | // Prepare mosaic filters 65 | for (unsigned int level = 0 ; level <= m_NumberOfLevels ; level++) 66 | { 67 | itkDebugMacro("Create mosaic filter for level " << level); 68 | MosaicFilterPointer mosaicFilter = MosaicFilterType::New(); 69 | 70 | // Set output origin, size, spacing, AutomaticOutputParametersComputation, 71 | // scale matrix, shift-scale mode 72 | mosaicFilter->SetOutputOrigin(this->GetOutputOrigin() ); 73 | mosaicFilter->SetOutputSize(this->GetOutputSize() ); 74 | mosaicFilter->SetOutputSpacing(this->GetOutputSpacing() ); 75 | mosaicFilter->SetAutomaticOutputParametersComputation(this->GetAutomaticOutputParametersComputation() ); 76 | mosaicFilter->SetScaleMatrix(this->GetScaleMatrix() ); // Set scales (HF 77 | // and LF) 78 | mosaicFilter->SetShiftScaleInputImages(this->GetShiftScaleInputImages() ); 79 | mosaicFilter->SetInterpolator(this->GetInterpolator() ); // Interpolator 80 | mosaicFilter->SetNoDataOutputPixel(this->GetNoDataOutputPixel() ); // No 81 | // data 82 | // (output) 83 | mosaicFilter->SetNoDataInputPixel(this->GetNoDataInputPixel() ); // No 84 | // data 85 | // (input) 86 | mosaicFilter->SetFeatheringSmoothness(this->GetFeatheringSmoothness() ); // feathering 87 | // exponent 88 | mosaicFilter->SetDistanceInterpolator(this->GetDistanceInterpolator() ); // distance 89 | // image 90 | // interpolator 91 | 92 | // Set shifts 93 | if (level == m_NumberOfLevels) 94 | { 95 | // ...for LF 96 | mosaicFilter->SetShiftMatrix(this->GetShiftMatrix() ); 97 | } 98 | else 99 | { 100 | // ... but not for HF 101 | typename MosaicFilterType::MatrixType nullshifts(this->GetShiftMatrix() ); 102 | nullshifts.fill(0); 103 | mosaicFilter->SetShiftMatrix(nullshifts); 104 | } 105 | m_MosaicFilter.push_back(mosaicFilter); 106 | } 107 | 108 | // Now prepare all filters 109 | const unsigned int numberOfImages = 0.5*(this->GetNumberOfInputs() ); 110 | for (unsigned int i = 0 ; i < numberOfImages ; i++) 111 | { 112 | 113 | const unsigned int inputImageIndex = 2*i; 114 | const unsigned int inputDistanceImageIndex = 2*i+1; 115 | 116 | itkDebugMacro("Create filters for image " << i ); 117 | 118 | std::vector gaussianFilters; 119 | std::vector gaussianFilterAdapters; 120 | std::vector subImageFilters; 121 | 122 | // Create N filters 123 | for (unsigned int level = 0 ; level < m_NumberOfLevels ; level++) 124 | { 125 | 126 | itkDebugMacro("\tLevel " << level ); 127 | 128 | // compute variance of the level 129 | const double shrinkFactor = std::pow(2.0, (double) level ) ; // 1 2 4 8 16 130 | // ... 131 | const double variance = std::pow(0.5 * shrinkFactor, 2.0) ; // 132 | 133 | // discrete gaussian filter 134 | DiscreteGaussianFilterPointer discreteGaussianFilter = DiscreteGaussianFilterType::New(); 135 | discreteGaussianFilter->SetVariance(variance); 136 | discreteGaussianFilter->SetUseImageSpacingOff(); 137 | discreteGaussianFilter->SetReleaseDataFlag(true); 138 | gaussianFilters.push_back(discreteGaussianFilter); 139 | 140 | // filter adapter 141 | PerBandFilterPointer gaussianFilterAdapter = PerBandFilterType::New(); 142 | gaussianFilterAdapter->SetFilter(discreteGaussianFilter); 143 | gaussianFilterAdapter->SetInput(this->GetInput(inputImageIndex) ); 144 | gaussianFilterAdapter->SetReleaseDataFlag(true); 145 | gaussianFilterAdapters.push_back(gaussianFilterAdapter); 146 | 147 | // subtract filter 148 | SubImageFilterPointer subtractFilter = SubImageFilterType::New(); 149 | if (level == 0) 150 | { 151 | // HF band is I* - b0 152 | subtractFilter->SetInput1(this->GetInput(inputImageIndex) ); 153 | subtractFilter->SetInput2(gaussianFilterAdapters.at(level)->GetOutput() ); 154 | } 155 | else 156 | { 157 | // band is bn-1 - bn 158 | subtractFilter->SetInput1(gaussianFilterAdapters.at(level-1)->GetOutput() ); 159 | subtractFilter->SetInput2(gaussianFilterAdapters.at(level)->GetOutput() ); 160 | } 161 | subImageFilters.push_back(subtractFilter); 162 | 163 | // mosaic filter 164 | m_MosaicFilter[level]->PushBackInputs(subtractFilter->GetOutput(), 165 | static_cast(Superclass::ProcessObject::GetInput( 166 | inputDistanceImageIndex) ) ); 167 | 168 | } 169 | m_SingleFilter.push_back(gaussianFilters); 170 | m_Filter.push_back(gaussianFilterAdapters); 171 | m_SubImageFilter.push_back(subImageFilters); 172 | 173 | // Last band is lowest low pass filter 174 | itkDebugMacro("m_Filter size = " << m_Filter.size() << " / i = " << i); 175 | m_MosaicFilter[m_NumberOfLevels]->PushBackInputs(m_Filter.at(i).at(m_NumberOfLevels-1)->GetOutput(), 176 | static_cast(Superclass::ProcessObject:: 177 | GetInput( 178 | inputDistanceImageIndex) ) ); 179 | 180 | } 181 | 182 | // Compute extrapolation offset: 183 | // Avoid extrapolation near borders (gaussian filters blurs "no data" values 184 | // too...) 185 | // Because LF gaussian filters have the biggest kernel, one must 186 | // set an offset equal to this kernel size, in geographic unit. This will 187 | // avoid the use of blured "no data" values 188 | const double maximumSpacingInXY = std::max(std::abs(this->GetOutputSpacing()[0]), 189 | std::abs(this->GetOutputSpacing()[1]) ); 190 | const double extrapolationOffset = ( (double) 191 | m_SingleFilter.at(0).at(m_NumberOfLevels-1)->GetMaximumKernelWidth() ) 192 | *maximumSpacingInXY; 193 | itkDebugMacro(<<"Extrapolation offset: " << extrapolationOffset); 194 | 195 | // Set up mosaic filters offsets and transition distances 196 | itkDebugMacro("Level\tDist\tOffest"); 197 | for (unsigned int level = 0 ; level <= m_NumberOfLevels ; level++) 198 | { 199 | const double offset = extrapolationOffset + m_TransitionOffsets.at(level); 200 | m_MosaicFilter.at(level)->SetDistanceOffset(offset); 201 | m_MosaicFilter.at(level)->SetFeatheringTransitionDistance(m_TransitionDistances.at(level) ); 202 | itkDebugMacro(<PushBackInput(m_MosaicFilter.at(level)->GetOutput() ); 211 | } 212 | m_SummingFilter->SetReleaseDataFlag(true); 213 | 214 | } 215 | 216 | /* 217 | * GenerateData 218 | */ 219 | template 220 | void 221 | StreamingMultibandFeatherMosaicFilter 222 | ::GenerateData() 223 | { 224 | itkDebugMacro("Generate data on region " << this->GetOutput()->GetRequestedRegion() ); 225 | 226 | m_SummingFilter->GraftOutput(this->GetOutput() ); 227 | m_SummingFilter->Update(); 228 | this->GraftOutput(m_SummingFilter->GetOutput() ); 229 | 230 | itkDebugMacro("Generate data OK"); 231 | } 232 | 233 | } 234 | #endif 235 | -------------------------------------------------------------------------------- /include/otbStreamingStatisticsMosaicFilter.txx: -------------------------------------------------------------------------------- 1 | #ifndef __StreamingStatisticsMosaicFilter_txx 2 | #define __StreamingStatisticsMosaicFilter_txx 3 | 4 | #include "otbStreamingStatisticsMosaicFilter.h" 5 | 6 | namespace otb { 7 | 8 | template 9 | PersistentStatisticsMosaicFilter 10 | ::PersistentStatisticsMosaicFilter(){ 11 | 12 | // allocate the data objects for the outputs which are 13 | // just decorators around pixel types 14 | // 1: means 15 | // 2: stdevs 16 | // 3: means of products 17 | // 4: mins 18 | // 5: maxs 19 | for (int i = 1; i < 6; ++i) 20 | { 21 | typename RealMatrixListObjectType::Pointer output 22 | = static_cast(this->MakeOutput(i).GetPointer()); 23 | this->itk::ProcessObject::SetNthOutput(i, output.GetPointer()); 24 | } 25 | 26 | // allocate the data objects for the outputs which are 27 | // just decorators around real matrices 28 | // 29 | // 6: count 30 | typename RealMatrixObjectType::Pointer output 31 | = static_cast(this->MakeOutput(6).GetPointer()); 32 | this->itk::ProcessObject::SetNthOutput(6, output.GetPointer()); 33 | 34 | } 35 | 36 | /* 37 | * Make output 38 | */ 39 | template 40 | typename itk::DataObject::Pointer 41 | PersistentStatisticsMosaicFilter 42 | ::MakeOutput(DataObjectPointerArraySizeType output) 43 | { 44 | itkDebugMacro( << "Entering MakeOutput(" << output << ")" ); 45 | if (output == 0) 46 | { 47 | return static_cast(TOutputImage::New().GetPointer()); 48 | } 49 | else if (output == 6) 50 | { 51 | return static_cast(RealMatrixObjectType::New().GetPointer()); 52 | } 53 | return static_cast(RealMatrixListObjectType::New().GetPointer()); 54 | 55 | } 56 | 57 | template 58 | typename PersistentStatisticsMosaicFilter::RealMatrixListObjectType* 59 | PersistentStatisticsMosaicFilter 60 | ::GetMeansOutput() 61 | { 62 | return static_cast(this->itk::ProcessObject::GetOutput(1)); 63 | } 64 | 65 | template 66 | typename PersistentStatisticsMosaicFilter::RealMatrixListObjectType* 67 | PersistentStatisticsMosaicFilter 68 | ::GetStdsOutput() 69 | { 70 | return static_cast(this->itk::ProcessObject::GetOutput(2)); 71 | } 72 | 73 | template 74 | typename PersistentStatisticsMosaicFilter::RealMatrixListObjectType* 75 | PersistentStatisticsMosaicFilter 76 | ::GetMeansOfProductsOutput() 77 | { 78 | return static_cast(this->itk::ProcessObject::GetOutput(3)); 79 | } 80 | 81 | template 82 | typename PersistentStatisticsMosaicFilter::RealMatrixListObjectType* 83 | PersistentStatisticsMosaicFilter 84 | ::GetMinsOutput() 85 | { 86 | return static_cast(this->itk::ProcessObject::GetOutput(4)); 87 | } 88 | 89 | template 90 | typename PersistentStatisticsMosaicFilter::RealMatrixListObjectType* 91 | PersistentStatisticsMosaicFilter 92 | ::GetMaxsOutput() 93 | { 94 | return static_cast(this->itk::ProcessObject::GetOutput(5)); 95 | } 96 | 97 | template 98 | typename PersistentStatisticsMosaicFilter::RealMatrixObjectType* 99 | PersistentStatisticsMosaicFilter 100 | ::GetAreasOutput() 101 | { 102 | return static_cast(this->itk::ProcessObject::GetOutput(6)); 103 | } 104 | 105 | template 106 | const typename PersistentStatisticsMosaicFilter::RealMatrixListObjectType* 107 | PersistentStatisticsMosaicFilter 108 | ::GetMeansOutput() const 109 | { 110 | return static_cast(this->itk::ProcessObject::GetOutput(1)); 111 | } 112 | 113 | template 114 | const typename PersistentStatisticsMosaicFilter::RealMatrixListObjectType* 115 | PersistentStatisticsMosaicFilter 116 | ::GetStdsOutput() const 117 | { 118 | return static_cast(this->itk::ProcessObject::GetOutput(2)); 119 | } 120 | 121 | template 122 | const typename PersistentStatisticsMosaicFilter::RealMatrixListObjectType* 123 | PersistentStatisticsMosaicFilter 124 | ::GetMeansOfProductsOutput() const 125 | { 126 | return static_cast(this->itk::ProcessObject::GetOutput(3)); 127 | } 128 | 129 | template 130 | const typename PersistentStatisticsMosaicFilter::RealMatrixListObjectType* 131 | PersistentStatisticsMosaicFilter 132 | ::GetMinsOutput() const 133 | { 134 | return static_cast(this->itk::ProcessObject::GetOutput(4)); 135 | } 136 | 137 | template 138 | const typename PersistentStatisticsMosaicFilter::RealMatrixListObjectType* 139 | PersistentStatisticsMosaicFilter 140 | ::GetMaxsOutput() const 141 | { 142 | return static_cast(this->itk::ProcessObject::GetOutput(5)); 143 | } 144 | 145 | template 146 | const typename PersistentStatisticsMosaicFilter::RealMatrixObjectType* 147 | PersistentStatisticsMosaicFilter 148 | ::GetAreasOutput() const 149 | { 150 | return static_cast(this->itk::ProcessObject::GetOutput(6)); 151 | } 152 | 153 | /** 154 | * Reset() implementation 155 | */ 156 | template 157 | void 158 | PersistentStatisticsMosaicFilter 159 | ::Reset() 160 | { 161 | itkDebugMacro( << "Entering Reset()" ); 162 | 163 | Superclass::GenerateOutputInformation(); 164 | 165 | // Prepare threads result 166 | const unsigned int numberOfThreads = this->GetNumberOfThreads(); 167 | const unsigned int nBands = this->GetNumberOfBands(); 168 | const unsigned int nbImages = this->GetNumberOfInputImages(); 169 | 170 | itkDebugMacro ( << "\nN threads: " << numberOfThreads << 171 | "\nN bands: " << nBands << 172 | "\nN images: " << nbImages ); 173 | 174 | m_InternalThreadResults.clear(); 175 | for (unsigned int threadId = 0 ; threadId < numberOfThreads ; threadId++) 176 | { 177 | // Create a clean empty container for each thread 178 | ThreadResultsContainer threadResult(nBands,nbImages*nbImages); 179 | m_InternalThreadResults.push_back(threadResult); 180 | } 181 | 182 | } 183 | 184 | template 185 | void 186 | PersistentStatisticsMosaicFilter 187 | ::AllocateOutputs() 188 | { 189 | itkDebugMacro( << "Entering AllocateOutputs()" ); 190 | // This is commented to prevent the streaming of the whole image for the first stream strip 191 | // It shall not cause any problem because the output image of this filter is not intended to be used. 192 | //InputImagePointer image = const_cast< TInputImage * >( this->GetInput() ); 193 | //this->GraftOutput( image ); 194 | // Nothing that needs to be allocated for the remaining outputs 195 | } 196 | 197 | /* 198 | * Synthetize() implementation 199 | */ 200 | template 201 | void 202 | PersistentStatisticsMosaicFilter 203 | ::Synthetize() 204 | { 205 | itkDebugMacro( << "Entering Synthetize()" ); 206 | 207 | const unsigned int nBands = Superclass::GetNumberOfBands(); 208 | const unsigned int nbImages = this->GetNumberOfInputImages(); 209 | 210 | // Merge threads result 211 | ThreadResultsContainer finalResults = ThreadResultsContainer(nBands,nbImages*nbImages); 212 | for (const auto& res: m_InternalThreadResults) 213 | { 214 | finalResults.Update(res); 215 | } 216 | 217 | // Compute final outputs 218 | m_Means.clear(); 219 | m_Stds.clear(); 220 | m_ProdMeans.clear(); 221 | m_Mins.clear(); 222 | m_Maxs.clear(); 223 | m_Area = RealMatrixType(nbImages,nbImages,0); 224 | 225 | for (unsigned int band = 0 ; band < nBands ; band++) 226 | { 227 | RealMatrixType mean (nbImages, nbImages, 0); 228 | RealMatrixType prodmean(nbImages, nbImages, 0); 229 | RealMatrixType stdev (nbImages, nbImages, 0); 230 | RealMatrixType min (nbImages, nbImages, itk::NumericTraits::max() ); 231 | RealMatrixType max (nbImages, nbImages, itk::NumericTraits::NonpositiveMin() ); 232 | 233 | for (unsigned int i = 0 ; i < nbImages ; i++) 234 | { 235 | for (unsigned int j = 0 ; j < nbImages ; j++) 236 | { 237 | 238 | const InternalValueType count = finalResults.m_count[i*nbImages+j]; 239 | const InternalValueType sum = finalResults.m_sum[band][i*nbImages+j]; 240 | const InternalValueType cosum = finalResults.m_cosum[band][i*nbImages+j]; 241 | const InternalValueType sqSum = finalResults.m_sqSum[band][i*nbImages+j]; 242 | const InternalValueType minVal = finalResults.m_min[band][i*nbImages+j]; 243 | const InternalValueType maxVal = finalResults.m_max[band][i*nbImages+j]; 244 | 245 | // Update area 246 | m_Area[i][j] = count; 247 | 248 | // Update Min and Max 249 | if (minVal < min[i][j]) 250 | min[i][j] = minVal; 251 | if (maxVal > max[i][j]) 252 | max[i][j] = maxVal; 253 | 254 | // Update Mean, Std and Mean of products 255 | if (count > 0) 256 | { 257 | mean[i][j] = sum / (static_cast(count) ); 258 | prodmean[i][j] = cosum / (static_cast(count) ); 259 | 260 | // Unbiased estimate 261 | InternalValueType variance = (sqSum - (sum*sum 262 | / static_cast(count) ) ) 263 | / (static_cast(count) - 1); 264 | if (variance > 0) 265 | { 266 | stdev[i][j] = vcl_sqrt(variance); 267 | } 268 | 269 | } 270 | } 271 | } 272 | m_Means.push_back(mean); 273 | m_Stds.push_back(stdev); 274 | m_ProdMeans.push_back(prodmean); 275 | m_Mins.push_back(min); 276 | m_Maxs.push_back(max); 277 | 278 | } // next band 279 | 280 | this->GetMeansOutput()->Set(m_Means); 281 | this->GetStdsOutput()->Set(m_Stds); 282 | this->GetMeansOfProductsOutput()->Set(m_ProdMeans); 283 | this->GetMinsOutput()->Set(m_Mins); 284 | this->GetMaxsOutput()->Set(m_Maxs); 285 | this->GetAreasOutput()->Set(m_Area); 286 | } 287 | 288 | /** 289 | * Processing 290 | */ 291 | template 292 | void 293 | PersistentStatisticsMosaicFilter 294 | ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) 295 | { 296 | 297 | // Debug info 298 | itkDebugMacro(<<"Actually executing thread " << threadId << " in region " << outputRegionForThread); 299 | 300 | // Support progress methods/callbacks 301 | itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels() ); 302 | 303 | // Get number of input images 304 | const unsigned int nbOfInputImages = this->GetNumberOfInputImages(); 305 | 306 | // Get number of used inputs 307 | const unsigned int nbOfUsedInputImages = Superclass::GetNumberOfUsedInputImages(); 308 | 309 | // Iterate through the thread region 310 | IteratorType outputIt(this->GetOutput(), outputRegionForThread); 311 | 312 | // Prepare input pointers, interpolators, and valid regions (input images) 313 | typename std::vector currentImage; 314 | typename std::vector interp; 315 | Superclass::PrepareImageAccessors(currentImage, interp); 316 | 317 | // temporary variables 318 | OutputImagePointType geoPoint; 319 | 320 | for ( outputIt.GoToBegin(); !outputIt.IsAtEnd(); ++outputIt ) 321 | { 322 | 323 | // Update progress 324 | progress.CompletedPixel(); 325 | 326 | // Overlap descriptor for the current pixel (yes/no + value) 327 | std::vector overlapImagesIndices; 328 | std::vector overlapPixelValue; 329 | 330 | // Current pixel --> Geographical point 331 | this->GetOutput()->TransformIndexToPhysicalPoint (outputIt.GetIndex(), geoPoint) ; 332 | 333 | // Loop on used input images 334 | for (unsigned int i = 0 ; i < nbOfUsedInputImages ; i++) 335 | { 336 | 337 | // Check if the point is inside the transformed thread region 338 | // (i.e. the region in the current input image which match the thread 339 | // region) 340 | if (interp[i]->IsInsideBuffer(geoPoint) ) 341 | { 342 | 343 | // Compute the interpolated pixel value 344 | InputImagePixelType interpolatedPixel = interp[i]->Evaluate(geoPoint); 345 | 346 | // Put image index + image pixel value into memory 347 | if (Superclass::IsPixelNotEmpty(interpolatedPixel) ) 348 | { 349 | overlapImagesIndices.push_back (Superclass::GetUsedInputImageIndice(i) ); 350 | overlapPixelValue.push_back(interpolatedPixel); 351 | } 352 | 353 | } // point inside buffer 354 | } // next image 355 | 356 | // Update thread result 357 | 358 | // Nb of overlaps at the current pixel 359 | unsigned int nbOfOverlappingPixels = overlapImagesIndices.size(); 360 | 361 | // Loop on overlapping pixels 362 | for (unsigned int i = 0 ; i < nbOfOverlappingPixels ; i++) 363 | { 364 | // Index of the image whose comes the current overlapping pixel 365 | unsigned int imageIndex = overlapImagesIndices.at(i); 366 | 367 | // We need to sum this pixel to all overlaps ij 368 | InputImagePixelType pixel = overlapPixelValue.at(i); 369 | 370 | for (unsigned int j = 0 ; j < nbOfOverlappingPixels ; j++) 371 | { 372 | // if (i!=j) 373 | { 374 | // Index of the other image which share this overlapping pixel 375 | unsigned int otherImageIndex = overlapImagesIndices.at(j); 376 | 377 | // Pixel value of the other image which share this overlapping pixel 378 | InputImagePixelType otherPixel = overlapPixelValue.at(j); 379 | 380 | // Update 381 | m_InternalThreadResults.at(threadId).Update(pixel, otherPixel, imageIndex*nbOfInputImages + otherImageIndex); 382 | } 383 | } 384 | } // loop on overlapping pixels 385 | 386 | } // next output pixel 387 | 388 | } 389 | 390 | } // end namespace gtb 391 | 392 | #endif 393 | -------------------------------------------------------------------------------- /include/otbStreamingStatisticsMosaicFilter.h: -------------------------------------------------------------------------------- 1 | #ifndef __StreamingStatisticsMosaicFilter_H 2 | #define __StreamingStatisticsMosaicFilter_H 3 | 4 | #include "otbStreamingMosaicFilterBase.h" 5 | #include "otbPersistentMosaicFilter.h" 6 | #include "otbPersistentFilterStreamingDecorator.h" 7 | #include "itkArray.h" 8 | #include "itkSimpleDataObjectDecorator.h" 9 | #include "itkImageRegionConstIteratorWithOnlyIndex.h" 10 | 11 | namespace otb 12 | { 13 | /** \class PersistentStatisticsMosaicFilter 14 | * \brief Computes the statistics of a mosaic from an input images set. 15 | * The output pixel value is equal to the number of overlaps 16 | * 17 | * Support streaming 18 | * 19 | * The pixels must support the operator ==, +, /, etc. 20 | * The "no data value", output spacing, interpolator can be chosen. 21 | * The behavior of the filter is to compute input images statistics 22 | * as they were in a layered fashion: interpolators are used to 23 | * compute pixels values of all input images for a given output pixel. 24 | * This is used to compute the following matrices: mean, standard 25 | * deviation, min, max, and means of pixels products. Let's denote 26 | * X one of these matrices, then X\{ij} is the statistic of the image 27 | * i in the overlapping area with the image j. 28 | * 29 | * \ingroup OTBMosaic 30 | */ 31 | template 32 | class ITK_EXPORT PersistentStatisticsMosaicFilter : public otb::PersistentMosaicFilter 34 | { 35 | public: 36 | 37 | /** Standard Self typedef */ 38 | typedef PersistentStatisticsMosaicFilter Self; 39 | typedef PersistentMosaicFilter Superclass; 40 | typedef itk::SmartPointer Pointer; 41 | typedef itk::SmartPointer ConstPointer; 42 | 43 | /** Method for creation through the object factory. */ 44 | itkNewMacro(Self); 45 | 46 | /** Runtime information support. */ 47 | itkTypeMacro(PersistentStatisticsMosaicFilter, PersistentMosaicFilter); 48 | 49 | /** Input image typedefs. */ 50 | typedef typename Superclass::InputImageType InputImageType; 51 | typedef typename Superclass::InputImagePointer InputImagePointer; 52 | typedef typename Superclass::InputImagePointType InputImagePointType; 53 | typedef typename Superclass::InputImagePixelType InputImagePixelType; 54 | typedef typename Superclass::InputImageInternalPixelType InputImageInternalPixelType; 55 | 56 | /** Output image typedefs. */ 57 | typedef typename Superclass::OutputImageType OutputImageType; 58 | typedef typename Superclass::OutputImagePointType OutputImagePointType; 59 | typedef typename Superclass::OutputImageRegionType OutputImageRegionType; 60 | 61 | /** Internal computing typedef support. */ 62 | typedef typename Superclass::InternalValueType InternalValueType; 63 | typedef typename Superclass::InterpolatorPointerType InterpolatorPointerType; 64 | 65 | typedef itk::ImageRegionConstIteratorWithOnlyIndex IteratorType; 66 | 67 | /** Typedefs for statistics */ 68 | typedef vnl_vector RealVectorType; 69 | typedef vnl_matrix RealMatrixType; 70 | typedef itk::SimpleDataObjectDecorator RealMatrixObjectType; 71 | typedef std::vector RealMatrixListType; 72 | typedef itk::SimpleDataObjectDecorator RealMatrixListObjectType; 73 | 74 | /** Smart Pointer type to a DataObject. */ 75 | typedef typename itk::DataObject::Pointer DataObjectPointer; 76 | typedef itk::ProcessObject::DataObjectPointerArraySizeType DataObjectPointerArraySizeType; 77 | 78 | /** Overrided methods */ 79 | virtual void AllocateOutputs(); 80 | virtual void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId ); 81 | virtual void Reset(); 82 | virtual void Synthetize(); 83 | 84 | /** Make a DataObject of the correct type to be used as the specified output. */ 85 | DataObjectPointer MakeOutput(DataObjectPointerArraySizeType idx) ITK_OVERRIDE; 86 | using Superclass::MakeOutput; 87 | 88 | /** Return the computed Mean. */ 89 | RealMatrixListType GetMeans() const 90 | { 91 | return this->GetMeansOutput()->Get(); 92 | } 93 | RealMatrixListObjectType* GetMeansOutput(); 94 | const RealMatrixListObjectType* GetMeansOutput() const; 95 | 96 | /** Return the computed Std. */ 97 | RealMatrixListType GetStds() const 98 | { 99 | return this->GetStdsOutput()->Get(); 100 | } 101 | RealMatrixListObjectType* GetStdsOutput(); 102 | const RealMatrixListObjectType* GetStdsOutput() const; 103 | 104 | /** Return the computed Min. */ 105 | RealMatrixListType GetMins() const 106 | { 107 | return this->GetMinsOutput()->Get(); 108 | } 109 | RealMatrixListObjectType* GetMinsOutput(); 110 | const RealMatrixListObjectType* GetMinsOutput() const; 111 | 112 | /** Return the computed Max. */ 113 | RealMatrixListType GetMaxs() const 114 | { 115 | return this->GetMaxsOutput()->Get(); 116 | } 117 | RealMatrixListObjectType* GetMaxsOutput(); 118 | const RealMatrixListObjectType* GetMaxsOutput() const; 119 | 120 | /** Return the computed MeansOfProduct. */ 121 | RealMatrixListType GetMeansOfProducts() const 122 | { 123 | return this->GetMeansOfProductsOutput()->Get(); 124 | } 125 | RealMatrixListObjectType* GetMeansOfProductsOutput(); 126 | const RealMatrixListObjectType* GetMeansOfProductsOutput() const; 127 | 128 | /** Return the computed areas. */ 129 | RealMatrixType GetAreas() const 130 | { 131 | return this->GetAreasOutput()->Get(); 132 | } 133 | RealMatrixObjectType* GetAreasOutput(); 134 | const RealMatrixObjectType* GetAreasOutput() const; 135 | 136 | protected: 137 | PersistentStatisticsMosaicFilter(); 138 | virtual ~PersistentStatisticsMosaicFilter() {} 139 | 140 | /** PersistentStatisticsMosaicFilter can be implemented as a multithreaded filter. 141 | * Therefore, this implementation provides a ThreadedGenerateData() routine 142 | * which is called for each processing thread. The output image data is 143 | * allocated automatically by the superclass prior to calling 144 | * ThreadedGenerateData(). ThreadedGenerateData can only write to the 145 | * portion of the output image specified by the parameter 146 | * "outputRegionForThread" 147 | * 148 | * \sa ImageToImageFilter::ThreadedGenerateData(), 149 | * ImageToImageFilter::GenerateData() */ 150 | 151 | 152 | 153 | /** Class for storing thread results: 154 | * -sum of values 155 | * -sum of squared values 156 | * -min value 157 | * -max value 158 | * -count 159 | */ 160 | class ThreadResultsContainer { 161 | public: 162 | /** Default constructor */ 163 | ThreadResultsContainer(){ 164 | } 165 | 166 | /* Constructor with size */ 167 | ThreadResultsContainer(unsigned int nbOfBands, unsigned int nbOfSamples) 168 | { 169 | Clear(nbOfBands, nbOfSamples); 170 | } 171 | 172 | /* Copy constructor */ 173 | ThreadResultsContainer(const ThreadResultsContainer& other) 174 | { 175 | m_count = RealVectorType(other.m_count); 176 | m_sum = RealMatrixType(other.m_sum); 177 | m_cosum = RealMatrixType(other.m_cosum); 178 | m_sqSum = RealMatrixType(other.m_sqSum); 179 | m_min = RealMatrixType(other.m_min); 180 | m_max = RealMatrixType(other.m_max); 181 | } 182 | 183 | /* Clear routine: Resize at the specified dimension and clear values */ 184 | void Clear(unsigned int nbOfBands, unsigned int nbOfSamples) 185 | { 186 | const InternalValueType zeroValue = itk::NumericTraits::Zero; 187 | const InternalValueType supValue = itk::NumericTraits::max(); 188 | const InternalValueType infValue = itk::NumericTraits::NonpositiveMin(); 189 | 190 | m_count = RealVectorType(nbOfSamples, 0); 191 | m_sum = RealMatrixType(nbOfBands, nbOfSamples, zeroValue); 192 | m_cosum = RealMatrixType(nbOfBands, nbOfSamples, zeroValue); 193 | m_sqSum = RealMatrixType(nbOfBands, nbOfSamples, zeroValue); 194 | m_min = RealMatrixType(nbOfBands, nbOfSamples, supValue); 195 | m_max = RealMatrixType(nbOfBands, nbOfSamples, infValue); 196 | } 197 | 198 | /* 1-Pixel update */ 199 | void Update( const InputImagePixelType& pixel, unsigned int sampleId) 200 | { 201 | unsigned int nbOfBands = pixel.Size(); 202 | 203 | m_count[sampleId]++; 204 | for (unsigned int band = 0 ; band < nbOfBands ; band++) 205 | { 206 | // Cast 207 | InternalValueType pixelValue = static_cast(pixel[band]); 208 | 209 | // Update Min & max 210 | if (pixelValue < m_min[band][sampleId]) 211 | m_min[band][sampleId] = pixelValue; 212 | if (pixelValue > m_max[band][sampleId]) 213 | m_max[band][sampleId] = pixelValue; 214 | 215 | // Update Sums 216 | m_sum[band][sampleId] += pixelValue; 217 | m_sqSum[band][sampleId] += pixelValue*pixelValue; 218 | } 219 | } 220 | 221 | /* 2-Pixels update */ 222 | void Update( const InputImagePixelType& pixel_i,const InputImagePixelType& pixel_j, unsigned int sampleId) 223 | { 224 | Update(pixel_i, sampleId); 225 | unsigned int nbOfBands = pixel_i.Size(); 226 | for (unsigned int band = 0 ; band < nbOfBands ; band++) 227 | { 228 | // Cast 229 | InternalValueType pixelValue_i = static_cast(pixel_i[band]); 230 | InternalValueType pixelValue_j = static_cast(pixel_j[band]); 231 | 232 | m_cosum[band][sampleId] += pixelValue_i*pixelValue_j; 233 | } 234 | } 235 | 236 | /* Self update */ 237 | void Update(const ThreadResultsContainer& other) 238 | { 239 | unsigned int nbOfBands = other.m_sum.rows(); 240 | unsigned int nbOfSamples = other.m_sum.cols(); 241 | 242 | for (unsigned int sampleId = 0 ; sampleId < nbOfSamples ; sampleId++) 243 | { 244 | m_count[sampleId] += other.m_count[sampleId]; 245 | for (unsigned int band = 0 ; band < nbOfBands ; band++) 246 | { 247 | m_sum[band][sampleId] += other.m_sum[band][sampleId]; 248 | m_cosum[band][sampleId] += other.m_cosum[band][sampleId]; 249 | m_sqSum[band][sampleId] += other.m_sqSum[band][sampleId]; 250 | if (other.m_min[band][sampleId] < m_min[band][sampleId]) 251 | m_min[band][sampleId] = other.m_min[band][sampleId]; 252 | if (other.m_max[band][sampleId] > m_max[band][sampleId]) 253 | m_max[band][sampleId] = other.m_max[band][sampleId]; 254 | } 255 | } 256 | } 257 | 258 | RealMatrixType m_sum; 259 | RealMatrixType m_sqSum; 260 | RealMatrixType m_cosum; 261 | RealMatrixType m_min; 262 | RealMatrixType m_max; 263 | RealVectorType m_count; 264 | }; 265 | 266 | // Internal threads count 267 | std::vector m_InternalThreadResults; 268 | 269 | // Results 270 | RealMatrixListType m_Means; 271 | RealMatrixListType m_Stds; 272 | RealMatrixListType m_ProdMeans; 273 | RealMatrixListType m_Mins; 274 | RealMatrixListType m_Maxs; 275 | RealMatrixType m_Area; 276 | 277 | private: 278 | PersistentStatisticsMosaicFilter(const Self&); //purposely not implemented 279 | void operator=(const Self&); //purposely not implemented 280 | 281 | }; // end of class 282 | 283 | 284 | /* 285 | * Decorator 286 | */ 287 | template 288 | class ITK_EXPORT StreamingStatisticsMosaicFilter : 289 | public PersistentFilterStreamingDecorator< 290 | PersistentStatisticsMosaicFilter > 291 | { 292 | public: 293 | /** Standard Self typedef */ 294 | typedef StreamingStatisticsMosaicFilter Self; 295 | typedef PersistentFilterStreamingDecorator 296 | > Superclass; 297 | typedef itk::SmartPointer Pointer; 298 | typedef itk::SmartPointer ConstPointer; 299 | 300 | /** Type macro */ 301 | itkNewMacro(Self); 302 | 303 | /** Creation through object factory macro */ 304 | itkTypeMacro(StreamingStatisticsMosaicFilter, PersistentFilterStreamingDecorator); 305 | 306 | /** Typedefs for statistics */ 307 | typedef typename Superclass::FilterType::RealMatrixType RealMatrixType; 308 | typedef typename Superclass::FilterType::RealMatrixObjectType RealMatrixObjectType; 309 | typedef typename Superclass::FilterType::RealMatrixListType RealMatrixListType; 310 | typedef typename Superclass::FilterType::RealMatrixListObjectType RealMatrixListObjectType; 311 | 312 | /** Input image typedefs. */ 313 | typedef typename Superclass::FilterType::InputImageType InputImageType; 314 | 315 | using Superclass::PushBackInput; 316 | void PushBackInput(InputImageType * input) 317 | { 318 | this->GetFilter()->PushBackInput(input); 319 | } 320 | 321 | /** Return the computed Means. */ 322 | RealMatrixListType GetMeans() const 323 | { 324 | return this->GetFilter()->GetMeansOutput()->Get(); 325 | } 326 | RealMatrixListObjectType* GetMeansOutput() 327 | { 328 | return this->GetFilter()->GetMeansOutput(); 329 | } 330 | const RealMatrixListObjectType* GetMeansOutput() const 331 | { 332 | return this->GetFilter()->GetMeansOutput(); 333 | } 334 | 335 | /** Return the computed Stds. */ 336 | RealMatrixListType GetStds() const 337 | { 338 | return this->GetFilter()->GetStdsOutput()->Get(); 339 | } 340 | RealMatrixListObjectType* GetStdsOutput() 341 | { 342 | return this->GetFilter()->GetStdsOutput(); 343 | } 344 | const RealMatrixListObjectType* GetStdsOutput() const 345 | { 346 | return this->GetFilter()->GetStdsOutput(); 347 | } 348 | 349 | /** Return the computed MeansOfProducts. */ 350 | RealMatrixListType GetMeansOfProducts() const 351 | { 352 | return this->GetFilter()->GetMeansOfProductsOutput()->Get(); 353 | } 354 | RealMatrixListObjectType* GetMeansOfProductsOutput() 355 | { 356 | return this->GetFilter()->GetMeansOfProductsOutput(); 357 | } 358 | const RealMatrixListObjectType* GetMeansOfProductsOutput() const 359 | { 360 | return this->GetFilter()->GetMeansOfProductsOutput(); 361 | } 362 | 363 | /** Return the computed Mins. */ 364 | RealMatrixListType GetMins() const 365 | { 366 | return this->GetFilter()->GetMinsOutput()->Get(); 367 | } 368 | RealMatrixListObjectType* GetMinsOutput() 369 | { 370 | return this->GetFilter()->GetMinsOutput(); 371 | } 372 | const RealMatrixListObjectType* GetMinsOutput() const 373 | { 374 | return this->GetFilter()->GetMinsOutput(); 375 | } 376 | 377 | /** Return the computed Maxs. */ 378 | RealMatrixListType GetMaxs() const 379 | { 380 | return this->GetFilter()->GetMaxsOutput()->Get(); 381 | } 382 | RealMatrixListObjectType* GetMaxsOutput() 383 | { 384 | return this->GetFilter()->GetMaxsOutput(); 385 | } 386 | const RealMatrixListObjectType* GetMaxsOutput() const 387 | { 388 | return this->GetFilter()->GetMaxsOutput(); 389 | } 390 | 391 | /** Return the computed Areas. */ 392 | RealMatrixType GetAreas() const 393 | { 394 | return this->GetFilter()->GetAreasOutput()->Get(); 395 | } 396 | RealMatrixObjectType* GetAreasOutput() 397 | { 398 | return this->GetFilter()->GetAreasOutput(); 399 | } 400 | const RealMatrixObjectType* GetAreasOutput() const 401 | { 402 | return this->GetFilter()->GetAreasOutput(); 403 | } 404 | 405 | protected: 406 | /** Constructor */ 407 | StreamingStatisticsMosaicFilter() {}; 408 | /** Destructor */ 409 | ~StreamingStatisticsMosaicFilter() ITK_OVERRIDE {} 410 | 411 | private: 412 | StreamingStatisticsMosaicFilter(const Self &); //purposely not implemented 413 | void operator =(const Self&); //purposely not implemented 414 | }; 415 | 416 | } // end namespace otb 417 | 418 | #ifndef OTB_MANUAL_INSTANTIATION 419 | #include "otbStreamingStatisticsMosaicFilter.txx" 420 | #endif 421 | 422 | #endif 423 | -------------------------------------------------------------------------------- /include/otbStreamingMosaicFilterBase.txx: -------------------------------------------------------------------------------- 1 | #ifndef __StreamingMosaicFilterBase_txx 2 | #define __StreamingMosaicFilterBase_txx 3 | 4 | #include "otbStreamingMosaicFilterBase.h" 5 | 6 | namespace otb { 7 | 8 | template 9 | StreamingMosaicFilterBase 10 | ::StreamingMosaicFilterBase(){ 11 | 12 | m_OutputSpacing.Fill(0); 13 | m_OutputOrigin.Fill(0); 14 | m_OutputSize.Fill(0); 15 | m_ShiftScaleInputImages = false; 16 | m_AutomaticOutputParametersComputation = true; 17 | Superclass::SetCoordinateTolerance(itk::NumericTraits::max() ); 18 | Superclass::SetDirectionTolerance(itk::NumericTraits::max() ); 19 | interpolatorRadius = 0; 20 | nbOfBands = 0; 21 | } 22 | 23 | /** 24 | Compute the input image extent i.e. corners inf & sup 25 | */ 26 | template 27 | void 28 | StreamingMosaicFilterBase 29 | ::ImageToExtent(InputImageType* image, InputImagePointType &extentInf, InputImagePointType &extentSup) 30 | { 31 | 32 | // Get index of the last pixel 33 | InputImageIndexType imageLastIndex; 34 | 35 | for(unsigned int dim = 0; dimGetLargestPossibleRegion().GetSize()[dim]; 38 | } 39 | 40 | // Compute extent 41 | InputImagePointType imageOrigin = image->GetOrigin(); 42 | OutputImagePointType imageEnd; 43 | image->TransformIndexToPhysicalPoint(imageLastIndex, imageEnd); 44 | for(unsigned int dim = 0; dim 60 | bool 61 | StreamingMosaicFilterBase 62 | ::OutputRegionToInputRegion(const OutputImageRegionType &outputRegion, 63 | InputImageRegionType &inputRegion, InputImageType* &inputImage) 64 | { 65 | 66 | // Mosaic Region Start & End (mosaic image index) 67 | OutputImageIndexType outIndexStart = outputRegion.GetIndex(); 68 | OutputImageIndexType outIndexEnd = outputRegion.GetUpperIndex(); 69 | 70 | // Mosaic Region Start & End (geo) 71 | OutputImagePointType outPointStart, outPointEnd; 72 | this->GetOutput()->TransformIndexToPhysicalPoint(outIndexStart, outPointStart); 73 | this->GetOutput()->TransformIndexToPhysicalPoint(outIndexEnd , outPointEnd ); 74 | 75 | // Mosaic Region Start & End (input image index) 76 | InputImageIndexType defIndexStart, defIndexEnd; 77 | inputImage->TransformPhysicalPointToIndex(outPointStart, defIndexStart); 78 | inputImage->TransformPhysicalPointToIndex(outPointEnd , defIndexEnd); 79 | 80 | // Compute input image region 81 | InputImageSizeType defRequestedSize; 82 | InputImageIndexType defRequestedIndex; 83 | for(unsigned int dim = 0; dimGetLargestPossibleRegion() ); 100 | 101 | } 102 | 103 | template 104 | void 105 | StreamingMosaicFilterBase 106 | ::ComputeRequestedRegionOfInputImage(unsigned int inputImageIndex) 107 | { 108 | 109 | // Output requested region 110 | const OutputImageRegionType outRegion = this->GetOutput()->GetRequestedRegion(); 111 | 112 | // Get the input image pointer 113 | InputImageType * inputTile = static_cast( 114 | Superclass::ProcessObject::GetInput(inputImageIndex) ); 115 | InputImageRegionType inRegion; 116 | 117 | // Compute the requested region 118 | if (OutputRegionToInputRegion(outRegion, inRegion, inputTile) ) 119 | { 120 | // Image does overlap requested region: add the image to the used input 121 | // images list 122 | itkDebugMacro( << "Image #" << inputImageIndex << "\n" 123 | << inRegion << " is inside the requested region"); 124 | AddUsedInputImageIndex(inputImageIndex); 125 | } 126 | else 127 | { 128 | // Image does not overlap requested region: set requested region to null 129 | itkDebugMacro( << "Image #" << inputImageIndex << "\n" 130 | << inRegion << " is outside the requested region"); 131 | inRegion.GetModifiableSize().Fill(0); 132 | inRegion.GetModifiableIndex().Fill(0); 133 | } 134 | inputTile->SetRequestedRegion(inRegion); 135 | } 136 | 137 | /** 138 | * Generate the input requested region and the used input images list 139 | */ 140 | template 141 | void 142 | StreamingMosaicFilterBase 143 | ::GenerateInputRequestedRegion(void) 144 | { 145 | usedInputIndices.clear(); 146 | 147 | // For each image, get the requested region 148 | for(unsigned int i = 0; i < this->GetNumberOfInputs(); ++i) 149 | { 150 | ComputeRequestedRegionOfInputImage(i); 151 | } 152 | } 153 | 154 | /** Check if scales and shifts are good */ 155 | template 156 | void 157 | StreamingMosaicFilterBase 158 | ::CheckShiftScaleMatrices() 159 | { 160 | 161 | const unsigned int numberOfInputImages = this->GetNumberOfInputImages(); 162 | 163 | // Check shift-scale matrix dimensions 164 | if (m_ShiftScaleInputImages) 165 | { 166 | if (m_ShiftMatrix.rows() == 0) 167 | { 168 | m_ShiftMatrix.set_size(numberOfInputImages, nbOfBands); 169 | m_ShiftMatrix.fill(itk::NumericTraits::Zero); 170 | } 171 | if (m_ScaleMatrix.rows() == 0) 172 | { 173 | m_ScaleMatrix.set_size(numberOfInputImages, nbOfBands); 174 | m_ScaleMatrix.fill(itk::NumericTraits::One); 175 | } 176 | if(m_ShiftMatrix.cols() != nbOfBands || m_ScaleMatrix.cols() != nbOfBands) 177 | { 178 | itkWarningMacro(<<"Shift-Scale matrices should have " << nbOfBands << " cols (1 col/band)" 179 | << " instead of " << m_ShiftMatrix.cols()); 180 | } 181 | if(m_ShiftMatrix.rows() != numberOfInputImages || m_ScaleMatrix.rows() != numberOfInputImages) 182 | { 183 | itkWarningMacro(<<"Shift-Scale matrices must have " << numberOfInputImages << " rows (1 row/input image)" 184 | << " instead of " << m_ShiftMatrix.rows()); 185 | } 186 | } 187 | } 188 | 189 | /* 190 | * Compute output parameters: 191 | * -number of component per pixel 192 | * -spacing 193 | * -size 194 | * -origin 195 | */ 196 | template 197 | void 198 | StreamingMosaicFilterBase 199 | ::ComputeOutputParameters(void) 200 | { 201 | itkDebugMacro(<< "Computing output parameters of the mosaic image"); 202 | 203 | // Initialize extent and spacing 204 | OutputImagePointType extentInf, extentSup; 205 | m_OutputSpacing.Fill(itk::NumericTraits::max()); 206 | extentInf.Fill(itk::NumericTraits::max()); 207 | extentSup.Fill(itk::NumericTraits::NonpositiveMin()); 208 | 209 | // Compute output spacing, size, and origin 210 | for (unsigned int imageIndex = 0 ; imageIndex < this->GetNumberOfInputs() ; imageIndex++) 211 | { 212 | // Read image (cast is required since filter can have multiple input images 213 | // types) 214 | InputImageType * currentImage = static_cast( 215 | Superclass::ProcessObject::GetInput(imageIndex) ); 216 | 217 | // Update mosaic spacing (keep the nearest of 0) 218 | for(unsigned int dim = 0; dimGetSignedSpacing()[dim]) < vcl_abs(m_OutputSpacing[dim]) ) 221 | { 222 | m_OutputSpacing[dim] = currentImage->GetSignedSpacing()[dim]; 223 | } 224 | } 225 | 226 | // Update mosaic image extent 227 | InputImagePointType currentInputImageExtentInf, currentInputImageExtentSup; 228 | ImageToExtent(currentImage, currentInputImageExtentInf, currentInputImageExtentSup); 229 | for(unsigned int dim = 0; dim 251 | void 252 | StreamingMosaicFilterBase 253 | ::GenerateOutputInformation(void) 254 | { 255 | itkDebugMacro( << "Generate output informations" ); 256 | Superclass::GenerateOutputInformation(); 257 | 258 | // check interpolator and put a default interpolator if empty 259 | if (!m_Interpolator) 260 | { 261 | itkDebugMacro( << "No interpolator specified. Using default" ); 262 | typename DefaultInterpolatorType::Pointer interp = DefaultInterpolatorType::New(); 263 | m_Interpolator = static_cast( interp.GetPointer() ); 264 | 265 | } 266 | 267 | // buffer padding radius 268 | interpolatorRadius = StreamingTraitsType::CalculateNeededRadiusForInterpolator(m_Interpolator); 269 | 270 | // If AutomaticOutputParametersComputation mode is TRUE 271 | if (m_AutomaticOutputParametersComputation) 272 | { 273 | ComputeOutputParameters(); // compute output size, spacing, origin 274 | } 275 | 276 | // Update/Check following things: 277 | // -number of component per pixel 278 | // -projection 279 | nbOfBands = 0; 280 | std::string projectionRef = ""; 281 | for (unsigned int imageIndex = 0 ; imageIndex < this->GetNumberOfInputs() ; imageIndex++) 282 | { 283 | itkDebugMacro(<< "Input image #" << imageIndex); 284 | 285 | // Read image (cast is required since filter can have multiple input images 286 | // types) 287 | InputImageType * currentImage = static_cast( 288 | Superclass::ProcessObject::GetInput(imageIndex) ); 289 | 290 | itkDebugMacro( << "\tSize : " << currentImage->GetLargestPossibleRegion().GetSize() ); 291 | itkDebugMacro( << "\tSpacing: " << currentImage->GetSignedSpacing() ); 292 | itkDebugMacro( << "\tOrigin : " << currentImage->GetOrigin() ); 293 | 294 | // Update number of bands (keep the max) 295 | nbOfBands = vnl_math_max(nbOfBands, currentImage->GetNumberOfComponentsPerPixel() ); 296 | 297 | // Check projection 298 | itk::MetaDataDictionary metaData = currentImage->GetMetaDataDictionary(); 299 | std::string currentProjectionRef; 300 | if (metaData.HasKey(otb::MetaDataKey::ProjectionRefKey) ) 301 | { 302 | itk::ExposeMetaData(metaData, static_cast(otb::MetaDataKey::ProjectionRefKey), 303 | currentProjectionRef); 304 | } 305 | 306 | if (projectionRef.size()!=0) 307 | { 308 | if (currentProjectionRef.size()!=0) 309 | { 310 | if (currentProjectionRef.compare(projectionRef)!=0) 311 | { 312 | itkWarningMacro(<< "Input images may have not the same projection"); 313 | } 314 | } 315 | } 316 | else 317 | projectionRef=currentProjectionRef; 318 | 319 | } 320 | itk::MetaDataDictionary mosaicMetaData; 321 | itk::EncapsulateMetaData(mosaicMetaData, 322 | static_cast(otb::MetaDataKey::ProjectionRefKey), projectionRef); 323 | 324 | // check no data pixels 325 | if (m_NoDataOutputPixel.GetSize()!=nbOfBands || m_NoDataInputPixel.GetSize()!=nbOfBands) 326 | { 327 | if (m_NoDataOutputPixel.GetSize()!=0) 328 | itkWarningMacro(<< "Specified NoDataOutputPixel has not "<::Zero); 335 | m_NoDataInputPixel.Fill(itk::NumericTraits::Zero); 336 | } 337 | 338 | // Write no data flags 339 | std::vector noDataValueAvailable; 340 | std::vector noDataValues1; 341 | for (unsigned int band = 0 ; band < nbOfBands ; band++) 342 | { 343 | noDataValueAvailable.push_back(true); 344 | noDataValues1.push_back(static_cast(m_NoDataOutputPixel[band])); 345 | } 346 | otb::WriteNoDataFlags(noDataValueAvailable, noDataValues1, this->GetOutput()->GetMetaDataDictionary()); 347 | 348 | // Get min & max values from output pixel type 349 | minOutputPixelValue = 350 | static_cast(itk::NumericTraits::NonpositiveMin() ); 351 | maxOutputPixelValue = static_cast(itk::NumericTraits::max() ); 352 | 353 | // Output parameters 354 | OutputImageIndexType outputRegionStart; 355 | outputRegionStart.Fill(0); 356 | OutputImageRegionType outputRegion(outputRegionStart, m_OutputSize); 357 | OutputImageType * outputPtr = this->GetOutput(); 358 | outputPtr->SetOrigin ( m_OutputOrigin ); 359 | outputPtr->SetSignedSpacing ( m_OutputSpacing ); 360 | outputPtr->SetNumberOfComponentsPerPixel( nbOfBands ); 361 | outputPtr->SetLargestPossibleRegion( outputRegion ); 362 | 363 | itkDebugMacro( << "Output mosaic parameters:" 364 | << "\n\tBands : " << nbOfBands 365 | << "\n\tOrigin : " << m_OutputOrigin 366 | << "\n\tSize : " << m_OutputSize 367 | << "\n\tSpacing: " << m_OutputSpacing ); 368 | 369 | // Check shift-scale matrices 370 | if (m_ShiftScaleInputImages) 371 | { 372 | CheckShiftScaleMatrices(); 373 | } 374 | 375 | } 376 | 377 | /* 378 | * Check if the pixel is empty 379 | */ 380 | template 381 | bool 382 | StreamingMosaicFilterBase 383 | ::IsPixelNotEmpty(InputImagePixelType& pixelValue) 384 | { 385 | bool isDataInCurrentInputPixel = false; 386 | 387 | for (unsigned int band = 0 ; band < nbOfBands ; band++) 388 | { 389 | isDataInCurrentInputPixel = isDataInCurrentInputPixel || 390 | (pixelValue[band]!=m_NoDataInputPixel[band]); 391 | } 392 | return isDataInCurrentInputPixel; 393 | } 394 | 395 | /* 396 | * Clipping 397 | */ 398 | template 399 | void 400 | StreamingMosaicFilterBase 401 | ::NormalizePixelValue(InternalValueType& pixelValue) 402 | { 403 | if (pixelValue < minOutputPixelValue) 404 | pixelValue = minOutputPixelValue; 405 | if (pixelValue > maxOutputPixelValue) 406 | pixelValue = maxOutputPixelValue; 407 | } 408 | 409 | /** 410 | * Setup state of filter before multi-threading. 411 | * InterpolatorType::SetInputImage is not thread-safe and hence 412 | * has to be setup before ThreadedGenerateData 413 | */ 414 | template 415 | void 416 | StreamingMosaicFilterBase 417 | ::BeforeThreadedGenerateData() 418 | { 419 | if( !m_Interpolator ) 420 | { 421 | itkExceptionMacro(<< "Interpolator not set"); 422 | } 423 | } 424 | 425 | /** 426 | * Setup state of filter after multi-threading. 427 | */ 428 | template 429 | void StreamingMosaicFilterBase 430 | ::AfterThreadedGenerateData() 431 | { 432 | // Disconnect input image from interpolator 433 | m_Interpolator->SetInputImage( NULL ); 434 | } 435 | 436 | template 437 | void StreamingMosaicFilterBase 438 | ::PrepareImageAccessors( 439 | typename std::vector& image, 440 | typename std::vector& interpolator) 441 | { 442 | 443 | // Get number of used input images 444 | const unsigned int n = GetNumberOfUsedInputImages(); 445 | 446 | interpolator.reserve(n); 447 | image.reserve(n); 448 | 449 | // Loop on input images 450 | for (unsigned int i = 0 ; i < n ; i++) 451 | { 452 | // Input image i 453 | image.push_back( const_cast(this->GetInput(usedInputIndices.at(i) ) ) ); 454 | 455 | // Interpolator i 456 | interpolator.push_back( static_cast( (m_Interpolator->CreateAnother() ).GetPointer() ) ); 457 | interpolator[i]->SetInputImage(image[i]); 458 | } 459 | } 460 | 461 | } // end namespace otb 462 | 463 | #endif 464 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | 2 | CeCILL FREE SOFTWARE LICENSE AGREEMENT 3 | 4 | 5 | Notice 6 | 7 | This Agreement is a Free Software license agreement that is the result 8 | of discussions between its authors in order to ensure compliance with 9 | the two main principles guiding its drafting: 10 | 11 | * firstly, compliance with the principles governing the distribution 12 | of Free Software: access to source code, broad rights granted to 13 | users, 14 | * secondly, the election of a governing law, French law, with which 15 | it is conformant, both as regards the law of torts and 16 | intellectual property law, and the protection that it offers to 17 | both authors and holders of the economic rights over software. 18 | 19 | The authors of the CeCILL (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre]) 20 | license are: 21 | 22 | Commissariat à l'Energie Atomique - CEA, a public scientific, technical 23 | and industrial research establishment, having its principal place of 24 | business at 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris, France. 25 | 26 | Centre National de la Recherche Scientifique - CNRS, a public scientific 27 | and technological establishment, having its principal place of business 28 | at 3 rue Michel-Ange, 75794 Paris cedex 16, France. 29 | 30 | Institut National de Recherche en Informatique et en Automatique - 31 | INRIA, a public scientific and technological establishment, having its 32 | principal place of business at Domaine de Voluceau, Rocquencourt, BP 33 | 105, 78153 Le Chesnay cedex, France. 34 | 35 | 36 | Preamble 37 | 38 | The purpose of this Free Software license agreement is to grant users 39 | the right to modify and redistribute the software governed by this 40 | license within the framework of an open source distribution model. 41 | 42 | The exercising of these rights is conditional upon certain obligations 43 | for users so as to preserve this status for all subsequent redistributions. 44 | 45 | In consideration of access to the source code and the rights to copy, 46 | modify and redistribute granted by the license, users are provided only 47 | with a limited warranty and the software's author, the holder of the 48 | economic rights, and the successive licensors only have limited liability. 49 | 50 | In this respect, the risks associated with loading, using, modifying 51 | and/or developing or reproducing the software by the user are brought to 52 | the user's attention, given its Free Software status, which may make it 53 | complicated to use, with the result that its use is reserved for 54 | developers and experienced professionals having in-depth computer 55 | knowledge. Users are therefore encouraged to load and test the 56 | suitability of the software as regards their requirements in conditions 57 | enabling the security of their systems and/or data to be ensured and, 58 | more generally, to use and operate it in the same conditions of 59 | security. This Agreement may be freely reproduced and published, 60 | provided it is not altered, and that no provisions are either added or 61 | removed herefrom. 62 | 63 | This Agreement may apply to any or all software for which the holder of 64 | the economic rights decides to submit the use thereof to its provisions. 65 | 66 | 67 | Article 1 - DEFINITIONS 68 | 69 | For the purpose of this Agreement, when the following expressions 70 | commence with a capital letter, they shall have the following meaning: 71 | 72 | Agreement: means this license agreement, and its possible subsequent 73 | versions and annexes. 74 | 75 | Software: means the software in its Object Code and/or Source Code form 76 | and, where applicable, its documentation, "as is" when the Licensee 77 | accepts the Agreement. 78 | 79 | Initial Software: means the Software in its Source Code and possibly its 80 | Object Code form and, where applicable, its documentation, "as is" when 81 | it is first distributed under the terms and conditions of the Agreement. 82 | 83 | Modified Software: means the Software modified by at least one 84 | Contribution. 85 | 86 | Source Code: means all the Software's instructions and program lines to 87 | which access is required so as to modify the Software. 88 | 89 | Object Code: means the binary files originating from the compilation of 90 | the Source Code. 91 | 92 | Holder: means the holder(s) of the economic rights over the Initial 93 | Software. 94 | 95 | Licensee: means the Software user(s) having accepted the Agreement. 96 | 97 | Contributor: means a Licensee having made at least one Contribution. 98 | 99 | Licensor: means the Holder, or any other individual or legal entity, who 100 | distributes the Software under the Agreement. 101 | 102 | Contribution: means any or all modifications, corrections, translations, 103 | adaptations and/or new functions integrated into the Software by any or 104 | all Contributors, as well as any or all Internal Modules. 105 | 106 | Module: means a set of sources files including their documentation that 107 | enables supplementary functions or services in addition to those offered 108 | by the Software. 109 | 110 | External Module: means any or all Modules, not derived from the 111 | Software, so that this Module and the Software run in separate address 112 | spaces, with one calling the other when they are run. 113 | 114 | Internal Module: means any or all Module, connected to the Software so 115 | that they both execute in the same address space. 116 | 117 | GNU GPL: means the GNU General Public License version 2 or any 118 | subsequent version, as published by the Free Software Foundation Inc. 119 | 120 | Parties: mean both the Licensee and the Licensor. 121 | 122 | These expressions may be used both in singular and plural form. 123 | 124 | 125 | Article 2 - PURPOSE 126 | 127 | The purpose of the Agreement is the grant by the Licensor to the 128 | Licensee of a non-exclusive, transferable and worldwide license for the 129 | Software as set forth in Article 5 hereinafter for the whole term of the 130 | protection granted by the rights over said Software. 131 | 132 | 133 | Article 3 - ACCEPTANCE 134 | 135 | 3.1 The Licensee shall be deemed as having accepted the terms and 136 | conditions of this Agreement upon the occurrence of the first of the 137 | following events: 138 | 139 | * (i) loading the Software by any or all means, notably, by 140 | downloading from a remote server, or by loading from a physical 141 | medium; 142 | * (ii) the first time the Licensee exercises any of the rights 143 | granted hereunder. 144 | 145 | 3.2 One copy of the Agreement, containing a notice relating to the 146 | characteristics of the Software, to the limited warranty, and to the 147 | fact that its use is restricted to experienced users has been provided 148 | to the Licensee prior to its acceptance as set forth in Article 3.1 149 | hereinabove, and the Licensee hereby acknowledges that it has read and 150 | understood it. 151 | 152 | 153 | Article 4 - EFFECTIVE DATE AND TERM 154 | 155 | 156 | 4.1 EFFECTIVE DATE 157 | 158 | The Agreement shall become effective on the date when it is accepted by 159 | the Licensee as set forth in Article 3.1. 160 | 161 | 162 | 4.2 TERM 163 | 164 | The Agreement shall remain in force for the entire legal term of 165 | protection of the economic rights over the Software. 166 | 167 | 168 | Article 5 - SCOPE OF RIGHTS GRANTED 169 | 170 | The Licensor hereby grants to the Licensee, who accepts, the following 171 | rights over the Software for any or all use, and for the term of the 172 | Agreement, on the basis of the terms and conditions set forth hereinafter. 173 | 174 | Besides, if the Licensor owns or comes to own one or more patents 175 | protecting all or part of the functions of the Software or of its 176 | components, the Licensor undertakes not to enforce the rights granted by 177 | these patents against successive Licensees using, exploiting or 178 | modifying the Software. If these patents are transferred, the Licensor 179 | undertakes to have the transferees subscribe to the obligations set 180 | forth in this paragraph. 181 | 182 | 183 | 5.1 RIGHT OF USE 184 | 185 | The Licensee is authorized to use the Software, without any limitation 186 | as to its fields of application, with it being hereinafter specified 187 | that this comprises: 188 | 189 | 1. permanent or temporary reproduction of all or part of the Software 190 | by any or all means and in any or all form. 191 | 192 | 2. loading, displaying, running, or storing the Software on any or 193 | all medium. 194 | 195 | 3. entitlement to observe, study or test its operation so as to 196 | determine the ideas and principles behind any or all constituent 197 | elements of said Software. This shall apply when the Licensee 198 | carries out any or all loading, displaying, running, transmission 199 | or storage operation as regards the Software, that it is entitled 200 | to carry out hereunder. 201 | 202 | 203 | 5.2 ENTITLEMENT TO MAKE CONTRIBUTIONS 204 | 205 | The right to make Contributions includes the right to translate, adapt, 206 | arrange, or make any or all modifications to the Software, and the right 207 | to reproduce the resulting software. 208 | 209 | The Licensee is authorized to make any or all Contributions to the 210 | Software provided that it includes an explicit notice that it is the 211 | author of said Contribution and indicates the date of the creation thereof. 212 | 213 | 214 | 5.3 RIGHT OF DISTRIBUTION 215 | 216 | In particular, the right of distribution includes the right to publish, 217 | transmit and communicate the Software to the general public on any or 218 | all medium, and by any or all means, and the right to market, either in 219 | consideration of a fee, or free of charge, one or more copies of the 220 | Software by any means. 221 | 222 | The Licensee is further authorized to distribute copies of the modified 223 | or unmodified Software to third parties according to the terms and 224 | conditions set forth hereinafter. 225 | 226 | 227 | 5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION 228 | 229 | The Licensee is authorized to distribute true copies of the Software in 230 | Source Code or Object Code form, provided that said distribution 231 | complies with all the provisions of the Agreement and is accompanied by: 232 | 233 | 1. a copy of the Agreement, 234 | 235 | 2. a notice relating to the limitation of both the Licensor's 236 | warranty and liability as set forth in Articles 8 and 9, 237 | 238 | and that, in the event that only the Object Code of the Software is 239 | redistributed, the Licensee allows future Licensees unhindered access to 240 | the full Source Code of the Software by indicating how to access it, it 241 | being understood that the additional cost of acquiring the Source Code 242 | shall not exceed the cost of transferring the data. 243 | 244 | 245 | 5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE 246 | 247 | When the Licensee makes a Contribution to the Software, the terms and 248 | conditions for the distribution of the resulting Modified Software 249 | become subject to all the provisions of this Agreement. 250 | 251 | The Licensee is authorized to distribute the Modified Software, in 252 | source code or object code form, provided that said distribution 253 | complies with all the provisions of the Agreement and is accompanied by: 254 | 255 | 1. a copy of the Agreement, 256 | 257 | 2. a notice relating to the limitation of both the Licensor's 258 | warranty and liability as set forth in Articles 8 and 9, 259 | 260 | and that, in the event that only the object code of the Modified 261 | Software is redistributed, the Licensee allows future Licensees 262 | unhindered access to the full source code of the Modified Software by 263 | indicating how to access it, it being understood that the additional 264 | cost of acquiring the source code shall not exceed the cost of 265 | transferring the data. 266 | 267 | 268 | 5.3.3 DISTRIBUTION OF EXTERNAL MODULES 269 | 270 | When the Licensee has developed an External Module, the terms and 271 | conditions of this Agreement do not apply to said External Module, that 272 | may be distributed under a separate license agreement. 273 | 274 | 275 | 5.3.4 COMPATIBILITY WITH THE GNU GPL 276 | 277 | The Licensee can include a code that is subject to the provisions of one 278 | of the versions of the GNU GPL in the Modified or unmodified Software, 279 | and distribute that entire code under the terms of the same version of 280 | the GNU GPL. 281 | 282 | The Licensee can include the Modified or unmodified Software in a code 283 | that is subject to the provisions of one of the versions of the GNU GPL, 284 | and distribute that entire code under the terms of the same version of 285 | the GNU GPL. 286 | 287 | 288 | Article 6 - INTELLECTUAL PROPERTY 289 | 290 | 291 | 6.1 OVER THE INITIAL SOFTWARE 292 | 293 | The Holder owns the economic rights over the Initial Software. Any or 294 | all use of the Initial Software is subject to compliance with the terms 295 | and conditions under which the Holder has elected to distribute its work 296 | and no one shall be entitled to modify the terms and conditions for the 297 | distribution of said Initial Software. 298 | 299 | The Holder undertakes that the Initial Software will remain ruled at 300 | least by this Agreement, for the duration set forth in Article 4.2. 301 | 302 | 303 | 6.2 OVER THE CONTRIBUTIONS 304 | 305 | The Licensee who develops a Contribution is the owner of the 306 | intellectual property rights over this Contribution as defined by 307 | applicable law. 308 | 309 | 310 | 6.3 OVER THE EXTERNAL MODULES 311 | 312 | The Licensee who develops an External Module is the owner of the 313 | intellectual property rights over this External Module as defined by 314 | applicable law and is free to choose the type of agreement that shall 315 | govern its distribution. 316 | 317 | 318 | 6.4 JOINT PROVISIONS 319 | 320 | The Licensee expressly undertakes: 321 | 322 | 1. not to remove, or modify, in any manner, the intellectual property 323 | notices attached to the Software; 324 | 325 | 2. to reproduce said notices, in an identical manner, in the copies 326 | of the Software modified or not. 327 | 328 | The Licensee undertakes not to directly or indirectly infringe the 329 | intellectual property rights of the Holder and/or Contributors on the 330 | Software and to take, where applicable, vis-à-vis its staff, any and all 331 | measures required to ensure respect of said intellectual property rights 332 | of the Holder and/or Contributors. 333 | 334 | 335 | Article 7 - RELATED SERVICES 336 | 337 | 7.1 Under no circumstances shall the Agreement oblige the Licensor to 338 | provide technical assistance or maintenance services for the Software. 339 | 340 | However, the Licensor is entitled to offer this type of services. The 341 | terms and conditions of such technical assistance, and/or such 342 | maintenance, shall be set forth in a separate instrument. Only the 343 | Licensor offering said maintenance and/or technical assistance services 344 | shall incur liability therefor. 345 | 346 | 7.2 Similarly, any Licensor is entitled to offer to its licensees, under 347 | its sole responsibility, a warranty, that shall only be binding upon 348 | itself, for the redistribution of the Software and/or the Modified 349 | Software, under terms and conditions that it is free to decide. Said 350 | warranty, and the financial terms and conditions of its application, 351 | shall be subject of a separate instrument executed between the Licensor 352 | and the Licensee. 353 | 354 | 355 | Article 8 - LIABILITY 356 | 357 | 8.1 Subject to the provisions of Article 8.2, the Licensee shall be 358 | entitled to claim compensation for any direct loss it may have suffered 359 | from the Software as a result of a fault on the part of the relevant 360 | Licensor, subject to providing evidence thereof. 361 | 362 | 8.2 The Licensor's liability is limited to the commitments made under 363 | this Agreement and shall not be incurred as a result of in particular: 364 | (i) loss due the Licensee's total or partial failure to fulfill its 365 | obligations, (ii) direct or consequential loss that is suffered by the 366 | Licensee due to the use or performance of the Software, and (iii) more 367 | generally, any consequential loss. In particular the Parties expressly 368 | agree that any or all pecuniary or business loss (i.e. loss of data, 369 | loss of profits, operating loss, loss of customers or orders, 370 | opportunity cost, any disturbance to business activities) or any or all 371 | legal proceedings instituted against the Licensee by a third party, 372 | shall constitute consequential loss and shall not provide entitlement to 373 | any or all compensation from the Licensor. 374 | 375 | 376 | Article 9 - WARRANTY 377 | 378 | 9.1 The Licensee acknowledges that the scientific and technical 379 | state-of-the-art when the Software was distributed did not enable all 380 | possible uses to be tested and verified, nor for the presence of 381 | possible defects to be detected. In this respect, the Licensee's 382 | attention has been drawn to the risks associated with loading, using, 383 | modifying and/or developing and reproducing the Software which are 384 | reserved for experienced users. 385 | 386 | The Licensee shall be responsible for verifying, by any or all means, 387 | the suitability of the product for its requirements, its good working 388 | order, and for ensuring that it shall not cause damage to either persons 389 | or properties. 390 | 391 | 9.2 The Licensor hereby represents, in good faith, that it is entitled 392 | to grant all the rights over the Software (including in particular the 393 | rights set forth in Article 5). 394 | 395 | 9.3 The Licensee acknowledges that the Software is supplied "as is" by 396 | the Licensor without any other express or tacit warranty, other than 397 | that provided for in Article 9.2 and, in particular, without any warranty 398 | as to its commercial value, its secured, safe, innovative or relevant 399 | nature. 400 | 401 | Specifically, the Licensor does not warrant that the Software is free 402 | from any error, that it will operate without interruption, that it will 403 | be compatible with the Licensee's own equipment and software 404 | configuration, nor that it will meet the Licensee's requirements. 405 | 406 | 9.4 The Licensor does not either expressly or tacitly warrant that the 407 | Software does not infringe any third party intellectual property right 408 | relating to a patent, software or any other property right. Therefore, 409 | the Licensor disclaims any and all liability towards the Licensee 410 | arising out of any or all proceedings for infringement that may be 411 | instituted in respect of the use, modification and redistribution of the 412 | Software. Nevertheless, should such proceedings be instituted against 413 | the Licensee, the Licensor shall provide it with technical and legal 414 | assistance for its defense. Such technical and legal assistance shall be 415 | decided on a case-by-case basis between the relevant Licensor and the 416 | Licensee pursuant to a memorandum of understanding. The Licensor 417 | disclaims any and all liability as regards the Licensee's use of the 418 | name of the Software. No warranty is given as regards the existence of 419 | prior rights over the name of the Software or as regards the existence 420 | of a trademark. 421 | 422 | 423 | Article 10 - TERMINATION 424 | 425 | 10.1 In the event of a breach by the Licensee of its obligations 426 | hereunder, the Licensor may automatically terminate this Agreement 427 | thirty (30) days after notice has been sent to the Licensee and has 428 | remained ineffective. 429 | 430 | 10.2 A Licensee whose Agreement is terminated shall no longer be 431 | authorized to use, modify or distribute the Software. However, any 432 | licenses that it may have granted prior to termination of the Agreement 433 | shall remain valid subject to their having been granted in compliance 434 | with the terms and conditions hereof. 435 | 436 | 437 | Article 11 - MISCELLANEOUS 438 | 439 | 440 | 11.1 EXCUSABLE EVENTS 441 | 442 | Neither Party shall be liable for any or all delay, or failure to 443 | perform the Agreement, that may be attributable to an event of force 444 | majeure, an act of God or an outside cause, such as defective 445 | functioning or interruptions of the electricity or telecommunications 446 | networks, network paralysis following a virus attack, intervention by 447 | government authorities, natural disasters, water damage, earthquakes, 448 | fire, explosions, strikes and labor unrest, war, etc. 449 | 450 | 11.2 Any failure by either Party, on one or more occasions, to invoke 451 | one or more of the provisions hereof, shall under no circumstances be 452 | interpreted as being a waiver by the interested Party of its right to 453 | invoke said provision(s) subsequently. 454 | 455 | 11.3 The Agreement cancels and replaces any or all previous agreements, 456 | whether written or oral, between the Parties and having the same 457 | purpose, and constitutes the entirety of the agreement between said 458 | Parties concerning said purpose. No supplement or modification to the 459 | terms and conditions hereof shall be effective as between the Parties 460 | unless it is made in writing and signed by their duly authorized 461 | representatives. 462 | 463 | 11.4 In the event that one or more of the provisions hereof were to 464 | conflict with a current or future applicable act or legislative text, 465 | said act or legislative text shall prevail, and the Parties shall make 466 | the necessary amendments so as to comply with said act or legislative 467 | text. All other provisions shall remain effective. Similarly, invalidity 468 | of a provision of the Agreement, for any reason whatsoever, shall not 469 | cause the Agreement as a whole to be invalid. 470 | 471 | 472 | 11.5 LANGUAGE 473 | 474 | The Agreement is drafted in both French and English and both versions 475 | are deemed authentic. 476 | 477 | 478 | Article 12 - NEW VERSIONS OF THE AGREEMENT 479 | 480 | 12.1 Any person is authorized to duplicate and distribute copies of this 481 | Agreement. 482 | 483 | 12.2 So as to ensure coherence, the wording of this Agreement is 484 | protected and may only be modified by the authors of the License, who 485 | reserve the right to periodically publish updates or new versions of the 486 | Agreement, each with a separate number. These subsequent versions may 487 | address new issues encountered by Free Software. 488 | 489 | 12.3 Any Software distributed under a given version of the Agreement may 490 | only be subsequently distributed under the same version of the Agreement 491 | or a subsequent version, subject to the provisions of Article 5.3.4. 492 | 493 | 494 | Article 13 - GOVERNING LAW AND JURISDICTION 495 | 496 | 13.1 The Agreement is governed by French law. The Parties agree to 497 | endeavor to seek an amicable solution to any disagreements or disputes 498 | that may arise during the performance of the Agreement. 499 | 500 | 13.2 Failing an amicable solution within two (2) months as from their 501 | occurrence, and unless emergency proceedings are necessary, the 502 | disagreements or disputes shall be referred to the Paris Courts having 503 | jurisdiction, by the more diligent Party. 504 | 505 | 506 | Version 2.0 dated 2006-09-05. 507 | 508 | --------------------------------------------------------------------------------