diff --git a/.gitignore b/.gitignore index 7fb9b7d..a303274 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ [Bb]uild __pycache__ +data/result.tif +tmp +result +*.egg-info/ diff --git a/CMakeLists.txt b/CMakeLists.txt index ea02227..49fd89e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,32 +1,59 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.5) +project(libtriskele VERSION 1.0.0 LANGUAGES C CXX) -project(TreeBuilder) +# Add custom modules like FindTBB.cmake +list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake) -set(OUT_NAME "TreeBuilder") +############################################## +# Find dependencies -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -pthread -Wall -g") #-Wshadow") +find_package(Boost REQUIRED system chrono thread program_options date_time serialization filesystem unit_test_framework) +find_package(GDAL REQUIRED) +find_package(TBB REQUIRED) +find_package(Threads REQUIRED) +find_package(TinyXML) -set(TREEBUILDER_INCLUDES include) +############################################## +# Create triskele and set properties -file(GLOB_RECURSE TREEBUILDER_SOURCES src/*.cpp) +list(APPEND TRISKELE_SRC + "src/ArrayTree/triskeleArrayTreeBase.cpp" + "src/QuadTree/QuadTreeBuilder.cpp" + "src/IImage.cpp" + "src/Tree.cpp" + "src/triskeleBase.cpp" + "src/triskeleDebug.cpp") -find_package(OTB) +if (TinyXML_FOUND) + list(APPEND TRISKELE_SRC "src/XMLTree/XMLTreeBuilder.cpp") + message(STATUS "TinyXML found, XMLTreeBuilder will be compiled") +else() + message(WARNING "TinyXML not found, XMLTreeBuilder won't be compiled") +endif(TinyXML_FOUND) -find_package(OpenCV REQUIRED) # Petra +add_library(triskele + ${TRISKELE_SRC}) -if(OTB_FOUND) - include(${OTB_USE_FILE}) -else(OTB_FOUND) - message(FATAL_ERROR - "Cannot build OTB project without OTB. Please set OTB_DIR.") -endif(OTB_FOUND) +target_include_directories(triskele + PUBLIC + $ + $ + ${GDAL_INCLUDE_DIR}) -include_directories(${OTB_INCLUDES}) -include_directories(${TREEBUILDER_INCLUDES}) +target_link_libraries(triskele ${BOOST_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${GDAL_LIBRARY} ${TBB_LIBRARIES}) + # ${TinyXML_LIBRARY}) -set(TREEBUILDER_LIBS tinyxml opencv_ml opencv_core pthread boost_system boost_chrono boost_thread boost_program_options boost_date_time boost_serialization boost_filesystem boost_unit_test_framework gdal) +target_compile_definitions(triskele PUBLIC -DNDEBUG -DNO_OTB -DINTEL_TBB_THREAD) # -DBOOST_DISABLE_ASSERTS) -# Ajout de l'exec / lib -add_executable(${OUT_NAME} ${TREEBUILDER_SOURCES}) - -target_link_libraries(${OUT_NAME} ${TREEBUILDER_LIBS} ${OpenCV_LIBS} ${OTB_LIBRARIES}) +# Add Warnings for Unix and Windows, Optimization, MMD and debug for Unix +if(MSVC) + # Force to always compile with W4 + if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]") + string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") + endif() +elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) + # Update if necessary + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall -MMD -pthread -g") +endif() diff --git a/MakefileNoOTB b/MakefileNoOTB index 4cde640..30f3351 100644 --- a/MakefileNoOTB +++ b/MakefileNoOTB @@ -1,5 +1,6 @@ ## DIR ################################# SRC_DIR = . +TST_DIR = $(SRC_DIR)/test CPP_DIR = $(SRC_DIR)/src HPP_DIR = $(SRC_DIR)/include BLD_DIR = build @@ -8,6 +9,11 @@ LIB_DIR = $(BLD_DIR)/lib OBJ_DIR = $(BLD_DIR)/obj ## PRG ################################# + +TRSK_MOD = IImage triskeleArrayTreeBase Tree triskeleDebug TreeStats triskeleBase QuadTreeBuilder Option Selected +TRSK_OBJ = $(patsubst %, $(OBJ_DIR)/%.o, $(TRSK_MOD)) +TRSK_OBJ_XML = $(TRSK_OBJ) $(OBJ_DIR)/XMLTreeBuilder.o + APG_PRG = apGenerator APG_SRC = $(patsubst %, $(CPP_DIR)/%.cpp, $(APG_PRG)) APG_OUT = $(patsubst %, $(OUT_DIR)/%, $(APG_PRG)) @@ -20,64 +26,83 @@ PRF_PRG = PerfArrayTreeBuilder PRF_SRC = $(patsubst %, $(CPP_DIR)/%.cpp, $(PRF_PRG)) PRF_OUT = $(patsubst %, $(OUT_DIR)/%, $(PRF_PRG)) +TTH_MOD = TestDeal +TTH_PRG = TestThread +TTH_SRC = $(patsubst %, $(TST_DIR)/%.cpp, $(TTH_PRG)) +TTH_OBJ = $(patsubst %, $(OBJ_DIR)/%.o, $(TTH_MOD)) +TTH_OUT = $(patsubst %, $(OUT_DIR)/%, $(TTH_PRG)) + ## FLAGS ############################### -DFLAGS = -O2 -DNDEBUG -DNO_OTB -DINTEL_TBB_THREAD # -DBOOST_DISABLE_ASSERTS -#DFLAGS = -g -DENABLE_LOG -DNO_OTB # -DTHREAD_DISABLE -DENABLE_SMART_LOG +# fast and no control +#DFLAGS = -O2 -DNDEBUG -DNO_OTB -DINTEL_TBB_THREAD -DBOOST_DISABLE_ASSERTS +DFLAGS = -O2 -DNDEBUG -DNO_OTB -DBOOST_DISABLE_ASSERTS +# fast but control +#DFLAGS = -O2 -DNDEBUG -DNO_OTB -DINTEL_TBB_THREAD +# debug multi-threaded +#DFLAGS = -g -DENABLE_LOG -DNO_OTB +# debug one thread +#DFLAGS = -g -DENABLE_LOG -DNO_OTB -DTHREAD_DISABLE -DENABLE_SMART_LOG + IFLAGS = $(DFLAGS) -MMD -I$(HPP_DIR) -I/usr/include/gdal LFLAGS = -L$(LIB_DIR) -ltriskele -lstdc++ -lpthread -lboost_system -lboost_chrono -lboost_thread -lboost_program_options -lboost_date_time -lboost_serialization -lboost_filesystem -lboost_unit_test_framework -lgdal -ltbb CC = g++ ## RULES ############################### -$(OBJ_DIR)/%.o: $(CPP_DIR)/%.cpp +$(OBJ_DIR)/%.o: $(SRC_DIR)/*/%.cpp $(CC) $< $(IFLAGS) -cpp -c -o $@ -$(OBJ_DIR)/%.o: $(CPP_DIR)/*/%.cpp +$(OBJ_DIR)/%.o: $(SRC_DIR)/*/*/%.cpp $(CC) $< $(IFLAGS) -cpp -c -o $@ -$(OUT_DIR)/%: $(CPP_DIR)/%.cpp - $(CC) $(IFLAGS) $< -L$(LIB_DIR) $(LFLAGS) -cpp -o $@ -$(OUT_DIR)/%: $(CPP_DIR)/*/%.cpp +$(OUT_DIR)/%: $(SRC_DIR)/*/%.cpp $(CC) $(IFLAGS) $< -L$(LIB_DIR) $(LFLAGS) -cpp -o $@ ## ENTRIES ############################# -all: init libtriskele apGenerator test pref +all: init libtriskele apGenerator test perf -testA: all +test: testA testB testThread + +testThread: init $(TTH_OUT) + $(TTH_OUT) + +testA: init $(TST_OUT) $(TST_OUT) -testB: all +testB: init $(APG_OUT) $(APG_OUT) data/10m.tif data/result.tif --min-tree --max-tree --tos-tree --alpha-tree -A data/areaThresholds.txt -S data/sdThresholds.txt -M data/moiThresholds.txt # --debug -perfA: all - $(PRF_OUT) MIN 4 20 1000000 +perf: perfA + +perfA: init $(PRF_OUT) + $(PRF_OUT) MIN 32 20 1000000 init: mkdir -p $(OUT_DIR) $(OBJ_DIR) $(LIB_DIR) + clean: find . -type f '(' -name '#*' -o -name '*~' ')' -print -exec rm -f '{}' \; wipe: clean rm -rf $(OBJ_DIR) - rm -f $(APG_OUT) $(TST_OUT) $(LIB_DIR)/libtriskele.a + rm -f $(APG_OUT) $(TST_OUT) $(PRF_OUT) $(LIB_DIR)/libtriskele.a rm -f $(OUT_DIR)/*.d + -rmdir $(OUT_DIR) $(OBJ_DIR) $(LIB_DIR) $(BLD_DIR) libtriskele: $(LIB_DIR)/libtriskele.a $(APG_OUT): $(APG_SRC) $(LIB_DIR)/libtriskele.a $(TST_OUT): $(TST_SRC) $(LIB_DIR)/libtriskele.a $(PRF_OUT): $(PRF_SRC) $(LIB_DIR)/libtriskele.a +$(TTH_OUT): $(TTH_SRC) $(TTH_OBJ) $(LIB_DIR)/libtriskele.a + $(CC) $(IFLAGS) $< $(TTH_OBJ) -L$(LIB_DIR) $(LFLAGS) -cpp -o $@ -apGenerator: $(APG_OUT) -test: init $(TST_OUT) -pref: init $(PRF_OUT) +apGenerator: init $(APG_OUT) ## DEPENDS ############################# ALL_OUT = $(APG_OUT) -ALL_OBJ = $(OBJ_DIR)/IImage.o $(OBJ_DIR)/triskeleArrayTreeBase.o $(OBJ_DIR)/Tree.o $(OBJ_DIR)/triskeleDebug.o $(OBJ_DIR)/TreeStats.o $(OBJ_DIR)/triskeleBase.o $(OBJ_DIR)/QuadTreeBuilder.o $(OBJ_DIR)/Option.o $(OBJ_DIR)/Selected.o +ALL_OBJ = $(TRSK_OBJ) -ALL_OBJ_XML = $(OBJ_DIR)/IImage.o $(OBJ_DIR)/triskeleArrayTreeBase.o $(OBJ_DIR)/Tree.o $(OBJ_DIR)/triskeleDebug.o $(OBJ_DIR)/TreeStats.o $(OBJ_DIR)/triskeleBase.o $(OBJ_DIR)/QuadTreeBuilder.o $(OBJ_DIR)/XMLTreeBuilder.o $(OBJ_DIR)/Option.o $(OBJ_DIR)/Selected.o - -DEPENDS = ${ALL_OUT:=.d} ${ALL_OBJ:.o=.d} +DEPENDS = ${ALL_OUT:=.d} ${ALL_OBJ:.o=.d} ${TTH_OBJ:.o=.d} -include ${DEPENDS} $(LIB_DIR)/libtriskele.a: $(ALL_OBJ) diff --git a/cmake/FindTBB.cmake b/cmake/FindTBB.cmake new file mode 100644 index 0000000..0a1a5bb --- /dev/null +++ b/cmake/FindTBB.cmake @@ -0,0 +1,303 @@ +# The MIT License (MIT) +# +# Copyright (c) 2015 Justus Calvin +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# +# FindTBB +# ------- +# +# Find TBB include directories and libraries. +# +# Usage: +# +# find_package(TBB [major[.minor]] [EXACT] +# [QUIET] [REQUIRED] +# [[COMPONENTS] [components...]] +# [OPTIONAL_COMPONENTS components...]) +# +# where the allowed components are tbbmalloc and tbb_preview. Users may modify +# the behavior of this module with the following variables: +# +# * TBB_ROOT_DIR - The base directory the of TBB installation. +# * TBB_INCLUDE_DIR - The directory that contains the TBB headers files. +# * TBB_LIBRARY - The directory that contains the TBB library files. +# * TBB__LIBRARY - The path of the TBB the corresponding TBB library. +# These libraries, if specified, override the +# corresponding library search results, where +# may be tbb, tbb_debug, tbbmalloc, tbbmalloc_debug, +# tbb_preview, or tbb_preview_debug. +# * TBB_USE_DEBUG_BUILD - The debug version of tbb libraries, if present, will +# be used instead of the release version. +# +# Users may modify the behavior of this module with the following environment +# variables: +# +# * TBB_INSTALL_DIR +# * TBBROOT +# * LIBRARY_PATH +# +# This module will set the following variables: +# +# * TBB_FOUND - Set to false, or undefined, if we haven’t found, or +# don’t want to use TBB. +# * TBB__FOUND - If False, optional part of TBB sytem is +# not available. +# * TBB_VERSION - The full version string +# * TBB_VERSION_MAJOR - The major version +# * TBB_VERSION_MINOR - The minor version +# * TBB_INTERFACE_VERSION - The interface version number defined in +# tbb/tbb_stddef.h. +# * TBB__LIBRARY_RELEASE - The path of the TBB release version of +# , where may be tbb, tbb_debug, +# tbbmalloc, tbbmalloc_debug, tbb_preview, or +# tbb_preview_debug. +# * TBB__LIBRARY_DEGUG - The path of the TBB release version of +# , where may be tbb, tbb_debug, +# tbbmalloc, tbbmalloc_debug, tbb_preview, or +# tbb_preview_debug. +# +# The following varibles should be used to build and link with TBB: +# +# * TBB_INCLUDE_DIRS - The include directory for TBB. +# * TBB_LIBRARIES - The libraries to link against to use TBB. +# * TBB_LIBRARIES_RELEASE - The release libraries to link against to use TBB. +# * TBB_LIBRARIES_DEBUG - The debug libraries to link against to use TBB. +# * TBB_DEFINITIONS - Definitions to use when compiling code that uses +# TBB. +# * TBB_DEFINITIONS_RELEASE - Definitions to use when compiling release code that +# uses TBB. +# * TBB_DEFINITIONS_DEBUG - Definitions to use when compiling debug code that +# uses TBB. +# +# This module will also create the "tbb" target that may be used when building +# executables and libraries. + +include(FindPackageHandleStandardArgs) + +if(NOT TBB_FOUND) + + ################################## + # Check the build type + ################################## + + if(NOT DEFINED TBB_USE_DEBUG_BUILD) + if(CMAKE_BUILD_TYPE MATCHES "(Debug|DEBUG|debug|RelWithDebInfo|RELWITHDEBINFO|relwithdebinfo)") + set(TBB_BUILD_TYPE DEBUG) + else() + set(TBB_BUILD_TYPE RELEASE) + endif() + elseif(TBB_USE_DEBUG_BUILD) + set(TBB_BUILD_TYPE DEBUG) + else() + set(TBB_BUILD_TYPE RELEASE) + endif() + + ################################## + # Set the TBB search directories + ################################## + + # Define search paths based on user input and environment variables + set(TBB_SEARCH_DIR ${TBB_ROOT_DIR} $ENV{TBB_INSTALL_DIR} $ENV{TBBROOT}) + + # Define the search directories based on the current platform + if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + set(TBB_DEFAULT_SEARCH_DIR "C:/Program Files/Intel/TBB" + "C:/Program Files (x86)/Intel/TBB") + + # Set the target architecture + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(TBB_ARCHITECTURE "intel64") + else() + set(TBB_ARCHITECTURE "ia32") + endif() + + # Set the TBB search library path search suffix based on the version of VC + if(WINDOWS_STORE) + set(TBB_LIB_PATH_SUFFIX "lib/${TBB_ARCHITECTURE}/vc11_ui") + elseif(MSVC14) + set(TBB_LIB_PATH_SUFFIX "lib/${TBB_ARCHITECTURE}/vc14") + elseif(MSVC12) + set(TBB_LIB_PATH_SUFFIX "lib/${TBB_ARCHITECTURE}/vc12") + elseif(MSVC11) + set(TBB_LIB_PATH_SUFFIX "lib/${TBB_ARCHITECTURE}/vc11") + elseif(MSVC10) + set(TBB_LIB_PATH_SUFFIX "lib/${TBB_ARCHITECTURE}/vc10") + endif() + + # Add the library path search suffix for the VC independent version of TBB + list(APPEND TBB_LIB_PATH_SUFFIX "lib/${TBB_ARCHITECTURE}/vc_mt") + + elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + # OS X + set(TBB_DEFAULT_SEARCH_DIR "/opt/intel/tbb") + + # TODO: Check to see which C++ library is being used by the compiler. + if(NOT ${CMAKE_SYSTEM_VERSION} VERSION_LESS 13.0) + # The default C++ library on OS X 10.9 and later is libc++ + set(TBB_LIB_PATH_SUFFIX "lib/libc++" "lib") + else() + set(TBB_LIB_PATH_SUFFIX "lib") + endif() + elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") + # Linux + set(TBB_DEFAULT_SEARCH_DIR "/opt/intel/tbb") + + # TODO: Check compiler version to see the suffix should be /gcc4.1 or + # /gcc4.1. For now, assume that the compiler is more recent than + # gcc 4.4.x or later. + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") + set(TBB_LIB_PATH_SUFFIX "lib/intel64/gcc4.4") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^i.86$") + set(TBB_LIB_PATH_SUFFIX "lib/ia32/gcc4.4") + endif() + endif() + + ################################## + # Find the TBB include dir + ################################## + + find_path(TBB_INCLUDE_DIRS tbb/tbb.h + HINTS ${TBB_INCLUDE_DIR} ${TBB_SEARCH_DIR} + PATHS ${TBB_DEFAULT_SEARCH_DIR} + PATH_SUFFIXES include) + + ################################## + # Set version strings + ################################## + + if(TBB_INCLUDE_DIRS) + file(READ "${TBB_INCLUDE_DIRS}/tbb/tbb_stddef.h" _tbb_version_file) + string(REGEX REPLACE ".*#define TBB_VERSION_MAJOR ([0-9]+).*" "\\1" + TBB_VERSION_MAJOR "${_tbb_version_file}") + string(REGEX REPLACE ".*#define TBB_VERSION_MINOR ([0-9]+).*" "\\1" + TBB_VERSION_MINOR "${_tbb_version_file}") + string(REGEX REPLACE ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" + TBB_INTERFACE_VERSION "${_tbb_version_file}") + set(TBB_VERSION "${TBB_VERSION_MAJOR}.${TBB_VERSION_MINOR}") + endif() + + ################################## + # Find TBB components + ################################## + + if(TBB_VERSION VERSION_LESS 4.3) + set(TBB_SEARCH_COMPOMPONENTS tbb_preview tbbmalloc tbb) + else() + set(TBB_SEARCH_COMPOMPONENTS tbb_preview tbbmalloc_proxy tbbmalloc tbb) + endif() + + # Find each component + foreach(_comp ${TBB_SEARCH_COMPOMPONENTS}) + if(";${TBB_FIND_COMPONENTS};tbb;" MATCHES ";${_comp};") + + # Search for the libraries + find_library(TBB_${_comp}_LIBRARY_RELEASE ${_comp} + HINTS ${TBB_LIBRARY} ${TBB_SEARCH_DIR} + PATHS ${TBB_DEFAULT_SEARCH_DIR} ENV LIBRARY_PATH + PATH_SUFFIXES ${TBB_LIB_PATH_SUFFIX}) + + find_library(TBB_${_comp}_LIBRARY_DEBUG ${_comp}_debug + HINTS ${TBB_LIBRARY} ${TBB_SEARCH_DIR} + PATHS ${TBB_DEFAULT_SEARCH_DIR} ENV LIBRARY_PATH + PATH_SUFFIXES ${TBB_LIB_PATH_SUFFIX}) + + if(TBB_${_comp}_LIBRARY_DEBUG) + list(APPEND TBB_LIBRARIES_DEBUG "${TBB_${_comp}_LIBRARY_DEBUG}") + endif() + if(TBB_${_comp}_LIBRARY_RELEASE) + list(APPEND TBB_LIBRARIES_RELEASE "${TBB_${_comp}_LIBRARY_RELEASE}") + endif() + if(TBB_${_comp}_LIBRARY_${TBB_BUILD_TYPE} AND NOT TBB_${_comp}_LIBRARY) + set(TBB_${_comp}_LIBRARY "${TBB_${_comp}_LIBRARY_${TBB_BUILD_TYPE}}") + endif() + + if(TBB_${_comp}_LIBRARY AND EXISTS "${TBB_${_comp}_LIBRARY}") + set(TBB_${_comp}_FOUND TRUE) + else() + set(TBB_${_comp}_FOUND FALSE) + endif() + + # Mark internal variables as advanced + mark_as_advanced(TBB_${_comp}_LIBRARY_RELEASE) + mark_as_advanced(TBB_${_comp}_LIBRARY_DEBUG) + mark_as_advanced(TBB_${_comp}_LIBRARY) + + endif() + endforeach() + + ################################## + # Set compile flags and libraries + ################################## + + set(TBB_DEFINITIONS_RELEASE "") + set(TBB_DEFINITIONS_DEBUG "-DTBB_USE_DEBUG=1") + + if(TBB_LIBRARIES_${TBB_BUILD_TYPE}) + set(TBB_DEFINITIONS "${TBB_DEFINITIONS_${TBB_BUILD_TYPE}}") + set(TBB_LIBRARIES "${TBB_LIBRARIES_${TBB_BUILD_TYPE}}") + elseif(TBB_LIBRARIES_RELEASE) + set(TBB_DEFINITIONS "${TBB_DEFINITIONS_RELEASE}") + set(TBB_LIBRARIES "${TBB_LIBRARIES_RELEASE}") + elseif(TBB_LIBRARIES_DEBUG) + set(TBB_DEFINITIONS "${TBB_DEFINITIONS_DEBUG}") + set(TBB_LIBRARIES "${TBB_LIBRARIES_DEBUG}") + endif() + + find_package_handle_standard_args(TBB + REQUIRED_VARS TBB_INCLUDE_DIRS TBB_LIBRARIES + HANDLE_COMPONENTS + VERSION_VAR TBB_VERSION) + + ################################## + # Create targets + ################################## + + if(NOT CMAKE_VERSION VERSION_LESS 3.0 AND TBB_FOUND) + add_library(tbb SHARED IMPORTED) + set_target_properties(tbb PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${TBB_INCLUDE_DIRS} + IMPORTED_LOCATION ${TBB_LIBRARIES}) + if(TBB_LIBRARIES_RELEASE AND TBB_LIBRARIES_DEBUG) + set_target_properties(tbb PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "$<$,$>:TBB_USE_DEBUG=1>" + IMPORTED_LOCATION_DEBUG ${TBB_LIBRARIES_DEBUG} + IMPORTED_LOCATION_RELWITHDEBINFO ${TBB_LIBRARIES_DEBUG} + IMPORTED_LOCATION_RELEASE ${TBB_LIBRARIES_RELEASE} + IMPORTED_LOCATION_MINSIZEREL ${TBB_LIBRARIES_RELEASE} + ) + elseif(TBB_LIBRARIES_RELEASE) + set_target_properties(tbb PROPERTIES IMPORTED_LOCATION ${TBB_LIBRARIES_RELEASE}) + else() + set_target_properties(tbb PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "${TBB_DEFINITIONS_DEBUG}" + IMPORTED_LOCATION ${TBB_LIBRARIES_DEBUG} + ) + endif() + endif() + + mark_as_advanced(TBB_INCLUDE_DIRS TBB_LIBRARIES) + + unset(TBB_ARCHITECTURE) + unset(TBB_BUILD_TYPE) + unset(TBB_LIB_PATH_SUFFIX) + unset(TBB_DEFAULT_SEARCH_DIR) + +endif() diff --git a/cmake/FindTinyXML.cmake b/cmake/FindTinyXML.cmake new file mode 100644 index 0000000..aabb323 --- /dev/null +++ b/cmake/FindTinyXML.cmake @@ -0,0 +1,74 @@ +################################################################################################## +# +# CMake script for finding TinyXML. +# +# Input variables: +# +# - TinyXML_ROOT_DIR (optional): When specified, header files and libraries will be searched for in +# ${TinyXML_ROOT_DIR}/include +# ${TinyXML_ROOT_DIR}/libs +# respectively, and the default CMake search order will be ignored. When unspecified, the default +# CMake search order is used. +# This variable can be specified either as a CMake or environment variable. If both are set, +# preference is given to the CMake variable. +# Use this variable for finding packages installed in a nonstandard location, or for enforcing +# that one of multiple package installations is picked up. +# +# +# Cache variables (not intended to be used in CMakeLists.txt files) +# +# - TinyXML_INCLUDE_DIR: Absolute path to package headers. +# - TinyXML_LIBRARY: Absolute path to library. +# +# +# Output variables: +# +# - TinyXML_FOUND: Boolean that indicates if the package was found +# - TinyXML_INCLUDE_DIRS: Paths to the necessary header files +# - TinyXML_LIBRARIES: Package libraries +# +# +# Example usage: +# +# find_package(TinyXML) +# if(NOT TinyXML_FOUND) +# # Error handling +# endif() +# ... +# include_directories(${TinyXML_INCLUDE_DIRS} ...) +# ... +# target_link_libraries(my_target ${TinyXML_LIBRARIES}) +# +################################################################################################## + +# Get package location hint from environment variable (if any) +if(NOT TinyXML_ROOT_DIR AND DEFINED ENV{TinyXML_ROOT_DIR}) + set(TinyXML_ROOT_DIR "$ENV{TinyXML_ROOT_DIR}" CACHE PATH + "TinyXML base directory location (optional, used for nonstandard installation paths)") +endif() + +# Search path for nonstandard package locations +if(TinyXML_ROOT_DIR) + set(TinyXML_INCLUDE_PATH PATHS "${TinyXML_ROOT_DIR}/include" NO_DEFAULT_PATH) + set(TinyXML_LIBRARY_PATH PATHS "${TinyXML_ROOT_DIR}/lib" NO_DEFAULT_PATH) +endif() + +# Find headers and libraries +find_path(TinyXML_INCLUDE_DIR NAMES tinyxml.h PATH_SUFFIXES "tinyxml" ${TinyXML_INCLUDE_PATH}) +find_library(TinyXML_LIBRARY NAMES tinyxml PATH_SUFFIXES "tinyxml" ${TinyXML_LIBRARY_PATH}) + +mark_as_advanced(TinyXML_INCLUDE_DIR + TinyXML_LIBRARY) + +# Output variables generation +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(TinyXML DEFAULT_MSG TinyXML_LIBRARY + TinyXML_INCLUDE_DIR) + +set(TinyXML_FOUND ${TINYXML_FOUND}) # Enforce case-correctness: Set appropriately cased variable... +unset(TINYXML_FOUND) # ...and unset uppercase variable generated by find_package_handle_standard_args + +if(TinyXML_FOUND) + set(TinyXML_INCLUDE_DIRS ${TinyXML_INCLUDE_DIR}) + set(TinyXML_LIBRARIES ${TinyXML_LIBRARY}) +endif() diff --git a/data/10m.tif b/data/10m.tif deleted file mode 100755 index e5264cb..0000000 Binary files a/data/10m.tif and /dev/null differ diff --git a/data/areaThresholds.txt b/data/areaThresholds.txt old mode 100755 new mode 100644 diff --git a/data/levelThresholds.txt b/data/levelThresholds.txt new file mode 100644 index 0000000..d2864ab --- /dev/null +++ b/data/levelThresholds.txt @@ -0,0 +1,8 @@ +0 +1 +5 +10 +25 +50 +100 +200 diff --git a/data/moiThresholds.txt b/data/moiThresholds.txt old mode 100755 new mode 100644 diff --git a/data/sdThresholds.txt b/data/sdThresholds.txt old mode 100755 new mode 100644 diff --git a/documentation/GitInfos.org b/documentation/GitInfos.org new file mode 100644 index 0000000..c730b26 --- /dev/null +++ b/documentation/GitInfos.org @@ -0,0 +1,81 @@ +* Git de Triskele + Note aux développeurs + +** La TODO list + - vérifier coupure (avec sens de la monotonie) + - faire coupures suivant (A>, W<>, SD>, MOI>) + - sort W thresholds + - faire les features-profiles (L, mean, SD, A, MOI) + - vérifier production windows + - refaire le tableau des exemples de traces (./result/BuildSteps.ods) + - vérifier min et max apla tos + - faire un omega-tree + - faire des tests de perf pour algo parallèle + +** Fonctions intégré depuis la dernière version + - copier les valeurs de géolocalisation (de input vers output) + + +** Infos concernant le pattern de git de Triskele + +Triskele suit partiellement le [[https://nvie.com/posts/a-successful-git-branching-model/][modèle gitflow]] pour son développement en conservant certaines branches : +- la master qui contient les versions stables du logiciel +- la develop qui découle de la master sur laquelle on corrige les bugs / on crée de nouvelles features +- les features, ajoutant une ou plusieurs fonctionnalités et qui découlent chacune de dévelop + +** Commandes utiles + +- récupération du git + $ git clone git://git.renater.fr/triskele.git + +- Se déplacer sur une branche + $ git checkout nomDeBranche + +- Créer une branche locale et s'y placer de suite + $ git checkout -b nomDeBranche nomDeBrancheParent + # Exemple, création d'une feature pour les oméga-tree + $ git checkout -b omega_feature develop + +- Synchroniser la branche créée avec le dépot distant + $ git push orgin nomDeBranche + # Exemple avec la feature ci-dessus + $ git push origin omega_feature + +- Annuler les modifications effectuées depuis la dernière synchronisation + $ git checkout -- [nomDuFichier] + +- Afficher toutes les branches existantes (locales ou distantes) + $ git branch -a + +- Supprimer une branche sur un dépot local / sur un dépot distant + # Pour une branche locale + $ git branch -d nomDeBranche + + # Pour la supprimer sur le dépot distant + $ git push origin --delete nomDeBranch + +- Fusionner les modifications + # Il faut synchroniser la branche développement + $ git pull + $ git commit -a + $ git push + # Il faut sélectionner la branche master + $ git checkout master + # Il faut fusionner + $ git merge develop + # editer les fichiers en confli + $ git commit -a + $ git push + # Puis mettre à jour la branch develop si conflit + $ git checkout develop + $ git merge master + # Il est possible d'annuler le traitement en cas de conflit + $ git merge --abort + +- Etiquetage de version + # Choisir la branch master + git checkout master + # Donner un nom majeru.mineur.AAMMJJ + git tag 1.0.180610 + # valider sur le serveur + git push --tags diff --git a/include/Appli/Option.hpp b/include/Appli/Option.hpp index 58bcbfa..5ba1697 100644 --- a/include/Appli/Option.hpp +++ b/include/Appli/Option.hpp @@ -6,14 +6,17 @@ #include #include "triskeleBase.hpp" +#include "ArrayTree/GraphWalker.hpp" #include "IImage.hpp" #include "Appli/Selected.hpp" namespace otb { namespace triskele { using namespace ::triskele; + using namespace otb::triskele::arrayTree; // ======================================== + enum FeatureType { AP, MEAN, SD, AREA, MOI }; class Option { public: @@ -25,11 +28,12 @@ namespace otb { Selected selectedBand; size_t countingSortCeil = 2; vector areaThresholds; - vector sdThresholds, moiThresholds; + vector levelThresholds, sdThresholds, moiThresholds; unsigned int coreCount = boost::thread::hardware_concurrency (); bool maxTreeFlag = false, minTreeFlag = false, tosTreeFlag = false, alphaTreeFlag = false; - bool oneBand = false; - + bool border = false, oneBand = false; + Connectivity connectivity = Connectivity::C4; + FeatureType featureType = FeatureType::AP; Option (); Option (int argc, char** argv); diff --git a/include/ArrayTree/ArrayTreeBuilder.tpp b/include/ArrayTree/ArrayTreeBuilder.tpp index 892f537..17d72a9 100644 --- a/include/ArrayTree/ArrayTreeBuilder.tpp +++ b/include/ArrayTree/ArrayTreeBuilder.tpp @@ -43,10 +43,10 @@ ArrayTreeBuilder::buildTree (Tree &tree, WeightAttributes (raster.getPixels (), raster.getSize ())); + buildTree (tree, MaxWeight (raster.getPixels (), raster.getSize ())); break; case MAX: - buildTree (tree, MaxWeight (raster.getPixels (), raster.getSize ())); + buildTree (tree, MinWeight (raster.getPixels (), raster.getSize ())); break; case TOS: buildTree (tree, MedianWeight (raster.getPixels (), graphWalker)); @@ -84,10 +84,10 @@ ArrayTreeBuilder::setAttributProfiles (AttributeProfiles (raster.getPixels (), raster.getSize ())); + setAttributProfiles (attributeProfiles, MaxWeight (raster.getPixels (), raster.getSize ())); break; case MAX: - setAttributProfiles (attributeProfiles, MaxWeight (raster.getPixels (), raster.getSize ())); + setAttributProfiles (attributeProfiles, MinWeight (raster.getPixels (), raster.getSize ())); break; case TOS: setAttributProfiles (attributeProfiles, MedianWeight (raster.getPixels (), graphWalker)); @@ -143,7 +143,6 @@ ArrayTreeBuilder::buildTree (Tree &tree, const WeightFunct &wei << tree.printTree (2*leafCount-1)); // merge sub-tree auto startMerge = high_resolution_clock::now (); - DimImg compCount = compTops [0]; DimImg *topC = NULL; DimImg compBase = vertexMaxBounds[tileCount]; if (boundCount) { @@ -186,6 +185,53 @@ ArrayTreeBuilder::buildTree (Tree &tree, const WeightFunct &wei }); } + // SMART_LOG ("compWeights:" << endl + // << printMap (compWeights, size, 0) << endl << endl + // << tree.printTree (2*leafCount-1)); + auto startForest = high_resolution_clock::now (); + if (graphWalker.border.exists ()) { + // merge comp forest + DimImg rootId = 0; + for (unsigned int tileId = 0; tileId < tileCount; tileId++) + if (compTops [tileId] != compBases [tileId]) { + rootId = findRoot (compTops [tileId] - 1); + break; + } + + LOG ("merge forest: " << printComp (rootId)); + for (unsigned int tileId = 0; tileId < tileCount; ++tileId) + for (DimImg compId = compBases [tileId]; compId < compTops [tileId]; ++compId) + if (compParents [compId] == DimImg_MAX) { + connectComp (compId, rootId, weightFunct); + rootId = findRoot (rootId); + LOG ("merge top: compId:" << printComp (compId) << " nr:" << printComp (rootId)); + } + + // merge pixels forest + vector lonelyPixelsCount (tileCount, 0); + vector topsWeight (tileCount, compWeights [rootId]); + dealThreadRange (tileCount, coreCount, [this, &tiles, &rootId, &weightFunct, &lonelyPixelsCount, &topsWeight] (const DimImg &tileId) { + WeightT &topWeight (topsWeight [tileId]); + DimImg &lonelyPixelCount (lonelyPixelsCount [tileId]); + graphWalker.forEachVertexIdx (tiles [tileId], [this, &rootId, &lonelyPixelCount, &topWeight, &weightFunct] (const DimImg &leafId) { + if (leafParents [leafId] == DimImg_MAX) { + WeightT pixelWeight (weightFunct.getWeight (leafId)); + leafParents [leafId] = rootId; + lonelyPixelCount++; + if (weightFunct.isWeightInf (topWeight, pixelWeight)) + topWeight = pixelWeight; + } + }); + }); + for (unsigned int tileId = 0; tileId < tileCount; ++tileId) { + childCount [rootId] += lonelyPixelsCount [tileId]; + if (weightFunct.isWeightInf (compWeights [rootId], topsWeight [tileId])) + compWeights [rootId] = topsWeight [tileId]; + // XXX on ne reprend pas la fraterie inférieur car plus d'appel à findMultiChildrenTop + LOG ("merge pixels: tileId:" << tileId << " lonely:" << lonelyPixelsCount [tileId] << " root:" << printComp (rootId)); + } + } + SMART_LOG ("compWeights:" << endl << printMap (compWeights, size, 0) << endl << endl << tree.printTree (2*leafCount-1)); @@ -196,7 +242,7 @@ ArrayTreeBuilder::buildTree (Tree &tree, const WeightFunct &wei SMART_LOG ("reuse leaders:" << endl << printMap (newCompId, size, 0) << endl << endl); - compCount = updateNewId (compBases, compTops, weightFunct); + DimImg maxTop = updateNewId (compBases, compTops, weightFunct); SMART_LOG ("updateNewId:" << endl << printMap (newCompId, size, 0) << endl << endl); @@ -207,22 +253,23 @@ ArrayTreeBuilder::buildTree (Tree &tree, const WeightFunct &wei << printMap (newCompId, size, 0) << endl << endl); leaders.free (); - while (compCount > 1 && childCount[compCount-1] == 1) { - --compCount; - compParents [compCount-1] = DimImg_MAX; - SMART_LOG ("reduce lonely root:" << printComp (compCount) << endl); + while (maxTop > 1 && childCount[maxTop-1] == 1) { + --maxTop; + compParents [maxTop-1] = DimImg_MAX; + SMART_LOG ("reduce lonely root:" << printComp (maxTop) << endl); } - setNodeCount (tree, leafCount+compCount); + setNodeCount (tree, leafCount+maxTop); LOG ("nodeCount:" << tree.getNodeCount()); - // DimEdge root = compCount-1; - // compParents[root] = root; + // DimEdge rootId = maxTop-1; + // compParents[rootId] = rootId; SMART_LOG ("compWeights:" << endl << printMap (compWeights, size, 0) << endl << endl); auto end = high_resolution_clock::now (); globalTreeStats.addTime (buildSetupStats, duration_cast > (startParent-start).count ()); globalTreeStats.addTime (buildParentsStats, duration_cast > (startMerge-startParent).count ()); - globalTreeStats.addTime (buildMergeStats, duration_cast > (startIndex-startMerge).count ()); + globalTreeStats.addTime (buildMergeStats, duration_cast > (startForest-startMerge).count ()); + globalTreeStats.addTime (buildForestStats, duration_cast > (startIndex-startForest).count ()); globalTreeStats.addTime (buildIndexStats, duration_cast > (startCompress-startIndex).count ()); globalTreeStats.addTime (buildCompressStats, duration_cast > (end-startCompress).count ()); } @@ -275,8 +322,12 @@ ArrayTreeBuilder::buildParents (Edge *edges, const Wei SMART_LOG ("pa:" << pa << " pb:" << pb << " la:" << la << " lb:" << lb); SMART_LOG ("ra:" << printComp (ra) << " rb:" << printComp (rb)); - if (la == lb) + if (la == lb) { + leaders.link (pa, la); + leaders.link (pb, la); + SMART_LOG ("la=lb"); continue; + } if (ra == DimImg_MAX) { swap (la, lb); swap (ra, rb); @@ -299,9 +350,9 @@ ArrayTreeBuilder::buildParents (Edge *edges, const Wei leader = lb; } } else if (ra == rb) { - // XXX + SMART_LOG ("ra=rb **** XXXX ****"); BOOST_ASSERT (false); - continue; + leader = la; } else if (compWeights[ra] == compWeights [rb]) { // ra.weight = rb.weight // XXX ?= curEdge.weight if (childCount [ra] < childCount [rb]) { @@ -327,7 +378,7 @@ ArrayTreeBuilder::buildParents (Edge *edges, const Wei leaders.link (pa, leader); leaders.link (pb, leader); - SMART_LOG (" leader:" << leader << " ra:" << printComp (ra) << " rb:" << printComp (rb)); + SMART_LOG (" leader:" << leader << " ra:" << printComp (ra) << " rb:" << printComp (rb) << " nr:" << printComp (findRoot (leafParents [la]))); } SMART_LOG ("topParent:" << topParent); @@ -368,11 +419,13 @@ ArrayTreeBuilder::connectLeaf (DimImg a, DimImg b, const Weight SMART_LOG ("same parents for: " << a << ", " << b); return; } - if (parA == DimImg_MAX) { + if (parB == DimImg_MAX) { + // XXX 20180776 bug fixed parA => parB swap (a, b); swap (parA, parB); SMART_LOG ("swap: " << printComp (parA) << " " << printComp (parB)); } + // XXX parB =? DimImg_MAX if ((parA == DimImg_MAX || weightFunct.isWeightInf (weight, compWeights[parA])) && weightFunct.isWeightInf (weight, compWeights[parB])) { // upW1 & upW2 : upper @@ -431,7 +484,7 @@ ArrayTreeBuilder::connectLeaf (DimImg a, DimImg b, const Weight unlinkParent (parA); ++childCount[parB]; leafParents[a] = parB; - SMART_LOG ("parA: " << printComp (parA) << " parB: " << printComp (parB)); + SMART_LOG ("link a: " << a << " parB: " << printComp (parB)); } // eqW0 | eqW1 | eqW2 SMART_LOG ("eqW0 | eqW1 | eqW2: connect"); @@ -455,8 +508,7 @@ ArrayTreeBuilder::connect3Comp (DimImg newComp, DimImg topA, Di swap (topA, topB); BOOST_ASSERT (findTopComp (topB, weightFunct) == topB); BOOST_ASSERT (weightFunct.isWeightInf (compWeights[newComp], compWeights[topB])); - compParents[newComp] = topB; - ++childCount[topB]; + addChild (topB, compParents[newComp]); SMART_LOG ("topB: " << printComp (topB)); connectComp (topA, topB, weightFunct); } diff --git a/include/ArrayTree/Border.hpp b/include/ArrayTree/Border.hpp deleted file mode 100644 index c164d36..0000000 --- a/include/ArrayTree/Border.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef _OTB_TRISKELE_ARRAY_TREE_BORDER_HPP -#define _OTB_TRISKELE_ARRAY_TREE_BORDER_HPP - -#include - -#include "triskeleBase.hpp" -#include "triskeleArrayTreeBase.hpp" - -namespace otb { - namespace triskele { - namespace arrayTree { - - /** Border */ - class Border { - public: - /*! Retourne le nombre de pixels à l'aide de la taille */ - static inline DimImg getPixelsCount (const Size &size); - - /*! Retourne la taille que doit faire le tableau simplifié */ - static inline DimImg getMapLength (DimImg pixelsCount); - - /*! Vérifie si un index est sur la map ou une bordure, en se basant sur le bit de l'index idx de la map */ - inline bool isBorder (DimImg idx) const; - - /*! Vérifie si un point est sur la map ou une bordure en appelant la méthode précédente après avoir converti le point en index */ - inline bool isBorder (const Point &p) const; - - /*! Supprime toutes les occurences de bordure à l'index idx */ - inline void clearBorder (DimImg idx); - - /*! Supprime toutes les occurences de bordure en appelant la méthode précédente après avoir converti le point en index */ - inline void clearBorder (const Point &p); - - /*! Rajoute une occurence de bordure à l'index indiqué */ - inline void setBorder (DimImg idx); - - /*! Rajoute une occurence de bordure en appelant la méthode précédente après avoir converti le point en index */ - inline void setBorder (const Point &p); - - /*! Construit par défault sans aucune bordure */ - inline Border (); - - /*! Construit Border, les valeurs de map dépendent de defaultVal */ - inline Border (const Size &size, bool defaultVal); - inline Border (const Border &border, const Rect &tile); - inline ~Border (); - - inline void reset (bool defaultVal); - - inline const Size &getSize () const; - - /*! Compte le nombre de pixels considérés comme de la bordure */ - inline DimImg borderCount (); - - private: - /*! Nombre de pixels dans l'image */ - DimImg pixelsCount; - - /*! Taille du tableau "simplifié" des pixels */ - DimImg mapLength; - - /*! Dimensions de l'image */ - Size size; - - /*! Tableau "simplifié" des pixels */ - vector map; - - bool defaultVal; - - inline void createMap (); - - friend inline ostream &operator << (ostream &out, const Border &border); - }; - -#include "Border.tpp" - - } //arrayTree - } // triskele -} // otb - -#endif // _OTB_TRISKELE_ARRAY_TREE_BORDER_HPP diff --git a/include/ArrayTree/Weight.hpp b/include/ArrayTree/Weight.hpp index 29b402a..a3c4cf5 100644 --- a/include/ArrayTree/Weight.hpp +++ b/include/ArrayTree/Weight.hpp @@ -44,12 +44,13 @@ namespace otb { const DimImg &minVal, const DimImg &maxVal) const; }; + // ======================================== /*! Structure intégrant la façon dont est géré un poids pour un MinTree */ template struct MinWeight : public WeightBase { typedef WeightBase WB; inline bool getDecr () const; - static inline bool isWeightInf (const WeightT &a, const WeightT &b); + static inline bool isWeightInf (const WeightT &a, const WeightT &b); static inline bool isEdgeInf (const Edge &a, const Edge &b); static inline void sort (Edge *edges, DimEdge count); @@ -66,7 +67,7 @@ namespace otb { template struct MaxWeight : public WeightBase { typedef WeightBase WB; - inline MaxWeight (); + inline MaxWeight(); inline MaxWeight (const PixelT *pixels, const Size &size); inline MaxWeight (const MaxWeight &model, const PixelT *pixels, const Size &size); diff --git a/include/ArrayTree/triskeleArrayTreeBase.hpp b/include/ArrayTree/triskeleArrayTreeBase.hpp index 4a69c9e..21cbcf6 100644 --- a/include/ArrayTree/triskeleArrayTreeBase.hpp +++ b/include/ArrayTree/triskeleArrayTreeBase.hpp @@ -29,6 +29,8 @@ namespace otb { /* Définit le type d'arbre à construire */ enum TreeType { MIN, MAX, TOS, ALPHA, TreeTypeCard}; + inline bool getDecrFromTreetype (TreeType treeType); + /*! Définit les noms des connectivités (utile pour le debug) */ extern string connectivityName[]; diff --git a/include/ArrayTree/triskeleArrayTreeBase.tpp b/include/ArrayTree/triskeleArrayTreeBase.tpp index a0fe25e..518fd82 100644 --- a/include/ArrayTree/triskeleArrayTreeBase.tpp +++ b/include/ArrayTree/triskeleArrayTreeBase.tpp @@ -1,6 +1,14 @@ #ifndef _OTB_TRISKELE_ARRAY_TREE_BASE_TPP #define _OTB_TRISKELE_ARRAY_TREE_BASE_TPP +inline bool +getDecrFromTreetype (TreeType treeType) { + switch (treeType) { + case MIN: return true; + } + return false; +} + inline ostream & operator << (ostream &out, const Connectivity &c) { BOOST_ASSERT (c >= 0 && c < 4); diff --git a/include/AttributeProfiles.hpp b/include/AttributeProfiles.hpp index 23434ec..86dbf30 100644 --- a/include/AttributeProfiles.hpp +++ b/include/AttributeProfiles.hpp @@ -16,6 +16,12 @@ namespace otb { inline PixelT *getValues (); inline const PixelT *getValues () const; + template + inline void setValues (const PixelT defaultValue, const WeightT *weights); + + template + inline void setValues (const PixelT *pixels, const WeightT *weights); + protected: const Tree &tree; DimNodeId leafCount; diff --git a/include/AttributeProfiles.tpp b/include/AttributeProfiles.tpp index b8b6945..aa0143d 100644 --- a/include/AttributeProfiles.tpp +++ b/include/AttributeProfiles.tpp @@ -1,6 +1,7 @@ #ifndef _OTB_TRISKELE_ATTRIBUTE_PROFILES_TPP #define _OTB_TRISKELE_ATTRIBUTE_PROFILES_TPP +// ======================================== template inline AttributeProfiles::AttributeProfiles (const Tree &tree) @@ -34,6 +35,38 @@ AttributeProfiles::getValues () const { return &values[0]; } +// ======================================== +template +template +inline void +AttributeProfiles::setValues (const PixelT defaultValue, const WeightT *weights) { + updateTranscient (); + fill_n (&values[0], tree.getLeafCount (), defaultValue); + PixelT *compAP = &values[tree.getLeafCount ()]; + dealThreadBound (tree.getCompCount (), tree.getCoreCount (), [&compAP, &weights] (const DimImg &minVal, const DimImg &maxVal) { + for (DimImg compIdx = minVal; compIdx < maxVal; ++compIdx) + compAP[compIdx] = weights[compIdx]; + }); +} + +template +template +inline void +AttributeProfiles::setValues (const PixelT *pixels, const WeightT *weights) { + updateTranscient (); + PixelT *leafAP = &values[0]; + dealThreadBound (tree.getLeafCount (), tree.getCoreCount (), [&leafAP, &pixels] (const DimImg &minVal, const DimImg &maxVal) { + for (DimImg i = minVal; i < maxVal; ++i) + leafAP[i] = pixels [i]; + }); + PixelT *compAP = leafAP+tree.getLeafCount (); + dealThreadBound (tree.getCompCount (), tree.getCoreCount (), [&compAP, &weights] (const DimImg &minVal, const DimImg &maxVal) { + for (DimImg compIdx = minVal; compIdx < maxVal; ++compIdx) + compAP[compIdx] = weights[compIdx]; + }); +} + + template inline void AttributeProfiles::free () { @@ -58,4 +91,5 @@ AttributeProfiles::print (ostream &out) const { return out; } +// ======================================== #endif // _OTB_TRISKELE_ATTRIBUTE_PROFILES_TPP diff --git a/include/Attributes/AreaAttributes.hpp b/include/Attributes/AreaAttributes.hpp index e843e0e..eaed0a4 100644 --- a/include/Attributes/AreaAttributes.hpp +++ b/include/Attributes/AreaAttributes.hpp @@ -9,7 +9,8 @@ namespace otb { namespace triskele { - class AreaAttributes : public CompAttributeC { + /*! Fonction monotonne strictement croissante. */ + class AreaAttributes : public CompAttribute { public: inline AreaAttributes (const Tree &tree); inline ~AreaAttributes (); diff --git a/include/Attributes/AreaAttributes.tpp b/include/Attributes/AreaAttributes.tpp index c7b41cd..eb800ff 100644 --- a/include/Attributes/AreaAttributes.tpp +++ b/include/Attributes/AreaAttributes.tpp @@ -5,7 +5,7 @@ using namespace boost::chrono; inline AreaAttributes::AreaAttributes (const Tree &tree) - : CompAttributeC (tree) { + : CompAttribute (tree) { compute (); } @@ -18,7 +18,7 @@ inline void AreaAttributes::cut (vector > &allBands, const AttributeProfiles &attributeProfiles, const vector &thresholds) const { auto start = high_resolution_clock::now (); - CompAttributeC::cut (allBands, attributeProfiles, 1, thresholds); + CompAttribute::cut (allBands, attributeProfiles, 1, thresholds); globalTreeStats.addTime (filteringStats, duration_cast > (high_resolution_clock::now ()-start).count ()); } diff --git a/include/Attributes/AverageAttributes.hpp b/include/Attributes/AverageAttributes.hpp index 07cc6b7..e316eea 100644 --- a/include/Attributes/AverageAttributes.hpp +++ b/include/Attributes/AverageAttributes.hpp @@ -11,11 +11,13 @@ namespace otb { namespace triskele { - class AverageAttributes : public CompAttributeC { + /*! Fonction non monotonne. */ + class AverageAttributes : public CompAttribute { public: template inline AverageAttributes (const Tree &tree, const Raster &raster, const AreaAttributes &areaAttributes); inline ~AverageAttributes (); + virtual inline ostream &print (ostream &out) const { CompAttribute::print (out, "average"); return out; } protected: template diff --git a/include/Attributes/AverageAttributes.tpp b/include/Attributes/AverageAttributes.tpp index 7a174f8..2fdcd23 100644 --- a/include/Attributes/AverageAttributes.tpp +++ b/include/Attributes/AverageAttributes.tpp @@ -6,7 +6,7 @@ using namespace boost::chrono; template inline AverageAttributes::AverageAttributes (const Tree &tree, const Raster &raster, const AreaAttributes &areaAttributes) - : CompAttributeC (tree) { + : CompAttribute (tree) { compute (raster, areaAttributes); } diff --git a/include/Attributes/MoIAttributes.hpp b/include/Attributes/MoIAttributes.hpp index 9041a5e..9fa9603 100644 --- a/include/Attributes/MoIAttributes.hpp +++ b/include/Attributes/MoIAttributes.hpp @@ -9,7 +9,8 @@ namespace otb { namespace triskele { - class MoIAttributes : public CompAttributeC { + /*! Fonction monotonne strictement croissante. */ + class MoIAttributes : public CompAttribute { public: inline MoIAttributes (const Tree &tree, const AreaAttributes &areaAttributes, const XYAttributes &xyAttributes); inline ~MoIAttributes (); diff --git a/include/Attributes/MoIAttributes.tpp b/include/Attributes/MoIAttributes.tpp index ba197ef..089ecd8 100644 --- a/include/Attributes/MoIAttributes.tpp +++ b/include/Attributes/MoIAttributes.tpp @@ -5,7 +5,7 @@ using namespace boost::chrono; inline MoIAttributes::MoIAttributes (const Tree &tree, const AreaAttributes &areaAttributes, const XYAttributes &xyAttributes) - : CompAttributeC (tree) { + : CompAttribute (tree) { compute (areaAttributes, xyAttributes); } @@ -23,8 +23,8 @@ MoIAttributes::cut (vector > &allBands, const AttributeProfiles

