diff --git a/app/otbSAROrthoInterferogram.cxx b/app/otbSAROrthoInterferogram.cxx index 8943cf069370caf37f00679a9b08b54908ebaa31..9342fce752eb575edceb0f29df5f4a42df5e0ffe 100644 --- a/app/otbSAROrthoInterferogram.cxx +++ b/app/otbSAROrthoInterferogram.cxx @@ -76,7 +76,7 @@ namespace otb AddParameter(ParameterType_InputImage, "topographicphase", "Input Topographic Phase (estimation with DEM projection)"); SetParameterDescription("topographicphase", "Input Topographic Phase (estimation with DEM projection)."); MandatoryOff("topographicphase"); - + AddParameter(ParameterType_InputImage, "incartmeanmaster", "Input Cartesian Mean Master image"); SetParameterDescription("incartmeanmaster", "Input Cartesian Mean Master image."); @@ -150,14 +150,11 @@ namespace otb FloatVectorImageType::Pointer CartMeanPtr; CartMeanPtr = GetParameterFloatVectorImage("incartmeanmaster"); - filterGroupedBy->SetCartesianMeanInput(CartMeanPtr); filterGroupedBy->SetCompensatedComplexInput(filterCompensatedComplex->GetOutput()); - // Main Output SetParameterOutputImage("out", filterGroupedBy->GetOutput()); - } // Vector for filters std::vector<itk::ProcessObject::Pointer> m_Ref; diff --git a/include/otbSARGroupedByOrthoImageFilter.h b/include/otbSARGroupedByOrthoImageFilter.h index 37f647a1ad98b9b5a028f9aa7687dfe2f18a7c0f..bd2ae6a339ab7b8150b2416b16c9ac3043367fa4 100644 --- a/include/otbSARGroupedByOrthoImageFilter.h +++ b/include/otbSARGroupedByOrthoImageFilter.h @@ -24,6 +24,8 @@ #include "itkImageToImageFilter.h" #include "itkSmartPointer.h" #include "itkPoint.h" +#include "itkSimpleFastMutexLock.h" +#include "itkImageRegionSplitter.h" #include "itkImageScanlineConstIterator.h" #include "itkImageScanlineIterator.h" @@ -128,6 +130,10 @@ public: using Point3DType = itk::Point<double,3>; typedef double ValueType; + typedef itk::SimpleFastMutexLock MutexType; + typedef typename itk::ImageRegionSplitter<2> SplitterType; // Dimension = 2 for inputs + typedef typename SplitterType::Pointer SplitterPointer; + // Typedef for iterators typedef itk::ImageScanlineConstIterator< ImageVectorType > InputIterator; typedef itk::ImageScanlineIterator< ImageOutType > OutputIterator; @@ -150,6 +156,18 @@ public: void SetSARImageKeyWorList(ImageKeywordlist sarImageKWL); void SetDEMImagePtr(ImageDEMPointer demPtr); + + // Getter for arrays called inot callback function + void GetArrays(double * &tmpArray_real, double * &tmpArray_imag, double * &tmpArray_mod, + double * &tmpArray_count) + { + // Assign Ptrs (=> needs reference) + tmpArray_real = m_tmpArray_real; + tmpArray_imag = m_tmpArray_imag; + tmpArray_mod = m_tmpArray_mod; + tmpArray_count = m_tmpArray_count; + } + protected: // Constructor SARGroupedByOrthoImageFilter(); @@ -187,14 +205,33 @@ protected: * Therefore, this implementation provides a ThreadedGenerateData() routine * which is called for each processing thread. The main output image data is * allocated automatically by the superclass prior to calling - * ThreadedGenerateData(). ThreadedGenerateData can only write to the - * portion of the output image specified by the parameter - * "outputRegionForThread" - * + * ThreadedGenerateData(). The implementation of multithreading is overrided here with the used of + * MultiThreader directly */ + using Superclass::ThreadedGenerateData; + /** inputRegion and outputRegion represent the input/output region for the current streaming. + Temporary arrays are shared between all threads. */ + void ThreadedGenerateData(const ImageVectorRegionType& inputRegion, + const ImageOutRegionType& outputRegion, + double * tmpArray_real, double * tmpArray_imag, + double * tmpArray_mod, double * tmpArray_count, + itk::ThreadIdType threadId); + + + /** Static function used as a "callback" by the MultiThreader. The threading + * library will call this routine for each thread, which will delegate the + * control to ThreadedGenerateData(). */ + static ITK_THREAD_RETURN_TYPE ThreaderCallback(void *arg); + + /** Internal structure used for passing image data into the threading library */ + struct ThreadStruct + { + Pointer Filter; + }; + + /** * \sa ImageToImageFilter::ThreadedGenerateData(), * ImageToImageFilter::GenerateData() */ - virtual void ThreadedGenerateData(const ImageOutRegionType& outputRegionForThread, - itk::ThreadIdType threadId) ITK_OVERRIDE; + void GenerateData() override; private: @@ -217,6 +254,13 @@ protected: int m_nbLinesSAR; int m_nbColSAR; + MutexType * m_Mutex; + + // Temporary arrays + double * m_tmpArray_real; + double * m_tmpArray_imag; + double * m_tmpArray_mod; + double * m_tmpArray_count; }; } // End namespace otb diff --git a/include/otbSARGroupedByOrthoImageFilter.txx b/include/otbSARGroupedByOrthoImageFilter.txx index bb6105306270dab41d481853fa55f659c82872fd..4dc7ba1ca258a7363118a692aba1726769103959 100644 --- a/include/otbSARGroupedByOrthoImageFilter.txx +++ b/include/otbSARGroupedByOrthoImageFilter.txx @@ -77,7 +77,8 @@ namespace otb m_geoidEmg96 = new ossimGeoidEgm96(ossimFilename(ConfigurationManager::GetGeoidFile())); } } - + + m_Mutex = new MutexType(); } /** @@ -91,6 +92,10 @@ namespace otb delete m_geoidEmg96; m_geoidEmg96 = 0; } + + delete m_Mutex; + m_Mutex = 0; + } /** @@ -196,10 +201,11 @@ SARGroupedByOrthoImageFilter< TImageVector, TImageDEM, TImageOut > /////////////////////// Main Output : interferogram (into Ground geometry) /////////////////////// // Vector Image : - // At Least 3 Components : + // At Least 4 Components : // _ amplitude // _ phase // _ coherency + // _ count outputPtr->SetNumberOfComponentsPerPixel(4); // The output is defined with the DEM Image @@ -260,12 +266,9 @@ SARGroupedByOrthoImageFilter< TImageVector, TImageDEM, TImageOut > int nbColSAR = m_nbColSAR; int nbLinesSAR = m_nbLinesSAR; - - - //std::cout << "nbColSAR and nbLineSAR : " << nbColSAR << " , " << nbLinesSAR << std::endl; // Margin to apply on direct localisation for the four sides. - int margin = 100; + int margin = 1000; // Indice for the SAR bloc (determined by the Pipeline) ImageOutIndexType id[4] ; @@ -280,7 +283,6 @@ SARGroupedByOrthoImageFilter< TImageVector, TImageDEM, TImageOut > Point2DType pixelSAR_Into_MNT_LatLon(0); Point2DType pixelSAR(0); - // ImageType::IndexType pixelSAR_Into_MNT; itk::ContinuousIndex<double,2> pixelSAR_Into_MNT; Point3DType demGeoPoint; @@ -297,9 +299,6 @@ SARGroupedByOrthoImageFilter< TImageVector, TImageDEM, TImageOut > firstC = nbColSAR; lastC = 0; intoInputImage = true; - - //std::cout << "At the beggindg of OuputToInput intoInputImage = " << intoInputImage << " And firstC, firstL, lastC, lastL : " << firstC << ", " << firstL << ", " << lastC << ", " << lastL - // << std::endl; // For each side of the output region @@ -318,8 +317,8 @@ SARGroupedByOrthoImageFilter< TImageVector, TImageDEM, TImageOut > gptPt.lat = demLatLonPoint[1]; h = m_geoidEmg96->offsetFromEllipsoid(gptPt); } - //demGeoPoint[2] = h; - demGeoPoint[2] = 0; + demGeoPoint[2] = h; + //demGeoPoint[2] = 0; // Call the method of sarSensorModelAdapter m_SarSensorModelAdapter->WorldToLineSampleYZ(demGeoPoint, col_row, y_z); @@ -397,15 +396,8 @@ SARGroupedByOrthoImageFilter< TImageVector, TImageDEM, TImageOut > inputRequestedRegion.SetIndex(inputRequestedRegionIndex); inputRequestedRegion.SetSize(inputRequestedRegionSize); - - //std::cout << "Pouet : " << inputRequestedRegion << std::endl; } - - // std::cout << "At the end of OuputToInput : " << inputRequestedRegion << " with intoInputImage = " << intoInputImage << " And firstC, firstL, lastC, lastL : " << firstC << ", " << firstL << ", " << lastC << ", " << lastL - // << std::endl; - - //std::cout << "At the end of OuputToInput : " << inputRequestedRegion.GetSize() << std::endl; - + return inputRequestedRegion; } @@ -430,8 +422,6 @@ SARGroupedByOrthoImageFilter< TImageVector, TImageDEM, TImageOut > ImageVectorPointer cartesianMeanPtr = const_cast< ImageVectorType * >( this->GetCartesianMeanInput() ); ImageVectorPointer compensatedComplexPtr = const_cast< ImageVectorType * >( this->GetCompensatedComplexInput() ); - //std::cout << "inputRequestedRegion : " << inputRequestedRegion << std::endl; - //if (isIntoInputImages) // { cartesianMeanPtr->SetRequestedRegion(inputRequestedRegion); @@ -441,224 +431,259 @@ SARGroupedByOrthoImageFilter< TImageVector, TImageDEM, TImageOut > // { // itkExceptionMacro(<<"DEM and SAR geometry do not match."); // } + } - /** - * Method ThreadedGenerateDataWithoutTopographicPhase +/** + * Method GenerateData */ template<class TImageVector, class TImageDEM, class TImageOut> void SARGroupedByOrthoImageFilter< TImageVector, TImageDEM, TImageOut > - ::ThreadedGenerateData(const ImageOutRegionType & outputRegionForThread, - itk::ThreadIdType threadId) + ::GenerateData() { - + // Allocate outputs + this->AllocateOutputs(); + + int nbThreads = this->GetNumberOfThreads(); + + // Get Output Requested region + ImageOutRegionType outputRegion = this->GetOutput()->GetRequestedRegion(); + // Compute corresponding input region bool isIntoInputImage = true; - ImageVectorRegionType inputRegionForThread = OutputRegionToInputRegion(outputRegionForThread, isIntoInputImage); + ImageVectorRegionType inputRegion = OutputRegionToInputRegion(outputRegion, isIntoInputImage); - //std::cout << "Pouet : " << inputRegionForThread << " With " << isIntoInputImage << std::endl; + if (isIntoInputImage) + { + // Allocation for temporay arrays + int regionSize = outputRegion.GetSize()[0] * outputRegion.GetSize()[1]; + m_tmpArray_real = new double[regionSize]; + m_tmpArray_imag = new double[regionSize]; + m_tmpArray_mod = new double[regionSize]; + m_tmpArray_count = new double[regionSize]; + for (unsigned int i = 0; i < regionSize; i++) + { + m_tmpArray_real[i] = static_cast<double>(0); + m_tmpArray_imag[i] = static_cast<double>(0); + m_tmpArray_mod[i] = static_cast<double>(0); + m_tmpArray_count[i] = static_cast<double>(0); + } - // Support progress methods/callbacks - itk::ProgressReporter progress( this, threadId, outputRegionForThread.GetNumberOfPixels() ); - - // Iterator on output (Ground geometry) - OutputIterator OutIt(this->GetOutput(), outputRegionForThread); - OutIt.GoToBegin(); - - // Temporary arrays to store outputRegion pixels - int regionSize = outputRegionForThread.GetSize()[0] * outputRegionForThread.GetSize()[1]; - ValueType * tmpArray_real = new ValueType[regionSize]; - ValueType * tmpArray_imag = new ValueType[regionSize]; - ValueType * tmpArray_mod = new ValueType[regionSize]; - ValueType * tmpArray_count = new ValueType[regionSize]; + // Set up the multithreaded processing + ThreadStruct str; + str.Filter = this; - Point2DType demLonLatPoint; - itk::ContinuousIndex<double,2> pixel_Into_DEM_index; - ImageOutIndexType index; + // Setting up multithreader + this->GetMultiThreader()->SetNumberOfThreads(this->GetNumberOfThreads()); + this->GetMultiThreader()->SetSingleMethod(this->ThreaderCallback, &str); - // Init Temporary array (to zero) - for (unsigned int i = 0; i < regionSize; i++) - { - tmpArray_real[i] = static_cast<ValueType>(0); - tmpArray_imag[i] = static_cast<ValueType>(0); - tmpArray_mod[i] = static_cast<ValueType>(0); - tmpArray_count[i] = static_cast<ValueType>(0); - } + // multithread the execution + this->GetMultiThreader()->SingleMethodExecute(); + + // Loop on output + ImageOutPixelType pixelOutput; + pixelOutput.Reserve(4); + int index_intoArray = 0; + + // Iterator on output (Ground geometry) + OutputIterator OutIt(this->GetOutput(), outputRegion); + OutIt.GoToBegin(); - // Scan input and estimate ortho geometry if output Region corresponds to input SAR image - if (isIntoInputImage) - { - // Iterators on inputs (SAR geometry) - InputIterator CartMeanIt(this->GetCartesianMeanInput(), inputRegionForThread); - InputIterator CompComplexIt(this->GetCompensatedComplexInput(), inputRegionForThread); - - CartMeanIt.GoToBegin(); - CompComplexIt.GoToBegin(); - - // Scan the input Region - // for each line - while ( !CartMeanIt.IsAtEnd() && !CompComplexIt.IsAtEnd()) + // For each line + while ( !OutIt.IsAtEnd()) { - CartMeanIt.GoToBeginOfLine(); - CompComplexIt.GoToBeginOfLine(); - - // For each column - while (!CartMeanIt.IsAtEndOfLine() && !CompComplexIt.IsAtEndOfLine()) + OutIt.GoToBeginOfLine(); + + // For each colunm + while (!OutIt.IsAtEndOfLine()) { - // Get elt from cartesian mean image (X, Y and Z) and create an ECEF point with its - ossimEcefPoint cartPoint(CartMeanIt.Get()[0], CartMeanIt.Get()[1], CartMeanIt.Get()[2]); + if (m_tmpArray_count[index_intoArray] > 0) + { + double mod_Acc = sqrt(m_tmpArray_real[index_intoArray]* + m_tmpArray_real[index_intoArray] + + m_tmpArray_imag[index_intoArray]* + m_tmpArray_imag[index_intoArray]); + + // Amplitude + pixelOutput[0] = m_Gain * + sqrt((m_tmpArray_mod[index_intoArray]/(m_tmpArray_count[index_intoArray]))); - // Conversion into World point - ossimGpt worldPoint(cartPoint); + // Phase + pixelOutput[1] = std::atan2(m_tmpArray_imag[index_intoArray], + m_tmpArray_real[index_intoArray]); - demLonLatPoint[0] = worldPoint.lon; - demLonLatPoint[1] = worldPoint.lat; - - // Get Nearest index into DEM/Ground Geometry - // Transform into continuous index - m_DEMPtr->TransformPhysicalPointToContinuousIndex(demLonLatPoint, - pixel_Into_DEM_index); - - // Integer index - index [0] = static_cast<int>(pixel_Into_DEM_index[0]); - index [1] = static_cast<int>(pixel_Into_DEM_index[1]); - - // Check if index into outputRegionForThread - if (index[0] >= outputRegionForThread.GetIndex()[0] && - index[0] < (outputRegionForThread.GetIndex()[0] + - outputRegionForThread.GetSize()[0]) && - index[1] >= outputRegionForThread.GetIndex()[1] && - index[1] < (outputRegionForThread.GetIndex()[1] + - outputRegionForThread.GetSize()[1])) + // Mod 2*Pi + pixelOutput[1] = pixelOutput[1]-(2*M_PI)*floor(pixelOutput[1]/(2*M_PI)); + + // Coherency + pixelOutput[2] = mod_Acc / m_tmpArray_mod[index_intoArray] ; + + // IsData + pixelOutput[3] = m_tmpArray_count[index_intoArray]; + } + else { - //std::cout << "index : " << index << std::endl; - - // Accumulations for CompensatedComplex for current ground index - int index_intoArray = static_cast<int>((index[0]-outputRegionForThread.GetIndex()[0]) + - (index[1] - outputRegionForThread.GetIndex()[1]) * - outputRegionForThread.GetSize()[0]); - - if (index_intoArray > regionSize) - { - std::cout << "WTF !! " << std::endl; - std::cout << "index[0] = " << index[0] << " And " << "index[1] = " << index[1] << - std::endl; - std::cout << "outputRegionForThread.GetIndex()[0] = " << - outputRegionForThread.GetIndex()[0] << " outputRegionForThread.GetIndex()[1] = " << - outputRegionForThread.GetIndex()[1] << std::endl; - std::cout << "outputRegionForThread.GetSize()[0] = " << - outputRegionForThread.GetSize()[0] << " outputRegionForThread.GetSize()[1] = " << - outputRegionForThread.GetSize()[1] << std::endl; - - - std::cout << "index_intoArray = " << index_intoArray << " And index_intoArray " << - regionSize << std::endl; - } - - if (index[0] == 1261 && index[1] == 634) - { - std::cout << "Rien ????????????" << std::endl; - } - - if (index[0] == 1557 && index[1] == 2038) - { - std::cout << "de la donnee !!!!!!" << std::endl; - } - - tmpArray_real[index_intoArray] += CompComplexIt.Get()[0]; - tmpArray_imag[index_intoArray] += CompComplexIt.Get()[1]; - tmpArray_mod[index_intoArray] += CompComplexIt.Get()[2]; - - ++tmpArray_count[index_intoArray]; + pixelOutput[0] = 0; + pixelOutput[1] = 0; + pixelOutput[2] = 0; + pixelOutput[3] = 0; } - ++ CartMeanIt; - ++ CompComplexIt; - + + // Assigne Main output (Groun geometry) + OutIt.Set(pixelOutput); + + // Next colunm + ++OutIt; + ++index_intoArray; } - + // Next line - CartMeanIt.NextLine(); - CompComplexIt.NextLine(); + OutIt.NextLine(); } - - } // End scan inputs + // Free Memory + delete m_tmpArray_real; + m_tmpArray_real = 0; + delete m_tmpArray_imag; + m_tmpArray_imag = 0; + delete m_tmpArray_mod; + m_tmpArray_mod = 0; + delete m_tmpArray_count; + m_tmpArray_count = 0; + } + } + + + // Callback routine used by the threading library. This routine just calls + // the ThreadedGenerateData method after setting the correct region for this + // thread. + template<class TImageVector, class TImageDEM, class TImageOut> + ITK_THREAD_RETURN_TYPE + SARGroupedByOrthoImageFilter< TImageVector, TImageDEM, TImageOut > + ::ThreaderCallback(void *arg) + { + ThreadStruct *str; + int threadId, threadCount; + + threadId = ((itk::MultiThreader::ThreadInfoStruct *) (arg))->ThreadID; + threadCount = ((itk::MultiThreader::ThreadInfoStruct *) (arg))->NumberOfThreads; + str = (ThreadStruct *) (((itk::MultiThreader::ThreadInfoStruct *) (arg))->UserData); + + // Get filter elts (temporary arrays and vector of input regions) + double * tmpArray_real; + double * tmpArray_imag; + double * tmpArray_mod; + double * tmpArray_count; + str->Filter->GetArrays(tmpArray_real, tmpArray_imag, tmpArray_mod, tmpArray_count); + + // Get inputRegion for current thread (Split the input region to get smaller ones : one per thread) + SplitterPointer splitter = SplitterType::New(); + ImageVectorRegionType inputRegionForThread = splitter->GetSplit(threadId, threadCount, + str->Filter->GetInput()->GetRequestedRegion()); - // Loop on output - ImageOutPixelType pixelOutput; - pixelOutput.Reserve(4); - int index_intoArray = 0; - // For each line - while ( !OutIt.IsAtEnd()) + str->Filter->ThreadedGenerateData(inputRegionForThread, + str->Filter->GetOutput()->GetRequestedRegion(), + tmpArray_real, tmpArray_imag, + tmpArray_mod, tmpArray_count, + threadId); + + return ITK_THREAD_RETURN_VALUE; + } + + + /** + * Method ThreadedGenerateData + */ + template<class TImageVector, class TImageDEM, class TImageOut> + void + SARGroupedByOrthoImageFilter< TImageVector, TImageDEM, TImageOut > + ::ThreadedGenerateData(const ImageVectorRegionType& inputRegion, + const ImageOutRegionType& outputRegion, + double * tmpArray_real, double * tmpArray_imag, + double * tmpArray_mod, double * tmpArray_count, + itk::ThreadIdType threadId) + { + + Point2DType demLonLatPoint; + itk::ContinuousIndex<double,2> pixel_Into_DEM_index; + ImageOutIndexType index; + + int regionSize = outputRegion.GetSize()[0] * outputRegion.GetSize()[1]; + + // Iterators on inputs (SAR geometry) + InputIterator CartMeanIt(this->GetCartesianMeanInput(), inputRegion); + InputIterator CompComplexIt(this->GetCompensatedComplexInput(), inputRegion); + + CartMeanIt.GoToBegin(); + CompComplexIt.GoToBegin(); + + // Scan the input Region + // for each line + while ( !CartMeanIt.IsAtEnd() && !CompComplexIt.IsAtEnd()) { - OutIt.GoToBeginOfLine(); + CartMeanIt.GoToBeginOfLine(); + CompComplexIt.GoToBeginOfLine(); - // For each colunm - while (!OutIt.IsAtEndOfLine()) + // For each column + while (!CartMeanIt.IsAtEndOfLine() && !CompComplexIt.IsAtEndOfLine()) { - if (tmpArray_count[index_intoArray] > 0) - { - double mod_Acc = sqrt(tmpArray_real[index_intoArray]*tmpArray_real[index_intoArray] + - tmpArray_imag[index_intoArray]*tmpArray_imag[index_intoArray]); - - // Amplitude - pixelOutput[0] = m_Gain * - sqrt((tmpArray_mod[index_intoArray]/(tmpArray_count[index_intoArray]))); + // Get elt from cartesian mean image (X, Y and Z) and create an ECEF point with its + ossimEcefPoint cartPoint(CartMeanIt.Get()[0], CartMeanIt.Get()[1], CartMeanIt.Get()[2]); - // Phase - pixelOutput[1] = std::atan2(tmpArray_imag[index_intoArray], - tmpArray_real[index_intoArray]); + // Conversion into World point + ossimGpt worldPoint(cartPoint); - // Mod 2*Pi - pixelOutput[1] = pixelOutput[1]-(2*M_PI)*floor(pixelOutput[1]/(2*M_PI)); - - // Coherency - pixelOutput[2] = mod_Acc / tmpArray_mod[index_intoArray] ; - - // IsData - pixelOutput[3] = tmpArray_count[index_intoArray]; - } - else + demLonLatPoint[0] = worldPoint.lon; + demLonLatPoint[1] = worldPoint.lat; + + // Get Nearest index into DEM/Ground Geometry + // Transform into continuous index + m_DEMPtr->TransformPhysicalPointToContinuousIndex(demLonLatPoint, + pixel_Into_DEM_index); + + // Integer index + index [0] = static_cast<int>(pixel_Into_DEM_index[0]); + index [1] = static_cast<int>(pixel_Into_DEM_index[1]); + + // Check if index into outputRegion + if (index[0] >= outputRegion.GetIndex()[0] && + index[0] < (outputRegion.GetIndex()[0] + + outputRegion.GetSize()[0]) && + index[1] >= outputRegion.GetIndex()[1] && + index[1] < (outputRegion.GetIndex()[1] + + outputRegion.GetSize()[1])) { - pixelOutput[0] = 0; - pixelOutput[1] = 0; - pixelOutput[2] = 0; - pixelOutput[3] = 0; + // Accumulations for CompensatedComplex for current ground index + int index_intoArray = static_cast<int>((index[0]-outputRegion.GetIndex()[0]) + + (index[1] - outputRegion.GetIndex()[1]) * + outputRegion.GetSize()[0]); + + // Mutex to protect class arguments (m_*Arrays) + m_Mutex->Lock(); + tmpArray_real[index_intoArray] += CompComplexIt.Get()[0]; + tmpArray_imag[index_intoArray] += CompComplexIt.Get()[1]; + tmpArray_mod[index_intoArray] += CompComplexIt.Get()[2]; + ++tmpArray_count[index_intoArray]; + m_Mutex->Unlock(); } - - // Assigne Main output (Groun geometry) - OutIt.Set(pixelOutput); - progress.CompletedPixel(); - - // Next colunm - ++OutIt; - ++index_intoArray; + ++ CartMeanIt; + ++ CompComplexIt; + } - + // Next line - OutIt.NextLine(); - } + CartMeanIt.NextLine(); + CompComplexIt.NextLine(); + } // End scan inputs - - // Free Memory - delete tmpArray_real; - tmpArray_real = 0; - delete tmpArray_imag; - tmpArray_imag = 0; - delete tmpArray_mod; - tmpArray_mod = 0; - delete tmpArray_count; - tmpArray_count = 0; - } - - - - } /*namespace otb*/ + + +} /*namespace otb*/ #endif