diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5a49ac9a3d25f1df41b6fedbb4df81aa7498c089..9525bdc2898a29d2e111dba868cb80dc60bc912f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -25,7 +25,12 @@ before_script: # Checkout the expected branch - git checkout $CI_COMMIT_REF_NAME +after_script: + - python3 CI/cdash_handler.py $CI_COMMIT_SHA $CI_PROJECT_ID $CI_PROJECT_DIR $K8S_SECRET_CDASH + stages: + - precheck + - prepare - build .general: @@ -35,13 +40,18 @@ stages: - runner_system_failure - stuck_or_timeout_failure -native-build: +fast-build: extends: .general - only: [merge_requests] - stage: build - image: $BUILD_IMAGE_REGISTRY/otb-ubuntu-native:18.04 + only: [merge_requests, branches] + stage: precheck + image: $CI_REGISTRY/gpasero/otb/otb-install-ubuntu-native + before_script: + - export GIT_LFS_SKIP_SMUDGE=1 + - git checkout $CI_COMMIT_REF_NAME + - python3 CI/check_twin_pipelines.py script: - - ctest -VV -S CI/main_ci.cmake -DIMAGE_NAME:string=ubuntu-18.04-gcc + - ctest -V -S CI/main_ci.cmake -DIMAGE_NAME:string=ubuntu-18.04-fast + - ccache -s debian-build: extends: .general @@ -49,20 +59,59 @@ debian-build: stage: build image: $BUILD_IMAGE_REGISTRY/otb-debian-native:unstable script: - - ctest -VV -S CI/main_ci.cmake -DIMAGE_NAME:string=debian-unstable-gcc + - xvfb-run -a -n 1 -s "-screen 0 1024x768x24 -dpi 96" ctest -V -S CI/main_ci.cmake -DIMAGE_NAME:string=debian-unstable-gcc .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: - - ctest -VV -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 -build:ubuntu-llvm: +ubuntu-llvm: only: [merge_requests] extends: .common-build -build:ubuntu-llvm-wip: - except: [merge_requests] - extends: .common-build +superbuild-prepare: + only: [merge_requests] + extends: .general + stage: prepare + image: $BUILD_IMAGE_REGISTRY/otb-ubuntu-superbuild-base:18.04 + before_script: +# This override the previous before_script + - git checkout $CI_COMMIT_REF_NAME +# We are now doing the git-lfs install +# This is done after the checkout so we avoid downloading Data +# But we need it to upload the archive + - git-lfs install + - git config --global user.email "otbbot@orfeo-toolbox.org" + - git config --global user.name "otbbot" + - eval $(ssh-agent -s) + - ssh-add <(echo "$K8S_SECRET_SSH") +# This is for debug, we are checking the owner of the ssh key + - ssh -o StrictHostKeyChecking=no -T git@gitlab.orfeo-toolbox.org + script: + - ctest -VV -S CI/prepare_superbuild.cmake -DIMAGE_NAME:string=otb-ubuntu-superbuild-base + after_script: + - echo "Nothing to do for after_script" + artifacts: + expire_in: 24 hrs + paths: + # This recovers logs from superbuild build + - build/*/*/*/*.log + - sb_branch.txt +superbuild-build: + only: [merge_requests] + extends: .general + stage: build + image: $BUILD_IMAGE_REGISTRY/otb-ubuntu-superbuild-base:18.04 + script: + - ctest -VV -S CI/main_superbuild.cmake -DIMAGE_NAME:string=otb-ubuntu-superbuild-base + dependencies: + - superbuild-prepare diff --git a/CI/cdash_handler.py b/CI/cdash_handler.py new file mode 100644 index 0000000000000000000000000000000000000000..7a19d5a87f870f785565319d0dcd24dc47de6df4 --- /dev/null +++ b/CI/cdash_handler.py @@ -0,0 +1,280 @@ +# +# 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. +# + +import os.path +import urllib.request +import urllib.parse +import glob +import re +import unittest +import sys +import json +import time + + +trace = False + +class Handler: +# project +# site +# stamp +# name + def __init__ (self): + self.build_dir = "" + self.configure_path = "" + self.url = "https://cdash.orfeo-toolbox.org" + self.project = "OTB" + self.site = "" + self.stamp = "" + self.name = "" + self.buildid = "" + + def GetConfigureFile (self , build_dir = "" ): + if build_dir == "": + build_dir = self.build_dir + build_dir = os.path.normpath(build_dir) + test_path = os.path.join( build_dir , "Testing/") + list_folder = os.listdir(test_path) + if trace: + print(list_folder) + configure_xml = "" + for folder in list_folder: + if folder == "Temporary" or folder == "TAG": + pass + configure_xml = os.path.join( test_path , folder , "Configure.xml" ) + if os.path.exists( configure_xml ): + break + if os.path.exists( configure_xml ): + if trace: + print ( configure_xml ) + configure_file = open( configure_xml, "r" ) + content = configure_file.read() + configure_file.close() + print( content ) + self.configure_path = configure_xml + return self.configure_path + print("Could not find the Configure.xml produced by ctest") + return + + def GetSite (self , build_dir="" ): + """ + Site is corresponding to the Name field in the xml. + """ + if ( build_dir == ""): + build_dir = self.build_dir + if self.configure_path == "" and not self.GetConfigureFile( build_dir ): + print ("Error in GetSite function, could not find Configure.xml") + return + configure_file = open( self.configure_path, "r" ) + content = configure_file.read() + configure_file.close() + site_regex = re.compile( "\\bName\\b=\"([0-9,\\s,\(,\),\-,\.,_,A-Z,a-z]+)") + site = site_regex.search( content ) + if trace: + print (site_regex) + print(site) + if site: + if trace: + print("site value \n" , site.group(1)) + self.site = site.group(1) + return self.site + print("Could not retreive site value") + return + return + + def GetName (self , build_dir = ""): + """ + This function is looking for the name information in the build tree: + which is BuildName + """ + if ( build_dir == ""): + build_dir = self.build_dir + if self.configure_path == "" and not self.GetConfigureFile( build_dir ): + print ("Error in GetName function, could not find Configure.xml") + return + configure_file = open( self.configure_path, "r" ) + content = configure_file.read() + configure_file.close() + name_regex = re.compile( "\\bBuildName\\b=\"([0-9,\\s,\(,\),\-,\.,_,A-Z,a-z]+)\"") + name = name_regex.search( content ) + if trace: + print (name_regex) + print( name) + if name: + if trace: + print("name value \n" , name.group(1)) + self.name = name.group(1) + return self.name + print("Could not retreive name value") + return + + def GetStamp (self , build_dir = "" ): + """ + This function is looking for the stamp information in the build tree + """ + if ( build_dir == ""): + build_dir = self.build_dir + if self.configure_path == "" and not self.GetConfigureFile( build_dir ): + print ("Error in GetStamp function, could not find Configure.xml") + return + configure_file = open( self.configure_path, "r" ) + content = configure_file.read() + configure_file.close() + stamp_regex = re.compile( "\\bBuildStamp\\b=\"([0-9,\\s,\(,\),\-,\.,_,A-Z,a-z]+)\"") + stamp = stamp_regex.search( content ) + if trace: + print( stamp_regex ) + print( stamp ) + if stamp: + if trace: + print("Stamp value \n" , stamp.group(1)) + self.stamp = stamp.group(1) + return self.stamp + print("Could not retreive stamp value") + return + + def GetBuildId (self, **kwargs): + """ + This function is returning the buildid. Dict can be passed with the + different informations + """ + site = self.site + stamp = self.stamp + name = self.name + project = self.project + for key , value in kwargs.items(): + if key == "site": + site = value + if key == "stamp": + stamp = value + if key == "name": + name = value + if key == "project": + project = value + if ( site == "" or stamp == "" or name == "" or project == ""): + print( "Missing argument for buildid request \ +site:"+site+", stamp:"+stamp+", name:"+name+", project:"+project+".") + return + buildid_api = "/api/v1/getbuildid.php?" + buildid_params = urllib.parse.urlencode({'project': project, 'site': site, 'stamp': stamp , 'name': name}) + full_url = self.url + buildid_api + buildid_params + if trace: + print("full_url: "+full_url) + nb_try = 6 + build_id_regex = re.compile( "<buildid>([0-9]+)</buildid>" ) + 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: + print ( "build id is ", self.buildid) + return buildid.group(1) + else: + print("Error in recovering buildid") + return + + def GetBuildUrl (self , buildid = "" ): + """ + This function is returning the build url. It can be called only when + everything is set + """ + if ( buildid == "" ): + buildid = self.buildid + if ( buildid == "" ): + print( "Missing argument to build url") + return + build_url = self.url + build_url +="/buildSummary.php?" + build_url += "buildid=" + buildid + return build_url + + def GetBuildStatus(self, buildid = "" ): + """ + This function returns the status of a build id as a pair 'state' + 'errors' + """ + if ( buildid == "" ): + buildid = self.buildid + if ( buildid == "" ): + 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() + full_status = json.loads(response) + state = "success" + if full_status["configure"]["nerrors"] or full_status["build"]["nerrors"] \ + or full_status["test"]["nerrors"] or full_status["test"]["nfailed"]: + state = 'failed' + errors = "" + if full_status["configure"]["nerrors"]: + errors = "Errors occur during configure" + elif full_status["build"]["nerrors"]: + errors = "Errors occur during build" + elif full_status["test"]["nerrors"] or full_status["test"]["nfailed"]: + errors = "Errors occur during tests" + return ( state , errors) + +""" +TODO : + documentation, header, test if it is possible. + the script aims only at recovering the build url + +""" +if __name__ == "__main__": + if ( len(sys.argv) < 5 ): + print("Usage : "+sys.argv[0]+" commit_sha1 project_id build_directory token") + sys.exit() + if trace: + print (sys.argv) + handler = Handler() + build_dir = os.path.join( sys.argv[3] , "build/") + # build_dir = sys.argv[3] + if trace: + print("build_dir is: " + build_dir) + handler.build_dir = build_dir + handler.GetSite() + handler.GetName() + handler.GetStamp() + 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/" + gitlab_url += sys.argv[2] + "/statuses/" + sys.argv[1] + params = urllib.parse.urlencode({'name':'cdash:' + handler.site , 'state': state ,\ + 'target_url' : cdash_url , 'description' : error }) + gitlab_request = urllib.request.Request(gitlab_url) + gitlab_request.add_header('PRIVATE-TOKEN' , sys.argv[4] ) + res = urllib.request.urlopen(gitlab_request, data=params.encode('ascii')) + if trace: + print ("gitlab_request.url: " + gitlab_request.full_url) + print ("gitlab_request.text: " + res.read().decode()) diff --git a/CI/check_twin_pipelines.py b/CI/check_twin_pipelines.py new file mode 100644 index 0000000000000000000000000000000000000000..d2a6113924677266de8cf30f8d35debc8ee2c3ea --- /dev/null +++ b/CI/check_twin_pipelines.py @@ -0,0 +1,88 @@ +# +# 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. +# + +import os +import urllib.request +import urllib.parse +import json +import re +import time + +""" +Send a request to Gitlab and return the answer +The request parameter is added after `project/:id/` +WARNING: when data is given, the request will be a POST +Otherwise, it is a GET +""" +def GitlabRequest(request, project=53, data=None, token=''): + gitlab_url = "https://gitlab.orfeo-toolbox.org/api/v4/projects/" + gitlab_url+= str(project) + '/' + request + params = None + myHeader = {} + if not data is None: + params = urllib.parse.urlencode(data).encode('ascii') + if token: + myHeader = {'PRIVATE-TOKEN':token} + gitlab_request = urllib.request.Request(gitlab_url, data=params, headers=myHeader) + res = urllib.request.urlopen(gitlab_request) + return json.loads(res.read().decode()) + +""" +Check needed environment parameters +""" +def CheckEnvParameters(params): + for p in params: + if not p in os.environ.keys(): + print("Missing environment variable '"+p+"'") + return False + return True + +""" +Check for any duplicated twin pipeline and cancel it +""" +if __name__ == "__main__": + if not CheckEnvParameters(['CI_COMMIT_SHA']): + sys.exit(1) + env = os.environ + sha1 = env['CI_COMMIT_SHA'] + # are we in a merge_request pipeline ? + if 'CI_MERGE_REQUEST_IID' in env.keys(): + if not CheckEnvParameters(['K8S_SECRET_TWIN_PIPELINE','CI_PROJECT_ID','CI_PIPELINE_ID']): + sys.exit(1) + mrInfo = GitlabRequest('merge_requests/'+env['CI_MERGE_REQUEST_IID'],token=env['K8S_SECRET_TWIN_PIPELINE']) + wip_regex = re.compile("^[Ww][Ii][Pp]:") + # is it a "WIP" merge request ? + if wip_regex.search(mrInfo["title"]): + # Yes: cancel the current pipeline + print("Cancel current pipeline "+env['CI_PIPELINE_ID']) + GitlabRequest('pipelines/'+env['CI_PIPELINE_ID']+'/cancel', data={}, \ + project=env['CI_PROJECT_ID'], token=env['K8S_SECRET_TWIN_PIPELINE']) + time.sleep(180) + print("Error: this pipeline should have been canceled") + sys.exit(1) + else: + # No: cancel any previous "normal" pipeline on the same SHA1 + jres = GitlabRequest('pipelines?sha='+sha1, project=env['CI_PROJECT_ID'], token=env['K8S_SECRET_TWIN_PIPELINE']) + for item in jres: + if item["id"] < int(env['CI_PIPELINE_ID']) and item["status"] == "running": + print("Cancel pipeline "+str(item["id"])) + jres2 = GitlabRequest('pipelines/'+str(item["id"])+'/cancel', data={}, \ + project=env['CI_PROJECT_ID'], token=env['K8S_SECRET_TWIN_PIPELINE']) + diff --git a/CI/configure_option.cmake b/CI/configure_option.cmake index 7cc9b319fa96eec436a3454d916c7e7c2eb35d21..26502b11bfa758e483b8b60cafb62e1ad6ff9067 100644 --- a/CI/configure_option.cmake +++ b/CI/configure_option.cmake @@ -51,12 +51,12 @@ OTB_USE_QWT:BOOL=ON OTB_USE_SHARK:BOOL=ON OTB_USE_SIFTFAST:BOOL=ON OTB_USE_SPTW:BOOL=ON -OTB_USE_SSE_FLAGS:BOOL=ON") +OTB_USE_SSE_FLAGS:BOOL=ON +OTB_MPIEXEC_OPT:STRING=--allow-run-as-root") set (otb_wrap_option "OTB_WRAP_JAVA:BOOL=ON -OTB_WRAP_PYTHON:BOOL=ON -OTB_WRAP_PYTHON3:BOOL=ON") +OTB_WRAP_PYTHON:BOOL=ON") set (otb_data_option "OTB_DATA_USE_LARGEINPUT:BOOL=OFF diff --git a/CI/main_ci.cmake b/CI/main_ci.cmake index ad1c92969db630f43936dc0496b717047ab16720..c0a1cf37f37e88b86af2a88efab623ff02079b0b 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,12 +54,37 @@ elseif(ci_ref_name) endif() endif() +# 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}") +# Detect "skip testing" +if(DEFINED ENV{CI_SKIP_TESTING}) + set(ci_skip_testing 1) +endif() + # 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 @@ -62,6 +96,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" ) @@ -86,6 +121,7 @@ ctest_configure(BUILD "${CTEST_BINARY_DIRECTORY}" ) if ( NOT _configure_rv EQUAL 0 ) + # stop processing here ctest_submit() message( FATAL_ERROR "An error occurs during ctest_configure.") endif() @@ -96,19 +132,30 @@ ctest_build(BUILD "${CTEST_BINARY_DIRECTORY}" ) if ( NOT _build_rv EQUAL 0 ) - ctest_submit() message( SEND_ERROR "An error occurs during ctest_build.") endif() -# Uncomment when ready for test -# ctest_test(PARALLEL_LEVEL 8 -# RETURN_VALUE _test_rv -# CAPTURE_CMAKE_ERROR _test_error -# ) +if(ci_skip_testing) + message(STATUS "Skip testing") + set(_test_rv 0) +else() + ctest_test(PARALLEL_LEVEL 8 + RETURN_VALUE _test_rv + CAPTURE_CMAKE_ERROR _test_error + ) +endif() -# if ( NOT _test_rv EQUAL 0 ) -# ctest_submit() -# message( SEND_ERROR "An error occurs during ctest_test.") -# endif() +if ( NOT _test_rv EQUAL 0 ) + message( SEND_ERROR "An error occurs during ctest_test.") +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/main_superbuild.cmake b/CI/main_superbuild.cmake new file mode 100644 index 0000000000000000000000000000000000000000..93c896662166992ebdf1bd0e8cce860f26c2d959 --- /dev/null +++ b/CI/main_superbuild.cmake @@ -0,0 +1,161 @@ +# +# 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. +# + +# This script is a prototype for the future CI, it may evolve rapidly in a near future +set (ENV{LANG} "C") # Only ascii output +get_filename_component(OTB_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR} DIRECTORY) +get_filename_component(CI_PROJ_DIR ${OTB_SOURCE_DIR} DIRECTORY) +get_filename_component(CI_ROOT_DIR ${CI_PROJ_DIR} DIRECTORY) + +########################################################################### +########################################################################### +# Download xkd +########################################################################### +########################################################################### + +# How to get md5sum: +# * concatenate all source files in one +# * add configure result from previous job ${OTB_SOURCE_DIR}/build/CMakeCache.txt +########################### + +file(READ "${OTB_SOURCE_DIR}/sb_branch.txt" BRANCH_NAME) + +#################################### + + +# git clone $REPOSITORY_URL --branch $BRANCH_NAME --depth 1 superbuild-artifact +############################################################################### +set ( REMOTE "https://gitlab.orfeo-toolbox.org/gbonnefille/superbuild-artifact.git") +# set ( BRANCH_NAME "${IMAGE_NAME}/${SB_MD5}") +set( GIT "git" ) + +execute_process( + COMMAND ${GIT} "clone" "${REMOTE}" "--branch" "${BRANCH_NAME}" + "--depth" "1" "superbuild-artifact" + WORKING_DIRECTORY ${CI_PROJ_DIR} + RESULT_VARIABLE clone_res + OUTPUT_VARIABLE clone_out + ERROR_VARIABLE clone_err + ) + +if ( DEBUG ) + message( "Clone") + message( "clone_res = ${clone_res}" ) + message( "clone_out = ${clone_out}" ) + message( "clone_err = ${clone_err}" ) +endif() + +if (clone_res) + message( SEND_ERROR "Problem in retreiving the archive") + return() +endif() + +set (CMAKE_COMMAND "cmake") +execute_process( + COMMAND ${CMAKE_COMMAND} "-E" "tar" "xf" + "${CI_PROJ_DIR}/superbuild-artifact/SuperBuild_Install.tar" + WORKING_DIRECTORY ${CI_ROOT_DIR} + ) + +set( XDK_PATH "${CI_ROOT_DIR}/xdk") + +if ( DEBUG ) + if ( EXISTS "${XDK_PATH}") + message("Tar file exists at ${XDK_PATH}") + else() + message("Something went wrong no tar file in ${XDK_PATH}") + endif() +endif() + +########################################################################### +########################################################################### +# Building OTB +########################################################################### +########################################################################### + +set ( CTEST_BUILD_CONFIGURATION "Release" ) +set ( CTEST_CMAKE_GENERATOR "Unix Makefiles" ) +set ( CTEST_BUILD_FLAGS "-j16" ) +set ( CTEST_BUILD_NAME "Superbuild_Build_Otb" ) +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/" ) +set ( PROJECT_SOURCE_DIR "${OTB_SOURCE_DIR}" ) + +set (CONFIGURE_OPTIONS "") +include ( "${CMAKE_CURRENT_LIST_DIR}/configure_option.cmake" ) +# SuperBuild case : one more configure option +set ( CONFIGURE_OPTIONS + "${CONFIGURE_OPTIONS}-DCMAKE_PREFIX_PATH=${XDK_PATH};") + +# Hack because there is no more superbuild available (LIBKML) +set ( CONFIGURE_OPTIONS + "${CONFIGURE_OPTIONS}-DOTB_USE_LIBKML:BOOL=OFF;" ) + +# FIX ME this part might platform dependent +set( GDAL_DATA "${XDK_PATH}/share/gdal" ) +set( GEOTIFF_CSV "${XDK_PATH}/share/epsg_csv" ) +set( PROJ_LIB "${XDK_PATH}/share" ) +set( CTEST_ENVIRONMENT +"PATH=${XDK_PATH}/lib:${XDK_PATH}/bin:$ENV{PATH} +GDAL_DATA= GDAL_DATA +GEOTIFF_CSV= GEOTIFF_CSV +PROJ_LIB= PROJ_LIB +") + +ctest_start (Experimental TRACK Experimental) + +ctest_configure(BUILD "${CTEST_BINARY_DIRECTORY}" + SOURCE "${OTB_SOURCE_DIR}" + OPTIONS "${CONFIGURE_OPTIONS}" + RETURN_VALUE _configure_rv + CAPTURE_CMAKE_ERROR _configure_error + ) + +if ( NOT _configure_rv EQUAL 0 ) + ctest_submit() + message( SEND_ERROR "An error occurs during ctest_configure.") +endif() + +ctest_build(BUILD "${CTEST_BINARY_DIRECTORY}" + RETURN_VALUE _build_rv + CAPTURE_CMAKE_ERROR _build_error + ) + +if ( NOT _build_rv EQUAL 0 ) + ctest_submit() + message( SEND_ERROR "An error occurs during ctest_build.") +endif() + +# Uncomment when ready for test +# ctest_test(PARALLEL_LEVEL 8 +# RETURN_VALUE _test_rv +# CAPTURE_CMAKE_ERROR _test_error +# ) + +# if ( NOT _test_rv EQUAL 0 ) +# ctest_submit() +# message( SEND_ERROR "An error occurs during ctest_test.") +# endif() + +ctest_submit() diff --git a/CI/prepare_superbuild.cmake b/CI/prepare_superbuild.cmake new file mode 100644 index 0000000000000000000000000000000000000000..c94329788b40a995e5c1a497823fbfc9c8b32743 --- /dev/null +++ b/CI/prepare_superbuild.cmake @@ -0,0 +1,345 @@ +# +# 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. +# +# This script is for the superbuild build on the CI platform + +set (ENV{LANG} "C") # Only ascii output +get_filename_component(OTB_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR} DIRECTORY) +get_filename_component(CI_PROJ_DIR ${OTB_SOURCE_DIR} DIRECTORY) +get_filename_component(CI_ROOT_DIR ${CI_PROJ_DIR} DIRECTORY) + +# In GitLab we have : +# OTB_SOURCE_DIR=/builds/{project_dir}/otb +# CI_PROJ_DIR=/builds/{project_dir} +# CI_ROOT_DIR=/builds + +set ( DEBUG "1" ) + +set ( SUPERBUILD_SOURCE_DIR "${OTB_SOURCE_DIR}/SuperBuild" ) + +set ( CTEST_BUILD_CONFIGURATION "Release" ) +set ( CTEST_CMAKE_GENERATOR "Unix Makefiles" ) +set ( PROJECT_SOURCE_DIR "${SUPERBUILD_SOURCE_DIR}" ) +set ( CTEST_SOURCE_DIRECTORY "${SUPERBUILD_SOURCE_DIR}" ) +set ( CTEST_BINARY_DIRECTORY "${OTB_SOURCE_DIR}/build/" ) +set ( CTEST_SITE "${IMAGE_NAME}" ) +set ( CTEST_BUILD_NAME "Superbuild_Build_Depends" ) # FIXME + +# We need a directory independent from user +# in CI the architecture is /builds/user/otb +# So we will go in /builds/ +# This is platform dependent, and the next step (build) also +# depends on that, as some paths are hardcoded +# This can be fixed with a packaging of OTB_DEPENDS +set (CTEST_INSTALL_DIRECTORY "${CI_ROOT_DIR}/xdk/") + +# HACK +# This is needed because when using return() function ctest is trying +# to run the CTEST_COMMAND. And we need it to not produce an error +set (CTEST_COMMAND "echo \"Exit\"") # HACK FIX ME +set (CMAKE_COMMAND "cmake") + +######################################################################## +######################################################################## +# Build process +######################################################################## +######################################################################## + +ctest_start (Experimental TRACK Experimental) + +set(CTEST_BUILD_FLAGS "-j16") + +set ( SB_CONFIGURE_OPTIONS "") +include( "${CMAKE_CURRENT_LIST_DIR}/sb_configure_options.cmake" ) + +ctest_configure(BUILD "${CTEST_BINARY_DIRECTORY}" + SOURCE "${SUPERBUILD_SOURCE_DIR}" + OPTIONS "${SB_CONFIGURE_OPTIONS}" + RETURN_VALUE _configure_rv + CAPTURE_CMAKE_ERROR _configure_error + ) + +if ( NOT _configure_rv EQUAL 0 ) + ctest_submit() + message( SEND_ERROR "An error occurs during ctest_configure. Dependencies might be buggy.") + return() +endif() + +######################################################################## +######################################################################## +# Check process +######################################################################## +######################################################################## +# Once that we have configure our build we can check if it exists a +# corresponding SB on superbuild-artifact + +# How to get md5sum: +# * concatenate all source files in one +# * add configure result : CMakeCache.txt +#################################### +file( GLOB_RECURSE sb_file_list "${OTB_SOURCE_DIR}/SuperBuild/*") +set( SB_TXT "${OTB_SOURCE_DIR}/full_sb.txt") +foreach(sb_file ${sb_file_list}) + file(READ ${sb_file} CONTENTS) + file(APPEND ${SB_TXT} "${sb_file}${CONTENTS}") +endforeach(sb_file) +file(READ "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt" CMAKE_ORIG) +string(REPLACE "${CI_PROJ_DIR}" "" CMAKE_UNIFIED ${CMAKE_ORIG}) +file(APPEND ${SB_TXT} "CMakeCache.txt${CMAKE_UNIFIED}") +file ( MD5 "${SB_TXT}" SB_MD5) +message ( "SB_MD5 = ${SB_MD5}" ) +file (REMOVE ${SB_TXT}) + +#################################### + +# checkout part +# we look for the right branch +# Branch name cannot have a ":" +# git ls-remote $REMOTE $BRANCH_NAME +#################################### +file ( WRITE "${OTB_SOURCE_DIR}/sb_branch.txt" "${IMAGE_NAME}/${SB_MD5}") +message( "Checking out git for existence of archive") +set ( REMOTE "https://gitlab.orfeo-toolbox.org/gbonnefille/superbuild-artifact/") +set ( BRANCH_NAME "${IMAGE_NAME}/${SB_MD5}") +set( GIT "git" ) +execute_process( + COMMAND ${GIT} "ls-remote" "${REMOTE}" "${BRANCH_NAME}" + OUTPUT_VARIABLE IS_SB_BUILD + ) +if ( IS_SB_BUILD ) + message( "Superbuild is already build for ${IMAGE_NAME} with sources as ${SB_MD5}") + return() +else() + message( "No build available, this job will build and push OTB_DEPENDS") +endif() +#################################### +# Back to build + +ctest_build(BUILD "${CTEST_BINARY_DIRECTORY}" + TARGET "OTB_DEPENDS" + RETURN_VALUE _build_rv + NUMBER_ERRORS _build_nb_err + CAPTURE_CMAKE_ERROR _build_error + ) + +if ( DEBUG ) + message( "Status for build:" ) + message("_build_rv=${_build_rv}") + message("_build_nb_err=${_build_nb_err}") + message("_build_error=${_build_error}") +endif() + +if ( ( NOT ${_build_nb_err} EQUAL 0 ) OR ( ${_build_error} EQUAL -1 )) + ctest_submit() + message( FATAL_ERROR "An error occurs during ctest_build.") +endif() + +ctest_submit() + +######################################################################## +######################################################################## +# Git process +######################################################################## +######################################################################## + +# WE PUSH ONLY IF BUILD SUCCEED +# The image used will be passed to this script. +# TODO verify that images does not have forbidden char in there name +# TODO right now we rely on ctest_build to know whether there has been an error +# in build, whereas SuperBuild does not necessarily return an error if something +#Â goes wrong +set ( SB_ARTIFACT_GIT "${CI_PROJ_DIR}/superbuild-artifact" ) + +# REPOSITORY_GIT_URL and REMOTE whould be the same. Right now there are +# different because one is https and one is ssh. Both should be ssh. +set( REPOSITORY_GIT_URL "git@gitlab.orfeo-toolbox.org:gbonnefille/superbuild-artifact.git") +# We clone master to have a basic configuration, mainly a correct .gitattribute +# git clone $REMOTE --branch master --depth 1 superbuild-artifact +execute_process( + COMMAND ${GIT} "clone" "${REPOSITORY_GIT_URL}" + "--branch" "master" "--depth" "1" "superbuild-artifact" + WORKING_DIRECTORY "${CI_PROJ_DIR}" + ) + +# setting up the repo +# StrictHostKeyChecking so we don't have to add the host as a known key +# -F /dev/null so the agent is not taking a default file ~/.ssh/.. +execute_process( + COMMAND ${GIT} "config" "core.sshCommand" + "ssh -o StrictHostKeyChecking=no -F /dev/null" + WORKING_DIRECTORY ${SB_ARTIFACT_GIT} + RESULT_VARIABLE ssh_res + OUTPUT_VARIABLE ssh_out + ERROR_VARIABLE ssh_err + ) + +if ( DEBUG ) + message( "Step 1: ssh") + message( "ssh_res = ${ssh_res}" ) + message( "ssh_out = ${ssh_out}" ) + message( "ssh_err = ${ssh_err}" ) +endif() + +execute_process( + COMMAND ${GIT} "config" "user.mail" "otbbot@orfeo-toolbox.org" + WORKING_DIRECTORY ${SB_ARTIFACT_GIT} + RESULT_VARIABLE mail_res + OUTPUT_VARIABLE mail_out + ERROR_VARIABLE mail_err + ) + +if ( DEBUG ) + message( "Step 2: mail") + message( "mail_res = ${mail_res}" ) + message( "mail_out = ${mail_out}" ) + message( "mail_err = ${mail_err}" ) +endif() + +execute_process( + COMMAND ${GIT} "config" "user.name" "otbbot" + WORKING_DIRECTORY ${SB_ARTIFACT_GIT} + RESULT_VARIABLE name_res + OUTPUT_VARIABLE name_out + ERROR_VARIABLE name_err + ) + +if ( DEBUG ) + message( "Step 3: name") + message( "name_res = ${name_res}" ) + message( "name_out = ${name_out}" ) + message( "name_err = ${name_err}" ) +endif() + +# create a branche +execute_process( + COMMAND ${GIT} "checkout" "-b" "${BRANCH_NAME}" + WORKING_DIRECTORY ${SB_ARTIFACT_GIT} + RESULT_VARIABLE co_res + OUTPUT_VARIABLE co_out + ERROR_VARIABLE co_err + ) + +if ( DEBUG ) + message( "Step 4: check-o") + message( "co_res = ${co_res}" ) + message( "co_out = ${co_out}" ) + message( "co_err = ${co_err}" ) +endif() + +set ( SB_TAR_NAME "SuperBuild_Install.tar" ) + +# create the tar +# We need to create tar in its directory to avoid weird name in file +# "tar: Removing leading `../../' from member names" +# WARNING +# We are creating a tar containing xdk/.., so when extracting the archive in +# an other environment the output file will be xdk... Obvious isn't it? +# Well... Not for everyone... +# May be for easier maintainability the tar name should be the same as the +# file inside. +execute_process( + COMMAND ${CMAKE_COMMAND} "-E" "tar" "cf" "${SB_TAR_NAME}" + -- "${CTEST_INSTALL_DIRECTORY}" + WORKING_DIRECTORY ${CI_ROOT_DIR} + ) + +# We need to copy the tar file, as it is on a different partition in the gitlab +# context +file ( COPY "${CI_ROOT_DIR}/${SB_TAR_NAME}" DESTINATION "${SB_ARTIFACT_GIT}") + +# In a near futur it might be nice to clean up the mess we made... + +if ( DEBUG ) + if (EXISTS "${SB_ARTIFACT_GIT}/${SB_TAR_NAME}") + message("Tar file exists in superbuild_artefact at: ${SB_ARTIFACT_GIT}/${SB_TAR_NAME}") + else() + message("Tar file does not exist") + endif() +endif() + +# add the file +execute_process( + COMMAND ${GIT} "add" "${SB_TAR_NAME}" + WORKING_DIRECTORY ${SB_ARTIFACT_GIT} + RESULT_VARIABLE add_res + OUTPUT_VARIABLE add_out + ERROR_VARIABLE add_err + ) + +if ( DEBUG ) + message( "Step 5: add") + message( "add_res = ${add_res}" ) + message( "add_out = ${add_out}" ) + message( "add_err = ${add_err}" ) +endif() + + +# commit +# We need the author because otherwise the mail is wrong +# In our case if toto is deploying a key in superbuild-artifact repo +# the the mail will be toto's +execute_process( + COMMAND ${GIT} "commit" "--author=\"otbbot <otbbot@orfeo-toolbox.org>\"" + "-m" "\"New Superbuild for ${SB_MD5} on ${IMAGE_NAME}\"" + WORKING_DIRECTORY ${SB_ARTIFACT_GIT} + RESULT_VARIABLE com_res + OUTPUT_VARIABLE com_out + ERROR_VARIABLE com_err + ) + +if ( DEBUG ) + message( "Step 6: com") + message( "com_res = ${com_res}" ) + message( "com_out = ${com_out}" ) + message( "com_err = ${com_err}" ) +endif() + + +# This part is just for debug +if ( DEBUG ) + execute_process( + COMMAND ${GIT} "log" "-1" + WORKING_DIRECTORY ${SB_ARTIFACT_GIT} + RESULT_VARIABLE log_res + OUTPUT_VARIABLE log_out + ERROR_VARIABLE log_err + ) + + message( "Step 6bis: log") + message( "log_res = ${log_res}" ) + message( "log_out = ${log_out}" ) + message( "log_err = ${log_err}" ) +endif() + +# push +# we should be able to do a simple : git push origin $BRANCH_NAME +execute_process( + COMMAND ${GIT} "push" "${REPOSITORY_GIT_URL}" "${BRANCH_NAME}" + WORKING_DIRECTORY ${SB_ARTIFACT_GIT} + RESULT_VARIABLE push_res + OUTPUT_VARIABLE push_out + ERROR_VARIABLE push_err + ) + +if ( DEBUG ) + message( "Step 7: push") + message( "push_res = ${push_res}" ) + message( "push_out = ${push_out}" ) + message( "push_err = ${push_err}" ) +endif() \ No newline at end of file diff --git a/CI/ubuntu-18.04-gcc-shark.cmake b/CI/sb_configure_options.cmake similarity index 58% rename from CI/ubuntu-18.04-gcc-shark.cmake rename to CI/sb_configure_options.cmake index b9ef2642b4890d8be17aabb164727bb70add5120..1487eedcaf79fce02a113d75d030a6635595c2dc 100644 --- a/CI/ubuntu-18.04-gcc-shark.cmake +++ b/CI/sb_configure_options.cmake @@ -17,8 +17,23 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# For know OTB_DEPENDS is build with default value -# Configuration options for ubuntu-18.04-gcc-shark-3.1.4 +set ( cmake_configure_option +"CMAKE_BUILD_TYPE=${CTEST_BUILD_CONFIGURATION} +CMAKE_INSTALL_PREFIX:PATH=${CTEST_INSTALL_DIRECTORY}") -set(site_option -"opencv_INCLUDE_DIR:PATH=/usr/include") +set ( temporary_option +"OTB_USE_LIBKML=OFF") + +set(concat_options +"${cmake_configure_option} +${temporary_option} +") + +#Transform the previous string in list +string (REPLACE "\n" ";" sb_options ${concat_options}) + +foreach(item ${sb_options}) + set( SB_CONFIGURE_OPTIONS "${SB_CONFIGURE_OPTIONS}-D${item};") +endforeach(item) \ No newline at end of file diff --git a/CI/test/README b/CI/test/README new file mode 100644 index 0000000000000000000000000000000000000000..c6379e2b71a4bc6cde69c8d6b5eeca7a5273ca46 --- /dev/null +++ b/CI/test/README @@ -0,0 +1 @@ +This folder aims at simulating a build directory. It contains the sub-durectory Testing with a Configure.xml file as the one generated by ctest. diff --git a/CI/test/Testing/20190320-1706/Configure.xml b/CI/test/Testing/20190320-1706/Configure.xml new file mode 100644 index 0000000000000000000000000000000000000000..73293b6502b3fee8c7f8c6ca730acd3ccedf23d2 --- /dev/null +++ b/CI/test/Testing/20190320-1706/Configure.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Site BuildName="185_f-54sf_ghs-dgh (out_space)" + BuildStamp="20190320-1706-Experimental_test" + Name="debian-unstable-gcc.42" + Generator="ctest-3.13.4" + CompilerName="" + CompilerVersion="" + OSName="Linux" + Hostname="0e82a8db0490" + OSRelease="4.13.0-43-generic" + OSVersion="#48~16.04.1-Ubuntu SMP Thu May 17 12:56:46 UTC 2018" + OSPlatform="x86_64" + Is64Bits="1" + VendorString="GenuineIntel" + VendorID="Intel Corporation" + FamilyID="6" + ModelID="78" + ProcessorCacheSize="3072" + NumberOfLogicalCPU="4" + NumberOfPhysicalCPU="2" + TotalVirtualMemory="5720" + TotalPhysicalMemory="7858" + LogicalProcessorsPerPhysical="2" + ProcessorClockFrequency="1626.81" + > + <Configure> + <StartDateTime>Mar 20 17:06 UTC</StartDateTime> + <StartConfigureTime>1553101581</StartConfigureTime> + <ConfigureCommand>--</ConfigureCommand> + <Log>--</Log> + <ConfigureStatus>0</ConfigureStatus> + <EndDateTime>Mar 20 17:06 UTC</EndDateTime> + <EndConfigureTime>1553101601</EndConfigureTime> + <ElapsedMinutes>0</ElapsedMinutes> + </Configure> +</Site> diff --git a/CI/test/cdash_test.py b/CI/test/cdash_test.py new file mode 100644 index 0000000000000000000000000000000000000000..d64ce9f26c5975d2968edcf9170851fa5dcac447 --- /dev/null +++ b/CI/test/cdash_test.py @@ -0,0 +1,73 @@ +import unittest +import os.path +import sys + +# This is done so we can access the module handler +synthetic_build_dir = os.path.dirname(os.path.realpath(__file__)) +(module_path , _) = os.path.split(synthetic_build_dir) +sys.path.append(module_path) + +import cdash_handler + + +class TestHandler(unittest.TestCase): + + def test_GetConfigureFile (self): + handler = cdash_handler.Handler() + handler.build_dir = synthetic_build_dir + config_path = handler.GetConfigureFile() + self.assertTrue(os.path.exists(config_path)) + + def test_GetName (self): + handler = cdash_handler.Handler() + handler.build_dir = synthetic_build_dir + name = handler.GetName() + self.assertTrue("185_f-54sf_ghs-dgh (out_space)" == name) + + def test_GetSite (self): + handler = cdash_handler.Handler() + handler.build_dir = synthetic_build_dir + site = handler.GetSite() + self.assertTrue("debian-unstable-gcc.42" == site) + + def test_GetStamp (self): + handler = cdash_handler.Handler() + handler.build_dir = synthetic_build_dir + stamp = handler.GetStamp() + self.assertTrue("20190320-1706-Experimental_test" == stamp) + + def test_GetBuildId (self): + handler = cdash_handler.Handler() + buildid= handler.GetBuildId( site="debian-unstable-gcc" ,\ + stamp="20190319-1243-Experimental" , name="0388a356 (debian_CI)") + self.assertTrue( "1" == buildid ) + + def test_GetBuildUrl (self): + handler = cdash_handler.Handler() + url = handler.GetBuildUrl("1") + self.assertTrue( \ + "https://cdash.orfeo-toolbox.org/buildSummary.php?buildid=1" == url) + + def test_GetBuildStatus (self): + handler = cdash_handler.Handler() + # We need to test error in configure, build, test, and no error + # test buildid 720 + (status , error) = handler.GetBuildStatus("720") + self.assertTrue( status == "failed") + self.assertTrue( error == "Errors occur during tests") + # configure buildid 352 + (status , error) = handler.GetBuildStatus("352") + self.assertTrue( status == "failed") + self.assertTrue( error == "Errors occur during configure") + # build buildid 358 + (status , error) = handler.GetBuildStatus("358") + self.assertTrue( status == "failed") + self.assertTrue( error == "Errors occur during build") + # passing buildid 373 + (status , error) = handler.GetBuildStatus("373") + self.assertTrue( status == "success") + self.assertTrue( error == "") + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/CI/ubuntu-18.04-llvm-shark.cmake b/CI/ubuntu-18.04-fast.cmake similarity index 85% rename from CI/ubuntu-18.04-llvm-shark.cmake rename to CI/ubuntu-18.04-fast.cmake index af3b0283f2b122c7796d6eca61f4892fac11117f..5ba38ec80c18fcf420f77160b528c6555ee1d84e 100644 --- a/CI/ubuntu-18.04-llvm-shark.cmake +++ b/CI/ubuntu-18.04-fast.cmake @@ -18,7 +18,7 @@ # limitations under the License. # -# Configuration options for ubuntu-18.04-llvm-shark-3.1.4 +# Configuration options for ubuntu-18.04-fast set(site_option "opencv_INCLUDE_DIR:PATH=/usr/include @@ -28,4 +28,8 @@ 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_C_COMPILER_LAUNCHER:STRING=ccache -CMAKE_CXX_COMPILER_LAUNCHER:STRING=ccache") +CMAKE_CXX_COMPILER_LAUNCHER:STRING=ccache +OTB_USE_SHARK:BOOL=OFF +BUILD_EXAMPLES:BOOL=OFF") + +set(ci_skip_testing ON) 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/CMake/OTBModuleTest.cmake b/CMake/OTBModuleTest.cmake index 97e21fbf0d80cb69fb10e02072a650e66b9e936c..c1402718ece7ecb92c2aabc0b581f16e7c679aa3 100644 --- a/CMake/OTBModuleTest.cmake +++ b/CMake/OTBModuleTest.cmake @@ -224,7 +224,7 @@ endfunction() function(otb_add_test_mpi) set( _OPTIONS_ARGS ) set( _ONE_VALUE_ARGS NAME NBPROCS COMMAND) - set( _MULTI_VALUE_ARGS ) + set( _MULTI_VALUE_ARGS EXTRA_OPT) cmake_parse_arguments( TEST_MPI "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN} ) # Test nb procs @@ -235,6 +235,6 @@ function(otb_add_test_mpi) foreach(arg IN LISTS TEST_MPI_UNPARSED_ARGUMENTS) list(APPEND ARGS ${arg}) endforeach() - set (test_parameters -np ${TEST_MPI_NBPROCS} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_MPI_COMMAND} ${ARGS}) + set (test_parameters -n ${TEST_MPI_NBPROCS} ${OTB_MPIEXEC_OPT} ${TEST_MPI_EXTRA_OPT} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_MPI_COMMAND} ${ARGS}) otb_add_test(NAME ${TEST_MPI_NAME} COMMAND ${MPIEXEC} ${test_parameters}) endfunction() diff --git a/CMake/OTBStandaloneModuleMacros.cmake b/CMake/OTBStandaloneModuleMacros.cmake index 54e3ada505601f2a0d17559aa80daf61eec71352..e877a15ceb405951e27bddf2e55f914b5ad2d980 100644 --- a/CMake/OTBStandaloneModuleMacros.cmake +++ b/CMake/OTBStandaloneModuleMacros.cmake @@ -101,7 +101,7 @@ endmacro() function(otb_add_test_mpi) set( _OPTIONS_ARGS ) set( _ONE_VALUE_ARGS NAME NBPROCS COMMAND) - set( _MULTI_VALUE_ARGS ) + set( _MULTI_VALUE_ARGS EXTRA_OPT) cmake_parse_arguments( TEST_MPI "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN} ) # Test nb procs @@ -112,7 +112,7 @@ function(otb_add_test_mpi) foreach(arg IN LISTS TEST_MPI_UNPARSED_ARGUMENTS) list(APPEND ARGS ${arg}) endforeach() - set (test_parameters -np ${TEST_MPI_NBPROCS} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_MPI_COMMAND} ${ARGS}) + set (test_parameters -n ${TEST_MPI_NBPROCS} ${OTB_MPIEXEC_OPT} ${TEST_MPI_EXTRA_OPT} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_MPI_COMMAND} ${ARGS}) otb_add_test(NAME ${TEST_MPI_NAME} COMMAND ${MPIEXEC} ${test_parameters}) endfunction() diff --git a/Data/Baseline/OTB-Applications/Files/apTvClTrainRegressionTest_monovar.2.txt b/Data/Baseline/OTB-Applications/Files/apTvClTrainRegressionTest_monovar.2.txt new file mode 100644 index 0000000000000000000000000000000000000000..da64925e95b925035b8027d2c8ccfd3655d23970 --- /dev/null +++ b/Data/Baseline/OTB-Applications/Files/apTvClTrainRegressionTest_monovar.2.txt @@ -0,0 +1 @@ +io.mse: 0.02761062607 diff --git a/Data/Baseline/OTB-Applications/Files/clDT_ModelQB1.1.dt b/Data/Baseline/OTB-Applications/Files/clDT_ModelQB1.1.dt new file mode 100644 index 0000000000000000000000000000000000000000..14e83e643867a596baa6b98ae1966dfb8ad58a67 --- /dev/null +++ b/Data/Baseline/OTB-Applications/Files/clDT_ModelQB1.1.dt @@ -0,0 +1,57 @@ +%YAML:1.0 +--- +opencv_ml_dtree: + format: 3 + is_classifier: 1 + var_all: 5 + var_count: 4 + ord_var_count: 4 + cat_var_count: 1 + training_params: + use_surrogates: 0 + max_categories: 10 + regression_accuracy: 9.9999997764825821e-03 + max_depth: 10 + min_sample_count: 10 + cross_validation_folds: 0 + global_var_idx: 1 + var_idx: [ 0, 1, 2, 3 ] + var_type: [ 0, 0, 0, 0, 1 ] + cat_ofs: [ 0, 0, 0, 0, 0, 0, 0, 0 ] + class_labels: [ 1, 2, 3, 4 ] + missing_subst: [ 0., 0., 0., 0., 0. ] + nodes: + - + depth: 0 + value: 1. + norm_class_idx: 0 + splits: + - { var:0, quality:86., le:-8.9000031352043152e-02 } + - + depth: 1 + value: 1. + norm_class_idx: 0 + splits: + - { var:3, quality:86., le:-1.3876452445983887e+00 } + - + depth: 2 + value: 1. + norm_class_idx: 0 + - + depth: 2 + value: 3. + norm_class_idx: 2 + - + depth: 1 + value: 2. + norm_class_idx: 1 + splits: + - { var:1, quality:86., le:3.4949243068695068e-01 } + - + depth: 2 + value: 2. + norm_class_idx: 1 + - + depth: 2 + value: 4. + norm_class_idx: 3 diff --git a/Data/Baseline/OTB/Images/bfTvVectorDataRasterizeFilter_OutputSHP.3.tif b/Data/Baseline/OTB/Images/bfTvVectorDataRasterizeFilter_OutputSHP.3.tif new file mode 100644 index 0000000000000000000000000000000000000000..a55d2a4fdc0eb3fac06b9f324bafe52905567f78 --- /dev/null +++ b/Data/Baseline/OTB/Images/bfTvVectorDataRasterizeFilter_OutputSHP.3.tif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d45e82154f7f148836f952c6a492d30b40c420f612370002b062eb790601c3ab +size 4004576 diff --git a/Data/Baseline/OTB/Images/bfTvVectorDataRasterizeFilter_OutputSHP.4.tif b/Data/Baseline/OTB/Images/bfTvVectorDataRasterizeFilter_OutputSHP.4.tif new file mode 100644 index 0000000000000000000000000000000000000000..9697dbe2512ad89ad861fc054a56f2fbb3302e23 --- /dev/null +++ b/Data/Baseline/OTB/Images/bfTvVectorDataRasterizeFilter_OutputSHP.4.tif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a86632ee6283bc1c03fce842b011fb29d5106d08d21567157e0b4bf6391bd7b +size 4004576 diff --git a/Data/Input/Classification/apTvClLabeledVector.dbf b/Data/Input/Classification/apTvClLabeledVector.dbf index 8c9c8fa2e9adc2038102e6bbfe03e0e7f47d4ba4..99d7d94a0bc953330ba371b27922c4d0cb7788f6 100644 --- a/Data/Input/Classification/apTvClLabeledVector.dbf +++ b/Data/Input/Classification/apTvClLabeledVector.dbf @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c32639ad40e2cb8d439b0cb5961f0bce1b5bbfd258d13caa2a71392d54605cb4 -size 608145 +oid sha256:a22e6012765efaa5104afc6586b8c8e051294c9e9947f4f4ad25cf6d7cd67f09 +size 608146 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/Examples/FeatureExtraction/HarrisExample.cxx b/Examples/FeatureExtraction/HarrisExample.cxx index 62cc413105b759a9e7b22a0b26c95e0d051af1ff..cde2e254a38da5c1a3523b52918909e5ea6a8e43 100644 --- a/Examples/FeatureExtraction/HarrisExample.cxx +++ b/Examples/FeatureExtraction/HarrisExample.cxx @@ -19,7 +19,7 @@ */ -#include "itkMacro.h" +#include "otbMacro.h" #include "otbImage.h" #include "otbImageFileReader.h" @@ -166,7 +166,7 @@ int main(int argc, char* argv[]) { typedef OutputPointSetType::PointType OutputPointType; OutputPointType pCoordinate = (itList.Value()); - std::cout << pCoordinate << std::endl; + otbLogMacro(Debug, << pCoordinate); ++itList; } diff --git a/Examples/Hyperspectral/HyperspectralUnmixingExample.cxx b/Examples/Hyperspectral/HyperspectralUnmixingExample.cxx index 228e4d7386159a4a3f1ece1660fcdea882f5706e..e45218c390298e7cf84f31a29fec2b9575340f57 100644 --- a/Examples/Hyperspectral/HyperspectralUnmixingExample.cxx +++ b/Examples/Hyperspectral/HyperspectralUnmixingExample.cxx @@ -44,6 +44,8 @@ #include "otbVcaImageFilter.h" #include "otbUnConstrainedLeastSquareImageFilter.h" +#include "itkMersenneTwisterRandomVariateGenerator.h" + int main(int argc, char* argv[]) { if (argc != 7) @@ -71,6 +73,10 @@ int main(int argc, char* argv[]) typedef otb::VectorRescaleIntensityImageFilter<ImageType, ImageType> RescalerType; typedef otb::VectorImageToMatrixImageFilter<ImageType> VectorImageToMatrixImageFilterType; + // We set the seed of the random number generator. + + itk::Statistics::MersenneTwisterRandomVariateGenerator::GetInstance()->SetSeed(121212); + // We instantiate now the image reader and we set the image file name. ReaderType::Pointer reader = ReaderType::New(); diff --git a/Examples/Projections/test/CMakeLists.txt b/Examples/Projections/test/CMakeLists.txt index a65749b842bdbf900b8117f201700c3b70a60c50..5cd898e29184e612e87d43477cd79effbd0a6c24 100644 --- a/Examples/Projections/test/CMakeLists.txt +++ b/Examples/Projections/test/CMakeLists.txt @@ -66,7 +66,7 @@ otb_add_test(NAME prTeVectorDataProjectionExampleTest COMMAND ${OTB_TEST_DRIVER} ) otb_add_test(NAME prTeGeometriesProjectionTest COMMAND ${OTB_TEST_DRIVER} - --compare-ogr ${NOTOL} + --compare-ogr ${EPSILON_7} ${BASELINE}/geometriesProjectionExample.shp ${TEMP}/geometriesProjectionExample.shp Execute $<TARGET_FILE:GeometriesProjectionExample> diff --git a/Examples/Simulation/ProsailModel.cxx b/Examples/Simulation/ProsailModel.cxx index 33ed31b2daa108ad31df4f60caac91edac2f0488..42e06f71691e029c1f55ba3199b175c9f5cd04ee 100644 --- a/Examples/Simulation/ProsailModel.cxx +++ b/Examples/Simulation/ProsailModel.cxx @@ -34,7 +34,7 @@ #include "otbSailModel.h" #include "otbProspectModel.h" - +#include "otbMacro.h" #include "otbImageFileReader.h" #include "otbImageFileWriter.h" @@ -151,13 +151,12 @@ int main(int argc, char* argv[]) for (unsigned int i = 0; i < sail->GetViewingReflectance()->Size(); ++i) { - std::cout << "wavelength : "; - std::cout << sail->GetViewingReflectance()->GetResponse()[i].first; - std::cout << ". Viewing reflectance "; - std::cout << sail->GetViewingReflectance()->GetResponse()[i].second; - std::cout << ". Hemispherical reflectance "; - std::cout << sail->GetHemisphericalReflectance()->GetResponse()[i].second; - std::cout << std::endl; + otbLogMacro(Debug, << "wavelength : " + << sail->GetViewingReflectance()->GetResponse()[i].first + << ". Viewing reflectance " + << sail->GetViewingReflectance()->GetResponse()[i].second + << ". Hemispherical reflectance " + << sail->GetHemisphericalReflectance()->GetResponse()[i].second); } std::ofstream outputFile(OutputName, std::ios::out); diff --git a/Modules/Adapters/OSSIMAdapters/src/otbImageKeywordlist.cxx b/Modules/Adapters/OSSIMAdapters/src/otbImageKeywordlist.cxx index 6de34b30ed9b51edcab3f751057f4370855ee418..84b2ee18a43f2631fa8d3fc6269c103d6546b8d9 100644 --- a/Modules/Adapters/OSSIMAdapters/src/otbImageKeywordlist.cxx +++ b/Modules/Adapters/OSSIMAdapters/src/otbImageKeywordlist.cxx @@ -19,6 +19,7 @@ */ #include "otbImageKeywordlist.h" +#include "otbConfigurationManager.h" #include <cassert> @@ -38,6 +39,7 @@ #include "ossim/ossimTileMapModel.h" #include "ossim/projection/ossimProjectionFactoryRegistry.h" #include "ossim/projection/ossimRpcModel.h" +#include "ossim/base/ossimNotify.h" #pragma GCC diagnostic pop #else #include "ossim/base/ossimKeywordlist.h" @@ -47,6 +49,7 @@ #include "ossim/ossimTileMapModel.h" #include "ossim/projection/ossimProjectionFactoryRegistry.h" #include "ossim/projection/ossimRpcModel.h" +#include "ossim/base/ossimNotify.h" #endif #include "otbSensorModelAdapter.h" @@ -228,6 +231,15 @@ ReadGeometryFromImage(const std::string& filename, bool checkRpcTag) ossimKeywordlist geom_kwl; // = new ossimKeywordlist(); ImageKeywordlist otb_kwl; + // Save Ossim notify flags + ossimPushNotifyFlags(); + + // Except for DEBUG logger level, only fatal errors of OSSIM should be seen + if(otb::ConfigurationManager::GetLoggerLevel() < itk::LoggerBase::DEBUG) + { + ossimSetNotifyFlag(ossimNotifyFlags_FATAL); + } + /****************************************************/ /* First try : test the OSSIM plugins factory */ /****************************************************/ @@ -313,6 +325,9 @@ ReadGeometryFromImage(const std::string& filename, bool checkRpcTag) // which uses ossimSensorModelFactory and ossimPluginProjectionFactory internally, // thus by-passing the need for a valid ossimImageHandler. + // Restore Ossim notify flags + ossimPopNotifyFlags(); + return otb_kwl; } diff --git a/Modules/Adapters/OSSIMAdapters/src/otbSensorModelAdapter.cxx b/Modules/Adapters/OSSIMAdapters/src/otbSensorModelAdapter.cxx index 27316187ac7ff5f1d7434c654b9f03026871dac2..eebdacb42da3f3f3ad5bd03f42b89669a03fba3a 100644 --- a/Modules/Adapters/OSSIMAdapters/src/otbSensorModelAdapter.cxx +++ b/Modules/Adapters/OSSIMAdapters/src/otbSensorModelAdapter.cxx @@ -37,6 +37,8 @@ #include "ossim/projection/ossimRpcProjection.h" #include "ossim/ossimPluginProjectionFactory.h" #include "ossim/base/ossimTieGptSet.h" +#include "ossim/projection/ossimRpcSolver.h" +#include "ossim/imaging/ossimImageGeometry.h" #pragma GCC diagnostic pop #else @@ -46,6 +48,8 @@ #include "ossim/projection/ossimRpcProjection.h" #include "ossim/ossimPluginProjectionFactory.h" #include "ossim/base/ossimTieGptSet.h" +#include "ossim/projection/ossimRpcSolver.h" +#include "ossim/imaging/ossimImageGeometry.h" #endif @@ -221,8 +225,36 @@ double SensorModelAdapter::Optimize() } else if (simpleRpcModel != nullptr) { - // Call optimize fit - precision = simpleRpcModel->optimizeFit(*m_TiePoints); + ossimRefPtr<ossimRpcSolver> rpcSolver = new ossimRpcSolver(false, false); + + std::vector<ossimDpt> imagePoints; + std::vector<ossimGpt> groundPoints; + m_TiePoints->getSlaveMasterPoints(imagePoints, groundPoints); + rpcSolver->solveCoefficients(imagePoints, groundPoints); + +#if OTB_OSSIM_VERSION < 20200 + ossimRefPtr<ossimRpcProjection> rpcProjection = dynamic_cast<ossimRpcProjection*>(rpcSolver->createRpcProjection()->getProjection()); +#else + ossimRefPtr<ossimRpcModel> rpcProjection = rpcSolver->getRpcModel(); +#endif + + if (!rpcProjection) + { + itkExceptionMacro(<< "Optimize(): Failed to solve RPC!"); + } + + ossimKeywordlist geom; + rpcProjection->saveState(geom); +#if OTB_OSSIM_VERSION < 20200 + simpleRpcModel->loadState(geom); +#else + // we have to convert simpleRpcModel into an ossimRpcModel + delete m_SensorModel; + m_SensorModel = new ossimRpcModel; + m_SensorModel->loadState(geom); +#endif + + precision = std::pow(rpcSolver->getRmsError(), 2); } } @@ -238,6 +270,18 @@ bool SensorModelAdapter::ReadGeomFile(const std::string & infile) m_SensorModel = ossimSensorModelFactory::instance()->createProjection(geom); + // search for ossimRpcProjection (not in ossimSensorModelFactory since OSSIM 2) + const char * typeValue = geom.find(0, "type"); + if (m_SensorModel == nullptr && strcmp(typeValue, "ossimRpcProjection") == 0) + { + m_SensorModel = new ossimRpcProjection; + if (!m_SensorModel->loadState(geom)) + { + delete m_SensorModel; + m_SensorModel = nullptr; + } + } + if (m_SensorModel == nullptr) { m_SensorModel = ossimplugins::ossimPluginProjectionFactory::instance()->createProjection(geom); 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/AppImageUtils/test/CMakeLists.txt b/Modules/Applications/AppImageUtils/test/CMakeLists.txt index 182db8fca0cb7815d17a54ffd4cb56aa00211cdc..0e3ed23abab8aa8a3d47d71e9e0c1fd5d28a079d 100644 --- a/Modules/Applications/AppImageUtils/test/CMakeLists.txt +++ b/Modules/Applications/AppImageUtils/test/CMakeLists.txt @@ -44,7 +44,7 @@ otb_test_application(NAME apTvUtDynamicConvertBasic otb_test_application(NAME apTuUtDynamicConvertExtendedFilename_writer APP DynamicConvert OPTIONS -in ${INPUTDATA}/ToulouseExtract_WithGeom.tif - -out ${TEMP}/apTvUtGeomExtendedFilename.tif?&gdal:co:TILED=YES&writegeom=false + -out ${TEMP}/apTvUtNoGeomExtendedFilename.tif?&gdal:co:TILED=YES&writegeom=false ) otb_test_application(NAME apTvUtDynamicConvertExtendedFilename_readerGEOM diff --git a/Modules/Applications/AppProjection/app/otbGenerateRPCSensorModel.cxx b/Modules/Applications/AppProjection/app/otbGenerateRPCSensorModel.cxx index 36ff3a27e097f3791324f94f9aad7cab588518cf..e604e8e4b656317f9c8eb2d2233aefe4b5e54e6b 100644 --- a/Modules/Applications/AppProjection/app/otbGenerateRPCSensorModel.cxx +++ b/Modules/Applications/AppProjection/app/otbGenerateRPCSensorModel.cxx @@ -140,7 +140,7 @@ private: iss >> x >> y >> lon >> lat; z = otb::DEMHandler::Instance()->GetHeightAboveEllipsoid(lon,lat); - otbAppLogINFO("Adding tie point x="<<x<<", y="<<y<<", z="<<z<<", lon="<<lon<<", lat="<<lat); + otbAppLogDEBUG("Adding tie point x="<<x<<", y="<<y<<", z="<<z<<", lon="<<lon<<", lat="<<lat); Point2DType p1; Point3DType p2; diff --git a/Modules/Applications/AppProjection/app/otbRefineSensorModel.cxx b/Modules/Applications/AppProjection/app/otbRefineSensorModel.cxx index 4d3b243cf57f2137d2317f3299659702e7fd0d29..6c1346b288e1423a6bd5e2748c0bff2606c57195 100644 --- a/Modules/Applications/AppProjection/app/otbRefineSensorModel.cxx +++ b/Modules/Applications/AppProjection/app/otbRefineSensorModel.cxx @@ -118,9 +118,12 @@ private: otb::SensorModelAdapter::Pointer sm_ref = otb::SensorModelAdapter::New(); // Read the geom file - sm->ReadGeomFile(GetParameterString("ingeom")); + bool isRead = sm->ReadGeomFile(GetParameterString("ingeom")); sm_ref->ReadGeomFile(GetParameterString("ingeom")); + if (!isRead) + otbAppLogFATAL("Can't read the input geom file!"); + // Setup the DEM Handler otb::Wrapper::ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(this,"elev"); @@ -156,7 +159,7 @@ private: z = otb::DEMHandler::Instance()->GetHeightAboveEllipsoid(lon,lat); - otbAppLogINFO("Adding tie point x="<<x<<", y="<<y<<", z="<<z<<", lon="<<lon<<", lat="<<lat); + otbAppLogDEBUG("Adding tie point x="<<x<<", y="<<y<<", z="<<z<<", lon="<<lon<<", lat="<<lat); sm->AddTiePoint(x,y,z,lon,lat); @@ -210,6 +213,7 @@ private: ofs<<"#ref_lon ref_lat elevation predicted_lon predicted_lat predicted_elev x_error_ref(meters) y_error_ref(meters) global_error_ref(meters) x_error(meters) y_error(meters) global_error(meters)"<<std::endl; } + size_t validPoints=0; for(TiePointsType::const_iterator it = tiepoints.begin(); it!=tiepoints.end(); ++it) { @@ -217,6 +221,22 @@ private: sm->ForwardTransformPoint(it->first[0],it->first[1],it->first[2],tmpPoint[0],tmpPoint[1],tmpPoint[2]); sm_ref->ForwardTransformPoint(it->first[0],it->first[1],it->first[2],tmpPoint_ref[0],tmpPoint_ref[1],tmpPoint_ref[2]); + if (!(std::isfinite(tmpPoint[0]) && + std::isfinite(tmpPoint[1]) && + std::isfinite(tmpPoint[2]))) + { + otbAppLogWARNING("Can't project tie point at ["<<it->first[0]<<","<<it->first[1]<<","<<it->first[2]<<"] with optimized model!"); + continue; + } + + if (!(std::isfinite(tmpPoint_ref[0]) && + std::isfinite(tmpPoint_ref[1]) && + std::isfinite(tmpPoint_ref[2]))) + { + otbAppLogWARNING("Can't project tie point at ["<<it->first[0]<<","<<it->first[1]<<","<<it->first[2]<<"] with original model!"); + continue; + } + tmpPoint = rsTransform->TransformPoint(tmpPoint); tmpPoint_ref = rsTransform->TransformPoint(tmpPoint_ref); @@ -257,29 +277,34 @@ private: meanx_ref += xerror_ref; meany_ref += yerror_ref; + validPoints++; + } + if (!validPoints) + { + otbAppLogFATAL("No valid points to compute RMSE !"); } - rmse/=tiepoints.size(); + rmse/=validPoints; - rmsex/=tiepoints.size(); + rmsex/=validPoints; - rmsey/=tiepoints.size(); + rmsey/=validPoints; - meanx/=tiepoints.size(); - meany/=tiepoints.size(); + meanx/=validPoints; + meany/=validPoints; - rmse_ref/=tiepoints.size(); + rmse_ref/=validPoints; - rmsex_ref/=tiepoints.size(); + rmsex_ref/=validPoints; - rmsey_ref/=tiepoints.size(); + rmsey_ref/=validPoints; - meanx_ref/=tiepoints.size(); - meany_ref/=tiepoints.size(); + meanx_ref/=validPoints; + meany_ref/=validPoints; double stdevx = std::sqrt(rmsex - meanx * meanx); diff --git a/Modules/Applications/AppProjection/test/CMakeLists.txt b/Modules/Applications/AppProjection/test/CMakeLists.txt index 7672754ad00584ffbc094193154d58f52e1fecdd..28b843b2157b84c32720f2a218302b9e36942f2b 100644 --- a/Modules/Applications/AppProjection/test/CMakeLists.txt +++ b/Modules/Applications/AppProjection/test/CMakeLists.txt @@ -151,6 +151,14 @@ otb_test_application(NAME apTvPrConvertCartoToGeoPoint #----------- GenerateRPCSensorModel TESTS ---------------- +# Remove baseline for OSSIM >= 2.2, as ossimRPCProjection.optimizeFit() is broken +set(VALID_CONDITION) +if(OTB_OSSIM_VERSION LESS 20200) +set(VALID_CONDITION + VALID --compare-ascii ${EPSILON_3} + ${BASELINE_FILES}/apTvPrGenerateRPCSensorModelGeomOutput.geom + ${TEMP}/apTvPrGenerateRPCSensorModelGeomOutput.geom) +endif() otb_test_application(NAME apTvPrGenerateRPCSensorModel APP GenerateRPCSensorModel OPTIONS -inpoints ${INPUTDATA}/QB_TOULOUSE_MUL_Extract_500_500_in_tie_points.txt @@ -160,9 +168,7 @@ otb_test_application(NAME apTvPrGenerateRPCSensorModel -map utm -map.utm.zone 31 -map.utm.northhem 1 -elev.dem ${INPUTDATA}/DEM/srtm_directory -elev.geoid ${INPUTDATA}/DEM/egm96.grd - VALID --compare-ascii ${EPSILON_3} - ${BASELINE_FILES}/apTvPrGenerateRPCSensorModelGeomOutput.geom - ${TEMP}/apTvPrGenerateRPCSensorModelGeomOutput.geom) + ${VALID_CONDITION}) #----------- GridBasedImageResampling TESTS ---------------- @@ -281,17 +287,24 @@ otb_test_application(NAME apTvPrRefineSensorModel -elev.geoid ${INPUTDATA}/DEM/egm96.grd VALID --compare-ascii 0.1 ${BASELINE_FILES}/apTvPrRefineSensorModelGeomOutput.geom - ${TEMP}/apTvPrRefineSensorModelGeomOutput.geom) + ${TEMP}/apTvPrRefineSensorModelGeomOutput.geom + --ignore-lines-with 1 support_data.) + +# Remove baseline for OSSIM >= 2, as ossimRPCProjection.optimizeFit() is broken +set(VALID_CONDITION) +if(OTB_OSSIM_VERSION LESS 20200) +set(VALID_CONDITION + VALID --compare-ascii 0.1 + ${BASELINE_FILES}/apTvPrRefineSensorModelGeomOutput2.geom + ${TEMP}/apTvPrRefineSensorModelGeomOutput2.geom) +endif() - otb_test_application(NAME apTvPrRefineSensorModel2 APP RefineSensorModel OPTIONS -ingeom ${INPUTDATA}/s1a-iw-grd-vh-20150210t060009-20150210t060034-004557-0059a3-002.geom -inpoints ${INPUTDATA}/pts_idV5.txt -outgeom ${TEMP}/apTvPrRefineSensorModelGeomOutput2.geom - VALID --compare-ascii 0.1 - ${BASELINE_FILES}/apTvPrRefineSensorModelGeomOutput2.geom - ${TEMP}/apTvPrRefineSensorModelGeomOutput2.geom) + ${VALID_CONDITION}) @@ -330,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/AppSARPolarMatrixConvert/test/CMakeLists.txt b/Modules/Applications/AppSARPolarMatrixConvert/test/CMakeLists.txt index 9f5b23cdeeca105cd7fe4205cc13441ca2b5bc04..56ed2b28b458a3aa7c4ec61797481798cae4beb6 100644 --- a/Modules/Applications/AppSARPolarMatrixConvert/test/CMakeLists.txt +++ b/Modules/Applications/AppSARPolarMatrixConvert/test/CMakeLists.txt @@ -95,7 +95,7 @@ otb_test_application(NAME apTvSARPolarMatrixConvertRecLinCovToRecCirCov OPTIONS -inc ${BASELINE}/saTvSinclairImageFilter_SinclairToReciprocalCovariance.tif -conv mlinearcovariancetocircularcovariance - -outc ${TEMP}/apTvSARPolarMatrixConvertRecCovToRecCoh.tif + -outc ${TEMP}/apTvSARPolarMatrixConvertRecLinCovToRecCirCov.tif ) 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/Feature/Textures/test/otbScalarImageToHigherOrderTexturesFilter.cxx b/Modules/Feature/Textures/test/otbScalarImageToHigherOrderTexturesFilter.cxx index d2298e5796960dd4276c47642cbe6adbe485150e..dbaf3ddfbb271f928bb0676b358a7d7ff6ca7930 100644 --- a/Modules/Feature/Textures/test/otbScalarImageToHigherOrderTexturesFilter.cxx +++ b/Modules/Feature/Textures/test/otbScalarImageToHigherOrderTexturesFilter.cxx @@ -22,6 +22,7 @@ #include "otbImage.h" #include "otbImageFileReader.h" #include "itkExtractImageFilter.h" +#include "otbMacro.h" const unsigned int Dimension = 2; typedef float PixelType; @@ -128,9 +129,9 @@ int ValidateAt( ImageType* inputImage, std::vector<ImageType::Pointer> computeRe PixelType output = computeResults[i]->GetPixel(idx); PixelType reference = featuresMeans[i]; - std::cout << "index : " << idx << std::endl; - std::cout << "compute : " << output << std::endl; - std::cout << "ref : " << reference << std::endl; + otbLogMacro(Debug, << "index = " << idx + << " ; compute = " << output + << " ; ref = " << reference); if (reference != output) { diff --git a/Modules/Filtering/Contrast/test/otbComputeGainLutFilter.cxx b/Modules/Filtering/Contrast/test/otbComputeGainLutFilter.cxx index 74899c7f2d3ddf750b6c1ec7307493188b8fd5f5..2bc307aa9575d4f86ca476d0da6e5bcaeff35baa 100644 --- a/Modules/Filtering/Contrast/test/otbComputeGainLutFilter.cxx +++ b/Modules/Filtering/Contrast/test/otbComputeGainLutFilter.cxx @@ -23,6 +23,7 @@ #include "otbImageFileWriter.h" #include "otbImageFileReader.h" #include "otbComputeGainLutFilter.h" +#include "otbMacro.h" int otbComputeGainLutFilter(int itkNotUsed(argc), char * argv []) { @@ -62,7 +63,7 @@ int otbComputeGainLutFilter(int itkNotUsed(argc), char * argv []) writer->Update(); auto index = computeGainLut->GetOutput()->GetLargestPossibleRegion().GetIndex(); - std::cout<<computeGainLut->GetOutput()->GetPixel( index )<<std::endl; + otbLogMacro(Debug, <<computeGainLut->GetOutput()->GetPixel( index )); return EXIT_SUCCESS; } diff --git a/Modules/Filtering/Path/test/otbImageToEdgePathFilter.cxx b/Modules/Filtering/Path/test/otbImageToEdgePathFilter.cxx index 450d33c2779751a006ba73c2da10f26232724c07..688bd0fca736b92ca78a9acc4f90c4d90550df8b 100644 --- a/Modules/Filtering/Path/test/otbImageToEdgePathFilter.cxx +++ b/Modules/Filtering/Path/test/otbImageToEdgePathFilter.cxx @@ -25,6 +25,7 @@ #include "otbImage.h" #include "otbImageFileReader.h" #include "otbImageFileWriter.h" +#include "otbMacro.h" int otbImageToEdgePathFilter(int itkNotUsed(argc), char * argv[]) { @@ -54,7 +55,7 @@ int otbImageToEdgePathFilter(int itkNotUsed(argc), char * argv[]) pathFilter->Update(); - std::cout << " pathFilter = " << pathFilter << std::endl; + otbLogMacro(Debug, << " pathFilter = " << pathFilter); PathType * outputPath = pathFilter->GetOutput(); @@ -67,7 +68,7 @@ int otbImageToEdgePathFilter(int itkNotUsed(argc), char * argv[]) VertexListTypePointer ptrVertexList = outputPath->GetVertexList(); - std::cout << "Size : " << ptrVertexList->Size() << std::endl; + otbLogMacro(Info, << "Size : " << ptrVertexList->Size()); // Initialize Output Image ImageType::Pointer outputImage = ImageType::New(); @@ -80,7 +81,7 @@ int otbImageToEdgePathFilter(int itkNotUsed(argc), char * argv[]) for (unsigned int cpt = 0; cpt < ptrVertexList->Size(); ++cpt) { - std::cout << " Point " << cpt << " : " << ptrVertexList->GetElement(cpt) << std::endl; + otbLogMacro(Debug, << " Point " << cpt << " : " << ptrVertexList->GetElement(cpt)); IndexType pos; pos[0] = static_cast<unsigned long>(ptrVertexList->GetElement(cpt)[0]); pos[1] = static_cast<unsigned long>(ptrVertexList->GetElement(cpt)[1]); diff --git a/Modules/Filtering/Path/test/otbPathListToHistogramGenerator.cxx b/Modules/Filtering/Path/test/otbPathListToHistogramGenerator.cxx index 23165541122163dbed43f788be8a5d86e2e35766..eaa39a949918925e2c6112d569676b53d9752c36 100644 --- a/Modules/Filtering/Path/test/otbPathListToHistogramGenerator.cxx +++ b/Modules/Filtering/Path/test/otbPathListToHistogramGenerator.cxx @@ -21,7 +21,7 @@ -#include "itkMacro.h" +#include "otbMacro.h" #include "itkPolyLineParametricPath.h" #include "otbOrientationPathFunction.h" #include "otbPathListToHistogramGenerator.h" @@ -78,17 +78,16 @@ int otbPathListToHistogramGenerator(int itkNotUsed(argc), char * argv[]) const HistogramType * histogram = histogramGenerator->GetOutput(); const unsigned int histogramSize = histogram->Size(); - std::cout << "Histogram size " << histogramSize << std::endl; + otbLogMacro(Info, << "Histogram size " << histogramSize); for (unsigned int bin = 0; bin < histogramSize; bin++) { if (histogram->GetFrequency(bin, 0) != NbOfPointsPerHistogram) { - std::cout << "Error in histogram value !" << std::endl; + otbLogMacro(Warning, << "Error in histogram value !"); return EXIT_FAILURE; } - std::cout << "bin = " << bin << " frequency = "; - std::cout << histogram->GetFrequency(bin, 0) << std::endl; + otbLogMacro(Debug, << "bin = " << bin << " frequency = " << histogram->GetFrequency(bin, 0)); } return EXIT_SUCCESS; diff --git a/Modules/Filtering/Projection/test/CMakeLists.txt b/Modules/Filtering/Projection/test/CMakeLists.txt index ce356198437339a0c7cceb404ff537d1125a6ffd..e2e346b3c1805dd0124080886dde1d0356cdd5ee 100644 --- a/Modules/Filtering/Projection/test/CMakeLists.txt +++ b/Modules/Filtering/Projection/test/CMakeLists.txt @@ -112,7 +112,6 @@ foreach( file ${GEOMGCP} ) 1 # imgTol ${current_geotol} # geoTol 0 # create baseline (argv[7]) - 1 # mode verbose 1 # 0 : no keyword check 1 : check needed keywords ) endforeach() @@ -157,7 +156,6 @@ foreach( file ${GEOMGCP} ) 1 # imgTol 1 # geoTol 0 # create baseline (argv[7]) - 1 # mode verbose 0 # 0 : no keyword check 1 : check needed keywords ) endforeach() @@ -608,6 +606,10 @@ otb_add_test(NAME bfTvSpectralAngleDataNodeFeatureFunction_Line COMMAND otbProje 0 ) +set(VALID_CONDITION err=12) +if(OTB_OSSIM_VERSION LESS 20200) +set(VALID_CONDITION err=10) +endif() otb_add_test(NAME prTvGCPsToRPCSensorModelImageCheckInputGcpPointsProjection_WithDEM COMMAND otbProjectionTestDriver otbGCPsToRPCSensorModelImageFilterCheckRpcModel ${INPUTDATA}/QB_TOULOUSE_MUL_Extract_500_500.tif @@ -712,9 +714,13 @@ otb_add_test(NAME prTvGCPsToRPCSensorModelImageCheckInputGcpPointsProjection_Wit 2450 2350 1.43238 43.6063 144.66 2450 2400 1.43239 43.6051 144.932 2450 2450 1.43239 43.6038 136.794 - err=10 # Tolerance in meters, the first goal of this test + ${VALID_CONDITION} # Tolerance in meters, the first goal of this test ) +set(VALID_CONDITION err=20) +if(OTB_OSSIM_VERSION LESS 20200) +set(VALID_CONDITION err=10) +endif() otb_add_test(NAME prTvGCPsToRPCSensorModelImageCheckInputGcpPointsProjection_WithoutDEM COMMAND otbProjectionTestDriver otbGCPsToRPCSensorModelImageFilterCheckRpcModel ${INPUTDATA}/QB_TOULOUSE_MUL_Extract_500_500.tif @@ -819,7 +825,7 @@ otb_add_test(NAME prTvGCPsToRPCSensorModelImageCheckInputGcpPointsProjection_Wit 2450 2350 1.43238 43.6059 0 2450 2400 1.43238 43.6047 0 2450 2450 1.43239 43.6034 0 - err=10 # Tolerance in meters, the first goal of this test + ${VALID_CONDITION} # Tolerance in meters, the first goal of this test ) otb_add_test(NAME prTvGeographicalDistance COMMAND otbProjectionTestDriver @@ -846,10 +852,15 @@ otb_add_test(NAME prTvTileImageFilterGenericRSTransformTest_LASVEGAS_DIMAPv1 COM LARGEINPUT{PLEIADES/LASVEGAS_JP2_DIMAPv1_PRIMARY_PMS_lossless_12bits/IMGPHR_PHR1A_SENSOR_20120217_IPU_20120217_5374-001_V1/IMG_R3C1.JP2} ) -otb_add_test(NAME prTvGCPsToRPCSensorModelImageFilterAndOrtho COMMAND otbProjectionTestDriver +set(VALID_CONDITION) +if(OTB_OSSIM_VERSION LESS 20200) +set(VALID_CONDITION --compare-image ${EPSILON_4} ${BASELINE}/otbGCPsToRPCSensorModelImageFilterAndOrthoOutput.tif - ${TEMP}/otbGCPsToRPCSensorModelImageFilterAndOrthoOutput.tif + ${TEMP}/otbGCPsToRPCSensorModelImageFilterAndOrthoOutput.tif) +endif() +otb_add_test(NAME prTvGCPsToRPCSensorModelImageFilterAndOrtho COMMAND otbProjectionTestDriver + ${VALID_CONDITION} otbGCPsToRPCSensorModelImageFilterAndOrtho ${INPUTDATA}/QB_TOULOUSE_MUL_Extract_500_500.tif ${TEMP}/otbGCPsToRPCSensorModelImageFilterAndOrthoOutput.tif @@ -968,10 +979,15 @@ otb_add_test(NAME prTvGCPsToRPCSensorModelImageFilterAndOrtho COMMAND otbProject #LARGEINPUT{VECTOR/MidiPyrenees/roads.shp} #) -otb_add_test(NAME prTvGCPsToRPCSensorModelImageFilterWithoutDEM COMMAND otbProjectionTestDriver +set(VALID_CONDITION) +if(OTB_OSSIM_VERSION LESS 20200) +set(VALID_CONDITION --compare-ascii ${EPSILON_4} ${BASELINE_FILES}/otbGCPsToRPCSensorModelImageFilterWithoutDEMOutput.txt - ${TEMP}/otbGCPsToRPCSensorModelImageFilterWithoutDEMOutput.txt + ${TEMP}/otbGCPsToRPCSensorModelImageFilterWithoutDEMOutput.txt) +endif() +otb_add_test(NAME prTvGCPsToRPCSensorModelImageFilterWithoutDEM COMMAND otbProjectionTestDriver + ${VALID_CONDITION} otbGCPsToRPCSensorModelImageFilterWithoutDEM ${INPUTDATA}/QB_TOULOUSE_MUL_Extract_500_500.tif ${TEMP}/otbGCPsToRPCSensorModelImageFilterWithoutDEMOutput.txt diff --git a/Modules/Filtering/Projection/test/otbGCPsToRPCSensorModelImageFilterAndOrtho.cxx b/Modules/Filtering/Projection/test/otbGCPsToRPCSensorModelImageFilterAndOrtho.cxx index 8ebb1678fd04526694eb59bc4604f4368985f38c..20dc63f23e52b24bdfadf74aabb6159f61f6372b 100644 --- a/Modules/Filtering/Projection/test/otbGCPsToRPCSensorModelImageFilterAndOrtho.cxx +++ b/Modules/Filtering/Projection/test/otbGCPsToRPCSensorModelImageFilterAndOrtho.cxx @@ -23,6 +23,7 @@ #include "otbImageFileWriter.h" #include "otbGenericMapProjection.h" #include "otbOrthoRectificationFilter.h" +#include "otbMacro.h" int otbGCPsToRPCSensorModelImageFilterAndOrtho(int argc, char* argv[]) { @@ -58,7 +59,7 @@ int otbGCPsToRPCSensorModelImageFilterAndOrtho(int argc, char* argv[]) unsigned int nbGCPs = (argc - 11) / 5; - std::cout << "Receiving " << nbGCPs << " from command line." << std::endl; + otbLogMacro(Info, << "Receiving " << nbGCPs << " from command line."); for (unsigned int gcpId = 0; gcpId < nbGCPs; ++gcpId) { @@ -71,7 +72,7 @@ int otbGCPsToRPCSensorModelImageFilterAndOrtho(int argc, char* argv[]) geoPoint[1] = atof(argv[14 + 5 * gcpId]); geoPoint[2] = atof(argv[15 + 5 * gcpId]); - std::cout << "Adding GCP sensor: " << sensorPoint << " <-> geo: " << geoPoint << std::endl; + otbLogMacro(Debug, << "Adding GCP sensor: " << sensorPoint << " <-> geo: " << geoPoint); rpcEstimator->AddGCP(sensorPoint, geoPoint); } @@ -82,8 +83,8 @@ int otbGCPsToRPCSensorModelImageFilterAndOrtho(int argc, char* argv[]) std::cout.setf(std::ios::fixed, std::ios::floatfield); std::cout.precision(10); - std::cout << rpcEstimator->GetOutput()->GetImageKeywordlist() << std::endl; - std::cout << "Residual ground error: " << rpcEstimator->GetRMSGroundError() << std::endl; + otbLogMacro(Debug, << rpcEstimator->GetOutput()->GetImageKeywordlist()); + otbLogMacro(Info, << "Residual ground error: " << rpcEstimator->GetRMSGroundError()); // Orthorectify the output image WriterType::Pointer writer = WriterType::New(); diff --git a/Modules/Filtering/Projection/test/otbGCPsToRPCSensorModelImageFilterCheckRpcModel.cxx b/Modules/Filtering/Projection/test/otbGCPsToRPCSensorModelImageFilterCheckRpcModel.cxx index 23c60827eba42ff34561c4e951813694ee8928d4..a7f96117e0790366160dace88340ecdc6e7fb131 100644 --- a/Modules/Filtering/Projection/test/otbGCPsToRPCSensorModelImageFilterCheckRpcModel.cxx +++ b/Modules/Filtering/Projection/test/otbGCPsToRPCSensorModelImageFilterCheckRpcModel.cxx @@ -23,6 +23,7 @@ #include "otbGCPsToRPCSensorModelImageFilter.h" #include "otbGenericRSTransform.h" #include "otbGeographicalDistance.h" +#include "otbMacro.h" #include <string> int otbGCPsToRPCSensorModelImageFilterCheckRpcModel(int argc, char * argv[]) @@ -62,7 +63,7 @@ int otbGCPsToRPCSensorModelImageFilterCheckRpcModel(int argc, char * argv[]) rpcEstimator->SetInput(reader->GetOutput()); unsigned int nbGCPs = nbPoints / 5; - std::cout << "Receiving " << nbPoints << " from command line." << std::endl; + otbLogMacro(Info, << "Receiving " << nbPoints << " from command line."); for (unsigned int gcpId = 0; gcpId < nbGCPs; ++gcpId) { @@ -75,7 +76,7 @@ int otbGCPsToRPCSensorModelImageFilterCheckRpcModel(int argc, char * argv[]) geoPoint[1] = std::stof(argv[ 6 + gcpId * 5]); geoPoint[2] = std::stof(argv[ 7 + gcpId * 5]); - std::cout << "Adding GCP sensor: " << sensorPoint << " <-> geo: " << geoPoint << std::endl; + otbLogMacro(Debug, << "Adding GCP sensor: " << sensorPoint << " <-> geo: " << geoPoint); rpcEstimator->AddGCP(sensorPoint, geoPoint); } @@ -91,7 +92,7 @@ int otbGCPsToRPCSensorModelImageFilterCheckRpcModel(int argc, char * argv[]) GenericRSTransformType::Pointer grsTrasnform = GenericRSTransformType::New(); grsTrasnform->SetInputKeywordList(rpcEstimator->GetKeywordlist()); - std::cout<<rpcEstimator->GetKeywordlist()<<std::endl; + otbLogMacro(Debug, <<rpcEstimator->GetKeywordlist()); grsTrasnform->SetOutputProjectionRef("EPSG:4326"); // Set the DEM Directory @@ -126,11 +127,9 @@ int otbGCPsToRPCSensorModelImageFilterCheckRpcModel(int argc, char * argv[]) // Search for nans if ( vnl_math_isnan(transformedPoint2D[0]) || vnl_math_isnan(transformedPoint2D[1]) ) { - std::cout << "Reference : "<< geoPoint - <<" --> Result of the reprojection using the estimated RpcModel "<< transformedPoint2D - << std::endl; - std::cout<<"The result of the projection is nan, there is a problem with the estimated RpcModel " - << std::endl<<std::endl; + otbLogMacro(Warning, << "Reference : "<< geoPoint + <<" --> Result of the reprojection using the estimated RpcModel "<< transformedPoint2D); + otbLogMacro(Warning, <<"The result of the projection is nan, there is a problem with the estimated RpcModel"); isErrorDetected = true; } @@ -138,14 +137,13 @@ int otbGCPsToRPCSensorModelImageFilterCheckRpcModel(int argc, char * argv[]) double residual = geoDistance->Evaluate(geoPoint, transformedPoint2D); if( residual > tol ) { - std::cout << "Reference : "<< geoPoint - <<" --> Result of the reprojection using the estimated RpcModel " - << transformedPoint2D - << std::endl - << " Residual ["<< residual << "] is higher than the tolerance [" - << tol - <<"], there is a problem with the estimated RpcModel" - <<std::endl<<std::endl; + otbLogMacro(Warning, << "Reference : "<< geoPoint + <<" --> Result of the reprojection using the estimated RpcModel " + << transformedPoint2D + << std::endl + << " Residual ["<< residual << "] is higher than the tolerance [" + << tol + <<"], there is a problem with the estimated RpcModel"); isErrorDetected = true; } } diff --git a/Modules/Filtering/Projection/test/otbGCPsToRPCSensorModelImageFilterWithoutDEM.cxx b/Modules/Filtering/Projection/test/otbGCPsToRPCSensorModelImageFilterWithoutDEM.cxx index 454efe2bec765317ade7baf261d3bb1307ee97a2..e09549e06e51570fefb2b134a627680dc53f5c50 100644 --- a/Modules/Filtering/Projection/test/otbGCPsToRPCSensorModelImageFilterWithoutDEM.cxx +++ b/Modules/Filtering/Projection/test/otbGCPsToRPCSensorModelImageFilterWithoutDEM.cxx @@ -53,7 +53,7 @@ int otbGCPsToRPCSensorModelImageFilterWithoutDEM(int argc, char* argv[]) unsigned int nbGCPs = (argc - 3) / 5; - std::cout << "Receiving " << nbGCPs << " from command line." << std::endl; + otbLogMacro(Info, << "Receiving " << nbGCPs << " from command line."); for (unsigned int gcpId = 0; gcpId < nbGCPs; ++gcpId) { @@ -66,7 +66,7 @@ int otbGCPsToRPCSensorModelImageFilterWithoutDEM(int argc, char* argv[]) geoPoint[1] = atof(argv[6 + 5 * gcpId]); geoPoint[2] = atof(argv[7 + 5 * gcpId]); - std::cout << "Adding GCP sensor: " << sensorPoint << " <-> geo: " << geoPoint << std::endl; + otbLogMacro(Debug, << "Adding GCP sensor: " << sensorPoint << " <-> geo: " << geoPoint); rpcEstimator->AddGCP(sensorPoint, geoPoint); } diff --git a/Modules/Filtering/Projection/test/otbSensorModel.cxx b/Modules/Filtering/Projection/test/otbSensorModel.cxx index f6b3c0454a7fd69a42806915eb216a7a3e15f59b..d64e315160dfb4cf90e58649f357cd48a02de6cb 100644 --- a/Modules/Filtering/Projection/test/otbSensorModel.cxx +++ b/Modules/Filtering/Projection/test/otbSensorModel.cxx @@ -34,6 +34,7 @@ #include "itkEuclideanDistanceMetric.h" #include "otbGeographicalDistance.h" #include "otbGenericRSTransform.h" +#include "otbMacro.h" #if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic push @@ -65,7 +66,7 @@ int produceGCP(char * outputgcpfilename, const otb::ImageKeywordlist& kwlist, bo forwardSensorModel->SetImageGeometry(kwlist); if( forwardSensorModel->IsValidSensorModel() == false ) { - std::cout<<"Invalid Model pointer m_Model == NULL!\n The ossim keywordlist is invalid!"<<std::endl; + otbLogMacro(Warning, <<"Invalid Model pointer m_Model == NULL!\n The ossim keywordlist is invalid!"); return EXIT_FAILURE; } @@ -155,11 +156,11 @@ bool provideGCP(char * gcpfilename, pointsContainerType& imgPt, geo3dPointsConta int otbSensorModel(int argc, char* argv[]) { - if (argc != 10) + if (argc != 9) { std::cout << argv[0] << " <input geom filename> <input gcp filename> <output gcp filename> " - <<" <needed keywords> <imgTol> <geoTol> <writeBaseline> <modeVerbose> <only check needed keywords>" << std::endl; + <<" <needed keywords> <imgTol> <geoTol> <writeBaseline> <only check needed keywords>" << std::endl; return EXIT_FAILURE; } @@ -171,8 +172,7 @@ int otbSensorModel(int argc, char* argv[]) double imgTol = atof(argv[5]); double geoTol = atof(argv[6]); int writeBaseline = atoi(argv[7]); - int modeVerbose = atoi(argv[8]); - bool checkNeededKw = atoi(argv[9]); + bool checkNeededKw = atoi(argv[8]); // ------------------- // Some instantiations @@ -370,21 +370,18 @@ int otbSensorModel(int argc, char* argv[]) geoPointOSSIM[1] = ossimGPoint.lat; // Just for debug purpose - if (modeVerbose) - { - std::cout << ">>>>>>>>>>>>>> ---------------------" << std::endl; - std::cout << ">>>>>>>>>>>>>>" << geomfilename << std::endl; - std::cout << ">>>>>>>>>>>>>>" << std::setprecision(15) - << "Image to geo (Inverse/Forward SensorModel): " << imagePoint << " -> " << geoPoint << "\n"; - std::cout << ">>>>>>>>>>>>>>" << std::setprecision(15) - << "Geo to image (Inverse/Forward SensorModel): " << geoPoint << " -> " << reversedImagePoint << "\n"; - std::cout << ">>>>>>>>>>>>>>" << std::setprecision(15) - << "Image to geo (GenericRSTransform): " << imagePoint << " -> " << geoPointGRS << "\n"; - std::cout << ">>>>>>>>>>>>>>" << std::setprecision(15) - << "Geo to image (GenericRSTransform): " << geoPointGRS << " -> " << reversedImagePointGRS << "\n"; - std::cout << ">>>>>>>>>>>>>>" << std::setprecision(15) - << "Image to geo (OSSIM): " << imagePoint << " -> " << geoPointOSSIM << "\n"; - } + otbLogMacro(Debug, << "------------------------------------------------"); + otbLogMacro(Debug, << geomfilename); + otbLogMacro(Debug, << std::setprecision(15) + << "Image to geo (Inverse/Forward SensorModel): " << imagePoint << " -> " << geoPoint); + otbLogMacro(Debug, << std::setprecision(15) + << "Geo to image (Inverse/Forward SensorModel): " << geoPoint << " -> " << reversedImagePoint); + otbLogMacro(Debug, << std::setprecision(15) + << "Image to geo (GenericRSTransform): " << imagePoint << " -> " << geoPointGRS); + otbLogMacro(Debug, << std::setprecision(15) + << "Geo to image (GenericRSTransform): " << geoPointGRS << " -> " << reversedImagePointGRS); + otbLogMacro(Debug, << std::setprecision(15) + << "Image to geo (OSSIM): " << imagePoint << " -> " << geoPointOSSIM); // 3. Results should be plausible (no NaN and no clearly out of bound results) @@ -477,12 +474,9 @@ int otbSensorModel(int argc, char* argv[]) double dist6 = geoDistance->Evaluate(geoPointGRS, geoPointGCP); double dist7 = geoDistance->Evaluate(geoPointOSSIM, geoPointGCP); - if (modeVerbose) - { - std::cout << ">>>>>>>>>>>>>>" << "Forward SensorModel VS GCP : " << dist5 << std::endl; - std::cout << ">>>>>>>>>>>>>>" << "GenericRSTransform VS GCP : " << dist6 << std::endl; - std::cout << ">>>>>>>>>>>>>>" << "OSSIM VS GCP : " << dist7 << std::endl; - } + otbLogMacro(Debug, << "Forward SensorModel VS GCP : " << dist5); + otbLogMacro(Debug, << "GenericRSTransform VS GCP : " << dist6); + otbLogMacro(Debug, << "OSSIM VS GCP : " << dist7); if (dist5>geoTol) { diff --git a/Modules/Filtering/Wavelet/include/otbWaveletOperatorBase.hxx b/Modules/Filtering/Wavelet/include/otbWaveletOperatorBase.hxx index 704e8eff1809e13aee0570b76f312c4a0b4720ce..193ed93eca16281259824f9d3699212698633ef0 100644 --- a/Modules/Filtering/Wavelet/include/otbWaveletOperatorBase.hxx +++ b/Modules/Filtering/Wavelet/include/otbWaveletOperatorBase.hxx @@ -156,14 +156,9 @@ void WaveletOperatorBase<TMotherWaveletOperator, TPixel, VDimension, TAllocator> ::ReduceFilterLength(CoefficientVector& coeff) { - const unsigned int length = coeff.size(); - assert(length >= 2); - CoefficientVector newFilter(length - 2); - for (unsigned int i = 0; i < newFilter.size(); ++i) - { - newFilter[i] = coeff[i + 1]; - } - coeff = newFilter; + assert(coeff.size() >= 2); + coeff.pop_back(); + coeff.erase(coeff.begin()); } } // end of namespace otb diff --git a/Modules/IO/IOGDAL/src/otbOGRIOHelper.cxx b/Modules/IO/IOGDAL/src/otbOGRIOHelper.cxx index f0bd16acb33d5cc824933eaa9ac7610c331f3ca7..3f4d9771db9bfe0bbe1125a6380389af162f139b 100644 --- a/Modules/IO/IOGDAL/src/otbOGRIOHelper.cxx +++ b/Modules/IO/IOGDAL/src/otbOGRIOHelper.cxx @@ -772,7 +772,9 @@ unsigned int OGRIOHelper if (std::string(key) != "FID") { // Edit the value of the field and add it to the current feature - ogrFeature->SetField(ogrFeature->GetFieldIndex(key) , kwl.GetFieldAsString(key).c_str()); + int fIndex = ogrFeature->GetFieldIndex(key); + if (fIndex >= 0) + ogrFeature->SetField(fIndex , kwl.GetFieldAsString(key).c_str()); } } @@ -826,7 +828,9 @@ unsigned int OGRIOHelper // Get the key of the Nth OGRFieldRefn const char * key = kwl.GetNthField(i).first->GetNameRef(); // Edit the value of the field and add it to the current feature - ogrFeature->SetField(ogrFeature->GetFieldIndex(key) , kwl.GetFieldAsString(key).c_str()); + int fIndex = ogrFeature->GetFieldIndex(key); + if (fIndex >= 0) + ogrFeature->SetField(fIndex , kwl.GetFieldAsString(key).c_str()); } // ogrFeature->SetField("Name", dataNode->GetNodeId()); @@ -911,7 +915,9 @@ unsigned int OGRIOHelper // Get the key of the Nth OGRFieldRefn const char * key = kwl.GetNthField(i).first->GetNameRef(); // Edit the value of the field and add it to the current feature - ogrFeature->SetField(ogrFeature->GetFieldIndex(key) , kwl.GetFieldAsString(key).c_str()); + int fIndex = ogrFeature->GetFieldIndex(key); + if (fIndex >= 0) + ogrFeature->SetField(fIndex , kwl.GetFieldAsString(key).c_str()); } ogrFeature->SetGeometry(ogrPolygon); diff --git a/Modules/IO/ImageIO/include/otbImageFileReader.hxx b/Modules/IO/ImageIO/include/otbImageFileReader.hxx index 09c7e0cae81c623443aeb33566093047a2a67c7c..4d39b7cd1797e35930be419fbf797291b0469b47 100644 --- a/Modules/IO/ImageIO/include/otbImageFileReader.hxx +++ b/Modules/IO/ImageIO/include/otbImageFileReader.hxx @@ -445,7 +445,7 @@ ImageFileReader<TOutputImage, ConvertPixelTraits> } if (otb_kwl.Empty()) { - otbLogMacro(Info,<< "No kwl metadata found in file "<<lFileNameOssimKeywordlist); + otbLogMacro(Debug,<< "No kwl metadata found in file "<<lFileNameOssimKeywordlist); } } } diff --git a/Modules/IO/ImageIO/test/CMakeLists.txt b/Modules/IO/ImageIO/test/CMakeLists.txt index 04d68c8293cc8e29b00c957863e6abd96f45a694..6fd2e7e6fd5957f9e91e724b67f27283bedf190b 100644 --- a/Modules/IO/ImageIO/test/CMakeLists.txt +++ b/Modules/IO/ImageIO/test/CMakeLists.txt @@ -1352,6 +1352,7 @@ otb_add_test(NAME ioTvCompoundMetadataReaderTest --compare-ascii ${EPSILON_9} ${INPUTDATA}/QB_Toulouse_SensorModel_labelImage.geom ${TEMP}/ioTvCompoundMetadataReaderTest.geom + --ignore-lines-with 1 support_data. otbWriteGeomFile ${INPUTDATA}/QB_Toulouse_combo.vrt ${TEMP}/ioTvCompoundMetadataReaderTest.tif) diff --git a/Modules/IO/ImageIO/test/otbComplexImageManipulationTest.cxx b/Modules/IO/ImageIO/test/otbComplexImageManipulationTest.cxx index aa59af502ce74303a5a8cac74c854015a591abca..2cd546a6f7988116852a3e79f010a347cf6a92b7 100644 --- a/Modules/IO/ImageIO/test/otbComplexImageManipulationTest.cxx +++ b/Modules/IO/ImageIO/test/otbComplexImageManipulationTest.cxx @@ -68,11 +68,11 @@ bool IsEqual(itk::VariableLengthVector<TInternalPixel> output, itk::VariableLeng template<class TIndex, class TPixel> bool TestCompare(TIndex idx, TPixel output, TPixel expected) { - std::cout << "PIXEL " << idx << " --> " + otbLogMacro(Debug, << "PIXEL " << idx << " --> " << "OUTPUT = " << output << " || " << "EXPECTED = " << expected - << std::endl; + << std::endl); if (!IsEqual(output, expected)) { diff --git a/Modules/IO/TestKernel/include/otbTestHelper.h b/Modules/IO/TestKernel/include/otbTestHelper.h index 19f7207d04124dfbcf45934772687910e021baad..a99b106e1b4b4a32f0d934aca60e3887713b73fd 100644 --- a/Modules/IO/TestKernel/include/otbTestHelper.h +++ b/Modules/IO/TestKernel/include/otbTestHelper.h @@ -60,38 +60,45 @@ public: typedef std::vector<std::string> StringList; typedef StringList::const_iterator StringListIt; + typedef std::vector<double> EpsilonList; + typedef EpsilonList::const_iterator EpsilonListIt; + TestHelper(); ~TestHelper() override; int RegressionTestAllImages(const StringList& baselineFilenamesImage, - const StringList& testFilenamesImage); + const StringList& testFilenamesImage, + const EpsilonList& epsilons); int RegressionTestAllMetaData(const StringList& baselineFilenamesMetaData, - const StringList& testFilenamesMetaData); + const StringList& testFilenamesMetaData, + const EpsilonList& epsilons); int RegressionTestAllAscii(const StringList& baselineFilenamesAscii, const StringList& testFilenamesAscii, + const EpsilonList& epsilons, const StringList& ignoredLines); int RegressionTestAllDiff(const StringList& baselineFilenamesAscii, const StringList& testFilenamesAscii, + const EpsilonList& epsilons, const StringList& ignoredLines); int RegressionTestAllBinary(const StringList& baselineFilenamesBinary, const StringList& testFilenamesBinary); int RegressionTestAllOgr(const StringList& baselineFilenamesOgr, - const StringList& testFilenamesOgr); + const StringList& testFilenamesOgr, + const EpsilonList& epsilons); itkSetMacro(ReportErrors, bool); itkBooleanMacro(ReportErrors); itkSetMacro(IgnoreLineOrder, bool); itkBooleanMacro(IgnoreLineOrder); - itkSetMacro(ToleranceDiffValue, double); - itkSetMacro(Epsilon, double); itkSetMacro(EpsilonBoundaryChecking, double); + itkSetMacro(ToleranceRatio, double); private: @@ -157,8 +164,7 @@ private: static void DumpOGRFeature(FILE* fileid, OGRFeature* feature, char** papszOptions = nullptr); static void DumpOGRGeometry(FILE* fileid, OGRGeometry* geometry, const char * pszPrefix, char** papszOptions = nullptr); - double m_ToleranceDiffValue; - double m_Epsilon; + double m_ToleranceRatio; double m_EpsilonBoundaryChecking; bool m_ReportErrors; bool m_IgnoreLineOrder; diff --git a/Modules/IO/TestKernel/include/otbTestMain.h b/Modules/IO/TestKernel/include/otbTestMain.h index 40696ad53934f22e1864e316565cda2f79b7ae3e..d0d988393af1207beb29467ae5919191f17432e2 100644 --- a/Modules/IO/TestKernel/include/otbTestMain.h +++ b/Modules/IO/TestKernel/include/otbTestMain.h @@ -69,6 +69,25 @@ void LoadTestEnv() itk::Statistics::MersenneTwisterRandomVariateGenerator::GetInstance()->SetSeed(121212); } +/** CheckOption, utility function to test the presence of a given token + * in the argument list. The function also checks if there are at least 'min' + * arguments left to parse the token (token included) */ +bool CheckOption(char* arg,const char* token,int ac, int min) +{ + if( strcmp(arg, token) == 0 ) + { + if (min < ac) + { + return true; + } + else + { + std::cerr << "Can't parse token '"<<token<< "', need at least "<<min-1<<" arguments after.\n"; + } + } + return false; +} + int main(int ac, char* av[]) { #ifdef OTB_USE_MPI @@ -76,10 +95,13 @@ int main(int ac, char* av[]) #endif bool lFlagRegression(false); - double lToleranceDiffValue(0); - double lEpsilon(0); + std::vector<double> toleranceDiffValues; + std::vector<double> toleranceOgrValues; + std::vector<double> toleranceMetaValues; + std::vector<double> toleranceAsciiValues; bool lIgnoreOrder(false); double epsilonBoundary(0.0); + double lToleranceRatio(0.0); typedef otb::TestHelper::StringList StringList; StringList baselineFilenamesBinary; @@ -125,185 +147,176 @@ int main(int ac, char* av[]) } else { - if (strcmp(av[1], "--with-threads") == 0) - { - int numThreads = atoi(av[2]); - itk::MultiThreader::SetGlobalDefaultNumberOfThreads(numThreads); - av += 2; - ac -= 2; - } - else if (strcmp(av[1], "--without-threads") == 0) - { - itk::MultiThreader::SetGlobalDefaultNumberOfThreads(1); - av += 1; - ac -= 1; - } - if (strcmp(av[1], "--ignore-order") == 0) - { - lIgnoreOrder = true; - av += 1; - ac -= 1; - } - if (strcmp(av[1], "--epsilon-boundary") == 0) - { - epsilonBoundary = atof(av[2]); - av += 2; - ac -= 2; - } - if (strcmp(av[1], "--compare-image") == 0) - { - lFlagRegression = true; - lToleranceDiffValue = (double) (::atof(av[2])); - baselineFilenamesImage.reserve(1); - testFilenamesImage.reserve(1); - baselineFilenamesImage.push_back(av[3]); - testFilenamesImage.push_back(av[4]); - av += 4; - ac -= 4; - } - else if (strcmp(av[1], "--compare-n-images") == 0) + int ac0 = ac+1; + while (strncmp(av[1], "--", 2) == 0 && ac0 > ac) { - lFlagRegression = true; - lToleranceDiffValue = (double) (::atof(av[2])); - // Number of comparisons to do - unsigned int nbComparisons = (unsigned int) (::atoi(av[3])); - baselineFilenamesImage.reserve(nbComparisons); - testFilenamesImage.reserve(nbComparisons); - // Retrieve all the file names - for (unsigned int i = 0; i < nbComparisons; ++i) + ac0 = ac; + if (CheckOption(av[1],"--with-threads", ac, 2)) { - baselineFilenamesImage.push_back(av[4 + 2 * i]); - testFilenamesImage.push_back(av[5 + 2 * i]); + int numThreads = atoi(av[2]); + itk::MultiThreader::SetGlobalDefaultNumberOfThreads(numThreads); + av += 2; + ac -= 2; } - av += 3 + 2 * nbComparisons; - ac -= 3 + 2 * nbComparisons; - } - else if (strcmp(av[1], "--compare-binary") == 0) - { - lFlagRegression = true; - baselineFilenamesBinary.reserve(1); - testFilenamesBinary.reserve(1); - baselineFilenamesBinary.push_back(av[2]); - testFilenamesBinary.push_back(av[3]); - av += 3; - ac -= 3; - } - else if (strcmp(av[1], "--compare-n-binary") == 0) - { - lFlagRegression = true; - unsigned int nbComparisons = (unsigned int) (::atoi(av[2])); - baselineFilenamesBinary.reserve(nbComparisons); - testFilenamesBinary.reserve(nbComparisons); - // Retrieve all the file names - for (unsigned int i = 0; i < nbComparisons; ++i) + else if (CheckOption(av[1], "--without-threads",ac, 1)) { - baselineFilenamesBinary.push_back(av[3 + 2 * i]); - testFilenamesBinary.push_back(av[4 + 2 * i]); + itk::MultiThreader::SetGlobalDefaultNumberOfThreads(1); + av += 1; + ac -= 1; } - av += 2 + 2 * nbComparisons; - ac -= 2 + 2 * nbComparisons; - } - /************************************************************************/ - // COMPARE ASCII - else if (strcmp(av[1], "--compare-ascii") == 0) - { - lFlagRegression = true; - lEpsilon = (double) (::atof(av[2])); - baselineFilenamesAscii.reserve(1); - testFilenamesAscii.reserve(1); - baselineFilenamesAscii.push_back(av[3]); - testFilenamesAscii.push_back(av[4]); - av += 4; - ac -= 4; - - if (ac > 1) + else if (CheckOption(av[1], "--ignore-order", ac, 1)) + { + lIgnoreOrder = true; + av += 1; + ac -= 1; + } + else if (CheckOption(av[1], "--epsilon-boundary", ac, 2)) { - if (strcmp(av[1], "--ignore-lines-with") == 0) + epsilonBoundary = atof(av[2]); + av += 2; + ac -= 2; + } + else if (CheckOption(av[1], "--compare-image", ac, 4)) + { + lFlagRegression = true; + toleranceDiffValues.push_back((double) (::atof(av[2]))); + baselineFilenamesImage.push_back(av[3]); + testFilenamesImage.push_back(av[4]); + av += 4; + ac -= 4; + } + else if (CheckOption(av[1], "--compare-n-images", ac, 3)) + { + lFlagRegression = true; + // Number of comparisons to do + unsigned int nbComparisons = (unsigned int) (::atoi(av[3])); + double tol = (double) (::atof(av[2])); + toleranceDiffValues.reserve(toleranceDiffValues.size() + nbComparisons); + baselineFilenamesImage.reserve(baselineFilenamesImage.size() + nbComparisons); + testFilenamesImage.reserve(testFilenamesImage.size() + nbComparisons); + // Retrieve all the file names + for (unsigned int i = 0; i < nbComparisons; ++i) { - unsigned int nbIgnoredLines = (unsigned int) (::atoi(av[2])); - for (unsigned int i = 0; i < nbIgnoredLines; ++i) - { - ignoredLines.push_back(av[3 + i]); - } - av += 2 + nbIgnoredLines; - ac -= 2 + nbIgnoredLines; + toleranceDiffValues.push_back(tol); + baselineFilenamesImage.push_back(av[4 + 2 * i]); + testFilenamesImage.push_back(av[5 + 2 * i]); } + av += 3 + 2 * nbComparisons; + ac -= 3 + 2 * nbComparisons; } - } - /************************************************************************/ - else if (strcmp(av[1], "--compare-n-ascii") == 0) - { - lFlagRegression = true; - lEpsilon = (double) (::atof(av[2])); - // Number of comparisons to do - unsigned int nbComparisons = (unsigned int) (::atoi(av[3])); - baselineFilenamesAscii.reserve(nbComparisons); - testFilenamesAscii.reserve(nbComparisons); - // Retrieve all the file names - for (unsigned int i = 0; i < nbComparisons; ++i) + else if (CheckOption(av[1], "--compare-binary", ac, 3)) { - baselineFilenamesAscii.push_back(av[4 + 2 * i]); - testFilenamesAscii.push_back(av[5 + 2 * i]); + lFlagRegression = true; + baselineFilenamesBinary.reserve(1); + testFilenamesBinary.reserve(1); + baselineFilenamesBinary.push_back(av[2]); + testFilenamesBinary.push_back(av[3]); + av += 3; + ac -= 3; } - av += 3 + 2 * nbComparisons; - ac -= 3 + 2 * nbComparisons; - - if (ac > 1) + else if (CheckOption(av[1], "--compare-n-binary", ac, 2)) { - if (strcmp(av[1], "--ignore-lines-with") == 0) + lFlagRegression = true; + unsigned int nbComparisons = (unsigned int) (::atoi(av[2])); + baselineFilenamesBinary.reserve(nbComparisons); + testFilenamesBinary.reserve(nbComparisons); + // Retrieve all the file names + for (unsigned int i = 0; i < nbComparisons; ++i) { - unsigned int nbIgnoredLines = (unsigned int) (::atoi(av[2])); - for (unsigned int i = 0; i < nbIgnoredLines; ++i) - { - ignoredLines.push_back(av[3 + i]); - } - av += 2 + nbIgnoredLines; - ac -= 2 + nbIgnoredLines; + baselineFilenamesBinary.push_back(av[3 + 2 * i]); + testFilenamesBinary.push_back(av[4 + 2 * i]); } + av += 2 + 2 * nbComparisons; + ac -= 2 + 2 * nbComparisons; } + /************************************************************************/ + // COMPARE ASCII + else if (CheckOption(av[1], "--compare-ascii", ac, 4)) + { + lFlagRegression = true; + toleranceAsciiValues.push_back((double) (::atof(av[2]))); + baselineFilenamesAscii.push_back(av[3]); + testFilenamesAscii.push_back(av[4]); + av += 4; + ac -= 4; + } + else if (CheckOption(av[1], "--compare-n-ascii", ac, 3)) + { + lFlagRegression = true; + double tol = (double) (::atof(av[2])); + // Number of comparisons to do + unsigned int nbComparisons = (unsigned int) (::atoi(av[3])); + baselineFilenamesAscii.reserve(baselineFilenamesAscii.size() + nbComparisons); + testFilenamesAscii.reserve(testFilenamesAscii.size() + nbComparisons); + // Retrieve all the file names + for (unsigned int i = 0; i < nbComparisons; ++i) + { + toleranceAsciiValues.push_back(tol); + baselineFilenamesAscii.push_back(av[4 + 2 * i]); + testFilenamesAscii.push_back(av[5 + 2 * i]); + } + av += 3 + 2 * nbComparisons; + ac -= 3 + 2 * nbComparisons; + } + else if (CheckOption(av[1], "--ignore-lines-with", ac, 2)) + { + unsigned int nbIgnoredLines = (unsigned int) (::atoi(av[2])); + for (unsigned int i = 0; i < nbIgnoredLines; ++i) + { + ignoredLines.push_back(av[3 + i]); + } + av += 2 + nbIgnoredLines; + ac -= 2 + nbIgnoredLines; + } + /************************************************************************/ + else if (CheckOption(av[1], "--compare-metadata", ac, 4)) + { + lFlagRegression = true; + toleranceMetaValues.push_back((double) (::atof(av[2]))); + baselineFilenamesMetaData.push_back(av[3]); + testFilenamesMetaData.push_back(av[4]); + av += 4; + ac -= 4; + } + else if (CheckOption(av[1], "--compare-ogr", ac, 4)) + { + lFlagRegression = true; + toleranceOgrValues.push_back((double) (::atof(av[2]))); + baselineFilenamesOgr.push_back(av[3]); + testFilenamesOgr.push_back(av[4]); + av += 4; + ac -= 4; + } + else if (CheckOption(av[1], "--tolerance-ratio", ac, 2)) + { + lToleranceRatio = (double) (::atof(av[2])); + av += 2; + ac -= 2; + } + } // end while - } - else if (strcmp(av[1], "--compare-metadata") == 0) - { - lFlagRegression = true; - lToleranceDiffValue = (double) (::atof(av[2])); - baselineFilenamesMetaData.reserve(1); - testFilenamesMetaData.reserve(1); - baselineFilenamesMetaData.push_back(av[3]); - testFilenamesMetaData.push_back(av[4]); - av += 4; - ac -= 4; - } - - else if (strcmp(av[1], "--compare-ogr") == 0) + // Check there is one argument left for the test + if (ac >= 2) { - lFlagRegression = true; - lToleranceDiffValue = (double) (::atof(av[2])); - baselineFilenamesOgr.reserve(1); - testFilenamesOgr.reserve(1); - baselineFilenamesOgr.push_back(av[3]); - testFilenamesOgr.push_back(av[4]); - av += 4; - ac -= 4; + testToRun = av[1]; } - testToRun = av[1]; } otb::ConfigurationManager::InitOpenMPThreads(); std::map<std::string, MainFuncPointer>::iterator j = StringToTestFunctionMap.find(testToRun); + int result = EXIT_SUCCESS; // If the test doesn't exists if ( j == StringToTestFunctionMap.end() ) { PrintAvailableTests(); - std::cerr << "Failure: " << testToRun << ": no test identified " << testToRun << "\n"; - return -1; + std::cerr << "Failure: no test identified for '" << testToRun << "'\n"; + result = -1; } else { otb::Logger::Instance()->LogSetupInformation(); MainFuncPointer f = j->second; - int result; try { // Invoke the test's "main" function. @@ -326,24 +339,29 @@ int main(int ac, char* av[]) result = EXIT_FAILURE; } + bool checkBaseline = true; if (result != EXIT_SUCCESS) { - return -1; + checkBaseline = false; + result = -1; } - - result = EXIT_SUCCESS; #ifdef OTB_USE_MPI - otb::MPIConfig::Pointer mpiConfig = otb::MPIConfig::Instance(); - if (mpiConfig->GetMyRank() == 0) - { + if (otb::MPIConfig::Instance()->GetMyRank() != 0) + { + checkBaseline = false; + } #endif + + if (checkBaseline) + { std::cout << " -> Test EXIT SUCCESS." << std::endl; if (lFlagRegression == false) { std::cout << "------------- No control baseline tests -------------" << std::endl; - return result; } + else + { try { @@ -351,8 +369,7 @@ int main(int ac, char* av[]) // Make a list of possible baselines testHelper->SetIgnoreLineOrder(lIgnoreOrder); - testHelper->SetToleranceDiffValue(lToleranceDiffValue); // What's the difference - testHelper->SetEpsilon(lEpsilon); // maybe we should consolidate... + testHelper->SetToleranceRatio(lToleranceRatio); if (epsilonBoundary != 0.0) { testHelper->SetEpsilonBoundaryChecking(epsilonBoundary); @@ -361,21 +378,20 @@ int main(int ac, char* av[]) // Non regression test for images if ((baselineFilenamesImage.size() > 0) && (testFilenamesImage.size() > 0)) { - result += testHelper->RegressionTestAllImages(baselineFilenamesImage, testFilenamesImage); + result += testHelper->RegressionTestAllImages(baselineFilenamesImage, testFilenamesImage, toleranceDiffValues); } /***********************************************************************************/ // Non-regression test for metadata. if ((baselineFilenamesMetaData.size() > 0) && (testFilenamesMetaData.size() > 0)) { - result += testHelper->RegressionTestAllMetaData(baselineFilenamesMetaData, testFilenamesMetaData); + result += testHelper->RegressionTestAllMetaData(baselineFilenamesMetaData, testFilenamesMetaData, toleranceMetaValues); } - /***********************************************************************************/ // Non regression test for ascii files if ((baselineFilenamesAscii.size() > 0) && (testFilenamesAscii.size() > 0)) { //result += testHelper->RegressionTestAllAscii(baselineFilenamesAscii, testFilenamesAscii, ignoredLines); - result += testHelper->RegressionTestAllDiff(baselineFilenamesAscii, testFilenamesAscii, ignoredLines); + result += testHelper->RegressionTestAllDiff(baselineFilenamesAscii, testFilenamesAscii, toleranceAsciiValues, ignoredLines); } /******************************************************************************/ // Non regression test for binary files @@ -387,42 +403,44 @@ int main(int ac, char* av[]) // Non regression test for OGR files if ((baselineFilenamesOgr.size() > 0) && (testFilenamesOgr.size() > 0)) { - result += testHelper->RegressionTestAllOgr(baselineFilenamesOgr, testFilenamesOgr); + result += testHelper->RegressionTestAllOgr(baselineFilenamesOgr, testFilenamesOgr, toleranceOgrValues); } - + std::cout << "------------- End control baseline tests -------------" << std::endl; } catch (itk::ExceptionObject& e) { std::cerr << "otbTestMain 'control baseline test': ITK Exception thrown:" << std::endl; std::cerr << e.GetFile() << ":" << e.GetLine() << ":" << std::endl; std::cerr << e.GetDescription() << std::endl; - return -1; + result = -1; } catch (std::bad_alloc& err) { std::cerr << "otbTestMain 'control baseline test': Exception bad_alloc thrown: " << std::endl; std::cerr << (char*) err.what() << std::endl; - return -1; + result = -1; } catch (const std::exception& e) { std::cerr << "otbTestMain 'control baseline test': std::exception thrown:" << std::endl; std::cerr << e.what() << std::endl; - return -1; + result = -1; } catch (...) { std::cerr << "otbTestMain 'control baseline test': Unknown exception thrown !" << std::endl; - return -1; + result = -1; } - std::cout << "------------- End control baseline tests -------------" << std::endl; + + } // if there is a baseline control + + } // if checkBaseline + } // if test function exists #ifdef OTB_USE_MPI - otb::MPIConfig::Instance()->terminate(); - } + otb::MPIConfig::Instance()->terminate(); #endif - return result; - } + return result; } #endif diff --git a/Modules/IO/TestKernel/src/otbTestDriver.cxx b/Modules/IO/TestKernel/src/otbTestDriver.cxx index 3cc8444bbef895fb40132d9a125899a8e2cc1fa3..930c1910b4ea1311fbb60faa47bbf0e29845e533 100644 --- a/Modules/IO/TestKernel/src/otbTestDriver.cxx +++ b/Modules/IO/TestKernel/src/otbTestDriver.cxx @@ -200,6 +200,7 @@ int Execute(int argc, char * argv[]) itksysProcess_Execute(process); itksysProcess_WaitForExit(process, nullptr); int retCode = itksysProcess_GetExitValue(process); + itksysProcess_Delete(process); return retCode; } diff --git a/Modules/IO/TestKernel/src/otbTestHelper.cxx b/Modules/IO/TestKernel/src/otbTestHelper.cxx index 69079360ccebd6cad29b10118713af8e88d2daf4..af7f6aa58d4ef96437508649fc20db2c3cdc42d7 100644 --- a/Modules/IO/TestKernel/src/otbTestHelper.cxx +++ b/Modules/IO/TestKernel/src/otbTestHelper.cxx @@ -106,16 +106,19 @@ void TestHelper::CheckValueTolerance(const char *comment, double ref, double tes } int TestHelper::RegressionTestAllImages(const StringList& baselineFilenamesImage, - const StringList& testFilenamesImage) + const StringList& testFilenamesImage, + const EpsilonList& epsilons) { int result = 0; StringListIt itbaselineFilenames = baselineFilenamesImage.begin(); StringListIt itTestFilenames = testFilenamesImage.begin(); + EpsilonListIt itEpsilon = epsilons.begin(); int cpt(1); // For each couple of baseline and test file, do the comparison for (; (itbaselineFilenames != baselineFilenamesImage.end()) - && (itTestFilenames != testFilenamesImage.end()); - ++itbaselineFilenames, ++itTestFilenames) + && (itTestFilenames != testFilenamesImage.end()) + && (itEpsilon != epsilons.end()); + ++itbaselineFilenames, ++itTestFilenames, ++itEpsilon) { std::string baselineFilenameImage = (*itbaselineFilenames); std::string testFilenameImage = (*itTestFilenames); @@ -131,7 +134,7 @@ int TestHelper::RegressionTestAllImages(const StringList& baselineFilenamesImage this->ReportErrorsOff(); baseline->second = this->RegressionTestImage(cpt, testFilenameImage.c_str(), (baseline->first).c_str(), - m_ToleranceDiffValue); + *itEpsilon); multiResult = baseline->second; ++baseline; @@ -143,7 +146,7 @@ int TestHelper::RegressionTestAllImages(const StringList& baselineFilenamesImage baseline->second = this->RegressionTestImage(cpt, testFilenameImage.c_str(), (baseline->first).c_str(), - m_ToleranceDiffValue); + *itEpsilon); } ++cpt; result += multiResult; @@ -152,16 +155,19 @@ int TestHelper::RegressionTestAllImages(const StringList& baselineFilenamesImage } int TestHelper::RegressionTestAllMetaData(const StringList& baselineFilenamesMetaData, - const StringList& testFilenamesMetaData) + const StringList& testFilenamesMetaData, + const EpsilonList& epsilons) { int result = 0; // Creates iterators on baseline filenames vector and test filenames vector StringListIt itbaselineFilenames = baselineFilenamesMetaData.begin(); StringListIt itTestFilenames = testFilenamesMetaData.begin(); + EpsilonListIt itEpsilon = epsilons.begin(); // For each couple of baseline and test file, do the comparison for (; (itbaselineFilenames != baselineFilenamesMetaData.end()) - && (itTestFilenames != testFilenamesMetaData.end()); - ++itbaselineFilenames, ++itTestFilenames) + && (itTestFilenames != testFilenamesMetaData.end()) + && (itEpsilon != epsilons.end()); + ++itbaselineFilenames, ++itTestFilenames, ++itEpsilon) { std::string baselineFilenameImage = (*itbaselineFilenames); std::string testFilenameImage = (*itTestFilenames); @@ -177,7 +183,7 @@ int TestHelper::RegressionTestAllMetaData(const StringList& baselineFilenamesMet this->ReportErrorsOff(); baseline->second = this->RegressionTestMetaData(testFilenameImage.c_str(), (baseline->first).c_str(), - m_ToleranceDiffValue); + *itEpsilon); multiResult = baseline->second; ++baseline; @@ -189,7 +195,7 @@ int TestHelper::RegressionTestAllMetaData(const StringList& baselineFilenamesMet baseline->second = this->RegressionTestMetaData(testFilenameImage.c_str(), (baseline->first).c_str(), - m_ToleranceDiffValue); + *itEpsilon); } result += multiResult; } @@ -198,6 +204,7 @@ int TestHelper::RegressionTestAllMetaData(const StringList& baselineFilenamesMet int TestHelper::RegressionTestAllAscii(const StringList& baselineFilenamesAscii, const StringList& testFilenamesAscii, + const EpsilonList& epsilons, const StringList& ignoredLines) { int result = 0; @@ -205,6 +212,7 @@ int TestHelper::RegressionTestAllAscii(const StringList& baselineFilenamesAscii, StringListIt itbaselineFilenames = baselineFilenamesAscii.begin(); StringListIt itTestFilenames = testFilenamesAscii.begin(); StringListIt itIgnoredLines = ignoredLines.begin(); + EpsilonListIt itEpsilon = epsilons.begin(); // Warning message if (ignoredLines.size() > 0) @@ -219,8 +227,9 @@ int TestHelper::RegressionTestAllAscii(const StringList& baselineFilenamesAscii, // For each couple of baseline and test file, do the comparison for (; (itbaselineFilenames != baselineFilenamesAscii.end()) - && (itTestFilenames != testFilenamesAscii.end()); - ++itbaselineFilenames, ++itTestFilenames) + && (itTestFilenames != testFilenamesAscii.end()) + && (itEpsilon != epsilons.end()); + ++itbaselineFilenames, ++itTestFilenames, ++itEpsilon) { std::string baselineFilenameAscii = (*itbaselineFilenames); std::string testFilenameAscii = (*itTestFilenames); @@ -237,7 +246,7 @@ int TestHelper::RegressionTestAllAscii(const StringList& baselineFilenamesAscii, this->ReportErrorsOff(); baseline->second = this->RegressionTestAsciiFile(testFilenameAscii.c_str(), (baseline->first).c_str(), - m_Epsilon, + *itEpsilon, ignoredLines); multiResult = baseline->second; @@ -250,7 +259,7 @@ int TestHelper::RegressionTestAllAscii(const StringList& baselineFilenamesAscii, baseline->second = this->RegressionTestAsciiFile(testFilenameAscii.c_str(), (baseline->first).c_str(), - m_Epsilon, + *itEpsilon, ignoredLines); } result += multiResult; @@ -261,6 +270,7 @@ int TestHelper::RegressionTestAllAscii(const StringList& baselineFilenamesAscii, int TestHelper::RegressionTestAllDiff(const StringList& baselineFilenamesAscii, const StringList& testFilenamesAscii, + const EpsilonList& epsilons, const StringList& ignoredLines) { int result = 0; @@ -268,6 +278,7 @@ int TestHelper::RegressionTestAllDiff(const StringList& baselineFilenamesAscii, StringListIt itbaselineFilenames = baselineFilenamesAscii.begin(); StringListIt itTestFilenames = testFilenamesAscii.begin(); StringListIt itIgnoredLines = ignoredLines.begin(); + EpsilonListIt itEpsilon = epsilons.begin(); // Warning message if (ignoredLines.size() > 0) @@ -282,8 +293,9 @@ int TestHelper::RegressionTestAllDiff(const StringList& baselineFilenamesAscii, // For each couple of baseline and test file, do the comparison for (; (itbaselineFilenames != baselineFilenamesAscii.end()) - && (itTestFilenames != testFilenamesAscii.end()); - ++itbaselineFilenames, ++itTestFilenames) + && (itTestFilenames != testFilenamesAscii.end()) + && (itEpsilon != epsilons.end()); + ++itbaselineFilenames, ++itTestFilenames, ++itEpsilon) { std::string baselineFilenameAscii = (*itbaselineFilenames); std::string testFilenameAscii = (*itTestFilenames); @@ -300,7 +312,7 @@ int TestHelper::RegressionTestAllDiff(const StringList& baselineFilenamesAscii, this->ReportErrorsOff(); baseline->second = this->RegressionTestDiffFile(testFilenameAscii.c_str(), (baseline->first).c_str(), - m_Epsilon, + *itEpsilon, ignoredLines); multiResult = baseline->second; @@ -313,7 +325,7 @@ int TestHelper::RegressionTestAllDiff(const StringList& baselineFilenamesAscii, baseline->second = this->RegressionTestDiffFile(testFilenameAscii.c_str(), (baseline->first).c_str(), - m_Epsilon, + *itEpsilon, ignoredLines); } result += multiResult; @@ -369,16 +381,19 @@ int TestHelper::RegressionTestAllBinary(const StringList& baselineFilenamesBinar } int TestHelper::RegressionTestAllOgr(const StringList& baselineFilenamesOgr, - const StringList& testFilenamesOgr) + const StringList& testFilenamesOgr, + const EpsilonList& epsilons) { int result = 0; // Creates iterators on baseline filenames vector and test filenames vector StringListIt itbaselineFilenames = baselineFilenamesOgr.begin(); StringListIt itTestFilenames = testFilenamesOgr.begin(); + EpsilonListIt itEpsilon = epsilons.begin(); // For each couple of baseline and test file, do the comparison for (; (itbaselineFilenames != baselineFilenamesOgr.end()) - && (itTestFilenames != testFilenamesOgr.end()); - ++itbaselineFilenames, ++itTestFilenames) + && (itTestFilenames != testFilenamesOgr.end()) + && (itEpsilon != epsilons.end()); + ++itbaselineFilenames, ++itTestFilenames, ++itEpsilon) { std::string baselineFilenameOgr = (*itbaselineFilenames); std::string testFilenameOgr = (*itTestFilenames); @@ -394,8 +409,8 @@ int TestHelper::RegressionTestAllOgr(const StringList& baselineFilenamesOgr, std::cout << "Testing non-regression on OGR file: " << (baseline->first) << std::endl; this->ReportErrorsOff(); baseline->second = this->RegressionTestOgrFile(testFilenameOgr.c_str(), - (baseline->first).c_str(), - m_ToleranceDiffValue); + (baseline->first).c_str(), + *itEpsilon); multiResult = baseline->second; ++baseline; @@ -407,7 +422,7 @@ int TestHelper::RegressionTestAllOgr(const StringList& baselineFilenamesOgr, baseline->second = this->RegressionTestOgrFile(testFilenameOgr.c_str(), (baseline->first).c_str(), - m_ToleranceDiffValue); + *itEpsilon); } result += multiResult; } @@ -1326,6 +1341,12 @@ int TestHelper::RegressionTestImage(int cpt, const char *testImageFilename, cons ImageType::PixelType status = diff->GetTotalDifference(); unsigned long numberOfPixelsWithDifferences = diff->GetNumberOfPixelsWithDifferences(); + int ret = 0; + if ((status.GetSquaredNorm() > 0) && + ((double) numberOfPixelsWithDifferences > m_ToleranceRatio*baselineSize[0]*baselineSize[1])) + { + ret = 1; + } //Write only one this message if (m_ReportErrors == 0) @@ -1335,7 +1356,7 @@ int TestHelper::RegressionTestImage(int cpt, const char *testImageFilename, cons << status << " for " << numberOfPixelsWithDifferences << " pixel(s)."); } // if there are discrepencies, create an diff image - if (status.GetSquaredNorm() > 0 && m_ReportErrors) + if (ret && m_ReportErrors) { typedef otb::PrintableImageFilter<ImageType> RescaleType; typedef otb::ImageFileWriter<RescaleType::OutputImageType> WriterType; @@ -1479,7 +1500,7 @@ int TestHelper::RegressionTestImage(int cpt, const char *testImageFilename, cons std::cout << "</DartMeasurement>" << std::endl; } } - return (status.GetSquaredNorm() > 0) ? 1 : 0; + return ret; } int TestHelper::RegressionTestMetaData(const char *testImageFilename, const char *baselineImageFilename, @@ -2643,8 +2664,7 @@ void TestHelper::ogrReportOnLayer(OGRLayer * ref_poLayer, } TestHelper::TestHelper() : - m_ToleranceDiffValue(0), - m_Epsilon(0), + m_ToleranceRatio(0), m_EpsilonBoundaryChecking(1.0e-30), m_ReportErrors(false), m_IgnoreLineOrder(false), diff --git a/Modules/Learning/DempsterShafer/test/otbConfusionMatrixToMassOfBeliefTest.cxx b/Modules/Learning/DempsterShafer/test/otbConfusionMatrixToMassOfBeliefTest.cxx index 16b6aba2c91b5e00ed7ecef33418d17bf549322e..e13f12d3dcb5c5b21eaa3a37d0a3ea255413ac2c 100644 --- a/Modules/Learning/DempsterShafer/test/otbConfusionMatrixToMassOfBeliefTest.cxx +++ b/Modules/Learning/DempsterShafer/test/otbConfusionMatrixToMassOfBeliefTest.cxx @@ -18,7 +18,7 @@ * limitations under the License. */ -#include "itkMacro.h" +#include "otbMacro.h" #include <iostream> #include "otbConfusionMatrixToMassOfBelief.h" diff --git a/Modules/Learning/DempsterShafer/test/otbDempsterShaferFusionTests.cxx b/Modules/Learning/DempsterShafer/test/otbDempsterShaferFusionTests.cxx index de6790003dd25767c5623f4e5dfb075ca9213b74..2c27a36d124845e896cd27b8b7ab4ca0256ab9ff 100644 --- a/Modules/Learning/DempsterShafer/test/otbDempsterShaferFusionTests.cxx +++ b/Modules/Learning/DempsterShafer/test/otbDempsterShaferFusionTests.cxx @@ -22,6 +22,7 @@ #include "otbMassOfBelief.h" #include "otbJointMassOfBeliefFilter.h" #include "otbConfusionMatrixToMassOfBelief.h" +#include "otbMacro.h" #include <fstream> @@ -337,11 +338,12 @@ int otbDempsterShaferFusionOptRecConfMatTest(int itkNotUsed(argc), char * argv[] // Vector containing the Mass of Belief of the universe for each classifier vectorUniverseMOBs.push_back(mobUniverseClk); - std::cout << "confusion matrix[Cl_" << itClk << "] = " << std::endl; + otbLogMacro(Debug, << "confusion matrix[Cl_" << itClk << "] = "); + std::ostringstream oss; for (unsigned int itLabel = 0; itLabel < nbClassesClk; ++itLabel) { IntLabelPixelType classLabel = mapOfIndicesClk[itLabel]; - std::cout << "[" << classLabel << "] "; + oss << "[" << classLabel << "] "; // If the current classLabel has already been added to the universe if (universe.count(classLabel) > 0) @@ -353,29 +355,26 @@ int otbDempsterShaferFusionOptRecConfMatTest(int itkNotUsed(argc), char * argv[] universe[classLabel] = 1; } } - std::cout << std::endl << confMatClk << std::endl; - std::cout << std::endl; + otbLogMacro(Debug, << oss.str()); + otbLogMacro(Debug, << confMatClk); for (itMapMOBClk = mapMOBClk.begin(); itMapMOBClk != mapMOBClk.end(); ++itMapMOBClk) { - std::cout << "mapMOBCl_" << itClk << "[" << itMapMOBClk->first << "] = " << itMapMOBClk->second << std::endl; + otbLogMacro(Debug, << "mapMOBCl_" << itClk << "[" << itMapMOBClk->first << "] = " << itMapMOBClk->second); } - std::cout << "*******************************************************************************" << std::endl; + otbLogMacro(Debug, << "*******************************************************************************"); } // Number of classes in the universe unsigned int nbClasses = universe.size(); - std::cout << "universe:" << std::endl; + otbLogMacro(Info, << "universe:"); for (itUniverse = universe.begin(); itUniverse != universe.end(); ++itUniverse) { - std::cout << "Class Label " << itUniverse->first; - std::cout << " present in " << itUniverse->second << " classifier(s)" << std::endl; + otbLogMacro(Info, << "Class Label " << itUniverse->first + << " present in " << itUniverse->second << " classifier(s)"); } - std::cout << std::endl; - - /* ***************************************************************************************** */ /* ************************ RESULTS OF THE CLASSIFICATION OF PIXEL X *********************** */ @@ -415,9 +414,8 @@ int otbDempsterShaferFusionOptRecConfMatTest(int itkNotUsed(argc), char * argv[] mLabelSetClk = vectorMapMOBs[itClk][classLabelk]; mLabelSetClk_ = 1 - mLabelSetClk - mUniverseClk; - std::cout << "classifiedPixelX[" << itClk << "] = " << classLabelk; - std::cout << "; MassOfBelief_Cl_" << itClk << "[" << classLabelk << "] = " << mLabelSetClk; - std::cout << std::endl; + otbLogMacro(Debug, << "classifiedPixelX[" << itClk << "] = " << classLabelk + << "; MassOfBelief_Cl_" << itClk << "[" << classLabelk << "] = " << mLabelSetClk); // The first time the label {Ai} is found in classifiedPixelX if (mapJointMassesStepI.count(classLabelk) == 0) @@ -443,9 +441,6 @@ int otbDempsterShaferFusionOptRecConfMatTest(int itkNotUsed(argc), char * argv[] mapJointMassesUniverseStepI[classLabelk] = mUniverseClkNew; } - std::cout << "*******************************************************************************" << std::endl; - std::cout << std::endl; - /* ***************************************************************************************** */ /* *************************************** DS STEP #2 ************************************** */ /* ***************************************************************************************** */ @@ -464,10 +459,9 @@ int otbDempsterShaferFusionOptRecConfMatTest(int itkNotUsed(argc), char * argv[] B = B * (1 - mLabelSetClk); C = C * mLabelSetClk_; - std::cout << "****************************************" << std::endl; - std::cout << "mapJointMassesStepI[" << classLabelk << "] = " << mLabelSetClk << std::endl; - std::cout << "mapJointMassesStepI_[" << classLabelk << "] = " << mLabelSetClk_ << std::endl; - std::cout << "mapJointMassesUniverseStepI[" << classLabelk << "] = " << mUniverseClk << std::endl; + otbLogMacro(Debug, << "mapJointMassesStepI[" << classLabelk << "] = " << mLabelSetClk); + otbLogMacro(Debug, << "mapJointMassesStepI_[" << classLabelk << "] = " << mLabelSetClk_); + otbLogMacro(Debug, << "mapJointMassesUniverseStepI[" << classLabelk << "] = " << mUniverseClk); } unsigned int nbClkGroupsStepI = mapJointMassesStepI.size(); @@ -483,13 +477,9 @@ int otbDempsterShaferFusionOptRecConfMatTest(int itkNotUsed(argc), char * argv[] } } - std::cout << "****************************************************************************" << std::endl; - std::cout << "****************************************************************************" << std::endl; - std::cout << "nbClasses = " << nbClasses << std::endl; - std::cout << "nbClassifiers = " << nbClassifiers << std::endl; - std::cout << "nbClkGroupsStepI = " << nbClkGroupsStepI << std::endl; - std::cout << "****************************************************************************" << std::endl; - std::cout << "****************************************************************************" << std::endl; + otbLogMacro(Info, << "nbClasses = " << nbClasses); + otbLogMacro(Info, << "nbClassifiers = " << nbClassifiers); + otbLogMacro(Info, << "nbClkGroupsStepI = " << nbClkGroupsStepI); // Calculation of the Belief function of each singleton {Ai} and {Ai_} SingleClassLabelMassMapType mapBelStepII, mapBelStepII_; @@ -536,9 +526,6 @@ int otbDempsterShaferFusionOptRecConfMatTest(int itkNotUsed(argc), char * argv[] addBelLabelSetClk += belLabelSetClk; } - std::cout << "****************************************************************************" << std::endl; - - /* ***************************************************************************************** */ /* ************************************ DECISION PROCESS *********************************** */ /* ***************************************************************************************** */ @@ -580,9 +567,8 @@ int otbDempsterShaferFusionOptRecConfMatTest(int itkNotUsed(argc), char * argv[] mapBelStepII_[classLabelk] = addBelLabelSetClk; } - std::cout << "Bel(" << classLabelk << ") = " << mapBelStepII[classLabelk] << std::endl; - std::cout << "Bel(NOT_" << classLabelk << ") = " << mapBelStepII_[classLabelk] << std::endl; - std::cout << std::endl; + otbLogMacro(Info, << "Bel(" << classLabelk << ") = " << mapBelStepII[classLabelk]); + otbLogMacro(Info, << "Bel(NOT_" << classLabelk << ") = " << mapBelStepII_[classLabelk]); } // If the DS VOTED LABEL is NOT unique, the result of the DS Fusion is undefinedValue @@ -595,20 +581,12 @@ int otbDempsterShaferFusionOptRecConfMatTest(int itkNotUsed(argc), char * argv[] } } - std::cout << "****************************************************************************" << std::endl; - std::cout << "fusedDSLabelSet = " << fusedDSLabelSet << std::endl; - std::cout << "fusedDSBelLabelSetClk = " << fusedDSBelLabelSetClk << std::endl; - std::cout << std::endl; + otbLogMacro(Info, << "fusedDSLabelSet = " << fusedDSLabelSet); + otbLogMacro(Info, << "fusedDSBelLabelSetClk = " << fusedDSBelLabelSetClk); return EXIT_SUCCESS; } -// ******************************************************************************************************** -// ******************************************************************************************************** -// ******************************************************************************************************** - - - // OPTIMIZED RECURSIVE DS FUSION int otbDempsterShaferFusionOptRecTest(int argc, char * argv[]) @@ -640,7 +618,7 @@ int otbDempsterShaferFusionOptRecTest(int argc, char * argv[]) mapLabelSets[vectorAllLabels[it]] = labelSet; } - std::cout << "universe = " << universe << std::endl; + otbLogMacro(Info, << "universe = " << universe); //********************************************************************** //************** RESULTS OF THE CLASSIFICATION OF PIXEL X ************** @@ -691,7 +669,7 @@ int otbDempsterShaferFusionOptRecTest(int argc, char * argv[]) for (unsigned int it = 0; it < classifiedPixelX.size(); ++it) { - std::cout << "classifiedPixelX[" << it << "] = " << classifiedPixelX[it] << std::endl; + otbLogMacro(Debug, << "classifiedPixelX[" << it << "] = " << classifiedPixelX[it]); } //********************************************************************** @@ -882,11 +860,9 @@ int otbDempsterShaferFusionOptRecTest(int argc, char * argv[]) B = B * (1 - mLabelSetClk); C = C * mLabelSetClk_; - std::cout << "****************************************" << std::endl; - std::cout << "mapJointMassesStepI[" << labelSetClk << "] = " << mLabelSetClk << std::endl; - std::cout << "mapJointMassesStepI_[" << labelSetClk << "] = " << mLabelSetClk_ << std::endl; - std::cout << "mapJointMassesUniverseStepI[" << labelSetClk << "] = " << mapJointMassesUniverseStepI[labelSetClk] - << std::endl; + otbLogMacro(Debug, << "mapJointMassesStepI[" << labelSetClk << "] = " << mLabelSetClk); + otbLogMacro(Debug, << "mapJointMassesStepI_[" << labelSetClk << "] = " << mLabelSetClk_); + otbLogMacro(Debug, << "mapJointMassesUniverseStepI[" << labelSetClk << "] = " << mapJointMassesUniverseStepI[labelSetClk]); } unsigned int nbClkGroupsStepI = mapJointMassesStepI.size(); @@ -902,11 +878,9 @@ int otbDempsterShaferFusionOptRecTest(int argc, char * argv[]) } } - std::cout << "****************************************************************************" << std::endl; - std::cout << "****************************************************************************" << std::endl; - std::cout << "nbClasses = " << nbClasses << std::endl; - std::cout << "nbClassifiers = " << classifiedPixelX .size() << std::endl; - std::cout << "nbClkGroupsStepI = " << nbClkGroupsStepI << std::endl; + otbLogMacro(Info, << "nbClasses = " << nbClasses); + otbLogMacro(Info, << "nbClassifiers = " << classifiedPixelX .size()); + otbLogMacro(Info, << "nbClkGroupsStepI = " << nbClkGroupsStepI); // Calculation of the Belief function of each singleton {Ai} and {Ai_} @@ -954,8 +928,6 @@ int otbDempsterShaferFusionOptRecTest(int argc, char * argv[]) addBelLabelSetClk = addBelLabelSetClk + belLabelSetClk; } - std::cout << "****************************************************************************" << std::endl; - // The decision for the DS Fusion is made with the MAXIMAL Belief function: // {Ai} is chosen if Bel({Ai}) = MAX(Bel({Aj})) @@ -992,9 +964,8 @@ int otbDempsterShaferFusionOptRecTest(int argc, char * argv[]) mapBelStepII_[labelSetClk] = addBelLabelSetClk; } - std::cout << "Bel(" << labelSetClk << ") = " << mapBelStepII[labelSetClk] << std::endl; - std::cout << "Bel(NOT_" << labelSetClk << ") = " << mapBelStepII_[labelSetClk] << std::endl; - std::cout << std::endl; + otbLogMacro(Debug, << "Bel(" << labelSetClk << ") = " << mapBelStepII[labelSetClk]); + otbLogMacro(Debug, << "Bel(NOT_" << labelSetClk << ") = " << mapBelStepII_[labelSetClk]); } // If the DS VOTED LABEL is NOT unique, the result of the DS Fusion is the UNION of all the candidates {Ai} @@ -1008,10 +979,8 @@ int otbDempsterShaferFusionOptRecTest(int argc, char * argv[]) } } - std::cout << "****************************************************************************" << std::endl; - std::cout << "fusedDSLabelSet = " << fusedDSLabelSet << std::endl; - std::cout << "fusedDSBelLabelSetClk = " << fusedDSBelLabelSetClk << std::endl; - std::cout << std::endl; + otbLogMacro(Info, << "fusedDSLabelSet = " << fusedDSLabelSet); + otbLogMacro(Info, << "fusedDSBelLabelSetClk = " << fusedDSBelLabelSetClk); return EXIT_SUCCESS; } @@ -1045,7 +1014,7 @@ int otbDempsterShaferFusionOptTest(int argc, char * argv[]) mapLabelSets[vectorAllLabels[it]] = labelSet; } - std::cout << "universe = " << universe << std::endl; + otbLogMacro(Info, << "universe = " << universe); //********************************************************************** //************** RESULTS OF THE CLASSIFICATION OF PIXEL X ************** @@ -1063,7 +1032,7 @@ int otbDempsterShaferFusionOptTest(int argc, char * argv[]) for (unsigned int it = 0; it < classifiedPixelX.size(); ++it) { - std::cout << "classifiedPixelX[" << it << "] = " << classifiedPixelX[it] << std::endl; + otbLogMacro(Debug, << "classifiedPixelX[" << it << "] = " << classifiedPixelX[it]); } //********************************************************************** @@ -1184,14 +1153,9 @@ int otbDempsterShaferFusionOptTest(int argc, char * argv[]) itMapJMOBFilters->second->Update(); mapJMOBFStepI[itMapJMOBFilters->first] = itMapJMOBFilters->second->GetOutput(); - std::cout << "****************************************************************************" << std::endl; - std::cout << "jointMassClkFilterStepI[" << itMapJMOBFilters->first << "] = " << itMapJMOBFilters->second - << std::endl; + otbLogMacro(Debug, << "jointMassClkFilterStepI[" << itMapJMOBFilters->first << "] = " << itMapJMOBFilters->second); } - std::cout << "****************************************************************************" << std::endl; - std::cout << "****************************************************************************" << std::endl; - //********************************************************************** //***************************** DS STEP #2 ***************************** //********************************************************************** @@ -1213,8 +1177,7 @@ int otbDempsterShaferFusionOptTest(int argc, char * argv[]) B = B * (1 - mLabelSetClk); C = C * mLabelSetClk_; - std::cout << "****************************************************************************" << std::endl; - std::cout << "jointMassOfBeliefStepI[" << itMapJMOBF->first << "] = " << itMapJMOBF->second << std::endl; + otbLogMacro(Debug, << "jointMassOfBeliefStepI[" << itMapJMOBF->first << "] = " << itMapJMOBF->second); } unsigned int nbClkGroupsStepI = mapJMOBFStepI.size(); @@ -1278,9 +1241,6 @@ int otbDempsterShaferFusionOptTest(int argc, char * argv[]) addBelLabelSetClk = addBelLabelSetClk + belLabelSetClk; } - std::cout << "****************************************************************************" << std::endl; - std::cout << "****************************************************************************" << std::endl; - // The decision for the DS Fusion is made with the MAXIMAL Belief function: // {Ai} is chosen if Bel({Ai}) = MAX(Bel({Aj})) @@ -1319,10 +1279,8 @@ int otbDempsterShaferFusionOptTest(int argc, char * argv[]) mapBelStepII[labelSetClk_] = addBelLabelSetClk; } - std::cout << "Bel(" << labelSetClk << ") = " << mapBelStepII[labelSetClk] << std::endl; - std::cout << "Bel(NOT_" << labelSetClk << ") = Bel(" << labelSetClk_ << ") = " << mapBelStepII[labelSetClk_] - << std::endl; - std::cout << std::endl; + otbLogMacro(Debug, << "Bel(" << labelSetClk << ") = " << mapBelStepII[labelSetClk]); + otbLogMacro(Debug, << "Bel(NOT_" << labelSetClk << ") = Bel(" << labelSetClk_ << ") = " << mapBelStepII[labelSetClk_]); } // If the DS VOTED LABEL is NOT unique, the result of the DS Fusion is the UNION of all the candidates {Ai} @@ -1336,10 +1294,8 @@ int otbDempsterShaferFusionOptTest(int argc, char * argv[]) } } - std::cout << "****************************************************************************" << std::endl; - std::cout << "fusedDSLabelSet = " << fusedDSLabelSet << std::endl; - std::cout << "fusedDSBelLabelSetClk = " << fusedDSBelLabelSetClk << std::endl; - std::cout << std::endl; + otbLogMacro(Info, << "fusedDSLabelSet = " << fusedDSLabelSet); + otbLogMacro(Info, << "fusedDSBelLabelSetClk = " << fusedDSBelLabelSetClk); return EXIT_SUCCESS; } @@ -1372,7 +1328,7 @@ int otbDempsterShaferFusionTest(int argc, char * argv[]) mapLabelSets[vectorAllLabels[it]] = labelSet; } - std::cout << "universe = " << universe << std::endl; + otbLogMacro(Info, << "universe = " << universe); //********************************************************************** //************** RESULTS OF THE CLASSIFICATION OF PIXEL X ************** @@ -1390,7 +1346,7 @@ int otbDempsterShaferFusionTest(int argc, char * argv[]) for (unsigned int it = 0; it < classifiedPixelX.size(); ++it) { - std::cout << "classifiedPixelX[" << it << "] = " << classifiedPixelX[it] << std::endl; + otbLogMacro(Debug, << "classifiedPixelX[" << it << "] = " << classifiedPixelX[it]); } //********************************************************************** @@ -1490,13 +1446,8 @@ int otbDempsterShaferFusionTest(int argc, char * argv[]) jointMassClkFilter->Update(); MassOfBeliefFunctionType::Pointer jointMass = jointMassClkFilter->GetOutput(); - std::cout << "****************************************************************************" << std::endl; - std::cout << "jointMassClkFilter = " << jointMassClkFilter << std::endl; - std::cout << "****************************************************************************" << std::endl; - std::cout << std::endl; - std::cout << "****************************************************************************" << std::endl; - std::cout << "jointMassOfBelief = " << jointMass << std::endl; - std::cout << "****************************************************************************" << std::endl; + otbLogMacro(Debug, << "jointMassClkFilter = " << jointMassClkFilter); + otbLogMacro(Debug, << "jointMassOfBelief = " << jointMass); // The decision for the DS Fusion is made with the MAXIMAL Belief function: // {Ai} is chosen if Bel({Ai}) = MAX(Bel({Aj})) @@ -1523,10 +1474,9 @@ int otbDempsterShaferFusionTest(int argc, char * argv[]) } } - std::cout << "Bel(" << labelSetClk << ") = " << jointMass->GetBelief(labelSetClk) << std::endl; - std::cout << "Bel(NOT_" << labelSetClk << ") = Bel(" << labelSetClk_ << ") = " - << jointMass->GetBelief(labelSetClk_) << std::endl; - std::cout << std::endl; + otbLogMacro(Debug, << "Bel(" << labelSetClk << ") = " << jointMass->GetBelief(labelSetClk)); + otbLogMacro(Debug, << "Bel(NOT_" << labelSetClk << ") = Bel(" << labelSetClk_ << ") = " + << jointMass->GetBelief(labelSetClk_)); } //If the DS VOTED LABEL is NOT unique @@ -1539,28 +1489,13 @@ int otbDempsterShaferFusionTest(int argc, char * argv[]) } } - std::cout << "****************************************************************************" << std::endl; - std::cout << "fusedDSLabelSet = " << fusedDSLabelSet << std::endl; - std::cout << "fusedDSBelLabelSetClk = " << fusedDSBelLabelSetClk << std::endl; - std::cout << std::endl; + otbLogMacro(Info, << "fusedDSLabelSet = " << fusedDSLabelSet); + otbLogMacro(Info, << "fusedDSBelLabelSetClk = " << fusedDSBelLabelSetClk); return EXIT_SUCCESS; } - - - - - -// ******************************************************************************************************** -// ******************************************************************************************************** -// ******************************************************************************************************** -// ******************************************************************************************************** -// ******************************************************************************************************** -// ******************************************************************************************************** - - // OPTIMIZED RECURSIVE DS FUSION FROM CONFUSION MATRIX FILES int otbDempsterShaferFusionOptRecConfMatFileTest(int argc, char * argv[]) { @@ -1658,11 +1593,12 @@ int otbDempsterShaferFusionOptRecConfMatFileTest(int argc, char * argv[]) // Vector containing the Mass of Belief of the universe for each classifier vectorUniverseMOBs.push_back(mobUniverseClk); - std::cout << "confusion matrix[Cl_" << itClk << "] = " << std::endl; + otbLogMacro(Debug, << "confusion matrix[Cl_" << itClk << "] = "); + std::ostringstream oss; for (itMapOfClassesClk = mapOfClassesClk.begin(); itMapOfClassesClk != mapOfClassesClk.end(); ++itMapOfClassesClk) { IntLabelPixelType classLabel = itMapOfClassesClk->first; - std::cout << "[" << classLabel << "] "; + oss << "[" << classLabel << "] "; // If the current classLabel has already been added to the universe if (universe.count(classLabel) > 0) @@ -1674,29 +1610,24 @@ int otbDempsterShaferFusionOptRecConfMatFileTest(int argc, char * argv[]) universe[classLabel] = 1; } } - std::cout << std::endl << confMatClk << std::endl; - std::cout << std::endl; + otbLogMacro(Debug, << oss.str()); + otbLogMacro(Debug, << confMatClk); for (itMapMOBClk = mapMOBClk.begin(); itMapMOBClk != mapMOBClk.end(); ++itMapMOBClk) { - std::cout << "mapMOBCl_" << itClk << "[" << itMapMOBClk->first << "] = " << itMapMOBClk->second << std::endl; + otbLogMacro(Debug, << "mapMOBCl_" << itClk << "[" << itMapMOBClk->first << "] = " << itMapMOBClk->second); } - - std::cout << "*******************************************************************************" << std::endl; } // Number of classes in the universe unsigned int nbClasses = universe.size(); - std::cout << "universe:" << std::endl; + otbLogMacro(Info, << "universe:"); for (itUniverse = universe.begin(); itUniverse != universe.end(); ++itUniverse) { - std::cout << "Class Label " << itUniverse->first; - std::cout << " present in " << itUniverse->second << " classifier(s)" << std::endl; + otbLogMacro(Info, << "Class Label " << itUniverse->first + << " present in " << itUniverse->second << " classifier(s)"); } - std::cout << std::endl; - - /* ***************************************************************************************** */ /* ************************ RESULTS OF THE CLASSIFICATION OF PIXEL X *********************** */ @@ -1740,9 +1671,8 @@ int otbDempsterShaferFusionOptRecConfMatFileTest(int argc, char * argv[]) mLabelSetClk = vectorMapMOBs[itClk][classLabelk]; mLabelSetClk_ = 1 - mLabelSetClk - mUniverseClk; - std::cout << "classifiedPixelX[" << itClk << "] = " << classLabelk; - std::cout << "; MassOfBelief_Cl_" << itClk << "[" << classLabelk << "] = " << mLabelSetClk; - std::cout << std::endl; + otbLogMacro(Debug, << "classifiedPixelX[" << itClk << "] = " << classLabelk + << "; MassOfBelief_Cl_" << itClk << "[" << classLabelk << "] = " << mLabelSetClk); // The first time the label {Ai} is found in classifiedPixelX if (mapJointMassesStepI.count(classLabelk) == 0) @@ -1768,9 +1698,6 @@ int otbDempsterShaferFusionOptRecConfMatFileTest(int argc, char * argv[]) mapJointMassesUniverseStepI[classLabelk] = mUniverseClkNew; } - std::cout << "*******************************************************************************" << std::endl; - std::cout << std::endl; - /* ***************************************************************************************** */ /* *************************************** DS STEP #2 ************************************** */ /* ***************************************************************************************** */ @@ -1789,10 +1716,9 @@ int otbDempsterShaferFusionOptRecConfMatFileTest(int argc, char * argv[]) B = B * (1 - mLabelSetClk); C = C * mLabelSetClk_; - std::cout << "****************************************" << std::endl; - std::cout << "mapJointMassesStepI[" << classLabelk << "] = " << mLabelSetClk << std::endl; - std::cout << "mapJointMassesStepI_[" << classLabelk << "] = " << mLabelSetClk_ << std::endl; - std::cout << "mapJointMassesUniverseStepI[" << classLabelk << "] = " << mUniverseClk << std::endl; + otbLogMacro(Debug, << "mapJointMassesStepI[" << classLabelk << "] = " << mLabelSetClk); + otbLogMacro(Debug, << "mapJointMassesStepI_[" << classLabelk << "] = " << mLabelSetClk_); + otbLogMacro(Debug, << "mapJointMassesUniverseStepI[" << classLabelk << "] = " << mUniverseClk); } unsigned int nbClkGroupsStepI = mapJointMassesStepI.size(); @@ -1808,13 +1734,9 @@ int otbDempsterShaferFusionOptRecConfMatFileTest(int argc, char * argv[]) } } - std::cout << "****************************************************************************" << std::endl; - std::cout << "****************************************************************************" << std::endl; - std::cout << "nbClasses = " << nbClasses << std::endl; - std::cout << "nbClassifiers = " << nbClassifiers << std::endl; - std::cout << "nbClkGroupsStepI = " << nbClkGroupsStepI << std::endl; - std::cout << "****************************************************************************" << std::endl; - std::cout << "****************************************************************************" << std::endl; + otbLogMacro(Info, << "nbClasses = " << nbClasses); + otbLogMacro(Info, << "nbClassifiers = " << nbClassifiers); + otbLogMacro(Info, << "nbClkGroupsStepI = " << nbClkGroupsStepI); // Calculation of the Belief function of each singleton {Ai} and {Ai_} SingleClassLabelMassMapType mapBelStepII, mapBelStepII_; @@ -1861,9 +1783,6 @@ int otbDempsterShaferFusionOptRecConfMatFileTest(int argc, char * argv[]) addBelLabelSetClk += belLabelSetClk; } - std::cout << "****************************************************************************" << std::endl; - - /* ***************************************************************************************** */ /* ************************************ DECISION PROCESS *********************************** */ /* ***************************************************************************************** */ @@ -1905,9 +1824,8 @@ int otbDempsterShaferFusionOptRecConfMatFileTest(int argc, char * argv[]) mapBelStepII_[classLabelk] = addBelLabelSetClk; } - std::cout << "Bel(" << classLabelk << ") = " << mapBelStepII[classLabelk] << std::endl; - std::cout << "Bel(NOT_" << classLabelk << ") = " << mapBelStepII_[classLabelk] << std::endl; - std::cout << std::endl; + otbLogMacro(Debug, << "Bel(" << classLabelk << ") = " << mapBelStepII[classLabelk]); + otbLogMacro(Debug, << "Bel(NOT_" << classLabelk << ") = " << mapBelStepII_[classLabelk]); } // If the DS VOTED LABEL is NOT unique, the result of the DS Fusion is undefinedValue @@ -1920,24 +1838,13 @@ int otbDempsterShaferFusionOptRecConfMatFileTest(int argc, char * argv[]) } } - std::cout << "****************************************************************************" << std::endl; - std::cout << "fusedDSLabelSet = " << fusedDSLabelSet << std::endl; - std::cout << "fusedDSBelLabelSetClk = " << fusedDSBelLabelSetClk << std::endl; - std::cout << std::endl; + otbLogMacro(Info, << "fusedDSLabelSet = " << fusedDSLabelSet); + otbLogMacro(Info, << "fusedDSBelLabelSetClk = " << fusedDSBelLabelSetClk); return EXIT_SUCCESS; } - - -// ******************************************************************************************************** -// ******************************************************************************************************** -// ******************************************************************************************************** - - - - // NOT OPTIMIZED DS FUSION FROM CONFUSION MATRIX FILES int otbDempsterShaferFusionConfMatFileTest(int argc, char * argv[]) { @@ -2036,11 +1943,12 @@ int otbDempsterShaferFusionConfMatFileTest(int argc, char * argv[]) // Vector containing the Mass of Belief of the universe for each classifier vectorUniverseMOBs.push_back(mobUniverseClk); - std::cout << "confusion matrix[Cl_" << itClk << "] = " << std::endl; + otbLogMacro(Debug, << "confusion matrix[Cl_" << itClk << "] = "); + std::ostringstream oss; for (itMapOfClassesClk = mapOfClassesClk.begin(); itMapOfClassesClk != mapOfClassesClk.end(); ++itMapOfClassesClk) { IntLabelPixelType classLabel = itMapOfClassesClk->first; - std::cout << "[" << classLabel << "] "; + oss << "[" << classLabel << "] "; // If the current classLabel has already been added to the universe if (universe.count(classLabel) > 0) @@ -2052,15 +1960,13 @@ int otbDempsterShaferFusionConfMatFileTest(int argc, char * argv[]) universe[classLabel] = 1; } } - std::cout << std::endl << confMatClk << std::endl; - std::cout << std::endl; + otbLogMacro(Debug, << oss.str()); + otbLogMacro(Debug, << confMatClk); for (itMapMOBClk = mapMOBClk.begin(); itMapMOBClk != mapMOBClk.end(); ++itMapMOBClk) { - std::cout << "mapMOBCl_" << itClk << "[" << itMapMOBClk->first << "] = " << itMapMOBClk->second << std::endl; + otbLogMacro(Debug, << "mapMOBCl_" << itClk << "[" << itMapMOBClk->first << "] = " << itMapMOBClk->second); } - - std::cout << "*******************************************************************************" << std::endl; } // Number of classes in the universe @@ -2072,19 +1978,16 @@ int otbDempsterShaferFusionConfMatFileTest(int argc, char * argv[]) IntLabelSetMapType mapLabelSets; IntLabelSetMapType::iterator itMapLabelSets; - std::cout << "universe:" << std::endl; + otbLogMacro(Debug, << "universe:"); for (itUniverse = universe.begin(); itUniverse != universe.end(); ++itUniverse) { - std::cout << "Class Label " << itUniverse->first; - std::cout << " present in " << itUniverse->second << " classifier(s)" << std::endl; + otbLogMacro(Debug, << "Class Label " << itUniverse->first + << " present in " << itUniverse->second << " classifier(s)"); universeSet.insert(itUniverse->first); labelSet.clear(); labelSet.insert(itUniverse->first); mapLabelSets[itUniverse->first] = labelSet; } - std::cout << std::endl; - - // Vector containing the std::maps of masses of ALL the singleton sets for each classifier k IntMassMapType mClk; @@ -2160,13 +2063,8 @@ int otbDempsterShaferFusionConfMatFileTest(int argc, char * argv[]) jointMassClkFilter->Update(); IntMassOfBeliefFunctionType::Pointer jointMass = jointMassClkFilter->GetOutput(); - std::cout << "****************************************************************************" << std::endl; - std::cout << "jointMassClkFilter = " << jointMassClkFilter << std::endl; - std::cout << "****************************************************************************" << std::endl; - std::cout << std::endl; - std::cout << "****************************************************************************" << std::endl; - std::cout << "jointMassOfBelief = " << jointMass << std::endl; - std::cout << "****************************************************************************" << std::endl; + otbLogMacro(Debug, << "jointMassClkFilter = " << jointMassClkFilter); + otbLogMacro(Debug, << "jointMassOfBelief = " << jointMass); // The decision for the DS Fusion is made with the MAXIMAL Belief function: // {Ai} is chosen if Bel({Ai}) = MAX(Bel({Aj})) @@ -2193,10 +2091,9 @@ int otbDempsterShaferFusionConfMatFileTest(int argc, char * argv[]) } } - std::cout << "Bel(" << labelSetClk << ") = " << jointMass->GetBelief(labelSetClk) << std::endl; - std::cout << "Bel(NOT_" << labelSetClk << ") = Bel(" << labelSetClk_ << ") = " - << jointMass->GetBelief(labelSetClk_) << std::endl; - std::cout << std::endl; + otbLogMacro(Debug, << "Bel(" << labelSetClk << ") = " << jointMass->GetBelief(labelSetClk)); + otbLogMacro(Debug, << "Bel(NOT_" << labelSetClk << ") = Bel(" << labelSetClk_ << ") = " + << jointMass->GetBelief(labelSetClk_)); } //If the DS VOTED LABEL is NOT unique @@ -2209,10 +2106,8 @@ int otbDempsterShaferFusionConfMatFileTest(int argc, char * argv[]) } } - std::cout << "****************************************************************************" << std::endl; - std::cout << "fusedDSLabelSet = " << fusedDSLabelSet << std::endl; - std::cout << "fusedDSBelLabelSetClk = " << fusedDSBelLabelSetClk << std::endl; - std::cout << std::endl; + otbLogMacro(Info, << "fusedDSLabelSet = " << fusedDSLabelSet); + otbLogMacro(Info, << "fusedDSBelLabelSetClk = " << fusedDSBelLabelSetClk); return EXIT_SUCCESS; } diff --git a/Modules/Learning/DempsterShafer/test/otbMassOfBelief.cxx b/Modules/Learning/DempsterShafer/test/otbMassOfBelief.cxx index 209186c5da9d474ee8fcc91500a69a6bab5bbf09..23f076e55afd23989afa9b0a6f7df041bb10bdd2 100644 --- a/Modules/Learning/DempsterShafer/test/otbMassOfBelief.cxx +++ b/Modules/Learning/DempsterShafer/test/otbMassOfBelief.cxx @@ -21,6 +21,7 @@ #include "otbMassOfBelief.h" +#include "otbMacro.h" typedef otb::MassOfBelief<std::string> MassOfBeliefFunctionType; @@ -44,56 +45,60 @@ int otbMassOfBelief(int itkNotUsed(argc), char* itkNotUsed(argv)[]) massFunction->SetMass(set2, 0.3); massFunction->SetMass(set4, 0.1); - std::cout<<massFunction<<std::endl; + otbLogMacro(Debug, <<massFunction); - std::cout<<"Removing mass from set "; - MassOfBeliefFunctionType::PrintLabelSet(std::cout, set4); - std::cout<<std::endl; + std::ostringstream oss; + MassOfBeliefFunctionType::PrintLabelSet(oss, set4); + otbLogMacro(Info, << "Removing mass from set " << oss.str()); massFunction->RemoveMass(set4); - std::cout<<massFunction<<std::endl; + otbLogMacro(Debug, <<massFunction); - std::cout<<"Estimating uncertainty "<<std::endl; + otbLogMacro(Info, <<"Estimating uncertainty"); massFunction->EstimateUncertainty(); - std::cout<<massFunction<<std::endl; + otbLogMacro(Debug, <<massFunction); + + oss.str(std::string()); + oss << "Removing mass "; + MassOfBeliefFunctionType::PrintLabelSet(oss, set2); + oss << " and adding mass "; + MassOfBeliefFunctionType::PrintLabelSet(oss, set3); + otbLogMacro(Info, << oss.str()); - std::cout<<"Removing mass "; - MassOfBeliefFunctionType::PrintLabelSet(std::cout, set2); - std::cout<<" and adding mass "; - MassOfBeliefFunctionType::PrintLabelSet(std::cout, set3); - std::cout<<std::endl; massFunction->RemoveMass(set2); massFunction->SetMass(set3, 0.6); - std::cout<<massFunction<<std::endl; + otbLogMacro(Debug, <<massFunction); - std::cout<<"Normalizing masses "<<std::endl; + otbLogMacro(Info, <<"Normalizing masses "); massFunction->Normalize(); - std::cout<<massFunction<<std::endl; + otbLogMacro(Debug, <<massFunction); + + oss.str(std::string()); + MassOfBeliefFunctionType::PrintLabelSet(oss, set3); + otbLogMacro(Info, <<"Belief of "<< oss.str() + << " is "<< massFunction->GetBelief(set3)); - std::cout<<"Belief of "; - MassOfBeliefFunctionType::PrintLabelSet(std::cout, set3); - std::cout<<" is "<<massFunction->GetBelief(set3)<<std::endl; - - std::cout<<"Plausibility of "; - MassOfBeliefFunctionType::PrintLabelSet(std::cout, set3); - std::cout<<" is "<<massFunction->GetPlausibility(set3)<<std::endl; + oss.str(std::string()); + MassOfBeliefFunctionType::PrintLabelSet(oss, set3); + otbLogMacro(Info, <<"Plausibility of " << oss.str() + << " is " << massFunction->GetPlausibility(set3)); MassOfBeliefFunctionType::LabelSetType otherSet; otherSet.insert("cat"); otherSet.insert("dog"); otherSet.insert("bird"); - std::cout<<"Initializing with power set from universal set "; - MassOfBeliefFunctionType::PrintLabelSet(std::cout, otherSet); - std::cout<<std::endl; - + oss.str(std::string()); + MassOfBeliefFunctionType::PrintLabelSet(oss, otherSet); + otbLogMacro(Info, <<"Initializing with power set from universal set "<< oss.str()); + massFunction->InitializePowerSetMasses(otherSet); - std::cout<<massFunction<<std::endl; + otbLogMacro(Debug, <<massFunction); return EXIT_SUCCESS; } diff --git a/Modules/Learning/DempsterShafer/test/otbMassOfBeliefDSApplied.cxx b/Modules/Learning/DempsterShafer/test/otbMassOfBeliefDSApplied.cxx index b39e2b5e0a8025c69dc99b77adf1c5c13af0fd3b..4ea8993fee118e879e9d976e6d2322297ca99548 100644 --- a/Modules/Learning/DempsterShafer/test/otbMassOfBeliefDSApplied.cxx +++ b/Modules/Learning/DempsterShafer/test/otbMassOfBeliefDSApplied.cxx @@ -24,6 +24,7 @@ #include "otbFuzzyVariable.h" #include "otbJointMassOfBeliefFilter.h" +#include "otbMacro.h" typedef float PrecisionType; @@ -90,27 +91,23 @@ int otbMassOfBeliefDSApplied(int itkNotUsed(argc), char* argv[]) jointMassFilter->Update(); jointMass = jointMassFilter->GetOutput(); - std::cout<<mass1<<std::endl; + otbLogMacro(Debug,<< "Mass 1:" <<mass1); - std::cout<<mass2<<std::endl; + otbLogMacro(Debug,<< "Mass 2:"<<mass2); - std::cout << jointMass << std::endl; - - std::cout << "Considered Hypothesis : "; - MassOfBeliefFunctionType::PrintLabelSet(std::cout, Hyp); - std::cout << std::endl; + otbLogMacro(Debug,<< "Joint mass :" << jointMass); + + std::ostringstream oss; + MassOfBeliefFunctionType::PrintLabelSet(oss, Hyp); + otbLogMacro(Info, << "Considered Hypothesis : " << oss.str()); - std::cout << "Belief(Hyp) : " - << jointMass->GetBelief(Hyp) - << " - Plausibility(Hyp) : " - << jointMass->GetPlausibility(Hyp) - << " - Score(Hyp) : " - << (jointMass->GetBelief(Hyp) + jointMass->GetPlausibility(Hyp))/2.0 - << std::endl; + otbLogMacro(Info, << "Belief(Hyp) : " << jointMass->GetBelief(Hyp)); + otbLogMacro(Info, << "Plausibility(Hyp) : " << jointMass->GetPlausibility(Hyp)); + otbLogMacro(Info, << "Score(Hyp) : " << (jointMass->GetBelief(Hyp) + jointMass->GetPlausibility(Hyp))/2.0); if (jointMass->GetBelief(Hyp) > jointMass->GetPlausibility(Hyp)) { - std::cout << "Belief > Plausibility" << std::endl; + otbLogMacro(Warning, << "Belief > Plausibility"); return EXIT_FAILURE; } else diff --git a/Modules/Learning/LearningBase/include/otbMachineLearningModel.hxx b/Modules/Learning/LearningBase/include/otbMachineLearningModel.hxx index 543453f5b9cae8f25ce88d244c2dfde2c9662693..392857b02bc6106fd3f474b0c4e169f186bca266 100644 --- a/Modules/Learning/LearningBase/include/otbMachineLearningModel.hxx +++ b/Modules/Learning/LearningBase/include/otbMachineLearningModel.hxx @@ -144,10 +144,13 @@ MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue> { assert(input != nullptr); assert(targets != nullptr); - - assert(input->Size()==targets->Size()&&"Input sample list and target label list do not have the same size."); - assert(((quality==nullptr)||(quality->Size()==input->Size()))&&"Quality samples list is not null and does not have the same size as input samples list"); - assert((proba==nullptr)||(input->Size()==proba->Size())&&"Proba sample list and target label list do not have the same size."); + + assert(input->Size() == targets->Size() + && "Input sample list and target label list do not have the same size."); + assert(((quality == nullptr) || (quality->Size() == input->Size())) + && "Quality samples list is not null and does not have the same size as input samples list"); + assert(((proba == nullptr) || (input->Size() == proba->Size())) + && "Proba sample list and target label list do not have the same size."); if(startIndex+size>input->Size()) { 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 cd5c2a6a7ae16064cc346f1010414e231c2f3e8a..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; } @@ -167,9 +168,12 @@ SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> assert(input != nullptr); assert(targets != nullptr); - assert(input->Size()==targets->Size()&&"Input sample list and target label list do not have the same size."); - assert(((quality==nullptr)||(quality->Size()==input->Size()))&&"Quality samples list is not null and does not have the same size as input samples list"); - assert((proba==nullptr)||(input->Size()==proba->Size())&&"Proba sample list and target label list do not have the same size."); + assert(input->Size() == targets->Size() + && "Input sample list and target label list do not have the same size."); + assert(((quality == nullptr) || (quality->Size() == input->Size())) + && "Quality samples list is not null and does not have the same size as input samples list"); + assert(((proba == nullptr) || (input->Size() == proba->Size())) + && "Proba sample list and target label list do not have the same size."); if(startIndex+size>input->Size()) { diff --git a/Modules/Learning/Supervised/test/otbTrainMachineLearningModel.cxx b/Modules/Learning/Supervised/test/otbTrainMachineLearningModel.cxx index df5cd21a5d24db67c8dac1c16d94f352f4e2cfe9..60f48c6e73daf1fa419d4a6e6e6418d4c8a03dee 100644 --- a/Modules/Learning/Supervised/test/otbTrainMachineLearningModel.cxx +++ b/Modules/Learning/Supervised/test/otbTrainMachineLearningModel.cxx @@ -22,6 +22,9 @@ #include <fstream> #include <string> #include <algorithm> +#include <chrono> + +#include "otbMacro.h" #include <otbMachineLearningModel.h> #include "otbConfusionMatrixCalculator.h" @@ -48,10 +51,28 @@ typedef MachineLearningModelRegressionType::TargetListSampleType TargetListSampl typedef otb::ConfusionMatrixCalculator<TargetListSampleType, TargetListSampleType> ConfusionMatrixCalculatorType; -#ifdef OTB_USE_LIBSVM -#include "otbLibSVMMachineLearningModel.h" +float GetConfusionMatrixResults(TargetListSampleType::Pointer predicted, TargetListSampleType::Pointer ref) +{ + ConfusionMatrixCalculatorType::Pointer cmCalculator = ConfusionMatrixCalculatorType::New(); + cmCalculator->SetProducedLabels(predicted); + cmCalculator->SetReferenceLabels(ref); + cmCalculator->Compute(); -int otbLibSVMMachineLearningModel(int argc, char * argv[]) + otbLogMacro(Debug, << "Confusion matrix:\n" << cmCalculator->GetConfusionMatrix()); + otbLogMacro(Info, << "Kappa: "<< cmCalculator->GetKappaIndex()); + otbLogMacro(Debug, << "Overall Accuracy: " << cmCalculator->GetOverallAccuracy()); + + return cmCalculator->GetKappaIndex(); +} + +template <class TModel> +void SetupModel(TModel* /*model*/) +{ + // do nothing by default +} + +template <class TModel> +int otbGenericMachineLearningModel(int argc, char * argv[]) { if (argc != 3) { @@ -59,69 +80,50 @@ int otbLibSVMMachineLearningModel(int argc, char * argv[]) std::cout<<"Usage : sample file, output file "<<std::endl; return EXIT_FAILURE; } - - - typedef otb::LibSVMMachineLearningModel<InputValueType, TargetValueType> SVMType; InputListSampleType::Pointer samples = InputListSampleType::New(); TargetListSampleType::Pointer labels = TargetListSampleType::New(); - if (!otb::ReadDataFile(argv[1], samples, labels)) { std::cout << "Failed to read samples file " << argv[1] << std::endl; return EXIT_FAILURE; } - SVMType::Pointer classifier = SVMType::New(); + typename TModel::Pointer classifier = TModel::New(); classifier->SetInputListSample(samples); classifier->SetTargetListSample(labels); + SetupModel<TModel>(classifier); classifier->Train(); - - TargetListSampleType::Pointer predicted = classifier->PredictBatch(samples, NULL); - - ConfusionMatrixCalculatorType::Pointer cmCalculator = ConfusionMatrixCalculatorType::New(); - - cmCalculator->SetProducedLabels(predicted); - cmCalculator->SetReferenceLabels(labels); - cmCalculator->Compute(); - - std::cout << "Confusion matrix: " << std::endl; - std::cout << cmCalculator->GetConfusionMatrix() << std::endl; - const float kappaIdx = cmCalculator->GetKappaIndex(); - std::cout<<"Kappa: "<<kappaIdx<<std::endl; - std::cout << "Overall Accuracy: " << cmCalculator->GetOverallAccuracy() << std::endl; - classifier->Save(argv[2]); + TargetListSampleType::Pointer predicted = classifier->PredictBatch(samples, NULL); + const float kappa = GetConfusionMatrixResults(predicted, labels); - //Load Model to new LibSVM - SVMType::Pointer classifierLoad = SVMType::New(); - + typename TModel::Pointer classifierLoad = TModel::New(); classifierLoad->Load(argv[2]); + auto start = std::chrono::system_clock::now(); + otbLogMacro(Debug, << "Predict loaded"); TargetListSampleType::Pointer predictedLoad = classifierLoad->PredictBatch(samples, NULL); + using TimeT = std::chrono::milliseconds; + auto duration = std::chrono::duration_cast< TimeT> + (std::chrono::system_clock::now() - start); + auto elapsed = duration.count(); + otbLogMacro(Debug, << "PredictBatch took " << elapsed << " ms"); + const float kappaLoad = GetConfusionMatrixResults(predictedLoad, labels); - ConfusionMatrixCalculatorType::Pointer cmCalculatorLoad = ConfusionMatrixCalculatorType::New(); - - cmCalculatorLoad->SetProducedLabels(predictedLoad); - cmCalculatorLoad->SetReferenceLabels(labels); - cmCalculatorLoad->Compute(); - - std::cout<<"Confusion matrix: "<<std::endl; - std::cout<<cmCalculatorLoad->GetConfusionMatrix()<<std::endl; - const float kappaIdxLoad = cmCalculatorLoad->GetKappaIndex(); - std::cout<<"Kappa: "<<kappaIdxLoad<<std::endl; - std::cout<<"Overall Accuracy: "<<cmCalculatorLoad->GetOverallAccuracy()<<std::endl; + return (std::abs(kappaLoad - kappa) < 0.00000001 ? EXIT_SUCCESS : EXIT_FAILURE); +} +// -------------------------- LibSVM ------------------------------------------- +#ifdef OTB_USE_LIBSVM +#include "otbLibSVMMachineLearningModel.h" - if ( std::abs(kappaIdxLoad - kappaIdx) < 0.00000001) - { - return EXIT_SUCCESS; - } - else - { - return EXIT_FAILURE; - } +using LibSVMType = otb::LibSVMMachineLearningModel<InputValueType, TargetValueType>; +int otbLibSVMMachineLearningModel(int argc, char * argv[]) +{ + return otbGenericMachineLearningModel<LibSVMType>(argc,argv); } #endif +// -------------------------- OpenCV ------------------------------------------- #ifdef OTB_USE_OPENCV #include "otbSVMMachineLearningModel.h" #include "otbKNearestNeighborsMachineLearningModel.h" @@ -132,75 +134,10 @@ int otbLibSVMMachineLearningModel(int argc, char * argv[]) #include "otbDecisionTreeMachineLearningModel.h" #include "otbKNearestNeighborsMachineLearningModel.h" - +using SVMType = otb::SVMMachineLearningModel<InputValueType, TargetValueType>; int otbSVMMachineLearningModel(int argc, char * argv[]) { - if (argc != 3 ) - { - std::cout<<"Wrong number of arguments "<<std::endl; - std::cout<<"Usage : sample file, output file "<<std::endl; - return EXIT_FAILURE; - } - - typedef otb::SVMMachineLearningModel<InputValueType, TargetValueType> SVMType; - - InputListSampleType::Pointer samples = InputListSampleType::New(); - TargetListSampleType::Pointer labels = TargetListSampleType::New(); - - if(!otb::ReadDataFile(argv[1],samples,labels)) - { - std::cout<<"Failed to read samples file "<<argv[1]<<std::endl; - return EXIT_FAILURE; - } - - SVMType::Pointer classifier = SVMType::New(); - classifier->SetInputListSample(samples); - classifier->SetTargetListSample(labels); - classifier->Train(); - - TargetListSampleType::Pointer predicted = classifier->PredictBatch(samples, NULL); - - classifier->Save(argv[2]); - - ConfusionMatrixCalculatorType::Pointer cmCalculator = ConfusionMatrixCalculatorType::New(); - - cmCalculator->SetProducedLabels(predicted); - cmCalculator->SetReferenceLabels(labels); - cmCalculator->Compute(); - - std::cout<<"Confusion matrix: "<<std::endl; - std::cout<<cmCalculator->GetConfusionMatrix()<<std::endl; - const float kappaIdx = cmCalculator->GetKappaIndex(); - std::cout<<"Kappa: "<<kappaIdx<<std::endl; - std::cout<<"Overall Accuracy: "<<cmCalculator->GetOverallAccuracy()<<std::endl; - - //Load Model to new SVM - SVMType::Pointer classifierLoad = SVMType::New(); - - classifierLoad->Load(argv[2]); - TargetListSampleType::Pointer predictedLoad = classifierLoad->PredictBatch(samples); - - ConfusionMatrixCalculatorType::Pointer cmCalculatorLoad = ConfusionMatrixCalculatorType::New(); - - cmCalculatorLoad->SetProducedLabels(predictedLoad); - cmCalculatorLoad->SetReferenceLabels(labels); - cmCalculatorLoad->Compute(); - - std::cout<<"Confusion matrix: "<<std::endl; - std::cout<<cmCalculatorLoad->GetConfusionMatrix()<<std::endl; - const float kappaIdxLoad = cmCalculatorLoad->GetKappaIndex(); - std::cout<<"Kappa: "<<kappaIdxLoad<<std::endl; - std::cout<<"Overall Accuracy: "<<cmCalculatorLoad->GetOverallAccuracy()<<std::endl; - - - if ( std::abs(kappaIdxLoad - kappaIdx) < 0.00000001) - { - return EXIT_SUCCESS; - } - else - { - return EXIT_FAILURE; - } + return otbGenericMachineLearningModel<SVMType>(argc,argv); } int otbSVMMachineLearningRegressionModel(int argc, char * argv[]) @@ -272,570 +209,93 @@ int otbSVMMachineLearningRegressionModel(int argc, char * argv[]) } } - +using KNearestNeighborsType = otb::KNearestNeighborsMachineLearningModel<InputValueType,TargetValueType>; int otbKNearestNeighborsMachineLearningModel(int argc, char * argv[]) { - if (argc != 3 ) - { - std::cout<<"Wrong number of arguments "<<std::endl; - std::cout<<"Usage : sample file, output file"<<std::endl; - return EXIT_FAILURE; - } - - typedef otb::KNearestNeighborsMachineLearningModel<InputValueType,TargetValueType> KNearestNeighborsType; - InputListSampleType::Pointer samples = InputListSampleType::New(); - TargetListSampleType::Pointer labels = TargetListSampleType::New(); - - if(!otb::ReadDataFile(argv[1],samples,labels)) - { - std::cout<<"Failed to read samples file "<<argv[1]<<std::endl; - return EXIT_FAILURE; - } - - KNearestNeighborsType::Pointer classifier = KNearestNeighborsType::New(); - classifier->SetInputListSample(samples); - classifier->SetTargetListSample(labels); - classifier->Train(); - //write the model - classifier->Save(argv[2]); - - TargetListSampleType::Pointer predicted = classifier->PredictBatch(samples, NULL); - - ConfusionMatrixCalculatorType::Pointer cmCalculator = ConfusionMatrixCalculatorType::New(); - - cmCalculator->SetProducedLabels(predicted); - cmCalculator->SetReferenceLabels(labels); - cmCalculator->Compute(); - - std::cout<<"Confusion matrix: "<<std::endl; - std::cout<<cmCalculator->GetConfusionMatrix()<<std::endl; - const float kappaIdx = cmCalculator->GetKappaIndex(); - std::cout<<"Kappa: "<<kappaIdx<<std::endl; - std::cout<<"Overall Accuracy: "<<cmCalculator->GetOverallAccuracy()<<std::endl; - - - //Load Model to new KNN - KNearestNeighborsType::Pointer classifierLoad = KNearestNeighborsType::New(); - - classifierLoad->Load(argv[2]); - TargetListSampleType::Pointer predictedLoad = classifierLoad->PredictBatch(samples, NULL); - - ConfusionMatrixCalculatorType::Pointer cmCalculatorLoad = ConfusionMatrixCalculatorType::New(); - - cmCalculatorLoad->SetProducedLabels(predictedLoad); - cmCalculatorLoad->SetReferenceLabels(labels); - cmCalculatorLoad->Compute(); - - std::cout<<"Confusion matrix: "<<std::endl; - std::cout<<cmCalculatorLoad->GetConfusionMatrix()<<std::endl; - const float kappaIdxLoad = cmCalculatorLoad->GetKappaIndex(); - std::cout<<"Kappa: "<<kappaIdxLoad<<std::endl; - std::cout<<"Overall Accuracy: "<<cmCalculatorLoad->GetOverallAccuracy()<<std::endl; - - - if ( std::abs(kappaIdxLoad - kappaIdx) < 0.00000001) - { - return EXIT_SUCCESS; - } - else - { - return EXIT_FAILURE; - } + return otbGenericMachineLearningModel<KNearestNeighborsType>(argc,argv); } - +using RandomForestType = otb::RandomForestsMachineLearningModel<InputValueType,TargetValueType>; int otbRandomForestsMachineLearningModel(int argc, char * argv[]) { - if (argc != 3 ) - { - std::cout<<"Wrong number of arguments "<<std::endl; - std::cout<<"Usage : sample file, output file "<<std::endl; - return EXIT_FAILURE; - } - - typedef otb::RandomForestsMachineLearningModel<InputValueType,TargetValueType> RandomForestType; - InputListSampleType::Pointer samples = InputListSampleType::New(); - TargetListSampleType::Pointer labels = TargetListSampleType::New(); - - if(!otb::ReadDataFile(argv[1],samples,labels)) - { - std::cout<<"Failed to read samples file "<<argv[1]<<std::endl; - return EXIT_FAILURE; - } + return otbGenericMachineLearningModel<RandomForestType>(argc,argv); +} +template <> +void SetupModel(RandomForestType* model) +{ std::vector<float> priors(26,1.); - - - RandomForestType::Pointer classifier = RandomForestType::New(); - classifier->SetInputListSample(samples); - classifier->SetTargetListSample(labels); - - //set parameters - classifier->SetPriors(priors); - // classifier->SetMaxNumberOfTrees(30); - // classifier->SetMaxDepth(30); - // classifier->SetMaxNumberOfCategories(30); - // classifier->SetMaxNumberOfVariables(4); - - classifier->Train(); - classifier->Save(argv[2]); - - TargetListSampleType::Pointer predicted = classifier->PredictBatch(samples, NULL); - - ConfusionMatrixCalculatorType::Pointer cmCalculator = ConfusionMatrixCalculatorType::New(); - - cmCalculator->SetProducedLabels(predicted); - cmCalculator->SetReferenceLabels(labels); - cmCalculator->Compute(); - - std::cout<<"Confusion matrix: "<<std::endl; - std::cout<<cmCalculator->GetConfusionMatrix()<<std::endl; - const float kappaIdx = cmCalculator->GetKappaIndex(); - std::cout<<"Kappa: "<<kappaIdx<<std::endl; - std::cout<<"Overall Accuracy: "<<cmCalculator->GetOverallAccuracy()<<std::endl; - - //Load Model to new RF - RandomForestType::Pointer classifierLoad = RandomForestType::New(); - - classifierLoad->Load(argv[2]); - TargetListSampleType::Pointer predictedLoad = classifierLoad->PredictBatch(samples, NULL); - - ConfusionMatrixCalculatorType::Pointer cmCalculatorLoad = ConfusionMatrixCalculatorType::New(); - - cmCalculatorLoad->SetProducedLabels(predictedLoad); - cmCalculatorLoad->SetReferenceLabels(labels); - cmCalculatorLoad->Compute(); - - std::cout<<"Confusion matrix: "<<std::endl; - std::cout<<cmCalculatorLoad->GetConfusionMatrix()<<std::endl; - const float kappaIdxLoad = cmCalculatorLoad->GetKappaIndex(); - std::cout<<"Kappa: "<<kappaIdxLoad<<std::endl; - std::cout<<"Overall Accuracy: "<<cmCalculatorLoad->GetOverallAccuracy()<<std::endl; - - - if ( std::abs(kappaIdxLoad - kappaIdx) < 0.00000001) - { - return EXIT_SUCCESS; - } - else - { - return EXIT_FAILURE; - } + model->SetPriors(priors); } - +using BoostType = otb::BoostMachineLearningModel<InputValueType, TargetValueType>; int otbBoostMachineLearningModel(int argc, char * argv[]) { - if (argc != 3 ) - { - std::cout<<"Wrong number of arguments "<<std::endl; - std::cout<<"Usage : sample file, output file "<<std::endl; - return EXIT_FAILURE; - } - - typedef otb::BoostMachineLearningModel<InputValueType, TargetValueType> BoostType; - - InputListSampleType::Pointer samples = InputListSampleType::New(); - TargetListSampleType::Pointer labels = TargetListSampleType::New(); - - if(!otb::ReadDataFile(argv[1],samples,labels)) - { - std::cout<<"Failed to read samples file "<<argv[1]<<std::endl; - return EXIT_FAILURE; - } + return otbGenericMachineLearningModel<BoostType>(argc,argv); +} +template <> +void SetupModel(BoostType *model) +{ // Since otb::BoostMachineLearningModel ONLY handles 2-class classifications, then the // labels are split into 2 subsets: even (label = 1) and odd (label = 3) labels + TargetListSampleType::Pointer labels = model->GetTargetListSample(); TargetSampleType currentLabel; for (unsigned itLabel = 0; itLabel < labels->Size(); ++itLabel) { currentLabel = labels->GetMeasurementVector(itLabel); labels->SetMeasurementVector(itLabel, (2 * (currentLabel[0] % 2)) + 1); } - - BoostType::Pointer classifier = BoostType::New(); - classifier->SetInputListSample(samples); - classifier->SetTargetListSample(labels); - classifier->Train(); - - TargetListSampleType::Pointer predicted = classifier->PredictBatch(samples, NULL); - - classifier->Save(argv[2]); - - ConfusionMatrixCalculatorType::Pointer cmCalculator = ConfusionMatrixCalculatorType::New(); - - cmCalculator->SetProducedLabels(predicted); - cmCalculator->SetReferenceLabels(labels); - cmCalculator->Compute(); - - std::cout<<"Confusion matrix: "<<std::endl; - std::cout<<cmCalculator->GetConfusionMatrix()<<std::endl; - const float kappaIdx = cmCalculator->GetKappaIndex(); - std::cout<<"Kappa: "<<kappaIdx<<std::endl; - std::cout<<"Overall Accuracy: "<<cmCalculator->GetOverallAccuracy()<<std::endl; - - //Load Model to new Boost model - BoostType::Pointer classifierLoad = BoostType::New(); - - classifierLoad->Load(argv[2]); - TargetListSampleType::Pointer predictedLoad = classifierLoad->PredictBatch(samples, NULL); - - ConfusionMatrixCalculatorType::Pointer cmCalculatorLoad = ConfusionMatrixCalculatorType::New(); - - cmCalculatorLoad->SetProducedLabels(predictedLoad); - cmCalculatorLoad->SetReferenceLabels(labels); - cmCalculatorLoad->Compute(); - - std::cout<<"Confusion matrix: "<<std::endl; - std::cout<<cmCalculatorLoad->GetConfusionMatrix()<<std::endl; - const float kappaIdxLoad = cmCalculatorLoad->GetKappaIndex(); - std::cout<<"Kappa: "<<kappaIdxLoad<<std::endl; - std::cout<<"Overall Accuracy: "<<cmCalculatorLoad->GetOverallAccuracy()<<std::endl; - - - if ( std::abs(kappaIdxLoad - kappaIdx) < 0.00000001) - { - return EXIT_SUCCESS; - } - else - { - return EXIT_FAILURE; - } + model->SetTargetListSample(labels); } - +using ANNType = otb::NeuralNetworkMachineLearningModel<InputValueType, TargetValueType>; int otbANNMachineLearningModel(int argc, char * argv[]) { - if (argc != 3) - { - std::cout<<"Wrong number of arguments "<<std::endl; - std::cout<<"Usage : sample file, output file "<<std::endl; - return EXIT_FAILURE; - } - - - typedef otb::NeuralNetworkMachineLearningModel<InputValueType, TargetValueType> ANNType; - InputListSampleType::Pointer samples = InputListSampleType::New(); - TargetListSampleType::Pointer labels = TargetListSampleType::New(); - - if (!otb::ReadDataFile(argv[1], samples, labels)) - { - std::cout << "Failed to read samples file " << argv[1] << std::endl; - return EXIT_FAILURE; - } + return otbGenericMachineLearningModel<ANNType>(argc,argv); +} +template <> +void SetupModel(ANNType* model) +{ std::vector<unsigned int> layerSizes; layerSizes.push_back(16); layerSizes.push_back(100); layerSizes.push_back(100); layerSizes.push_back(26); - - ANNType::Pointer classifier = ANNType::New(); - classifier->SetInputListSample(samples); - classifier->SetTargetListSample(labels); - classifier->SetLayerSizes(layerSizes); - /*classifier->SetTrainMethod(CvANN_MLP_TrainParams::RPROP); - classifier->SetRegPropDW0(0.1); - classifier->SetRegPropDWMin(0.1); - classifier->SetTermCriteriaType(CV_TERMCRIT_ITER); - classifier->SetMaxIter(300); - classifier->SetEpsilon(0.01); */ - classifier->Train(); - - TargetListSampleType::Pointer predicted = classifier->PredictBatch(samples, NULL); - - ConfusionMatrixCalculatorType::Pointer cmCalculator = ConfusionMatrixCalculatorType::New(); - - cmCalculator->SetProducedLabels(predicted); - cmCalculator->SetReferenceLabels(labels); - cmCalculator->Compute(); - - std::cout << "Confusion matrix: " << std::endl; - std::cout << cmCalculator->GetConfusionMatrix() << std::endl; - const float kappaIdx = cmCalculator->GetKappaIndex(); - std::cout<<"Kappa: "<<kappaIdx<<std::endl; - std::cout << "Overall Accuracy: " << cmCalculator->GetOverallAccuracy() << std::endl; - - classifier->Save(argv[2]); - - //Load Model to new ANN - ANNType::Pointer classifierLoad = ANNType::New(); - - classifierLoad->Load(argv[2]); - TargetListSampleType::Pointer predictedLoad = classifierLoad->PredictBatch(samples, NULL); - - ConfusionMatrixCalculatorType::Pointer cmCalculatorLoad = ConfusionMatrixCalculatorType::New(); - - cmCalculatorLoad->SetProducedLabels(predictedLoad); - cmCalculatorLoad->SetReferenceLabels(labels); - cmCalculatorLoad->Compute(); - - std::cout<<"Confusion matrix: "<<std::endl; - std::cout<<cmCalculatorLoad->GetConfusionMatrix()<<std::endl; - const float kappaIdxLoad = cmCalculatorLoad->GetKappaIndex(); - std::cout<<"Kappa: "<<kappaIdxLoad<<std::endl; - std::cout<<"Overall Accuracy: "<<cmCalculatorLoad->GetOverallAccuracy()<<std::endl; - - - if ( std::abs(kappaIdxLoad - kappaIdx) < 0.00000001) - { - return EXIT_SUCCESS; - } - else - { - return EXIT_FAILURE; - } + model->SetLayerSizes(layerSizes); } - +using NormalBayesType = otb::NormalBayesMachineLearningModel<InputValueType, TargetValueType>; int otbNormalBayesMachineLearningModel(int argc, char * argv[]) { - if (argc != 3 ) - { - std::cout<<"Wrong number of arguments "<<std::endl; - std::cout<<"Usage : sample file, output file "<<std::endl; - return EXIT_FAILURE; - } - - typedef otb::NormalBayesMachineLearningModel<InputValueType, TargetValueType> NormalBayesType; - - InputListSampleType::Pointer samples = InputListSampleType::New(); - TargetListSampleType::Pointer labels = TargetListSampleType::New(); - - if(!otb::ReadDataFile(argv[1],samples,labels)) - { - std::cout<<"Failed to read samples file "<<argv[1]<<std::endl; - return EXIT_FAILURE; - } - - NormalBayesType::Pointer classifier = NormalBayesType::New(); - classifier->SetInputListSample(samples); - classifier->SetTargetListSample(labels); - classifier->Train(); - - TargetListSampleType::Pointer predicted = classifier->PredictBatch(samples, NULL); - - classifier->Save(argv[2]); - - ConfusionMatrixCalculatorType::Pointer cmCalculator = ConfusionMatrixCalculatorType::New(); - - cmCalculator->SetProducedLabels(predicted); - cmCalculator->SetReferenceLabels(labels); - cmCalculator->Compute(); - - std::cout<<"Confusion matrix: "<<std::endl; - std::cout<<cmCalculator->GetConfusionMatrix()<<std::endl; - const float kappaIdx = cmCalculator->GetKappaIndex(); - std::cout<<"Kappa: "<<kappaIdx<<std::endl; - std::cout<<"Overall Accuracy: "<<cmCalculator->GetOverallAccuracy()<<std::endl; - - //Load Model to new Normal Bayes - NormalBayesType::Pointer classifierLoad = NormalBayesType::New(); - - classifierLoad->Load(argv[2]); - TargetListSampleType::Pointer predictedLoad = classifierLoad->PredictBatch(samples, NULL); - - ConfusionMatrixCalculatorType::Pointer cmCalculatorLoad = ConfusionMatrixCalculatorType::New(); - - cmCalculatorLoad->SetProducedLabels(predictedLoad); - cmCalculatorLoad->SetReferenceLabels(labels); - cmCalculatorLoad->Compute(); - - std::cout<<"Confusion matrix: "<<std::endl; - std::cout<<cmCalculatorLoad->GetConfusionMatrix()<<std::endl; - const float kappaIdxLoad = cmCalculatorLoad->GetKappaIndex(); - std::cout<<"Kappa: "<<kappaIdxLoad<<std::endl; - std::cout<<"Overall Accuracy: "<<cmCalculatorLoad->GetOverallAccuracy()<<std::endl; - - - if ( std::abs(kappaIdxLoad - kappaIdx) < 0.00000001) - { - return EXIT_SUCCESS; - } - else - { - return EXIT_FAILURE; - } + return otbGenericMachineLearningModel<NormalBayesType>(argc,argv); } - +using DecisionTreeType = otb::DecisionTreeMachineLearningModel<InputValueType, TargetValueType>; int otbDecisionTreeMachineLearningModel(int argc, char * argv[]) { - if (argc != 3 ) - { - std::cout<<"Wrong number of arguments "<<std::endl; - std::cout<<"Usage : sample file, output file "<<std::endl; - return EXIT_FAILURE; - } - - typedef otb::DecisionTreeMachineLearningModel<InputValueType, TargetValueType> DecisionTreeType; - - InputListSampleType::Pointer samples = InputListSampleType::New(); - TargetListSampleType::Pointer labels = TargetListSampleType::New(); - - if(!otb::ReadDataFile(argv[1],samples,labels)) - { - std::cout<<"Failed to read samples file "<<argv[1]<<std::endl; - return EXIT_FAILURE; - } - - DecisionTreeType::Pointer classifier = DecisionTreeType::New(); - classifier->SetInputListSample(samples); - classifier->SetTargetListSample(labels); - classifier->Train(); - - TargetListSampleType::Pointer predicted = classifier->PredictBatch(samples, NULL); - - classifier->Save(argv[2]); - - ConfusionMatrixCalculatorType::Pointer cmCalculator = ConfusionMatrixCalculatorType::New(); - - cmCalculator->SetProducedLabels(predicted); - cmCalculator->SetReferenceLabels(labels); - cmCalculator->Compute(); - - std::cout<<"Confusion matrix: "<<std::endl; - std::cout<<cmCalculator->GetConfusionMatrix()<<std::endl; - const float kappaIdx = cmCalculator->GetKappaIndex(); - std::cout<<"Kappa: "<<kappaIdx<<std::endl; - std::cout<<"Overall Accuracy: "<<cmCalculator->GetOverallAccuracy()<<std::endl; - - //Load Model to new Decision Tree - DecisionTreeType::Pointer classifierLoad = DecisionTreeType::New(); - - classifierLoad->Load(argv[2]); - TargetListSampleType::Pointer predictedLoad = classifierLoad->PredictBatch(samples, NULL); - - ConfusionMatrixCalculatorType::Pointer cmCalculatorLoad = ConfusionMatrixCalculatorType::New(); - - cmCalculatorLoad->SetProducedLabels(predictedLoad); - cmCalculatorLoad->SetReferenceLabels(labels); - cmCalculatorLoad->Compute(); - - std::cout<<"Confusion matrix: "<<std::endl; - std::cout<<cmCalculatorLoad->GetConfusionMatrix()<<std::endl; - const float kappaIdxLoad = cmCalculatorLoad->GetKappaIndex(); - std::cout<<"Kappa: "<<kappaIdxLoad<<std::endl; - std::cout<<"Overall Accuracy: "<<cmCalculatorLoad->GetOverallAccuracy()<<std::endl; - - - if ( std::abs(kappaIdxLoad - kappaIdx) < 0.00000001) - { - return EXIT_SUCCESS; - } - else - { - return EXIT_FAILURE; - } + return otbGenericMachineLearningModel<DecisionTreeType>(argc,argv); } - #endif +// -------------------------- Shark -------------------------------------------- #ifdef OTB_USE_SHARK -#include <chrono> // If shark is on, then we are using c++11 - #include "otbSharkRandomForestsMachineLearningModel.h" +using SharkRandomForestType = otb::SharkRandomForestsMachineLearningModel<InputValueType,TargetValueType>; int otbSharkRFMachineLearningModel(int argc, char * argv[]) { - if (argc != 3 ) - { - std::cout<<"Wrong number of arguments "<<std::endl; - std::cout<<"Usage : sample file, output file "<<std::endl; - return EXIT_FAILURE; - } - - typedef otb::SharkRandomForestsMachineLearningModel<InputValueType,TargetValueType> RandomForestType; - InputListSampleType::Pointer samples = InputListSampleType::New(); - TargetListSampleType::Pointer labels = TargetListSampleType::New(); - - if(!otb::ReadDataFile(argv[1],samples,labels)) - { - std::cout<<"Failed to read samples file "<<argv[1]<<std::endl; - return EXIT_FAILURE; - } - - - RandomForestType::Pointer classifier = RandomForestType::New(); - classifier->SetInputListSample(samples); - classifier->SetTargetListSample(labels); - classifier->SetRegressionMode(false); - classifier->SetNumberOfTrees(100); - classifier->SetMTry(0); - classifier->SetNodeSize(25); - classifier->SetOobRatio(0.3); - std::cout << "Train\n"; - classifier->Train(); - std::cout << "Save\n"; - classifier->Save(argv[2]); - - std::cout << "Predict\n"; - TargetListSampleType::Pointer predicted = classifier->PredictBatch(samples, NULL); - - ConfusionMatrixCalculatorType::Pointer cmCalculator = ConfusionMatrixCalculatorType::New(); - - cmCalculator->SetProducedLabels(predicted); - cmCalculator->SetReferenceLabels(labels); - cmCalculator->Compute(); - - std::cout<<"Confusion matrix: "<<std::endl; - std::cout<<cmCalculator->GetConfusionMatrix()<<std::endl; - const float kappaIdx = cmCalculator->GetKappaIndex(); - std::cout<<"Kappa: "<<kappaIdx<<std::endl; - std::cout<<"Overall Accuracy: "<<cmCalculator->GetOverallAccuracy()<<std::endl; - - // //Predict single samples. Written for benchmarking purposes, but - // too long for regression testing - // std::cout << "Predict single samples\n"; - // auto sIt = samples->Begin(); - // auto lIt = labels->Begin(); - // auto start = std::chrono::system_clock::now(); - // for(; sIt != samples->End(); ++sIt, ++lIt) - // { - // classifier->Predict(sIt.GetMeasurementVector())[0]; - // } - // auto duration = std::chrono::duration_cast< TimeT> - // (std::chrono::system_clock::now() - start); - // auto elapsed = duration.count(); - // std::cout << "Predict took " << elapsed << " ms\n"; - // std::cout << "Single sample OA = " << oa << '\n'; -//Load Model to new RF - RandomForestType::Pointer classifierLoad = RandomForestType::New(); - - std::cout << "Load\n"; - classifierLoad->Load(argv[2]); - auto start = std::chrono::system_clock::now(); - std::cout << "Predict loaded\n"; - TargetListSampleType::Pointer predictedLoad = classifierLoad->PredictBatch(samples, NULL); - using TimeT = std::chrono::milliseconds; - auto duration = std::chrono::duration_cast< TimeT> - (std::chrono::system_clock::now() - start); - auto elapsed = duration.count(); - std::cout << "PredictBatch took " << elapsed << " ms\n"; - ConfusionMatrixCalculatorType::Pointer cmCalculatorLoad = ConfusionMatrixCalculatorType::New(); - - cmCalculatorLoad->SetProducedLabels(predictedLoad); - cmCalculatorLoad->SetReferenceLabels(labels); - cmCalculatorLoad->Compute(); - - std::cout<<"Confusion matrix: "<<std::endl; - std::cout<<cmCalculatorLoad->GetConfusionMatrix()<<std::endl; - const float kappaIdxLoad = cmCalculatorLoad->GetKappaIndex(); - std::cout<<"Kappa: "<<kappaIdxLoad<<std::endl; - std::cout<<"Overall Accuracy: "<<cmCalculatorLoad->GetOverallAccuracy()<<std::endl; - - - if ( std::abs(kappaIdxLoad - kappaIdx) < 0.00000001) - { - return EXIT_SUCCESS; - } - else - { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; + return otbGenericMachineLearningModel<SharkRandomForestType>(argc,argv); } - +template <> +void SetupModel(SharkRandomForestType* model) +{ + model->SetRegressionMode(false); + model->SetNumberOfTrees(100); + model->SetMTry(0); + model->SetNodeSize(25); + model->SetOobRatio(0.3); +} #endif diff --git a/Modules/Radiometry/OpticalCalibration/test/otbSurfaceAdjacencyEffectCorrectionSchemeFilter.cxx b/Modules/Radiometry/OpticalCalibration/test/otbSurfaceAdjacencyEffectCorrectionSchemeFilter.cxx index c70da18dfa09004c57facbcc8a9fa3a8cecb319d..0b099fbd35c0481504aaa2835f3c923e907a9339 100644 --- a/Modules/Radiometry/OpticalCalibration/test/otbSurfaceAdjacencyEffectCorrectionSchemeFilter.cxx +++ b/Modules/Radiometry/OpticalCalibration/test/otbSurfaceAdjacencyEffectCorrectionSchemeFilter.cxx @@ -26,6 +26,7 @@ #include "otbImageFileWriter.h" #include "otbAtmosphericCorrectionParameters.h" #include "otbAtmosphericRadiativeTerms.h" +#include "otbMacro.h" #include <fstream> #include <iostream> @@ -150,9 +151,9 @@ int otbSurfaceAdjacencyEffectCorrectionSchemeFilter(int itkNotUsed(argc), char * { value = atof(line.c_str()); vect.push_back(value); - std::cout << "value " << value << std::endl; + otbLogMacro(Debug, << "value " << value); } - std::cout << "vec size " << vect.size()<< std::endl; + otbLogMacro(Debug, << "vec size " << vect.size()); fin2.close(); functionValues->SetFilterFunctionValues(vect); functionValues->SetMinSpectralValue(minSpectralValue); diff --git a/Modules/Radiometry/Simulation/test/otbReduceSpectralResponse.cxx b/Modules/Radiometry/Simulation/test/otbReduceSpectralResponse.cxx index b5e61e7a7056980e76a758d5adabf0463d28cf86..154ee53f4a9d599310e92ea39f5585b70c50d0db 100644 --- a/Modules/Radiometry/Simulation/test/otbReduceSpectralResponse.cxx +++ b/Modules/Radiometry/Simulation/test/otbReduceSpectralResponse.cxx @@ -66,14 +66,13 @@ int otbReduceSpectralResponse(int argc, char * argv[]) myReduceResponse->SetReflectanceMode(reflectanceMode); myReduceResponse->CalculateResponse(); /** Print the Reduce SR*/ - std::cout << myReduceResponse << std::endl; + otbLogMacro(Debug, << myReduceResponse); if (argc == 6) { char * outputName = argv[5]; std::ofstream outputFile(outputName, std::ios::out); outputFile << myReduceResponse << std::endl; } - else std::cout << myReduceResponse << std::endl; return EXIT_SUCCESS; } diff --git a/Modules/Radiometry/Simulation/test/otbReduceSpectralResponseSVMClassifier.cxx b/Modules/Radiometry/Simulation/test/otbReduceSpectralResponseSVMClassifier.cxx index b62fad816de6dc073338364c29c483ac41a6b2aa..7a707f714090b4f7d3592cd03ea7ea614ad2905a 100644 --- a/Modules/Radiometry/Simulation/test/otbReduceSpectralResponseSVMClassifier.cxx +++ b/Modules/Radiometry/Simulation/test/otbReduceSpectralResponseSVMClassifier.cxx @@ -19,7 +19,7 @@ */ - +#include "otbMacro.h" #include "otbSatelliteRSR.h" #include "otbReduceSpectralResponse.h" @@ -89,7 +89,7 @@ int otbReduceSpectralResponseSVMClassifier(int argc, char * argv[]) for (unsigned int i = 0; i < dirSR.size(); ++i) //for each class (directory) { - std::cout << "dirSR[" << i << "] : " << dirSR[i] << std::endl; + otbLogMacro(Info, << "dirSR[" << i << "] : " << dirSR[i]); std::string fileExp = dirSR[i]; // Find all .txt file in the directory @@ -97,7 +97,7 @@ int otbReduceSpectralResponseSVMClassifier(int argc, char * argv[]) itksys::Glob glob; if ( glob.FindFiles( fileExp ) == false ) { - std::cout<<"No .txt file found in "<<dirSR[i]<<"."<<std::endl; + otbLogMacro(Warning,<<"No .txt file found in "<<dirSR[i]<<"."); return EXIT_FAILURE; } @@ -122,14 +122,14 @@ int otbReduceSpectralResponseSVMClassifier(int argc, char * argv[]) //add to global training files and testing files for (unsigned int k = 0; k < testing.size(); ++k) { - std::cout << "testing[" << k << "] : " << testing[k] << std::endl; + otbLogMacro(Debug, << "testing[" << k << "] : " << testing[k]); testingFiles.push_back(testing[k]); testingGTClasses.push_back(i); } for (unsigned int l = 0; l < training.size(); ++l) { - std::cout << "training[" << l << "] : " << training[l] << std::endl; + otbLogMacro(Debug, << "training[" << l << "] : " << training[l]); trainingFiles.push_back(training[l]); trainingClasses.push_back(i); //class is the directory number } @@ -141,7 +141,7 @@ int otbReduceSpectralResponseSVMClassifier(int argc, char * argv[]) for (unsigned int i = 0; i < trainingFiles.size(); ++i) { ResponsePointerType spectralResponse = ResponseType::New(); - std::cout << "training file : " << trainingFiles[i] << std::endl; + otbLogMacro(Debug, << "training file : " << trainingFiles[i]); spectralResponse->Load(trainingFiles[i], 100.0); //Compute Reduce Spectral Response @@ -156,17 +156,19 @@ int otbReduceSpectralResponseSVMClassifier(int argc, char * argv[]) SampleType sample; TrainingSampleType trainingSample; sample.SetSize(reduceResponse->GetReduceResponse()->Size()); - std::cout << "reduce response : ["; + std::ostringstream oss; + oss << "reduce response : ["; for (unsigned int j = 0; j < reduceResponse->GetReduceResponse()->Size(); ++j) { sample[j] = reduceResponse->GetReduceResponse()->GetResponse()[j].second; - std::cout << reduceResponse->GetReduceResponse()->GetResponse()[j].second << " "; + oss << reduceResponse->GetReduceResponse()->GetResponse()[j].second << " "; } - std::cout << "]" << std::endl; + oss << "]"; + otbLogMacro(Debug, << oss.str()); sampleList->SetMeasurementVectorSize(nbBand); sampleList->PushBack(sample); trainingSample = trainingClasses[i]; - std::cout << "training class : " << trainingSample << std::endl; + otbLogMacro(Debug, << "training class : " << trainingSample); trainingList->PushBack(trainingSample); } @@ -191,7 +193,7 @@ int otbReduceSpectralResponseSVMClassifier(int argc, char * argv[]) for (unsigned int i = 0; i < testingFiles.size(); ++i) { ResponsePointerType spectralResponse = ResponseType::New(); - std::cout << "testing file : " << testingFiles[i] << std::endl; + otbLogMacro(Debug, << "testing file : " << testingFiles[i]); spectralResponse->Load(testingFiles[i], 100.0); //Compute Reduce Spectral Response @@ -222,12 +224,12 @@ int otbReduceSpectralResponseSVMClassifier(int argc, char * argv[]) TrainingSampleListType::ConstIterator it = classifierListLabel->Begin(); while (it != classifierListLabel->End()) { - std::cout << "class : " << it.GetMeasurementVector()[0] << std::endl; + otbLogMacro(Debug, << "class : " << it.GetMeasurementVector()[0]); ++it; } for (unsigned int i = 0; i < testingFiles.size(); ++i) { - std::cout << "ground truth class : " << testingGTClasses[i] << std::endl; + otbLogMacro(Debug, << "ground truth class : " << testingGTClasses[i]); } //Compute confusion matrix @@ -236,9 +238,8 @@ int otbReduceSpectralResponseSVMClassifier(int argc, char * argv[]) confMatCalc->SetProducedLabels(classifierListLabel); confMatCalc->Compute(); - std::cout << std::endl; - std::cout << "Confusion matrix: " << std::endl << confMatCalc->GetConfusionMatrix() << std::endl << std::endl; - std::cout << "Kappa Index: " << std::endl << confMatCalc->GetKappaIndex() << std::endl << std::endl; + otbLogMacro(Info, << "Confusion matrix: " << std::endl << confMatCalc->GetConfusionMatrix()); + otbLogMacro(Info, << "Kappa Index: " << std::endl << confMatCalc->GetKappaIndex()); return EXIT_SUCCESS; } diff --git a/Modules/Radiometry/Simulation/test/otbSatelliteRSR.cxx b/Modules/Radiometry/Simulation/test/otbSatelliteRSR.cxx index 4fe40bf15f1301572a47391d9f85b45964c7f2a1..fb5b72baec1387016eef0cd863dd5b92dc592f78 100644 --- a/Modules/Radiometry/Simulation/test/otbSatelliteRSR.cxx +++ b/Modules/Radiometry/Simulation/test/otbSatelliteRSR.cxx @@ -44,13 +44,8 @@ int otbSatelliteRSR(int argc, char * argv[]) unsigned int NumBand = atoi(argv[4]); double lambda = atof(argv[3]); - std::cout << myResponse <<std::endl; - std::cout << "RSR("<<lambda<<","<< NumBand <<")= " << (*myResponse)(lambda, NumBand) << std::endl; -// for(unsigned int i=0; i<myResponse->GetRSR()[NumBand]->GetResponse().size(); ++i) -// { -// std::cout << "RSR("<<myResponse->GetRSR()[NumBand]->GetResponse()[i]->first<<","<< NumBand <<")= " << myResponse->GetRSR()[NumBand]->GetResponse()[i]->second << std::endl; -// } - + otbLogMacro(Debug, << myResponse); + otbLogMacro(Info, << "RSR("<<lambda<<","<< NumBand <<")= " << (*myResponse)(lambda, NumBand)); return EXIT_SUCCESS; } diff --git a/Modules/Radiometry/Simulation/test/otbSpectralResponse.cxx b/Modules/Radiometry/Simulation/test/otbSpectralResponse.cxx index cd1413d226f1b33a6e344ba2eb2a4b6a54402cd8..e0aaa4e94c446c310e18688dc977df90799f5b57 100644 --- a/Modules/Radiometry/Simulation/test/otbSpectralResponse.cxx +++ b/Modules/Radiometry/Simulation/test/otbSpectralResponse.cxx @@ -45,7 +45,7 @@ int otbSpectralResponse(int argc, char * argv[]) ImageType::Pointer image = ImageType::New(); myResponse->GetImage(image); - std::cout<<myResponse<<std::endl; - std::cout << "SpectResponse("<<lambda<<")= " << (*myResponse)(lambda) << std::endl; + otbLogMacro(Debug, << myResponse); + otbLogMacro(Info, << "SpectResponse("<<lambda<<")= " << (*myResponse)(lambda)); return EXIT_SUCCESS; } 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/Segmentation/Conversion/test/CMakeLists.txt b/Modules/Segmentation/Conversion/test/CMakeLists.txt index fa65b73233189ee8f31ceda1981f381a827f8e7a..363687e5c3cd789d24cdeaa9b26b594e2f56513d 100644 --- a/Modules/Segmentation/Conversion/test/CMakeLists.txt +++ b/Modules/Segmentation/Conversion/test/CMakeLists.txt @@ -128,6 +128,7 @@ otb_add_test(NAME bfTvVectorDataRasterizeFilterSHP COMMAND otbConversionTestDriv --compare-image 0.0001 ${BASELINE}/bfTvVectorDataRasterizeFilter_OutputSHP.tif ${TEMP}/bfTvVectorDataRasterizeFilter_OutputSHP.tif + --tolerance-ratio 0.01 otbVectorDataRasterizeFilter ${INPUTDATA}/QB_Toulouse_Ortho_XS.tif ${INPUTDATA}/Capitole-Shadows.shp diff --git a/Modules/ThirdParty/MPI/otb-module-init.cmake b/Modules/ThirdParty/MPI/otb-module-init.cmake index 6d4f3673db59cee99a7ac83d0e0ae6a0483276cd..39665d6ad48fe54fdc175fca64c45c0529dbe738 100644 --- a/Modules/ThirdParty/MPI/otb-module-init.cmake +++ b/Modules/ThirdParty/MPI/otb-module-init.cmake @@ -19,3 +19,5 @@ # find_package ( MPI REQUIRED ) + +set(OTB_MPIEXEC_OPT "" CACHE STRING "Additional options for mpiexec tests") 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) diff --git a/Modules/Wrappers/CommandLine/src/otbApplicationLauncherCommandLine.cxx b/Modules/Wrappers/CommandLine/src/otbApplicationLauncherCommandLine.cxx index 8cdca28487f797c1b6962edf031eeb623fea8c77..816e56d81fc7ea3f9c9f178198cc999eea1e6cb7 100644 --- a/Modules/Wrappers/CommandLine/src/otbApplicationLauncherCommandLine.cxx +++ b/Modules/Wrappers/CommandLine/src/otbApplicationLauncherCommandLine.cxx @@ -264,12 +264,6 @@ void ShowUsage(char* argv[]) int main(int argc, char* argv[]) { - #ifdef OTB_USE_MPI - otb::MPIConfig::Instance()->Init(argc,argv); - #endif - - otb::ConfigurationManager::InitOpenMPThreads(); - if (argc < 2) { ShowUsage(argv); @@ -299,15 +293,22 @@ int main(int argc, char* argv[]) } } - typedef otb::Wrapper::CommandLineLauncher LauncherType; - LauncherType::Pointer launcher = LauncherType::New(); - if (vexp.empty()) { ShowUsage(argv); return EXIT_FAILURE; } + #ifdef OTB_USE_MPI + if (std::find(vexp.begin(), vexp.end(), "-testenv") == vexp.end() ) + otb::MPIConfig::Instance()->Init(argc,argv); + #endif + + otb::ConfigurationManager::InitOpenMPThreads(); + + typedef otb::Wrapper::CommandLineLauncher LauncherType; + LauncherType::Pointer launcher = LauncherType::New(); + bool success = launcher->Load(vexp) && launcher->ExecuteAndWriteOutput(); // shutdown MPI after application finished diff --git a/Utilities/Doxygen/mcdoc.py b/Utilities/Doxygen/mcdoc.py index b380dd153f6754bab1ab9142b9b18951945a9d78..0242dcfbea1c0a6d15ea142891f96cec738c871c 100644 --- a/Utilities/Doxygen/mcdoc.py +++ b/Utilities/Doxygen/mcdoc.py @@ -70,7 +70,7 @@ def setGroup( fname, group ): def checkGroup( fname, group ): # sys.stderr.write("Checking"+ fname + "\n") - f = open( fname, "r" ) + f = open( fname, "r", encoding='utf-8') # load everything in memory fcontent = f.read() f.close()