::getMaxValue (); cerr << "moi max value:" << maxValue << endl; - CompAttributeC::cut (allBands, attributeProfiles, 0, - CompAttributeC::getScaledThresholds (thresholds, maxValue)); + CompAttribute::cut (allBands, attributeProfiles, 0, + CompAttribute::getScaledThresholds (thresholds, maxValue)); globalTreeStats.addTime (filteringStats, duration_cast > (high_resolution_clock::now ()-start).count ()); } diff --git a/include/Attributes/SDAttributes.hpp b/include/Attributes/SDAttributes.hpp index 1521c95..696bb35 100644 --- a/include/Attributes/SDAttributes.hpp +++ b/include/Attributes/SDAttributes.hpp @@ -11,7 +11,8 @@ namespace otb { namespace triskele { - class SDAttributes : public CompAttributeC { + /*! Fonction non monotonne, globalement croissante. */ + class SDAttributes : public CompAttribute { public: inline SDAttributes (const Tree &tree, const AreaAttributes &areaAttributes); inline ~SDAttributes (); diff --git a/include/Attributes/SDAttributes.tpp b/include/Attributes/SDAttributes.tpp index 9d2fcf8..66f127d 100644 --- a/include/Attributes/SDAttributes.tpp +++ b/include/Attributes/SDAttributes.tpp @@ -5,7 +5,7 @@ using namespace boost::chrono; inline SDAttributes::SDAttributes (const Tree &tree, const AreaAttributes &areaAttributes) - : CompAttributeC (tree) { + : CompAttribute (tree) { compute (areaAttributes); } @@ -23,8 +23,8 @@ SDAttributes::cut (vector > &allBands, const AttributeProfiles::getMaxValue (); cerr << "sd max value:" << maxValue << endl; - CompAttributeC::cut (allBands, attributeProfiles, 0, - CompAttributeC::getScaledThresholds (thresholds, maxValue)); + CompAttribute::cut (allBands, attributeProfiles, 0, + CompAttribute::getScaledThresholds (thresholds, maxValue)); globalTreeStats.addTime (filteringStats, duration_cast > (high_resolution_clock::now ()-start).count ()); } diff --git a/include/Attributes/WeightAttributes.hpp b/include/Attributes/WeightAttributes.hpp index 1fee457..3c184ec 100644 --- a/include/Attributes/WeightAttributes.hpp +++ b/include/Attributes/WeightAttributes.hpp @@ -2,19 +2,24 @@ #ifndef _OTB_TRISKELE_WEIGHT_ATTRIBUTES_HPP #define _OTB_TRISKELE_WEIGHT_ATTRIBUTES_HPP +#include + #include "triskeleBase.hpp" namespace otb { namespace triskele { - /** Attribute */ + /*! Fonction monotonne strict croissante ou décroissante en fonction de la fonction de poid. */ template class WeightAttributes : public CompAttribute { public: - inline WeightAttributes (const Tree &tree); + inline WeightAttributes (const Tree &tree, const bool &decr); inline ~WeightAttributes (); inline void setWeightBounds (Tree &tree); + template + inline void cut (vector > &allBands, const AttributeProfiles &attributeProfiles, + const vector &thresholds) const; virtual inline ostream &print (ostream &out) const { CompAttribute::print (out, "weight"); return out; } }; diff --git a/include/Attributes/WeightAttributes.tpp b/include/Attributes/WeightAttributes.tpp index f7bfd96..c36a1fb 100644 --- a/include/Attributes/WeightAttributes.tpp +++ b/include/Attributes/WeightAttributes.tpp @@ -1,10 +1,12 @@ #ifndef _OTB_TRISKELE_WEIGHT_ATTRIBUTES_TPP #define _OTB_TRISKELE_WEIGHT_ATTRIBUTES_TPP +using namespace boost::chrono; + template inline -WeightAttributes::WeightAttributes (const Tree &tree) - : CompAttribute (tree) { +WeightAttributes::WeightAttributes (const Tree &tree, const bool &decr) + : CompAttribute (tree, decr) { } template @@ -39,4 +41,19 @@ WeightAttributes::setWeightBounds (Tree &tree) { weightBounds.push_back (rootId+1); } + +template +template +inline void +WeightAttributes::cut (vector > &allBands, const AttributeProfiles &attributeProfiles, + const vector &thresholds) const { + auto start = high_resolution_clock::now (); + vector orderedThresholds (thresholds); + if (CompAttribute::decr) + reverse (orderedThresholds.begin (), orderedThresholds.end ()); + CompAttribute::cut (allBands, attributeProfiles, 0., orderedThresholds); + globalTreeStats.addTime (filteringStats, duration_cast > (high_resolution_clock::now ()-start).count ()); +} + + #endif // _OTB_TRISKELE_WEIGHT_ATTRIBUTES_TPP diff --git a/include/Attributes/XYAttributes.hpp b/include/Attributes/XYAttributes.hpp index bc14297..d4bc0ea 100644 --- a/include/Attributes/XYAttributes.hpp +++ b/include/Attributes/XYAttributes.hpp @@ -11,6 +11,7 @@ namespace otb { namespace triskele { using namespace ::triskele; + /*! Fonction non monotonne. */ struct AverageXY { double x, y; inline AverageXY () : x(0), y(0) {} @@ -18,7 +19,7 @@ namespace otb { operator DimImg () const { return (DimImg) (x*y); } }; - class XYAttributes : public CompAttributeC { + class XYAttributes : public CompAttribute { public: inline XYAttributes (const Tree &tree, const AreaAttributes &areaAttributes); inline ~XYAttributes (); diff --git a/include/Attributes/XYAttributes.tpp b/include/Attributes/XYAttributes.tpp index c26cfa5..92d7bc2 100644 --- a/include/Attributes/XYAttributes.tpp +++ b/include/Attributes/XYAttributes.tpp @@ -5,7 +5,7 @@ using namespace boost::chrono; inline XYAttributes::XYAttributes (const Tree &tree, const AreaAttributes &areaAttributes) - : CompAttributeC (tree) { + : CompAttribute (tree) { compute (areaAttributes); } diff --git a/include/Border.hpp b/include/Border.hpp new file mode 100644 index 0000000..41af2ab --- /dev/null +++ b/include/Border.hpp @@ -0,0 +1,80 @@ +#ifndef _OTB_TRISKELE_BORDER_HPP +#define _OTB_TRISKELE_BORDER_HPP + +#include + +#include "triskeleBase.hpp" +//#include "triskeleArrayTreeBase.hpp" + +namespace triskele { + + /** Border */ + class Border { + public: + /*! Retourne le nombre de pixels à l'aide de la taille */ + static inline DimImg getPixelsCount (const Size &size); + + /*! Retourne la taille que doit faire le tableau simplifié */ + static inline DimImg getMapLength (DimImg pixelsCount); + + /*! Indique qu'une carte de borfure est présente (donc potentiellement des pixels de bordures). */ + inline bool exists () const; + + /*! Vérifie si un index est sur la map ou une bordure, en se basant sur le bit de l'index idx de la map */ + inline bool isBorder (DimImg idx) const; + + /*! Vérifie si un point est sur la map ou une bordure en appelant la méthode précédente après avoir converti le point en index */ + inline bool isBorder (const Point &p) const; + + /*! Supprime toutes les occurences de bordure à l'index idx */ + inline void clearBorder (DimImg idx); + + /*! Supprime toutes les occurences de bordure en appelant la méthode précédente après avoir converti le point en index */ + inline void clearBorder (const Point &p); + + /*! Rajoute une occurence de bordure à l'index indiqué */ + inline void setBorder (DimImg idx); + + /*! Rajoute une occurence de bordure en appelant la méthode précédente après avoir converti le point en index */ + inline void setBorder (const Point &p); + + /*! Construit par défault sans aucune bordure */ + inline Border (); + + /*! Construit Border, les valeurs de map dépendent de defaultVal */ + inline Border (const Size &size, bool defaultVal); + inline Border (const Border &border, const Rect &tile); + inline ~Border (); + + inline void reset (bool defaultVal); + + inline const Size &getSize () const; + + /*! Compte le nombre de pixels considérés comme de la bordure */ + inline DimImg borderCount (); + + private: + /*! Nombre de pixels dans l'image */ + DimImg pixelsCount; + + /*! Taille du tableau "simplifié" des pixels */ + DimImg mapLength; + + /*! Dimensions de l'image */ + Size size; + + /*! Tableau "simplifié" des pixels */ + vector map; + + bool defaultVal; + + inline void createMap (); + + friend inline ostream &operator << (ostream &out, const Border &border); + }; + +#include "Border.tpp" + +} // triskele + +#endif // _OTB_TRISKELE_BORDER_HPP diff --git a/include/ArrayTree/Border.tpp b/include/Border.tpp similarity index 93% rename from include/ArrayTree/Border.tpp rename to include/Border.tpp index b05e643..7c5bb74 100644 --- a/include/ArrayTree/Border.tpp +++ b/include/Border.tpp @@ -10,6 +10,11 @@ Border::getMapLength (DimImg pixelsCount) { return (pixelsCount+7)/8; } +inline bool +Border::exists () const { + return map.size (); +} + inline bool Border::isBorder (DimImg idx) const { BOOST_ASSERT (idx < pixelsCount); @@ -60,19 +65,21 @@ Border::Border () inline Border::Border (const Size &size, bool defaultVal) : pixelsCount (getPixelsCount (size)), - size (size), mapLength (getMapLength (pixelsCount)), + size (size), map (), defaultVal (defaultVal) { } inline Border::Border (const Border &border, const Rect &tile) - : size (tile.width, tile.height), - pixelsCount (getPixelsCount (size)), - mapLength (getMapLength (pixelsCount)), + : size (tile.width, tile.height), map (), defaultVal (border.defaultVal) { + + pixelsCount = getPixelsCount (size); + mapLength = getMapLength (pixelsCount); + if (!border.map.size ()) return; // XXX todo diff --git a/include/CompAttribute.hpp b/include/CompAttribute.hpp index 69d822a..2ce312d 100644 --- a/include/CompAttribute.hpp +++ b/include/CompAttribute.hpp @@ -14,44 +14,18 @@ namespace otb { template class CompAttribute { public: - inline CompAttribute (const Tree &tree); + static inline vector getScaledThresholds (const vector &thresholds, const AttrT &maxValue); + static inline vector getConvertedThresholds (const vector &thresholds); + + inline CompAttribute (const Tree &tree, const bool &decr = false); inline ~CompAttribute (); inline void updateTranscient (); inline const AttrT *getValues () const; inline AttrT *getValues (); inline AttrT getMaxValue () const; + inline bool getDecr () const; - virtual inline ostream &print (ostream &out) const { print (out, ""); return out; } - - protected: - const Tree &tree; - DimNodeId leafCount; - vector values; - - inline void free (); - inline void book (const DimImg &leafCount); - - ostream &print (ostream &out, const string &msg) const; - friend ostream &operator << (ostream& out, const CompAttribute &ca) { return ca.print (out); } - }; - - } // triskele -} // otb - -#include "Attributes/WeightAttributes.hpp" - -namespace otb { - namespace triskele { - - template - class CompAttributeC : public CompAttribute { - public: - inline CompAttributeC (const Tree &tree); - inline ~CompAttributeC (); - - static inline vector getScaledThresholds (const vector &thresholds, const AttrT &maxValue); - template inline void cut (vector > &allBands, const AttributeProfiles &attributeProfiles, const AttrT &pixelAttrValue, const vector &thresholds) const; @@ -60,11 +34,30 @@ namespace otb { inline void cutOnPos (vector > &allBands, const AttributeProfiles &attributeProfiles, const DimImg &pixelId, const AttrT &pixelAttrValue, const vector &thresholds) const; + virtual inline ostream &print (ostream &out) const { print (out, ""); return out; } + protected: + const Tree &tree; + DimNodeId leafCount; + vector values; + bool decr; + + inline void free (); + inline void book (const DimImg &leafCount); + template inline void computeSameCompLevel (const CumpFunctPSE &cumpFunctPSE /* cumpFunctPSE (DimImg parentId)*/) const; + + ostream &print (ostream &out, const string &msg) const; + friend ostream &operator << (ostream& out, const CompAttribute &ca) { return ca.print (out); return out; } + }; + } // triskele +} // otb +#include "Attributes/WeightAttributes.hpp" +namespace otb { + namespace triskele { #include "CompAttribute.tpp" } // triskele } // otb diff --git a/include/CompAttribute.tpp b/include/CompAttribute.tpp index d7f0b25..a528597 100644 --- a/include/CompAttribute.tpp +++ b/include/CompAttribute.tpp @@ -1,12 +1,34 @@ #ifndef _OTB_TRISKELE_COMP_ATTRIBUTE_TPP #define _OTB_TRISKELE_COMP_ATTRIBUTE_TPP +// ======================================== +template +inline vector +CompAttribute::getScaledThresholds (const vector &thresholds, const AttrT &maxValue) { + vector result; + for (double percent : thresholds) + result.push_back (percent*maxValue); + return result; +} + +template +inline vector +CompAttribute::getConvertedThresholds (const vector &thresholds) { + vector result; + for (double value : thresholds) + result.push_back ((AttrT) value); + return result; +} + +// ======================================== template inline -CompAttribute::CompAttribute (const Tree &tree) +CompAttribute::CompAttribute (const Tree &tree, const bool &decr) : tree (tree), leafCount (0), - values () { + values (), + decr (decr) +{ updateTranscient (); } @@ -47,78 +69,13 @@ CompAttribute::getMaxValue () const { return max; } -template -inline ostream & -CompAttribute::print (ostream &out, const string &msg) const { - cout << "values: " << msg << endl; - const Size doubleSize (tree.getSize().width, 2*tree.getSize ().height); - return cout << printMap (&values[0], doubleSize, tree.getCompCount ()) << endl << endl; -} - -template -inline void -CompAttribute::free () { - values = vector (); -} - -template -inline void -CompAttribute::book (const DimImg &leafCount) { - this->leafCount = leafCount; - values.resize (leafCount); -} - // ======================================== -template -inline -CompAttributeC::CompAttributeC (const Tree &tree) - : CompAttribute (tree) { -} - -template -inline -CompAttributeC::~CompAttributeC () { -} - -template -inline vector -CompAttributeC::getScaledThresholds (const vector &thresholds, const AttrT &maxValue) { - vector result; - for (AttrT percent : thresholds) - result.push_back (percent*maxValue); - return result; -} - - -template -template -inline void -CompAttributeC::computeSameCompLevel (const CumpFunctPSE &cumpFunctPSE) const { - const vector &weightBounds (CompAttribute::tree.getWeightBounds ()); - unsigned int coreCount = CompAttribute::tree.getCoreCount (); - DEF_LOG ("CompAttributeC::computeSameCompLevel", "coreCount:" << coreCount); - if (!weightBounds.size () || CompAttribute::tree.getCompCount ()/weightBounds.size () < coreCount) { - LOG ("CompAttributeC::computeSameCompLevel: no thread"); - CompAttribute::tree.forEachComp (cumpFunctPSE); - return; - } - DimImg first = weightBounds [0]; - for (DimImg curBound = 1; curBound < weightBounds.size (); curBound++) { - DimImg next = weightBounds [curBound]; - dealThreadRange (next-first, coreCount, [this, &first, &cumpFunctPSE] (const DimImg &id) { - const DimImg parentId = id+first; - cumpFunctPSE (parentId); - }); - first = next; - } -} - template template inline void -CompAttributeC::cut (vector > &allBands, const AttributeProfiles &attributeProfiles, +CompAttribute::cut (vector > &allBands, const AttributeProfiles &attributeProfiles, const AttrT &pixelAttrValue, const vector &thresholds) const { - DEF_LOG ("CompAttributeC::cut", "coreCount:" << CompAttribute::tree.getCoreCount () << " thresholds:" << thresholds.size ()); + DEF_LOG ("CompAttribute::cut", "coreCount:" << CompAttribute::tree.getCoreCount () << " thresholds:" << thresholds.size ()); dealThreadRange (CompAttribute::leafCount, CompAttribute::tree.getCoreCount (), [this, &allBands, &attributeProfiles, &pixelAttrValue, &thresholds] (const DimImg &leafId) { cutOnPos (allBands, attributeProfiles, leafId, pixelAttrValue, thresholds); }); @@ -127,12 +84,13 @@ CompAttributeC::cut (vector > &allBands, const AttributePr template template inline void -CompAttributeC::cutOnPos (vector > &allBands, const AttributeProfiles &attributeProfiles, +CompAttribute::cutOnPos (vector > &allBands, const AttributeProfiles &attributeProfiles, const DimImg &leafId, const AttrT &pixelAttrValue, const vector &thresholds) const { // no debug (to many pixels) DimImg parentId = CompAttribute::tree.getLeafParent (leafId); DimChanel thresholdsSize = thresholds.size (); if (parentId == DimImg_MAX) { + // border case for (DimChanel chanel = 0; chanel < thresholdsSize; ++chanel) allBands[chanel][leafId] = 0; return; @@ -150,9 +108,17 @@ CompAttributeC::cutOnPos (vector > &allBands, const Attrib DimImg rootId = CompAttribute::tree.getCompRoot (); for (DimChanel chanel = 0; chanel < thresholdsSize; ++chanel) { AttrT ceil = thresholds[chanel]; - for ( ; curValue < ceil && curId < rootId; ) { + for ( ; curId < rootId; ) { + if (decr) { + if (curValue < ceil) + break; + } else { + if (curValue > ceil) + break; + } if (parentId == DimImg_MAX || curId >= parentId) { - // cerr << "CompAttributeC::cutOnPos find sub-root:" << rootId << " rootId:" << rootId << endl; + // cerr << "CompAttribute::cutOnPos find sub-root:" << rootId << " rootId:" << rootId << endl; + // find root for (; chanel < thresholdsSize; ++chanel) allBands[chanel][leafId] = curValue; return; @@ -167,4 +133,53 @@ CompAttributeC::cutOnPos (vector > &allBands, const Attrib } } +// ======================================== +template +inline ostream & +CompAttribute::print (ostream &out, const string &msg) const { + cout << "values: " << msg << endl; + const Size doubleSize (tree.getSize().width, 2*tree.getSize ().height); + cout << printMap (&values[0], doubleSize, tree.getCompCount ()) << endl << endl; + return out; +} + +// ======================================== +template +inline void +CompAttribute::free () { + values = vector (); +} + +template +inline void +CompAttribute::book (const DimImg &leafCount) { + this->leafCount = leafCount; + values.resize (leafCount); +} + +// ======================================== +template +template +inline void +CompAttribute::computeSameCompLevel (const CumpFunctPSE &cumpFunctPSE) const { + const vector &weightBounds (CompAttribute::tree.getWeightBounds ()); + unsigned int coreCount = CompAttribute::tree.getCoreCount (); + DEF_LOG ("CompAttribute::computeSameCompLevel", "coreCount:" << coreCount); + if (!weightBounds.size () || CompAttribute::tree.getCompCount ()/weightBounds.size () < coreCount) { + LOG ("CompAttribute::computeSameCompLevel: no thread"); + CompAttribute::tree.forEachComp (cumpFunctPSE); + return; + } + DimImg first = weightBounds [0]; + for (DimImg curBound = 1; curBound < weightBounds.size (); curBound++) { + DimImg next = weightBounds [curBound]; + dealThreadRange (next-first, coreCount, [this, &first, &cumpFunctPSE] (const DimImg &id) { + const DimImg parentId = id+first; + cumpFunctPSE (parentId); + }); + first = next; + } +} + +// ======================================== #endif // _OTB_TRISKELE_COMP_ATTRIBUTE_TPP diff --git a/include/IImage.hpp b/include/IImage.hpp index ff1c553..17bf5a0 100644 --- a/include/IImage.hpp +++ b/include/IImage.hpp @@ -19,6 +19,7 @@ namespace triskele { private: Size size; vector pixels; + public: inline void setSize (const Size &size); inline const Size &getSize () const; @@ -39,6 +40,8 @@ namespace triskele { class IImage { public: void setFileName (string fileName); + inline void getGeo (string& projectionRef, vector &geoTransform) const; + inline void setGeo (const string& projectionRef, vector geoTransform, const Point &topLeft); inline const string &getFileName () const; inline const Size &getSize () const; inline const DimChanel &getBandCount () const; @@ -46,11 +49,13 @@ namespace triskele { inline const bool isRead () const; inline const bool isEmpty () const; - IImage (const std::string &imageFileName = ""); - ~IImage (); + IImage (const std::string &imageFileName = ""); + ~IImage (); void readImage (); void createImage (const Size &size, const GDALDataType &dataType, const DimChanel &nbOutputBands); + void createImage (const Size &size, const GDALDataType &dataType, const DimChanel &nbOutputBands, + const IImage &inputImage, const Point &topLeft); void close (); template @@ -66,6 +71,8 @@ namespace triskele { private: static size_t gdalCount; + string projectionRef; + vector geoTransform; string fileName; Size size; DimChanel bandCount; diff --git a/include/IImage.tpp b/include/IImage.tpp index aad6f02..fb6d697 100644 --- a/include/IImage.tpp +++ b/include/IImage.tpp @@ -86,6 +86,37 @@ IImage::setFileName (string fileName) { close (); } +inline void +IImage::getGeo (string& projectionRef, vector &geoTransform) const { + projectionRef = this->projectionRef; + geoTransform = this->geoTransform; +} + +inline void +IImage::setGeo (const string& projectionRef, vector geoTransform, const Point &topLeft) { + DEF_LOG ("IImage::setGeo", "projectionRef:" << projectionRef); + // move TopLeft cf WordFile + double + x (geoTransform[0]), + xScale (geoTransform[1]), + xSkew (geoTransform[2]), + y (geoTransform[3]), + ySkew (geoTransform[4]), + yScale (geoTransform[5]); + double + xTrans = x + topLeft.x*xScale + topLeft.y*xSkew, + yTrans = y + topLeft.x*ySkew + topLeft.y*yScale; + geoTransform[0] = xTrans; + geoTransform[3] = yTrans; + CPLErr err = gdalOutputDataset->SetGeoTransform (&geoTransform[0]); + if (err != CE_None) + cerr << "IImage::setGeo: can't set geoTransform for " << fileName << endl; + err = gdalOutputDataset->SetProjection (projectionRef.c_str ()); + if (err != CE_None) + cerr << "IImage::setGeo: can't set projection for " << fileName << endl; +} + + inline const string & IImage::getFileName () const { return fileName; diff --git a/include/Tree.hpp b/include/Tree.hpp index 344fd0d..51f2ca9 100644 --- a/include/Tree.hpp +++ b/include/Tree.hpp @@ -9,6 +9,7 @@ #include "triskeleBase.hpp" #include "triskeleDebug.hpp" +#include "Border.hpp" namespace otb { namespace triskele { @@ -121,8 +122,8 @@ namespace otb { bool compareTo (const Tree &tree, bool testChildren = false) const; - void checkSpare () const; - void check () const; + void checkSpare (const Border& border) const; + void check (const Border& border) const; // XXX void checkWeightCurve (bool incr) const; // nice ostream diff --git a/include/TreeStats.hpp b/include/TreeStats.hpp index 738e3b3..f227d58 100644 --- a/include/TreeStats.hpp +++ b/include/TreeStats.hpp @@ -11,6 +11,7 @@ #include #include +#include "triskeleDebug.hpp" #include "ArrayTree/triskeleArrayTreeBase.hpp" namespace otb { @@ -37,6 +38,7 @@ namespace otb { buildParentsStats, buildFromTilesStats, buildMergeStats, + buildForestStats, buildIndexStats, buildCompressStats, buildChildrenStats, diff --git a/include/triskeleDealThreads.hpp b/include/triskeleDealThreads.hpp index 23e3a70..4ed24d5 100644 --- a/include/triskeleDealThreads.hpp +++ b/include/triskeleDealThreads.hpp @@ -6,6 +6,8 @@ #endif #include +#include "triskeleDebug.hpp" + namespace triskele { template diff --git a/include/triskeleDealThreads.tpp b/include/triskeleDealThreads.tpp index 9bafaac..969e926 100644 --- a/include/triskeleDealThreads.tpp +++ b/include/triskeleDealThreads.tpp @@ -71,7 +71,7 @@ dealThread (const DimImg &maxId, unsigned int coreCount, const FunctThreadMinMax functThreadMinMax (idCopyValInThread, maxIds[idCopyValInThread], maxIds[idCopyValInThread+1]); }); #else /* BOOST thread */ - boost::thread tasks [coreCount]; + std::vector tasks; for (unsigned int idCopyValInThread = 0; idCopyValInThread < coreCount; ++idCopyValInThread) { tasks.push_back (boost::thread ([/*no ref!!!*/idCopyValInThread, &maxIds, &functThreadMinMax] () { functThreadMinMax (idCopyValInThread, maxIds[idCopyValInThread], maxIds[idCopyValInThread+1]); @@ -106,37 +106,37 @@ callOnSortedSets (const std::vector &sizes, // get min bool found = false; DimImg minVectIdx = 0; - WeightT minWeight = 0; + WeightT maxWeight = 0; for (DimImg vectId = 0; vectId < size; ++vectId) { if (!vectCounts [vectId]) continue; WeightT tmpWeight = getWeight (vectId, 0); - if (found && !isWeightInf (tmpWeight, minWeight)) + if (found && !isWeightInf (tmpWeight, maxWeight)) continue; minVectIdx = vectId; - minWeight = tmpWeight; + maxWeight = tmpWeight; found = true; } - LOG ("found:" << found << " minVectIdx:" << minVectIdx << " minWeight:" << minWeight); + LOG ("found:" << found << " minVectIdx:" << minVectIdx << " maxWeight:" << maxWeight); // loop for ( ; found; ) { // get next min found = false; DimImg nextMinVectIdx = 0; - WeightT nextMinWeight = 0; + WeightT nextMaxWeight = 0; for (DimImg vectId = minVectIdx; ; ) { if (vectCounts [vectId]) { WeightT tmpWeight = getWeight (vectId, vectIds [vectId]); - if (!isWeightInf (minWeight, tmpWeight)) { - // minWeight == tmpWeight + if (!isWeightInf (maxWeight, tmpWeight)) { + // maxWeight == tmpWeight callIdId (vectId, vectIds [vectId]); ++vectIds [vectId]; --vectCounts [vectId]; continue; } - if (!found || isWeightInf (tmpWeight, nextMinWeight)) { + if (!found || isWeightInf (tmpWeight, nextMaxWeight)) { nextMinVectIdx = vectId; - nextMinWeight = tmpWeight; + nextMaxWeight = tmpWeight; found = true; } } @@ -145,7 +145,7 @@ callOnSortedSets (const std::vector &sizes, break; } minVectIdx = nextMinVectIdx; - minWeight = nextMinWeight; + maxWeight = nextMaxWeight; } } diff --git a/include/triskeleDebug.hpp b/include/triskeleDebug.hpp index 9d33a34..9feffbd 100644 --- a/include/triskeleDebug.hpp +++ b/include/triskeleDebug.hpp @@ -6,6 +6,8 @@ #include #include #include +#include + #ifdef ENABLE_SMART_LOG @@ -18,7 +20,7 @@ #endif #ifndef SMART_LOG_EXPR -#define SMART_LOG_EXPR(expr) {if (triskele::debug) {expr;} } +#define SMART_LOG_EXPR(expr) {if (::triskele::debug) {expr;} } #endif #else @@ -52,15 +54,15 @@ #else #ifndef DEF_LOG -#define DEF_LOG(name, expr) ::triskele::Log log (name); { if (triskele::debug) cerr << expr << endl << flush; } +#define DEF_LOG(name, expr) ::triskele::Log log (name); { if (::triskele::debug) cerr << expr << endl << flush; } #endif #ifndef LOG -#define LOG(expr) { if (triskele::debug) cerr << log << "| " << expr << endl << flush; } +#define LOG(expr) { if (::triskele::debug) cerr << log << "| " << expr << endl << flush; } #endif #ifndef DEBUG -#define DEBUG(expr) { if (triskele::debug) cerr << expr << endl << flush; } +#define DEBUG(expr) { if (::triskele::debug) cerr << expr << endl << flush; } #endif #endif @@ -94,14 +96,18 @@ namespace triskele { static unsigned int indent; string functName; public: - Log (const string &functName) : functName (functName) { ++indent; if (triskele::debug) cerr << *this << "> "; } - ~Log () { if (triskele::debug) cerr << *this << "<" << endl << flush; --indent; } + Log (const string &functName) : functName (functName) { ++indent; if (::triskele::debug) cerr << *this << "> "; } + ~Log () { if (::triskele::debug) cerr << *this << "<" << endl << flush; --indent; } friend inline ostream &operator << (ostream &out, const Log &log) { return out << getLocalTimeStr () << setw (3) << setw ((log.indent % 20)*2) << "" << log.functName; } }; + inline string ns2string (double delta); + // ======================================== +#include "triskeleDebug.tpp" + }//namespace triskele #endif //_TRISKELE_DEBUG_HPP diff --git a/include/triskeleDebug.tpp b/include/triskeleDebug.tpp new file mode 100644 index 0000000..7fbadc0 --- /dev/null +++ b/include/triskeleDebug.tpp @@ -0,0 +1,24 @@ +#ifndef _OTB_TRISKELE_DEBUG_TPP +#define _OTB_TRISKELE_DEBUG_TPP + +string +ns2string (double delta) { + using namespace boost::chrono; + + ostringstream oss; + duration ns (delta); + oss.fill ('0'); + // typedef duration > days; + // auto d = duration_cast(ns); + // ns -= d; + auto h = duration_cast (ns); + ns -= h; + auto m = duration_cast (ns); + ns -= m; + oss << setw (2) << h.count () << ":" + << setw (2) << m.count () << ":" + << setw (9) << fixed << setprecision (6) << ns.count (); + return oss.str (); +} + +#endif // _OTB_TRISKELE_DEBUG_TPP diff --git a/python/setup.py b/python/setup.py new file mode 100644 index 0000000..6e5c739 --- /dev/null +++ b/python/setup.py @@ -0,0 +1,20 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# \file setup.py +# \brief TODO +# \author Florent Guiotte +# \version 0.1 +# \date 11 sept. 2018 +# +# TODO details + +from distutils.core import setup + +setup(name='triskele', + version='1.0', + description='Python wrapper for Triskele', + author='Florent Guiotte', + author_email='florent.guiotte@uhb.fr', + url='https://git.guiotte.fr/Florent/Triskele', + packages=['triskele'], + ) diff --git a/python/triskele/CreaTIFF.py b/python/triskele/CreaTIFF.py index 0e07363..a5f3268 100644 --- a/python/triskele/CreaTIFF.py +++ b/python/triskele/CreaTIFF.py @@ -24,6 +24,10 @@ np_to_gdt = { def write(fname, X): """X.shape = (length, width) or X.shape = (length, width, samples)""" + + fname = Path(fname) + if not fname.parent.exists(): + raise IOError('Directory not found: {}'.format(fname.parent)) width = X.shape[1] length = X.shape[0] @@ -38,7 +42,7 @@ def write(fname, X): dst_ds = driver.Create(str(fname), width, length, samples, np_to_gdt[X.dtype.type]) for i in range(samples): - dst_ds.GetRasterBand(i + 1).WriteArray(X[:,:,i].astype(np.uint8)) + dst_ds.GetRasterBand(i + 1).WriteArray(X[:,:,i]) dst_ds.FlushCache() def read(fname): diff --git a/python/triskele/Triskele.py b/python/triskele/Triskele.py index 5c81555..c3560cd 100644 --- a/python/triskele/Triskele.py +++ b/python/triskele/Triskele.py @@ -37,8 +37,8 @@ class Triskele: self._write_infile(raster, dtype) - def filter(self, tree='max-tree', area=None, standard_deviation=None, moment_of_inertia=None): - self._setup(tree, area, standard_deviation, moment_of_inertia) + def filter(self, tree='max-tree', area=None, standard_deviation=None, moment_of_inertia=None, feature='weight'): + self._setup(tree, area, standard_deviation, moment_of_inertia, feature) self._run() return self._read_outfile() @@ -46,14 +46,14 @@ class Triskele: return read(self.outfile) def _write_infile(self, rasters, dtype): - ## Scale to new dtype - rep = np.iinfo(dtype) - ## Expand if rasters is 2D if len(rasters.shape) < 3: rasters = np.expand_dims(rasters, 2) - rasters = rasters.astype(np.float32) + ## Scale to new dtype + rep = np.iinfo(dtype) + + rasters = rasters.astype(np.float64) ## Channel independant scale for i in range(rasters.shape[2]): @@ -63,11 +63,12 @@ class Triskele: rasters = rasters.astype(dtype) write(self.infile, rasters) - def _setup(self, tree, area, standard_deviation, moment_of_inertia): + def _setup(self, tree, area, standard_deviation, moment_of_inertia, feature): self.process = [self.triskele_bin, '-i', '{}'.format(self.infile), '-o', '{}'.format(self.outfile), - '--{}'.format(tree)] + '--{}'.format(tree), + '--f-{}'.format(feature)] if area is not None: np.savetxt(self.areafile, area, fmt='%d') diff --git a/src/Appli/Option.cpp b/src/Appli/Option.cpp index 329fde5..c9ab7bc 100644 --- a/src/Appli/Option.cpp +++ b/src/Appli/Option.cpp @@ -1,5 +1,4 @@ -#define LAST_VERSION "2018-03-29 (Debian Stretch)" - +#define LAST_VERSION "1.1 2018-08-06 (Debian Stretch)" #include #include @@ -97,26 +96,50 @@ Option::parse (int argc, char** argv) { bool helpFlag = false, versionFlag = false, useTheForceLuke = false; string inputFileName, outputFileName, bandsRange; long left = -1, top = -1, width = -1, height = -1; - string areaThresholdsName, sdThresholdsName, moiThresholdsName; + string areaThresholdsName, levelThresholdsName, sdThresholdsName, moiThresholdsName; + bool c4 = false, c6p = false, c6n = false, c8 = false; + bool weightFlag = false, meanFlag = false, sdFlag = false, areaFlag = false, moiFlag; try { desc.add_options () ("help", po::bool_switch (&helpFlag), "produce this help message") ("version", po::bool_switch (&versionFlag), "display version information") ("debug", po::bool_switch (&debugFlag), "debug mode") + ("band,b", po::value (&bandsRange), "select input band (first band is 0) (default all bands : 0-*)") ("left,x", po::value (&left), "left crop (default center)") ("top,y", po::value (&top), "top crop (default middle)") ("width,w", po::value (&width), "width crop (default input width)") ("height,h", po::value (&height), "height crop (default input height)") + + ("border", po::bool_switch (&border), "build tree without border pixels (no-data)") + ("C4", po::bool_switch (&c4), (string ("4-connected pixels")+ + (connectivity == Connectivity::C4 ? " (default)" : "")).c_str ()) + ("C6P", po::bool_switch (&c6p), (string ("6-connected pixels (positive")+ + (connectivity == Connectivity::C6P ? " (default)" : "")+")").c_str ()) + ("C6N", po::bool_switch (&c6n), (string ("6-connected pixels (negative")+ + (connectivity == Connectivity::C6N ? " (default)" : "")+")").c_str ()) + ("C8", po::bool_switch (&c8), (string ("8-connected pixels")+ + (connectivity == Connectivity::C8 ? " (default)" : "")).c_str ()) + ("input,i", po::value (&inputFileName), "input file name image") ("output,o", po::value (&outputFileName), "output file name hyperbands image (contains attributs profiles)") + ("max-tree", po::bool_switch (&maxTreeFlag), "build max-tree") ("min-tree", po::bool_switch (&minTreeFlag), "build min-tree") ("tos-tree", po::bool_switch (&tosTreeFlag), "build tree-of-shape") ("alpha-tree", po::bool_switch (&alphaTreeFlag), "build alpha-tree") - ("area,A", po::value (&areaThresholdsName), "produce area attributs") - ("standard-deviation,S", po::value (&sdThresholdsName), "produce standard deviation attributs") - ("moment-of-inertia,M", po::value (&moiThresholdsName), "produce moment of inertia attributs") + + ("f-weight", po::bool_switch (&weightFlag), "produce attribut profiles (default)") + // ("f-level,FPL", po::bool_switch (&weightFlag), "produce feature profiles level") + ("f-mean", po::bool_switch (&meanFlag), "produce feature profiles mean") + ("f-SD", po::bool_switch (&sdFlag), "produce feature profiles SD") + ("f-area", po::bool_switch (&areaFlag), "produce feature profiles area") + ("f-MOI", po::bool_switch (&moiFlag), "produce feature profiles area") + + ("area,A", po::value (&areaThresholdsName), "cut according area attributs") + ("weight,W", po::value (&levelThresholdsName), "cut according level attributs") + ("standard-deviation,S", po::value (&sdThresholdsName), "cut according standard deviation attributs") + ("moment-of-inertia,M", po::value (&moiThresholdsName), "cut according moment of inertia attributs") ; hide.add_options () ("use-the-force-luke", po::bool_switch (&useTheForceLuke), "display hidded options") @@ -186,6 +209,7 @@ Option::parse (int argc, char** argv) { usage ("Bad options"); } areaThresholds = readThresholds (areaThresholdsName); + levelThresholds = readThresholds (levelThresholdsName); sdThresholds = readThresholds (sdThresholdsName); moiThresholds = readThresholds (moiThresholdsName); @@ -217,6 +241,32 @@ Option::parse (int argc, char** argv) { topLeft = Point ((DimSideImg) left, (DimSideImg) top); size = Size ((DimSideImg) width, (DimSideImg) height); + int connectivityCount = c4 + c6n + c6p + c8; + if (connectivityCount > 1) + usage ("You must choose only one connectivity model"); + if (c6p) + connectivity = Connectivity::C6P; + else if (c6n) + connectivity = Connectivity::C6N; + else if (c8) + connectivity = Connectivity::C8; + else + connectivity = Connectivity::C4; + + int featureCount = weightFlag + meanFlag + sdFlag + areaFlag + moiFlag; + if (featureCount > 1) + usage ("You must choose only one feature attribut profile"); + if (meanFlag) + featureType = FeatureType::MEAN; + if (sdFlag) + featureType = FeatureType::SD; + if (areaFlag) + featureType = FeatureType::AREA; + if (moiFlag) + featureType = FeatureType::MOI; + else + featureType = FeatureType::AP; + cout << "Input:" << inputFileName << " " << orgSize << " (" << bandInputCount << " chanels of " << GDALGetDataTypeName (inputType) << ")" << endl << "Crop topLeft:" << topLeft << " size:" << size << " band:" << selectedBand << endl diff --git a/src/ArrayTree/triskeleArrayTreeBase.cpp b/src/ArrayTree/triskeleArrayTreeBase.cpp index c37d733..e7b9524 100644 --- a/src/ArrayTree/triskeleArrayTreeBase.cpp +++ b/src/ArrayTree/triskeleArrayTreeBase.cpp @@ -14,5 +14,5 @@ otb::triskele::arrayTree::tileItemName[] = { std::string otb::triskele::arrayTree::treeTypeLabels[] = { - "min", "max", "tos" + "min", "max", "tos", "alpha" }; diff --git a/src/IImage.cpp b/src/IImage.cpp index 3860f09..d744a97 100644 --- a/src/IImage.cpp +++ b/src/IImage.cpp @@ -11,10 +11,11 @@ size_t IImage::gdalCount = 0; IImage::IImage (const string &imageFileName) - : fileName (imageFileName), - read (false), + : geoTransform (6, 0), + fileName (imageFileName), gdalInputDataset (nullptr), - gdalOutputDataset (nullptr) + gdalOutputDataset (nullptr), + read (false) { } @@ -24,7 +25,7 @@ IImage::~IImage () { void IImage::readImage () { - DEF_LOG ("IImage::readImage", "fileName: " << fileName); + DEF_LOG ("IImage::readImage", "fileName: " << fileName << " c_str:" << fileName.c_str ()); BOOST_ASSERT (gdalInputDataset == nullptr); BOOST_ASSERT (gdalOutputDataset == nullptr); close (); @@ -36,11 +37,18 @@ IImage::readImage () { cerr << "GDALError: can't define dataset" << endl; return; } + size = Size (gdalInputDataset->GetRasterXSize (), gdalInputDataset->GetRasterYSize ()); bandCount = gdalInputDataset->GetRasterCount (); LOG ("size: " << size << " x " << bandCount); read = true; + projectionRef = gdalInputDataset->GetProjectionRef (); + CPLErr err = gdalInputDataset->GetGeoTransform (&geoTransform[0]); + if (err != CE_None) + cerr << "IImage::readImage: can't read geoTransform from " << fileName << endl; + else + LOG ("geoTransform: " << geoTransform [0] << " " << geoTransform [1] << " " << geoTransform [2] << " " << geoTransform [3] << " " << geoTransform [4] << " " << geoTransform [5]); for (DimChanel band = 0; band < bandCount; ++band) { GDALRasterBand &poBand = *gdalInputDataset->GetRasterBand (band+1); @@ -81,14 +89,25 @@ IImage::createImage (const Size &size, const GDALDataType &dataType, const DimCh GDALDriver *driverTiff = GetGDALDriverManager ()->GetDriverByName ("GTiff"); remove (fileName.c_str ()); gdalOutputDataset = driverTiff->Create (fileName.c_str (), size.width, size.height, nbBands, dataType, NULL); + LOG("gdalCount: " << gdalCount); } +void +IImage::createImage (const Size &size, const GDALDataType &dataType, const DimChanel &nbBands, + const IImage &inputImage, const Point &topLeft) +{ + createImage (size, dataType, nbBands); + string projectionRef; + vector geoTransform; + inputImage.getGeo (projectionRef, geoTransform); + setGeo (projectionRef, geoTransform, topLeft); +} + void IImage::close () { DEF_LOG ("IImage::close", "fileName: " << fileName); if (gdalOutputDataset) { - // XXX pour écriture gdalOutputDataset->SetProjection ("WGS84"); GDALClose (gdalOutputDataset); gdalOutputDataset = nullptr; if (!--gdalCount) diff --git a/src/PerfArrayTreeBuilder.cpp b/src/PerfArrayTreeBuilder.cpp index f86fd13..597cac3 100644 --- a/src/PerfArrayTreeBuilder.cpp +++ b/src/PerfArrayTreeBuilder.cpp @@ -5,6 +5,7 @@ #include "triskeleDebug.hpp" #include "triskeleBase.hpp" +#include "Border.hpp" #include "Tree.hpp" #include "TreeStats.hpp" #include "TreeBuilder.hpp" @@ -12,7 +13,6 @@ #include "AttributeProfiles.hpp" #include "ArrayTree/triskeleArrayTreeBase.hpp" #include "ArrayTree/triskeleSort.hpp" -#include "ArrayTree/Border.hpp" #include "ArrayTree/GraphWalker.hpp" #include "ArrayTree/Leader.hpp" #include "ArrayTree/Weight.hpp" @@ -33,14 +33,14 @@ perf (const Raster &raster, const GraphWalker &graphWalker, const TreeTy Tree tree (coreCount); WeightAttributes weightAttributes (tree); atb.buildTree (tree, weightAttributes); - tree.check (); + tree.check (graphWalker.border); } // ======================================== int main (int argc, char **argv, char **envp) { if (argc != 5) { - cerr << "Usage: " << argv[0] << ": treeType coreCount nbTest imageSize" << endl; + cerr << "Usage: " << argv[0] << ": {MIN|MAX|TOS|ALPHA} coreCount nbTest imageSize" << endl; exit (1); } string argType (argv[1]); diff --git a/src/TestArrayTreeBuilder.cpp b/src/TestArrayTreeBuilder.cpp index 9813d60..6d745b7 100644 --- a/src/TestArrayTreeBuilder.cpp +++ b/src/TestArrayTreeBuilder.cpp @@ -5,6 +5,7 @@ #include "triskeleDebug.hpp" #include "triskeleBase.hpp" +#include "Border.hpp" #include "Tree.hpp" #include "TreeStats.hpp" #include "TreeBuilder.hpp" @@ -12,7 +13,6 @@ #include "AttributeProfiles.hpp" #include "ArrayTree/triskeleArrayTreeBase.hpp" #include "ArrayTree/triskeleSort.hpp" -#include "ArrayTree/Border.hpp" #include "ArrayTree/GraphWalker.hpp" #include "ArrayTree/Leader.hpp" #include "ArrayTree/Weight.hpp" @@ -23,9 +23,9 @@ using namespace otb::triskele; using namespace otb::triskele::arrayTree; -const unsigned int nbTest = 1000; -const TreeType treeType = ALPHA; // TOS; // MIN; // MAX; -const unsigned int coreCount = 4; +const unsigned int nbTest = 1; // 1000; +const TreeType treeType = MIN; // ALPHA; // TOS; // MIN; // MAX; +const unsigned int coreCount = 2; typedef uint16_t PixelT; typedef uint16_t WeightT; @@ -92,7 +92,7 @@ PixelT pixelsB3 [] = { //) parents[0]:0 parentId:6 level child:0 parent:0 parent 5, 1, 7, 2, 4, 1, 6, 6, 4, 6, 1, 5 }; -PixelT pixelsC1 [] = { //A) childIdx:26 parentId:1 parentIdx:25 rootId:9 +PixelT pixelsC1_6x4 [] = { //A) childIdx:26 parentId:1 parentIdx:25 rootId:9 6, 1, 7, 7, 3, 3, 0, 3, 0, 0, 6, 4, 3, 3, 4, 6, 7, 4, @@ -208,23 +208,31 @@ PixelT pixelsT7_12x8 [] = { // ======================================== void test () { //Size size (6, 4); - //Size size (18, 12); + // Size size (18, 12); Size size (12, 8); Border border (size, false); + border.setBorder (1); + //border.setBorder (12); + border.setBorder (13); + border.setBorder (24); + border.setBorder (25); + GraphWalker graphWalker (border); int leafCount = graphWalker.vertexMaxCount (); // ==================== + // PixelT *pixels = pixelsC1_6x4; + // PixelT *pixels = pixelsT1_18x12; // PixelT *pixels = pixelsT2_12x8; // PixelT *pixels = pixelsT3_12x8; // PixelT *pixels = pixelsT4_12x8; - // PixelT *pixels = pixelsT5_12x8; + PixelT *pixels = pixelsT5_12x8; // PixelT *pixels = pixelsT6_12x8; // PixelT *pixels = pixelsT7_12x8; - PixelT *pixels = new PixelT [leafCount]; - for (int i = 0; i < leafCount; ++i) - pixels[i] = std::rand() % 8; + // PixelT *pixels = new PixelT [leafCount]; + // for (int i = 0; i < leafCount; ++i) + // pixels[i] = std::rand() % 8; // ==================== Raster raster (size); @@ -246,7 +254,7 @@ void test () { Tree tree (coreCount); WeightAttributes weightAttributes (tree); atb.buildTree (tree, weightAttributes); - tree.check (); + tree.check (border); AttributeProfiles attributeProfiles (tree); atb.setAttributProfiles (attributeProfiles); diff --git a/src/Tree.cpp b/src/Tree.cpp index 22f5970..88d648f 100644 --- a/src/Tree.cpp +++ b/src/Tree.cpp @@ -1,5 +1,5 @@ #include "Tree.hpp" -#include "ArrayTree/Border.hpp" +#include "Border.hpp" #include "ArrayTree/GraphWalker.hpp" using namespace otb::triskele; @@ -7,21 +7,21 @@ using namespace otb::triskele::arrayTree; using namespace std; Tree::Tree (const DimSideImg &width, const DimSideImg &height, unsigned int coreCount) - : Tree (coreCount) + : Tree(coreCount) { - resize (width, height); + resize(width, height); } Tree::Tree (unsigned int coreCount) - : size (), - coreCount (coreCount), - leafCount (0), - nodeCount (0), - leafParents (), - compParents (nullptr), - children (), - childrenStart (), - state (State::Void) + : coreCount(coreCount), + size(), + leafCount(0), + nodeCount(0), + leafParents(), + compParents(nullptr), + childrenStart(), + children(), + state(State::Void) { clear (); } @@ -170,8 +170,7 @@ Tree::compareTo (const Tree &tree, bool testChildren) const { // ======================================== void -Tree::checkSpare () const { - Border border; // default = no border +Tree::checkSpare (const Border &border) const { GraphWalker graphWalker (border); vector tiles; vector boundaries; @@ -195,7 +194,7 @@ Tree::checkSpare () const { maxParent = leafParents[leafId]; }); } - DimImg *childCount = (DimImg*)&childrenStart[2]; + // DimImg *childCount = (DimImg*)&childrenStart[2]; // Only used for the assert (so put to comment to prevent warnings) for (unsigned int i = 0; i < tileCount; ++i) { DimImg base = vertexMaxBounds [i], maxParent = maxParents [i]; for (DimImg compId = base; compId < maxParent; ++compId) { @@ -203,7 +202,8 @@ Tree::checkSpare () const { BOOST_ASSERT (compParents[compId] != compId); BOOST_ASSERT (compParents[compId] < maxParent); if (compParents[compId] < compId) - BOOST_ASSERT (childCount[compParents[compId]] > childCount[compId]); + BOOST_ASSERT (childrenStart[2 + compParents[compId]] > childrenStart[2 + compId]); + //BOOST_ASSERT (childCount[compParents[compId]] > childCount[compId]); // Edited line to prevent the "Unused variable" warning } BOOST_ASSERT (compParents[maxParent] == DimImg_MAX); } @@ -228,11 +228,12 @@ Tree::checkSpare () const { } void -Tree::check () const { +Tree::check (const Border& border) const { + GraphWalker graphWalker (border); DimImg compCount = getCompCount (); BOOST_ASSERT (compCount < leafCount); // check parents - forEachLeaf ([this, &compCount] (const DimImg &leafId) { + graphWalker.forEachVertexIdx ([this, &compCount] (const DimImg &leafId) { // XXX si border => leafParents [leafId] == DimImg_MAX BOOST_ASSERT (leafParents[leafId] < compCount); }); @@ -296,8 +297,8 @@ Tree::check () const { BOOST_ASSERT (children[childId-1] < children[childId]); } }); - for (DimImg child = 0; child < nodeCount-1; ++child) - BOOST_ASSERT (childrenMap [child] != DimImg_MAX); + for (DimNodeId child = 0; child < nodeCount-1; ++child) + BOOST_ASSERT (childrenMap [child] != DimImg_MAX || (child < leafCount && border.isBorder (child))); } } @@ -319,10 +320,11 @@ Tree::CPrintTree::print (ostream &out) const { if (!onRecord) out << printMap (&tree.children[0], doubleSize, nodeCount-1) << endl << endl; if (tree.weightBounds.size ()) { - out << "weightBounds: " << endl - << printMap (&tree.weightBounds[0], tree.size, tree.weightBounds.size ()) << endl << endl; + return out << "weightBounds: " << endl + << printMap (&tree.weightBounds[0], tree.size, tree.weightBounds.size ()) << endl << endl; } else return out << "no weightBounds" << endl << endl; + } Tree::CPrintTree diff --git a/src/TreeStats.cpp b/src/TreeStats.cpp index d87397f..1c577fc 100644 --- a/src/TreeStats.cpp +++ b/src/TreeStats.cpp @@ -1,7 +1,5 @@ #include -#include - #include "TreeStats.hpp" using namespace otb::triskele; @@ -16,6 +14,7 @@ static string timeTypeLabels [TimeTypeCard] = { " parents ", " from tiles ", " merge ", + " forest mgt. ", " index ", " compress ", " children ", @@ -46,26 +45,6 @@ TreeStats::reset () { } // ======================================== -using namespace boost::chrono; -inline string -ns2string (double delta) { - ostringstream oss; - duration ns (delta); - oss.fill ('0'); - // typedef duration > days; - // auto d = duration_cast(ns); - // ns -= d; - auto h = duration_cast (ns); - ns -= h; - auto m = duration_cast (ns); - ns -= m; - oss << setw (2) << h.count () << ":" - << setw (2) << m.count () << ":" - << setw (9) << fixed << setprecision (6) << ns.count (); - return oss.str (); -} - -// ---------------------------------------- TreeStats::CPrintDim::CPrintDim (const TreeStats &treeStats) : treeStats (treeStats) { } diff --git a/src/XMLTree/XMLTreeBuilder.cpp b/src/XMLTree/XMLTreeBuilder.cpp index fc0adac..8e4ae75 100644 --- a/src/XMLTree/XMLTreeBuilder.cpp +++ b/src/XMLTree/XMLTreeBuilder.cpp @@ -1,4 +1,4 @@ -<#include "XMLTree/XMLTreeBuilder.hpp" +#include "XMLTree/XMLTreeBuilder.hpp" using namespace otb::triskele; diff --git a/src/apGenerator.cpp b/src/apGenerator.cpp index 7a6f104..6bfdcbe 100644 --- a/src/apGenerator.cpp +++ b/src/apGenerator.cpp @@ -3,6 +3,7 @@ #include "triskeleDebug.hpp" #include "triskeleBase.hpp" +#include "Border.hpp" #include "Appli/Option.hpp" #include "Tree.hpp" #include "TreeStats.hpp" @@ -13,7 +14,6 @@ #include "ArrayTree/triskeleArrayTreeBase.hpp" #include "ArrayTree/triskeleSort.hpp" -#include "ArrayTree/Border.hpp" #include "ArrayTree/GraphWalker.hpp" #include "ArrayTree/Leader.hpp" #include "ArrayTree/Weight.hpp" @@ -31,9 +31,9 @@ using namespace otb::triskele; using namespace otb::triskele::arrayTree; -template +template inline void -writeBand (Option &option, PixelT *pixels, DimChanel band) { +writeBand (Option &option, const GDALDataType &outDataType, OutPixelT *pixels, DimChanel band) { if (!option.oneBand) { option.outputImage.writeBand (pixels, band); return; @@ -44,14 +44,15 @@ writeBand (Option &option, PixelT *pixels, DimChanel band) { ostringstream fileNameStream; fileNameStream << outputBaseName << "-" << std::setfill ('0') << std::setw (3) << (band) << outputExtension; IImage outputImage (fileNameStream.str ()); - outputImage.createImage (option.size, option.inputImage.getDataType (), 1); + outputImage.createImage (option.size, outDataType, 1, option.inputImage, option.topLeft); + outputImage.writeBand (pixels, 0); } -template +template inline -void apGenerator (Option &option) { +void apGenerator (Option &option, const GDALDataType &outDataType, const APFunct &setAP) { vector treeTypes; if (option.minTreeFlag) @@ -66,48 +67,70 @@ void apGenerator (Option &option) { if (!treeTypesCard) cerr << "*** no tree type ! => copy mode" << endl; - Border border (option.size, false); // default = no border + Border border (option.size, option.border); GraphWalker graphWalker (border); DimImg leafCount = graphWalker.vertexMaxCount (); - DimChanel maxThresholds = max (max (option.areaThresholds.size (), option.sdThresholds.size ()), option.moiThresholds.size ()); - vector > allBands (maxThresholds, vector (leafCount, 0)); + DimChanel maxThresholds = max (max (max (option.areaThresholds.size (), option.levelThresholds.size ()), option.sdThresholds.size ()), option.moiThresholds.size ()); + vector > allBands (maxThresholds, vector (leafCount, 0)); - DimChanel outputBandsCard = option.selectedBand.getSet ().size ()*(1+treeTypesCard*(option.areaThresholds.size ()+option.sdThresholds.size ()+option.moiThresholds.size ())); - if (!option.oneBand) - option.outputImage.createImage (option.size, option.inputImage.getDataType (), outputBandsCard); + DimChanel outputBandsCard = option.selectedBand.getSet ().size ()*(1+treeTypesCard*(option.areaThresholds.size ()+option.levelThresholds.size ()+option.sdThresholds.size ()+option.moiThresholds.size ())); + if (!option.oneBand) { + option.outputImage.createImage (option.size, outDataType, outputBandsCard, + option.inputImage, option.topLeft); + } - Raster raster; + Raster raster; + if (option.border) { + DimChanel bandCount (option.inputImage.getBandCount ()); // -1); // XXX sans NDVI + for (DimChanel band = 0; band < bandCount; ++band) { + option.inputImage.readBand (raster, band, option.topLeft, option.size); + for (DimImg idx = 0; idx < leafCount; ++idx) + if (raster.getValue (idx)) + border.clearBorder (idx); + } + //cerr << "XXX border: " << border.borderCount () << endl; + } + DimChanel chanel = 0; for (DimChanel band : option.selectedBand.getSet ()) { option.inputImage.readBand (raster, band, option.topLeft, option.size); - writeBand (option, raster.getPixels (), chanel++); + writeBand (option, outDataType, raster.getPixels (), chanel++); for (TreeType treeType : treeTypes) { - ArrayTreeBuilder atb (raster, graphWalker, treeType, option.countingSortCeil); + ArrayTreeBuilder atb (raster, graphWalker, treeType, option.countingSortCeil); Tree tree (option.coreCount); - WeightAttributes weightAttributes (tree); + WeightAttributes weightAttributes (tree, getDecrFromTreetype (treeType)); atb.buildTree (tree, weightAttributes); - AttributeProfiles attributeProfiles (tree); - atb.setAttributProfiles (attributeProfiles); + AttributeProfiles attributeProfiles (tree); AreaAttributes areaAttributes (tree); + AverageAttributes averageAttributes (tree, raster, areaAttributes); + + setAP (tree, atb, attributeProfiles, raster, averageAttributes, areaAttributes); + + if (option.levelThresholds.size ()) { + vector thresholds (weightAttributes.getConvertedThresholds (option.levelThresholds)); + weightAttributes.cut (allBands, attributeProfiles, thresholds); + for (DimChanel c = 0; c < option.levelThresholds.size (); ++c, ++chanel) + writeBand (option, outDataType, &allBands[c][0], chanel); + } if (option.areaThresholds.size ()) { areaAttributes.cut (allBands, attributeProfiles, option.areaThresholds); for (DimChanel c = 0; c < option.areaThresholds.size (); ++c, ++chanel) - writeBand (option, &allBands[c][0], chanel); + writeBand (option, outDataType, &allBands[c][0], chanel); } if (option.sdThresholds.size ()) { SDAttributes sdAttributes (tree, areaAttributes); sdAttributes.cut (allBands, attributeProfiles, option.sdThresholds); for (DimChanel c = 0; c < option.sdThresholds.size (); ++c, ++chanel) - writeBand (option, &allBands[c][0], chanel); + writeBand (option, outDataType, &allBands[c][0], chanel); } if (option.moiThresholds.size ()) { XYAttributes xyAttributes (tree, areaAttributes); MoIAttributes moiAttributes (tree, areaAttributes, xyAttributes); moiAttributes.cut (allBands, attributeProfiles, option.moiThresholds); for (DimChanel c = 0; c < option.moiThresholds.size (); ++c, ++chanel) - writeBand (option, &allBands[c][0], chanel); + writeBand (option, outDataType, &allBands[c][0], chanel); } } } @@ -117,6 +140,45 @@ void apGenerator (Option &option) { << globalTreeStats.printTime (); } +template +inline +void outTypeSelection (Option &option) { + switch (option.featureType) { + case MEAN: + apGenerator (option, option.inputImage.getDataType (), + [] (Tree &tree, ArrayTreeBuilder &atb, AttributeProfiles &attributeProfiles, Raster &raster, AverageAttributes &averageAttributes, AreaAttributes &areaAttributes) { + attributeProfiles.setValues (raster.getPixels (), averageAttributes.getValues ()); + }); + break; + case AREA: + apGenerator (option, GDT_UInt32, + [] (Tree &tree, ArrayTreeBuilder &atb, AttributeProfiles &attributeProfiles, Raster &raster, AverageAttributes &averageAttributes, AreaAttributes &areaAttributes) { + attributeProfiles.setValues (1, areaAttributes.getValues ()); + }); + break; + case SD: + apGenerator (option, GDT_Float64, + [] (Tree &tree, ArrayTreeBuilder &atb, AttributeProfiles &attributeProfiles, Raster &raster, AverageAttributes &averageAttributes, AreaAttributes &areaAttributes) { + SDAttributes sdAttributes (tree, areaAttributes); + attributeProfiles.setValues (0., sdAttributes.getValues ()); + }); + break; + case MOI: + apGenerator (option, GDT_Float64, + [] (Tree &tree, ArrayTreeBuilder &atb, AttributeProfiles &attributeProfiles, Raster &raster, AverageAttributes &averageAttributes, AreaAttributes &areaAttributes) { + XYAttributes xyAttributes (tree, areaAttributes); + MoIAttributes moiAttributes (tree, areaAttributes, xyAttributes); + attributeProfiles.setValues (0., moiAttributes.getValues ()); + }); + break; + default: + apGenerator (option, option.inputImage.getDataType (), + [] (Tree &tree, ArrayTreeBuilder &atb, AttributeProfiles &attributeProfiles, Raster &raster, AverageAttributes &averageAttributes, AreaAttributes &areaAttributes) { + atb.setAttributProfiles (attributeProfiles); + }); + } +} + int main (int argc, char** argv, char** envp) { Option option (argc, argv); @@ -124,20 +186,19 @@ main (int argc, char** argv, char** envp) { switch (option.inputImage.getDataType ()) { case GDT_Byte: - apGenerator (option); break; - - case GDT_UInt16: - apGenerator (option); break; - case GDT_Int16: - apGenerator (option); break; - case GDT_UInt32: - apGenerator (option); break; - case GDT_Int32: - apGenerator (option); break; - case GDT_Float32: - apGenerator (option); break; - case GDT_Float64: - apGenerator (option); break; + outTypeSelection (option); break; + case GDT_UInt16: + outTypeSelection (option); break; + case GDT_Int16: + outTypeSelection (option); break; + case GDT_UInt32: + outTypeSelection (option); break; + case GDT_Int32: + outTypeSelection (option); break; + case GDT_Float32: + outTypeSelection (option); break; + case GDT_Float64: + outTypeSelection (option); break; default : cerr << "unknown type!" << endl; break; diff --git a/test/TestDeal.cpp b/test/TestDeal.cpp new file mode 100644 index 0000000..36496a6 --- /dev/null +++ b/test/TestDeal.cpp @@ -0,0 +1,91 @@ +// faire test 10000 + lamba + 1...coreCount +#include +#include + +#include "triskeleDealThreads.hpp" +#include "TestThread.hpp" + +using namespace std; +using namespace boost::chrono; +using namespace triskele; +using namespace otb; +using namespace otb::triskele; + +inline void +fDirect (const DimImg &nbItem, const vector &global) { + DimImg sum = 0; + for (DimImg x = 0; x < nbItem; ++x) + sum += global[x]; +} + +template +inline void +fLambda (DimImg &nbItem, const FunctId &functId/* functId (id) */) { + for (DimImg x = 0; x < nbItem; ++x) + functId (x); +} + +template +inline void +fThread (double &inDuration, const DimImg &nbItem, const FunctId &functId/* functId (id) */) { +#if INTEL_TBB_THREAD + using namespace tbb; +#pragma warning(disable: 588) + parallel_for (size_t (0), size_t (1), [&nbItem, &functId] (size_t idCopyValInThread) { + auto start = high_resolution_clock::now (); + for (DimImg x = 0; x < nbItem; ++x) + functId (x); + auto end = high_resolution_clock::now (); + inDuration = duration_cast > (end-start).count (); + }); +#else /* BOOST thread */ + std::vector tasks; + for (unsigned int idCopyValInThread = 0; idCopyValInThread < 1; ++idCopyValInThread) { + tasks.push_back (boost::thread ([/*no ref!!!*/idCopyValInThread, &nbItem, &functId, &inDuration] () { + auto start = high_resolution_clock::now (); + for (DimImg x = 0; x < nbItem; ++x) + functId (x); + auto end = high_resolution_clock::now (); + inDuration += duration_cast > (end-start).count (); + })); + } + for (unsigned int i = 0; i < 1; ++i) + tasks[i].join (); +#endif +} + +void +TestThread::testDeal () { + + DimImg nbItem = global.size (); + double inDuration = 0; + // XXX direct + auto startDirect = high_resolution_clock::now (); + fDirect (nbItem, global); + + // XXX lambda + auto startLamba = high_resolution_clock::now (); + DimImg sum = 0; + fLambda (nbItem, [this, &sum] (const DimImg &x) { + sum += global [x]; + }); + + // XXX thread + auto startThread = high_resolution_clock::now (); + sum = 0; + fThread (inDuration, nbItem, [this, &sum] (const DimImg &x) { + sum += global [x]; + }); + + // XXX n direct + + // XXX n lambda + + // XXX n thread + + auto end = high_resolution_clock::now (); + addTime (directDealStats, duration_cast > (startLamba-startDirect).count ()); + addTime (lambdaDealStats, duration_cast > (startThread-startLamba).count ()); + addTime (threadDealStats, duration_cast > (end-startThread).count ()); + addTime (inThreadDealStats, inDuration); +} diff --git a/test/TestThread.cpp b/test/TestThread.cpp new file mode 100644 index 0000000..af481de --- /dev/null +++ b/test/TestThread.cpp @@ -0,0 +1,222 @@ +#include +#include +#include + +#include "triskeleDealThreads.hpp" +#include "TestThread.hpp" + +using namespace std; +using namespace boost::chrono; +using namespace triskele; +using namespace otb; +using namespace otb::triskele; + +static string timeTypeLabels [TimeTypeCard] = { + "directDeal", + "lambdaDeal", + "threadDeal", + "inThreadDeal", + + + "initStats", + "seqReadStats", + "parReadStats", + "seqWriteStats", + "parWriteStats", + "seqRWStats", + "parRWStats" +}; + +const unsigned int +TestThread::maxCoreCount = boost::thread::hardware_concurrency (); + +// ======================================== +inline string +TestThread::ns2string (double delta) { + ostringstream oss; + duration ns (delta); + oss.fill ('0'); + // typedef duration > days; + // auto d = duration_cast(ns); + // ns -= d; + auto h = duration_cast (ns); + ns -= h; + auto m = duration_cast (ns); + ns -= m; + oss << setw (2) << h.count () << ":" + << setw (2) << m.count () << ":" + << setw (9) << fixed << setprecision (6) << ns.count (); + return oss.str (); +} + +// ======================================== +template +inline void +nodealThreadRange (const DimImg &maxId, const unsigned int &coreCount, const FunctId &functId/* functId (id) */) { + nodealThread (maxId, coreCount, [&functId] (const unsigned int &threadId, const DimImg &minVal, const DimImg &maxVal) { + for (DimImg id = minVal; id < maxVal; ++id) + functId (id); + }); +} + +// ---------------------------------------- +template +inline void +nodealThreadThreadRange (const DimImg &maxId, const unsigned int &coreCount, const FunctThreadId &functThreadId/* functThreadId (threadId, id) */) { + nodealThread (maxId, coreCount, [&functThreadId] (const unsigned int &threadId, const DimImg &minVal, const DimImg &maxVal) { + for (DimImg id = minVal; id < maxVal; ++id) + functThreadId (threadId, id); + }); +} + +// ---------------------------------------- +template +inline void +nodealThread (const DimImg &maxId, unsigned int coreCount, const FunctThreadMinMax &functThreadMinMax/* functThreadMinMax (threadId, minVal, maxVal) */) { + //DEF_LOG ("dealThreadBound", "coreCount:" << coreCount << " maxId:" << maxId); + if (!maxId || !coreCount) + return; + if (DimImg (coreCount) > maxId) + coreCount = (unsigned int) maxId; + if (coreCount == 1) { + functThreadMinMax (0, 0, maxId); + return; + } + + std::vector maxIds = getDealThreadBounds (maxId, coreCount); + for (unsigned int idCopyValInThread = 0; idCopyValInThread < coreCount; ++idCopyValInThread) { + functThreadMinMax (idCopyValInThread, maxIds[idCopyValInThread], maxIds[idCopyValInThread+1]); + } +} + +// ======================================== +TestThread::TestThread (const unsigned int &coreCount) + : coreCount (coreCount), + global (nbItem*coreCount, 0) +{ +} + +ostream & +TestThread::print (ostream &out, const AlgoStat stats[]) { + out << endl + << setw (16) << left << "Time" << "\t" + << setw (15) << left << "Sum" << "\t" + << setw (3) << left << "Count" << "\t" + << setw (15) << left << "Mean" << "\t" + << setw (15) << left << "Min" << "\t" + << setw (15) << left << "Max" << endl; + for (unsigned int i = 0; i < TimeTypeCard; ++i) { + if (!ba::count (stats[i])) + continue; + out << setw (16) << right << timeTypeLabels[i] << "\t" + << ns2string (ba::sum (stats[i])) << "\t" << setw (3) << ba::count (stats[i]) << "\t" + << ns2string (ba::mean (stats[i])) << "\t" + << ns2string (ba::min (stats[i])) << "\t" + << ns2string (ba::max (stats[i])) + << endl << flush; + } + return out; +} + +template +void +TestThread::fillVector (vector &vect) { + for (size_t i = 0; i < vect.size (); ++i) + vect[i] = (T) std::rand (); +} + +// show algin + + +void +TestThread::multiTest () { + for (int i = 0; i < 100; ++i) { + vector sumSeq (coreCount, 0); + vector sumPar (coreCount, 0); + + auto start = high_resolution_clock::now (); + fillVector (global); + + // lecture seq => faire somme + auto startSeqRead = high_resolution_clock::now (); + nodealThreadThreadRange (nbItem, coreCount, [this, &sumSeq] (const unsigned int &threadId, const DimImg &item) { + sumSeq[threadId] += global[item]; + }); + + // lecture // => faire somme + auto startParRead = high_resolution_clock::now (); + dealThreadThreadRange (nbItem, coreCount, [this, &sumPar] (const unsigned int &threadId, const DimImg &item) { + sumPar[threadId] += global[item]; + }); + // XXX vérifier égalité de sumSeq sumPar + + // écriture seq => écrire idx + // écriture // => écrire idx + + // lecture/écriture seq => écrire x/2 + // lecture/écriture // => écrire x/2 + + auto end = high_resolution_clock::now (); + addTime (initStats, duration_cast > (startSeqRead-start).count ()); + addTime (seqReadStats, duration_cast > (startParRead-startSeqRead).count ()); + addTime (parReadStats, duration_cast > (end-startParRead).count ()); + } + print (cout, timeStats); +} + +// ======================================== +int +main (int argc, char** argv) { + cout << "start test" << endl; + srand (time (NULL)); + + TestThread tt; + //tt.multiTest (); + for (int i = 0; i < 100; ++i) + tt.testDeal (); + tt.print (cout, tt.timeStats); + + return 0; +} + +// namespace utils { + +// inline size_t alignSize(size_t size, size_t alignment) { +// return (size+alignment-1)&~(alignment-1); +// } + +// template +// inline T * alignPtr(T * ptr, uintptr_t alignment) { +// union { +// T *p; +// uintptr_t u; +// } u; +// u.p = ptr; +// u.u = (u.u+alignment-1)&~(alignment-1); +// return u.p; +// } + +// }//namespace utils +// void init (Index c, Data const &d) { +// if (count != c) { +// kill (); +// count = c; +// size_t const alignment = 64; +// size_t size = alignment-1 +// + utils::alignSize (count*sizeof (Index), alignment) +// + utils::alignSize (count*sizeof (Rank ), alignment) +// + utils::alignSize (count*sizeof (Data ), alignment); +// //memory.reset (new char[size]); +// delete [] memory; +// memory = nullptr; +// memory = new char[size]; + +// char *ptr = utils::alignPtr (memory, alignment); +// parents = reinterpret_cast (ptr); +// ptr += utils::alignSize (count*sizeof (Index), alignment); +// ranks = reinterpret_cast (ptr); +// ptr += utils::alignSize (count*sizeof (Rank ), alignment); +// datas = reinterpret_cast (ptr); +// } +// reset (d); +// } diff --git a/test/TestThread.hpp b/test/TestThread.hpp new file mode 100644 index 0000000..8634636 --- /dev/null +++ b/test/TestThread.hpp @@ -0,0 +1,80 @@ +// OK faire une classe +// OK changer coreCount en maxCoreCount +// faire test 10000 + lamba + 1...coreCount +// découpe fichier TestThread.cpp +// calcul alignement +// lecture seq => faire somme +// lecture // => faire somme + +// écriture seq => écrire idx +// écriture // => écrire idx + +// lecture/écriture seq => écrire x/2 +// lecture/écriture // => écrire x/2 + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace otb { + namespace triskele { + using namespace std; + namespace ba = boost::accumulators; + typedef ba::accumulator_set > AlgoStat; + enum TimeType { + directDealStats, + lambdaDealStats, + threadDealStats, + inThreadDealStats, + + initStats, + seqReadStats, + parReadStats, + seqWriteStats, + parWriteStats, + seqRWStats, + parRWStats, + + TimeTypeCard + }; + typedef uint32_t DimImg; + + class TestThread { + public: + + static const unsigned int maxCoreCount; + unsigned int coreCount; + AlgoStat timeStats[TimeTypeCard]; + size_t nbItem = 1000000; + // XXX vérifier l'alignement vector + vector global; + + TestThread (const unsigned int &coreCount = maxCoreCount); + // XXX en commun + static inline string ns2string (double delta); + inline void addTime (const TimeType &timeType, const double &duration) { + timeStats[timeType] (duration); + } + ostream &print (ostream &out, const AlgoStat stats[]); + // XXX déclarer nodealThread + + template + void fillVector (vector &vect); + void multiTest (); + + void testDeal (); + }; + } +}