diff --git a/Modules/Feature/Descriptors/test/CMakeLists.txt b/Modules/Feature/Descriptors/test/CMakeLists.txt index 01e15723f36c1d542e6822989db9dfffeb4b4c69..0fe85ecd942620afc349c8150998d3dc3f4b3cc2 100644 --- a/Modules/Feature/Descriptors/test/CMakeLists.txt +++ b/Modules/Feature/Descriptors/test/CMakeLists.txt @@ -22,54 +22,19 @@ otb_module_test() set(OTBDescriptorsTests otbDescriptorsTestDriver.cxx -otbImageToSURFKeyPointSetFilterOutputDescriptorAscii.cxx -otbImageToSIFTKeyPointSetFilterOutputInterestPointAscii.cxx otbHistogramOfOrientedGradientCovariantImageFunction.cxx -otbImageToSURFKeyPointSetFilterOutputInterestPointAscii.cxx -otbKeyPointSetsMatchingFilter.cxx -otbImageToSIFTKeyPointSetFilterOutputDescriptorAscii.cxx -otbImageToSIFTKeyPointSetFilterOutputAscii.cxx otbFourierMellinImageFilter.cxx otbImageToHessianDeterminantImageFilter.cxx -otbImageToSIFTKeyPointSetFilterOutputImage.cxx otbFourierMellinDescriptors.cxx -otbImageToSIFTKeyPointSetFilterDistanceMap.cxx +otbKeyPointsAlgorithmsTest.cxx ) -if(OTB_USE_SIFTFAST) - list(APPEND OTBDescriptorsTests - otbImageToFastSIFTKeyPointSetFilterOutputInterestPointAscii.cxx - otbImageToFastSIFTKeyPointSetFilterOutputDescriptorAscii.cxx - ) -endif() - add_executable(otbDescriptorsTestDriver ${OTBDescriptorsTests}) target_link_libraries(otbDescriptorsTestDriver ${OTBDescriptors-Test_LIBRARIES}) otb_module_target_label(otbDescriptorsTestDriver) # Tests Declaration -otb_add_test(NAME feTvImageToSURFKeyPointSetFilterSceneOutputDescriptorAscii COMMAND otbDescriptorsTestDriver - --compare-ascii ${EPSILON_3} - ${BASELINE_FILES}/feTvImageToSURFKeyPointSetFilterSceneKeysOutputDescriptor.txt - ${TEMP}/feTvImageToSURFKeyPointSetFilterSceneKeysOutputDescriptor.txt - otbImageToSURFKeyPointSetFilterOutputDescriptorAscii - ${INPUTDATA}/scene.png - ${TEMP}/feTvImageToSURFKeyPointSetFilterSceneKeysOutputDescriptor.txt - 3 3 - ) - - -otb_add_test(NAME feTvImageToSIFTKeyPointSetFilterSceneOutputInterestPointAscii COMMAND otbDescriptorsTestDriver - --ignore-order --compare-ascii ${EPSILON_3} - ${BASELINE_FILES}/feTvImageToSIFTKeyPointSetFilterSceneKeysOutputInterestPoint.txt - ${TEMP}/feTvImageToSIFTKeyPointSetFilterSceneKeysOutputInterestPoint.txt - otbImageToSIFTKeyPointSetFilterOutputInterestPointAscii - ${INPUTDATA}/scene.png - ${TEMP}/feTvImageToSIFTKeyPointSetFilterSceneKeysOutputInterestPoint.txt - 6 3 0.08 10.0 - ) - otb_add_test(NAME feTvHistogramOfOrientedGradientCovariantImageFunction COMMAND otbDescriptorsTestDriver --compare-ascii ${EPSILON_8} ${BASELINE_FILES}/feTvHistogramOfOrientedGradientCovariantImageFunction.txt @@ -80,94 +45,7 @@ otb_add_test(NAME feTvHistogramOfOrientedGradientCovariantImageFunction COMMAND 5 273 64 ) -otb_add_test(NAME feTvImageToSURFKeyPointSetFilterSceneOutputInterestPointAscii COMMAND otbDescriptorsTestDriver - --compare-ascii ${EPSILON_3} - ${BASELINE_FILES}/feTvImageToSURFKeyPointSetFilterSceneKeysOutputInterestPoint.txt - ${TEMP}/feTvImageToSURFKeyPointSetFilterSceneKeysOutputInterestPoint.txt - otbImageToSURFKeyPointSetFilterOutputInterestPointAscii - ${INPUTDATA}/scene.png - ${TEMP}/feTvImageToSURFKeyPointSetFilterSceneKeysOutputInterestPoint.txt - 3 3 - ) - -otb_add_test(NAME feTvKeyPointSetsMatchingFilter COMMAND otbDescriptorsTestDriver - --compare-ascii ${EPSILON_3} - ${BASELINE_FILES}/feTvKeyPointSetsMatchingFilterOutputAscii.txt - ${TEMP}/feTvKeyPointSetsMatchingFilterOutputAscii.txt - otbKeyPointSetsMatchingFilter - ${TEMP}/feTvKeyPointSetsMatchingFilterOutputAscii.txt - 0.6 0 - ) - -otb_add_test(NAME feTvImageToSIFTKeyPointSetFilterSceneDescriptorAscii COMMAND otbDescriptorsTestDriver - --ignore-order --compare-ascii ${EPSILON_3} - ${BASELINE_FILES}/feTvImageToSIFTKeyPointSetFilterSceneKeysOutputDescriptor.txt - ${TEMP}/feTvImageToSIFTKeyPointSetFilterSceneKeysOutputDescriptor.txt - otbImageToSIFTKeyPointSetFilterOutputDescriptorAscii - ${INPUTDATA}/scene.png - ${TEMP}/feTvImageToSIFTKeyPointSetFilterSceneKeysOutputDescriptor.txt - 6 3 0.08 10.0 - ) -otb_add_test(NAME feTvImageToSIFTKeyPointSetFilterGridOutputAscii COMMAND otbDescriptorsTestDriver - --compare-ascii ${EPSILON_3} - ${BASELINE_FILES}/feTvImageToSIFTKeyPointSetFilterGridKeysOutput.txt - ${TEMP}/feTvImageToSIFTKeyPointSetFilterGridKeysOutput.txt - otbImageToSIFTKeyPointSetFilterOutputAscii - ${INPUTDATA}/damier.png - ${TEMP}/feTvImageToSIFTKeyPointSetFilterGridKeysOutput.txt - 7 3 0.01 10.0 - ) - -otb_add_test(NAME feTvImageToSIFTKeyPointSetFilterSquareRotatedOutputAscii COMMAND otbDescriptorsTestDriver - --compare-ascii ${EPSILON_3} - ${BASELINE_FILES}/feTvImageToSIFTKeyPointSetFilterSquareRotatedKeysOutput.txt - ${TEMP}/feTvImageToSIFTKeyPointSetFilterSquareRotatedKeysOutput.txt - otbImageToSIFTKeyPointSetFilterOutputAscii - ${INPUTDATA}/carre_ori.png - ${TEMP}/feTvImageToSIFTKeyPointSetFilterSquareRotatedKeysOutput.txt - 7 3 0.01 10.0 - ) - -otb_add_test(NAME feTvImageToSIFTKeyPointSetFilterSquare2OutputAscii COMMAND otbDescriptorsTestDriver - --compare-ascii ${EPSILON_3} - ${BASELINE_FILES}/feTvImageToSIFTKeyPointSetFilterSquareKeysOutput2.txt - ${TEMP}/feTvImageToSIFTKeyPointSetFilterSquareKeysOutput2.txt - otbImageToSIFTKeyPointSetFilterOutputAscii - ${INPUTDATA}/carre.png - ${TEMP}/feTvImageToSIFTKeyPointSetFilterSquareKeysOutput2.txt - 1 3 0.2 0.9 - ) - -otb_add_test(NAME feTvImageToSIFTKeyPointSetFilterSquareRotated2OutputAscii COMMAND otbDescriptorsTestDriver - --compare-ascii ${EPSILON_3} - ${BASELINE_FILES}/feTvImageToSIFTKeyPointSetFilterSquareRotatedKeysOutput2.txt - ${TEMP}/feTvImageToSIFTKeyPointSetFilterSquareRotatedKeysOutput2.txt - otbImageToSIFTKeyPointSetFilterOutputAscii - ${INPUTDATA}/carre_ori.png - ${TEMP}/feTvImageToSIFTKeyPointSetFilterSquareRotatedKeysOutput2.txt - 1 3 0.215 10.0 - ) - -otb_add_test(NAME feTvImageToSIFTKeyPointSetFilterSquareOutputAscii COMMAND otbDescriptorsTestDriver - --compare-ascii ${EPSILON_3} - ${BASELINE_FILES}/feTvImageToSIFTKeyPointSetFilterSquareKeysOutput.txt - ${TEMP}/feTvImageToSIFTKeyPointSetFilterSquareKeysOutput.txt - otbImageToSIFTKeyPointSetFilterOutputAscii - ${INPUTDATA}/carre.png - ${TEMP}/feTvImageToSIFTKeyPointSetFilterSquareKeysOutput.txt - 7 3 0.01 10.0 - ) - -otb_add_test(NAME feTvImageToSIFTKeyPointSetFilterQB_SuburbOutputAscii COMMAND otbDescriptorsTestDriver - --compare-ascii ${EPSILON_3} - ${BASELINE_FILES}/feTvImageToSIFTKeyPointSetFilterQB_SuburbOutputAscii.txt - ${TEMP}/feTvImageToSIFTKeyPointSetFilterQB_SuburbOutputAscii.txt - otbImageToSIFTKeyPointSetFilterOutputAscii - ${INPUTDATA}/QB_Suburb.png - ${TEMP}/feTvImageToSIFTKeyPointSetFilterQB_SuburbOutputAscii.txt - 2 3 5.0 0.0 - ) otb_add_test(NAME feTvForwardFourierMellinImageFilter COMMAND otbDescriptorsTestDriver --compare-n-images ${EPSILON_6} 2 @@ -190,26 +68,6 @@ otb_add_test(NAME feTvImageToHessianDeterminantImageFilter COMMAND otbDescriptor 1.5 ) -otb_add_test(NAME feTvImageToSIFTKeyPointSetFilterSquareOutputImage COMMAND otbDescriptorsTestDriver - --compare-image ${EPSILON_8} - ${BASELINE}/feTvImageToSIFTKeyPointSetFilterSquareImageOutput.png - ${TEMP}/feTvImageToSIFTKeyPointSetFilterSquareImageOutput.png - otbImageToSIFTKeyPointSetFilterOutputImage - ${INPUTDATA}/carre.png - ${TEMP}/feTvImageToSIFTKeyPointSetFilterSquareImageOutput.png - 7 3 0.01 10.0 - ) - -otb_add_test(NAME feTvImageToSIFTKeyPointSetFilterGridOutputImage COMMAND otbDescriptorsTestDriver - --compare-image ${EPSILON_8} - ${BASELINE}/feTvImageToSIFTKeyPointSetFilterGridImageOutput.png - ${TEMP}/feTvImageToSIFTKeyPointSetFilterGridImageOutput.png - otbImageToSIFTKeyPointSetFilterOutputImage - ${INPUTDATA}/damier.png - ${TEMP}/feTvImageToSIFTKeyPointSetFilterGridImageOutput.png - 7 3 0.01 10.0 - ) - otb_add_test(NAME feTvFourierMellinDescriptorsRotationInvariant COMMAND otbDescriptorsTestDriver otbFourierMellinDescriptorsRotationInvariant ${INPUTDATA}/poupees.png @@ -237,41 +95,7 @@ otb_add_test(NAME feTvFourierMellinDescriptors COMMAND otbDescriptorsTestDriver ${TEMP}/feTvFourierMellinDescriptors.txt ) -otb_add_test(NAME feTvImageToSIFTKeyPointSetFilterDistanceMap COMMAND otbDescriptorsTestDriver - --compare-ascii ${EPSILON_3} - ${BASELINE_FILES}/feTvImageToSIFTKeyPointSetFilterDistanceMap.txt - ${TEMP}/feTvImageToSIFTKeyPointSetFilterDistanceMap.txt - --ignore-lines-with 2 INFO DEBUG - otbImageToSIFTKeyPointSetFilterDistanceMap - ${INPUTDATA}/scene.png - 6 3 0.08 10.0 - 15.0 # rotation - 1.2 # zoom factor - 10 255 - ${TEMP}/feTvImageToSIFTKeyPointSetFilterDistanceMap.txt - ) - -if(OTB_USE_SIFTFAST) -otb_add_test(NAME feTvImageToFastSIFTKeyPointSetFilterSceneOutputInterestPointAscii COMMAND otbDescriptorsTestDriver - --ignore-order --compare-ascii ${EPSILON_3} - ${BASELINE_FILES}/feTvImageToFastSIFTKeyPointSetFilterSceneKeysOutputInterestPoint.txt - ${TEMP}/feTvImageToFastSIFTKeyPointSetFilterSceneKeysOutputInterestPoint.txt - otbImageToFastSIFTKeyPointSetFilterOutputInterestPointAscii - ${INPUTDATA}/ROI_IKO_PAN_LesHalles_sub.tif - ${TEMP}/feTvImageToFastSIFTKeyPointSetFilterSceneKeysOutputInterestPoint.txt - 6 - ) - -# RK: 06/2016. the root cause of this test having different output on platforms comes from libsiftfast (3rd party code) -# Until there is a fix, that failure cannot be attributed to OTB or dashboard results -# --ignore-order --epsilon-boundary 0.01 --compare-ascii ${EPSILON_2} -# ${BASELINE_FILES}/feTvImageToFastSIFTKeyPointSetFilterSceneKeysOutputDescriptor.txt -# ${TEMP}/feTvImageToFastSIFTKeyPointSetFilterSceneKeysOutputDescriptor.txt - -otb_add_test(NAME feTvImageToFastSIFTKeyPointSetFilterSceneOutputDescriptorAscii COMMAND otbDescriptorsTestDriver - otbImageToFastSIFTKeyPointSetFilterOutputDescriptorAscii - ${INPUTDATA}/ROI_IKO_PAN_LesHalles_sub.tif - ${TEMP}/feTvImageToFastSIFTKeyPointSetFilterSceneKeysOutputDescriptor.txt - 6 - ) -endif() +otb_add_test(NAME feTvKeyPointsAlgorithmsTest COMMAND otbDescriptorsTestDriver + otbKeyPointsAlgorithmsTest + ${INPUTDATA}/QB_TOULOUSE_RpcTag_100_100.tif +) diff --git a/Modules/Feature/Descriptors/test/otbDescriptorsTestDriver.cxx b/Modules/Feature/Descriptors/test/otbDescriptorsTestDriver.cxx index 9a319d5b1663b957d10725f9da78a89d6321b101..3a6d21657d06621d9b6663e150cfb5bc77514b08 100644 --- a/Modules/Feature/Descriptors/test/otbDescriptorsTestDriver.cxx +++ b/Modules/Feature/Descriptors/test/otbDescriptorsTestDriver.cxx @@ -22,22 +22,11 @@ void RegisterTests() { - REGISTER_TEST(otbImageToSURFKeyPointSetFilterOutputDescriptorAscii); - REGISTER_TEST(otbImageToSIFTKeyPointSetFilterOutputInterestPointAscii); REGISTER_TEST(otbHistogramOfOrientedGradientCovariantImageFunction); - REGISTER_TEST(otbImageToSURFKeyPointSetFilterOutputInterestPointAscii); - REGISTER_TEST(otbKeyPointSetsMatchingFilter); - REGISTER_TEST(otbImageToSIFTKeyPointSetFilterOutputDescriptorAscii); - REGISTER_TEST(otbImageToSIFTKeyPointSetFilterOutputAscii); REGISTER_TEST(otbFourierMellinImageFilter); REGISTER_TEST(otbImageToHessianDeterminantImageFilter); - REGISTER_TEST(otbImageToSIFTKeyPointSetFilterOutputImage); REGISTER_TEST(otbFourierMellinDescriptors); REGISTER_TEST(otbFourierMellinDescriptorsScaleInvariant); REGISTER_TEST(otbFourierMellinDescriptorsRotationInvariant); - REGISTER_TEST(otbImageToSIFTKeyPointSetFilterDistanceMap); -#ifdef OTB_USE_SIFTFAST - REGISTER_TEST(otbImageToFastSIFTKeyPointSetFilterOutputInterestPointAscii); - REGISTER_TEST(otbImageToFastSIFTKeyPointSetFilterOutputDescriptorAscii); -#endif + REGISTER_TEST(otbKeyPointsAlgorithmsTest); } diff --git a/Modules/Feature/Descriptors/test/otbImageToFastSIFTKeyPointSetFilterOutputDescriptorAscii.cxx b/Modules/Feature/Descriptors/test/otbImageToFastSIFTKeyPointSetFilterOutputDescriptorAscii.cxx deleted file mode 100644 index a711078ca9fb094924b5088c27433e524a799b37..0000000000000000000000000000000000000000 --- a/Modules/Feature/Descriptors/test/otbImageToFastSIFTKeyPointSetFilterOutputDescriptorAscii.cxx +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) - * - * This file is part of Orfeo Toolbox - * - * https://www.orfeo-toolbox.org/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#include <iomanip> -#include <iostream> -#include <fstream> -#include <algorithm> - -#include "otbSiftFastImageFilter.h" -#include "otbImageFileReader.h" -#include "itkPointSet.h" -#include "itkVariableLengthVector.h" -#include "itkRGBPixel.h" -#include "itkImageRegionIterator.h" - -bool CMPData(std::vector<float> a, std::vector<float> b) -{ - return lexicographical_compare(a.begin(), a.begin() + 2, b.begin(), b.begin() + 2); -} - -int otbImageToFastSIFTKeyPointSetFilterOutputDescriptorAscii(int itkNotUsed(argc), char * argv[]) -{ - const char * infname = argv[1]; - const char * outfname = argv[2]; - - const unsigned int scales = atoi(argv[3]); - - typedef float RealType; - const unsigned int Dimension = 2; - - typedef otb::Image<RealType, Dimension> ImageType; - typedef itk::VariableLengthVector<RealType> RealVectorType; - typedef otb::ImageFileReader<ImageType> ReaderType; - typedef itk::PointSet<RealVectorType, Dimension> PointSetType; - typedef otb::SiftFastImageFilter<ImageType, PointSetType> ImageToFastSIFTKeyPointSetFilterType; - - // Iterator types - typedef PointSetType::PointsContainer PointsContainerType; - typedef PointsContainerType::Iterator PointsIteratorType; - typedef PointSetType::PointDataContainer PointDataContainerType; - typedef PointDataContainerType::Iterator PointDataIteratorType; - - typedef std::vector<float> siftDataVector; - typedef std::vector<siftDataVector> ImageDataType; //Kind of PointSet with vectors - - // Instantiating object - ReaderType::Pointer reader = ReaderType::New(); - ImageToFastSIFTKeyPointSetFilterType::Pointer filter = ImageToFastSIFTKeyPointSetFilterType::New(); - - //Instantiation of std::vector for lexicographiacal sorting - ImageDataType imageData; - - reader->SetFileName(infname); - filter->SetInput(reader->GetOutput()); - filter->SetScalesNumber(scales); - filter->Update(); - - PointsIteratorType pIt = filter->GetOutput()->GetPoints()->Begin(); - PointDataIteratorType pDataIt = filter->GetOutput()->GetPointData()->Begin(); - - std::ofstream outfile(outfname); - - outfile << "Number of scales: " << scales << std::endl; - outfile << "Number of SIFT key points: " << filter->GetOutput()->GetNumberOfPoints() << std::endl; - - if (filter->GetOutput()->GetPointData()->Size() != filter->GetOutput()->GetPoints()->Size()) return EXIT_FAILURE; - if (filter->GetOutput()->GetPointData()->Size() == 0) return EXIT_FAILURE; - - // Copy the PointSet to std::vector< std::vector > - while (pIt != filter->GetOutput()->GetPoints()->End() && pDataIt != filter->GetOutput()->GetPointData()->End()) - { - siftDataVector siftData; - - siftData.push_back(pIt.Value()[0]); - siftData.push_back(pIt.Value()[1]); - - unsigned int lIterDesc = 0; - while (lIterDesc < pDataIt.Value().Size()) - { - siftData.push_back(pDataIt.Value()[lIterDesc]); - lIterDesc++; - } - - imageData.push_back(siftData); - ++pIt; - ++pDataIt; - } - - //Sorting the vectors - ImageDataType::iterator itData; - sort(imageData.begin(), imageData.end(), CMPData); - - itData = imageData.begin(); - unsigned int stopVal = static_cast<unsigned int>(filter->GetOutput()->GetPointData()->Begin().Value().Size()); - - while (itData != imageData.end()) - { - unsigned int itDescriptor = 0; - outfile << "[ "; - while (itDescriptor < stopVal) - //while (itDescriptor < static_cast<int>((*itData).size()-2) ) - { - outfile << std::fixed << std::setprecision(4) << (*itData)[itDescriptor + 2] << " "; - itDescriptor++; - } - outfile << "]" << std::endl; - ++itData; - } - - outfile.close(); - - return EXIT_SUCCESS; -} diff --git a/Modules/Feature/Descriptors/test/otbImageToFastSIFTKeyPointSetFilterOutputInterestPointAscii.cxx b/Modules/Feature/Descriptors/test/otbImageToFastSIFTKeyPointSetFilterOutputInterestPointAscii.cxx deleted file mode 100644 index 46b8cfcb022ab690337813800049d8c0cc0ed00e..0000000000000000000000000000000000000000 --- a/Modules/Feature/Descriptors/test/otbImageToFastSIFTKeyPointSetFilterOutputInterestPointAscii.cxx +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) - * - * This file is part of Orfeo Toolbox - * - * https://www.orfeo-toolbox.org/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <iomanip> -#include <iostream> -#include <fstream> -#include <algorithm> - -#include "otbSiftFastImageFilter.h" -#include "otbImageFileReader.h" -#include "otbImageFileWriter.h" -#include "itkPointSet.h" -#include "itkVariableLengthVector.h" -#include "itkRGBPixel.h" -#include "itkImageRegionIterator.h" - -bool CMP(std::vector<float> a, std::vector<float> b) -{ - return lexicographical_compare(a.begin(), a.begin() + 2, b.begin(), b.begin() + 2); -} - -int -otbImageToFastSIFTKeyPointSetFilterOutputInterestPointAscii( int itkNotUsed( argc ), char * argv[] ) -{ - const char * infname = argv[1]; - const char * outfname = argv[2]; - - const unsigned int scales = atoi(argv[3]); - typedef float RealType; - const unsigned int Dimension = 2; - - typedef otb::Image<RealType, Dimension> ImageType; - typedef itk::VariableLengthVector<RealType> RealVectorType; - typedef otb::ImageFileReader<ImageType> ReaderType; - typedef itk::PointSet<RealVectorType, Dimension> PointSetType; - - typedef otb::SiftFastImageFilter<ImageType, PointSetType> ImageToFastSIFTKeyPointSetFilterType; - - // PointSet iterator types - typedef PointSetType::PointsContainer PointsContainerType; - typedef PointsContainerType::Iterator PointsIteratorType; - typedef PointSetType::PointDataContainer PointDataContainerType; - typedef PointDataContainerType::Iterator PointDataIteratorType; - - typedef std::vector< RealType > siftDataVector; - typedef std::vector<siftDataVector> ImageDataType; //Kind of PointSet with vectors - - // Instantiating object - ReaderType::Pointer reader = ReaderType::New(); - ImageToFastSIFTKeyPointSetFilterType::Pointer filter = ImageToFastSIFTKeyPointSetFilterType::New(); - - //Instantiation of std::vector for lexicographiacal sorting - ImageDataType imageData; - - reader->SetFileName(infname); - filter->SetInput(reader->GetOutput()); - filter->SetScalesNumber(scales); - filter->Update(); - PointsIteratorType pIt = filter->GetOutput()->GetPoints()->Begin(); - PointDataIteratorType pDataIt = filter->GetOutput()->GetPointData()->Begin(); - - assert( - filter->GetOutput()->GetPoints()->Size() == - filter->GetOutput()->GetPointData()->Size() ); - - std::ofstream outfile(outfname); - - outfile << "Number of scales: " << scales << std::endl; - - outfile << "Number of SIFT key points: " - << filter->GetOutput()->GetNumberOfPoints() - << std::endl; - - outfile << "Number of points: " - << filter->GetOutput()->GetPoints()->Size() - << std::endl; - - outfile << "Number of points data: " - << filter->GetOutput()->GetPointData()->Size() - << std::endl; - - if( filter->GetOutput()->GetPoints()->Size() != - filter->GetOutput()->GetPointData()->Size() ) - return EXIT_FAILURE; - - // Copy the PointSet to std::vector< std::vector > - while (pIt != filter->GetOutput()->GetPoints()->End()) - { - siftDataVector siftData; - - siftData.push_back(pIt.Value()[0]); - siftData.push_back(pIt.Value()[1]); - - unsigned int lIterDesc = 0; - while (lIterDesc < pDataIt.Value().Size()) - { - siftData.push_back(pDataIt.Value()[lIterDesc]); - lIterDesc++; - } - - imageData.push_back(siftData); - ++pIt; - ++pDataIt; - } - - //Sorting the vectors - ImageDataType::iterator itData; - sort(imageData.begin(), imageData.end(), CMP); - - itData = imageData.begin(); - - while (itData != imageData.end()) - { - outfile << "[" << std::fixed << std::setprecision(1) << (*itData)[0] << ", " << std::setprecision(1) << - (*itData)[1] << "]" << std::endl; - - ++itData; - } - outfile.close(); - - return EXIT_SUCCESS; -} diff --git a/Modules/Feature/Descriptors/test/otbImageToSIFTKeyPointSetFilterDistanceMap.cxx b/Modules/Feature/Descriptors/test/otbImageToSIFTKeyPointSetFilterDistanceMap.cxx deleted file mode 100644 index 2ca4aa327ac2f9d804724acd6c900dc149cbe824..0000000000000000000000000000000000000000 --- a/Modules/Feature/Descriptors/test/otbImageToSIFTKeyPointSetFilterDistanceMap.cxx +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) - * - * This file is part of Orfeo Toolbox - * - * https://www.orfeo-toolbox.org/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <iostream> -#include <fstream> - -#include "itkUnaryFunctorImageFilter.h" -#include "itkPointSet.h" -#include "itkVariableLengthVector.h" -#include "itkResampleImageFilter.h" -#include "itkDanielssonDistanceMapImageFilter.h" -#include "itkPointSetToImageFilter.h" -#include "itkRescaleIntensityImageFilter.h" - -#include "otbImageToSIFTKeyPointSetFilter.h" -#include "otbImage.h" -#include "otbImageFileReader.h" -#include "otbImageFileWriter.h" -#include "itkAffineTransform.h" - -typedef itk::VariableLengthVector<float> RealVectorType; -typedef itk::PointSet<RealVectorType, 2> PointSetType; -typedef otb::Image<float, 2> ImageType; -typedef otb::Image<unsigned char, 2> OutputImageType; - -// PointSet iterator types -typedef PointSetType::PointsContainer PointsContainerType; -typedef PointsContainerType::Iterator PointsIteratorType; -typedef PointSetType::PointDataContainer PointDataContainerType; -typedef PointDataContainerType::Iterator PointDataIteratorType; - -// Filter -typedef otb::ImageFileReader<ImageType> ReaderType; -typedef otb::ImageFileWriter<OutputImageType> WriterType; -typedef otb::ImageFileWriter<ImageType> WriterInputType; - -OutputImageType::Pointer sift(ImageType::Pointer input, - const unsigned int octaves, - const unsigned int scales, - const float threshold, - const float ratio, - const char* siftFileName) -{ - typedef otb::ImageToSIFTKeyPointSetFilter<ImageType, PointSetType> SiftFilterType; - typedef itk::PointSetToImageFilter<PointSetType, OutputImageType> PointSetFilterType; - - SiftFilterType::Pointer sift = SiftFilterType::New(); - PointSetFilterType::Pointer pointSetFilter = PointSetFilterType::New(); - - sift->SetInput(input); - sift->SetOctavesNumber(octaves); - sift->SetScalesNumber(scales); - sift->SetDoGThreshold(threshold); - sift->SetEdgeThreshold(ratio); - - pointSetFilter->SetInput(sift->GetOutput()); - pointSetFilter->SetOutsideValue(0); - pointSetFilter->SetInsideValue(255); - pointSetFilter->SetSize(input->GetLargestPossibleRegion().GetSize()); - pointSetFilter->SetSpacing(input->GetSignedSpacing()); - pointSetFilter->SetOrigin(input->GetOrigin()); - pointSetFilter->Update(); - - WriterType::Pointer writer = WriterType::New(); - writer->SetFileName(siftFileName); - writer->SetInput(pointSetFilter->GetOutput()); - //writer->Update(); - - return pointSetFilter->GetOutput(); -} - -OutputImageType::Pointer ddm(OutputImageType::Pointer input, - const char* ddmFileName) -{ - typedef itk::DanielssonDistanceMapImageFilter <OutputImageType, OutputImageType> DDMFilterType; - DDMFilterType::Pointer ddmFilter = DDMFilterType::New(); - - ddmFilter->SetInput(input); - ddmFilter->InputIsBinaryOn(); - ddmFilter->Update(); - - WriterType::Pointer writer = WriterType::New(); - writer->SetFileName(ddmFileName); - writer->SetInput(ddmFilter->GetOutput()); - //writer->Update(); - - return ddmFilter->GetOutput(); -} - -ImageType::Pointer rotate(ImageType::Pointer input, - const unsigned int rotation) -{ - typedef itk::AffineTransform<double, 2> TransformType; - typedef itk::ResampleImageFilter<ImageType, ImageType> - ResampleFilterType; - ResampleFilterType::Pointer resampler = ResampleFilterType::New(); - - TransformType::Pointer transform = TransformType::New(); - TransformType::OutputVectorType translation1; - TransformType::OutputVectorType translation2; - - const ImageType::SpacingType& spacing = input->GetSignedSpacing(); - const ImageType::PointType& origin = input->GetOrigin(); - ImageType::SizeType size = input->GetLargestPossibleRegion().GetSize(); - - const double imageCenterX = origin[0] + spacing[0] * size[0] / 2.0; - const double imageCenterY = origin[1] + spacing[1] * size[1] / 2.0; - const double degreesToRadians = atan(1.0) / 45.0; - const double angle = rotation * degreesToRadians; - - translation1[0] = -imageCenterX; - translation1[1] = -imageCenterY; - translation2[0] = imageCenterX; - translation2[1] = imageCenterY; - - transform->Translate(translation1); - transform->Rotate2D(-angle, false); - transform->Translate(translation2); - - resampler->SetOutputOrigin(origin); - resampler->SetOutputSpacing(spacing); - resampler->SetSize(size); - resampler->SetTransform(transform); - resampler->SetInput(input); - resampler->Update(); - return resampler->GetOutput(); -} - -OutputImageType::Pointer invRotate(OutputImageType::Pointer input, - const unsigned int rotation) -{ - typedef itk::AffineTransform<double, 2> TransformType; - typedef itk::ResampleImageFilter<OutputImageType, OutputImageType> - ResampleFilterType; - ResampleFilterType::Pointer resampler = ResampleFilterType::New(); - - TransformType::Pointer transform = TransformType::New(); - TransformType::OutputVectorType translation1; - TransformType::OutputVectorType translation2; - - const ImageType::SpacingType& spacing = input->GetSignedSpacing(); - const ImageType::PointType& origin = input->GetOrigin(); - ImageType::SizeType size = input->GetLargestPossibleRegion().GetSize(); - - const double imageCenterX = origin[0] + spacing[0] * size[0] / 2.0; - const double imageCenterY = origin[1] + spacing[1] * size[1] / 2.0; - - const double degreesToRadians = atan(1.0) / 45.0; - const double angle = rotation * degreesToRadians; - - translation1[0] = -imageCenterX; - translation1[1] = -imageCenterY; - translation2[0] = imageCenterX; - translation2[1] = imageCenterY; - - transform->Translate(translation1); - transform->Rotate2D(angle, false); - transform->Translate(translation2); - - resampler->SetOutputOrigin(origin); - resampler->SetOutputSpacing(spacing); - resampler->SetSize(size); - resampler->SetTransform(transform); - resampler->SetInput(input); - resampler->Update(); - return resampler->GetOutput(); -} - -ImageType::Pointer zoom(ImageType::Pointer input, - const unsigned int zoomFactor) -{ - typedef itk::ShrinkImageFilter<ImageType, ImageType> ShrinkFilterType; - ShrinkFilterType::Pointer shrink = ShrinkFilterType::New(); - - shrink->SetInput(input); - shrink->SetShrinkFactors(zoomFactor); - shrink->Update(); - - return shrink->GetOutput(); -} - -OutputImageType::Pointer invZoom(OutputImageType::Pointer input, - const unsigned int zoomFactor) -{ - typedef itk::ExpandImageFilter<OutputImageType, OutputImageType> ExpandFilterType; - ExpandFilterType::Pointer expand = ExpandFilterType::New(); - - expand->SetInput(input); - expand->SetExpandFactors(zoomFactor); - expand->Update(); - - return expand->GetOutput(); -} - -ImageType::Pointer contrast(ImageType::Pointer input, - const unsigned int contrastMin, - const unsigned int contrastMax) -{ - typedef itk::RescaleIntensityImageFilter<ImageType, ImageType> RescaleFilterType; - RescaleFilterType::Pointer rescaler = RescaleFilterType::New(); - - rescaler->SetInput(input); - rescaler->SetOutputMinimum(static_cast<RescaleFilterType::OutputPixelType>(contrastMin)); - rescaler->SetOutputMaximum(static_cast<RescaleFilterType::OutputPixelType>(contrastMax)); - rescaler->Update(); - return rescaler->GetOutput(); -} - -OutputImageType::Pointer invContrast(OutputImageType::Pointer input, - const unsigned int itkNotUsed(contrastMin), - const unsigned int itkNotUsed(contrastMax)) -{ - return input; -} - -void subtract(OutputImageType::Pointer image1, - OutputImageType::Pointer image2, - const char* subtractFileName) -{ - typedef itk::SubtractImageFilter<OutputImageType, OutputImageType, ImageType> SubtractFilterType; - typedef itk::MinimumMaximumImageCalculator<ImageType> MaximumCalculatorType; - typedef itk::RescaleIntensityImageFilter<ImageType, OutputImageType> OutputRescaleFilterType; - - SubtractFilterType::Pointer subtract = SubtractFilterType::New(); - MaximumCalculatorType::Pointer maximumCalculator = MaximumCalculatorType::New(); - - subtract->SetInput1(image1); - subtract->SetInput2(image2); - subtract->Update(); - - OutputRescaleFilterType::Pointer rescaler = OutputRescaleFilterType::New(); - rescaler->SetInput(subtract->GetOutput()); - rescaler->SetOutputMinimum(0); - rescaler->SetOutputMaximum(255); - - WriterType::Pointer writer = WriterType::New(); - writer->SetFileName(subtractFileName); - writer->SetInput(rescaler->GetOutput()); - //writer->Update(); - - maximumCalculator->SetImage(subtract->GetOutput()); - maximumCalculator->Compute(); - - std::cout << "Mix(sub)= " << maximumCalculator->GetMinimum() << " "; - std::cout << "Max(sub)= " << maximumCalculator->GetMaximum() << std::endl; -} - -int otbImageToSIFTKeyPointSetFilterDistanceMap(int argc, char * argv[]) -{ - - if (argc < 10) - { - std::cout << "Missing arguments " << std::endl; - return EXIT_FAILURE; - } - - // Input Image file name - const char * infname = argv[1]; - const char * outfname = argv[10]; - - const unsigned int octaves = atoi(argv[2]); - const unsigned int scales = atoi(argv[3]); - const float threshold = atof(argv[4]); - const float ratio = atof(argv[5]); - - // Rotation angle [0, 360[ - const unsigned int rotation = atoi(argv[6]); - - // Zoom factor - const unsigned int zoomFactor = atoi(argv[7]); - - // contrast factor - const unsigned int contrastMin = atoi(argv[8]); - const unsigned int contrastMax = atoi(argv[9]); - - //redirect cout to a file - std::ofstream file(outfname); - std::streambuf* strm_buffer = std::cout.rdbuf(); //save the cout to put it - //back later - std::cout.rdbuf(file.rdbuf()); - - ReaderType::Pointer reader = ReaderType::New(); - reader->SetFileName(infname); - reader->Update(); - - ImageType::Pointer _rotated = - rotate(reader->GetOutput(), rotation); - ImageType::Pointer _zoomed = - zoom(reader->GetOutput(), zoomFactor); - ImageType::Pointer _contrasted = - contrast(reader->GetOutput(), contrastMin, contrastMax); - - ImageType::Pointer _combined1 = zoom(_rotated, zoomFactor); - ImageType::Pointer _combined2 = contrast(_combined1, contrastMin, contrastMax); - - OutputImageType::Pointer sift_base = - sift(reader->GetOutput(), octaves, scales, threshold, ratio, "sift_base.png"); - - OutputImageType::Pointer _sift_rotated = - sift(_rotated, octaves, scales, threshold, ratio, "sift_rotated.png"); - - OutputImageType::Pointer _sift_zoomed = - sift(_zoomed, octaves, scales, threshold, ratio, "sift_zoomed.png"); - - OutputImageType::Pointer _sift_contrasted = - sift(_contrasted, octaves, scales, threshold, ratio, "sift_contrasted.png"); - - OutputImageType::Pointer _sift_combined = - sift(_combined2, octaves, scales, threshold, ratio, "sift_combined.png"); - - OutputImageType::Pointer sift_rotated = - invRotate(_sift_rotated, rotation); - - OutputImageType::Pointer sift_zoomed = - invZoom(_sift_zoomed, zoomFactor); - - OutputImageType::Pointer sift_contrasted = - invContrast(_sift_contrasted, contrastMin, contrastMax); - - OutputImageType::Pointer _sift_combined1 = - invContrast(_sift_combined, contrastMin, contrastMax); - OutputImageType::Pointer _sift_combined2 = - invRotate(_sift_combined1, rotation); - OutputImageType::Pointer sift_combined = - invZoom(_sift_combined2, zoomFactor); - - OutputImageType::Pointer ddm_base = ddm(sift_base, "ddm_base.png"); - OutputImageType::Pointer ddm_rotated = ddm(sift_rotated, "ddm_rotated.png"); - OutputImageType::Pointer ddm_contrasted = ddm(sift_contrasted, "ddm_contrasted.png"); - OutputImageType::Pointer ddm_zoomed = ddm(sift_zoomed, "ddm_zoomed.png"); - OutputImageType::Pointer ddm_combined = ddm(sift_combined, "ddm_combined.png"); - - subtract(ddm_base, ddm_rotated, - "subtract_rotated.png"); - - subtract(ddm_base, ddm_zoomed, - "subtract_zoomed.png"); - - subtract(ddm_base, ddm_contrasted, - "subtract_contrasted.png"); - - subtract(ddm_base, ddm_combined, - "subtract_combined.png"); - - std::cout.rdbuf(strm_buffer); - file.close(); - - return EXIT_SUCCESS; -} diff --git a/Modules/Feature/Descriptors/test/otbImageToSIFTKeyPointSetFilterOutputAscii.cxx b/Modules/Feature/Descriptors/test/otbImageToSIFTKeyPointSetFilterOutputAscii.cxx deleted file mode 100644 index 57da84a5340018e38a86c7a6f1a20c1e7c038900..0000000000000000000000000000000000000000 --- a/Modules/Feature/Descriptors/test/otbImageToSIFTKeyPointSetFilterOutputAscii.cxx +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) - * - * This file is part of Orfeo Toolbox - * - * https://www.orfeo-toolbox.org/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <iomanip> -#include <iostream> -#include <fstream> - -#include "otbImageToSIFTKeyPointSetFilter.h" -#include "otbImage.h" -#include "otbImageFileReader.h" -#include "otbImageFileWriter.h" -#include "itkPointSet.h" -#include "itkVariableLengthVector.h" -#include "itkRGBPixel.h" -#include "itkImageRegionIterator.h" - -int otbImageToSIFTKeyPointSetFilterOutputAscii(int itkNotUsed(argc), char * argv[]) -{ - const char * infname = argv[1]; - const char * outfname = argv[2]; - - const unsigned int octaves = atoi(argv[3]); - const unsigned int scales = atoi(argv[4]); - const float threshold = atof(argv[5]); - const float ratio = atof(argv[6]); - - typedef float RealType; - const unsigned int Dimension = 2; - - typedef otb::Image<RealType, Dimension> ImageType; - typedef itk::VariableLengthVector<RealType> RealVectorType; - typedef otb::ImageFileReader<ImageType> ReaderType; - typedef itk::PointSet<RealVectorType, Dimension> PointSetType; - typedef otb::ImageToSIFTKeyPointSetFilter<ImageType, PointSetType> ImageToSIFTKeyPointSetFilterType; - - // PointSet iterator type - typedef PointSetType::PointsContainer PointsContainerType; - typedef PointsContainerType::Iterator PointsIteratorType; - typedef PointSetType::PointDataContainer PointDataContainerType; - typedef PointDataContainerType::Iterator PointDataIteratorType; - - // Instantiating object - ReaderType::Pointer reader = ReaderType::New(); - ImageToSIFTKeyPointSetFilterType::Pointer filter = ImageToSIFTKeyPointSetFilterType::New(); - - reader->SetFileName(infname); - filter->SetInput(reader->GetOutput()); - filter->SetOctavesNumber(octaves); - filter->SetScalesNumber(scales); - filter->SetDoGThreshold(threshold); - filter->SetEdgeThreshold(ratio); - filter->Update(); - - PointsIteratorType pIt = filter->GetOutput()->GetPoints()->Begin(); - if (filter->GetOutput()->GetPointData() == nullptr) - { - std::cerr << "No sift point found!" << std::endl; - return EXIT_FAILURE; //Avoid the subsequent segfault, but need to check if that what the test want to do - } - PointDataIteratorType pDataIt = filter->GetOutput()->GetPointData()->Begin(); - - std::ofstream outfile(outfname); - - outfile << "Number of octaves: " << octaves << std::endl; - outfile << "Number of scales: " << scales << std::endl; - outfile << "Number of SIFT key points: " << filter->GetOutput()->GetNumberOfPoints() << std::endl; - while (pIt != filter->GetOutput()->GetPoints()->End()) - { - outfile << "[" << std::fixed << std::setprecision(2) << pIt.Value()[0] << ", " << std::setprecision(2) << - pIt.Value()[1] << "]["; - - unsigned int lIterDesc = 0; - while (lIterDesc < pDataIt.Value().Size()) - { - outfile << std::setprecision(3) << pDataIt.Value()[lIterDesc] << " "; - lIterDesc++; - } - outfile << "]" << std::endl; - ++pIt; - ++pDataIt; - } - - outfile.close(); - - return EXIT_SUCCESS; -} diff --git a/Modules/Feature/Descriptors/test/otbImageToSIFTKeyPointSetFilterOutputDescriptorAscii.cxx b/Modules/Feature/Descriptors/test/otbImageToSIFTKeyPointSetFilterOutputDescriptorAscii.cxx deleted file mode 100644 index 40c64f7fe6a1983d628e02a1b04b961957ff31aa..0000000000000000000000000000000000000000 --- a/Modules/Feature/Descriptors/test/otbImageToSIFTKeyPointSetFilterOutputDescriptorAscii.cxx +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) - * - * This file is part of Orfeo Toolbox - * - * https://www.orfeo-toolbox.org/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <iomanip> -#include <iostream> -#include <fstream> - -#include "otbImageToSIFTKeyPointSetFilter.h" -#include "otbImage.h" -#include "otbImageFileReader.h" -#include "otbImageFileWriter.h" -#include "itkPointSet.h" -#include "itkVariableLengthVector.h" -#include "itkRGBPixel.h" -#include "itkImageRegionIterator.h" - -int otbImageToSIFTKeyPointSetFilterOutputDescriptorAscii(int itkNotUsed(argc), char * argv[]) -{ - const char * infname = argv[1]; - const char * outfname = argv[2]; - - const unsigned int octaves = atoi(argv[3]); - const unsigned int scales = atoi(argv[4]); - const float threshold = atof(argv[5]); - const float ratio = atof(argv[6]); - - typedef float RealType; - const unsigned int Dimension = 2; - - typedef otb::Image<RealType, Dimension> ImageType; - typedef itk::VariableLengthVector<RealType> RealVectorType; - typedef otb::ImageFileReader<ImageType> ReaderType; - typedef itk::PointSet<RealVectorType, Dimension> PointSetType; - typedef otb::ImageToSIFTKeyPointSetFilter<ImageType, PointSetType> ImageToSIFTKeyPointSetFilterType; - - // PointSet terator type - typedef PointSetType::PointsContainer PointsContainerType; - typedef PointsContainerType::Iterator PointsIteratorType; - typedef PointSetType::PointDataContainer PointDataContainerType; - typedef PointDataContainerType::Iterator PointDataIteratorType; - - // Instantiating object - ReaderType::Pointer reader = ReaderType::New(); - ImageToSIFTKeyPointSetFilterType::Pointer filter = ImageToSIFTKeyPointSetFilterType::New(); - - reader->SetFileName(infname); - filter->SetInput(reader->GetOutput()); - filter->SetOctavesNumber(octaves); - filter->SetScalesNumber(scales); - filter->SetDoGThreshold(threshold); - filter->SetEdgeThreshold(ratio); - filter->Update(); - - PointsIteratorType pIt = filter->GetOutput()->GetPoints()->Begin(); - PointDataIteratorType pDataIt = filter->GetOutput()->GetPointData()->Begin(); - - std::ofstream outfile(outfname); - - outfile << "Number of octaves: " << octaves << std::endl; - outfile << "Number of scales: " << scales << std::endl; - outfile << "Number of SIFT key points: " << filter->GetOutput()->GetNumberOfPoints() << std::endl; - while (pIt != filter->GetOutput()->GetPoints()->End()) - { - outfile << "["; - unsigned int lIterDesc = 0; - while (lIterDesc < pDataIt.Value().Size()) - { - outfile << std::setprecision(3) << pDataIt.Value()[lIterDesc] << " "; - lIterDesc++; - } - outfile << "]" << std::endl; - ++pIt; - ++pDataIt; - } - - outfile.close(); - - return EXIT_SUCCESS; -} diff --git a/Modules/Feature/Descriptors/test/otbImageToSIFTKeyPointSetFilterOutputImage.cxx b/Modules/Feature/Descriptors/test/otbImageToSIFTKeyPointSetFilterOutputImage.cxx deleted file mode 100644 index 18a1da214e808e9b588d6b6de2c37c1557bc91ae..0000000000000000000000000000000000000000 --- a/Modules/Feature/Descriptors/test/otbImageToSIFTKeyPointSetFilterOutputImage.cxx +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) - * - * This file is part of Orfeo Toolbox - * - * https://www.orfeo-toolbox.org/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "otbImageToSIFTKeyPointSetFilter.h" -#include "otbImage.h" -#include "otbImageFileReader.h" -#include "otbImageFileWriter.h" -#include "itkPointSet.h" -#include "itkVariableLengthVector.h" -#include "itkRGBPixel.h" -#include "itkImageRegionIterator.h" - -#include <iostream> -#include <fstream> - -int otbImageToSIFTKeyPointSetFilterOutputImage(int itkNotUsed(argc), char * argv[]) -{ - const char * infname = argv[1]; - const char * outputImageFilename = argv[2]; - - const unsigned int octaves = atoi(argv[3]); - const unsigned int scales = atoi(argv[4]); - - float threshold = atof(argv[5]); - float ratio = atof(argv[6]); - - typedef float RealType; - const unsigned int Dimension = 2; - - typedef otb::Image<RealType, Dimension> ImageType; - typedef itk::VariableLengthVector<RealType> RealVectorType; - typedef otb::ImageFileReader<ImageType> ReaderType; - typedef itk::PointSet<RealVectorType, Dimension> PointSetType; - typedef otb::ImageToSIFTKeyPointSetFilter<ImageType, PointSetType> ImageToSIFTKeyPointSetFilterType; - typedef PointSetType::PointsContainer PointsContainerType; - typedef PointsContainerType::Iterator PointsIteratorType; - - // Instantiating object - ReaderType::Pointer reader = ReaderType::New(); - ImageToSIFTKeyPointSetFilterType::Pointer filter = ImageToSIFTKeyPointSetFilterType::New(); - - reader->SetFileName(infname); - filter->SetInput(reader->GetOutput()); - filter->SetOctavesNumber(octaves); - filter->SetScalesNumber(scales); - filter->SetDoGThreshold(threshold); - filter->SetEdgeThreshold(ratio); - - filter->Update(); - - ImageType::OffsetType t = {{ 0, 1}}; - ImageType::OffsetType b = {{ 0, -1}}; - ImageType::OffsetType l = {{ 1, 0}}; - ImageType::OffsetType r = {{-1, 0}}; - - typedef unsigned char PixelType; - typedef itk::RGBPixel<PixelType> RGBPixelType; - typedef otb::Image<RGBPixelType, 2> OutputImageType; - - typedef otb::ImageFileWriter<OutputImageType> WriterType; - OutputImageType::Pointer outputImage = OutputImageType::New(); - OutputImageType::RegionType region; - - OutputImageType::SizeType outputSize; - outputSize[0] = reader->GetOutput()->GetLargestPossibleRegion().GetSize()[0]; - outputSize[1] = reader->GetOutput()->GetLargestPossibleRegion().GetSize()[1]; - region.SetSize(outputSize); - - OutputImageType::IndexType indexStart; - indexStart[0] = 0; - indexStart[1] = 0; - region.SetIndex(indexStart); - - outputImage->SetRegions(region); - outputImage->Allocate(); - - itk::ImageRegionIterator<OutputImageType> iterOutput(outputImage, - outputImage->GetLargestPossibleRegion()); - itk::ImageRegionIterator<ImageType> iterInput(reader->GetOutput(), - reader->GetOutput()->GetLargestPossibleRegion()); - - for (iterOutput.GoToBegin(), iterInput.GoToBegin(); - !iterOutput.IsAtEnd(); - ++iterOutput, ++iterInput) - { - OutputImageType::PixelType rgbPixel; - rgbPixel.SetRed(static_cast<PixelType>(iterInput.Get())); - rgbPixel.SetGreen(static_cast<PixelType>(iterInput.Get())); - rgbPixel.SetBlue(static_cast<PixelType>(iterInput.Get())); - - iterOutput.Set(rgbPixel); - } - - WriterType::Pointer writerTmp = WriterType::New(); - writerTmp->SetFileName(outputImageFilename); - writerTmp->SetInput(outputImage); - writerTmp->Update(); - - std::cout << "Copy Input image in Output image" << std::endl; - - PointsIteratorType pIt = filter->GetOutput()->GetPoints()->Begin(); - ImageType::SpacingType spacing = reader->GetOutput()->GetSignedSpacing(); - ImageType::PointType origin = reader->GetOutput()->GetOrigin(); - //OutputImageType::SizeType size = outputImage->GetLargestPossibleRegion().GetSize(); - - while (pIt != filter->GetOutput()->GetPoints()->End()) - { - ImageType::IndexType index; - - index[0] = (unsigned int) - (std::floor - ((double) ((pIt.Value()[0] - origin[0]) / spacing[0] + 0.5))); - - index[1] = (unsigned int) - (std::floor - ((double) ((pIt.Value()[1] - origin[1]) / spacing[1] + 0.5))); - - OutputImageType::PixelType keyPixel; - keyPixel.SetRed(0); - keyPixel.SetGreen(255); - keyPixel.SetBlue(0); - - if (outputImage->GetLargestPossibleRegion().IsInside(index)) - { - outputImage->SetPixel(index, keyPixel); - - if (outputImage->GetLargestPossibleRegion().IsInside(index + t)) outputImage->SetPixel(index + t, keyPixel); - - if (outputImage->GetLargestPossibleRegion().IsInside(index + b)) outputImage->SetPixel(index + b, keyPixel); - - if (outputImage->GetLargestPossibleRegion().IsInside(index + l)) outputImage->SetPixel(index + l, keyPixel); - - if (outputImage->GetLargestPossibleRegion().IsInside(index + r)) outputImage->SetPixel(index + r, keyPixel); - } - ++pIt; - } - - std::cout << "Copy sift key" << std::endl; - - WriterType::Pointer writer = WriterType::New(); - writer->SetFileName(outputImageFilename); - writer->SetInput(outputImage); - writer->Update(); - - std::cout << "Write image" << std::endl; - return EXIT_SUCCESS; -} diff --git a/Modules/Feature/Descriptors/test/otbImageToSIFTKeyPointSetFilterOutputInterestPointAscii.cxx b/Modules/Feature/Descriptors/test/otbImageToSIFTKeyPointSetFilterOutputInterestPointAscii.cxx deleted file mode 100644 index 51d4d3188621e9f615ed8dbab0bc3f88941892a8..0000000000000000000000000000000000000000 --- a/Modules/Feature/Descriptors/test/otbImageToSIFTKeyPointSetFilterOutputInterestPointAscii.cxx +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) - * - * This file is part of Orfeo Toolbox - * - * https://www.orfeo-toolbox.org/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <iomanip> -#include <iostream> -#include <fstream> - -#include "otbImageToSIFTKeyPointSetFilter.h" -#include "otbImage.h" -#include "otbImageFileReader.h" -#include "otbImageFileWriter.h" -#include "itkPointSet.h" -#include "itkVariableLengthVector.h" -#include "itkRGBPixel.h" -#include "itkImageRegionIterator.h" - -int otbImageToSIFTKeyPointSetFilterOutputInterestPointAscii(int itkNotUsed(argc), char * argv[]) -{ - const char * infname = argv[1]; - const char * outfname = argv[2]; - - const unsigned int octaves = atoi(argv[3]); - const unsigned int scales = atoi(argv[4]); - const float threshold = atof(argv[5]); - const float ratio = atof(argv[6]); - - typedef float RealType; - const unsigned int Dimension = 2; - - typedef otb::Image<RealType, Dimension> ImageType; - typedef itk::VariableLengthVector<RealType> RealVectorType; - typedef otb::ImageFileReader<ImageType> ReaderType; - typedef itk::PointSet<RealVectorType, Dimension> PointSetType; - typedef otb::ImageToSIFTKeyPointSetFilter<ImageType, PointSetType> ImageToSIFTKeyPointSetFilterType; - - typedef PointSetType::PointsContainer PointsContainerType; - typedef PointsContainerType::Iterator PointsIteratorType; - - // Instantiating object - ReaderType::Pointer reader = ReaderType::New(); - ImageToSIFTKeyPointSetFilterType::Pointer filter = ImageToSIFTKeyPointSetFilterType::New(); - - reader->SetFileName(infname); - filter->SetInput(reader->GetOutput()); - filter->SetOctavesNumber(octaves); - filter->SetScalesNumber(scales); - filter->SetDoGThreshold(threshold); - filter->SetEdgeThreshold(ratio); - filter->Update(); - - PointsIteratorType pIt = filter->GetOutput()->GetPoints()->Begin(); - - std::ofstream outfile(outfname); - - outfile << "Number of octaves: " << octaves << std::endl; - outfile << "Number of scales: " << scales << std::endl; - outfile << "Number of SIFT key points: " << filter->GetOutput()->GetNumberOfPoints() << std::endl; - - while (pIt != filter->GetOutput()->GetPoints()->End()) - { - outfile << "[" << std::fixed << std::setprecision(2) << pIt.Value()[0] << ", " << std::setprecision(2) << - pIt.Value()[1] << "]" << std::endl; - ++pIt; - } - - outfile.close(); - - return EXIT_SUCCESS; -} diff --git a/Modules/Feature/Descriptors/test/otbImageToSURFKeyPointSetFilterOutputDescriptorAscii.cxx b/Modules/Feature/Descriptors/test/otbImageToSURFKeyPointSetFilterOutputDescriptorAscii.cxx deleted file mode 100644 index 91b45476551fca96ceae7fd217d3de18c5346bb7..0000000000000000000000000000000000000000 --- a/Modules/Feature/Descriptors/test/otbImageToSURFKeyPointSetFilterOutputDescriptorAscii.cxx +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) - * - * This file is part of Orfeo Toolbox - * - * https://www.orfeo-toolbox.org/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <iomanip> -#include <iostream> -#include <fstream> - -#include "otbImageToSURFKeyPointSetFilter.h" -#include "otbImage.h" -#include "otbImageFileReader.h" -#include "otbImageFileWriter.h" -#include "itkVariableLengthVector.h" -#include "itkRGBPixel.h" -#include "itkImageRegionIterator.h" - -int otbImageToSURFKeyPointSetFilterOutputDescriptorAscii(int argc, char * argv[]) -{ - - if (argc < 5) - { - std::cout << " Usage : otbSURFTest imageName FileOutName Octave[int] Level[int]" << std::endl; - return EXIT_FAILURE; - } - - const char * infname = argv[1]; - const char * outfname = argv[2]; - - const unsigned int octaves = atoi(argv[3]); - const unsigned int scales = atoi(argv[4]); - - typedef float RealType; - const unsigned int Dimension = 2; - - typedef otb::Image<RealType, Dimension> ImageType; - typedef itk::VariableLengthVector<RealType> RealVectorType; - typedef otb::ImageFileReader<ImageType> ReaderType; - typedef itk::PointSet<RealVectorType, Dimension> PointSetType; - typedef otb::ImageToSURFKeyPointSetFilter<ImageType, PointSetType> ImageToSURFKeyPointSetFilterType; - typedef PointSetType::PointsContainer PointsContainerType; - typedef PointsContainerType::Iterator PointsIteratorType; - typedef PointSetType::PointDataContainer PointDataContainerType; - typedef PointDataContainerType::Iterator PointDataIteratorType; - - // Instantiating object - ReaderType::Pointer reader = ReaderType::New(); - ImageToSURFKeyPointSetFilterType::Pointer filter = ImageToSURFKeyPointSetFilterType::New(); - - reader->SetFileName(infname); - filter->SetInput(reader->GetOutput()); - filter->SetOctavesNumber(octaves); - filter->SetScalesNumber(scales); - filter->Update(); - - PointsIteratorType pIt = filter->GetOutput()->GetPoints()->Begin(); - PointDataIteratorType pDataIt = filter->GetOutput()->GetPointData()->Begin(); - - std::ofstream outfile(outfname); - - outfile << "Number of octaves: " << octaves << std::endl; - outfile << "Number of scales: " << scales << std::endl; - outfile << "Number of SURF key points: " << filter->GetNumberOfPoints() << std::endl; - - while (pIt != filter->GetOutput()->GetPoints()->End()) - { - outfile << "["; - unsigned int lIterDesc = 0; - while (lIterDesc < pDataIt.Value().Size()) - { - outfile << std::setprecision(3) << pDataIt.Value()[lIterDesc] << " "; - lIterDesc++; - } - outfile << "]" << std::endl; - ++pIt; - ++pDataIt; - } - - outfile.close(); - - return EXIT_SUCCESS; -} diff --git a/Modules/Feature/Descriptors/test/otbImageToSURFKeyPointSetFilterOutputInterestPointAscii.cxx b/Modules/Feature/Descriptors/test/otbImageToSURFKeyPointSetFilterOutputInterestPointAscii.cxx deleted file mode 100644 index fc40afba0cbf61071291911a35427b447cfa52c5..0000000000000000000000000000000000000000 --- a/Modules/Feature/Descriptors/test/otbImageToSURFKeyPointSetFilterOutputInterestPointAscii.cxx +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) - * - * This file is part of Orfeo Toolbox - * - * https://www.orfeo-toolbox.org/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#include <iomanip> -#include <iostream> -#include <fstream> - -#include "otbImageToSURFKeyPointSetFilter.h" -#include "otbImage.h" -#include "otbImageFileReader.h" -#include "otbImageFileWriter.h" -#include "itkVariableLengthVector.h" -#include "itkRGBPixel.h" -#include "itkImageRegionIterator.h" - -int otbImageToSURFKeyPointSetFilterOutputInterestPointAscii(int argc, char * argv[]) -{ - - if (argc < 5) - { - std::cout << " Usage : otbSURFTest imageName FileOutName Octave[int] Level[int]" << std::endl; - return EXIT_FAILURE; - } - - const char * infname = argv[1]; - const char * outfname = argv[2]; - - const unsigned int octaves = atoi(argv[3]); - const unsigned int scales = atoi(argv[4]); - - typedef float RealType; - const unsigned int Dimension = 2; - - typedef otb::Image<RealType, Dimension> ImageType; - typedef itk::VariableLengthVector<RealType> RealVectorType; - typedef otb::ImageFileReader<ImageType> ReaderType; - typedef itk::PointSet<RealVectorType, Dimension> PointSetType; - typedef otb::ImageToSURFKeyPointSetFilter<ImageType, PointSetType> ImageToSURFKeyPointSetFilterType; - typedef PointSetType::PointsContainer PointsContainerType; - typedef PointsContainerType::Iterator PointsIteratorType; - - // Instantiating object - ReaderType::Pointer reader = ReaderType::New(); - ImageToSURFKeyPointSetFilterType::Pointer filter = ImageToSURFKeyPointSetFilterType::New(); - - reader->SetFileName(infname); - filter->SetInput(reader->GetOutput()); - filter->SetOctavesNumber(octaves); - filter->SetScalesNumber(scales); - filter->Update(); - - PointsIteratorType pIt = filter->GetOutput()->GetPoints()->Begin(); - filter->GetOutput()->GetPointData()->Begin(); - - std::ofstream outfile(outfname); - - outfile << "Number of octaves: " << octaves << std::endl; - outfile << "Number of scales: " << scales << std::endl; - outfile << "Number of SURF key points: " << filter->GetNumberOfPoints() << std::endl; - - while (pIt != filter->GetOutput()->GetPoints()->End()) - { - outfile << "[" << std::fixed << std::setprecision(2) << pIt.Value()[0] << ", " << std::setprecision(2) << - pIt.Value()[1] << "]" << std::endl; - ++pIt; - } - - outfile.close(); - - return EXIT_SUCCESS; -} diff --git a/Modules/Feature/Descriptors/test/otbKeyPointSetsMatchingFilter.cxx b/Modules/Feature/Descriptors/test/otbKeyPointSetsMatchingFilter.cxx deleted file mode 100644 index c4d563dc15f87545cae69d9b0ae4a76d05e6b0df..0000000000000000000000000000000000000000 --- a/Modules/Feature/Descriptors/test/otbKeyPointSetsMatchingFilter.cxx +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) - * - * This file is part of Orfeo Toolbox - * - * https://www.orfeo-toolbox.org/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - - -#include "otbKeyPointSetsMatchingFilter.h" - -#include "itkVariableLengthVector.h" -#include "itkPointSet.h" - -#include <iostream> -#include <fstream> - -int otbKeyPointSetsMatchingFilter(int itkNotUsed(argc), char* argv[]) -{ - - const char * outfname = argv[1]; - const double thresh = atof(argv[2]); - const bool useBackMatching = atoi(argv[3]); - - typedef itk::VariableLengthVector<double> PointDataType; - typedef itk::PointSet<PointDataType, 2> PointSetType; - typedef PointSetType::PointType PointType; - typedef otb::KeyPointSetsMatchingFilter<PointSetType> MatchingFilterType; - typedef MatchingFilterType::LandmarkListType LandmarkListType; - - // instantiation - MatchingFilterType::Pointer filter = MatchingFilterType::New(); - - filter->SetUseBackMatching(useBackMatching); - filter->SetDistanceThreshold(thresh); - - // Building two pointsets - PointSetType::Pointer ps1 = PointSetType::New(); - PointSetType::Pointer ps2 = PointSetType::New(); - - PointType p1, p2, p3; - - p1.Fill(1); - p2.Fill(2); - p3.Fill(3); - - PointDataType d1(3), d2(3), d3(3), d1b(3), d2b(3), d3b(3); - - d1.Fill(1); - d1b.Fill(1); - - d2.Fill(0); - d2[0] = 10; - d2b.Fill(0); - d2b[1] = 10; - - d3.Fill(2); - d3b.Fill(10); - - ps1->SetPoint(0, p1); - ps1->SetPoint(1, p2); - ps1->SetPoint(2, p3); - - ps2->SetPoint(0, p1); - ps2->SetPoint(1, p2); - ps2->SetPoint(2, p3); - - ps1->SetPointData(0, d1); - ps1->SetPointData(1, d2); - ps1->SetPointData(2, d3); - - ps2->SetPointData(0, d1b); - ps2->SetPointData(1, d2b); - ps2->SetPointData(2, d3b); - - filter->SetInput1(ps1); - filter->SetInput2(ps2); - - filter->Update(); - - LandmarkListType * matching = filter->GetOutput(); - - std::ofstream outfile(outfname); - outfile << "Matches: " << std::endl; - - for (LandmarkListType::Iterator it = matching->Begin(); it != matching->End(); ++it) - { - outfile << "Matching: " << it.Get()->GetPoint1() << " " << it.Get()->GetPointData1() << " <- " << - it.Get()->GetLandmarkData() << " -> " << it.Get()->GetPoint2() << " " << it.Get()->GetPointData2() << std::endl; - } - - outfile.close(); - - return EXIT_SUCCESS; -} diff --git a/Modules/Feature/Descriptors/test/otbKeyPointsAlgorithmsTest.cxx b/Modules/Feature/Descriptors/test/otbKeyPointsAlgorithmsTest.cxx new file mode 100644 index 0000000000000000000000000000000000000000..99dcc44a799a982b76f2f7d7ef9776fd9ad449b2 --- /dev/null +++ b/Modules/Feature/Descriptors/test/otbKeyPointsAlgorithmsTest.cxx @@ -0,0 +1,379 @@ +/* + * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) + * + * This file is part of Orfeo Toolbox + * + * https://www.orfeo-toolbox.org/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "otbImage.h" +#include "otbImageFileReader.h" +#include "otbExtractROI.h" +#include "itkScalableAffineTransform.h" +#include "otbStreamingResampleImageFilter.h" +#include "otbBCOInterpolateImageFunction.h" +#include "otbKeyPointSetsMatchingFilter.h" +#include "otbSiftFastImageFilter.h" +#include "otbImageToSIFTKeyPointSetFilter.h" +#include "otbImageToSURFKeyPointSetFilter.h" +#include "itkPointSet.h" + +#include <tuple> + +using ImageType = otb::Image<double>; +using ReaderType = otb::ImageFileReader<ImageType>; +using ExtractType = otb::ExtractROI<double,double>; +using TransformType = itk::ScalableAffineTransform<double, 2>; +using ResamplerType = otb::StreamingResampleImageFilter<ImageType, ImageType, double>; +using InterpolatorType = otb::BCOInterpolateImageFunction<ImageType, double>; +using VectorType = itk::VariableLengthVector<double>; +using PointSetType = itk::PointSet<VectorType, 2>; +using SiftFastFilterType = otb::SiftFastImageFilter<ImageType, PointSetType>; +using SiftFilterType = otb::ImageToSIFTKeyPointSetFilter<ImageType, PointSetType>; +using SurfFilterType = otb::ImageToSURFKeyPointSetFilter<ImageType, PointSetType>; +using MatchingFilterType = otb::KeyPointSetsMatchingFilter<PointSetType>; + +auto printResult = [](bool value) { return value ? "Ok" : "Nok"; }; + +bool testMatchingFilter() +{ + auto ps1 = PointSetType::New(); + auto ps2 = PointSetType::New(); + + PointSetType::PointType p1,p2,p3,p4,p5,p6; + p1.Fill(1.); + p2.Fill(2.); + p3.Fill(3.); + p4.Fill(4.); + p5.Fill(5.); + p6.Fill(6.); + ps1->SetPoint(0, p1); + ps1->SetPoint(1, p2); + ps1->SetPoint(2, p3); + ps2->SetPoint(0, p4); + ps2->SetPoint(1, p5); + ps2->SetPoint(2, p6); + + + VectorType d1(1), d2(1), d3(1), d4(1),d5(1), d6(1); + d1[0]=0.7; + d2[0]=0.8; + d3[0]=10.; + d4[0]=0.; + d5[0]=1.; + d6[0]=11.; + + ps1->SetPointData(0, d1); + ps1->SetPointData(1, d2); + ps1->SetPointData(2, d3); + ps2->SetPointData(0, d4); + ps2->SetPointData(1, d5); + ps2->SetPointData(2, d6); + + auto filter1 = MatchingFilterType::New(); + filter1->SetDistanceThreshold(0.6); + filter1->SetUseBackMatching(false); + filter1->SetInput1(ps1); + filter1->SetInput2(ps2); + filter1->Update(); + + auto matches1 = filter1->GetOutput(); + + std::cout<<"Matches without backmatching: "<<std::endl; + + for (auto it = matches1->Begin(); it != matches1->End(); ++it) + { + std::cout<<it.Get()->GetPoint1()<<" <-> "<<it.Get()->GetPoint2()<<std::endl; + } + + auto filter2 = MatchingFilterType::New(); + filter2->SetDistanceThreshold(0.6); + filter2->SetUseBackMatching(true); + filter2->SetInput1(ps1); + filter2->SetInput2(ps2); + filter2->Update(); + + auto matches2 = filter2->GetOutput(); + + std::cout<<"Matches with backmatching: "<<std::endl; + + for (auto it = matches2->Begin(); it != matches2->End(); ++it) + { + std::cout<<it.Get()->GetPoint1()<<" <-> "<<it.Get()->GetPoint2()<<std::endl; + } + + bool success = true; + + // Without backmatching, matches should be: + // p1 <-> p5 + // p2 <-> p5 + // p3 <-> p6 + unsigned int nb_matches = matches1->Size(); + + bool test = nb_matches == 3; + std::cout<<"Without backmatching, the number of matches is 3:\t"<<printResult(test)<<std::endl; + success = success && test; + + test = nb_matches > 1 && matches1->GetNthElement(0)->GetPoint1() == p1 && matches1->GetNthElement(0)->GetPoint2() == p5; + std::cout<<"Without backmatching, p1 matches with p5:\t\t"<<printResult(test)<<std::endl; + success = success && test; + + test = nb_matches > 0 && matches1->GetNthElement(1)->GetPoint1() == p2 && matches1->GetNthElement(1)->GetPoint2() == p5; + std::cout<<"Without backmatching, p2 matches with p5:\t\t"<<printResult(test)<<std::endl; + success = success && test; + + + test = nb_matches > 2 && matches1->GetNthElement(2)->GetPoint1() == p3 && matches1->GetNthElement(2)->GetPoint2() == p6; + std::cout<<"Without backmatching, p3 matches with p6:\t\t"<<printResult(test)<<std::endl; + success = success && test; + + // With back-matching there should be only 2 matches: + // p2 <-> p5 + // p3 <-> p6 + test = matches2->Size() == 2; + std::cout<<"With backmatching, the number of matches is 2:\t"<<printResult(test)<<std::endl; + success = success && test; + + test = matches2->GetNthElement(0)->GetPoint1() == p2 && matches2->GetNthElement(0)->GetPoint2() == p5; + std::cout<<"With backmatching, p2 matches with p5:\t\t"<<printResult(test)<<std::endl; + success = success && test; + + test = matches2->GetNthElement(1)->GetPoint1() == p3 && matches2->GetNthElement(1)->GetPoint2() == p6; + std::cout<<"With backmatching, p3 matches with p6:\t\t"<<printResult(test)<<std::endl; + success = success && test; + + + + return success; +} + + +/** Generate a pair of images, one beeing slightly warped wrt the + * other */ +auto generateImagePair(const std::string& infname, double rotation, double scaling) +{ + // Read reference image + auto reader = ReaderType::New(); + reader->SetFileName(infname); + + auto extractor = ExtractType::New(); + extractor->SetInput(reader->GetOutput()); + extractor->SetSizeX(50); + extractor->SetSizeY(50); + extractor->Update(); + + ImageType::Pointer reference = extractor->GetOutput(); + + // Create secondary image + + // Setup transform + auto transform = TransformType::New(); + + // Set rotation center as image center + auto origin = reference->GetOrigin(); + auto spacing = reference->GetSpacing(); + auto size = reference->GetLargestPossibleRegion().GetSize(); + auto center = origin; + center[0] += 0.5 * spacing[0] * size[0]; + center[1] += 0.5 * spacing[1] * size[1]; + transform->SetCenter(center); + + // Set rotation angle + transform->Rotate2D(rotation * otb::CONST_PI_180); + + // Set scale + ImageType::SpacingType scalingVector; + scalingVector.Fill(scaling); + transform->Scale(scalingVector); + + // Invert transform + auto inverse = TransformType::New(); + bool ok = transform->GetInverse(inverse); + if (!ok) + throw std::logic_error("Could not inverse transform"); + // Setup interpolator + auto interpolator = InterpolatorType::New(); + + // Setup resampler + auto resampler = ResamplerType::New(); + resampler->SetInput(reference); + resampler->SetTransform(transform); + resampler->SetInterpolator(interpolator); + + // Since rotation and scaling are small, use same image parameter + // for secondary image + resampler->SetOutputOrigin(origin); + resampler->SetOutputSize(size); + resampler->SetOutputSpacing(spacing); + resampler->Update(); + ImageType::Pointer secondary = resampler->GetOutput(); + + return std::make_tuple(reference, secondary, transform); +} + +/** Perform checks for one keypoints algorithm */ +template <typename TKeyPointsFilter, typename TParameterSetter> +bool checkKeyPointsFilter(const ImageType* reference, const ImageType* secondary, const TransformType* transform, const TParameterSetter& configureFilter, + unsigned int nb_points_thresh, double match_rate_thresh, double good_match_rate_thresh) +{ + // Keypoints on first image + auto filterReference = TKeyPointsFilter::New(); + filterReference->SetInput(reference); + configureFilter(filterReference); + + // Keypoints on secondary image + auto filterSecondary = TKeyPointsFilter::New(); + filterSecondary->SetInput(secondary); + configureFilter(filterSecondary); + + // Match keypoints + auto matcher = MatchingFilterType::New(); + matcher->SetUseBackMatching(false); + matcher->SetDistanceThreshold(0.6); + matcher->SetInput1(filterReference->GetOutput()); + matcher->SetInput2(filterSecondary->GetOutput()); + matcher->Update(); + + PointSetType::Pointer referencePoints = filterReference->GetOutput(); + const size_t nbReferencePoints = referencePoints->GetPoints()->Size(); + + typename PointSetType::Pointer secondaryPoints = filterSecondary->GetOutput(); + const size_t nbSecondaryPoints = secondaryPoints->GetPoints()->Size(); + + std::cout << "Found " << nbReferencePoints << " points in reference image and " << nbSecondaryPoints << " points in secondary image" << std::endl; + + auto matches = matcher->GetOutput(); + const size_t nb_matches = matches->Size(); + + size_t good_matches = 0; + const double threshold_for_good_match = 0.5; // pixels + + // Count good and bad matches + for (auto it = matches->Begin(); it != matches->End(); ++it) + { + const auto p1 = it.Get()->GetPoint1(); + const auto p2 = it.Get()->GetPoint2(); + + const auto p2_mapped = transform->TransformPoint(p2); + + // Check that matches are good up to 0.1 pixel + if ((p1[0] - p2_mapped[0]) * (p1[0] - p2_mapped[0]) + (p1[1] - p2_mapped[1]) * (p1[1] - p2_mapped[1]) <= + threshold_for_good_match * threshold_for_good_match) + ++good_matches; + } + + // Performances metrics + const float reference_match_rate = nb_matches / static_cast<float>(nbReferencePoints); + const float secondary_match_rate = nb_matches / static_cast<float>(nbSecondaryPoints); + const float good_match_rate = good_matches / static_cast<float>(nb_matches); + + + std::cout << "Found " << nb_matches << " matches with " << good_matches << " valid matches (tolerance of 0.5 pixels)" << std::endl; + + // Quality gate + bool current_test = nbReferencePoints >= nb_points_thresh; + std::cout << "More than " << nb_points_thresh << " points found in reference image:\t" << printResult(current_test) << " (" + << nbReferencePoints << ")" << std::endl; + bool overall_status = current_test; + + current_test = nbSecondaryPoints> nb_points_thresh; + std::cout << "More than " << nb_points_thresh << " points found in secondary image:\t" << printResult(current_test) << " (" + << nbSecondaryPoints << ")" << std::endl; + overall_status = overall_status && current_test; + + current_test = reference_match_rate > match_rate_thresh; + std::cout << "More than " << 100 * match_rate_thresh << "% of reference points have a match:\t" << printResult(current_test) << " (" + << 100 * reference_match_rate << "%)" << std::endl; + overall_status = overall_status && current_test; + + current_test = secondary_match_rate > match_rate_thresh; + std::cout << "More than " << 100 * match_rate_thresh << "% of secondary points have a match:\t" << printResult(current_test) << " (" + << 100 * secondary_match_rate << "%)" << std::endl; + overall_status = overall_status && current_test; + + current_test = good_match_rate > good_match_rate_thresh; + std::cout << "More than " << good_match_rate_thresh * 100 << "% of matches are good: \t" << printResult(current_test) << " (" + << 100 * good_match_rate << "% at 0.5 pixel accuracy)" + << "\n"; + overall_status = overall_status && current_test; + return overall_status; +} + + +int otbKeyPointsAlgorithmsTest(int argc, char* argv[]) +{ + if (argc != 2) + { + std::cerr << "Usage: " << argv[0] << " infname" << std::endl; + return EXIT_FAILURE; + } + const char* infname = argv[1]; + + // Generate reference and secondary image + ImageType::Pointer reference, secondary; + TransformType::Pointer transform; + + // Small rotation and scaling + const double rotation = 2.5; // 5° + const double scaling = 0.99; + + // First test matching filter alone + std::cout<<"Checking matching filter:"<<std::endl; + std::cout<<"========================="<<std::endl; + bool status = testMatchingFilter(); + + std::tie(reference, secondary, transform) = generateImagePair(infname, rotation, scaling); + + std::cout << "Secondary image generated by applying a rotation of " << rotation << " degrees and scaling of " << scaling << "." << std::endl; + + // Test Surf filter + std::cout << "Checking Surf implementation:" << std::endl; + std::cout << "=============================" << std::endl; + + // Lambda to configure surf algorithm + auto configureSurf = [](SurfFilterType* filter) { + filter->SetOctavesNumber(4); + filter->SetScalesNumber(8); + }; + + status = checkKeyPointsFilter<SurfFilterType>(reference, secondary, transform, configureSurf, 95, 0.13, 0.64) && status; + + // Test Sift filter + std::cout << "Checking Sift implementation:" << std::endl; + std::cout << "=============================" << std::endl; + + // Lambda to configure sift algorithm + auto configureSift = [](SiftFilterType* filter) { + filter->SetOctavesNumber(4); + filter->SetScalesNumber(8); + filter->SetDoGThreshold(0.01); + filter->SetEdgeThreshold(10.); + }; + + status = checkKeyPointsFilter<SiftFilterType>(reference, secondary, transform, configureSift, 120, 0.44, 0.82) && status; + +#ifdef OTB_USE_SIFTFAST + // Test SiftFast filter + std::cout << "Checking SiftFast implementation:" << std::endl; + std::cout << "=================================" << std::endl; + + // lambda to set specific filter parameter + auto configureSiftFast = [](SiftFastFilterType* filter) { filter->SetScalesNumber(8); }; + + status = checkKeyPointsFilter<SiftFastFilterType>(reference, secondary, transform, configureSiftFast, 100, 0.59, 0.95) && status; +#endif + + return status ? EXIT_SUCCESS : EXIT_FAILURE; +}