diff --git a/CMake/OTBCheckCpp11Keywords.cmake b/CMake/OTBCheckCpp11Keywords.cmake index 09e13b4182768447cee83e4bf7745a6f58f18f52..31a30c5cdea1e4a3b36c90231e486d736de68352 100644 --- a/CMake/OTBCheckCpp11Keywords.cmake +++ b/CMake/OTBCheckCpp11Keywords.cmake @@ -2,4 +2,4 @@ try_compile(OTB_IS_UNIQUE_PTR_DEFINED ${CMAKE_CURRENT_BINARY_DIR}/CMake ${CMAKE_SOURCE_DIR}/CMake/otbTestUniquePtr.cpp) try_compile(OTB_IS_OVERRIDE_DEFINED ${CMAKE_CURRENT_BINARY_DIR}/CMake ${CMAKE_SOURCE_DIR}/CMake/otbTestUniquePtr.cpp) try_compile(OTB_IS_NULLPTR_DEFINED ${CMAKE_CURRENT_BINARY_DIR}/CMake ${CMAKE_SOURCE_DIR}/CMake/otbTestUniquePtr.cpp) - +try_compile(OTB_HAS_CXX11 ${CMAKE_CURRENT_BINARY_DIR}/CMake ${CMAKE_SOURCE_DIR}/CMake/otbTestUniquePtr.cpp) diff --git a/CMake/OTBModuleHeaderTest.cmake b/CMake/OTBModuleHeaderTest.cmake index c381f0d7bfa6347878d2465f1cabc5ef54366865..6a1c72158a365e323c9b4f84529f03f8ccf38b3e 100644 --- a/CMake/OTBModuleHeaderTest.cmake +++ b/CMake/OTBModuleHeaderTest.cmake @@ -25,7 +25,9 @@ SET(BANNED_HEADERS) if(NOT OTB_USE_OPENCV) SET(BANNED_HEADERS "${BANNED_HEADERS} otbDecisionTreeMachineLearningModelFactory.h otbDecisionTreeMachineLearningModel.h otbKNearestNeighborsMachineLearningModelFactory.h otbKNearestNeighborsMachineLearningModel.h otbRandomForestsMachineLearningModelFactory.h otbRandomForestsMachineLearningModel.h otbSVMMachineLearningModelFactory.h otbSVMMachineLearningModel.h otbGradientBoostedTreeMachineLearningModelFactory.h otbGradientBoostedTreeMachineLearningModel.h otbBoostMachineLearningModelFactory.h otbBoostMachineLearningModel.h otbNeuralNetworkMachineLearningModelFactory.h otbNeuralNetworkMachineLearningModel.h otbNormalBayesMachineLearningModelFactory.h otbNormalBayesMachineLearningModel.h otbRequiresOpenCVCheck.h otbOpenCVUtils.h otbCvRTreesWrapper.h") endif() - +if(NOT OTB_USE_SHARK) + SET(BANNED_HEADERS "${BANNED_HEADERS} otbSharkRandomForestsMachineLearningModel.h otbSharkRandomForestsMachineLearningModel.txx otbSharkUtils.h otbRequiresSharkCheck.h otbSharkRandomForestsMachineLearningModelFactory.h") +endif() if(NOT OTB_USE_LIBSVM) SET(BANNED_HEADERS "${BANNED_HEADERS} otbLibSVMMachineLearningModel.h otbLibSVMMachineLearningModelFactory.h") endif() diff --git a/CMake/OTBModuleMacros.cmake b/CMake/OTBModuleMacros.cmake index 320b7f66b0a741ba1b71121a88f91e9e73efa013..4b6f20161423687471f68dc753a85e341a1e4b05 100644 --- a/CMake/OTBModuleMacros.cmake +++ b/CMake/OTBModuleMacros.cmake @@ -324,3 +324,9 @@ macro(otb_module_target _name) otb_module_target_install(${_name}) endif() endmacro() + +macro(otb_module_requires_cxx11) + if(NOT ${OTB_HAS_CXX11}) + message(FATAL_ERROR "Module ${otb-module} requires C++11 support. Consider adding --std=c++11 to your compiler flags.") + endif() +endmacro() diff --git a/CMake/OTBSetStandardCompilerFlags.cmake b/CMake/OTBSetStandardCompilerFlags.cmake index a264550f732429bd90158980dd49c6bdf20e77dc..d3b11b8a1f2a047bea12d451773bf2b7d53e5f7f 100644 --- a/CMake/OTBSetStandardCompilerFlags.cmake +++ b/CMake/OTBSetStandardCompilerFlags.cmake @@ -143,21 +143,6 @@ endfunction() macro(check_compiler_platform_flags) - # Since CMake 2.8.11, the size of the stack is not modified by CMake on - # windows platform, it uses the default size: with visual compiler it is 1Mbyte - # which is to lower for us (thanks to 6S code). - # if(MSVC) - # if("${CMAKE_EXE_LINKER_FLAGS}" MATCHES "/STACK:[0-9]+") - # message(STATUS "The size of the stack is already defined, so we don't modified it.") - # else() - # set(OTB_REQUIRED_LINK_FLAGS "${OTB_REQUIRED_LINK_FLAGS} /STACK:10000000") - # message(STATUS "The stack size is set to 10 Mbytes (/STACK:10000000).") - # endif() - # elseif(MINGW) - # set(OTB_REQUIRED_LINK_FLAGS "${OTB_REQUIRED_LINK_FLAGS} -Wl,--stack,10000000") - # message(STATUS "The stack size is set to 10 Mbytes (-Wl,--stack,10000000).") - # endif() # if(MSVC) - # On Visual Studio 8 MS deprecated C. This removes all 1.276E1265 security # warnings if(WIN32) diff --git a/CMake/otbCheckCXX11.cpp b/CMake/otbCheckCXX11.cpp new file mode 100644 index 0000000000000000000000000000000000000000..17853f2a02b63b4c226c54a553adba657b2eb596 --- /dev/null +++ b/CMake/otbCheckCXX11.cpp @@ -0,0 +1,8 @@ +#if __cplusplus <= 199711L + #error Compiler is not C++11 compliant +#endif + +int main(int argc, char *argv[]) +{ + return 0; +} diff --git a/CMakeLists.txt b/CMakeLists.txt index c37da5d534cf2c4946514fe36c65850b6bda365d..4b48264c0d590f98286796188bf9981ca46e02ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -442,6 +442,7 @@ foreach(otb_option CMAKE_BUILD_TYPE CMAKE_C_FLAGS CMAKE_CXX_FLAGS + OTB_HAS_CXX11 ${option_list} OTB_WRAP_PYTHON OTB_WRAP_JAVA diff --git a/Modules/Applications/AppClassification/app/otbComputeImagesStatistics.cxx b/Modules/Applications/AppClassification/app/otbComputeImagesStatistics.cxx index 990d41ba1a9d7fb4e80ad69ee4ef1c7db3d9a96c..b3e2a04b5ebe9ce9647f0e0c46979080971e0b4d 100644 --- a/Modules/Applications/AppClassification/app/otbComputeImagesStatistics.cxx +++ b/Modules/Applications/AppClassification/app/otbComputeImagesStatistics.cxx @@ -66,6 +66,8 @@ private: SetParameterDescription( "out", "XML filename where the statistics are saved for future reuse." ); MandatoryOff("out"); + AddRAMParameter(); + // Doc example parameter settings SetDocExampleParameterValue("il", "QB_1_ortho.tif"); SetDocExampleParameterValue("out", "EstimateImageStatisticsQB1.xml"); @@ -128,6 +130,7 @@ private: processName << "Processing Image (" << imageId+1 << "/" << imageList->Size() << ")"; AddProcess(statsEstimator->GetStreamer(), processName.str().c_str()); statsEstimator->SetInput(image); + statsEstimator->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram")); if( HasValue( "bv" )==true ) { statsEstimator->SetIgnoreUserDefinedValue(true); diff --git a/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx b/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx index 9a121ab8324cca321c00c2c031caa7ed854f4b36..a6167febed174d998276e97b23f8e8994a6f2d40 100644 --- a/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx +++ b/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx @@ -171,6 +171,7 @@ private: filter->SetOGRData(reprojVector); filter->SetFieldName(fieldName); filter->SetLayerIndex(this->GetParameterInt("layer")); + filter->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram")); AddProcess(filter->GetStreamer(),"Analyse polygons..."); filter->Update(); diff --git a/Modules/Applications/AppClassification/app/otbTrainImagesClassifier.cxx b/Modules/Applications/AppClassification/app/otbTrainImagesClassifier.cxx index 87d80a7a4410f96dbb2e0af7880c066c19e23b28..932454f0b5ebe89bd84c9367b6c582b9cd3c0970 100644 --- a/Modules/Applications/AppClassification/app/otbTrainImagesClassifier.cxx +++ b/Modules/Applications/AppClassification/app/otbTrainImagesClassifier.cxx @@ -120,8 +120,8 @@ void DoInit() ITK_OVERRIDE "validation sets per class and per image.\n Several classifier parameters can be set depending on the chosen classifier. In the " "validation process, the confusion matrix is organized the following way: rows = reference labels, columns = produced labels. " "In the header of the optional confusion matrix output file, the validation (reference) and predicted (produced) class labels" - " are ordered according to the rows/columns of the confusion matrix.\n This application is based on LibSVM and on OpenCV Machine Learning " - "classifiers, and is compatible with OpenCV 2.3.1 and later."); + " are ordered according to the rows/columns of the confusion matrix.\n This application is based on LibSVM and OpenCV Machine Learning " + "(2.3.1 and later)."); SetDocLimitations("None"); SetDocAuthors("OTB-Team"); SetDocSeeAlso("OpenCV documentation for machine learning http://docs.opencv.org/modules/ml/doc/ml.html "); diff --git a/Modules/Applications/AppClassification/include/otbLearningApplicationBase.h b/Modules/Applications/AppClassification/include/otbLearningApplicationBase.h index aaeb2e2ebd5984bc5d7c7538c076cfc2500fc499..6fd04d059d43c7be3450bc51fcf4a17e457e2c1b 100644 --- a/Modules/Applications/AppClassification/include/otbLearningApplicationBase.h +++ b/Modules/Applications/AppClassification/include/otbLearningApplicationBase.h @@ -31,22 +31,26 @@ #include "otbMachineLearningModelFactory.h" #ifdef OTB_USE_OPENCV -# include "otbKNearestNeighborsMachineLearningModel.h" -# include "otbRandomForestsMachineLearningModel.h" +#include "otbKNearestNeighborsMachineLearningModel.h" +#include "otbRandomForestsMachineLearningModel.h" // OpenCV SVM implementation is buggy with linear kernel // Users should use the libSVM implementation instead. -//# include "otbSVMMachineLearningModel.h" -# include "otbBoostMachineLearningModel.h" -# include "otbDecisionTreeMachineLearningModel.h" -# include "otbGradientBoostedTreeMachineLearningModel.h" -# include "otbNormalBayesMachineLearningModel.h" -# include "otbNeuralNetworkMachineLearningModel.h" +//#include "otbSVMMachineLearningModel.h" +#include "otbBoostMachineLearningModel.h" +#include "otbDecisionTreeMachineLearningModel.h" +#include "otbGradientBoostedTreeMachineLearningModel.h" +#include "otbNormalBayesMachineLearningModel.h" +#include "otbNeuralNetworkMachineLearningModel.h" #endif #ifdef OTB_USE_LIBSVM #include "otbLibSVMMachineLearningModel.h" #endif +#ifdef OTB_USE_SHARK +#include "otbSharkRandomForestsMachineLearningModel.h" +#endif + namespace otb { namespace Wrapper @@ -62,11 +66,12 @@ namespace Wrapper * methods. The classes derived from LearningApplicationBase only need these * 3 methods to handle the machine learning model. * - * There are multiple machine learning models in OTB, some imported from OpenCV, - * and one imported from LibSVM. They all have different parameters. The - * purpose of this class is to handle the creation of all parameters related to - * machine learning models (in DoInit() ), and to dispatch the calls to - * specific train functions in function Train(). + * There are multiple machine learning models in OTB, some imported + * from OpenCV and one imported from LibSVM. They all have + * different parameters. The purpose of this class is to handle the + * creation of all parameters related to machine learning models (in + * DoInit() ), and to dispatch the calls to specific train functions + * in function Train(). * * This class is templated over scalar types for input and output values. * Typically, the input value type will be either float of double. The choice @@ -131,7 +136,11 @@ public: #ifdef OTB_USE_LIBSVM typedef otb::LibSVMMachineLearningModel<InputValueType, OutputValueType> LibSVMType; #endif - + +#ifdef OTB_USE_SHARK + typedef otb::SharkRandomForestsMachineLearningModel<InputValueType, OutputValueType> SharkRandomForestType; +#endif + protected: LearningApplicationBase(); @@ -206,6 +215,13 @@ private: typename TargetListSampleType::Pointer trainingLabeledListSample, std::string modelPath); #endif + +#ifdef OTB_USE_SHARK + void InitSharkRandomForestsParams(); + void TrainSharkRandomForests(typename ListSampleType::Pointer trainingListSample, + typename TargetListSampleType::Pointer trainingLabeledListSample, + std::string modelPath); +#endif //@} }; @@ -229,6 +245,9 @@ private: #ifdef OTB_USE_LIBSVM #include "otbTrainLibSVM.txx" #endif +#ifdef OTB_USE_SHARK +#include "otbTrainSharkRandomForests.txx" +#endif #endif #endif diff --git a/Modules/Applications/AppClassification/include/otbLearningApplicationBase.txx b/Modules/Applications/AppClassification/include/otbLearningApplicationBase.txx index d92296ff4b551a0ea245c4149f6fd97aff87f153..bf110c82738e1223469bb2e0c486e6f911e5afd5 100644 --- a/Modules/Applications/AppClassification/include/otbLearningApplicationBase.txx +++ b/Modules/Applications/AppClassification/include/otbLearningApplicationBase.txx @@ -73,6 +73,11 @@ LearningApplicationBase<TInputValue,TOutputValue> InitRandomForestsParams(); InitKNNParams(); #endif + +#ifdef OTB_USE_SHARK + InitSharkRandomForestsParams(); +#endif + } template <class TInputValue, class TOutputValue> @@ -134,6 +139,15 @@ LearningApplicationBase<TInputValue,TOutputValue> otbAppLogFATAL("Module LIBSVM is not installed. You should consider turning OTB_USE_LIBSVM on during cmake configuration."); #endif } + if(modelName == "sharkrf") + { + #ifdef OTB_USE_SHARK + TrainSharkRandomForests(trainingListSample,trainingLabeledListSample,modelPath); + #else + otbAppLogFATAL("Module SharkLearning is not installed. You should consider turning OTB_USE_SHARK on during cmake configuration."); + #endif + } + // OpenCV SVM implementation is buggy with linear kernel // Users should use the libSVM implementation instead. // else if (modelName == "svm") @@ -200,6 +214,7 @@ LearningApplicationBase<TInputValue,TOutputValue> otbAppLogFATAL("Module OPENCV is not installed. You should consider turning OTB_USE_OPENCV on during cmake configuration."); #endif } + // update reporter dummyFilter->UpdateProgress(1.0f); dummyFilter->InvokeEvent(itk::EndEvent()); diff --git a/Modules/Applications/AppClassification/include/otbTrainSharkRandomForests.txx b/Modules/Applications/AppClassification/include/otbTrainSharkRandomForests.txx new file mode 100644 index 0000000000000000000000000000000000000000..c9b2d565695c708da557074076fadfcaa3a6c4cd --- /dev/null +++ b/Modules/Applications/AppClassification/include/otbTrainSharkRandomForests.txx @@ -0,0 +1,98 @@ +/*========================================================================= + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + + =========================================================================*/ +#ifndef otbTrainSharkRandomForests_txx +#define otbTrainSharkRandomForests_txx + +#include "otbLearningApplicationBase.h" + +namespace otb +{ +namespace Wrapper +{ + +template <class TInputValue, class TOutputValue> +void +LearningApplicationBase<TInputValue,TOutputValue> +::InitSharkRandomForestsParams() +{ + + + AddChoice("classifier.sharkrf", "Shark Random forests classifier"); + SetParameterDescription("classifier.sharkrf", + "This group of parameters allows setting Shark Random Forests classifier parameters. " + "See complete documentation here \\url{http://image.diku.dk/shark/doxygen_pages/html/classshark_1_1_r_f_trainer.html}.\n It is noteworthy that training is parallel."); + //MaxNumberOfTrees + AddParameter(ParameterType_Int, "classifier.sharkrf.nbtrees", + "Maximum number of trees in the forest"); + SetParameterInt("classifier.sharkrf.nbtrees", 100); + SetParameterDescription( + "classifier.sharkrf.nbtrees", + "The maximum number of trees in the forest. Typically, the more trees you have, the better the accuracy. " + "However, the improvement in accuracy generally diminishes and reaches an asymptote for a certain number of trees. " + "Also to keep in mind, increasing the number of trees increases the prediction time linearly."); + + + //NodeSize + AddParameter(ParameterType_Int, "classifier.sharkrf.nodesize", "Min size of the node for a split"); + SetParameterInt("classifier.sharkrf.nodesize", 25); + SetParameterDescription( + "classifier.sharkrf.nodesize", + "If the number of samples in a node is smaller than this parameter, " + "then the node will not be split. A reasonable value is a small percentage of the total data e.g. 1 percent."); + + //MTry + AddParameter(ParameterType_Int, "classifier.sharkrf.mtry", "Number of features tested at each node"); + SetParameterInt("classifier.sharkrf.mtry", 0); + SetParameterDescription( + "classifier.sharkrf.mtry", + "The number of features (variables) which will be tested at each node in " + "order to compute the split. If set to zero, the square root of the number of " + "features is used."); + + + //OOB Ratio + AddParameter(ParameterType_Float, "classifier.sharkrf.oobr", "Out of bound ratio"); + SetParameterFloat("classifier.sharkrf.oobr", 0.66); + SetParameterDescription("classifier.sharkrf.oobr", + "Set the fraction of the original training dataset to use as the out of bag sample." + "A good default value is 0.66. "); +} + +template <class TInputValue, class TOutputValue> +void +LearningApplicationBase<TInputValue,TOutputValue> +::TrainSharkRandomForests(typename ListSampleType::Pointer trainingListSample, + typename TargetListSampleType::Pointer trainingLabeledListSample, + std::string modelPath) +{ + typename SharkRandomForestType::Pointer classifier = SharkRandomForestType::New(); + classifier->SetRegressionMode(this->m_RegressionFlag); + classifier->SetInputListSample(trainingListSample); + classifier->SetTargetListSample(trainingLabeledListSample); + classifier->SetNodeSize(GetParameterInt("classifier.sharkrf.nodesize")); + classifier->SetOobRatio(GetParameterFloat("classifier.sharkrf.oobr")); + classifier->SetNumberOfTrees(GetParameterInt("classifier.sharkrf.nbtrees")); + classifier->SetMTry(GetParameterInt("classifier.sharkrf.mtry")); + + classifier->Train(); + classifier->Save(modelPath); +} + +} //end namespace wrapper +} //end namespace otb + +#endif diff --git a/Modules/Applications/AppClassification/test/CMakeLists.txt b/Modules/Applications/AppClassification/test/CMakeLists.txt index 5e9109e01b0a8aa3e65c06aefe3d978889a14f7b..378a1b5fd1748de513ec67bdff38d859a63df039 100644 --- a/Modules/Applications/AppClassification/test/CMakeLists.txt +++ b/Modules/Applications/AppClassification/test/CMakeLists.txt @@ -75,6 +75,7 @@ set(ann_output_format ".ann") set(bayes_output_format ".bayes") set(rf_output_format ".rf") set(knn_output_format ".knn") +set(sharkrf_output_format ".txt") # Training algorithms parameters set(libsvm_parameters "-classifier.libsvm.opt" "true" "-classifier.libsvm.prob" "true") @@ -86,6 +87,7 @@ set(ann_parameters "-classifier.ann.sizes" "100") set(bayes_parameters "") set(rf_parameters "") set(knn_parameters "") +set(sharkrf_parameters "") # Validation depending on mode set(ascii_comparison --compare-ascii ${NOTOL}) @@ -104,8 +106,16 @@ if(OTB_USE_OPENCV) #list(APPEND classifierList "SVM" "BOOST" "DT" "GBT" "ANN" "BAYES" "RF" "KNN") list(APPEND classifierList "BOOST" "DT" "GBT" "ANN" "BAYES" "RF" "KNN") endif() +if(OTB_USE_SHARK) + list(APPEND classifierList "SHARKRF") +endif() + set(classifier_with_confmap "LIBSVM" "BOOST" "KNN" "ANN" "RF") +# This is a black list for classifier that can not have a baseline +# because they are using randomness and seed can not be set +set(classifier_without_basline "SHARKRF") + # Loop on classifiers foreach(classifier ${classifierList}) string(TOLOWER ${classifier} lclassifier) @@ -115,6 +125,13 @@ foreach(classifier ${classifierList}) set(OUTRASTER cl${classifier}LabeledImageQB1${raster_output_format}) set(OUTCONFMAP cl${classifier}ConfidenceMapQB1${raster_output_format}) + set(valid ${ascii_comparison} ${ascii_ref_path}/${OUTMODELFILE} ${TEMP}/${OUTMODELFILE}) + + list(FIND classifier_without_basline ${classifier} _classifier_has_baseline) + if(NOT ${_classifier_has_baseline} EQUAL -1) + set(valid "") + endif() + otb_test_application( NAME apTvClTrainMethod${classifier}ImagesClassifierQB1 APP TrainImagesClassifier @@ -126,9 +143,7 @@ foreach(classifier ${classifierList}) -io.out ${TEMP}/${OUTMODELFILE} -rand 121212 - VALID ${ascii_comparison} - ${ascii_ref_path}/${OUTMODELFILE} - ${TEMP}/${OUTMODELFILE} + VALID ${valid} ) otb_test_application( @@ -143,9 +158,7 @@ foreach(classifier ${classifierList}) -rand 121212 -outxml ${TEMP}/cl${classifier}_OutXML1.xml - VALID ${ascii_comparison} - ${ascii_ref_path}/${OUTMODELFILE} - ${TEMP}/OutXML1_${OUTMODELFILE} + VALID ${valid} ) otb_test_application( @@ -157,9 +170,7 @@ foreach(classifier ${classifierList}) -io.imstat ${INPUTDATA}/Classification/clImageStatisticsQB1${stat_input_format} -io.out ${TEMP}/OutXML2_${OUTMODELFILE} - VALID ${ascii_comparison} - ${ascii_ref_path}/${OUTMODELFILE} - ${TEMP}/OutXML2_${OUTMODELFILE} + VALID ${valid} ) #set_tests_properties(apTvClTrainMethod${classifier}ImagesClassifierQB1_InXML1 PROPERTIES DEPENDS apTvClTrainMethod${classifier}ImagesClassifierQB1_OutXML1) @@ -900,20 +911,21 @@ if(OTB_USE_OPENCV) endif() #------------ MultiImageSamplingRate TESTS ---------------- -otb_test_application(NAME apTvClMultiImageSamplingRate - APP MultiImageSamplingRate - OPTIONS -il ${INPUTDATA}/Classification/vector_stats_QB1.xml - ${INPUTDATA}/Classification/vector_stats_QB2.xml - ${INPUTDATA}/Classification/vector_stats_QB3.xml - -out ${TEMP}/apTvClMultiImageSamplingRate_out.csv - -strategy constant - -strategy.constant.nb "300" - -mim proportional - VALID --compare-n-ascii ${NOTOL} 3 - ${OTBAPP_BASELINE_FILES}/apTvClMultiImageSamplingRate_out_1.csv - ${TEMP}/apTvClMultiImageSamplingRate_out_1.csv - ${OTBAPP_BASELINE_FILES}/apTvClMultiImageSamplingRate_out_2.csv - ${TEMP}/apTvClMultiImageSamplingRate_out_2.csv - ${OTBAPP_BASELINE_FILES}/apTvClMultiImageSamplingRate_out_3.csv - ${TEMP}/apTvClMultiImageSamplingRate_out_3.csv - ) +otb_test_application( + NAME apTvClMultiImageSamplingRate + APP MultiImageSamplingRate + OPTIONS -il ${INPUTDATA}/Classification/vector_stats_QB1.xml + ${INPUTDATA}/Classification/vector_stats_QB2.xml + ${INPUTDATA}/Classification/vector_stats_QB3.xml + -out ${TEMP}/apTvClMultiImageSamplingRate_out.csv + -strategy constant + -strategy.constant.nb "300" + -mim proportional + VALID --compare-n-ascii ${NOTOL} 3 + ${OTBAPP_BASELINE_FILES}/apTvClMultiImageSamplingRate_out_1.csv + ${TEMP}/apTvClMultiImageSamplingRate_out_1.csv + ${OTBAPP_BASELINE_FILES}/apTvClMultiImageSamplingRate_out_2.csv + ${TEMP}/apTvClMultiImageSamplingRate_out_2.csv + ${OTBAPP_BASELINE_FILES}/apTvClMultiImageSamplingRate_out_3.csv + ${TEMP}/apTvClMultiImageSamplingRate_out_3.csv + ) diff --git a/Modules/Applications/AppDimensionalityReduction/app/otbDimensionalityReduction.cxx b/Modules/Applications/AppDimensionalityReduction/app/otbDimensionalityReduction.cxx index 06e07d00ad394a5f89004263db84829073823cd1..2359b00bb607bffa6255433f345a1588c952e26a 100644 --- a/Modules/Applications/AppDimensionalityReduction/app/otbDimensionalityReduction.cxx +++ b/Modules/Applications/AppDimensionalityReduction/app/otbDimensionalityReduction.cxx @@ -169,6 +169,8 @@ private: SetParameterDescription("outmatrix", "Filename to store the transformation matrix (csv format)"); MandatoryOff("outmatrix"); + AddRAMParameter(); + // Doc example parameter settings SetDocExampleParameterValue("in", "cupriteSubHsi.tif"); SetDocExampleParameterValue("out", "FilterOutput.tif"); @@ -420,7 +422,8 @@ private: m_MinMaxFilter = MinMaxFilterType::New(); m_MinMaxFilter->SetInput(m_ForwardFilter->GetOutput()); - m_MinMaxFilter->GetStreamer()->SetNumberOfLinesStrippedStreaming(50); + //m_MinMaxFilter->GetStreamer()->SetNumberOfLinesStrippedStreaming(50); + m_MinMaxFilter->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram")); AddProcess(m_MinMaxFilter->GetStreamer(), "Min/Max computing"); m_MinMaxFilter->Update(); diff --git a/Modules/Applications/AppEdge/app/otbLineSegmentDetection.cxx b/Modules/Applications/AppEdge/app/otbLineSegmentDetection.cxx index 4212104bde1e006197b27e4863b259fb07c91baf..e1f303b86848bd238a025a91b67f0214088246ce 100644 --- a/Modules/Applications/AppEdge/app/otbLineSegmentDetection.cxx +++ b/Modules/Applications/AppEdge/app/otbLineSegmentDetection.cxx @@ -77,6 +77,8 @@ private: SetParameterDescription("norescale","By default, the input image amplitude is rescaled between [0,255]. Turn on this parameter to skip rescaling"); MandatoryOff("norescale"); + AddRAMParameter(); + // Doc example parameter settings SetDocExampleParameterValue("in", "QB_Suburb.png"); SetDocExampleParameterValue("out", "LineSegmentDetection.shp"); @@ -117,6 +119,7 @@ private: if ( !IsParameterEnabled("norescale") ) { stats->SetInput(amplitudeConverter->GetOutput()); + stats->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram")); AddProcess(stats->GetStreamer(), "Image statistics"); stats->Update(); @@ -133,6 +136,7 @@ private: LSDFilterType::Pointer lsd = LSDFilterType::New(); lsd->GetFilter()->SetInput(image); + lsd->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram")); AddProcess(lsd->GetStreamer(), "Running Line Segment Detector"); lsd->Update(); diff --git a/Modules/Applications/AppHyperspectral/app/otbHyperspectralUnmixing.cxx b/Modules/Applications/AppHyperspectral/app/otbHyperspectralUnmixing.cxx index 3894ed1484558ebe1df7314b0294b6f6f91889f0..50c8c11dcaa5b2ccf27a0d123d2db9dcb0b3c08f 100644 --- a/Modules/Applications/AppHyperspectral/app/otbHyperspectralUnmixing.cxx +++ b/Modules/Applications/AppHyperspectral/app/otbHyperspectralUnmixing.cxx @@ -18,7 +18,6 @@ #include "otbWrapperApplication.h" #include "otbWrapperApplicationFactory.h" -#include "otbStreamingStatisticsVectorImageFilter.h" #include "otbUnConstrainedLeastSquareImageFilter.h" #include "otbISRAUnmixingImageFilter.h" #include "otbNCLSUnmixingImageFilter.h" @@ -30,9 +29,6 @@ namespace otb { namespace Wrapper { - -typedef otb::StreamingStatisticsVectorImageFilter<DoubleVectorImageType> StreamingStatisticsVectorImageFilterType; - typedef otb::UnConstrainedLeastSquareImageFilter<DoubleVectorImageType, DoubleVectorImageType, double> UCLSUnmixingFilterType; typedef otb::ISRAUnmixingImageFilter<DoubleVectorImageType, DoubleVectorImageType, double> ISRAUnmixingFilterType; typedef otb::NCLSUnmixingImageFilter<DoubleVectorImageType, DoubleVectorImageType, double> NCLSUnmixingFilterType; diff --git a/Modules/Applications/AppImageUtils/app/otbColorMapping.cxx b/Modules/Applications/AppImageUtils/app/otbColorMapping.cxx index 72945f38f32cf933c517ae3b372f0faf2dd978d6..d4968e35a4a331bb78ef6d169c39617bb91ca0ef 100644 --- a/Modules/Applications/AppImageUtils/app/otbColorMapping.cxx +++ b/Modules/Applications/AppImageUtils/app/otbColorMapping.cxx @@ -293,8 +293,6 @@ private: SetParameterDescription("out","Output image filename"); SetDefaultOutputPixelType("out",ImagePixelType_uint8); - AddRAMParameter(); - // --- OPERATION --- : Label to color / Color to label AddParameter(ParameterType_Choice, "op", "Operation"); SetParameterDescription("op","Selection of the operation to execute (default is : label to color)."); @@ -384,6 +382,7 @@ private: SetMinimumParameterIntValue("method.image.up", 0); SetMaximumParameterIntValue("method.image.up", 100); + AddRAMParameter(); // Doc example parameter settings SetDocExampleParameterValue("in", "ROI_QB_MUL_1_SVN_CLASS_MULTI.png"); @@ -611,6 +610,8 @@ private: m_StatisticsMapFromLabelImageFilter = StreamingStatisticsMapFromLabelImageFilterType::New(); m_StatisticsMapFromLabelImageFilter->SetInput(GetParameterImage("method.image.in")); m_StatisticsMapFromLabelImageFilter->SetInputLabelImage(m_CasterToLabelImage->GetOutput()); + m_StatisticsMapFromLabelImageFilter->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram")); + AddProcess(m_StatisticsMapFromLabelImageFilter->GetStreamer(), "Computing statistics on labels..."); m_StatisticsMapFromLabelImageFilter->Update(); StreamingStatisticsMapFromLabelImageFilterType::MeanValueMapType diff --git a/Modules/Applications/AppImageUtils/app/otbCompareImages.cxx b/Modules/Applications/AppImageUtils/app/otbCompareImages.cxx index 9aebb220747a1d0affed52b8ec4ca568a3814f41..f08ac34ae20f07aa8847b34de459cf277746e158 100644 --- a/Modules/Applications/AppImageUtils/app/otbCompareImages.cxx +++ b/Modules/Applications/AppImageUtils/app/otbCompareImages.cxx @@ -114,6 +114,8 @@ private: SetParameterDescription("count", "Nb of pixels which are different"); SetParameterRole("count", Role_Output); + AddRAMParameter(); + // Doc example parameter settings SetDocExampleParameterValue("ref.in", "GomaApres.png"); SetDocExampleParameterValue("ref.channel", "1"); @@ -206,6 +208,8 @@ private: m_CompareFilter->SetInput1(m_ExtractRefFilter->GetOutput()); m_CompareFilter->SetInput2(m_ExtractMeasFilter->GetOutput()); m_CompareFilter->SetPhysicalSpaceCheck(false); + m_CompareFilter->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram")); + AddProcess(m_CompareFilter->GetStreamer(), "Comparing..."); m_CompareFilter->Update(); // Show result diff --git a/Modules/Applications/AppImageUtils/app/otbConvert.cxx b/Modules/Applications/AppImageUtils/app/otbConvert.cxx index 7de721d7863d62698879a16c4800a58b436cb0db..7f7d5651dc67b13dba29bed9d68bb99379c7e35a 100644 --- a/Modules/Applications/AppImageUtils/app/otbConvert.cxx +++ b/Modules/Applications/AppImageUtils/app/otbConvert.cxx @@ -199,6 +199,7 @@ private: otbAppLogDEBUG( << "Shrink starts..." ); shrinkFilter->SetShrinkFactor(shrinkFactor); + shrinkFilter->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram")); AddProcess(shrinkFilter->GetStreamer(), "Computing shrink Image for min/max estimation..."); if ( rescaleType == "log2") @@ -210,14 +211,12 @@ private: shrinkFilter->SetInput(m_TransferLog->GetOutput()); rescaler->SetInput(m_TransferLog->GetOutput()); - shrinkFilter->GetStreamer()->SetAutomaticTiledStreaming(GetParameterInt("ram")); shrinkFilter->Update(); } else { shrinkFilter->SetInput(input); rescaler->SetInput(input); - shrinkFilter->GetStreamer()->SetAutomaticTiledStreaming(GetParameterInt("ram")); shrinkFilter->Update(); } @@ -226,7 +225,7 @@ private: { maskShrinkFilter->SetShrinkFactor(shrinkFactor); maskShrinkFilter->SetInput(mask); - maskShrinkFilter->GetStreamer()->SetAutomaticTiledStreaming(GetParameterInt("ram")); + maskShrinkFilter->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram")); maskShrinkFilter->Update(); } diff --git a/Modules/Applications/AppImageUtils/app/otbRescale.cxx b/Modules/Applications/AppImageUtils/app/otbRescale.cxx index d0304e74a465fcad7c70add4e02a67c89f5d54fa..ea109547cf8cba64d6e9775436ad18aafeb4d6f3 100644 --- a/Modules/Applications/AppImageUtils/app/otbRescale.cxx +++ b/Modules/Applications/AppImageUtils/app/otbRescale.cxx @@ -97,7 +97,7 @@ private: m_MinMaxFilter = MinMaxFilterType::New(); m_MinMaxFilter->SetInput( inImage ); - m_MinMaxFilter->GetStreamer()->SetNumberOfLinesStrippedStreaming( 50 ); + m_MinMaxFilter->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram")); AddProcess(m_MinMaxFilter->GetStreamer(), "Min/Max computing"); m_MinMaxFilter->Update(); diff --git a/Modules/Applications/AppSegmentation/app/otbConnectedComponentSegmentation.cxx b/Modules/Applications/AppSegmentation/app/otbConnectedComponentSegmentation.cxx index 8f014d3ecd7f8e2407c9ddfef7eef7c5535b7c28..1c4e3073a7657abcd6bc73e0f45fc773d845308d 100644 --- a/Modules/Applications/AppSegmentation/app/otbConnectedComponentSegmentation.cxx +++ b/Modules/Applications/AppSegmentation/app/otbConnectedComponentSegmentation.cxx @@ -108,6 +108,8 @@ private: // Elevation ElevationParametersHandler::AddElevationParameters(this, "elev"); + AddRAMParameter(); + // Doc example parameter settings SetDocExampleParameterValue("in", "ROI_QB_MUL_4.tif"); SetDocExampleParameterValue("mask", "\"((b1>80)*intensity>95)\""); @@ -139,7 +141,8 @@ private: if (IsParameterEnabled("obia") && HasValue("obia")) m_Connected->GetFilter()->SetOBIAExpression(GetParameterString("obia")); - AddProcess(m_Connected,"Computing segmentation"); + m_Connected->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram")); + AddProcess(m_Connected->GetStreamer(),"Computing segmentation"); m_Connected->Update(); /* diff --git a/Modules/Applications/AppSegmentation/app/otbLSMSSmallRegionsMerging.cxx b/Modules/Applications/AppSegmentation/app/otbLSMSSmallRegionsMerging.cxx index 23f33978594b6c16e37190d2e30f9b3bed16ae20..5adea92933da93767bde59b94d11a5bcd955d694 100644 --- a/Modules/Applications/AppSegmentation/app/otbLSMSSmallRegionsMerging.cxx +++ b/Modules/Applications/AppSegmentation/app/otbLSMSSmallRegionsMerging.cxx @@ -108,6 +108,8 @@ private: SetDefaultParameterInt("tilesizey", 500); SetMinimumParameterIntValue("tilesizey", 1); + AddRAMParameter(); + // Doc example parameter settings SetDocExampleParameterValue("in","smooth.tif"); SetDocExampleParameterValue("inseg","segmentation.tif"); @@ -142,6 +144,8 @@ private: StatisticsImageFilterType::Pointer stats = StatisticsImageFilterType::New(); stats->SetInput(labelIn); + stats->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram")); + AddProcess(stats->GetStreamer(), "Retrieve region count..."); stats->Update(); unsigned int regionCount=stats->GetMaximum(); diff --git a/Modules/Applications/AppSegmentation/app/otbLSMSVectorization.cxx b/Modules/Applications/AppSegmentation/app/otbLSMSVectorization.cxx index 9a0c070e995925392b067ed4d42508694f0b2151..9238a008f50a8854024946dbb50933b38823dcb3 100644 --- a/Modules/Applications/AppSegmentation/app/otbLSMSVectorization.cxx +++ b/Modules/Applications/AppSegmentation/app/otbLSMSVectorization.cxx @@ -94,6 +94,8 @@ private: SetDefaultParameterInt("tilesizey", 500); SetMinimumParameterIntValue("tilesizey", 1); + AddRAMParameter(); + // Doc example parameter settings SetDocExampleParameterValue("in","avions.tif"); SetDocExampleParameterValue("inseg","merged.tif"); @@ -129,6 +131,8 @@ private: StatisticsImageFilterType::Pointer stats = StatisticsImageFilterType::New(); stats->SetInput(labelIn); + stats->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram")); + AddProcess(stats->GetStreamer(), "Retrieve region count..."); stats->Update(); unsigned int regionCount=stats->GetMaximum(); diff --git a/Modules/Applications/AppStereo/app/otbStereoFramework.cxx b/Modules/Applications/AppStereo/app/otbStereoFramework.cxx index 24c60f8d28c8c4faeb6f2da2e5e2baf15abb5931..1b18dc5b89b6cece6460f3c72f7774f239cc873b 100644 --- a/Modules/Applications/AppStereo/app/otbStereoFramework.cxx +++ b/Modules/Applications/AppStereo/app/otbStereoFramework.cxx @@ -39,7 +39,6 @@ #include "itkRescaleIntensityImageFilter.h" #include "otbStreamingMinMaxImageFilter.h" -#include "otbStreamingStatisticsImageFilter.h" #include "otbExtractROI.h" #include "otbImageFileReader.h" #include "otbImageFileWriter.h" @@ -183,9 +182,6 @@ public: typedef otb::StreamingMinMaxImageFilter <FloatImageType> MinMaxFilterType; - typedef otb::StreamingStatisticsImageFilter - <FloatImageType> StatisticsFilterType; - typedef otb::ExtractROI <FloatPixelType,FloatPixelType> ExtractFilterType; diff --git a/Modules/Applications/AppStereo/app/otbStereoRectificationGridGenerator.cxx b/Modules/Applications/AppStereo/app/otbStereoRectificationGridGenerator.cxx index a6f746a992a92f67447d5361345967fa720aa611..b9f6b1fdb4a0fbaf0acd6bbed9e7952155eec52b 100644 --- a/Modules/Applications/AppStereo/app/otbStereoRectificationGridGenerator.cxx +++ b/Modules/Applications/AppStereo/app/otbStereoRectificationGridGenerator.cxx @@ -239,7 +239,8 @@ private: m_DEMToImageGenerator->AboveEllipsoidOn(); m_StatisticsFilter->SetInput(m_DEMToImageGenerator->GetOutput()); - AddProcess(m_StatisticsFilter,"Computing DEM statistics ..."); + m_StatisticsFilter->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram")); + AddProcess(m_StatisticsFilter->GetStreamer(),"Computing DEM statistics ..."); m_StatisticsFilter->Update(); otb::DEMHandler::Instance()->SetDefaultHeightAboveEllipsoid(m_StatisticsFilter->GetMean()); diff --git a/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.h b/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.h index ba95eeaa148f39d7c3beccd505529b6d9daaf964..d09e21962c26b242c2c8bb3de2648eafadb9c4db 100644 --- a/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.h @@ -94,8 +94,6 @@ public: /** Train the machine learning model */ void Train() ITK_OVERRIDE; - /** Predict values using the model */ - TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality=NULL) const ITK_OVERRIDE; /** Save the model to file */ void Save(const std::string & filename, const std::string & name="") ITK_OVERRIDE; @@ -119,6 +117,10 @@ protected: /** Destructor */ ~BoostMachineLearningModel() ITK_OVERRIDE; + /** Predict values using the model */ + TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE; + + /** PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE; diff --git a/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.txx index 8d20ca5f7f5d16068ed2b136e6e53791d59c71d8..5f7745a37aa95c2207d28426e3ec4b250f35ff42 100644 --- a/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.txx +++ b/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.txx @@ -77,7 +77,7 @@ template <class TInputValue, class TOutputValue> typename BoostMachineLearningModel<TInputValue,TOutputValue> ::TargetSampleType BoostMachineLearningModel<TInputValue,TOutputValue> -::Predict(const InputSampleType & input, ConfidenceValueType *quality) const +::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const { //convert listsample to Mat cv::Mat sample; diff --git a/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.h b/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.h index 571bbd597a2c21a821ccd6a8d403a38718814c8f..a34417e810dba03423e85bcb853cf57d1aef741a 100644 --- a/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.h @@ -149,8 +149,6 @@ public: /** Train the machine learning model */ void Train() ITK_OVERRIDE; - /** Predict values using the model */ - TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality=NULL) const ITK_OVERRIDE; /** Save the model to file */ void Save(const std::string & filename, const std::string & name="") ITK_OVERRIDE; @@ -174,6 +172,9 @@ protected: /** Destructor */ ~DecisionTreeMachineLearningModel() ITK_OVERRIDE; + /** Predict values using the model */ + TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE; + /** PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE; diff --git a/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.txx index 07ce3a1129c93a9225e9dae06b4c208779a6093b..ebcc7bfbef5a60d34bbd96c1eefb9c12c90fb0a4 100644 --- a/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.txx +++ b/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.txx @@ -83,7 +83,7 @@ template <class TInputValue, class TOutputValue> typename DecisionTreeMachineLearningModel<TInputValue,TOutputValue> ::TargetSampleType DecisionTreeMachineLearningModel<TInputValue,TOutputValue> -::Predict(const InputSampleType & input, ConfidenceValueType *quality) const +::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const { //convert listsample to Mat cv::Mat sample; diff --git a/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.h b/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.h index 4221da6df8b58ba195c75347507665df8bd845f8..92f9e04781fcd19805b181954e9a7c8292e11d14 100644 --- a/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.h @@ -102,8 +102,6 @@ public: /** Train the machine learning model */ void Train() ITK_OVERRIDE; - /** Predict values using the model */ - TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality=NULL) const ITK_OVERRIDE; /** Save the model to file */ void Save(const std::string & filename, const std::string & name="") ITK_OVERRIDE; @@ -127,6 +125,10 @@ protected: /** Destructor */ ~GradientBoostedTreeMachineLearningModel() ITK_OVERRIDE; + /** Predict values using the model */ + TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE; + + /** PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE; diff --git a/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.txx index 53e6931575e6f134115a21d5587fa7a006a8f173..3ab84acbf58f4ff3ad2c22e1d8f4502a0feb48b8 100644 --- a/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.txx +++ b/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.txx @@ -79,7 +79,7 @@ template <class TInputValue, class TOutputValue> typename GradientBoostedTreeMachineLearningModel<TInputValue,TOutputValue> ::TargetSampleType GradientBoostedTreeMachineLearningModel<TInputValue,TOutputValue> -::Predict(const InputSampleType & input, ConfidenceValueType *quality) const +::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const { //convert listsample to Mat cv::Mat sample; diff --git a/Modules/Learning/Supervised/include/otbImageClassificationFilter.h b/Modules/Learning/Supervised/include/otbImageClassificationFilter.h index e8ee652f0fccb863fe6ce9c819f86fd6e8bcdc5e..7d4cf8a9766bf21e8cc1a7c2e77c16150720b218 100644 --- a/Modules/Learning/Supervised/include/otbImageClassificationFilter.h +++ b/Modules/Learning/Supervised/include/otbImageClassificationFilter.h @@ -67,7 +67,7 @@ public: typedef typename OutputImageType::PixelType LabelType; typedef MachineLearningModel<ValueType, LabelType> ModelType; - typedef typename ModelType::Pointer ModelPointerType; + typedef typename ModelType::Pointer ModelPointerType; typedef otb::Image<double> ConfidenceImageType; typedef typename ConfidenceImageType::Pointer ConfidenceImagePointerType; @@ -84,6 +84,10 @@ public: itkSetMacro(UseConfidenceMap, bool); itkGetMacro(UseConfidenceMap, bool); + itkSetMacro(BatchMode, bool); + itkGetMacro(BatchMode, bool); + itkBooleanMacro(BatchMode); + /** * If set, only pixels within the mask will be classified. * All pixels with a value greater than 0 in the mask, will be classified. @@ -110,6 +114,8 @@ protected: /** Threaded generate data */ void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) ITK_OVERRIDE; + void ClassicThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId); + void BatchThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId); /** Before threaded generate data */ void BeforeThreadedGenerateData() ITK_OVERRIDE; /**PrintSelf method */ @@ -125,6 +131,7 @@ private: LabelType m_DefaultLabel; /** Flag to produce the confidence map (if the model supports it) */ bool m_UseConfidenceMap; + bool m_BatchMode; }; } // End namespace otb #ifndef OTB_MANUAL_INSTANTIATION diff --git a/Modules/Learning/Supervised/include/otbImageClassificationFilter.txx b/Modules/Learning/Supervised/include/otbImageClassificationFilter.txx index 72614862a991acc87bd75ed14ff4e6d3fdc103cb..899a5a25066ddb9d0d77a8dd5d687f1bcfc5caa8 100644 --- a/Modules/Learning/Supervised/include/otbImageClassificationFilter.txx +++ b/Modules/Learning/Supervised/include/otbImageClassificationFilter.txx @@ -39,6 +39,7 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> this->SetNthOutput(0,TOutputImage::New()); this->SetNthOutput(1,ConfidenceImageType::New()); m_UseConfidenceMap = false; + m_BatchMode = true; } template <class TInputImage, class TOutputImage, class TMaskImage> @@ -84,12 +85,19 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> { itkGenericExceptionMacro(<< "No model for classification"); } + if(m_BatchMode) + { + #ifdef _OPENMP + // OpenMP will take care of threading + this->SetNumberOfThreads(1); + #endif + } } template <class TInputImage, class TOutputImage, class TMaskImage> void ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> -::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) +::ClassicThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) { // Get the input pointers InputImageConstPointerType inputPtr = this->GetInput(); @@ -165,6 +173,140 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> progress.CompletedPixel(); } +} + +template <class TInputImage, class TOutputImage, class TMaskImage> +void +ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> +::BatchThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) +{ + bool computeConfidenceMap(m_UseConfidenceMap && m_Model->HasConfidenceIndex() + && !m_Model->GetRegressionMode()); + // Get the input pointers + InputImageConstPointerType inputPtr = this->GetInput(); + MaskImageConstPointerType inputMaskPtr = this->GetInputMask(); + OutputImagePointerType outputPtr = this->GetOutput(); + ConfidenceImagePointerType confidencePtr = this->GetOutputConfidence(); + + // Progress reporting + itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels()); + + // Define iterators + typedef itk::ImageRegionConstIterator<InputImageType> InputIteratorType; + typedef itk::ImageRegionConstIterator<MaskImageType> MaskIteratorType; + typedef itk::ImageRegionIterator<OutputImageType> OutputIteratorType; + typedef itk::ImageRegionIterator<ConfidenceImageType> ConfidenceMapIteratorType; + + InputIteratorType inIt(inputPtr, outputRegionForThread); + OutputIteratorType outIt(outputPtr, outputRegionForThread); + + MaskIteratorType maskIt; + if (inputMaskPtr) + { + maskIt = MaskIteratorType(inputMaskPtr, outputRegionForThread); + maskIt.GoToBegin(); + } + + // typedef typename ModelType::InputValueType InputValueType; + typedef typename ModelType::InputSampleType InputSampleType; + typedef typename ModelType::InputListSampleType InputListSampleType; + typedef typename ModelType::TargetValueType TargetValueType; + // typedef typename ModelType::TargetSampleType TargetSampleType; + typedef typename ModelType::TargetListSampleType TargetListSampleType; + // typedef typename ModelType::ConfidenceValueType ConfidenceValueType; + // typedef typename ModelType::ConfidenceSampleType ConfidenceSampleType; + typedef typename ModelType::ConfidenceListSampleType ConfidenceListSampleType; + + typename InputListSampleType::Pointer samples = InputListSampleType::New(); + unsigned int num_features = inputPtr->GetNumberOfComponentsPerPixel(); + samples->SetMeasurementVectorSize(num_features); + InputSampleType sample(num_features); + // Fill the samples + bool validPoint = true; + for (inIt.GoToBegin(); !inIt.IsAtEnd(); ++inIt) + { + // Check pixel validity + if (inputMaskPtr) + { + validPoint = maskIt.Get() > 0; + ++maskIt; + } + if(validPoint) + { + typename InputImageType::PixelType pix = inIt.Get(); + for(size_t feat=0; feat<num_features; ++feat) + { + sample[feat]=pix[feat]; + } + samples->PushBack(sample); + } + } + //Make the batch prediction + typename TargetListSampleType::Pointer labels; + typename ConfidenceListSampleType::Pointer confidences; + if(computeConfidenceMap) + confidences = ConfidenceListSampleType::New(); + + // This call is threadsafe + labels = m_Model->PredictBatch(samples,confidences); + + // Set the output values + ConfidenceMapIteratorType confidenceIt; + if (computeConfidenceMap) + { + confidenceIt = ConfidenceMapIteratorType(confidencePtr,outputRegionForThread); + confidenceIt.GoToBegin(); + } + + typename TargetListSampleType::ConstIterator labIt = labels->Begin(); + maskIt.GoToBegin(); + for (outIt.GoToBegin(); labIt!=labels->End() && !outIt.IsAtEnd(); + ++outIt) + { + double confidenceIndex = 0.0; + TargetValueType labelValue(m_DefaultLabel); + if (inputMaskPtr) + { + validPoint = maskIt.Get() > 0; + ++maskIt; + } + if (validPoint) + { + labelValue = labIt.GetMeasurementVector()[0]; + + if(computeConfidenceMap) + { + confidenceIndex = confidences->GetMeasurementVector(labIt.GetInstanceIdentifier())[0]; + } + + ++labIt; + } + + outIt.Set(labelValue); + + if(computeConfidenceMap) + { + confidenceIt.Set(confidenceIndex); + ++confidenceIt; + } + + progress.CompletedPixel(); + } +} +template <class TInputImage, class TOutputImage, class TMaskImage> +void +ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> +::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) +{ + if(m_BatchMode) + { + this->BatchThreadedGenerateData(outputRegionForThread, threadId); + } + else + { + this->ClassicThreadedGenerateData(outputRegionForThread, threadId); + } + } /** * PrintSelf Method diff --git a/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.h b/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.h index 2954ba4ffd9fa161563cc7facddd183eca483da4..857fa37efc6c3c6411d57d8e35e1a1776b923e04 100644 --- a/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.h @@ -73,8 +73,6 @@ public: /** Train the machine learning model */ void Train() ITK_OVERRIDE; - /** Predict values using the model */ - TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality=NULL) const ITK_OVERRIDE; /** Save the model to file */ void Save(const std::string & filename, const std::string & name="") ITK_OVERRIDE; @@ -98,6 +96,10 @@ protected: /** Destructor */ ~KNearestNeighborsMachineLearningModel() ITK_OVERRIDE; + /** Predict values using the model */ + TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE; + + /** PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE; diff --git a/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.txx index 2a6705d1aa1aa5093d50201fe06731318f97ce38..040a0ea7ba8ee834267beeb53598c225a0732822 100644 --- a/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.txx +++ b/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.txx @@ -85,7 +85,7 @@ template <class TInputValue, class TTargetValue> typename KNearestNeighborsMachineLearningModel<TInputValue,TTargetValue> ::TargetSampleType KNearestNeighborsMachineLearningModel<TInputValue,TTargetValue> -::Predict(const InputSampleType & input, ConfidenceValueType *quality) const +::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const { //convert listsample to Mat cv::Mat sample; diff --git a/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.h b/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.h index b398f7d640a1f3c0add82222a56e31baeabb0fac..2fb03297052bf8a2cf7015dea7b8cba04b80e159 100644 --- a/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.h @@ -61,8 +61,6 @@ public: /** Train the machine learning model */ void Train() ITK_OVERRIDE; - /** Predict values using the model */ - TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality=NULL) const ITK_OVERRIDE; /** Save the model to file */ void Save(const std::string &filename, const std::string & name="") ITK_OVERRIDE; @@ -122,6 +120,9 @@ protected: /** Destructor */ ~LibSVMMachineLearningModel() ITK_OVERRIDE; + /** Predict values using the model */ + TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE; + /** PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE; diff --git a/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.txx index 70da67ed4ef9dea8dd124f0b6e5844f9545bcf13..bc35ad660e246796ffafe7df541fa2bd4c7cae86 100644 --- a/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.txx +++ b/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.txx @@ -71,7 +71,7 @@ template <class TInputValue, class TOutputValue> typename LibSVMMachineLearningModel<TInputValue,TOutputValue> ::TargetSampleType LibSVMMachineLearningModel<TInputValue,TOutputValue> -::Predict(const InputSampleType & input, ConfidenceValueType *quality) const +::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const { TargetSampleType target; diff --git a/Modules/Learning/Supervised/include/otbMachineLearningModel.h b/Modules/Learning/Supervised/include/otbMachineLearningModel.h index 3bc693cbc459fa35cb39821fe19ceed663b210ec..2cf4850182d5b8d6f34f84695a8390e2bd153cb4 100644 --- a/Modules/Learning/Supervised/include/otbMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbMachineLearningModel.h @@ -34,7 +34,8 @@ namespace otb * Neural Network, ...) in the generic supervised classification framework of the OTB. * The main generic virtual methods specifically implemented in each classifier * derived from the MachineLearningModel class are two learning-related methods: - * Train() and Save(), and two classification-related methods: Load() and Predict(). + * Train() and Save(), and three classification-related methods: Load(), + * DoPredict() and optionnaly DoPredictBatch(). * * Thus, each classifier derived from the MachineLearningModel class * computes its corresponding model with Train() and exports it with @@ -55,6 +56,7 @@ namespace otb * \sa GradientBoostedTreeMachineLearningModel * \sa NormalBayesMachineLearningModel * \sa NeuralNetworkMachineLearningModel + * \sa SharkRandomForestsMachineLearningModel * \sa ImageClassificationFilter * * @@ -89,6 +91,8 @@ public: /**\name Confidence value typedef */ typedef TConfidenceValue ConfidenceValueType; + typedef itk::FixedArray<ConfidenceValueType,1> ConfidenceSampleType; + typedef itk::Statistics::ListSample<ConfidenceSampleType> ConfidenceListSampleType; /**\name Standard macros */ //@{ @@ -99,10 +103,27 @@ public: /** Train the machine learning model */ virtual void Train() =0; - /** Predict values using the model */ - virtual TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality = ITK_NULLPTR) const = 0; - - /** Classify all samples in InputListSample and fill TargetListSample with the associated label */ + /** Predict a single sample + * \param input The sample + * \param quality A pointer to the quality variable were to store + * quality value, or NULL + * \return The predicted label + */ + TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality = ITK_NULLPTR) const; + + + + /** Predict a batch of samples (InputListSampleType) + * \param input The batch of sample to predict + * \param quality A pointer to the list were to store + * quality value, or NULL + * \return The predicted labels + * Note that this method will be multi-threaded if OTB is built + * with OpenMP. + */ + typename TargetListSampleType::Pointer PredictBatch(const InputListSampleType * input, ConfidenceListSampleType * quality = ITK_NULLPTR) const; + + /** THIS METHOD IS DEPRECATED AND SHOULD NOT BE USED. */ void PredictAll(); /**\name Classification model file manipulation */ @@ -130,6 +151,7 @@ public: //@{ itkSetObjectMacro(InputListSample,InputListSampleType); itkGetObjectMacro(InputListSample,InputListSampleType); + itkGetConstObjectMacro(InputListSample,InputListSampleType); //@} /**\name Classification output accessors */ @@ -140,6 +162,8 @@ public: itkGetObjectMacro(TargetListSample,TargetListSampleType); //@} + itkGetObjectMacro(ConfidenceListSample,ConfidenceListSampleType); + /**\name Use model in regression mode */ //@{ itkGetMacro(RegressionMode,bool); @@ -152,7 +176,7 @@ protected: /** Destructor */ ~MachineLearningModel() ITK_OVERRIDE; - + /** PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE; @@ -162,6 +186,8 @@ protected: /** Target list sample */ typename TargetListSampleType::Pointer m_TargetListSample; + typename ConfidenceListSampleType::Pointer m_ConfidenceListSample; + /** flag to choose between classification and regression modes */ bool m_RegressionMode; @@ -172,7 +198,36 @@ protected: /** flag that tells if the model support confidence index output */ bool m_ConfidenceIndex; + + /** Is DoPredictBatch multi-threaded ? */ + bool m_IsDoPredictBatchMultiThreaded; + private: + /** Actual implementation of BatchPredicition + * Default implementation will call DoPredict iteratively + * \param input The input batch + * \param startIndex Index of the first sample to predict + * \param size Number of samples to predict + * \param target Pointer to the list of produced labels + * \param quality Pointer to the list of produced confidence + * values, or NULL + * + * Override me if internal implementation allows for batch + * prediction. + * + * Also set m_IsDoPredictBatchMultiThreaded to true if internal + * implementation allows for parallel batch prediction. + */ + virtual void DoPredictBatch(const InputListSampleType * input, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * target, ConfidenceListSampleType * quality = ITK_NULLPTR) const; + + /** Actual implementation of single sample prediction + * \param input sample to predict + * \param quality Pointer to a variable to store confidence value, + * or NULL + * \return The predicted label + */ + virtual TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType * quality= ITK_NULLPTR) const = 0; + MachineLearningModel(const Self &); //purposely not implemented void operator =(const Self&); //purposely not implemented }; diff --git a/Modules/Learning/Supervised/include/otbMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbMachineLearningModel.txx index c3954072ccda0e90733f6299db5767540983475f..3d67a0a3a2a68000a60225d9b822a25157277f14 100644 --- a/Modules/Learning/Supervised/include/otbMachineLearningModel.txx +++ b/Modules/Learning/Supervised/include/otbMachineLearningModel.txx @@ -18,8 +18,14 @@ #ifndef otbMachineLearningModel_txx #define otbMachineLearningModel_txx +#ifdef _OPENMP + # include <omp.h> +#endif + #include "otbMachineLearningModel.h" +#include "itkMultiThreader.h" + namespace otb { @@ -28,7 +34,8 @@ MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue> ::MachineLearningModel() : m_RegressionMode(false), m_IsRegressionSupported(false), - m_ConfidenceIndex(false) + m_ConfidenceIndex(false), + m_IsDoPredictBatchMultiThreaded(false) {} @@ -58,13 +65,117 @@ void MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue> ::PredictAll() { - TargetListSampleType * targets = this->GetTargetListSample(); + itkWarningMacro("MachineLearningModel::PredictAll() has been DEPRECATED. Use MachineLearningModel::PredictBatch() instead."); + + typename TargetListSampleType::Pointer targets = this->GetTargetListSample(); targets->Clear(); + + typename TargetListSampleType::Pointer tmpTargets = this->PredictBatch(this->GetInputListSample()); + + targets->Graft(tmpTargets); +} + +template <class TInputValue, class TOutputValue, class TConfidenceValue> +typename MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue> +::TargetSampleType +MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue> +::Predict(const InputSampleType& input, ConfidenceValueType *quality) const +{ + // Call protected specialization entry point + return this->DoPredict(input,quality); +} - for(typename InputListSampleType::ConstIterator sIt = this->GetInputListSample()->Begin(); - sIt!=this->GetInputListSample()->End(); ++sIt) + +template <class TInputValue, class TOutputValue, class TConfidenceValue> +typename MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue> +::TargetListSampleType::Pointer +MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue> +::PredictBatch(const InputListSampleType * input, ConfidenceListSampleType * quality) const +{ + typename TargetListSampleType::Pointer targets = TargetListSampleType::New(); + targets->Resize(input->Size()); + + if(quality!=ITK_NULLPTR) + { + quality->Clear(); + quality->Resize(input->Size()); + } + + if(m_IsDoPredictBatchMultiThreaded) + { + // Simply calls DoPredictBatch + this->DoPredictBatch(input,0,input->Size(),targets,quality); + return targets; + } + else + { + + #ifdef _OPENMP + // OpenMP threading here + unsigned int nb_threads(0), threadId(0), nb_batches(0); + + #pragma omp parallel shared(nb_threads,nb_batches) private(threadId) + { + // Get number of threads configured with ITK + omp_set_num_threads(itk::MultiThreader::GetGlobalDefaultNumberOfThreads()); + nb_threads = omp_get_num_threads(); + threadId = omp_get_thread_num(); + nb_batches = std::min(nb_threads,(unsigned int)input->Size()); + // Ensure that we do not spawn unncessary threads + if(threadId<nb_batches) + { + unsigned int batch_size = ((unsigned int)input->Size()/nb_batches); + unsigned int batch_start = threadId*batch_size; + if(threadId == nb_threads-1) + { + batch_size+=input->Size()%nb_batches; + } + + this->DoPredictBatch(input,batch_start,batch_size,targets,quality); + } + } + #else + this->DoPredictBatch(input,0,input->Size(),targets,quality); + #endif + return targets; + } +} + + + +template <class TInputValue, class TOutputValue, class TConfidenceValue> +void +MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue> +::DoPredictBatch(const InputListSampleType * input, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * targets, ConfidenceListSampleType * quality) const +{ + assert(input != ITK_NULLPTR); + assert(targets != ITK_NULLPTR); + + assert(input->Size()==targets->Size()&&"Input sample list and target label list do not have the same size."); + assert(((quality==ITK_NULLPTR)||(quality->Size()==input->Size()))&&"Quality samples list is not null and does not have the same size as input samples list"); + + if(startIndex+size>input->Size()) + { + itkExceptionMacro(<<"requested range ["<<startIndex<<", "<<startIndex+size<<"[ partially outside input sample list range.[0,"<<input->Size()<<"["); + } + + if(quality != ITK_NULLPTR) + { + for(unsigned int id = startIndex;id<startIndex+size;++id) + { + ConfidenceValueType confidence = 0; + const TargetSampleType target = this->DoPredict(input->GetMeasurementVector(id),&confidence); + quality->SetMeasurementVector(id,confidence); + targets->SetMeasurementVector(id,target); + } + } + else { - targets->PushBack(this->Predict(sIt.GetMeasurementVector())); + for(unsigned int id = startIndex;id<startIndex+size;++id) + { + const TargetSampleType target = this->DoPredict(input->GetMeasurementVector(id)); + targets->SetMeasurementVector(id,target); + } } } diff --git a/Modules/Learning/Supervised/include/otbMachineLearningModelFactory.txx b/Modules/Learning/Supervised/include/otbMachineLearningModelFactory.txx index c5c5cea552a85b2f16b244e63d339c488d239d77..a99aa0f78e4d86f128b855299bfd4eacb340948b 100644 --- a/Modules/Learning/Supervised/include/otbMachineLearningModelFactory.txx +++ b/Modules/Learning/Supervised/include/otbMachineLearningModelFactory.txx @@ -35,6 +35,10 @@ #include "otbLibSVMMachineLearningModelFactory.h" #endif +#ifdef OTB_USE_SHARK +#include "otbSharkRandomForestsMachineLearningModelFactory.h" +#endif + #include "itkMutexLockHolder.h" @@ -98,6 +102,10 @@ MachineLearningModelFactory<TInputValue,TOutputValue> RegisterFactory(LibSVMMachineLearningModelFactory<TInputValue,TOutputValue>::New()); #endif +#ifdef OTB_USE_SHARK + RegisterFactory(SharkRandomForestsMachineLearningModelFactory<TInputValue,TOutputValue>::New()); +#endif + #ifdef OTB_USE_OPENCV RegisterFactory(RandomForestsMachineLearningModelFactory<TInputValue,TOutputValue>::New()); RegisterFactory(SVMMachineLearningModelFactory<TInputValue,TOutputValue>::New()); @@ -107,8 +115,7 @@ MachineLearningModelFactory<TInputValue,TOutputValue> RegisterFactory(DecisionTreeMachineLearningModelFactory<TInputValue,TOutputValue>::New()); RegisterFactory(GradientBoostedTreeMachineLearningModelFactory<TInputValue,TOutputValue>::New()); RegisterFactory(KNearestNeighborsMachineLearningModelFactory<TInputValue,TOutputValue>::New()); -#endif - +#endif } template <class TInputValue, class TOutputValue> @@ -144,6 +151,17 @@ MachineLearningModelFactory<TInputValue,TOutputValue> continue; } #endif + +#ifdef OTB_USE_SHARK + SharkRandomForestsMachineLearningModelFactory<TInputValue,TOutputValue> *sharkRFFactory = + dynamic_cast<SharkRandomForestsMachineLearningModelFactory<TInputValue,TOutputValue> *>(*itFac); + if (sharkRFFactory) + { + itk::ObjectFactoryBase::UnRegisterFactory(sharkRFFactory); + continue; + } +#endif + #ifdef OTB_USE_OPENCV // RandomForest RandomForestsMachineLearningModelFactory<TInputValue,TOutputValue> *rfFactory = @@ -209,7 +227,7 @@ MachineLearningModelFactory<TInputValue,TOutputValue> itk::ObjectFactoryBase::UnRegisterFactory(knnFactory); continue; } -#endif +#endif } } diff --git a/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.h b/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.h index dd132b956d17a3a7a39f45d03d0a200d2b2ed3be..629f078bc5abe87973f343746521b67d89ae82c0 100644 --- a/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.h @@ -170,8 +170,6 @@ public: /** Train the machine learning model */ void Train() ITK_OVERRIDE; - /** Predict values using the model */ - TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality=NULL) const ITK_OVERRIDE; /** Save the model to file */ void Save(const std::string & filename, const std::string & name="") ITK_OVERRIDE; @@ -195,6 +193,9 @@ protected: /** Destructor */ ~NeuralNetworkMachineLearningModel() ITK_OVERRIDE; + /** Predict values using the model */ + TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE; + void LabelsToMat(const TargetListSampleType * listSample, cv::Mat & output); /** PrintSelf method */ diff --git a/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.txx index 9e1e6bb8f507a01c8f4348d3e736db5fff3a5792..516655585ddb2063e332eef6ed4a67d1503bf3a9 100644 --- a/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.txx +++ b/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.txx @@ -200,7 +200,7 @@ void NeuralNetworkMachineLearningModel<TInputValue, TOutputValue>::Train() template<class TInputValue, class TOutputValue> typename NeuralNetworkMachineLearningModel<TInputValue, TOutputValue>::TargetSampleType NeuralNetworkMachineLearningModel< - TInputValue, TOutputValue>::Predict(const InputSampleType & input, ConfidenceValueType *quality) const + TInputValue, TOutputValue>::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const { //convert listsample to Mat cv::Mat sample; diff --git a/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.h b/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.h index f9362e970dfbfb9b5a82b87761e0e6c4b73333de..eb07312a21eaf9d0daf82bcf356e66cfda2ed505 100644 --- a/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.h @@ -54,8 +54,6 @@ public: /** Train the machine learning model */ void Train() ITK_OVERRIDE; - /** Predict values using the model */ - TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality=NULL) const ITK_OVERRIDE; /** Save the model to file */ void Save(const std::string & filename, const std::string & name="") ITK_OVERRIDE; @@ -79,6 +77,10 @@ protected: /** Destructor */ ~NormalBayesMachineLearningModel() ITK_OVERRIDE; + /** Predict values using the model */ + TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE; + + /** PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE; diff --git a/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.txx index b4ef2c295546a8cc3b9ba003ea091f31a9d0d2a6..26b3f35aa19b7d87895e970bc682d821a9bf553e 100644 --- a/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.txx +++ b/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.txx @@ -61,7 +61,7 @@ template <class TInputValue, class TOutputValue> typename NormalBayesMachineLearningModel<TInputValue,TOutputValue> ::TargetSampleType NormalBayesMachineLearningModel<TInputValue,TOutputValue> -::Predict(const InputSampleType & input, ConfidenceValueType *quality) const +::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const { //convert listsample to Mat cv::Mat sample; diff --git a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.h b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.h index bdd265b18018bb6d955fb30ff952d8b48ddfc8dc..6ce9bf630be8d70d603ec1d12086acaf63e9b71f 100644 --- a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.h @@ -62,8 +62,6 @@ public: /** Train the machine learning model */ void Train() ITK_OVERRIDE; - /** Predict values using the model */ - TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality=NULL) const ITK_OVERRIDE; /** Save the model to file */ void Save(const std::string & filename, const std::string & name="") ITK_OVERRIDE; @@ -136,6 +134,10 @@ protected: /** Destructor */ ~RandomForestsMachineLearningModel() ITK_OVERRIDE; + /** Predict values using the model */ + TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE; + + /** PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE; diff --git a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.txx index cb95be8e75b5edfaa0893c0f6f61050c3b339fb2..98042007b9382480a8176b910912d310a7d90a34 100644 --- a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.txx +++ b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.txx @@ -111,7 +111,7 @@ template <class TInputValue, class TOutputValue> typename RandomForestsMachineLearningModel<TInputValue,TOutputValue> ::TargetSampleType RandomForestsMachineLearningModel<TInputValue,TOutputValue> -::Predict(const InputSampleType & value, ConfidenceValueType *quality) const +::DoPredict(const InputSampleType & value, ConfidenceValueType *quality) const { //convert listsample to Mat cv::Mat sample; @@ -204,9 +204,9 @@ RandomForestsMachineLearningModel<TInputValue,TOutputValue> { cv::Mat cvMat = m_RFModel->getVarImportance(); VariableImportanceMatrixType itkMat(cvMat.rows,cvMat.cols); - for(unsigned int i =0; i<cvMat.rows; i++) + for(int i =0; i<cvMat.rows; i++) { - for(unsigned int j =0; j<cvMat.cols; j++) + for(int j =0; j<cvMat.cols; j++) { itkMat(i,j)=cvMat.at<float>(i,j); } diff --git a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModelFactory.h b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModelFactory.h index 02c97efe016551c0d9ed6b70546d0a3827728f02..7af7240036d2a6a6bca1f837571b692204bcc7b6 100644 --- a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModelFactory.h +++ b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModelFactory.h @@ -26,7 +26,7 @@ namespace otb { /** \class RandomForestsMachineLearningModelFactory - * \brief Creation d'un instance d'un objet RandomForestsMachineLearningModel utilisant les object factory. + * \brief Creation of an instance of a RandomForestsMachineLearningModel object using the object factory * * \ingroup OTBSupervised */ diff --git a/Modules/Learning/Supervised/include/otbRequiresSharkCheck.h b/Modules/Learning/Supervised/include/otbRequiresSharkCheck.h new file mode 100644 index 0000000000000000000000000000000000000000..a358a1b6a934e2e2438bb7067bb5c4d9632b2962 --- /dev/null +++ b/Modules/Learning/Supervised/include/otbRequiresSharkCheck.h @@ -0,0 +1,26 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + + =========================================================================*/ +#ifndef otbRequiresSharkCheck_h +#define otbRequiresSharkCheck_h + +#include "otbConfigure.h" +#ifndef OTB_USE_SHARK +# error "You need to enable Shark to compile this file" +#endif + +#endif diff --git a/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h b/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h index 06131fe76b398260cdb970120504a8e2ba494d88..5eee69c652006382e9abd9c2a346e44ddb74b4dc 100644 --- a/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h @@ -61,8 +61,6 @@ public: /** Train the machine learning model */ void Train() ITK_OVERRIDE; - /** Predict values using the model */ - TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality=NULL) const ITK_OVERRIDE; /** Save the model to file */ void Save(const std::string & filename, const std::string & name="") ITK_OVERRIDE; @@ -136,6 +134,10 @@ protected: /** Destructor */ ~SVMMachineLearningModel() ITK_OVERRIDE; + /** Predict values using the model */ + TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE; + + /** PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE; diff --git a/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.txx index 57006ce0d7945dcf6fdc8a38ea28d5a5e7940d19..48960bd13988910b2341cc7b65421c6bcdd555f0 100644 --- a/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.txx +++ b/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.txx @@ -118,7 +118,7 @@ template <class TInputValue, class TOutputValue> typename SVMMachineLearningModel<TInputValue,TOutputValue> ::TargetSampleType SVMMachineLearningModel<TInputValue,TOutputValue> -::Predict(const InputSampleType & input, ConfidenceValueType *quality) const +::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const { //convert listsample to Mat cv::Mat sample; diff --git a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.h b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.h new file mode 100644 index 0000000000000000000000000000000000000000..be45b9f4e4f32f3c74a8756190cd9cb22249ccd4 --- /dev/null +++ b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.h @@ -0,0 +1,172 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef otbSharkRandomForestsMachineLearningModel_h +#define otbSharkRandomForestsMachineLearningModel_h + +#include "otbRequiresSharkCheck.h" + +#include "itkLightObject.h" +#include "otbMachineLearningModel.h" + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Woverloaded-virtual" +#pragma GCC diagnostic ignored "-Wignored-qualifiers" +#endif +#include "shark/Algorithms/Trainers/RFTrainer.h" +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + + +/** \class SharkRandomForestsMachineLearningModel + * \brief Shark version of Random Forests algorithm + * + * This is a specialization of MachineLearningModel class allowing to + * use Shark implementation of the Random Forests algorithm. + * + * It is noteworthy that training step is parallel. + * + * For more information, see + * http://image.diku.dk/shark/doxygen_pages/html/classshark_1_1_r_f_trainer.html + * + * \ingroup OTBSupervised + */ + +namespace otb +{ +template <class TInputValue, class TTargetValue> +class ITK_EXPORT SharkRandomForestsMachineLearningModel + : public MachineLearningModel <TInputValue, TTargetValue> +{ +public: + /** Standard class typedefs. */ + typedef SharkRandomForestsMachineLearningModel Self; + typedef MachineLearningModel<TInputValue, TTargetValue> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + typedef typename Superclass::InputValueType InputValueType; + typedef typename Superclass::InputSampleType InputSampleType; + typedef typename Superclass::InputListSampleType InputListSampleType; + typedef typename Superclass::TargetValueType TargetValueType; + typedef typename Superclass::TargetSampleType TargetSampleType; + typedef typename Superclass::TargetListSampleType TargetListSampleType; + typedef typename Superclass::ConfidenceValueType ConfidenceValueType; + typedef typename Superclass::ConfidenceSampleType ConfidenceSampleType; + typedef typename Superclass::ConfidenceListSampleType ConfidenceListSampleType; + + /** Run-time type information (and related methods). */ + itkNewMacro(Self); + itkTypeMacro(SharkRandomForestsMachineLearningModel, MachineLearningModel); + + /** Train the machine learning model */ + virtual void Train() ITK_OVERRIDE; + + /** Save the model to file */ + virtual void Save(const std::string & filename, const std::string & name="") ITK_OVERRIDE; + + /** Load the model from file */ + virtual void Load(const std::string & filename, const std::string & name="") ITK_OVERRIDE; + + /**\name Classification model file compatibility tests */ + //@{ + /** Is the input model file readable and compatible with the corresponding classifier ? */ + virtual bool CanReadFile(const std::string &) ITK_OVERRIDE; + + /** Is the input model file writable and compatible with the corresponding classifier ? */ + virtual bool CanWriteFile(const std::string &) ITK_OVERRIDE; + //@} + + /** From Shark doc: Get the number of trees to grow.*/ + itkGetMacro(NumberOfTrees,unsigned int); + /** From Shark doc: Set the number of trees to grow.*/ + itkSetMacro(NumberOfTrees,unsigned int); + + /** From Shark doc: Get the number of random attributes to investigate at each node.*/ + itkGetMacro(MTry, unsigned int); + /** From Shark doc: Set the number of random attributes to investigate at each node.*/ + itkSetMacro(MTry, unsigned int); + + /** From Shark doc: Controls when a node is considered pure. If set +* to 1, a node is pure when it only consists of a single node. +*/ + itkGetMacro(NodeSize, unsigned int); + /** From Shark doc: Controls when a node is considered pure. If +* set to 1, a node is pure when it only consists of a single node. + */ + itkSetMacro(NodeSize, unsigned int); + + /** From Shark doc: Get the fraction of the original training +* dataset to use as the out of bag sample. The default value is +* 0.66.*/ + itkGetMacro(OobRatio, float); + + /** From Shark doc: Set the fraction of the original training +* dataset to use as the out of bag sample. The default value is 0.66. +*/ + itkSetMacro(OobRatio, float); + + /** If true, margin confidence value will be computed */ + itkGetMacro(ComputeMargin, bool); + /** If true, margin confidence value will be computed */ + itkSetMacro(ComputeMargin, bool); + +protected: + /** Constructor */ + SharkRandomForestsMachineLearningModel(); + + /** Destructor */ + virtual ~SharkRandomForestsMachineLearningModel(); + + /** Predict values using the model */ + virtual TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE; + + + virtual void DoPredictBatch(const InputListSampleType *, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType *, ConfidenceListSampleType * = ITK_NULLPTR) const ITK_OVERRIDE; + + /** PrintSelf method */ + void PrintSelf(std::ostream& os, itk::Indent indent) const; + +private: + SharkRandomForestsMachineLearningModel(const Self &); //purposely not implemented + void operator =(const Self&); //purposely not implemented + + shark::RFClassifier m_RFModel; + shark::RFTrainer m_RFTrainer; + + unsigned int m_NumberOfTrees; + unsigned int m_MTry; + unsigned int m_NodeSize; + float m_OobRatio; + bool m_ComputeMargin; + + /** Confidence list sample */ + ConfidenceValueType ComputeConfidence(shark::RealVector & probas, + bool computeMargin) const; + +}; +} // end namespace otb + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbSharkRandomForestsMachineLearningModel.txx" +#endif + +#endif diff --git a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.txx new file mode 100644 index 0000000000000000000000000000000000000000..833ab6b457e0e78a4cd073f694022d0a035331cb --- /dev/null +++ b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.txx @@ -0,0 +1,249 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef otbSharkRandomForestsMachineLearningModel_txx +#define otbSharkRandomForestsMachineLearningModel_txx + +#include <fstream> +#include "itkMacro.h" +#include "otbSharkRandomForestsMachineLearningModel.h" + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Woverloaded-virtual" +#pragma GCC diagnostic ignored "-Wignored-qualifiers" +#endif +#include <shark/Models/Converter.h> +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + + + +#include "otbSharkUtils.h" +#include <algorithm> + +namespace otb +{ + +template <class TInputValue, class TOutputValue> +SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> +::SharkRandomForestsMachineLearningModel() +{ + this->m_ConfidenceIndex = true; + this->m_IsRegressionSupported = false; + this->m_IsDoPredictBatchMultiThreaded = true; +} + + +template <class TInputValue, class TOutputValue> +SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> +::~SharkRandomForestsMachineLearningModel() +{ +} + +/** Train the machine learning model */ +template <class TInputValue, class TOutputValue> +void +SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> +::Train() +{ +#ifdef _OPENMP + omp_set_num_threads(itk::MultiThreader::GetGlobalDefaultNumberOfThreads()); +#endif + + std::vector<shark::RealVector> features; + std::vector<unsigned int> class_labels; + + Shark::ListSampleToSharkVector(this->GetInputListSample(), features); + Shark::ListSampleToSharkVector(this->GetTargetListSample(), class_labels); + shark::ClassificationDataset TrainSamples = shark::createLabeledDataFromRange(features,class_labels); + + //Set parameters + m_RFTrainer.setMTry(m_MTry); + m_RFTrainer.setNTrees(m_NumberOfTrees); + m_RFTrainer.setNodeSize(m_NodeSize); + m_RFTrainer.setOOBratio(m_OobRatio); + m_RFTrainer.train(m_RFModel, TrainSamples); + +} + +template <class TInputValue, class TOutputValue> +typename SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> +::ConfidenceValueType +SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> +::ComputeConfidence(shark::RealVector & probas, bool computeMargin) const +{ + assert(!probas.empty()&&"probas vector is empty"); + assert((!computeMargin||probas.size()>1)&&"probas size should be at least 2 if computeMargin is true"); + + ConfidenceValueType conf{0}; + if(computeMargin) + { + std::nth_element(probas.begin(), probas.begin()+1, + probas.end(), std::greater<double>()); + conf = static_cast<ConfidenceValueType>(probas[0]-probas[1]); + } + else + { + auto max_proba = *(std::max_element(probas.begin(), + probas.end())); + conf = static_cast<ConfidenceValueType>(max_proba); + } + return conf; +} + +template <class TInputValue, class TOutputValue> +typename SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> +::TargetSampleType +SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> +::DoPredict(const InputSampleType & value, ConfidenceValueType *quality) const +{ + shark::RealVector samples(value.Size()); + for(size_t i = 0; i < value.Size();i++) + { + samples.push_back(value[i]); + } + if (quality != ITK_NULLPTR) + { + shark::RealVector probas = m_RFModel(samples); + (*quality) = ComputeConfidence(probas, m_ComputeMargin); + } + shark::ArgMaxConverter<shark::RFClassifier> amc; + amc.decisionFunction() = m_RFModel; + unsigned int res; + amc.eval(samples, res); + TargetSampleType target; + target[0] = static_cast<TOutputValue>(res); + return target; +} + +template <class TInputValue, class TOutputValue> +void +SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> +::DoPredictBatch(const InputListSampleType *input, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * targets, ConfidenceListSampleType * quality) const +{ + assert(input != ITK_NULLPTR); + assert(targets != ITK_NULLPTR); + + assert(input->Size()==targets->Size()&&"Input sample list and target label list do not have the same size."); + assert(((quality==ITK_NULLPTR)||(quality->Size()==input->Size()))&&"Quality samples list is not null and does not have the same size as input samples list"); + + if(startIndex+size>input->Size()) + { + itkExceptionMacro(<<"requested range ["<<startIndex<<", "<<startIndex+size<<"[ partially outside input sample list range.[0,"<<input->Size()<<"["); + } + + std::vector<shark::RealVector> features; + Shark::ListSampleRangeToSharkVector(input, features,startIndex,size); + shark::Data<shark::RealVector> inputSamples = shark::createDataFromRange(features); + + #ifdef _OPENMP + omp_set_num_threads(itk::MultiThreader::GetGlobalDefaultNumberOfThreads()); + #endif + + shark::Data<shark::RealVector> probas = m_RFModel(inputSamples); + + if(quality != ITK_NULLPTR) + { + unsigned int id = startIndex; + for(shark::RealVector && p : probas.elements()) + { + ConfidenceSampleType confidence; + auto conf = ComputeConfidence(p, m_ComputeMargin); + confidence[0] = static_cast<ConfidenceValueType>(conf); + quality->SetMeasurementVector(id,confidence); + ++id; + } + } + + shark::ArgMaxConverter<shark::RFClassifier> amc; + amc.decisionFunction() = m_RFModel; + auto prediction = amc(inputSamples); + unsigned int id = startIndex; + for(const auto& p : prediction.elements()) + { + TargetSampleType target; + target[0] = static_cast<TOutputValue>(p); + targets->SetMeasurementVector(id,target); + ++id; + } +} + +template <class TInputValue, class TOutputValue> +void +SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> +::Save(const std::string & filename, const std::string & itkNotUsed(name)) +{ + std::ofstream ofs(filename.c_str()); + if(!ofs) + { + itkExceptionMacro(<< "Error opening " << filename.c_str() ); + } + shark::TextOutArchive oa(ofs); + m_RFModel.save(oa,0); +} + +template <class TInputValue, class TOutputValue> +void +SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> +::Load(const std::string & filename, const std::string & itkNotUsed(name)) +{ + std::ifstream ifs(filename.c_str()); + shark::TextInArchive ia(ifs); + m_RFModel.load(ia,0); +} + +template <class TInputValue, class TOutputValue> +bool +SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> +::CanReadFile(const std::string & file) +{ + try + { + this->Load(file); + m_RFModel.name(); + } + catch(...) + { + return false; + } + return true; +} + +template <class TInputValue, class TOutputValue> +bool +SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> +::CanWriteFile(const std::string & itkNotUsed(file)) +{ + return true; +} + +template <class TInputValue, class TOutputValue> +void +SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> +::PrintSelf(std::ostream& os, itk::Indent indent) const +{ + // Call superclass implementation + Superclass::PrintSelf(os,indent); +} + +} //end namespace otb + +#endif diff --git a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModelFactory.h b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModelFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..242eeb7aa7494cc6a1c705d03c76fa365db8412f --- /dev/null +++ b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModelFactory.h @@ -0,0 +1,74 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef otbSharkRandomForestsMachineLearningModelFactory_h +#define otbSharkRandomForestsMachineLearningModelFactory_h + +#include "itkObjectFactoryBase.h" +#include "itkImageIOBase.h" + +namespace otb +{ +/** \class SharkRandomForestsMachineLearningModelFactory + * \brief Creation of an instance of a SharkRandomForestsMachineLearningModel object using the object factory + * + * \ingroup OTBSupervised + */ +template <class TInputValue, class TTargetValue> +class ITK_EXPORT SharkRandomForestsMachineLearningModelFactory : public itk::ObjectFactoryBase +{ +public: + /** Standard class typedefs. */ + typedef SharkRandomForestsMachineLearningModelFactory Self; + typedef itk::ObjectFactoryBase Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** Class methods used to interface with the registered factories. */ + virtual const char* GetITKSourceVersion(void) const; + virtual const char* GetDescription(void) const; + + /** Method for class instantiation. */ + itkFactorylessNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(SharkRandomForestsMachineLearningModelFactory, itk::ObjectFactoryBase); + + /** Register one factory of this type */ + static void RegisterOneFactory(void) + { + Pointer RFFactory = SharkRandomForestsMachineLearningModelFactory::New(); + itk::ObjectFactoryBase::RegisterFactory(RFFactory); + } + +protected: + SharkRandomForestsMachineLearningModelFactory(); + virtual ~SharkRandomForestsMachineLearningModelFactory(); + +private: + SharkRandomForestsMachineLearningModelFactory(const Self &); //purposely not implemented + void operator =(const Self&); //purposely not implemented + +}; + +} // end namespace otb + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbSharkRandomForestsMachineLearningModelFactory.txx" +#endif + +#endif diff --git a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModelFactory.txx b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModelFactory.txx new file mode 100644 index 0000000000000000000000000000000000000000..9bd3c5217e79ede101a72ecca0d2b65b879afb01 --- /dev/null +++ b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModelFactory.txx @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef otbSharkRandomForestsMachineLearningModelFactory_txx +#define otbSharkRandomForestsMachineLearningModelFactory_txx + + +#include "otbSharkRandomForestsMachineLearningModelFactory.h" + +#include "itkCreateObjectFunction.h" +#include "otbSharkRandomForestsMachineLearningModel.h" +#include "itkVersion.h" + +namespace otb +{ + +template <class TInputValue, class TOutputValue> +SharkRandomForestsMachineLearningModelFactory<TInputValue,TOutputValue> +::SharkRandomForestsMachineLearningModelFactory() +{ + + std::string classOverride = std::string("otbMachineLearningModel"); + std::string subclass = std::string("otbSharkRandomForestsMachineLearningModel"); + + this->RegisterOverride(classOverride.c_str(), + subclass.c_str(), + "Shark RF ML Model", + 1, + itk::CreateObjectFunction<SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> >::New()); +} + +template <class TInputValue, class TOutputValue> +SharkRandomForestsMachineLearningModelFactory<TInputValue,TOutputValue> +::~SharkRandomForestsMachineLearningModelFactory() +{ +} + +template <class TInputValue, class TOutputValue> +const char* +SharkRandomForestsMachineLearningModelFactory<TInputValue,TOutputValue> +::GetITKSourceVersion(void) const +{ + return ITK_SOURCE_VERSION; +} + +template <class TInputValue, class TOutputValue> +const char* +SharkRandomForestsMachineLearningModelFactory<TInputValue,TOutputValue> +::GetDescription() const +{ + return "Shark Random Forest machine learning model factory"; +} + +} // end namespace otb + +#endif diff --git a/Modules/Learning/Supervised/include/otbSharkUtils.h b/Modules/Learning/Supervised/include/otbSharkUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..ed70f03fca36f5a0498512012eba3315ea5c76bd --- /dev/null +++ b/Modules/Learning/Supervised/include/otbSharkUtils.h @@ -0,0 +1,124 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + + =========================================================================*/ +#ifndef otbSharkUtils_h +#define otbSharkUtils_h + +#include "otbRequiresSharkCheck.h" + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#endif +#include <shark/Data/Dataset.h> +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + +namespace otb +{ +namespace Shark +{ +template <class T> void ListSampleRangeToSharkVector(const T * listSample, std::vector<shark::RealVector> & output, unsigned int start, unsigned int size) +{ + assert(listSample != ITK_NULLPTR); + + if(start+size>listSample->Size()) + { + itkGenericExceptionMacro(<<"Requested range ["<<start<<", "<<start+size<<"[ is out of bound for input list sample (range [0, "<<listSample->Size()<<"["); + } + + output.clear(); + + // Sample index + unsigned int sampleIdx = start; + + //Check for valid listSample + if(listSample->Size()>0) + { + // Retrieve samples size alike + const unsigned int sampleSize = listSample->GetMeasurementVectorSize(); + + // Fill the output vector + + for (auto const endOfRange = start+size ; sampleIdx < endOfRange ; ++sampleIdx) + { + // Retrieve sample + typename T::MeasurementVectorType const & sample = listSample->GetMeasurementVector(sampleIdx); + + // // Define a shark::RealVector + // shark::RealVector rv(sampleSize); + // // Loop on sample size + // for(unsigned int i = 0; i < sampleSize; ++i) + // { + // rv[i] = sample[i]; + // } + // using std::move; + // output.emplace_back(move(rv)); + + output.emplace_back(&sample[0], &sample[0]+sampleSize); + } + } +} + +template <class T> void ListSampleRangeToSharkVector(const T * listSample, std::vector<unsigned int> & output, unsigned int start, unsigned int size) +{ + assert(listSample != ITK_NULLPTR); + + if(start+size>listSample->Size()) + { + itkGenericExceptionMacro(<<"Requested range ["<<start<<", "<<start+size<<"[ is out of bound for input list sample (range [0, "<<listSample->Size()<<"["); + } + + output.clear(); + + // Sample index + unsigned int sampleIdx = start; + + //Check for valid listSample + if(listSample->Size()>0) + { + // Fill the output vector + while(sampleIdx<start+size) + { + // Retrieve sample + typename T::MeasurementVectorType const & sample = listSample->GetMeasurementVector(sampleIdx); + + // Define a shark::RealVector + output.push_back(sample[0]); + ++sampleIdx; + } + } +} + +template <class T> void ListSampleToSharkVector(const T * listSample, std::vector<shark::RealVector> & output) +{ + assert(listSample != ITK_NULLPTR); + ListSampleRangeToSharkVector(listSample,output,0U,static_cast<unsigned int>(listSample->Size())); +} + +template <class T> void ListSampleToSharkVector(const T * listSample, std::vector<unsigned int> & output) +{ + assert(listSample != ITK_NULLPTR); + ListSampleRangeToSharkVector(listSample,output,0, static_cast<unsigned int>(listSample->Size())); +} + +} +} + +#endif + diff --git a/Modules/Learning/Supervised/otb-module.cmake b/Modules/Learning/Supervised/otb-module.cmake index cce5b946c6e6e0d7aed1919ce8049b107a7fe01c..ebce0f334e6156c859dbb8d715c6287896e3b7ca 100644 --- a/Modules/Learning/Supervised/otb-module.cmake +++ b/Modules/Learning/Supervised/otb-module.cmake @@ -13,7 +13,8 @@ ENABLE_SHARED OPTIONAL_DEPENDS OTBOpenCV OTBSVMLearning - + OTBShark + TEST_DEPENDS OTBTestKernel OTBImageIO diff --git a/Modules/Learning/Supervised/src/CMakeLists.txt b/Modules/Learning/Supervised/src/CMakeLists.txt index b99187d2eab62b67dbe59892d38baddca4663016..015e24e74c3ec0e450cb01d267ab46c3935576fb 100644 --- a/Modules/Learning/Supervised/src/CMakeLists.txt +++ b/Modules/Learning/Supervised/src/CMakeLists.txt @@ -11,6 +11,7 @@ target_link_libraries(OTBSupervised ${OTBCommon_LIBRARIES} ${OTBSVMLearning_LIBRARIES} ${OTBOpenCV_LIBRARIES} + ${SHARK_LIBRARIES} ) otb_module_target(OTBSupervised) diff --git a/Modules/Learning/Supervised/test/CMakeLists.txt b/Modules/Learning/Supervised/test/CMakeLists.txt index abca168f4f7794ea1a9133370c65555593b9bf19..d6824242efe74f33d16fc55d2ae906d1dacd3546 100644 --- a/Modules/Learning/Supervised/test/CMakeLists.txt +++ b/Modules/Learning/Supervised/test/CMakeLists.txt @@ -1,5 +1,4 @@ otb_module_test() - set(OTBSupervisedTests otbSupervisedTestDriver.cxx otbConfusionMatrixCalculatorTest.cxx @@ -10,6 +9,10 @@ otbImageClassificationFilter.cxx otbMachineLearningRegressionTests.cxx ) +if(OTB_USE_SHARK) +set(OTBSupervisedTests ${OTBSupervisedTests} otbSharkImageClassificationFilter.cxx) +endif() + add_executable(otbSupervisedTestDriver ${OTBSupervisedTests}) target_link_libraries(otbSupervisedTestDriver ${OTBSupervised-Test_LIBRARIES}) otb_module_target_label(otbSupervisedTestDriver) @@ -54,3 +57,7 @@ endif() if(OTB_USE_OPENCV) include(tests-opencv.cmake) endif() + +if(OTB_USE_SHARK) + include(tests-shark.cmake) +endif() diff --git a/Modules/Learning/Supervised/test/otbImageClassificationFilter.cxx b/Modules/Learning/Supervised/test/otbImageClassificationFilter.cxx index 760a4fdb870f0e53d6783ae2a6385bc2a8dca40d..c2337665d60aa67093e6beea33e2396e8f89b365 100644 --- a/Modules/Learning/Supervised/test/otbImageClassificationFilter.cxx +++ b/Modules/Learning/Supervised/test/otbImageClassificationFilter.cxx @@ -42,6 +42,32 @@ int otbImageClassificationFilterNew(int itkNotUsed(argc), char * itkNotUsed(argv return EXIT_SUCCESS; } +int otbImageClassificationFilterLoadModel(int itkNotUsed(argc), char * argv[]) +{ + const char * infname = argv[1]; + const char * modelfname = argv[2]; + + // Instantiating object + ClassificationFilterType::Pointer filter = ClassificationFilterType::New(); + + ReaderType::Pointer reader = ReaderType::New(); + reader->SetFileName(infname); + + ModelType::Pointer model; + + model = MachineLearningModelFactoryType::CreateMachineLearningModel(modelfname, + MachineLearningModelFactoryType::ReadMode); + + if (model.IsNull()) + { + std::cerr << "Unable to create a model from " << modelfname << std::endl; + return EXIT_FAILURE; + } + + model->Load(modelfname); + return EXIT_SUCCESS; +} + int otbImageClassificationFilter(int itkNotUsed(argc), char * argv[]) { const char * infname = argv[1]; diff --git a/Modules/Learning/Supervised/test/otbMachineLearningModelCanRead.cxx b/Modules/Learning/Supervised/test/otbMachineLearningModelCanRead.cxx index 4749acfa32f5265d2112f116317abe194c40c4ae..b302542e812e50a90aa2359db5eca5068ff06c9e 100644 --- a/Modules/Learning/Supervised/test/otbMachineLearningModelCanRead.cxx +++ b/Modules/Learning/Supervised/test/otbMachineLearningModelCanRead.cxx @@ -18,22 +18,9 @@ #include <iostream> +#include <otbConfigure.h> #include <otbMachineLearningModel.h> -#ifdef OTB_USE_LIBSVM -#include "otbLibSVMMachineLearningModel.h" -#endif -#ifdef OTB_USE_OPENCV -#include "otbSVMMachineLearningModel.h" -#include "otbRandomForestsMachineLearningModel.h" -#include "otbBoostMachineLearningModel.h" -#include "otbNeuralNetworkMachineLearningModel.h" -#include "otbNormalBayesMachineLearningModel.h" -#include "otbDecisionTreeMachineLearningModel.h" -#include "otbGradientBoostedTreeMachineLearningModel.h" -#include "otbKNearestNeighborsMachineLearningModel.h" -#endif - typedef otb::MachineLearningModel<float,short> MachineLearningModelType; typedef MachineLearningModelType::InputValueType InputValueType; typedef MachineLearningModelType::InputSampleType InputSampleType; @@ -42,6 +29,10 @@ typedef MachineLearningModelType::TargetValueType TargetValueType; typedef MachineLearningModelType::TargetSampleType TargetSampleType; typedef MachineLearningModelType::TargetListSampleType TargetListSampleType; + +#ifdef OTB_USE_LIBSVM +#include "otbLibSVMMachineLearningModel.h" + int otbLibSVMMachineLearningModelCanRead(int argc, char* argv[]) { if (argc != 2) @@ -57,7 +48,6 @@ int otbLibSVMMachineLearningModelCanRead(int argc, char* argv[]) } std::string filename(argv[1]); - #ifdef OTB_USE_LIBSVM typedef otb::LibSVMMachineLearningModel<InputValueType, TargetValueType> SVMType; SVMType::Pointer classifier = SVMType::New(); bool lCanRead = classifier->CanReadFile(filename); @@ -66,10 +56,21 @@ int otbLibSVMMachineLearningModelCanRead(int argc, char* argv[]) std::cerr << "Erreur otb::LibSVMMachineLearningModel : impossible to open the file " << filename << "." << std::endl; return EXIT_FAILURE; } - #endif - + return EXIT_SUCCESS; } +#endif + + +#ifdef OTB_USE_OPENCV +#include "otbSVMMachineLearningModel.h" +#include "otbRandomForestsMachineLearningModel.h" +#include "otbBoostMachineLearningModel.h" +#include "otbNeuralNetworkMachineLearningModel.h" +#include "otbNormalBayesMachineLearningModel.h" +#include "otbDecisionTreeMachineLearningModel.h" +#include "otbGradientBoostedTreeMachineLearningModel.h" +#include "otbKNearestNeighborsMachineLearningModel.h" int otbSVMMachineLearningModelCanRead(int argc, char* argv[]) { @@ -86,7 +87,6 @@ int otbSVMMachineLearningModelCanRead(int argc, char* argv[]) } std::string filename(argv[1]); - #ifdef OTB_USE_OPENCV typedef otb::SVMMachineLearningModel<InputValueType, TargetValueType> SVMType; SVMType::Pointer classifier = SVMType::New(); bool lCanRead = classifier->CanReadFile(filename); @@ -95,7 +95,6 @@ int otbSVMMachineLearningModelCanRead(int argc, char* argv[]) std::cerr << "Erreur otb::SVMMachineLearningModel : impossible to open the file " << filename << "." << std::endl; return EXIT_FAILURE; } - #endif return EXIT_SUCCESS; } @@ -115,7 +114,6 @@ int otbRandomForestsMachineLearningModelCanRead(int argc, char* argv[]) } std::string filename(argv[1]); - #ifdef OTB_USE_OPENCV typedef otb::RandomForestsMachineLearningModel<InputValueType, TargetValueType> RFType; RFType::Pointer classifier = RFType::New(); bool lCanRead = classifier->CanReadFile(filename); @@ -124,7 +122,6 @@ int otbRandomForestsMachineLearningModelCanRead(int argc, char* argv[]) std::cerr << "Erreur otb::RandomForestsMachineLearningModel : impossible to open the file " << filename << "." << std::endl; return EXIT_FAILURE; } - #endif return EXIT_SUCCESS; } @@ -144,7 +141,6 @@ int otbBoostMachineLearningModelCanRead(int argc, char* argv[]) } std::string filename(argv[1]); - #ifdef OTB_USE_OPENCV typedef otb::BoostMachineLearningModel<InputValueType, TargetValueType> BoostType; BoostType::Pointer classifier = BoostType::New(); bool lCanRead = classifier->CanReadFile(filename); @@ -153,7 +149,6 @@ int otbBoostMachineLearningModelCanRead(int argc, char* argv[]) std::cerr << "Erreur otb::BoostMachineLearningModel : impossible to open the file " << filename << "." << std::endl; return EXIT_FAILURE; } - #endif return EXIT_SUCCESS; } @@ -173,7 +168,6 @@ int otbNeuralNetworkMachineLearningModelCanRead(int argc, char* argv[]) } std::string filename(argv[1]); - #ifdef OTB_USE_OPENCV typedef otb::NeuralNetworkMachineLearningModel<InputValueType, TargetValueType> ANNType; ANNType::Pointer classifier = ANNType::New(); bool lCanRead = classifier->CanReadFile(filename); @@ -182,7 +176,6 @@ int otbNeuralNetworkMachineLearningModelCanRead(int argc, char* argv[]) std::cerr << "Erreur otb::NeuralNetworkMachineLearningModel : impossible to open the file " << filename << "." << std::endl; return EXIT_FAILURE; } - #endif return EXIT_SUCCESS; } @@ -202,7 +195,6 @@ int otbNormalBayesMachineLearningModelCanRead(int argc, char* argv[]) } std::string filename(argv[1]); - #ifdef OTB_USE_OPENCV typedef otb::NormalBayesMachineLearningModel<InputValueType, TargetValueType> NormalBayesType; NormalBayesType::Pointer classifier = NormalBayesType::New(); bool lCanRead = classifier->CanReadFile(filename); @@ -211,7 +203,6 @@ int otbNormalBayesMachineLearningModelCanRead(int argc, char* argv[]) std::cerr << "Erreur otb::NormalBayesMachineLearningModel : impossible to open the file " << filename << "." << std::endl; return EXIT_FAILURE; } - #endif return EXIT_SUCCESS; } @@ -231,7 +222,6 @@ int otbDecisionTreeMachineLearningModelCanRead(int argc, char* argv[]) } std::string filename(argv[1]); - #ifdef OTB_USE_OPENCV typedef otb::DecisionTreeMachineLearningModel<InputValueType, TargetValueType> DecisionTreeType; DecisionTreeType::Pointer classifier = DecisionTreeType::New(); bool lCanRead = classifier->CanReadFile(filename); @@ -240,7 +230,6 @@ int otbDecisionTreeMachineLearningModelCanRead(int argc, char* argv[]) std::cerr << "Erreur otb::DecisionTreeMachineLearningModel : impossible to open the file " << filename << "." << std::endl; return EXIT_FAILURE; } - #endif return EXIT_SUCCESS; } @@ -260,7 +249,6 @@ int otbGradientBoostedTreeMachineLearningModelCanRead(int argc, char* argv[]) } std::string filename(argv[1]); - #ifdef OTB_USE_OPENCV typedef otb::GradientBoostedTreeMachineLearningModel<InputValueType, TargetValueType> GBTreeType; GBTreeType::Pointer classifier = GBTreeType::New(); bool lCanRead = classifier->CanReadFile(filename); @@ -269,7 +257,6 @@ int otbGradientBoostedTreeMachineLearningModelCanRead(int argc, char* argv[]) std::cerr << "Erreur otb::GradientBoostedTreeMachineLearningModel : impossible to open the file " << filename << "." << std::endl; return EXIT_FAILURE; } - #endif return EXIT_SUCCESS; } @@ -289,7 +276,6 @@ int otbKNNMachineLearningModelCanRead(int argc, char* argv[]) } std::string filename(argv[1]); - #ifdef OTB_USE_OPENCV typedef otb::KNearestNeighborsMachineLearningModel<InputValueType, TargetValueType> KNNType; KNNType::Pointer classifier = KNNType::New(); bool lCanRead = classifier->CanReadFile(filename); @@ -298,8 +284,39 @@ int otbKNNMachineLearningModelCanRead(int argc, char* argv[]) std::cerr << "Erreur otb::KNearestNeighborsMachineLearningModel : impossible to open the file " << filename << "." << std::endl; return EXIT_FAILURE; } - #endif return EXIT_SUCCESS; } +#endif + +#ifdef OTB_USE_SHARK +#include "otbSharkRandomForestsMachineLearningModel.h" + +int otbSharkRFMachineLearningModelCanRead(int argc, char* argv[]) +{ + if (argc != 2) + { + std::cerr << "Usage: " << argv[0] + << "<model>" << std::endl; + std::cerr << "Called here with " << argc << " arguments\n"; + for (int i = 1; i < argc; ++i) + { + std::cerr << " - " << argv[i] << "\n"; + } + return EXIT_FAILURE; + } + std::string filename(argv[1]); + typedef otb::SharkRandomForestsMachineLearningModel<InputValueType, TargetValueType> RFType; + RFType::Pointer classifier = RFType::New(); + bool lCanRead = classifier->CanReadFile(filename); + if (lCanRead == false) + { + std::cerr << "Error otb::SharkRandomForestsMachineLearningModel : impossible to open the file " << filename << "." << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +#endif diff --git a/Modules/Learning/Supervised/test/otbMachineLearningRegressionTests.cxx b/Modules/Learning/Supervised/test/otbMachineLearningRegressionTests.cxx index 2b0554d4372acc37f6754f394d2775498168ef53..efb46f39a76d06c50dd79d9c5f37e8bfc159d9e7 100644 --- a/Modules/Learning/Supervised/test/otbMachineLearningRegressionTests.cxx +++ b/Modules/Learning/Supervised/test/otbMachineLearningRegressionTests.cxx @@ -24,6 +24,8 @@ const double otb_epsilon_01 = 0.1; #endif +#include "otbMachineLearningModel.h" + #ifdef OTB_USE_OPENCV #include "otbNeuralNetworkMachineLearningModel.h" #include "otbSVMMachineLearningModel.h" diff --git a/Modules/Learning/Supervised/test/otbSharkImageClassificationFilter.cxx b/Modules/Learning/Supervised/test/otbSharkImageClassificationFilter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..6553f2970fa32650d5579743b10ebcd3730a84cd --- /dev/null +++ b/Modules/Learning/Supervised/test/otbSharkImageClassificationFilter.cxx @@ -0,0 +1,162 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + + =========================================================================*/ +#include "otbImageClassificationFilter.h" +#include "otbVectorImage.h" +#include "otbImage.h" +#include "otbImageFileReader.h" +#include "otbImageFileWriter.h" +#include "otbSharkRandomForestsMachineLearningModelFactory.h" +#include <random> +#include <chrono> + +const unsigned int Dimension = 2; +typedef float PixelType; +typedef unsigned short LabeledPixelType; + +typedef otb::VectorImage<PixelType, Dimension> ImageType; +typedef otb::Image<LabeledPixelType, Dimension> LabeledImageType; +typedef otb::ImageClassificationFilter<ImageType, LabeledImageType> ClassificationFilterType; +typedef ClassificationFilterType::ModelType ModelType; +typedef ClassificationFilterType::ValueType ValueType; +typedef ClassificationFilterType::LabelType LabelType; +typedef otb::SharkRandomForestsMachineLearningModelFactory<ValueType, LabelType> MachineLearningModelFactoryType; +typedef otb::ImageFileReader<ImageType> ReaderType; +typedef otb::ImageFileReader<LabeledImageType> MaskReaderType; +typedef otb::ImageFileWriter<LabeledImageType> WriterType; + +typedef otb::SharkRandomForestsMachineLearningModel<PixelType,short unsigned int> MachineLearningModelType; +typedef MachineLearningModelType::InputValueType LocalInputValueType; +typedef MachineLearningModelType::InputSampleType LocalInputSampleType; +typedef MachineLearningModelType::InputListSampleType LocalInputListSampleType; +typedef MachineLearningModelType::TargetValueType LocalTargetValueType; +typedef MachineLearningModelType::TargetSampleType LocalTargetSampleType; +typedef MachineLearningModelType::TargetListSampleType LocalTargetListSampleType; + +void generateSamples(unsigned int num_classes, unsigned int num_samples, + unsigned int num_features, + LocalInputListSampleType * samples, + LocalTargetListSampleType * labels) +{ + std::default_random_engine generator; + std::uniform_int_distribution<int> label_distribution(1,num_classes); + std::uniform_int_distribution<int> feat_distribution(0,256); + for(size_t scount=0; scount<num_samples; ++scount) + { + LabeledPixelType label = label_distribution(generator); + LocalInputSampleType sample(num_features); + for(unsigned int i=0; i<num_features; ++i) + sample[i]= feat_distribution(generator); + samples->SetMeasurementVectorSize(num_features); + samples->PushBack(sample); + labels->PushBack(label); + } +} + +void buildModel(unsigned int num_classes, unsigned int num_samples, + unsigned int num_features, std::string modelfname) +{ + LocalInputListSampleType::Pointer samples = LocalInputListSampleType::New(); + LocalTargetListSampleType::Pointer labels = LocalTargetListSampleType::New(); + + std::cout << "Sample generation\n"; + generateSamples(num_classes, num_samples, num_features, samples, labels); + + MachineLearningModelType::Pointer classifier = MachineLearningModelType::New(); + classifier->SetInputListSample(samples); + classifier->SetTargetListSample(labels); + classifier->SetRegressionMode(false); + classifier->SetNumberOfTrees(100); + classifier->SetMTry(0); + classifier->SetNodeSize(25); + classifier->SetOobRatio(0.3); + std::cout << "Training\n"; + using TimeT = std::chrono::milliseconds; + auto start = std::chrono::system_clock::now(); + classifier->Train(); + auto duration = std::chrono::duration_cast< TimeT> + (std::chrono::system_clock::now() - start); + auto elapsed = duration.count(); + std::cout << "Training took " << elapsed << " ms\n"; + classifier->Save(modelfname); +} + +int otbSharkImageClassificationFilter(int argc, char * argv[]) +{ + if(argc<5 || argc>7) + { + std::cout << "Usage: input_image output_image output_confidence batchmode [in_model_name] [mask_name]\n"; + } + std::string imfname = argv[1]; + std::string outfname = argv[2]; + std::string conffname = argv[3]; + bool batch = (std::string(argv[4])=="1"); + std::string modelfname = "/tmp/rf_model.txt"; + std::string maskfname{}; + + MaskReaderType::Pointer mask_reader = MaskReaderType::New(); + ReaderType::Pointer reader = ReaderType::New(); + reader->SetFileName(imfname); + reader->UpdateOutputInformation(); + + auto num_features = reader->GetOutput()->GetNumberOfComponentsPerPixel(); + + std::cout << "Image has " << num_features << " bands\n"; + + if(argc>5) + { + modelfname = argv[5]; + } + else + { + buildModel(3, 1000, num_features, modelfname); + } + + ClassificationFilterType::Pointer filter = ClassificationFilterType::New(); + + MachineLearningModelType::Pointer model = MachineLearningModelType::New(); + model->Load(modelfname); + filter->SetModel(model); + filter->SetInput(reader->GetOutput()); + if(argc==7) + { + maskfname = argv[6]; + mask_reader->SetFileName(maskfname); + filter->SetInputMask(mask_reader->GetOutput()); + } + + WriterType::Pointer writer = WriterType::New(); + writer->SetInput(filter->GetOutput()); + writer->SetFileName(outfname); + std::cout << "Classification\n"; + filter->SetBatchMode(batch); + filter->SetUseConfidenceMap(true); + using TimeT = std::chrono::milliseconds; + auto start = std::chrono::system_clock::now(); + writer->Update(); + auto duration = std::chrono::duration_cast< TimeT> + (std::chrono::system_clock::now() - start); + auto elapsed = duration.count(); + std::cout << "Classification took " << elapsed << " ms\n"; + + auto confWriter = otb::ImageFileWriter<ClassificationFilterType::ConfidenceImageType>::New(); + confWriter->SetInput(filter->GetOutputConfidence()); + confWriter->SetFileName(conffname); + confWriter->Update(); + + return EXIT_SUCCESS; +} diff --git a/Modules/Learning/Supervised/test/otbSupervisedTestDriver.cxx b/Modules/Learning/Supervised/test/otbSupervisedTestDriver.cxx index 2bf373c87f9f0579df333951b83ae818739d25c2..9bc337bf9d6e450ac07864cee6b8ce559f10ad3f 100644 --- a/Modules/Learning/Supervised/test/otbSupervisedTestDriver.cxx +++ b/Modules/Learning/Supervised/test/otbSupervisedTestDriver.cxx @@ -55,8 +55,15 @@ void RegisterTests() REGISTER_TEST(otbGradientBoostedTreeRegressionTests); REGISTER_TEST(otbKNearestNeighborsRegressionTests); REGISTER_TEST(otbRandomForestsRegressionTests); +#endif + +#ifdef OTB_USE_SHARK + REGISTER_TEST(otbSharkRFMachineLearningModelNew); + REGISTER_TEST(otbSharkRFMachineLearningModel); + REGISTER_TEST(otbSharkRFMachineLearningModelCanRead); + REGISTER_TEST(otbSharkImageClassificationFilter); #endif - REGISTER_TEST(otbImageClassificationFilterNew); + REGISTER_TEST(otbImageClassificationFilterNew); REGISTER_TEST(otbImageClassificationFilter); } diff --git a/Modules/Learning/Supervised/test/otbTrainMachineLearningModel.cxx b/Modules/Learning/Supervised/test/otbTrainMachineLearningModel.cxx index cb71ebab690d00ba219bad6b0c753691451ebe35..518a301e4e46a92b34f602e4c997f2e618f8b5d9 100644 --- a/Modules/Learning/Supervised/test/otbTrainMachineLearningModel.cxx +++ b/Modules/Learning/Supervised/test/otbTrainMachineLearningModel.cxx @@ -1035,3 +1035,255 @@ int otbGradientBoostedTreeMachineLearningModel(int argc, char * argv[]) } } #endif + +#ifdef OTB_USE_SHARK +#include <chrono> // If shark is on, then we are using c++11 + +bool SharkReadDataFile(const std::string & infname, InputListSampleType * samples, TargetListSampleType * labels) +{ + std::ifstream ifs(infname.c_str()); + + if(!ifs) + { + std::cout<<"Could not read file "<<infname<<std::endl; + return false; + } + + unsigned int nbfeatures = 0; + + std::string line; + while (std::getline(ifs, line)) + { + boost::algorithm::trim(line); + + if(nbfeatures == 0) + { + nbfeatures = std::count(line.begin(),line.end(),' '); + } + + if(line.size()>1) + { + InputSampleType sample(nbfeatures); + sample.Fill(0); + + std::string::size_type pos = line.find_first_of(" ", 0); + + // Parse label + TargetSampleType label; + label[0] = std::stoi(line.substr(0, pos).c_str()); + + bool endOfLine = false; + unsigned int id = 0; + + while(!endOfLine) + { + std::string::size_type nextpos = line.find_first_of(" ", pos+1); + + if(pos == std::string::npos) + { + endOfLine = true; + nextpos = line.size()-1; + } + else + { + std::string feature = line.substr(pos,nextpos-pos); + std::string::size_type semicolonpos = feature.find_first_of(":"); + id = std::stoi(feature.substr(0,semicolonpos).c_str()); + sample[id - 1] = atof(feature.substr(semicolonpos+1,feature.size()-semicolonpos).c_str()); + pos = nextpos; + } + + } + samples->SetMeasurementVectorSize(itk::NumericTraits<InputSampleType>::GetLength(sample)); + samples->PushBack(sample); + labels->PushBack(label); + } + } + + //std::cout<<"Retrieved "<<samples->Size()<<" samples"<<std::endl; + ifs.close(); + return true; +} + +bool SharkReadDataRegressionFile(const std::string & infname, InputListSampleRegressionType * samples, TargetListSampleRegressionType * labels) +{ + std::ifstream ifs(infname.c_str()); + if(!ifs) + { + std::cout<<"Could not read file "<<infname<<std::endl; + return false; + } + + unsigned int nbfeatures = 0; + + while (!ifs.eof()) + { + std::string line; + std::getline(ifs, line); + + if(nbfeatures == 0) + { + nbfeatures = std::count(line.begin(),line.end(),' ')-1; + //std::cout<<"Found "<<nbfeatures<<" features per samples"<<std::endl; + } + + if(line.size()>1) + { + InputSampleRegressionType sample(nbfeatures); + sample.Fill(0); + + std::string::size_type pos = line.find_first_of(" ", 0); + + // Parse label + TargetSampleRegressionType label; + label[0] = atof(line.substr(0, pos).c_str()); + + bool endOfLine = false; + unsigned int id = 0; + + while(!endOfLine) + { + std::string::size_type nextpos = line.find_first_of(" ", pos+1); + + if(nextpos == std::string::npos) + { + endOfLine = true; + nextpos = line.size()-1; + } + else + { + std::string feature = line.substr(pos,nextpos-pos); + std::string::size_type semicolonpos = feature.find_first_of(":"); + id = std::stoi(feature.substr(0,semicolonpos).c_str()); + sample[id - 1] = atof(feature.substr(semicolonpos+1,feature.size()-semicolonpos).c_str()); + pos = nextpos; + } + + } + samples->SetMeasurementVectorSize(itk::NumericTraits<InputSampleRegressionType>::GetLength(sample)); + samples->PushBack(sample); + labels->PushBack(label); + } + } + + //std::cout<<"Retrieved "<<samples->Size()<<" samples"<<std::endl; + ifs.close(); + return true; +} + + +#include "otbSharkRandomForestsMachineLearningModel.h" +int otbSharkRFMachineLearningModelNew(int itkNotUsed(argc), char * itkNotUsed(argv) []) +{ + typedef otb::SharkRandomForestsMachineLearningModel<InputValueType,TargetValueType> SharkRFType; + SharkRFType::Pointer classifier = SharkRFType::New(); + return EXIT_SUCCESS; +} + +int otbSharkRFMachineLearningModel(int argc, char * argv[]) +{ + if (argc != 3 ) + { + std::cout<<"Wrong number of arguments "<<std::endl; + std::cout<<"Usage : sample file, output file "<<std::endl; + return EXIT_FAILURE; + } + + typedef otb::SharkRandomForestsMachineLearningModel<InputValueType,TargetValueType> RandomForestType; + InputListSampleType::Pointer samples = InputListSampleType::New(); + TargetListSampleType::Pointer labels = TargetListSampleType::New(); + TargetListSampleType::Pointer predicted = TargetListSampleType::New(); + + if(!SharkReadDataFile(argv[1],samples,labels)) + { + std::cout<<"Failed to read samples file "<<argv[1]<<std::endl; + return EXIT_FAILURE; + } + + + RandomForestType::Pointer classifier = RandomForestType::New(); + classifier->SetInputListSample(samples); + classifier->SetTargetListSample(labels); + classifier->SetRegressionMode(false); + classifier->SetNumberOfTrees(100); + classifier->SetMTry(0); + classifier->SetNodeSize(25); + classifier->SetOobRatio(0.3); + std::cout << "Train\n"; + classifier->Train(); + std::cout << "Save\n"; + classifier->Save(argv[2]); + + std::cout << "Predict\n"; + classifier->SetTargetListSample(predicted); + classifier->PredictAll(); + + ConfusionMatrixCalculatorType::Pointer cmCalculator = ConfusionMatrixCalculatorType::New(); + + cmCalculator->SetProducedLabels(predicted); + cmCalculator->SetReferenceLabels(labels); + cmCalculator->Compute(); + + std::cout<<"Confusion matrix: "<<std::endl; + std::cout<<cmCalculator->GetConfusionMatrix()<<std::endl; + const float kappaIdx = cmCalculator->GetKappaIndex(); + std::cout<<"Kappa: "<<kappaIdx<<std::endl; + std::cout<<"Overall Accuracy: "<<cmCalculator->GetOverallAccuracy()<<std::endl; + + // //Predict single samples. Written for benchmarking purposes, but + // too long for regression testing + // std::cout << "Predict single samples\n"; + // auto sIt = samples->Begin(); + // auto lIt = labels->Begin(); + // auto start = std::chrono::system_clock::now(); + // for(; sIt != samples->End(); ++sIt, ++lIt) + // { + // classifier->Predict(sIt.GetMeasurementVector())[0]; + // } + // auto duration = std::chrono::duration_cast< TimeT> + // (std::chrono::system_clock::now() - start); + // auto elapsed = duration.count(); + // std::cout << "Predict took " << elapsed << " ms\n"; + // std::cout << "Single sample OA = " << oa << '\n'; +//Load Model to new RF + TargetListSampleType::Pointer predictedLoad = TargetListSampleType::New(); + RandomForestType::Pointer classifierLoad = RandomForestType::New(); + + std::cout << "Load\n"; + classifierLoad->Load(argv[2]); + auto start = std::chrono::system_clock::now(); + classifierLoad->SetInputListSample(samples); + classifierLoad->SetTargetListSample(predictedLoad); + std::cout << "Predict loaded\n"; + classifierLoad->PredictAll(); + using TimeT = std::chrono::milliseconds; + auto duration = std::chrono::duration_cast< TimeT> + (std::chrono::system_clock::now() - start); + auto elapsed = duration.count(); + std::cout << "PredictAll took " << elapsed << " ms\n"; + ConfusionMatrixCalculatorType::Pointer cmCalculatorLoad = ConfusionMatrixCalculatorType::New(); + + cmCalculatorLoad->SetProducedLabels(predictedLoad); + cmCalculatorLoad->SetReferenceLabels(labels); + cmCalculatorLoad->Compute(); + + std::cout<<"Confusion matrix: "<<std::endl; + std::cout<<cmCalculatorLoad->GetConfusionMatrix()<<std::endl; + const float kappaIdxLoad = cmCalculatorLoad->GetKappaIndex(); + std::cout<<"Kappa: "<<kappaIdxLoad<<std::endl; + std::cout<<"Overall Accuracy: "<<cmCalculatorLoad->GetOverallAccuracy()<<std::endl; + + + if ( vcl_abs(kappaIdxLoad - kappaIdx) < 0.00000001) + { + return EXIT_SUCCESS; + } + else + { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +#endif diff --git a/Modules/Learning/Supervised/test/tests-shark.cmake b/Modules/Learning/Supervised/test/tests-shark.cmake new file mode 100644 index 0000000000000000000000000000000000000000..bd4ffdf056395c61e629d6545592108d8a517877 --- /dev/null +++ b/Modules/Learning/Supervised/test/tests-shark.cmake @@ -0,0 +1,61 @@ +otb_add_test(NAME leTuSharkRFMachineLearningModelNew COMMAND otbSupervisedTestDriver + otbSharkRFMachineLearningModelNew) + +otb_add_test(NAME leTvSharkRFMachineLearningModel COMMAND otbSupervisedTestDriver + otbSharkRFMachineLearningModel + ${INPUTDATA}/letter.scale + ${TEMP}/shark_rf_model.txt + ) + +otb_add_test(NAME leTuSharkRFMachineLearningModelCanRead COMMAND otbSupervisedTestDriver + otbSharkRFMachineLearningModelCanRead + ${INPUTDATA}/Classification/otbSharkImageClassificationFilter_RFmodel.txt + ) + +otb_add_test(NAME leTuSharkRFMachineLearningModelCanReadFail COMMAND otbSupervisedTestDriver + otbSharkRFMachineLearningModelCanRead + ${INPUTDATA}/ROI_QB_MUL_4_svmModel.txt + ) +set_property(TEST leTuSharkRFMachineLearningModelCanReadFail PROPERTY WILL_FAIL true) + + +otb_add_test(NAME leTvImageClassificationFilterSharkFast COMMAND otbSupervisedTestDriver + --compare-n-images ${NOTOL} 2 + ${BASELINE}/leSharkImageClassificationFilterOutput.tif + ${TEMP}/leSharkImageClassificationFilterOutput.tif + ${BASELINE}/leSharkImageClassificationFilterConfidence.tif + ${TEMP}/leSharkImageClassificationFilterConfidence.tif + otbSharkImageClassificationFilter + ${INPUTDATA}/Classification/QB_1_ortho.tif + ${TEMP}/leSharkImageClassificationFilterOutput.tif + ${TEMP}/leSharkImageClassificationFilterConfidence.tif + 1 + ${INPUTDATA}/Classification/otbSharkImageClassificationFilter_RFmodel.txt + ) + +# This test has been added for benchmarking purposes. However, it is +# far too long to be part of regression testing + +# otb_add_test(NAME leTvImageClassificationFilterSharkClassic COMMAND otbSupervisedTestDriver +# otbSharkImageClassificationFilter +# ${INPUTDATA}/Classification/QB_1_ortho.tif +# ${TEMP}/leSharkImageClassificationFilterOutput.tif +# ${TEMP}/leSharkImageClassificationFilterConfidence.tif +# 0 +# ${INPUTDATA}/Classification/otbSharkImageClassificationFilter_RFmodel.txt +# ) + +otb_add_test(NAME leTvImageClassificationFilterSharkFastMask COMMAND otbSupervisedTestDriver + --compare-n-images ${NOTOL} 2 + ${BASELINE}/leSharkImageClassificationFilterWithMaskOutput.tif + ${TEMP}/leSharkImageClassificationFilterWithMaskOutput.tif + ${BASELINE}/leSharkImageClassificationFilterWithMaskConfidence.tif + ${TEMP}/leSharkImageClassificationFilterWithMaskConfidence.tif + otbSharkImageClassificationFilter + ${INPUTDATA}/Classification/QB_1_ortho.tif + ${TEMP}/leSharkImageClassificationFilterWithMaskOutput.tif + ${TEMP}/leSharkImageClassificationFilterWithMaskConfidence.tif + 1 + ${INPUTDATA}/Classification/otbSharkImageClassificationFilter_RFmodel.txt + ${INPUTDATA}/Classification/QB_1_ortho_mask.tif + ) diff --git a/Modules/Radiometry/OpticalCalibration/test/CMakeLists.txt b/Modules/Radiometry/OpticalCalibration/test/CMakeLists.txt index 37a1086bfd7f901d84e534de1b189b07aaedc160..366591f3a37f5bbf86af585042919e527350b382 100644 --- a/Modules/Radiometry/OpticalCalibration/test/CMakeLists.txt +++ b/Modules/Radiometry/OpticalCalibration/test/CMakeLists.txt @@ -43,6 +43,15 @@ add_executable(otbOpticalCalibrationTestDriver ${OTBOpticalCalibrationTests}) target_link_libraries(otbOpticalCalibrationTestDriver ${OTBOpticalCalibration-Test_LIBRARIES}) otb_module_target_label(otbOpticalCalibrationTestDriver) +# Since CMake 2.8.11, the size of the stack is not modified by CMake on +# windows platform, it uses the default size: with visual compiler it is 1Mbyte +# which is to lower for us (thanks to 6S code). +if(MSVC) + set_target_properties(otbOpticalCalibrationTestDriver PROPERTIES LINK_FLAGS "/STACK:10000000") +elseif(MINGW) + set_target_properties(otbOpticalCalibrationTestDriver PROPERTIES LINK_FLAGS "-Wl,--stack,10000000") +endif() + # Tests Declaration otb_add_test(NAME raTuSpectralSensitivityReaderNew COMMAND otbOpticalCalibrationTestDriver diff --git a/Modules/ThirdParty/Shark/CMakeLists.txt b/Modules/ThirdParty/Shark/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c6e4bcb6178cee28ceaebe781979d79506159656 --- /dev/null +++ b/Modules/ThirdParty/Shark/CMakeLists.txt @@ -0,0 +1,6 @@ +project(OTBShark) + +set(OTBShark_SYSTEM_INCLUDE_DIRS ${SHARK_INCLUDE_DIRS}) +set(OTBShark_LIBRARIES "${SHARK_LIBRARY_DIRS}/libshark.so" "-lboost_serialization") + +otb_module_impl() diff --git a/Modules/ThirdParty/Shark/otb-module-init.cmake b/Modules/ThirdParty/Shark/otb-module-init.cmake new file mode 100644 index 0000000000000000000000000000000000000000..ae75820b19b4ddc483115f56f14972b8d8998bd0 --- /dev/null +++ b/Modules/ThirdParty/Shark/otb-module-init.cmake @@ -0,0 +1,3 @@ +find_package ( Shark REQUIRED ) + +mark_as_advanced( Shark_DIR ) diff --git a/Modules/ThirdParty/Shark/otb-module.cmake b/Modules/ThirdParty/Shark/otb-module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..5e01d966b45efd3e57381f4bae065560b0b10ba9 --- /dev/null +++ b/Modules/ThirdParty/Shark/otb-module.cmake @@ -0,0 +1,16 @@ +set(DOCUMENTATION "This module imports SHARK to the build system") + +otb_module(OTBShark + DEPENDS + + TEST_DEPENDS + + DESCRIPTION + "${DOCUMENTATION}" + ) + +otb_module_activation_option("Enable SHARK dependent modules" OFF) + +if( OTB_USE_SHARK ) + otb_module_requires_cxx11() +endif() diff --git a/SuperBuild/CMake/External_otb.cmake b/SuperBuild/CMake/External_otb.cmake index 80876e74daadce0fb7f5aecc285860cf366fd725..b460bac4ac0e5054b65bf0b756de8fde967ade7b 100644 --- a/SuperBuild/CMake/External_otb.cmake +++ b/SuperBuild/CMake/External_otb.cmake @@ -42,6 +42,10 @@ if(OTB_USE_OPENCV) ADD_SUPERBUILD_CMAKE_VAR(OTB OpenCV_DIR) endif() +if(OTB_USE_SHARK) + ADDTO_DEPENDENCIES_IF_NOT_SYSTEM(OTB SHARK) +endif() + if(OTB_USE_LIBSVM) ADDTO_DEPENDENCIES_IF_NOT_SYSTEM(OTB LIBSVM) ADD_SUPERBUILD_CMAKE_VAR(OTB LIBSVM_INCLUDE_DIR) @@ -113,6 +117,26 @@ ADD_SUPERBUILD_CMAKE_VAR(OTB TINYXML_LIBRARY) ADD_SUPERBUILD_CMAKE_VAR(OTB Boost_INCLUDE_DIR) ADD_SUPERBUILD_CMAKE_VAR(OTB Boost_LIBRARY_DIR) +ADD_SUPERBUILD_CMAKE_VAR(OTB LIBKML_INCLUDE_DIR) +ADD_SUPERBUILD_CMAKE_VAR(OTB LIBKML_BASE_LIBRARY) +ADD_SUPERBUILD_CMAKE_VAR(OTB LIBKML_CONVENIENCE_LIBRARY) +ADD_SUPERBUILD_CMAKE_VAR(OTB LIBKML_DOM_LIBRARY) +ADD_SUPERBUILD_CMAKE_VAR(OTB LIBKML_ENGINE_LIBRARY) +ADD_SUPERBUILD_CMAKE_VAR(OTB LIBKML_REGIONATOR_LIBRARY) +ADD_SUPERBUILD_CMAKE_VAR(OTB LIBKML_XSD_LIBRARY) +ADD_SUPERBUILD_CMAKE_VAR(OTB LIBKML_MINIZIP_LIBRARY) + +ADD_SUPERBUILD_CMAKE_VAR(OTB OpenCV_DIR) +ADD_SUPERBUILD_CMAKE_VAR(OTB Shark_DIR) + +ADD_SUPERBUILD_CMAKE_VAR(OTB LIBSVM_INCLUDE_DIR) +ADD_SUPERBUILD_CMAKE_VAR(OTB LIBSVM_LIBRARY) + +if(OTB_USE_CURL) +ADD_SUPERBUILD_CMAKE_VAR(OTB CURL_INCLUDE_DIR) +ADD_SUPERBUILD_CMAKE_VAR(OTB CURL_LIBRARY) +endif() + if(MSVC) ADD_SUPERBUILD_CMAKE_VAR(OTB JPEG_LIBRARY) endif() @@ -163,6 +187,7 @@ ExternalProject_Add(OTB -DOTB_USE_MUPARSER:BOOL=${OTB_USE_MUPARSER} -DOTB_USE_MUPARSERX:BOOL=${OTB_USE_MUPARSERX} -DOTB_USE_OPENCV:BOOL=${OTB_USE_OPENCV} + -DOTB_USE_SHARK:BOOL=${OTB_USE_SHARK} -DOTB_USE_OPENJPEG:BOOL=OFF -DOTB_USE_QT4:BOOL=${OTB_USE_QT4} -DOTB_USE_SIFTFAST:BOOL=${OTB_USE_SIFTFAST} @@ -173,14 +198,15 @@ ExternalProject_Add(OTB -DOTB_USE_QWT:BOOL=${OTB_USE_QWT} -DOTB_WRAP_PYTHON:BOOL=${OTB_WRAP_PYTHON} -DOTB_WRAP_JAVA:BOOL=${OTB_WRAP_JAVA} - ${OTB_SB_CONFIG} - ${OTB_SB_LARGEINPUT_CONFIG} -DGENERATE_PACKAGE:BOOL=OFF -DGENERATE_XDK:BOOL=OFF + ${OTB_SB_CONFIG} + ${OTB_SB_LARGEINPUT_CONFIG} ${OTB_ADDITIONAL_CACHE} CMAKE_COMMAND ${SB_CMAKE_COMMAND} ) + ExternalProject_Add_Step(OTB install_copyright COMMAND ${CMAKE_COMMAND} -E copy_directory ${OTB_SB_SRC}/Copyright ${CMAKE_INSTALL_PREFIX}/share/copyright COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/Copyright ${CMAKE_INSTALL_PREFIX}/share/copyright diff --git a/SuperBuild/CMake/External_shark.cmake b/SuperBuild/CMake/External_shark.cmake new file mode 100644 index 0000000000000000000000000000000000000000..a360f876af4b1d73d629b73fa9f664c4b5311523 --- /dev/null +++ b/SuperBuild/CMake/External_shark.cmake @@ -0,0 +1,38 @@ +if(NOT __EXTERNAL_SHARK__) +set(__EXTERNAL_SHARK__ 1) + +if(USE_SYSTEM_SHARK) + message(STATUS " Using SHARK system version") +else() + SETUP_SUPERBUILD(PROJECT SHARK) + cmake_minimum_required(VERSION 3.1) + message(STATUS " Using SHARK SuperBuild version") + + # declare dependencies + ADDTO_DEPENDENCIES_IF_NOT_SYSTEM(SHARK BOOST) + + ADD_SUPERBUILD_CMAKE_VAR(SHARK Boost_INCLUDE_DIR) + ADD_SUPERBUILD_CMAKE_VAR(SHARK Boost_LIBRARY_DIR) + + ExternalProject_Add(SHARK + PREFIX SHARK + GIT_REPOSITORY "https://github.com/Shark-ML/Shark/" + GIT_TAG "master" + SOURCE_DIR ${SHARK_SB_SRC} + BINARY_DIR ${SHARK_SB_BUILD_DIR} + INSTALL_DIR ${SB_INSTALL_PREFIX} + DOWNLOAD_DIR ${DOWNLOAD_LOCATION} + CMAKE_CACHE_ARGS + -DCMAKE_INSTALL_PREFIX:STRING=${SB_INSTALL_PREFIX} + -DCMAKE_PREFIX_PATH:STRING=${SB_INSTALL_PREFIX};${CMAKE_PREFIX_PATH} + -DCMAKE_BUILD_TYPE:STRING=Release + -DBUILD_SHARED_LIBS:BOOL=ON + -DBUILD_DOCS:BOOL=OFF + -DBUILD_EXAMPLES:BOOL=OFF + -DBUILD_TESTING:BOOL=OFF + -DENABLE_HDF5:BOOL=OFF + CMAKE_COMMAND ${SB_CMAKE_COMMAND} + ) + set(_SB_SHARK_DIR ${SB_INSTALL_PREFIX}/share/SHARK) +endif() +endif() diff --git a/SuperBuild/CMakeLists.txt b/SuperBuild/CMakeLists.txt index 7056f8763d46d65639d2411f21770ad27e8ea25b..2f0955c16f3630b3bc88f539415a43cb33921030 100644 --- a/SuperBuild/CMakeLists.txt +++ b/SuperBuild/CMakeLists.txt @@ -232,6 +232,8 @@ option(USE_SYSTEM_GLEW "Use a system build of GLEW" OFF) option(USE_SYSTEM_GLFW "Use a system build of glfw" OFF) option(USE_SYSTEM_GLUT "Use a system build of glut" OFF) option(USE_SYSTEM_FREETYPE "Use a system build of freetype" OFF) +option(USE_SYSTEM_SHARK "Use a system build of Shark" OFF) + # Call OTB option(OTB_USE_6S "Enable module 6S in OTB" ON) @@ -253,6 +255,7 @@ option(OTB_USE_OPENGL "Enable module OpenGL in OTB" OFF) option(OTB_USE_GLEW "Enable module GLEW in OTB" OFF) option(OTB_USE_GLFW "Enable module GLFW in OTB" OFF) option(OTB_USE_GLUT "Enable module GLUT in OTB" OFF) +option(OTB_USE_SHARK "Enable module Shark in OTB" OFF) option(OTB_USE_QWT "Enable module QWT in OTB" OFF) #Problem: below cmake setting will fail! @@ -320,4 +323,5 @@ if(FROM_SUPERBUILD_LIST) endif() message(STATUS "SuperBuild will be installed to ${CMAKE_INSTALL_PREFIX}") -message(STATUS "To install to a different directory, re-run cmake -DCMAKE_INSTALL_PREFIX=/your/preferred/path") \ No newline at end of file +message(STATUS "To install to a different directory, re-run cmake -DCMAKE_INSTALL_PREFIX=/your/preferred/path") + diff --git a/SuperBuild/patches/SHARK/shark-1-disable-hdf5-linux.diff b/SuperBuild/patches/SHARK/shark-1-disable-hdf5-linux.diff new file mode 100644 index 0000000000000000000000000000000000000000..d0b3df4d7f8355a0da6f4a26ff4d0c4187bca1df --- /dev/null +++ b/SuperBuild/patches/SHARK/shark-1-disable-hdf5-linux.diff @@ -0,0 +1,258 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index df8be65..c6c3020 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -191,29 +191,32 @@ endif() + ##################################################################### + # HDF5 configuration + ##################################################################### +-find_package(HDF5 COMPONENTS C CXX HL QUIET) +-mark_as_advanced(HDF5_DIR) +-if(HDF5_FOUND) +- if(HDF5_C_COMPILER_EXECUTABLE AND HDF5_CXX_COMPILER_EXECUTABLE) +- message(STATUS "Checking HDF5 installation: HDF5 installation seems ok.") +- include_directories( ${HDF5_INCLUDE_DIR} ) +- link_directories( ${HDF5_LIBRARY_DIR} ) +- list(APPEND LINK_LIBRARIES ${HDF5_LIBRARIES}) +- else() +- message(STATUS "Checking HDF5 installation:HDF5 package might be broken.") +- if(NOT( HDF5_C_COMPILER_EXECUTABLE)) +- message(STATUS " C Compiler Extension not found.") +- endif() +- if(NOT( HDF5_CXX_COMPILER_EXECUTABLE)) +- message(STATUS " CXX Compiler Extension not found.") +- endif() +- message(STATUS "Disabling HDF5.") +- unset( HDF5_FOUND ) +- endif() +-else() +- message(STATUS "HDF5 not found, skip") ++option(ENABLE_HDF5 "Use HDF5" ON) ++ ++if(ENABLE_HDF5) ++ find_package(HDF5 COMPONENTS C CXX HL QUIET) ++ mark_as_advanced(HDF5_DIR) ++ if(HDF5_FOUND) ++ if(HDF5_C_COMPILER_EXECUTABLE AND HDF5_CXX_COMPILER_EXECUTABLE) ++ message(STATUS "Checking HDF5 installation: HDF5 installation seems ok.") ++ include_directories( ${HDF5_INCLUDE_DIR} ) ++ link_directories( ${HDF5_LIBRARY_DIR} ) ++ list(APPEND LINK_LIBRARIES ${HDF5_LIBRARIES}) ++ else() ++ message(STATUS "Checking HDF5 installation:HDF5 package might be broken.") ++ if(NOT( HDF5_C_COMPILER_EXECUTABLE)) ++ message(STATUS " C Compiler Extension not found.") ++ endif() ++ if(NOT( HDF5_CXX_COMPILER_EXECUTABLE)) ++ message(STATUS " CXX Compiler Extension not found.") ++ endif() ++ message(STATUS "Disabling HDF5.") ++ unset( HDF5_FOUND ) ++ endif() ++ else() ++ message(STATUS "HDF5 not found, skip") ++ endif() + endif() +- + ##################################################################### + # ATLAS configuration + ##################################################################### +@@ -222,104 +225,104 @@ endif() + option( ENABLE_CBLAS "Use Installed Linear Algebra Library" ON ) + + if( ENABLE_CBLAS ) +- set(CBLAS_VENDOR FALSE) +- if( APPLE ) +- set(CBLAS_VENDOR "Accelerate") +- set(CBLAS_INCLUDES "") +- set(CBLAS_LIBRARIES "-framework Accelerate" ) +- else() +- #todo: do a propper vendor check +- find_library(OPENBLAS_LIBRARY openblas +- HINTS ${CBLAS_ROOT}/lib /opt/local/lib +- ) +- find_library(CBLAS_LIBRARY cblas +- HINTS ${ATLAS_ROOT}/lib ${CBLAS_ROOT}/lib /opt/local/lib /usr/lib64/atlas/ +- ) +- find_library(CLAPACK_LIBRARY lapack +- HINTS ${ATLAS_ROOT}/lib ${CBLAS_ROOT}/lib /opt/local/lib /usr/lib64/atlas/ +- ) +- find_library(ATLAS_LIBRARY atlas +- HINTS ${ATLAS_ROOT}/lib ${CBLAS_ROOT}/lib /opt/local/lib /usr/lib64/atlas/ +- ) +- mark_as_advanced( +- OPENBLAS_LIBRARY +- CBLAS_LIBRARY +- CLAPACK_LIBRARY +- ATLAS_LIBRARY +- ) +- #find the cblas.h include path +- if(CBLAS_LIBRARY ) +- get_filename_component(CBLAS_LIB_PATH ${CBLAS_LIBRARY} PATH ) +- elseif( OPENBLAS_LIBRARY) +- get_filename_component(CBLAS_LIB_PATH ${OPENBLAS_LIBRARY} PATH ) +- endif() +- if(CBLAS_LIB_PATH) +- find_file(CBLAS_INCLUDES cblas.h +- PATHS ${CBLAS_LIB_PATH} ${CBLAS_LIB_PATH}/../include +- ) +- get_filename_component(CBLAS_INCLUDES ${CBLAS_INCLUDES} PATH ) +- endif() +- if(ATLAS_LIBRARY) +- get_filename_component(ATLAS_LIBRARY_PATH ${ATLAS_LIBRARY} PATH ) +- find_file(CLAPACK_INCLUDES clapack.h +- PATHS +- ${ATLAS_LIBRARY_PATH} +- ${ATLAS_LIBRARY_PATH}/../include +- ${ATLAS_LIBRARY_PATH}/../include/atlas +- ${ATLAS_LIBRARY_PATH}/../../include/atlas +- ) +- get_filename_component(CLAPACK_INCLUDES ${CLAPACK_INCLUDES} PATH ) +- set(CBLAS_INCLUDES ${CBLAS_INCLUDES} ${CLAPACK_INCLUDES}) +- endif() +- +- if( OPENBLAS_LIBRARY AND CBLAS_INCLUDES) +- set(CBLAS_VENDOR "OpenBLAS") +- set(CBLAS_LIBRARIES ${OPENBLAS_LIBRARY}) +- elseif( CBLAS_LIBRARY AND CLAPACK_LIBRARY AND ATLAS_LIBRARY AND CBLAS_INCLUDES) +- set(CBLAS_VENDOR "ATLAS") +- set(CBLAS_LIBRARIES ${CLAPACK_LIBRARY} ${CBLAS_LIBRARY} ${ATLAS_LIBRARY}) +- elseif( CBLAS_LIBRARY AND CBLAS_INCLUDES) +- #check that we can compile a basic program with the libraries we have found +- #vendor versions might come with additional libraries which would be bad. +- try_compile(CBLAS_COMPILE +- "${PROJECT_BINARY_DIR}/cBlasCheck" +- "${CMAKE_SOURCE_DIR}/cBlasCheck.cpp" +- CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${CBLAS_INCLUDES}" +- LINK_LIBRARIES ${CBLAS_LIBRARY} +- ) +- if(CBLAS_COMPILE) +- set(CBLAS_VENDOR "GENERIC") +- set(CBLAS_LIBRARIES ${CBLAS_LIBRARY}) +- else() +- message(WARNING "Unknown CBLAS. Can not use it") +- endif() +- endif() +- endif() ++ set(CBLAS_VENDOR FALSE) ++ if( APPLE ) ++ set(CBLAS_VENDOR "Accelerate") ++ set(CBLAS_INCLUDES "") ++ set(CBLAS_LIBRARIES "-framework Accelerate" ) ++ else() ++ #todo: do a propper vendor check ++ find_library(OPENBLAS_LIBRARY openblas ++ HINTS ${CBLAS_ROOT}/lib /opt/local/lib ++ ) ++ find_library(CBLAS_LIBRARY cblas ++ HINTS ${ATLAS_ROOT}/lib ${CBLAS_ROOT}/lib /opt/local/lib /usr/lib64/atlas/ ++ ) ++ find_library(CLAPACK_LIBRARY lapack ++ HINTS ${ATLAS_ROOT}/lib ${CBLAS_ROOT}/lib /opt/local/lib /usr/lib64/atlas/ ++ ) ++ find_library(ATLAS_LIBRARY atlas ++ HINTS ${ATLAS_ROOT}/lib ${CBLAS_ROOT}/lib /opt/local/lib /usr/lib64/atlas/ ++ ) ++ mark_as_advanced( ++ OPENBLAS_LIBRARY ++ CBLAS_LIBRARY ++ CLAPACK_LIBRARY ++ ATLAS_LIBRARY ++ ) ++ #find the cblas.h include path ++ if(CBLAS_LIBRARY ) ++ get_filename_component(CBLAS_LIB_PATH ${CBLAS_LIBRARY} PATH ) ++ elseif( OPENBLAS_LIBRARY) ++ get_filename_component(CBLAS_LIB_PATH ${OPENBLAS_LIBRARY} PATH ) ++ endif() ++ if(CBLAS_LIB_PATH) ++ find_file(CBLAS_INCLUDES cblas.h ++ PATHS ${CBLAS_LIB_PATH} ${CBLAS_LIB_PATH}/../include ++ ) ++ get_filename_component(CBLAS_INCLUDES ${CBLAS_INCLUDES} PATH ) ++ endif() ++ if(ATLAS_LIBRARY) ++ get_filename_component(ATLAS_LIBRARY_PATH ${ATLAS_LIBRARY} PATH ) ++ find_file(CLAPACK_INCLUDES clapack.h ++ PATHS ++ ${ATLAS_LIBRARY_PATH} ++ ${ATLAS_LIBRARY_PATH}/../include ++ ${ATLAS_LIBRARY_PATH}/../include/atlas ++ ${ATLAS_LIBRARY_PATH}/../../include/atlas ++ ) ++ get_filename_component(CLAPACK_INCLUDES ${CLAPACK_INCLUDES} PATH ) ++ set(CBLAS_INCLUDES ${CBLAS_INCLUDES} ${CLAPACK_INCLUDES}) ++ endif() ++ ++ if( OPENBLAS_LIBRARY AND CBLAS_INCLUDES) ++ set(CBLAS_VENDOR "OpenBLAS") ++ set(CBLAS_LIBRARIES ${OPENBLAS_LIBRARY}) ++ elseif( CBLAS_LIBRARY AND CLAPACK_LIBRARY AND ATLAS_LIBRARY AND CBLAS_INCLUDES) ++ set(CBLAS_VENDOR "ATLAS") ++ set(CBLAS_LIBRARIES ${CLAPACK_LIBRARY} ${CBLAS_LIBRARY} ${ATLAS_LIBRARY}) ++ elseif( CBLAS_LIBRARY AND CBLAS_INCLUDES) ++ #check that we can compile a basic program with the libraries we have found ++ #vendor versions might come with additional libraries which would be bad. ++ try_compile(CBLAS_COMPILE ++ "${PROJECT_BINARY_DIR}/cBlasCheck" ++ "${CMAKE_SOURCE_DIR}/cBlasCheck.cpp" ++ CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${CBLAS_INCLUDES}" ++ LINK_LIBRARIES ${CBLAS_LIBRARY} ++ ) ++ if(CBLAS_COMPILE) ++ set(CBLAS_VENDOR "GENERIC") ++ set(CBLAS_LIBRARIES ${CBLAS_LIBRARY}) ++ else() ++ message(WARNING "Unknown CBLAS. Can not use it") ++ endif() ++ endif() ++ endif() + +- if(CBLAS_VENDOR) +- message(STATUS "CBLAS FOUND: " ${CBLAS_VENDOR} " with include directory " ${CBLAS_INCLUDES} ) +- set(SHARK_USE_CBLAS 1) +- list(APPEND EXTRA_INCLUDE_DIRECTORIES ${CBLAS_INCLUDES} ) +- list(APPEND LINK_LIBRARIES ${CBLAS_LIBRARIES}) +- include_directories ( ${CBLAS_INCLUDES} ) +- else() +- message(STATUS "No usable CBLAS Library found. No fast linear Algebra used.") +- endif() ++ if(CBLAS_VENDOR) ++ message(STATUS "CBLAS FOUND: " ${CBLAS_VENDOR} " with include directory " ${CBLAS_INCLUDES} ) ++ set(SHARK_USE_CBLAS 1) ++ list(APPEND EXTRA_INCLUDE_DIRECTORIES ${CBLAS_INCLUDES} ) ++ list(APPEND LINK_LIBRARIES ${CBLAS_LIBRARIES}) ++ include_directories ( ${CBLAS_INCLUDES} ) ++ else() ++ message(STATUS "No usable CBLAS Library found. No fast linear Algebra used.") ++ endif() + +- #Special setup for ATLAS +- if( CBLAS_VENDOR MATCHES "ATLAS" ) +- set( SHARK_USE_ATLAS_LAPACK 1) # ATLAS always contains some LAPACK methods that we can use ++ #Special setup for ATLAS ++ if( CBLAS_VENDOR MATCHES "ATLAS" ) ++ set( SHARK_USE_ATLAS_LAPACK 1) # ATLAS always contains some LAPACK methods that we can use + +- #check for full lapack +- set(CMAKE_REQUIRE_QUIET 1) +- set(CMAKE_REQUIRED_LIBRARIES ${CBLAS_LIBRARIES}) +- check_function_exists(dsyev_ ATLAS_FULL_LAPACK) ++ #check for full lapack ++ set(CMAKE_REQUIRE_QUIET 1) ++ set(CMAKE_REQUIRED_LIBRARIES ${CBLAS_LIBRARIES}) ++ check_function_exists(dsyev_ ATLAS_FULL_LAPACK) + +- if( ATLAS_FULL_LAPACK ) +- set( SHARK_USE_LAPACK 1) +- message(STATUS "Detected ATLAS with full LAPACK package. Using it!") +- endif() +- endif() ++ if( ATLAS_FULL_LAPACK ) ++ set( SHARK_USE_LAPACK 1) ++ message(STATUS "Detected ATLAS with full LAPACK package. Using it!") ++ endif() ++ endif() + endif() + ##################################################################### + # Static Code Analysis diff --git a/Utilities/Maintenance/fix_typos.sh b/Utilities/Maintenance/fix_typos.sh index 0a4ebc4e7bc9cb2537b071a0776c5295cb410a0a..7e427029e156b8dba8c11d1671fa850a6d3485f6 100755 --- a/Utilities/Maintenance/fix_typos.sh +++ b/Utilities/Maintenance/fix_typos.sh @@ -73,6 +73,6 @@ WORDS_WHITE_LIST="$WORDS_WHITE_LIST,dum" # for pary variable WORDS_WHITE_LIST="$WORDS_WHITE_LIST,pary" -python3 fix_typos/codespell/codespell.py codespell.py -w -i 3 -q 2 -S $EXCLUDED_FILES \ +python3 fix_typos/codespell/codespell.py -w -i 3 -q 2 -S $EXCLUDED_FILES \ --words-white-list=$WORDS_WHITE_LIST \ -D fix_typos/otb_dict.txt ../..