diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3bd9f45f141aabc4352b359ec748d96a428140cd..d9d0760dcc88c2c90f9046d885b8d199eb18ddd7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -39,14 +39,6 @@ stages: - runner_system_failure - stuck_or_timeout_failure -native-build: - extends: .general - only: [merge_requests] - stage: build - image: $BUILD_IMAGE_REGISTRY/otb-ubuntu-native:18.04 - script: - - xvfb-run -a -n 1 -s "-screen 0 1024x768x24 -dpi 96" ctest -V -S CI/main_ci.cmake -DIMAGE_NAME:string=ubuntu-18.04-gcc - debian-build: extends: .general only: [merge_requests] @@ -58,10 +50,14 @@ debian-build: .common-build: extends: .general stage: build - image: $BUILD_IMAGE_REGISTRY/otb-ubuntu-shark:18.04 + image: $BUILD_IMAGE_REGISTRY/otb-ubuntu-native:18.04 script: - - xvfb-run -a -n 1 -s "-screen 0 1024x768x24 -dpi 96" ctest -V -S CI/main_ci.cmake -DIMAGE_NAME:string=ubuntu-18.04-llvm-shark - + - xvfb-run -a -n 1 -s "-screen 0 1024x768x24 -dpi 96" ctest -V -S CI/main_ci.cmake -DIMAGE_NAME:string=ubuntu-18.04-llvm + artifacts: + paths: + - build/CookBook-*-html.tar.gz + - build/Documentation/Cookbook/latex/CookBook-*.pdf + - build/Documentation/Doxygen/OTB-Doxygen-*.tar.bz2 # This is needed to have only one pipeline in a merge request context ubuntu-llvm: diff --git a/CI/cdash_handler.py b/CI/cdash_handler.py index 72a4f46c64e57b4a7c5835f99cee8a836d244a66..7a19d5a87f870f785565319d0dcd24dc47de6df4 100644 --- a/CI/cdash_handler.py +++ b/CI/cdash_handler.py @@ -26,6 +26,7 @@ import re import unittest import sys import json +import time trace = False @@ -168,7 +169,7 @@ class Handler: if key == "project": project = value if ( site == "" or stamp == "" or name == "" or project == ""): - print( "Not enougth argument given for buildid request \ + print( "Missing argument for buildid request \ site:"+site+", stamp:"+stamp+", name:"+name+", project:"+project+".") return buildid_api = "/api/v1/getbuildid.php?" @@ -176,11 +177,18 @@ site:"+site+", stamp:"+stamp+", name:"+name+", project:"+project+".") full_url = self.url + buildid_api + buildid_params if trace: print("full_url: "+full_url) - response = urllib.request.urlopen(full_url).read().decode() - if trace: - print ( "response: " + response ) + nb_try = 6 build_id_regex = re.compile( "<buildid>([0-9]+)</buildid>" ) - buildid = build_id_regex.search( response ) + while nb_try: + response = urllib.request.urlopen(full_url).read().decode() + if trace: + print ( "response: " + response ) + buildid = build_id_regex.search( response ) + nb_try -= 1 + if buildid or (nb_try == 0): + break + print("No build id, retry ...") + time.sleep(60) if buildid: self.buildid = buildid.group(1) if trace: @@ -198,7 +206,7 @@ site:"+site+", stamp:"+stamp+", name:"+name+", project:"+project+".") if ( buildid == "" ): buildid = self.buildid if ( buildid == "" ): - print( "Not enougth argument given to build url") + print( "Missing argument to build url") return build_url = self.url build_url +="/buildSummary.php?" @@ -212,7 +220,7 @@ site:"+site+", stamp:"+stamp+", name:"+name+", project:"+project+".") if ( buildid == "" ): buildid = self.buildid if ( buildid == "" ): - print( "Not enougth argument given to build Status") + print( "Missing argument to build Status") return full_url = self.url + "/api/v1/buildSummary.php?buildid=" + buildid response = urllib.request.urlopen(full_url).read().decode() @@ -251,10 +259,13 @@ if __name__ == "__main__": handler.GetSite() handler.GetName() handler.GetStamp() - handler.GetBuildId() - # handler.buildid="1" - cdash_url = handler.GetBuildUrl() - ( state , error ) = handler.GetBuildStatus() + if handler.GetBuildId() is None: + cdash_url = "https://cdash.orfeo-toolbox.org" + state = 'failed' + error = "Failed to get build id" + else: + cdash_url = handler.GetBuildUrl() + ( state , error ) = handler.GetBuildStatus() if trace: print ( "cdash_url is: " + cdash_url ) gitlab_url = "https://gitlab.orfeo-toolbox.org/api/v4/projects/" diff --git a/CI/main_ci.cmake b/CI/main_ci.cmake index 845b666466ece9cbb8b36aeb7cd353c21418cef3..1edbf1718ce81a666b2f65da919cc83113d09a4c 100644 --- a/CI/main_ci.cmake +++ b/CI/main_ci.cmake @@ -26,13 +26,22 @@ set (ENV{LANG} "C") # Only ascii output set (CTEST_BUILD_CONFIGURATION "Release") set (CTEST_CMAKE_GENERATOR "Ninja") +# detect short sha +if(NOT DEFINED ENV{CI_COMMIT_SHORT_SHA}) + execute_process(COMMAND git log -1 --pretty=format:%h + WORKING_DIRECTORY ${OTB_SOURCE_DIR} + OUTPUT_VARIABLE ci_short_sha) +else() + set(ci_short_sha "$ENV{CI_COMMIT_SHORT_SHA}") +endif() + # Find the build name and CI profile set(ci_profile wip) set(ci_mr_source "$ENV{CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}") set(ci_mr_target "$ENV{CI_MERGE_REQUEST_TARGET_BRANCH_NAME}") set(ci_mr_iid "$ENV{CI_MERGE_REQUEST_IID}") set(ci_ref_name "$ENV{CI_COMMIT_REF_NAME}") -set (CTEST_BUILD_NAME "$ENV{CI_COMMIT_SHORT_SHA}") +set (CTEST_BUILD_NAME ${ci_short_sha}) if(ci_mr_source AND ci_mr_target AND ci_mr_iid) set (CTEST_BUILD_NAME "${ci_mr_source} (MR ${ci_mr_iid})") set(ci_profile mr) @@ -45,14 +54,32 @@ elseif(ci_ref_name) endif() endif() -#Warning, this variable is used in cdash_status.py. If change from -# ${IMAGE_NAME} to something else do not forget to change it. +# set pipelines to enable documentation +set(ci_cookbook_profiles mr develop release) +set(ci_doxygen_profiles mr develop release) +list(FIND ci_cookbook_profiles ${ci_profile} ci_do_cookbook) +list(FIND ci_doxygen_profiles ${ci_profile} ci_do_doxygen) + +# Detect site +if(NOT DEFINED IMAGE_NAME) + if(DEFINED ENV{IMAGE_NAME}) + set(IMAGE_NAME $ENV{IMAGE_NAME}) + endif() +endif() set (CTEST_SITE "${IMAGE_NAME}") # Directory variable set (CTEST_SOURCE_DIRECTORY "${OTB_SOURCE_DIR}") -set (CTEST_BINARY_DIRECTORY "${OTB_SOURCE_DIR}/build/") -set (CTEST_INSTALL_DIRECTORY "${OTB_SOURCE_DIR}/install/") +if(BUILD_DIR) + set (CTEST_BINARY_DIRECTORY "${BUILD_DIR}") +else() + set (CTEST_BINARY_DIRECTORY "${OTB_SOURCE_DIR}/build/") +endif() +if(INSTALL_DIR) + set (CTEST_INSTALL_DIRECTORY "${INSTALL_DIR}") +else() + set (CTEST_INSTALL_DIRECTORY "${OTB_SOURCE_DIR}/install/") +endif() set (PROJECT_SOURCE_DIR "${OTB_SOURCE_DIR}") # Ctest command value @@ -64,6 +91,7 @@ set (OTB_LARGEINPUT_ROOT "") # todo message(STATUS "CI profile : ${ci_profile}") #The following file set the CONFIGURE_OPTIONS variable +set (ENABLE_DOXYGEN OFF) set (CONFIGURE_OPTIONS "") include ( "${CMAKE_CURRENT_LIST_DIR}/configure_option.cmake" ) @@ -112,3 +140,12 @@ if ( NOT _test_rv EQUAL 0 ) endif() ctest_submit() + +if(ENABLE_DOXYGEN) + # compile doxygen + ctest_build(BUILD "${CTEST_BINARY_DIRECTORY}" + TARGET Documentation + RETURN_VALUE _doxy_rv + CAPTURE_CMAKE_ERROR _doxy_error + ) +endif() diff --git a/CI/ubuntu-18.04-gcc-shark.cmake b/CI/ubuntu-18.04-gcc-shark.cmake deleted file mode 100644 index b9ef2642b4890d8be17aabb164727bb70add5120..0000000000000000000000000000000000000000 --- a/CI/ubuntu-18.04-gcc-shark.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# -# Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) -# -# This file is part of Orfeo Toolbox -# -# https://www.orfeo-toolbox.org/ -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# Configuration options for ubuntu-18.04-gcc-shark-3.1.4 - -set(site_option -"opencv_INCLUDE_DIR:PATH=/usr/include") diff --git a/CI/ubuntu-18.04-llvm-shark.cmake b/CI/ubuntu-18.04-llvm-shark.cmake deleted file mode 100644 index 21a888bf5c014dc7e2fc84b424b6a3e184613610..0000000000000000000000000000000000000000 --- a/CI/ubuntu-18.04-llvm-shark.cmake +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) -# -# This file is part of Orfeo Toolbox -# -# https://www.orfeo-toolbox.org/ -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# Configuration options for ubuntu-18.04-llvm-shark-3.1.4 - -set(site_option -"opencv_INCLUDE_DIR:PATH=/usr/include -CMAKE_C_COMPILER:STRING=clang -CMAKE_CXX_COMPILER:STRING=clang++ -CMAKE_EXE_LINKER_FLAGS:STRING=-fuse-ld=lld -CMAKE_MODULE_LINKER_FLAGS:STRING=-fuse-ld=lld -CMAKE_SHARED_LINKER_FLAGS:STRING=-fuse-ld=lld -OTB_USE_SHARK:BOOL=OFF -") diff --git a/CI/ubuntu-18.04-llvm.cmake b/CI/ubuntu-18.04-llvm.cmake index a92364f2b45d82176aa65d3d112753055421aef1..6480ab2f31b9ddb22b56a15d61ac305a85e85423 100644 --- a/CI/ubuntu-18.04-llvm.cmake +++ b/CI/ubuntu-18.04-llvm.cmake @@ -22,9 +22,33 @@ set(site_option "opencv_INCLUDE_DIR:PATH=/usr/include -OTB_USE_SHARK:BOOL=OFF CMAKE_C_COMPILER:STRING=clang CMAKE_CXX_COMPILER:STRING=clang++ CMAKE_EXE_LINKER_FLAGS:STRING=-fuse-ld=lld CMAKE_MODULE_LINKER_FLAGS:STRING=-fuse-ld=lld -CMAKE_SHARED_LINKER_FLAGS:STRING=-fuse-ld=lld") +CMAKE_SHARED_LINKER_FLAGS:STRING=-fuse-ld=lld +CMAKE_C_COMPILER_LAUNCHER:STRING=ccache +CMAKE_CXX_COMPILER_LAUNCHER:STRING=ccache +OTB_USE_SHARK:BOOL=OFF") + +if(NOT ${ci_do_cookbook} EQUAL -1) + set(site_option +"${site_option} +BUILD_COOKBOOK:BOOL=ON") +endif() + +if(NOT ${ci_do_doxygen} EQUAL -1) + set(site_option +"${site_option} +BUILD_DOCUMENTATION:BOOL=ON +OTB_DOXYGEN_ITK_TAGFILE:FILEPATH=${CTEST_BINARY_DIRECTORY}/InsightDoxygenDocTag-4.13.0 +OTB_DOXYGEN_ITK_DOXYGEN_URL:STRING=\"https://itk.org/Doxygen413/html\" +") + set (ENABLE_DOXYGEN ON) + # The ITK doxygen tag file needs to be patched before being used for OTB + # See otb-devutils/Scripts/tagfile_fix.py + message(STATUS "Get resources for Doxygen build ...") + execute_process(COMMAND wget https://www.orfeo-toolbox.org/packages/archives/Doxygen/InsightDoxygenDocTag-4.13.0.gz + COMMAND gzip -d InsightDoxygenDocTag-4.13.0.gz + WORKING_DIRECTORY ${CTEST_BINARY_DIRECTORY}) +endif() diff --git a/Documentation/Cookbook/Scripts/otbGenerateWrappersRstDoc.py b/Documentation/Cookbook/Scripts/otbGenerateWrappersRstDoc.py index 1fdf53d44841712fcb7f221dfc5618bd4c6cc47c..8cd9ab8ed70e204d915e32c25ebb4944f52b4a9b 100755 --- a/Documentation/Cookbook/Scripts/otbGenerateWrappersRstDoc.py +++ b/Documentation/Cookbook/Scripts/otbGenerateWrappersRstDoc.py @@ -426,7 +426,7 @@ def GenerateRstForApplications(rst_dir): tagFile.write("\tapp_" + appName + "\n") # Write application rst - with open(rst_dir + '/Applications/app_' + appName + '.rst', 'w') as appFile: + with open(rst_dir + '/Applications/app_' + appName + '.rst', 'w',encoding='utf-8') as appFile: appFile.write(render_application(appName, appNames)) if __name__ == "__main__": diff --git a/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx b/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx index 95e3314e115ac5254d08d6320207b4e1a80f43fe..bbfb99010e2df503fc561fad3ba528b8b3904151 100644 --- a/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx +++ b/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx @@ -54,7 +54,7 @@ public: /** Filters typedef */ typedef otb::OGRDataToClassStatisticsFilter<FloatVectorImageType,UInt8ImageType> FilterType; - + typedef otb::StatisticsXMLFileWriter<FloatVectorImageType::PixelType> StatWriterType; typedef otb::GeometriesSet GeometriesType; @@ -64,7 +64,6 @@ public: private: PolygonClassStatistics() { - } void DoInit() override @@ -98,17 +97,17 @@ private: AddParameter(ParameterType_InputImage, "mask", "Input validity mask"); SetParameterDescription("mask", "Validity mask (only pixels corresponding to a mask value greater than 0 will be used for statistics)"); MandatoryOff("mask"); - + AddParameter(ParameterType_InputFilename, "vec", "Input vectors"); SetParameterDescription("vec","Input geometries to analyze"); - + AddParameter(ParameterType_OutputFilename, "out", "Output XML statistics file"); SetParameterDescription("out","Output file to store statistics (XML format)"); AddParameter(ParameterType_ListView, "field", "Field Name"); SetParameterDescription("field","Name of the field carrying the class name in the input vectors."); SetListViewSingleSelectionMode("field",true); - + AddParameter(ParameterType_Int, "layer", "Layer Index"); SetParameterDescription("layer", "Layer index to read in the input vector file."); MandatoryOff("layer"); @@ -138,16 +137,16 @@ private: ogr::Feature feature = layer.ogr().GetNextFeature(); ClearChoices("field"); - + for(int iField=0; iField<feature.ogr().GetFieldCount(); iField++) { std::string key, item = feature.ogr().GetFieldDefnRef(iField)->GetNameRef(); key = item; std::string::iterator end = std::remove_if(key.begin(),key.end(),IsNotAlphaNum); std::transform(key.begin(), end, key.begin(), tolower); - + OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(iField)->GetType(); - + if(fieldType == OFTString || fieldType == OFTInteger || fieldType == OFTInteger64) { std::string tmpKey="field."+key.substr(0, end - key.begin()); @@ -159,7 +158,7 @@ private: // Check that the extension of the output parameter is XML (mandatory for // StatisticsXMLFileWriter) // Check it here to trigger the error before polygons analysis - + if ( HasValue("out") ) { // Store filename extension @@ -175,46 +174,39 @@ private: void DoExecute() override { - otb::ogr::DataSource::Pointer vectors = - otb::ogr::DataSource::New(this->GetParameterString("vec")); + otb::ogr::DataSource::Pointer vectors = otb::ogr::DataSource::New(this->GetParameterString("vec")); - // Retrieve the field name - std::vector<int> selectedCFieldIdx = GetSelectedItems("field"); + // Retrieve the field name + std::vector<int> selectedCFieldIdx = GetSelectedItems("field"); - if(selectedCFieldIdx.empty()) + if (selectedCFieldIdx.empty()) { otbAppLogFATAL(<<"No field has been selected for data labelling!"); } - std::vector<std::string> cFieldNames = GetChoiceNames("field"); - std::string fieldName = cFieldNames[selectedCFieldIdx.front()]; - - otb::Wrapper::ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(this,"elev"); - - // Reproject geometries - FloatVectorImageType::Pointer inputImg = this->GetParameterImage("in"); - std::string imageProjectionRef = inputImg->GetProjectionRef(); - FloatVectorImageType::ImageKeywordlistType imageKwl = - inputImg->GetImageKeywordlist(); - std::string vectorProjectionRef = - vectors->GetLayer(GetParameterInt("layer")).GetProjectionRef(); - - otb::ogr::DataSource::Pointer reprojVector = vectors; - GeometriesType::Pointer inputGeomSet; - ProjectionFilterType::Pointer geometriesProjFilter; - GeometriesType::Pointer outputGeomSet; - const OGRSpatialReference imgOGRSref = - OGRSpatialReference( imageProjectionRef.c_str() ); - const OGRSpatialReference vectorOGRSref = - OGRSpatialReference( vectorProjectionRef.c_str() ); - bool doReproj = true; - // don't reproject for these cases - if ( vectorProjectionRef.empty() - || ( imgOGRSref.IsSame( &vectorOGRSref ) ) - || ( imageProjectionRef.empty() && imageKwl.GetSize() == 0) ) - doReproj = false; - - if (doReproj) + std::vector<std::string> cFieldNames = GetChoiceNames("field"); + std::string fieldName = cFieldNames[selectedCFieldIdx.front()]; + + otb::Wrapper::ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(this, "elev"); + + // Reproject geometries + FloatVectorImageType::Pointer inputImg = this->GetParameterImage("in"); + std::string imageProjectionRef = inputImg->GetProjectionRef(); + FloatVectorImageType::ImageKeywordlistType imageKwl = inputImg->GetImageKeywordlist(); + std::string vectorProjectionRef = vectors->GetLayer(GetParameterInt("layer")).GetProjectionRef(); + + otb::ogr::DataSource::Pointer reprojVector = vectors; + GeometriesType::Pointer inputGeomSet; + ProjectionFilterType::Pointer geometriesProjFilter; + GeometriesType::Pointer outputGeomSet; + const OGRSpatialReference imgOGRSref = OGRSpatialReference(imageProjectionRef.c_str()); + const OGRSpatialReference vectorOGRSref = OGRSpatialReference(vectorProjectionRef.c_str()); + bool doReproj = true; + // don't reproject for these cases + if (vectorProjectionRef.empty() || (imgOGRSref.IsSame(&vectorOGRSref)) || (imageProjectionRef.empty() && imageKwl.GetSize() == 0)) + doReproj = false; + + if (doReproj) { inputGeomSet = GeometriesType::New(vectors); reprojVector = otb::ogr::DataSource::New(); @@ -236,7 +228,7 @@ private: filter->SetInput(this->GetParameterImage("in")); if (IsParameterEnabled("mask") && HasValue("mask")) { - filter->SetMask(this->GetParameterImage<UInt8ImageType>("mask")); + filter->SetMask(this->GetParameterUInt8Image("mask")); } filter->SetOGRData(reprojVector); filter->SetFieldName(fieldName); @@ -245,10 +237,10 @@ private: AddProcess(filter->GetStreamer(),"Analyze polygons..."); filter->Update(); - + FilterType::ClassCountMapType &classCount = filter->GetClassCountOutput()->Get(); FilterType::PolygonSizeMapType &polySize = filter->GetPolygonSizeOutput()->Get(); - + StatWriterType::Pointer statWriter = StatWriterType::New(); statWriter->SetFileName(this->GetParameterString("out")); statWriter->AddInputMap<FilterType::ClassCountMapType>("samplesPerClass",classCount); diff --git a/Modules/Applications/AppClassification/app/otbSampleSelection.cxx b/Modules/Applications/AppClassification/app/otbSampleSelection.cxx index a4f8b1fc33a73f4e1a2f123dafd8498238f3f984..959f3c129d0c32c3f77343f249c0b18e022232de 100644 --- a/Modules/Applications/AppClassification/app/otbSampleSelection.cxx +++ b/Modules/Applications/AppClassification/app/otbSampleSelection.cxx @@ -63,7 +63,7 @@ public: UInt8ImageType, otb::RandomSampler> RandomSamplerType; typedef otb::SamplingRateCalculator RateCalculatorType; - + typedef std::map<std::string, unsigned long> ClassCountMapType; typedef RateCalculatorType::MapRateType MapRateType; typedef itk::VariableLengthVector<float> MeasurementType; @@ -87,40 +87,41 @@ private: // Documentation SetDocName("Sample Selection"); - SetDocLongDescription("The application selects a set of samples from geometries " - "intended for training (they should have a field giving the associated " - "class). \n\nFirst of all, the geometries must be analyzed by the PolygonClassStatistics application " - "to compute statistics about the geometries, which are summarized in an xml file. " - "\nThen, this xml file must be given as input to this application (parameter instats).\n\n" - "The input support image and the input training vectors shall be given in " - "parameters 'in' and 'vec' respectively. Only the sampling grid (origin, size, spacing)" - "will be read in the input image.\n" - "There are several strategies to select samples (parameter strategy) : \n\n" - " - smallest (default) : select the same number of sample in each class" - " so that the smallest one is fully sampled.\n" - " - constant : select the same number of samples N in each class" - " (with N below or equal to the size of the smallest class).\n" - " - byclass : set the required number for each class manually, with an input CSV file" - " (first column is class name, second one is the required samples number).\n\n" - " - percent: set a target global percentage of samples to use. Class proportions will be respected. \n\n" - " - total: set a target total number of samples to use. Class proportions will be respected. \n\n" - "There is also a choice on the sampling type to performs : \n\n" - " - periodic : select samples uniformly distributed\n" - " - random : select samples randomly distributed\n\n" - "Once the strategy and type are selected, the application outputs samples positions" - "(parameter out).\n\n" - - "The other parameters to look at are : \n\n" - " - layer : index specifying from which layer to pick geometries.\n" - " - field : set the field name containing the class.\n" - " - mask : an optional raster mask can be used to discard samples.\n" - " - outrates : allows outputting a CSV file that summarizes the sampling rates for each class.\n" - - "\nAs with the PolygonClassStatistics application, different types of geometry are supported : " - "polygons, lines, points. \nThe behavior of this application is different for each type of geometry : \n\n" - " - polygon: select points whose center is inside the polygon\n" - " - lines : select points intersecting the line\n" - " - points : select closest point to the provided point"); + SetDocLongDescription( + "The application selects a set of samples from geometries " + "intended for training (they should have a field giving the associated " + "class). \n\nFirst of all, the geometries must be analyzed by the PolygonClassStatistics application " + "to compute statistics about the geometries, which are summarized in an xml file. " + "\nThen, this xml file must be given as input to this application (parameter instats).\n\n" + "The input support image and the input training vectors shall be given in " + "parameters 'in' and 'vec' respectively. Only the sampling grid (origin, size, spacing)" + "will be read in the input image.\n" + "There are several strategies to select samples (parameter strategy) : \n\n" + " - smallest (default) : select the same number of sample in each class" + " so that the smallest one is fully sampled.\n" + " - constant : select the same number of samples N in each class" + " (with N below or equal to the size of the smallest class).\n" + " - byclass : set the required number for each class manually, with an input CSV file" + " (first column is class name, second one is the required samples number).\n\n" + " - percent: set a target global percentage of samples to use. Class proportions will be respected. \n\n" + " - total: set a target total number of samples to use. Class proportions will be respected. \n\n" + "There is also a choice on the sampling type to performs : \n\n" + " - periodic : select samples uniformly distributed\n" + " - random : select samples randomly distributed\n\n" + "Once the strategy and type are selected, the application outputs samples positions" + "(parameter out).\n\n" + + "The other parameters to look at are : \n\n" + " - layer : index specifying from which layer to pick geometries.\n" + " - field : set the field name containing the class.\n" + " - mask : an optional raster mask can be used to discard samples.\n" + " - outrates : allows outputting a CSV file that summarizes the sampling rates for each class.\n" + + "\nAs with the PolygonClassStatistics application, different types of geometry are supported : " + "polygons, lines, points. \nThe behavior of this application is different for each type of geometry : \n\n" + " - polygon: select points whose center is inside the polygon\n" + " - lines : select points intersecting the line\n" + " - points : select closest point to the provided point"); SetDocLimitations("None"); SetDocAuthors("OTB-Team"); SetDocSeeAlso(" "); @@ -192,7 +193,7 @@ private: SetParameterDescription("strategy.total.v","The number of samples to generate"); SetMinimumParameterIntValue("strategy.total.v",1); SetDefaultParameterInt("strategy.total.v",1000); - + AddChoice("strategy.smallest","Set same number of samples for all classes, with the smallest class fully sampled"); SetParameterDescription("strategy.smallest","Set same number of samples for all classes, with the smallest class fully sampled"); @@ -238,16 +239,16 @@ private: ogr::Feature feature = layer.ogr().GetNextFeature(); ClearChoices("field"); - + for(int iField=0; iField<feature.ogr().GetFieldCount(); iField++) { std::string key, item = feature.ogr().GetFieldDefnRef(iField)->GetNameRef(); key = item; std::string::iterator end = std::remove_if(key.begin(),key.end(),IsNotAlphaNum); std::transform(key.begin(), end, key.begin(), tolower); - + OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(iField)->GetType(); - + if(fieldType == OFTString || fieldType == OFTInteger || fieldType == OFTInteger64) { std::string tmpKey="field."+key.substr(0, end - key.begin()); @@ -266,27 +267,26 @@ private: // Get field name std::vector<int> selectedCFieldIdx = GetSelectedItems("field"); - + if(selectedCFieldIdx.empty()) { otbAppLogFATAL(<<"No field has been selected for data labelling!"); } - - std::vector<std::string> cFieldNames = GetChoiceNames("field"); - std::string fieldName = cFieldNames[selectedCFieldIdx.front()]; - - m_ReaderStat->SetFileName(this->GetParameterString("instats")); - ClassCountMapType classCount = m_ReaderStat->GetStatisticMapByName<ClassCountMapType>("samplesPerClass"); - m_RateCalculator->SetClassCount(classCount); - - switch (this->GetParameterInt("strategy")) + + std::vector<std::string> cFieldNames = GetChoiceNames("field"); + std::string fieldName = cFieldNames[selectedCFieldIdx.front()]; + + m_ReaderStat->SetFileName(this->GetParameterString("instats")); + ClassCountMapType classCount = m_ReaderStat->GetStatisticMapByName<ClassCountMapType>("samplesPerClass"); + m_RateCalculator->SetClassCount(classCount); + + switch (this->GetParameterInt("strategy")) { // byclass case 0: { otbAppLogINFO("Sampling strategy : set number of samples for each class"); - ClassCountMapType requiredCount = - otb::SamplingRateCalculator::ReadRequiredSamples(this->GetParameterString("strategy.byclass.in")); + ClassCountMapType requiredCount = otb::SamplingRateCalculator::ReadRequiredSamples(this->GetParameterString("strategy.byclass.in")); m_RateCalculator->SetNbOfSamplesByClass(requiredCount); } break; @@ -330,12 +330,12 @@ private: otbAppLogFATAL("Strategy mode unknown :"<<this->GetParameterString("strategy")); break; } - + if (IsParameterEnabled("outrates") && HasValue("outrates")) { m_RateCalculator->Write(this->GetParameterString("outrates")); } - + MapRateType rates = m_RateCalculator->GetRatesByClass(); std::ostringstream oss; oss << " className requiredSamples totalSamples rate" << std::endl; @@ -376,16 +376,14 @@ private: ProjectionFilterType::Pointer geometriesProjFilter; GeometriesType::Pointer outputGeomSet; bool doReproj = true; - const OGRSpatialReference imgOGRSref = - OGRSpatialReference( imageProjectionRef.c_str() ); - const OGRSpatialReference vectorOGRSref = - OGRSpatialReference( vectorProjectionRef.c_str() ); + const OGRSpatialReference imgOGRSref = OGRSpatialReference(imageProjectionRef.c_str()); + const OGRSpatialReference vectorOGRSref = OGRSpatialReference(vectorProjectionRef.c_str()); // don't reproject for these cases if ( vectorProjectionRef.empty() || ( imgOGRSref.IsSame( &vectorOGRSref ) ) || ( imageProjectionRef.empty() && imageKwl.GetSize() == 0) ) doReproj = false; - + if (doReproj) { inputGeomSet = GeometriesType::New(vectors); @@ -407,7 +405,7 @@ private: // Create output dataset for sample positions otb::ogr::DataSource::Pointer outputSamples = otb::ogr::DataSource::New(this->GetParameterString("out"),otb::ogr::DataSource::Modes::Overwrite); - + switch (this->GetParameterInt("sampler")) { // periodic @@ -426,7 +424,7 @@ private: periodicFilt->SetSamplerParameters(param); if (IsParameterEnabled("mask") && HasValue("mask")) { - periodicFilt->SetMask(this->GetParameterImage<UInt8ImageType>("mask")); + periodicFilt->SetMask(this->GetParameterUInt8Image("mask")); } periodicFilt->GetStreamer()->SetAutomaticTiledStreaming(this->GetParameterInt("ram")); AddProcess(periodicFilt->GetStreamer(),"Selecting positions with periodic sampler..."); @@ -444,7 +442,7 @@ private: randomFilt->SetLayerIndex(this->GetParameterInt("layer")); if (IsParameterEnabled("mask") && HasValue("mask")) { - randomFilt->SetMask(this->GetParameterImage<UInt8ImageType>("mask")); + randomFilt->SetMask(this->GetParameterUInt8Image("mask")); } randomFilt->GetStreamer()->SetAutomaticTiledStreaming(this->GetParameterInt("ram")); AddProcess(randomFilt->GetStreamer(),"Selecting positions with random sampler..."); diff --git a/Modules/Applications/AppClassification/test/CMakeLists.txt b/Modules/Applications/AppClassification/test/CMakeLists.txt index 9d40b00dd166e3d5230b30cb62792ebceb8ad6a9..6a05178e64311574862ceaf555fcff1310111815 100644 --- a/Modules/Applications/AppClassification/test/CMakeLists.txt +++ b/Modules/Applications/AppClassification/test/CMakeLists.txt @@ -179,6 +179,9 @@ foreach(classifier ${classifierList}) VALID ${valid} ) + set_tests_properties(apTvClTrainMethod${classifier}ImagesClassifierQB1 PROPERTIES + RESOURCE_LOCK ${INPUTDATA}/Classification/VectorData_${${lclassifier}_input}QB1_utm31n${vector_input_format}) + if(${_classifier_has_baseline} EQUAL -1) set(valid ${ascii_confmat_comparison} ${ascii_ref_path}/${OUTCONFMATFILE} ${TEMP}/${OUTCONFMATFILE}) else() diff --git a/Modules/Applications/AppImageUtils/app/otbManageNoData.cxx b/Modules/Applications/AppImageUtils/app/otbManageNoData.cxx index 561131caab6a86f6d21c50695838fb4ba0821fe2..4cd2b5f917dfdf22963006931c5bcd91b583bee8 100644 --- a/Modules/Applications/AppImageUtils/app/otbManageNoData.cxx +++ b/Modules/Applications/AppImageUtils/app/otbManageNoData.cxx @@ -50,7 +50,7 @@ public: /** Filters typedef */ typedef otb::ImageToNoDataMaskFilter<FloatVectorImageType,UInt8ImageType> FilterType; typedef otb::ChangeNoDataValueFilter<FloatVectorImageType,FloatVectorImageType> ChangeNoDataFilterType; - + typedef otb::ImageList<FloatImageType> ImageListType; typedef otb::VectorImageToImageListFilter<FloatVectorImageType,ImageListType> VectorToListFilterType; typedef otb::ImageListToVectorImageFilter<ImageListType,FloatVectorImageType> ListToVectorFilterType; @@ -81,12 +81,12 @@ private: AddParameter(ParameterType_Bool,"usenan", "Consider NaN as no-data"); SetParameterDescription("usenan","If active, the application will consider NaN as no-data values as well"); - + AddParameter(ParameterType_Choice,"mode","No-data handling mode"); SetParameterDescription("mode","Allows choosing between different no-data handling options"); AddChoice("mode.buildmask","Build a no-data Mask"); - + AddParameter(ParameterType_Float,"mode.buildmask.inv","Inside Value"); SetParameterDescription("mode.buildmask.inv","Value given in the output mask to pixels that are not no data pixels"); SetDefaultParameterInt("mode.buildmask.inv",1); @@ -132,7 +132,7 @@ private: void DoExecute() override { FloatVectorImageType::Pointer inputPtr = this->GetParameterImage("in"); - + m_Filter = FilterType::New(); m_Filter->SetInsideValue(this->GetParameterFloat("mode.buildmask.inv")); m_Filter->SetOutsideValue(this->GetParameterFloat("mode.buildmask.outv")); @@ -146,7 +146,7 @@ private: std::vector<double> newNoData(inputPtr->GetNumberOfComponentsPerPixel(),GetParameterFloat("mode.changevalue.newv")); m_ChangeNoDataFilter->SetNewNoDataValues(newNoData); - + if(GetParameterString("mode") == "buildmask") { SetParameterOutputImage("out",m_Filter->GetOutput()); @@ -158,7 +158,7 @@ private: else if (GetParameterString("mode") == "apply") { m_MaskFilters.clear(); - UInt8ImageType::Pointer maskPtr = this->GetParameterImage<UInt8ImageType>("mode.apply.mask"); + UInt8ImageType::Pointer maskPtr = this->GetParameterUInt8Image("mode.apply.mask"); unsigned int nbBands = inputPtr->GetNumberOfComponentsPerPixel(); itk::MetaDataDictionary &dict = inputPtr->GetMetaDataDictionary(); std::vector<bool> flags; @@ -221,4 +221,3 @@ private: } OTB_APPLICATION_EXPORT(otb::Wrapper::ManageNoData) - diff --git a/Modules/Applications/AppProjection/test/CMakeLists.txt b/Modules/Applications/AppProjection/test/CMakeLists.txt index e9d4c8a0de20aea3cfcbbd79a9106573c68fd173..28b843b2157b84c32720f2a218302b9e36942f2b 100644 --- a/Modules/Applications/AppProjection/test/CMakeLists.txt +++ b/Modules/Applications/AppProjection/test/CMakeLists.txt @@ -343,7 +343,8 @@ otb_test_application(NAME apTvPrConvertSensorToGeoPoint TESTENVOPTIONS ${TEMP}/apTvPrConvertSensorToGeoPoint.txt VALID --compare-ascii ${EPSILON_7} ${BASELINE_FILES}/apTvPrConvertSensorToGeoPoint.txt - ${TEMP}/apTvPrConvertSensorToGeoPoint.txt) + ${TEMP}/apTvPrConvertSensorToGeoPoint.txt + --ignore-lines-with 2 town country) #----------- Superimpose TESTS ---------------- diff --git a/Modules/Applications/AppSegmentation/app/otbLargeScaleMeanShift.cxx b/Modules/Applications/AppSegmentation/app/otbLargeScaleMeanShift.cxx index 8f09d36adf5f74b938dfe1e838e49aa8fbf233a5..bc414d0f2081c4d6d9a7951ea079b24318838cea 100644 --- a/Modules/Applications/AppSegmentation/app/otbLargeScaleMeanShift.cxx +++ b/Modules/Applications/AppSegmentation/app/otbLargeScaleMeanShift.cxx @@ -33,7 +33,7 @@ namespace Wrapper * * This application gathers the 4 steps of the large-scale MeanShift * segmentation framework. - * + * */ class LargeScaleMeanShift : public CompositeApplication { @@ -191,13 +191,11 @@ private: if (IsParameterEnabled("mode.vector.imfield") && HasValue("mode.vector.imfield")) { - GetInternalApplication("vectorization")->SetParameterInputImage("in", - GetParameterImage<ImageBaseType>("mode.vector.imfield")); + GetInternalApplication("vectorization")->SetParameterInputImage("in", GetParameterImageBase("mode.vector.imfield")); } else { - GetInternalApplication("vectorization")->SetParameterInputImage("in", - GetParameterImage<ImageBaseType>("in")); + GetInternalApplication("vectorization")->SetParameterInputImage("in", GetParameterImageBase("in")); } GetInternalApplication("vectorization")->SetParameterString("inseg", tmpFilenames[2]); diff --git a/Modules/Learning/LearningBase/test/otbSharkUtilsTests.cxx b/Modules/Learning/LearningBase/test/otbSharkUtilsTests.cxx index c393293300a13191943abd41fd4ce474a262b3dd..c11ee59e541a0a3068111155cbe20d02b5847fbf 100644 --- a/Modules/Learning/LearningBase/test/otbSharkUtilsTests.cxx +++ b/Modules/Learning/LearningBase/test/otbSharkUtilsTests.cxx @@ -25,8 +25,8 @@ int otbSharkNormalizeLabels(int itkNotUsed(argc), char* itkNotUsed(argv) []) { std::vector<unsigned int> inLabels = {2, 2, 3, 20, 1}; - std::vector<unsigned int> expectedDictionary = {2, 3, 20, 1}; - std::vector<unsigned int> expectedLabels = {0, 0, 1, 2, 3}; + std::vector<unsigned int> expectedDictionary = {1, 2, 3, 20}; + std::vector<unsigned int> expectedLabels = {1, 1, 2, 3, 0}; auto newLabels = inLabels; std::vector<unsigned int> labelDict; diff --git a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.hxx index 81d02c885d6413a94636e549a442b51830fabf74..b59e079182e4ac3ea894c203ee7c6350159bdebb 100644 --- a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.hxx +++ b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.hxx @@ -53,6 +53,7 @@ SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> this->m_IsRegressionSupported = false; this->m_IsDoPredictBatchMultiThreaded = true; this->m_NormalizeClassLabels = true; + this->m_ComputeMargin = false; } diff --git a/Modules/Remote/temporal-gapfilling.remote.cmake b/Modules/Remote/temporal-gapfilling.remote.cmake index 0939185711b629f2a54a2648ab9935c1759d20b2..6e7b1f77e7fa8e49fab0e3e141729f5083af4c62 100644 --- a/Modules/Remote/temporal-gapfilling.remote.cmake +++ b/Modules/Remote/temporal-gapfilling.remote.cmake @@ -26,6 +26,5 @@ A more detailed description can be found on the project website: https://gitlab.orfeo-toolbox.org/jinglada/temporalgapfilling " GIT_REPOSITORY https://gitlab.orfeo-toolbox.org/jinglada/temporalgapfilling.git - # Commit on develop branch which includes patches for Windows support - GIT_TAG 9d97764f0411de1a32dd5e0a90bdcdd8adfa049f + GIT_TAG master ) diff --git a/Modules/ThirdParty/Shark/include/otbSharkUtils.h b/Modules/ThirdParty/Shark/include/otbSharkUtils.h index da56981943b33203ea3f2d5cc442d3bd737395e3..4ab8c0fdfe62e2f8a97638271354f684ea6b9f87 100644 --- a/Modules/ThirdParty/Shark/include/otbSharkUtils.h +++ b/Modules/ThirdParty/Shark/include/otbSharkUtils.h @@ -135,13 +135,18 @@ template <class T> void ListSampleToSharkVector(const T * listSample, std::vecto } /** Shark assumes that labels are 0 ... (nbClasses-1). This function modifies the labels contained in the input vector and returns a vector with size = nbClasses which allows the translation from the normalised labels to the new ones oldLabel = dictionary[newLabel]. +When we want to generate the image containing the probability for each class, we need to ensure that the probabilities are in the correct order wrt the incoming labels. We therefore sort the labels before building the encoding. */ template <typename T> void NormalizeLabelsAndGetDictionary(std::vector<T>& labels, std::vector<T>& dictionary) { + std::vector<T> sorted_labels = labels; + std::sort(std::begin(sorted_labels), std::end(sorted_labels)); + auto last = std::unique(std::begin(sorted_labels), std::end(sorted_labels)); + sorted_labels.erase(last, std::end(sorted_labels)); std::unordered_map<T, T> dictMap; T labelCount{0}; - for(const auto& l : labels) + for(const auto& l : sorted_labels) { if(dictMap.find(l)==dictMap.end()) dictMap.insert({l, labelCount++}); diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h index d53f70c266f4b9e8f59aa68ee033ba2fd384dfb8..3baadd6f0f747b5f640b284fd3bd6a7aeab79254 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h @@ -765,13 +765,13 @@ public: void SetParameterImageBase(const std::string & key, ImageBaseType* img, unsigned int idx = 0); /** - Register all ProcessObject that are linked to parameters : + Register all ProcessObject that are linked to parameters : \li ParameterType_OutputImage \li ParameterType_OutputVectorData - Those ProcessObjects are stored in the m_Filters set and are deleted at the + Those ProcessObjects are stored in the m_Filters set and are deleted at the end of ExecuteAndWriteOutput (if there are only held by the set) - This method can be called just before the end of a DoExecute in a derived + This method can be called just before the end of a DoExecute in a derived class of Application. */ void RegisterPipeline(); @@ -850,21 +850,7 @@ protected: * \li ParameterType_InputImage */ template <class TImageType> - TImageType* GetParameterImage(std::string parameter) - { - typename TImageType::Pointer ret; - Parameter* param = GetParameterByKey(parameter); - InputImageParameter* paramDown = dynamic_cast<InputImageParameter*>(param); - if (paramDown) - { - return paramDown->GetImage<TImageType>(); - } - else - { - itkExceptionMacro(<<parameter << " parameter can't be casted to ImageType"); - return nullptr; - } - } + TImageType* GetParameterImage(std::string parameter); /** Declare a parameter as having an automatic value */ void AutomaticValueOn(std::string paramKey); @@ -878,16 +864,7 @@ protected: * \li ParameterType_OutputImage */ template <class TImageType> - void SetParameterOutputImage(std::string parameter, TImageType* value) - { - Parameter* param = GetParameterByKey(parameter); - - if (dynamic_cast<OutputImageParameter*>(param)) - { - OutputImageParameter* paramDown = dynamic_cast<OutputImageParameter*>(param); - paramDown->SetValue(value); - } - } + void SetParameterOutputImage(std::string parameter, TImageType* value); private: /* Implement this method to add parameters */ @@ -963,9 +940,90 @@ private: } //end namespace otb -//#ifndef OTB_MANUAL_INSTANTIATION -//#include "otbWrapperApplication.hxx" -//#endif +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbWrapperApplication.hxx" +#endif + + +namespace otb +{ +namespace Wrapper +{ + +extern template OTBApplicationEngine_EXPORT_TEMPLATE UInt8VectorImageType* Application::GetParameterImage<UInt8VectorImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE Int16VectorImageType* Application::GetParameterImage<Int16VectorImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE UInt16VectorImageType* Application::GetParameterImage<UInt16VectorImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE Int32VectorImageType* Application::GetParameterImage<Int32VectorImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE UInt32VectorImageType* Application::GetParameterImage<UInt32VectorImageType>(std::string); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE FloatVectorImageType* Application::GetParameterImage<FloatVectorImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE DoubleVectorImageType* Application::GetParameterImage<DoubleVectorImageType>(std::string); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE ComplexInt16VectorImageType* Application::GetParameterImage<ComplexInt16VectorImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE ComplexInt32VectorImageType* Application::GetParameterImage<ComplexInt32VectorImageType>(std::string); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE ComplexFloatVectorImageType* Application::GetParameterImage<ComplexFloatVectorImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE ComplexDoubleVectorImageType* Application::GetParameterImage<ComplexDoubleVectorImageType>(std::string); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE UInt8RGBImageType* Application::GetParameterImage<UInt8RGBImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE UInt8RGBAImageType* Application::GetParameterImage<UInt8RGBAImageType>(std::string); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE UInt8ImageType* Application::GetParameterImage<UInt8ImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE Int16ImageType* Application::GetParameterImage<Int16ImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE UInt16ImageType* Application::GetParameterImage<UInt16ImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE Int32ImageType* Application::GetParameterImage<Int32ImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE UInt32ImageType* Application::GetParameterImage<UInt32ImageType>(std::string); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE FloatImageType* Application::GetParameterImage<FloatImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE DoubleImageType* Application::GetParameterImage<DoubleImageType>(std::string); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE ComplexInt16ImageType* Application::GetParameterImage<ComplexInt16ImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE ComplexInt32ImageType* Application::GetParameterImage<ComplexInt32ImageType>(std::string); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE ComplexFloatImageType* Application::GetParameterImage<ComplexFloatImageType>(std::string); +extern template OTBApplicationEngine_EXPORT_TEMPLATE ComplexDoubleImageType* Application::GetParameterImage<ComplexDoubleImageType>(std::string); + +// + +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<UInt8VectorImageType>(std::string, UInt8VectorImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<Int16VectorImageType>(std::string, Int16VectorImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<UInt16VectorImageType>(std::string, UInt16VectorImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<Int32VectorImageType>(std::string, Int32VectorImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<UInt32VectorImageType>(std::string, UInt32VectorImageType*); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<FloatVectorImageType>(std::string, FloatVectorImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<DoubleVectorImageType>(std::string, DoubleVectorImageType*); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<ComplexInt16VectorImageType>(std::string, + ComplexInt16VectorImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<ComplexInt32VectorImageType>(std::string, + ComplexInt32VectorImageType*); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<ComplexFloatVectorImageType>(std::string, + ComplexFloatVectorImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<ComplexDoubleVectorImageType>(std::string, + ComplexDoubleVectorImageType*); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<UInt8RGBImageType>(std::string, UInt8RGBImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<UInt8RGBAImageType>(std::string, UInt8RGBAImageType*); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<UInt8ImageType>(std::string, UInt8ImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<Int16ImageType>(std::string, Int16ImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<UInt16ImageType>(std::string, UInt16ImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<Int32ImageType>(std::string, Int32ImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<UInt32ImageType>(std::string, UInt32ImageType*); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<FloatImageType>(std::string, FloatImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<DoubleImageType>(std::string, DoubleImageType*); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<ComplexInt16ImageType>(std::string, ComplexInt16ImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<ComplexInt32ImageType>(std::string, ComplexInt32ImageType*); + +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<ComplexFloatImageType>(std::string, ComplexFloatImageType*); +extern template OTBApplicationEngine_EXPORT_TEMPLATE void Application::SetParameterOutputImage<ComplexDoubleImageType>(std::string, ComplexDoubleImageType*); + +} // namespace Wrapper +} // namespace otb #endif // otbWrapperApplication_h_ diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.hxx b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.hxx new file mode 100644 index 0000000000000000000000000000000000000000..33330cd2418fa7c81e506806d6a43b3d9d583f23 --- /dev/null +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.hxx @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) + * + * This file is part of Orfeo Toolbox + * + * https://www.orfeo-toolbox.org/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef otbWrapperApplication_hxx +#define otbWrapperApplication_hxx + + +#include "otbWrapperApplication.h" + + +namespace otb +{ + + +namespace Wrapper +{ + + +template <class TImageType> +TImageType* +Application +::GetParameterImage(std::string parameter) + +{ + typename TImageType::Pointer ret; + Parameter* param = GetParameterByKey(parameter); + InputImageParameter* paramDown = dynamic_cast<InputImageParameter*>(param); + if (paramDown) + { + return paramDown->GetImage<TImageType>(); + } + else + { + itkExceptionMacro(<<parameter << " parameter can't be casted to ImageType"); + return nullptr; + } +} + + +template <class TImageType> +void +Application +::SetParameterOutputImage(std::string parameter, TImageType* value) +{ + Parameter* param = GetParameterByKey(parameter); + + if (dynamic_cast<OutputImageParameter*>(param)) + { + OutputImageParameter* paramDown = dynamic_cast<OutputImageParameter*>(param); + paramDown->SetValue(value); + } +} + + +} // End namespace Wrapper + +} // End namespace otb + +#endif diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperCastImage.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperCastImage.h new file mode 100644 index 0000000000000000000000000000000000000000..0e975d7adc2fea303e776ad7202cda5e7852f689 --- /dev/null +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperCastImage.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) + * + * This file is part of Orfeo Toolbox + * + * https://www.orfeo-toolbox.org/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef otbWrapperCastimage_h +#define otbWrapperCastimage_h + + +#include "otbClampImageFilter.h" + +#include "OTBApplicationEngineExport.h" + +#include "otbWrapperTypes.h" + + +namespace otb +{ +namespace Wrapper +{ +namespace details +{ + +/** \class CastImage + * \brief Helper class (private) which casts and clamps input-image type into + * output-image type. + * + * \ingroup OTBApplicationEngine + */ +template <typename TOutputImage, typename TInputImage> +struct OTBApplicationEngine_EXPORT_TEMPLATE CastImage +{ + /** Input clamping */ + using InputClampImageFilter = ClampImageFilter<TInputImage, DoubleVectorImageType>; + + /** Output clamping */ + using OutputClampImageFilter = ClampImageFilter<DoubleVectorImageType, TOutputImage>; + + + /** Constructor. */ + CastImage(TInputImage* in) : icif(InputClampImageFilter::New()), ocif(OutputClampImageFilter::New()), out(ocif->GetOutput()) + { + assert(in); + + icif->SetInput(in); + + ocif->SetInput(icif->GetOutput()); + } + + /** Input-image clamp filter. */ + typename InputClampImageFilter::Pointer icif; + + /** Output-image clamp filter. */ + typename OutputClampImageFilter::Pointer ocif; + + /** Output image. */ + TOutputImage* out; +}; + + +/** \class CastImage + * \brief Partial template specialization which optimizes processing + * pipeline when input-image is DoubleVectorImageType. + * + * \ingroup OTBApplicationEngine + */ +template <typename TOutputImage> +struct OTBApplicationEngine_EXPORT_TEMPLATE CastImage<TOutputImage, DoubleVectorImageType> +{ + /** Output clamping */ + using OutputClampImageFilter = ClampImageFilter<DoubleVectorImageType, TOutputImage>; + + + /** Constructor. */ + CastImage(DoubleVectorImageType* in) : ocif(OutputClampImageFilter::New()), out(ocif->GetOutput()) + { + assert(in); + + ocif->SetInput(in); + } + + /** Input-image clamp filter. */ + itk::ProcessObject::Pointer icif; + + /** Output-image clamp filter. */ + typename OutputClampImageFilter::Pointer ocif; + + /** Output image. */ + TOutputImage* out; +}; + + +/** \class CastImage + * \brief Template specialization which optimizes the processing + * pipeline when input-image and output-image types are identical. + * + * \ingroup OTBApplicationEngine + */ +template <typename T> +struct OTBApplicationEngine_EXPORT_TEMPLATE CastImage<T, T> +{ + CastImage(T* in) : out(in) + { + assert(in); + } + + itk::ProcessObject::Pointer icif; + itk::ProcessObject::Pointer ocif; + T* out; +}; + + +/** \class CastImage + * \brief Template specialization which optimizes the processing + * pipeline when input-image and output-image types are identical. + * + * \ingroup OTBApplicationEngine + */ +template <> +struct OTBApplicationEngine_EXPORT_TEMPLATE CastImage<DoubleVectorImageType, DoubleVectorImageType> +{ + CastImage(DoubleVectorImageType* in) : out(in) + { + assert(in); + } + + itk::ProcessObject::Pointer icif; + itk::ProcessObject::Pointer ocif; + DoubleVectorImageType* out; +}; + +} // namespace details. + +} // namespace Wrapper + +} // namespace otb + +#endif diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperInputImageParameter.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperInputImageParameter.h index 80aefb371880dc53c0272de0496152b26f0c7a79..a49e4c2bfb477da878372e778b3174755361d5d3 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperInputImageParameter.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperInputImageParameter.h @@ -21,9 +21,13 @@ #ifndef otbWrapperInputImageParameter_h #define otbWrapperInputImageParameter_h + #include "otbImageFileReader.h" -#include "itkImageBase.h" +#include "otbClampImageFilter.h" #include "otbWrapperParameter.h" + +#include "itkImageBase.h" + #include <string> namespace otb @@ -56,27 +60,28 @@ public: itkGetConstReferenceMacro( FileName, std::string ); - /** Get the input image as FloatVectorImageType. */ - FloatVectorImageType* GetImage(); + /** Get input-image as ImageBaseType. */ + ImageBaseType const* GetImage() const; + ImageBaseType* GetImage(); /** Get the input image as XXXImageType */ - UInt8ImageType* GetUInt8Image(); + UInt8ImageType* GetUInt8Image(); UInt16ImageType* GetUInt16Image(); - Int16ImageType* GetInt16Image(); + Int16ImageType* GetInt16Image(); UInt32ImageType* GetUInt32Image(); - Int32ImageType* GetInt32Image(); - FloatImageType* GetFloatImage(); + Int32ImageType* GetInt32Image(); + FloatImageType* GetFloatImage(); DoubleImageType* GetDoubleImage(); - UInt8VectorImageType* GetUInt8VectorImage(); + UInt8VectorImageType* GetUInt8VectorImage(); UInt16VectorImageType* GetUInt16VectorImage(); - Int16VectorImageType* GetInt16VectorImage(); + Int16VectorImageType* GetInt16VectorImage(); UInt32VectorImageType* GetUInt32VectorImage(); - Int32VectorImageType* GetInt32VectorImage(); - FloatVectorImageType* GetFloatVectorImage(); + Int32VectorImageType* GetInt32VectorImage(); + FloatVectorImageType* GetFloatVectorImage(); DoubleVectorImageType* GetDoubleVectorImage(); - UInt8RGBImageType* GetUInt8RGBImage(); + UInt8RGBImageType* GetUInt8RGBImage(); UInt8RGBAImageType* GetUInt8RGBAImage(); // Complex image @@ -94,12 +99,8 @@ public: template <class TImageType> TImageType* GetImage(); - /** Set a FloatVectorImageType image.*/ - void SetImage(FloatVectorImageType* image); - /** Set a templated image.*/ - template <class TImageType> - void SetImage(TImageType* image); + void SetImage(ImageBaseType* image); /** Generic cast method that will be specified for each image type. */ @@ -120,48 +121,30 @@ protected: /** Destructor */ ~InputImageParameter() override; - ImageBaseType::Pointer m_Image; - std::string m_FileName; - - /** Readers typedefs */ - - typedef otb::ImageFileReader<UInt8ImageType> UInt8ReaderType; - typedef otb::ImageFileReader<Int16ImageType> Int16ReaderType; - typedef otb::ImageFileReader<UInt16ImageType> UInt16ReaderType; - typedef otb::ImageFileReader<Int32ImageType> Int32ReaderType; - typedef otb::ImageFileReader<UInt32ImageType> UInt32ReaderType; - typedef otb::ImageFileReader<FloatImageType> FloatReaderType; - typedef otb::ImageFileReader<DoubleImageType> DoubleReaderType; - - typedef otb::ImageFileReader<UInt8VectorImageType> UInt8VectorReaderType; - typedef otb::ImageFileReader<Int16VectorImageType> Int16VectorReaderType; - typedef otb::ImageFileReader<UInt16VectorImageType> UInt16VectorReaderType; - typedef otb::ImageFileReader<Int32VectorImageType> Int32VectorReaderType; - typedef otb::ImageFileReader<UInt32VectorImageType> UInt32VectorReaderType; - typedef otb::ImageFileReader<FloatVectorImageType> FloatVectorReaderType; - typedef otb::ImageFileReader<DoubleVectorImageType> DoubleVectorReaderType; +private: + InputImageParameter(const Parameter&) = delete; + void operator=(const Parameter&) = delete; + std::string m_FileName; + itk::ProcessObject::Pointer m_Reader; - typedef otb::ImageFileReader<UInt8RGBImageType> UInt8RGBReaderType; - typedef otb::ImageFileReader<UInt8RGBAImageType> UInt8RGBAReaderType; + ImageBaseType::Pointer m_Image; - // Complex - typedef otb::ImageFileReader<ComplexInt16ImageType> ComplexInt16ReaderType; - typedef otb::ImageFileReader<ComplexInt32ImageType> ComplexInt32ReaderType; - typedef otb::ImageFileReader<ComplexFloatImageType> ComplexFloatReaderType; - typedef otb::ImageFileReader<ComplexDoubleImageType> ComplexDoubleReaderType; + itk::ProcessObject::Pointer m_InputCaster; + itk::ProcessObject::Pointer m_OutputCaster; - typedef otb::ImageFileReader<ComplexInt16VectorImageType> ComplexInt16VectorReaderType; - typedef otb::ImageFileReader<ComplexInt32VectorImageType> ComplexInt32VectorReaderType; - typedef otb::ImageFileReader<ComplexFloatVectorImageType> ComplexFloatVectorReaderType; - typedef otb::ImageFileReader<ComplexDoubleVectorImageType> ComplexDoubleVectorReaderType; +private: + /** */ + template <typename T> + using InputClampImageFilter = ClampImageFilter<T, otb::Wrapper::DoubleVectorImageType>; - itk::ProcessObject::Pointer m_Reader; - itk::ProcessObject::Pointer m_Caster; + /** */ + template <typename T> + using OutputClampImageFilter = ClampImageFilter<otb::Wrapper::DoubleVectorImageType, T>; -private: - InputImageParameter(const Parameter &) = delete; - void operator =(const Parameter&) = delete; + /** */ + template <typename TOutputImage, typename TInputImage> + TOutputImage* Cast(TInputImage*); /** Store the loaded image filename */ std::string m_PreviousFileName; diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperInputImageParameter.hxx b/Modules/Wrappers/ApplicationEngine/include/otbWrapperInputImageParameter.hxx index eb0f507910c6baf093bcb2297784fa6bad00f35c..37ffbd7efae807466a60d05f708ea29ac271c49f 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperInputImageParameter.hxx +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperInputImageParameter.hxx @@ -23,7 +23,7 @@ #include "otbWrapperInputImageParameter.h" -#include "otbClampImageFilter.h" +#include "otbWrapperCastImage.h" namespace otb { @@ -31,7 +31,70 @@ namespace Wrapper { -#define INPUT_IMAGE_PARAMETER_GET_IMAGE_EXCEPTION 0 +#define CLAMP_IMAGE_IF( Out, In, image_base ) \ + { \ + In * in_image = dynamic_cast< In * >( image_base ); \ + \ + if( in_image ) \ + return Cast< Out, In >( in_image ); \ + } + +#define CLAMP_IMAGE_BASE( T, image_base ) \ + { \ + CLAMP_IMAGE_IF( T, UInt8VectorImageType, image_base ); \ + CLAMP_IMAGE_IF( T, Int16VectorImageType, image_base ); \ + CLAMP_IMAGE_IF( T, UInt16VectorImageType, image_base ); \ + CLAMP_IMAGE_IF( T, Int32VectorImageType, image_base ); \ + CLAMP_IMAGE_IF( T, UInt32VectorImageType, image_base ); \ + \ + CLAMP_IMAGE_IF( T, FloatVectorImageType, image_base ); \ + CLAMP_IMAGE_IF( T, DoubleVectorImageType, image_base ); \ + \ + CLAMP_IMAGE_IF( T, ComplexInt16VectorImageType, image_base ); \ + CLAMP_IMAGE_IF( T, ComplexInt32VectorImageType, image_base ); \ + \ + CLAMP_IMAGE_IF( T, ComplexFloatVectorImageType, image_base ); \ + CLAMP_IMAGE_IF( T, ComplexDoubleVectorImageType, image_base ); \ + \ + CLAMP_IMAGE_IF( T, UInt8RGBImageType, image_base ); \ + CLAMP_IMAGE_IF( T, UInt8RGBAImageType, image_base ); \ + \ + CLAMP_IMAGE_IF( T, UInt8ImageType, image_base ); \ + CLAMP_IMAGE_IF( T, Int16ImageType, image_base ); \ + CLAMP_IMAGE_IF( T, UInt16ImageType, image_base ); \ + CLAMP_IMAGE_IF( T, Int32ImageType, image_base ); \ + CLAMP_IMAGE_IF( T, UInt32ImageType, image_base ); \ + \ + CLAMP_IMAGE_IF( T, FloatImageType, image_base ); \ + CLAMP_IMAGE_IF( T, DoubleImageType, image_base ); \ + \ + CLAMP_IMAGE_IF( T, ComplexInt16ImageType, image_base ); \ + CLAMP_IMAGE_IF( T, ComplexInt32ImageType, image_base ); \ + \ + CLAMP_IMAGE_IF( T, ComplexFloatImageType, image_base ); \ + CLAMP_IMAGE_IF( T, ComplexDoubleImageType, image_base ); \ + \ + return nullptr; \ + } + + +template< typename TOutputImage, + typename TInputImage > +TOutputImage * +InputImageParameter +::Cast( TInputImage * image ) +{ + details::CastImage< TOutputImage, TInputImage > clamp( image ); + + if( clamp.ocif ) + clamp.ocif->UpdateOutputInformation(); + + m_InputCaster = clamp.icif; + m_OutputCaster = clamp.ocif; + + return clamp.out; +} + template <class TImageType> TImageType* @@ -68,10 +131,6 @@ InputImageParameter::GetImage() } else { -#if INPUT_IMAGE_PARAMETER_GET_IMAGE_EXCEPTION - return dynamic_cast< TImageType* >( m_Image.GetPointer() ); - -#else // INPUT_IMAGE_PARAMETER_GET_IMAGE_EXCEPTION // In this case, the reader and the image should already be there if (m_Image.IsNull()) { @@ -89,7 +148,6 @@ InputImageParameter::GetImage() itkExceptionMacro("Cannot ask a different image type"); } } -#endif // INPUT_IMAGE_PARAMETER_GET_IMAGE_EXCEPTION } } @@ -98,119 +156,10 @@ InputImageParameter::GetImage() //////////////////////// Image case: if (m_Image.IsNull()) { -#if INPUT_IMAGE_PARAMETER_GET_IMAGE_EXCEPTION - itkExceptionMacro("No input image or filename detected..."); -#else return nullptr; -#endif } else - { - if (dynamic_cast<UInt8ImageType*> (m_Image.GetPointer())) - { - return CastImage<UInt8ImageType, TImageType> (); - } - else if (dynamic_cast<Int16ImageType*> (m_Image.GetPointer())) - { - return CastImage<Int16ImageType, TImageType> (); - } - else if (dynamic_cast<UInt16ImageType*> (m_Image.GetPointer())) - { - return CastImage<UInt16ImageType, TImageType> (); - } - else if (dynamic_cast<Int32ImageType*> (m_Image.GetPointer())) - { - return CastImage<Int32ImageType, TImageType> (); - } - else if (dynamic_cast<UInt32ImageType*> (m_Image.GetPointer())) - { - return CastImage<UInt32ImageType, TImageType> (); - } - else if (dynamic_cast<FloatImageType*> (m_Image.GetPointer())) - { - return CastImage<FloatImageType, TImageType> (); - } - else if (dynamic_cast<DoubleImageType*> (m_Image.GetPointer())) - { - return CastImage<DoubleImageType, TImageType> (); - } - else if (dynamic_cast<ComplexInt16ImageType*>(m_Image.GetPointer())) - { - return CastImage<ComplexInt16ImageType, TImageType>(); - } - else if (dynamic_cast<ComplexInt32ImageType*>(m_Image.GetPointer())) - { - return CastImage<ComplexInt32ImageType, TImageType>(); - } - else if (dynamic_cast<ComplexFloatImageType*>(m_Image.GetPointer())) - { - return CastImage<ComplexFloatImageType, TImageType>(); - } - else if (dynamic_cast<ComplexDoubleImageType*>(m_Image.GetPointer())) - { - return CastImage<ComplexDoubleImageType, TImageType>(); - } - else if (dynamic_cast<UInt8VectorImageType*> (m_Image.GetPointer())) - { - return CastImage<UInt8VectorImageType, TImageType> (); - } - else if (dynamic_cast<Int16VectorImageType*> (m_Image.GetPointer())) - { - return CastImage<Int16VectorImageType, TImageType> (); - } - else if (dynamic_cast<UInt16VectorImageType*> (m_Image.GetPointer())) - { - return CastImage<UInt16VectorImageType, TImageType> (); - } - else if (dynamic_cast<Int32VectorImageType*> (m_Image.GetPointer())) - { - return CastImage<Int32VectorImageType, TImageType> (); - } - else if (dynamic_cast<UInt32VectorImageType*> (m_Image.GetPointer())) - { - return CastImage<UInt32VectorImageType, TImageType> (); - } - else if (dynamic_cast<FloatVectorImageType*> (m_Image.GetPointer())) - { - return CastImage<FloatVectorImageType, TImageType> (); - } - else if (dynamic_cast<DoubleVectorImageType*> (m_Image.GetPointer())) - { - return CastImage<DoubleVectorImageType, TImageType> (); - } - else if (dynamic_cast<UInt8RGBAImageType*> (m_Image.GetPointer())) - { - return CastImage<UInt8RGBAImageType, TImageType> (); - } - else if (dynamic_cast<UInt8RGBImageType*> (m_Image.GetPointer())) - { - return CastImage<UInt8RGBImageType, TImageType> (); - } - else if (dynamic_cast<ComplexInt16VectorImageType*>(m_Image.GetPointer())) - { - return CastImage<ComplexInt16VectorImageType, TImageType>(); - } - else if (dynamic_cast<ComplexInt32VectorImageType*>(m_Image.GetPointer())) - { - return CastImage<ComplexInt32VectorImageType, TImageType>(); - } - else if (dynamic_cast<ComplexFloatVectorImageType*>(m_Image.GetPointer())) - { - return CastImage<ComplexFloatVectorImageType, TImageType>(); - } - else if (dynamic_cast<ComplexDoubleVectorImageType*>(m_Image.GetPointer())) - { - return CastImage<ComplexDoubleVectorImageType, TImageType>(); - } - else - { -#if INPUT_IMAGE_PARAMETER_GET_IMAGE_EXCEPTION - itkExceptionMacro("Unknown image type"); -#else - return nullptr; -#endif - } - } + CLAMP_IMAGE_BASE( TImageType, m_Image.GetPointer() ); } } @@ -221,41 +170,6 @@ ImageBaseType* InputImageParameter::GetImage<ImageBaseType>(); -template <class TInputImage, class TOutputImage> -TOutputImage* -InputImageParameter::CastImage() -{ - if ( dynamic_cast<TOutputImage*> (m_Image.GetPointer()) ) - { - return dynamic_cast<TOutputImage*> (m_Image.GetPointer()); - } - else - { - TInputImage* realInputImage = dynamic_cast<TInputImage*>(m_Image.GetPointer()); - - typedef ClampImageFilter<TInputImage, TOutputImage> CasterType; - typename CasterType::Pointer caster = CasterType::New(); - - caster->SetInput(realInputImage); - caster->UpdateOutputInformation(); - - m_Image = caster->GetOutput(); - m_Caster = caster; - - return caster->GetOutput(); - } - // itkExceptionMacro("Cast from "<<typeid(TInputImage).name()<<" to "<<typeid(TOutputImage).name()<<" not authorized."); -} - -template <class TInputImage> -void -InputImageParameter::SetImage(TInputImage* image) -{ - m_UseFilename = false; - m_Image = image; -} - - } // End namespace Wrapper } // End namespace otb diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperOutputImageParameter.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperOutputImageParameter.h index 5a454d57bae108501f0822770616775ed914034e..ec7a1a8f859118d6d63c12872476647fe54b062d 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperOutputImageParameter.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperOutputImageParameter.h @@ -27,6 +27,7 @@ #include "otbImageFileWriter.h" #include <string> + namespace otb { namespace Wrapper @@ -126,36 +127,34 @@ protected: /** Destructor */ ~OutputImageParameter() override; - template <class TInput> - int SwitchInput(TInput *img); - - //FloatVectorImageType::Pointer m_Image; - ImageBaseType::Pointer m_Image; - std::string m_FileName; - ImagePixelType m_PixelType; - ImagePixelType m_DefaultPixelType; - private: OutputImageParameter(const Parameter &) = delete; void operator =(const Parameter&) = delete; - unsigned int m_RAMValue; + /** Switch TInputImage according to expected output type. */ + template <typename TInputImage> + void SwitchInput(TInputImage*); + + /** */ + template <typename TOutputImage, typename TInputImage> + void ClampAndWriteVectorImage(TInputImage*); - itk::ProcessObject::Pointer m_Caster; + // FloatVectorImageType::Pointer m_Image; + ImageBaseType::Pointer m_Image; + + itk::ProcessObject::Pointer m_InputCaster; + itk::ProcessObject::Pointer m_OutputCaster; itk::ProcessObject::Pointer m_Writer; -}; // End class OutputImage Parameter + std::string m_FileName; -// Declare specialisation for UInt8RGBAImageType -template <> -int -OutputImageParameter::SwitchInput(UInt8RGBAImageType *img); + ImagePixelType m_PixelType; + ImagePixelType m_DefaultPixelType; -// Declare specialisation for UInt8RGBImageType -template <> -int -OutputImageParameter::SwitchInput(UInt8RGBImageType *img); + unsigned int m_RAMValue; + +}; // End class OutputImage Parameter } // End namespace Wrapper } // End namespace otb diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameter.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameter.h index 0a93e62995f0dba21b7f35d89457d963d29b9c7e..6ab769e5eca20ac6d8c7b575680e32ca0b0de784 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameter.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameter.h @@ -21,13 +21,18 @@ #ifndef otbWrapperParameter_h #define otbWrapperParameter_h -#include "otbMacro.h" -#include "itkObjectFactory.h" -#include "otbWrapperTypes.h" #include "OTBApplicationEngineExport.h" +#include "otbMacro.h" +#include "otbWrapperTypes.h" + + +#include <itkObjectFactory.h> + + #include <string> + namespace otb { namespace Wrapper @@ -65,11 +70,11 @@ public: /** Set/get the parameter key */ virtual void SetKey(const std::string&); virtual const char* GetKey() const; - + /** Set the parameter Active flag */ virtual void SetActive(bool flag); bool GetActive(bool recurseParents = false) const; - + /** Set the parameter Mandatory flag */ virtual void SetMandatory(bool flag); virtual bool GetMandatory() const; @@ -78,19 +83,19 @@ public: /** Set the parameter AutomaticValue flag (which is the opposite of UserValue)*/ virtual void SetAutomaticValue(bool flag); - + /** Get the parameter AutomaticValue flag */ virtual bool GetAutomaticValue() const; - + /** Toogle ON the parameter AutomaticValue flag */ void AutomaticValueOn(); - + /** Toogle OFF the parameter AutomaticValue flag */ void AutomaticValueOff(); /** Set the user access level */ virtual void SetUserLevel(const UserLevel level); - + /** Get the user access level */ virtual UserLevel GetUserLevel() const; @@ -104,7 +109,7 @@ public: * nothing */ virtual void Reset(); - + virtual bool HasValue() const = 0; virtual bool HasUserValue() const; diff --git a/Modules/Wrappers/ApplicationEngine/src/CMakeLists.txt b/Modules/Wrappers/ApplicationEngine/src/CMakeLists.txt index 6f0b8809cb026b1b4143277ac45e41c4d9d62529..fb220c564fbe628d9e9469f6f3f438352caa6454 100644 --- a/Modules/Wrappers/ApplicationEngine/src/CMakeLists.txt +++ b/Modules/Wrappers/ApplicationEngine/src/CMakeLists.txt @@ -1,3 +1,4 @@ + # # Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) # @@ -57,6 +58,7 @@ set( OTBApplicationEngine_SRC otbWrapperBoolParameter.cxx otbWrapperMetaDataHelper.cxx otbWrapperParameter.cxx + otbWrapperCastImage.cxx otbWrapperTypes.cxx ) diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx index 8c0d624ae5e2f79bf323b3c41d3821d0ad38a5b3..4297ae946d62476a88847a9974cd5aff72526fb3 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx @@ -71,6 +71,80 @@ ExceptionObject(file, line, message, loc) namespace Wrapper { + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE UInt8VectorImageType* Application::GetParameterImage<UInt8VectorImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE Int16VectorImageType* Application::GetParameterImage<Int16VectorImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE UInt16VectorImageType* Application::GetParameterImage<UInt16VectorImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE Int32VectorImageType* Application::GetParameterImage<Int32VectorImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE UInt32VectorImageType* Application::GetParameterImage<UInt32VectorImageType>(std::string); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE FloatVectorImageType* Application::GetParameterImage<FloatVectorImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE DoubleVectorImageType* Application::GetParameterImage<DoubleVectorImageType>(std::string); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE ComplexInt16VectorImageType* Application::GetParameterImage<ComplexInt16VectorImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE ComplexInt32VectorImageType* Application::GetParameterImage<ComplexInt32VectorImageType>(std::string); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE ComplexFloatVectorImageType* Application::GetParameterImage<ComplexFloatVectorImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE ComplexDoubleVectorImageType* Application::GetParameterImage<ComplexDoubleVectorImageType>(std::string); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE UInt8RGBImageType* Application::GetParameterImage<UInt8RGBImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE UInt8RGBAImageType* Application::GetParameterImage<UInt8RGBAImageType>(std::string); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE UInt8ImageType* Application::GetParameterImage<UInt8ImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE Int16ImageType* Application::GetParameterImage<Int16ImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE UInt16ImageType* Application::GetParameterImage<UInt16ImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE Int32ImageType* Application::GetParameterImage<Int32ImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE UInt32ImageType* Application::GetParameterImage<UInt32ImageType>(std::string); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE FloatImageType* Application::GetParameterImage<FloatImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE DoubleImageType* Application::GetParameterImage<DoubleImageType>(std::string); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE ComplexInt16ImageType* Application::GetParameterImage<ComplexInt16ImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE ComplexInt32ImageType* Application::GetParameterImage<ComplexInt32ImageType>(std::string); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE ComplexFloatImageType* Application::GetParameterImage<ComplexFloatImageType>(std::string); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE ComplexDoubleImageType* Application::GetParameterImage<ComplexDoubleImageType>(std::string); + +// + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<UInt8VectorImageType>(std::string, UInt8VectorImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<Int16VectorImageType>(std::string, Int16VectorImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<UInt16VectorImageType>(std::string, UInt16VectorImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<Int32VectorImageType>(std::string, Int32VectorImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<UInt32VectorImageType>(std::string, UInt32VectorImageType*); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<FloatVectorImageType>(std::string, FloatVectorImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<DoubleVectorImageType>(std::string, DoubleVectorImageType*); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<ComplexInt16VectorImageType>(std::string, + ComplexInt16VectorImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<ComplexInt32VectorImageType>(std::string, + ComplexInt32VectorImageType*); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<ComplexFloatVectorImageType>(std::string, + ComplexFloatVectorImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<ComplexDoubleVectorImageType>(std::string, + ComplexDoubleVectorImageType*); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<UInt8RGBImageType>(std::string, UInt8RGBImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<UInt8RGBAImageType>(std::string, UInt8RGBAImageType*); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<UInt8ImageType>(std::string, UInt8ImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<Int16ImageType>(std::string, Int16ImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<UInt16ImageType>(std::string, UInt16ImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<Int32ImageType>(std::string, Int32ImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<UInt32ImageType>(std::string, UInt32ImageType*); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<FloatImageType>(std::string, FloatImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<DoubleImageType>(std::string, DoubleImageType*); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<ComplexInt16ImageType>(std::string, ComplexInt16ImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<ComplexInt32ImageType>(std::string, ComplexInt32ImageType*); + +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<ComplexFloatImageType>(std::string, ComplexFloatImageType*); +template OTBApplicationEngine_EXPORT_EXPLICIT_TEMPLATE void Application::SetParameterOutputImage<ComplexDoubleImageType>(std::string, ComplexDoubleImageType*); + + void Application::SetName( const std::string & name ) { m_Name = name; @@ -466,8 +540,7 @@ Application::RegisterPipeline() if ( GetParameterType(key) == ParameterType_OutputImage ) { Parameter* param = GetParameterByKey(key); - OutputImageParameter * outP = - dynamic_cast< OutputImageParameter * >( param ); + OutputImageParameter* outP = dynamic_cast<OutputImageParameter*>(param); itk::ImageBase< 2 > * outData = outP->GetValue(); if ( outData ) dataStack.push(outData); @@ -475,8 +548,7 @@ Application::RegisterPipeline() else if ( GetParameterType(key) == ParameterType_OutputVectorData ) { Parameter* param = GetParameterByKey(key); - OutputVectorDataParameter * outP = - dynamic_cast< OutputVectorDataParameter * >( param ); + OutputVectorDataParameter* outP = dynamic_cast<OutputVectorDataParameter*>(param); VectorDataType * outData = outP->GetValue(); if ( outData ) dataStack.push(outData); @@ -484,8 +556,7 @@ Application::RegisterPipeline() else if ( GetParameterType(key) == ParameterType_InputImage ) { Parameter* param = GetParameterByKey(key); - InputImageParameter * inP = - dynamic_cast< InputImageParameter * >( param ); + InputImageParameter* inP = dynamic_cast<InputImageParameter*>(param); if ( !inP->HasValue() ) continue; ImageBaseType * inData = inP->GetImage< ImageBaseType >(); @@ -495,13 +566,12 @@ Application::RegisterPipeline() else if ( GetParameterType(key) == ParameterType_InputImageList ) { Parameter * param = GetParameterByKey(key); - InputImageListParameter * inP = - dynamic_cast< InputImageListParameter * > ( param ); + InputImageListParameter* inP = dynamic_cast<InputImageListParameter*>(param); if ( !inP->HasValue() ) continue; const FloatVectorImageListType * list = inP->GetImageList(); - for ( auto it = list->Begin() ; it != list->End() ; ++it ) - { + for (auto it = list->Begin(); it != list->End(); ++it) + { FloatVectorImageType * inData = it.Get().GetPointer(); if ( inData && !inputData.count(inData) ) inputData.insert(inData); @@ -546,10 +616,9 @@ Application::RegisterPipeline() // if current is a list push every of its members in datastack if ( dynamic_cast< DataObjectListInterface *> (current) ) { - DataObjectListInterface * list = - dynamic_cast< DataObjectListInterface *> (current); - int length = list->Size(); - for ( int i = 0 ; i < length ; i++ ) + DataObjectListInterface* list = dynamic_cast<DataObjectListInterface*>(current); + int length = list->Size(); + for (int i = 0; i < length; i++) { itk::DataObject * newData = list->GetNthDataObject(i); if ( !current || inputData.count( current ) ) @@ -627,10 +696,9 @@ void Application::FreeRessources() // If input is a list if ( dynamic_cast< DataObjectListInterface *> (data.GetPointer()) ) { - DataObjectListInterface * list = - dynamic_cast< DataObjectListInterface *> (data.GetPointer()); - int length = list->Size(); - for ( int i = 0 ; i < length ; i++ ) + DataObjectListInterface* list = dynamic_cast<DataObjectListInterface*>(data.GetPointer()); + int length = list->Size(); + for (int i = 0; i < length; i++) { itk::DataObject * newData = list->GetNthDataObject(i); if ( !newData || dataSet.count( newData ) ) @@ -693,7 +761,7 @@ int Application::Execute() m_IsInPrivateDo = true; this->DoExecute(); m_IsInPrivateDo = false; - + // Ensure that all output image parameter have called UpdateOutputInformation() for (auto it = paramList.begin(); it != paramList.end(); ++it) { @@ -806,7 +874,7 @@ int Application::ExecuteAndWriteOutput() this->AfterExecuteAndWriteOutputs(); m_Chrono.Stop(); - + FreeRessources(); m_Filters.clear(); return status; @@ -1513,7 +1581,7 @@ Application::SetParameterImageBase(const std::string & key, ImageBaseType* img, if (dynamic_cast<InputImageParameter*>(param)) { InputImageParameter* paramDown = dynamic_cast<InputImageParameter*>(param); - paramDown->SetImage<ImageBaseType>(img); + paramDown->SetImage(img); } else if (dynamic_cast<InputImageListParameter*>(param)) { diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperCastImage.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperCastImage.cxx new file mode 100644 index 0000000000000000000000000000000000000000..347954c65e2bc783195d69db17d8a7619f42a0c1 --- /dev/null +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperCastImage.cxx @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) + * + * This file is part of Orfeo Toolbox + * + * https://www.orfeo-toolbox.org/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "otbWrapperCastImage.h" diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperInputImageParameter.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperInputImageParameter.cxx index 65d6d6780585ceaa9bb696d18dbbc1da3b39f6dd..6959aba4ff523f3d14717e52babe45c43efae7b7 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperInputImageParameter.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperInputImageParameter.cxx @@ -24,6 +24,7 @@ #include "otbWrapperInputImageParameterMacros.h" #include "otb_boost_string_header.h" + namespace otb { @@ -62,12 +63,18 @@ InputImageParameter::SetFromFileName(const std::string& filename) } -FloatVectorImageType* -InputImageParameter::GetImage() +ImageBaseType* InputImageParameter ::GetImage() +{ + return m_Image.GetPointer(); +} + + +ImageBaseType const* InputImageParameter ::GetImage() const { - return this->GetImage<FloatVectorImageType>(); + return m_Image.GetPointer(); } + template <> ImageBaseType* InputImageParameter::GetImage<ImageBaseType>() @@ -81,21 +88,18 @@ InputImageParameter::GetImage<ImageBaseType>() otbGetImageMacro(UInt8RGBImage); otbGetImageMacro(UInt8RGBAImage); -void -InputImageParameter::SetImage(FloatVectorImageType* image) + +void InputImageParameter ::SetImage(ImageBaseType* image) { m_UseFilename = false; - this->SetImage<FloatVectorImageType>( image ); + m_Image = image; } bool InputImageParameter::HasValue() const { - if( m_FileName.empty() && m_Image.IsNull() ) - return false; - else - return true; + return !m_FileName.empty() || !m_Image.IsNull(); } void @@ -104,7 +108,8 @@ InputImageParameter { m_Image = nullptr; m_Reader = nullptr; - m_Caster = nullptr; + m_InputCaster = nullptr; + m_OutputCaster = nullptr; m_FileName = ""; m_PreviousFileName=""; m_UseFilename = true; diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperOutputImageParameter.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperOutputImageParameter.cxx index 7dcd30d0bfebe934c618c9a9ea43fc6d6e65b191..39b36a355b29517de756b0193206a053434fff36 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperOutputImageParameter.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperOutputImageParameter.cxx @@ -19,35 +19,54 @@ */ #include "otbWrapperOutputImageParameter.h" + #include "otbClampImageFilter.h" #include "otbImageIOFactory.h" -#include "itksys/SystemTools.hxx" +#include "otbWrapperCastImage.h" #ifdef OTB_USE_MPI - #include "otbMPIConfig.h" #include "otbMPIVrtWriter.h" - #ifdef OTB_USE_SPTW #include "otbSimpleParallelTiffWriter.h" #endif - #endif +#include "itksys/SystemTools.hxx" + + +#define CAST_IMAGE_BASE(T, image_base) \ + { \ + T* img = dynamic_cast<T*>(image_base); \ + \ + if (img) \ + { \ + SwitchInput<T>(img); \ + \ + return; \ + } \ + } + + namespace otb { namespace Wrapper { -OutputImageParameter::OutputImageParameter() - : m_PixelType(ImagePixelType_float), - m_DefaultPixelType(ImagePixelType_float), - m_RAMValue(0), - m_Caster(nullptr), - m_Writer(nullptr) + +// Declare specialisation for UInt8RGBAImageType +template <> +void OutputImageParameter::SwitchInput(UInt8RGBAImageType*); + +// Declare specialisation for UInt8RGBImageType +template <> +void OutputImageParameter::SwitchInput(UInt8RGBImageType*); + + +OutputImageParameter::OutputImageParameter() : m_PixelType(ImagePixelType_float), m_DefaultPixelType(ImagePixelType_float), m_RAMValue(0) { - this->SetName("Output Image"); - this->SetKey("out"); + SetName("Output Image"); + SetKey("out"); } @@ -57,6 +76,9 @@ OutputImageParameter::~OutputImageParameter() std::string OutputImageParameter::ConvertPixelTypeToString(ImagePixelType type) { + // TODO: Could be replaced by constant static string array e.g.: + // return PIXEL_TYPE_NAME[ type ]; + std::string ret; switch(type) { @@ -122,6 +144,9 @@ std::string OutputImageParameter::ConvertPixelTypeToString(ImagePixelType type) bool OutputImageParameter::ConvertStringToPixelType(const std::string &value, ImagePixelType &type) { + // TODO: Could be replaced std::find_if() in constant static string + // array (see ::ConvertPixelTypeToString(). + if (value == "uint8") type = ImagePixelType_uint8; else if (value == "int16") @@ -149,278 +174,207 @@ OutputImageParameter::ConvertStringToPixelType(const std::string &value, ImagePi return true; } -void OutputImageParameter::InitializeWriters() + +void OutputImageParameter ::InitializeWriters() { - ImageBaseType* imgBase = m_Image.GetPointer(); - // Guess the image type - std::string className(m_Image->GetNameOfClass()); - if (className == "VectorImage") - { - UInt8VectorImageType* imgUInt8 = dynamic_cast<UInt8VectorImageType*>(imgBase); - if (imgUInt8 && SwitchInput(imgUInt8)) return; + ImageBaseType* image = m_Image.GetPointer(); - Int16VectorImageType* imgInt16 = dynamic_cast<Int16VectorImageType*>(imgBase); - if (imgInt16 && SwitchInput(imgInt16)) return; + CAST_IMAGE_BASE(UInt8VectorImageType, image); + CAST_IMAGE_BASE(Int16VectorImageType, image); + CAST_IMAGE_BASE(UInt16VectorImageType, image); + CAST_IMAGE_BASE(Int32VectorImageType, image); + CAST_IMAGE_BASE(UInt32VectorImageType, image); - UInt16VectorImageType* imgUInt16 = dynamic_cast<UInt16VectorImageType*>(imgBase); - if (imgUInt16 && SwitchInput(imgUInt16)) return; + CAST_IMAGE_BASE(FloatVectorImageType, image); + CAST_IMAGE_BASE(DoubleVectorImageType, image); - Int32VectorImageType* imgInt32 = dynamic_cast<Int32VectorImageType*>(imgBase); - if (imgInt32 && SwitchInput(imgInt32)) return; + CAST_IMAGE_BASE(ComplexInt16VectorImageType, image); + CAST_IMAGE_BASE(ComplexInt32VectorImageType, image); + CAST_IMAGE_BASE(ComplexFloatVectorImageType, image); + CAST_IMAGE_BASE(ComplexDoubleVectorImageType, image); - UInt32VectorImageType* imgUInt32 = dynamic_cast<UInt32VectorImageType*>(imgBase); - if (imgUInt32 && SwitchInput(imgUInt32)) return; + CAST_IMAGE_BASE(UInt8ImageType, image); + CAST_IMAGE_BASE(Int16ImageType, image); + CAST_IMAGE_BASE(UInt16ImageType, image); + CAST_IMAGE_BASE(Int32ImageType, image); + CAST_IMAGE_BASE(UInt32ImageType, image); - FloatVectorImageType* imgFloat = dynamic_cast<FloatVectorImageType*>(imgBase); - if (imgFloat && SwitchInput(imgFloat)) return; + CAST_IMAGE_BASE(FloatImageType, image); + CAST_IMAGE_BASE(DoubleImageType, image); - DoubleVectorImageType* imgDouble = dynamic_cast<DoubleVectorImageType*>(imgBase); - if (imgDouble && SwitchInput(imgDouble)) return; + CAST_IMAGE_BASE(ComplexInt16ImageType, image); + CAST_IMAGE_BASE(ComplexInt32ImageType, image); + CAST_IMAGE_BASE(ComplexFloatImageType, image); + CAST_IMAGE_BASE(ComplexDoubleImageType, image); - ComplexInt16VectorImageType* imgCInt16 = dynamic_cast<ComplexInt16VectorImageType*>(imgBase); - if (imgCInt16 && SwitchInput(imgCInt16)) return; + CAST_IMAGE_BASE(UInt8RGBImageType, image); + CAST_IMAGE_BASE(UInt8RGBAImageType, image); - ComplexInt32VectorImageType* imgCInt32 = dynamic_cast<ComplexInt32VectorImageType*>(imgBase); - if (imgCInt32 && SwitchInput(imgCInt32)) return; + itkExceptionMacro("Unknown image-base type."); +} - ComplexFloatVectorImageType* imgCFloat = dynamic_cast<ComplexFloatVectorImageType*>(imgBase); - if (imgCFloat && SwitchInput(imgCFloat)) return; - ComplexDoubleVectorImageType* imgCDouble = dynamic_cast<ComplexDoubleVectorImageType*>(imgBase); - if (imgCDouble && SwitchInput(imgCDouble)) return; - } - else - { - UInt8ImageType* imgUInt8 = dynamic_cast<UInt8ImageType*>(imgBase); - if (imgUInt8 && SwitchInput(imgUInt8)) return; +template <typename TOutputImage, typename TInputImage> +void OutputImageParameter ::ClampAndWriteVectorImage(TInputImage* in) +{ + assert(in); + assert(!m_FileName.empty()); - Int16ImageType* imgInt16 = dynamic_cast<Int16ImageType*>(imgBase); - if (imgInt16 && SwitchInput(imgInt16)) return; + // Use metaprogramming to choose optimized pipeline. + details::CastImage<TOutputImage, TInputImage> clamp(in); - UInt16ImageType* imgUInt16 = dynamic_cast<UInt16ImageType*>(imgBase); - if (imgUInt16 && SwitchInput(imgUInt16)) return; - Int32ImageType* imgInt32 = dynamic_cast<Int32ImageType*>(imgBase); - if (imgInt32 && SwitchInput(imgInt32)) return; +#ifdef OTB_USE_MPI - UInt32ImageType* imgUInt32 = dynamic_cast<UInt32ImageType*>(imgBase); - if (imgUInt32 && SwitchInput(imgUInt32)) return; + otb::MPIConfig::Pointer mpiConfig = otb::MPIConfig::Instance(); - FloatImageType* imgFloat = dynamic_cast<FloatImageType*>(imgBase); - if (imgFloat && SwitchInput(imgFloat)) return; + if (mpiConfig->GetNbProcs() > 1) + { + std::string extension = itksys::SystemTools::GetFilenameExtension(m_FileName); - DoubleImageType* imgDouble = dynamic_cast<DoubleImageType*>(imgBase); - if (imgDouble && SwitchInput(imgDouble)) return; + if (extension == ".vrt") + { + // Use the MPIVrtWriter - ComplexInt16ImageType* imgCInt16 = dynamic_cast<ComplexInt16ImageType*>(imgBase); - if (imgCInt16 && SwitchInput(imgCInt16)) return; + auto vrtWriter = otb::MPIVrtWriter<TOutputImage>::New(); - ComplexInt32ImageType* imgCInt32 = dynamic_cast<ComplexInt32ImageType*>(imgBase); - if (imgCInt32 && SwitchInput(imgCInt32)) return; + vrtWriter->SetInput(clamp.out); + vrtWriter->SetFileName(m_FileName); + vrtWriter->SetAvailableRAM(m_RAMValue); - ComplexFloatImageType* imgCFloat = dynamic_cast<ComplexFloatImageType*>(imgBase); - if (imgCFloat && SwitchInput(imgCFloat)) return; + // Change internal state only when everything has been setup + // without raising exception. - ComplexDoubleImageType* imgCDouble = dynamic_cast<ComplexDoubleImageType*>(imgBase); - if (imgCDouble && SwitchInput(imgCDouble)) return; + m_InputCaster = clamp.icif; + m_OutputCaster = clamp.ocif; - UInt8RGBImageType* imgRGB = dynamic_cast<UInt8RGBImageType*>(imgBase); - if (imgRGB && SwitchInput(imgRGB)) return; + m_Writer = vrtWriter; - UInt8RGBAImageType* imgRGBA = dynamic_cast<UInt8RGBAImageType*>(imgBase); - if (imgRGBA && SwitchInput(imgRGBA)) return; + return; } - itkExceptionMacro("Unknown image type"); -} - +#ifdef OTB_USE_SPTW -template <typename TInput, typename TOutput> -std::pair<itk::ProcessObject::Pointer,itk::ProcessObject::Pointer> -ClampAndWriteVectorImage( TInput * in , - const std::string & filename , - const unsigned int & ramValue ) -{ - std::pair<itk::ProcessObject::Pointer,itk::ProcessObject::Pointer> ret; - typedef ClampImageFilter < TInput , TOutput > ClampFilterType; - typename ClampFilterType::Pointer clampFilter ( ClampFilterType::New() ); + else if (extension == ".tif") + { + // Use simple parallel tiff writer - clampFilter->SetInput( in); - ret.first = clampFilter.GetPointer(); - - bool useStandardWriter = true; + auto sptWriter = otb::SimpleParallelTiffWriter<TOutputImage>::New(); - #ifdef OTB_USE_MPI + sptWriter->SetFileName(m_FileName); + sptWriter->SetInput(clamp.out); + sptWriter->GetStreamingManager()->SetDefaultRAM(m_RAMValue); - otb::MPIConfig::Pointer mpiConfig = otb::MPIConfig::Instance(); + // Change internal state only when everything has been setup + // without raising exception. - if (mpiConfig->GetNbProcs() > 1) - { - useStandardWriter = false; + m_InputCaster = clamp.icif; + m_OutputCaster = clamp.ocif; - // Get file extension - std::string extension = itksys::SystemTools::GetFilenameExtension(filename); + m_Writer = sptWriter; - if(extension == ".vrt") - { - // Use the MPIVrtWriter - typedef otb::MPIVrtWriter<TOutput> VRTWriterType; + return; + } - typename VRTWriterType::Pointer vrtWriter = VRTWriterType::New(); - vrtWriter->SetInput(clampFilter->GetOutput()); - vrtWriter->SetFileName(filename); - vrtWriter->SetAvailableRAM(ramValue); - ret.second = vrtWriter.GetPointer(); - } - #ifdef OTB_USE_SPTW - else if (extension == ".tif") - { - // Use simple parallel tiff writer - typedef otb::SimpleParallelTiffWriter<TOutput> SPTWriterType; +#endif // OTB_USE_SPTW - typename SPTWriterType::Pointer sptWriter = SPTWriterType::New(); - sptWriter->SetFileName(filename); - sptWriter->SetInput(clampFilter->GetOutput()); - sptWriter->GetStreamingManager()->SetDefaultRAM(ramValue); - ret.second = sptWriter.GetPointer(); - } - - #endif else { - itkGenericExceptionMacro("File format "<<extension<<" not supported for parallel writing with MPI. Supported formats are .vrt and .tif. Extended filenames are not supported."); + itkGenericExceptionMacro("File format " << extension + << " not supported for parallel writing with MPI. Supported formats are " + ".vrt and .tif. Extended filenames are not supported."); } - - } - - #endif - - if(useStandardWriter) - { - typename otb::ImageFileWriter<TOutput>::Pointer writer = - otb::ImageFileWriter<TOutput>::New(); - writer->SetFileName( filename ); - writer->SetInput(clampFilter->GetOutput()); - writer->GetStreamingManager()->SetDefaultRAM(ramValue); - ret.second = writer.GetPointer(); } - return ret; +#endif // OTB_USE_MPI + + // + // Use default OTB writer. + + auto writer = otb::ImageFileWriter<TOutputImage>::New(); + + writer->SetFileName(m_FileName); + writer->SetInput(clamp.out); + writer->GetStreamingManager()->SetDefaultRAM(m_RAMValue); + + // Change internal state only when everything has been setup + // without raising exception. + + m_InputCaster = clamp.icif; + m_OutputCaster = clamp.ocif; + + m_Writer = writer; } -template <class TInput> -int -OutputImageParameter::SwitchInput(TInput *img) + +template <typename TInputImage> +void OutputImageParameter ::SwitchInput(TInputImage* image) { - if (! img) return 0; + assert(image); - std::pair<itk::ProcessObject::Pointer,itk::ProcessObject::Pointer> ret; - switch(m_PixelType ) - { - case ImagePixelType_uint8: - { - ret = ClampAndWriteVectorImage< TInput , UInt8VectorImageType > ( - img , - m_FileName , - m_RAMValue ); + switch (m_PixelType) + { + case ImagePixelType_uint8: + ClampAndWriteVectorImage<UInt8VectorImageType>(image); break; - } - case ImagePixelType_int16: - { - ret = ClampAndWriteVectorImage< TInput , Int16VectorImageType > ( - img , - m_FileName , - m_RAMValue ); + + case ImagePixelType_int16: + ClampAndWriteVectorImage<Int16VectorImageType>(image); break; - } - case ImagePixelType_uint16: - { - ret = ClampAndWriteVectorImage< TInput , UInt16VectorImageType > ( - img , - m_FileName , - m_RAMValue ); + + case ImagePixelType_uint16: + ClampAndWriteVectorImage<UInt16VectorImageType>(image); break; - } - case ImagePixelType_int32: - { - ret = ClampAndWriteVectorImage< TInput , Int32VectorImageType > ( - img , - m_FileName , - m_RAMValue ); + + case ImagePixelType_int32: + + ClampAndWriteVectorImage<Int32VectorImageType>(image); break; - } - case ImagePixelType_uint32: - { - ret = ClampAndWriteVectorImage< TInput , UInt32VectorImageType > ( - img , - m_FileName , - m_RAMValue ); + + case ImagePixelType_uint32: + ClampAndWriteVectorImage<UInt32VectorImageType>(image); break; - } - case ImagePixelType_float: - { - ret = ClampAndWriteVectorImage< TInput , FloatVectorImageType > ( - img , - m_FileName , - m_RAMValue ); + + case ImagePixelType_float: + ClampAndWriteVectorImage<FloatVectorImageType>(image); break; - } - case ImagePixelType_double: - { - ret = ClampAndWriteVectorImage< TInput , DoubleVectorImageType > ( - img , - m_FileName , - m_RAMValue ); + + case ImagePixelType_double: + ClampAndWriteVectorImage<DoubleVectorImageType>(image); break; - } - case ImagePixelType_cint16: - { - ret = ClampAndWriteVectorImage < TInput , ComplexInt16VectorImageType > ( - img , - m_FileName , - m_RAMValue ); + + case ImagePixelType_cint16: + ClampAndWriteVectorImage<ComplexInt16VectorImageType>(image); break; - } - case ImagePixelType_cint32: - { - ret = ClampAndWriteVectorImage < TInput , ComplexInt32VectorImageType > ( - img , - m_FileName , - m_RAMValue ); + + case ImagePixelType_cint32: + ClampAndWriteVectorImage<ComplexInt32VectorImageType>(image); break; - } - case ImagePixelType_cfloat: - { - ret = ClampAndWriteVectorImage < TInput , ComplexFloatVectorImageType > ( - img , - m_FileName , - m_RAMValue ); + + case ImagePixelType_cfloat: + ClampAndWriteVectorImage<ComplexFloatVectorImageType>(image); break; - } + case ImagePixelType_cdouble: - { - ret = ClampAndWriteVectorImage < TInput , ComplexDoubleVectorImageType > ( - img , - m_FileName , - m_RAMValue ); - break; - } + ClampAndWriteVectorImage<ComplexDoubleVectorImageType>(image); + break; + default: + assert(false && "Unexpected image-type."); break; } - // Save the caster and writer - m_Caster = ret.first; - m_Writer = ret.second; - return 1; } + void OutputImageParameter::Write() { m_Writer->Update(); // Clean internal filters - m_Caster = nullptr; + m_InputCaster = nullptr; + m_OutputCaster = nullptr; + m_Writer = nullptr; } @@ -444,11 +398,9 @@ OutputImageParameter::SetValue(ImageBaseType* image) SetActive(true); } -bool -OutputImageParameter::HasValue() const +bool OutputImageParameter ::HasValue() const { - std::string filename(this->GetFileName()); - return !filename.empty(); + return !m_FileName.empty(); } std::string @@ -493,43 +445,38 @@ OutputImageParameter::CheckFileName(bool fixMissingExtension) } // Specialization for UInt8RGBAImageType + template <> -int -OutputImageParameter::SwitchInput(UInt8RGBAImageType *img) +void OutputImageParameter ::SwitchInput(UInt8RGBAImageType* img) { - if (! img) return 0; - if( m_PixelType == ImagePixelType_uint8 ) - { - typename otb::ImageFileWriter<UInt8RGBAImageType>::Pointer writer = - otb::ImageFileWriter<UInt8RGBAImageType>::New(); - writer->SetFileName( this->GetFileName() ); - writer->SetInput(img); - writer->GetStreamingManager()->SetDefaultRAM(m_RAMValue); - m_Writer = writer.GetPointer(); - } - else - itkExceptionMacro("Unknown PixelType for RGBA Image. Only uint8 is supported."); - return 1; + assert(img); + + if (m_PixelType != ImagePixelType_uint8) + itkExceptionMacro("Unknown PixelType for RGBA Image. Only uint8 is supported."); + + auto writer = otb::ImageFileWriter<UInt8RGBAImageType>::New(); + + writer->SetFileName(GetFileName()); + writer->SetInput(img); + writer->GetStreamingManager()->SetDefaultRAM(m_RAMValue); + + m_Writer = writer; } // Specialization for UInt8RGBImageType template <> -int -OutputImageParameter::SwitchInput(UInt8RGBImageType *img) +void OutputImageParameter ::SwitchInput(UInt8RGBImageType* img) { - if (! img) return 0; - if( m_PixelType == ImagePixelType_uint8 ) - { - typename otb::ImageFileWriter<UInt8RGBImageType>::Pointer writer = - otb::ImageFileWriter<UInt8RGBImageType>::New(); - writer->SetFileName( this->GetFileName() ); - writer->SetInput(img); - writer->GetStreamingManager()->SetDefaultRAM(m_RAMValue); - m_Writer = writer.GetPointer(); - } - else - itkExceptionMacro("Unknown PixelType for RGB Image. Only uint8 is supported."); - return 1; + if (m_PixelType != ImagePixelType_uint8) + itkExceptionMacro("Unknown PixelType for RGB Image. Only uint8 is supported."); + + auto writer = otb::ImageFileWriter<UInt8RGBImageType>::New(); + + writer->SetFileName(GetFileName()); + writer->SetInput(img); + writer->GetStreamingManager()->SetDefaultRAM(m_RAMValue); + + m_Writer = writer; } void OutputImageParameter::SetFileName (const char* filename)