diff --git a/find-object/.appveyor.yml b/find-object/.appveyor.yml deleted file mode 100644 index bad8627c..00000000 --- a/find-object/.appveyor.yml +++ /dev/null @@ -1,55 +0,0 @@ - -branches: - only: - - master - - devel - -os: Visual Studio 2015 - -clone_folder: c:\projects\find-object - -platform: x64 -configuration: Release - -init: - - cmake --version - - call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 - - call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64 - -install: - # Qt - - set QTDIR=C:\Qt\5.10.1\msvc2015_64 - # make sure Qt bin path is before cmake bin path to avoid copying qt5 dlls from cmake before qt installation - - set PATH=%QTDIR%\bin;%PATH% - # OpenCV - - ps: wget 'https://dl.dropboxusercontent.com/s/o6ofn491bc0jso1/opencv450_vc14.exe?dl=0' -outfile opencv.exe - - cmd: opencv.exe -o"C:\Program Files" -y - - ECHO "Installed OpenCV:" - - ps: "ls \"C:/Program Files/opencv\"" - - set PATH=%PATH%;C:\Program Files\opencv\x64\vc14\bin - # zlib - - ps: wget 'https://docs.google.com/uc?authuser=0&id=0B46akLGdg-uaYm9MTTI4MUtUcmc&export=download' -outfile zlib-1.2.8-vc2010-x64.zip - - ps: Expand-Archive zlib-1.2.8-vc2010-x64.zip -DestinationPath 'C:\Program Files' - - ECHO "Installed zlib:" - - ps: "ls \"C:/Program Files/zlib\"" - - set PATH=%PATH%;C:\Program Files\zlib\bin - -before_build: - - cd c:\projects\find-object\build - - ECHO %PROGRAMFILES% - - ECHO %PATH% - - cmake -G "Visual Studio 14 2015 Win64" -DOpenCV_DIR="C:\Program Files\opencv\build" .. - -after_build : - - cmake --build . --config Release --target package - -artifacts: - - path: build\Find-Object-* - -notifications: - - provider: Email - to: - - matlabbe@email.com - on_build_success: false - on_build_failure: false - on_build_status_changed: true diff --git a/find-object/.cproject b/find-object/.cproject deleted file mode 100644 index 25e2e9bc..00000000 --- a/find-object/.cproject +++ /dev/null @@ -1,221 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cmake - -E chdir build/ cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE=Debug ../ - - true - false - true - - - cmake - -E chdir build/ cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE=Release ../ - - true - false - true - - - cmake - -E chdir build/ cmake -G "Unix Makefiles" -D CMAKE_BUILD_TYPE=Debug ../ - - true - false - true - - - cmake - -E chdir build/ cmake -G "Unix Makefiles" -D CMAKE_BUILD_TYPE=Release ../ - - true - false - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cmake - -E chdir build/ cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE=Debug ../ - - true - false - true - - - cmake - -E chdir build/ cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE=Release ../ - - true - false - true - - - cmake - -E chdir build/ cmake -G "Unix Makefiles" -D CMAKE_BUILD_TYPE=Debug ../ - - true - false - true - - - cmake - -E chdir build/ cmake -G "Unix Makefiles" -D CMAKE_BUILD_TYPE=Release ../ - - true - false - true - - - - - - - - - - - - cmake - -E chdir build/ cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE=Debug ../ - - true - false - true - - - cmake - -E chdir build/ cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE=Release ../ - - true - false - true - - - cmake - -E chdir build/ cmake -G "Unix Makefiles" -D CMAKE_BUILD_TYPE=Debug ../ - - true - false - true - - - cmake - -E chdir build/ cmake -G "Unix Makefiles" -D CMAKE_BUILD_TYPE=Release ../ - - true - false - true - - - - - - - - - - - - - - - - - - - - - - - diff --git a/find-object/.github/workflows/cmake.yml b/find-object/.github/workflows/cmake.yml deleted file mode 100644 index 273581a1..00000000 --- a/find-object/.github/workflows/cmake.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: CMake - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -env: - BUILD_TYPE: Release - -jobs: - build: - name: ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-22.04, ubuntu-20.04, ubuntu-18.04] - - steps: - - name: Install dependencies - run: | - DEBIAN_FRONTEND=noninteractive - sudo apt-get update - sudo apt-get -y install libopencv-dev qtbase5-dev git cmake software-properties-common - - - uses: actions/checkout@v2 - - - name: Configure CMake - run: | - cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} - - - name: Build - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - - diff --git a/find-object/.github/workflows/ros1.yml b/find-object/.github/workflows/ros1.yml deleted file mode 100644 index bcc9713f..00000000 --- a/find-object/.github/workflows/ros1.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: ros1 - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -env: - # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) - BUILD_TYPE: Release - -jobs: - build: - # The CMake configure and build commands are platform agnostic and should work equally - # well on Windows or Mac. You can convert this to a matrix build if you need - # cross-platform coverage. - # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix - name: Build on ros ${{ matrix.ros_distro }} and ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-20.04, ubuntu-18.04] - include: - - os: ubuntu-20.04 - ros_distro: 'noetic' - - os: ubuntu-18.04 - ros_distro: 'melodic' - - steps: - - uses: ros-tooling/setup-ros@v0.2 - with: - required-ros-distributions: ${{ matrix.ros_distro }} - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get -y install ros-${{ matrix.ros_distro }}-cv-bridge qtbase5-dev - - - name: Setup catkin workspace - run: | - source /opt/ros/${{ matrix.ros_distro }}/setup.bash - mkdir -p ${{github.workspace}}/catkin_ws/src - cd ${{github.workspace}}/catkin_ws/src - catkin_init_workspace - cd .. - catkin_make - - - uses: actions/checkout@v2 - with: - path: 'catkin_ws/src/find_object_2d' - - - name: caktkin_make - run: | - source /opt/ros/${{ matrix.ros_distro }}/setup.bash - source ${{github.workspace}}/catkin_ws/devel/setup.bash - cd ${{github.workspace}}/catkin_ws - catkin_make -DSETUPTOOLS_DEB_LAYOUT=OFF - catkin_make install diff --git a/find-object/.github/workflows/ros2.yml b/find-object/.github/workflows/ros2.yml deleted file mode 100644 index 364bebb7..00000000 --- a/find-object/.github/workflows/ros2.yml +++ /dev/null @@ -1,58 +0,0 @@ - -name: ros2 - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -env: - # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) - BUILD_TYPE: Release - -jobs: - build: - # The CMake configure and build commands are platform agnostic and should work equally - # well on Windows or Mac. You can convert this to a matrix build if you need - # cross-platform coverage. - # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix - name: Build on ros2 ${{ matrix.ros_distro }} and ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - matrix: - ros_distro: [foxy, galactic, humble] - include: - - ros_distro: 'foxy' - os: ubuntu-20.04 - - ros_distro: 'galactic' - os: ubuntu-20.04 - - ros_distro: 'humble' - os: ubuntu-22.04 - - steps: - - uses: ros-tooling/setup-ros@v0.4 - with: - required-ros-distributions: ${{ matrix.ros_distro }} - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get -y install ros-${{ matrix.ros_distro }}-cv-bridge qtbase5-dev - - - name: Setup ros2 workspace - run: | - source /opt/ros/${{ matrix.ros_distro }}/setup.bash - mkdir -p ${{github.workspace}}/ros2_ws/src - cd ${{github.workspace}}/ros2_ws - colcon build - - - uses: actions/checkout@v2 - with: - path: 'ros2_ws/src/find_object_2d' - - - name: colcon build - run: | - source /opt/ros/${{ matrix.ros_distro }}/setup.bash - cd ${{github.workspace}}/ros2_ws - colcon build --event-handlers console_direct+ diff --git a/find-object/.project b/find-object/.project deleted file mode 100644 index 8c1ffa4b..00000000 --- a/find-object/.project +++ /dev/null @@ -1,79 +0,0 @@ - - - find_object - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - ?name? - - - - org.eclipse.cdt.make.core.append_environment - true - - - org.eclipse.cdt.make.core.autoBuildTarget - all - - - org.eclipse.cdt.make.core.buildArguments - -C ${ProjDirPath}/build VERBOSE=true - - - org.eclipse.cdt.make.core.buildCommand - make - - - org.eclipse.cdt.make.core.cleanBuildTarget - clean - - - org.eclipse.cdt.make.core.contents - org.eclipse.cdt.make.core.activeConfigSettings - - - org.eclipse.cdt.make.core.enableAutoBuild - false - - - org.eclipse.cdt.make.core.enableCleanBuild - true - - - org.eclipse.cdt.make.core.enableFullBuild - true - - - org.eclipse.cdt.make.core.fullBuildTarget - all - - - org.eclipse.cdt.make.core.stopOnError - true - - - org.eclipse.cdt.make.core.useDefaultBuildCmd - false - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/find-object/.travis.yml b/find-object/.travis.yml deleted file mode 100644 index 3472067a..00000000 --- a/find-object/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -sudo: true -dist: trusty -language: cpp - -compiler: - - gcc - - clang - -addons: - apt: - packages: - - cmake - - libopencv-dev - - libqt4-dev - -script: - - mkdir -p build && cd build - - cmake .. - - make - -notifications: - email: false diff --git a/find-object/CMakeLists.txt b/find-object/CMakeLists.txt deleted file mode 100644 index aee50230..00000000 --- a/find-object/CMakeLists.txt +++ /dev/null @@ -1,472 +0,0 @@ -cmake_minimum_required(VERSION 3.5) - -SET(CATKIN_BUILD FALSE) -SET(COLCON_BUILD FALSE) - -# Detect if it is called by catkin (ros1) -IF(CATKIN_TOPLEVEL OR CATKIN_BUILD_BINARY_PACKAGE OR CATKIN_SKIP_TESTING OR CATKIN_ENABLE_TESTING OR CATKIN_DEVEL_PREFIX) - SET(CATKIN_BUILD TRUE) -ELSE() - # Detect if it is called by colcon (ros2) - IF(DEFINED AMENT_PREFIX_PATH) # buildfarm - SET(COLCON_BUILD TRUE) - ELSE() # colcon local build in ros2_ws - string(FIND ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR} POS) - IF(${POS} EQUAL -1) - SET(COLCON_BUILD TRUE) - ENDIF() - ENDIF() -ENDIF() - -MESSAGE(STATUS "CATKIN_BUILD=${CATKIN_BUILD}") -MESSAGE(STATUS "COLCON_BUILD=${COLCON_BUILD}") -SET(ROS_BUILD FALSE) -IF(CATKIN_BUILD OR COLCON_BUILD) - SET(ROS_BUILD TRUE) -ENDIF() - -IF(NOT ROS_BUILD) - #Standalone build - PROJECT( Find-Object ) -ELSE() - #ROS build - PROJECT( find_object_2d ) - MESSAGE(STATUS "ROS_DISTRO=$ENV{ROS_DISTRO}") -ENDIF() - -# Catkin doesn't support multiarch library path, -# fix to "lib" if not set by user. -IF(NOT DEFINED CMAKE_INSTALL_LIBDIR) - set(CMAKE_INSTALL_LIBDIR "lib") -ENDIF(NOT DEFINED CMAKE_INSTALL_LIBDIR) - -INCLUDE(GNUInstallDirs) - -####### local cmake modules ####### -SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules") - -# Policy CMP0043 introduced in cmake version 3.0 IGNORES the use of COMPILE_DEFINITIONS suffixed variables, e.g. COMPILE_DEFINITIONS_DEBUG -# Set to OLD behavior until minimum cmake version >= 2.8.10 (version that COMPILE_DEFINITIONS can be set by generator expressions instead) -if (POLICY CMP0043) - cmake_policy(SET CMP0043 OLD) -endif (POLICY CMP0043) -# Policy CMP0042 introduced in cmake version 3.0 enables the use of @rpath in an install name via MACOSX_RPATH by default -# Set to OLD behavior so that all versions use the same behavior, or until minimum cmake version >= 2.8.12 (version where @rpath is available) -if (POLICY CMP0042) - cmake_policy(SET CMP0042 OLD) -endif (POLICY CMP0042) - -####################### -# VERSION -####################### -SET(PROJECT_VERSION "0.7.0") -SET(PROJECT_PREFIX find_object) - -STRING(REGEX MATCHALL "[0-9]" PROJECT_VERSION_PARTS "${PROJECT_VERSION}") -LIST(GET PROJECT_VERSION_PARTS 0 PROJECT_VERSION_MAJOR) -LIST(GET PROJECT_VERSION_PARTS 1 PROJECT_VERSION_MINOR) -LIST(GET PROJECT_VERSION_PARTS 2 PROJECT_VERSION_PATCH) - -ADD_DEFINITIONS(-DPROJECT_PREFIX="${PROJECT_PREFIX}") -ADD_DEFINITIONS(-DPROJECT_VERSION="${PROJECT_VERSION}") -ADD_DEFINITIONS(-DPROJECT_NAME="${PROJECT_NAME}") - -####### DEPENDENCIES ####### -FIND_PACKAGE(OpenCV REQUIRED) # tested on 2.3.1 - -# check if version status is "-dev" (SIFT compatibility issue between 4.3.0 vs 4.3.0-dev) -FIND_FILE(OpenCV_VERSION_HPP opencv2/core/version.hpp - PATHS ${OpenCV_INCLUDE_DIRS} - NO_DEFAULT_PATH) -FILE(READ ${OpenCV_VERSION_HPP} TMPTXT) -STRING(FIND "${TMPTXT}" "-dev" matchres) -IF(NOT ${matchres} EQUAL -1) - add_definitions(-DOPENCV_DEV) -ENDIF(NOT ${matchres} EQUAL -1) - -# For SuperPoint -SET(TORCH 0) -FIND_PACKAGE(Torch QUIET) -IF(TORCH_FOUND) - MESSAGE(STATUS "Found Torch: ${TORCH_INCLUDE_DIRS}") - SET(TORCH 1) -ENDIF(TORCH_FOUND) - -IF(NOT MSVC) - IF(TORCH_FOUND) - include(CheckCXXCompilerFlag) - CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14) - IF(COMPILER_SUPPORTS_CXX14) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") - set(CMAKE_CXX_STANDARD 14) - ELSE() - message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++14 support. Please use a different C++ compiler if you want to use Torch.") - ENDIF() - ENDIF(TORCH_FOUND) - - IF( NOT CMAKE_CXX_STANDARD AND OpenCV_VERSION_MAJOR EQUAL 4) - #Newest versions require std11 - include(CheckCXXCompilerFlag) - CHECK_CXX_COMPILER_FLAG("-std=c++17" COMPILER_SUPPORTS_CXX17) - CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) - CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) - IF(COMPILER_SUPPORTS_CXX17) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") - ELSEIF(COMPILER_SUPPORTS_CXX11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - ELSEIF(COMPILER_SUPPORTS_CXX0X) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") - ELSE() - message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") - ENDIF() - ENDIF() -ENDIF() - -# look for Qt5 before Qt4 -FIND_PACKAGE(Qt5 COMPONENTS Widgets Core Gui Network QUIET) -IF(NOT Qt5_FOUND) - FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED) -ENDIF(NOT Qt5_FOUND) -ADD_DEFINITIONS(-DQT_NO_KEYWORDS) # To avoid conflicts with boost signals used in ROS - -FIND_PACKAGE(Tcmalloc QUIET) - -FIND_PACKAGE(ZLIB REQUIRED QUIET) - -SET(NONFREE 1) -IF(NOT (OPENCV_NONFREE_FOUND OR OPENCV_XFEATURES2D_FOUND)) - SET(NONFREE 0) -ELSEIF(OpenCV_VERSION VERSION_GREATER "3.4.2") - FIND_FILE(OpenCV_MODULES_HPP opencv2/opencv_modules.hpp - PATHS ${OpenCV_INCLUDE_DIRS} - NO_DEFAULT_PATH) - FILE(READ ${OpenCV_MODULES_HPP} TMPTXT) - STRING(FIND "${TMPTXT}" "#define OPENCV_ENABLE_NONFREE" matchres) - IF(${matchres} EQUAL -1) - SET(NONFREE 0) - ENDIF(${matchres} EQUAL -1) -ENDIF() - -CONFIGURE_FILE(Version.h.in ${PROJECT_SOURCE_DIR}/include/${PROJECT_PREFIX}/Version.h) - -IF(NOT ROS_BUILD) - #Standalone build - IF(WIN32 AND NOT MINGW) - ADD_DEFINITIONS("-wd4251") - ELSE () - ADD_DEFINITIONS( "-Wall" ) - ENDIF() - #ADD_DEFINITIONS("-DUNICODE") # to test with UNICODE projects - - ####### COMPILATION PARAMS ####### - # In case of Makefiles if the user does not setup CMAKE_BUILD_TYPE, assume it's Release: - IF(${CMAKE_GENERATOR} MATCHES ".*Makefiles") - IF("${CMAKE_BUILD_TYPE}" STREQUAL "") - set(CMAKE_BUILD_TYPE Release) - ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") - ENDIF(${CMAKE_GENERATOR} MATCHES ".*Makefiles") - - SET(CMAKE_DEBUG_POSTFIX "d") - - ####### Build libraries as shared or static ####### - OPTION( BUILD_SHARED_LIBS "Set to OFF to build static libraries" ON ) - - ####### OUTPUT DIR ####### - SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin) - SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin) - SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib) - - ####### INSTALL DIR ####### - # Offer the user the choice of overriding the installation directories - set(INSTALL_INCLUDE_DIR include/${PROJECT_PREFIX}-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} CACHE PATH - "Installation directory for header files") - if(WIN32 AND NOT CYGWIN) - set(DEF_INSTALL_CMAKE_DIR CMake) - else() - set(DEF_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/${PROJECT_PREFIX}-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}) - endif() - set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH - "Installation directory for CMake files") - - - ####### OSX BUNDLE CMAKE_INSTALL_PREFIX ####### - IF(APPLE) - OPTION(BUILD_AS_BUNDLE "Set to ON to build as bundle (DragNDrop)" OFF) - ENDIF(APPLE) - IF(APPLE AND BUILD_AS_BUNDLE) - # Required when packaging, and set CMAKE_INSTALL_PREFIX to "/". - SET(CPACK_SET_DESTDIR TRUE) - - SET(CMAKE_BUNDLE_NAME - "${PROJECT_NAME}") - SET(CMAKE_BUNDLE_LOCATION "/") - - # make sure CMAKE_INSTALL_PREFIX ends in / - SET(CMAKE_INSTALL_PREFIX - "/${CMAKE_BUNDLE_NAME}.app/Contents") - ENDIF(APPLE AND BUILD_AS_BUNDLE) - - ####### SOURCES (Projects) ####### - ADD_SUBDIRECTORY( src ) - ADD_SUBDIRECTORY( app ) - ADD_SUBDIRECTORY( tools ) - IF(NONFREE OR OpenCV_VERSION VERSION_GREATER "4.2.0") # SIFT is free from 4.3.0 - ADD_SUBDIRECTORY( example ) - ENDIF(NONFREE OR OpenCV_VERSION VERSION_GREATER "4.2.0") - - ####################### - # Uninstall target, for "make uninstall" - ####################### - CONFIGURE_FILE( - "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" - IMMEDIATE @ONLY) - - ADD_CUSTOM_TARGET(uninstall - "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") - - ####################### - # Setup FindObjectConfig.cmake - ####################### - # Create the FindObjectConfig.cmake and FindObjectConfigVersion files - file(RELATIVE_PATH REL_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR}" "${CMAKE_INSTALL_PREFIX}/${INSTALL_INCLUDE_DIR}") - file(RELATIVE_PATH REL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR}" "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") - - # ... for the build tree - set(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/include") - set(CONF_LIB_DIR "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}") - configure_file(FindObjectConfig.cmake.in - "${PROJECT_BINARY_DIR}/FindObjectConfig.cmake" @ONLY) - - # ... for the install tree - set(CONF_INCLUDE_DIRS "\${FindObject_CMAKE_DIR}/${REL_INCLUDE_DIR}") - set(CONF_LIB_DIR "\${FindObject_CMAKE_DIR}/${REL_LIB_DIR}") - configure_file(FindObjectConfig.cmake.in - "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindObjectConfig.cmake" @ONLY) - - # ... for both - configure_file(FindObjectConfigVersion.cmake.in - "${PROJECT_BINARY_DIR}/FindObjectConfigVersion.cmake" @ONLY) - - # Install the FindObjectConfig.cmake and FindObjectConfigVersion.cmake - install(FILES - "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindObjectConfig.cmake" - "${PROJECT_BINARY_DIR}/FindObjectConfigVersion.cmake" - DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT devel) - #### - - ####################### - # CPACK (Packaging) - ####################### - INCLUDE(InstallRequiredSystemLibraries) - - SET(CPACK_PACKAGE_NAME "${PROJECT_NAME}") - SET(CPACK_PACKAGE_VENDOR "${PROJECT_NAME} project") - SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Find-Object") - SET(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}") - SET(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}") - SET(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}") - SET(CPACK_PACKAGE_CONTACT "matlabbe@gmail.com") - - set(CPACK_SOURCE_IGNORE_FILES - "\\\\.svn/" - "${PROJECT_SOURCE_DIR}/build/[a-zA-Z0-9_]+" - "~$" - "${PROJECT_SOURCE_DIR}/bin/.*${PROJECT_PREFIX}" - "${PROJECT_SOURCE_DIR}/bin/.*${PROJECT_NAME}" - "\\\\.DS_Store" - ) - - IF(WIN32) - SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE") - IF(CMAKE_CL_64) - SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64") - ELSE() - SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES") - ENDIF() - SET(CPACK_GENERATOR "ZIP;NSIS") - SET(CPACK_SOURCE_GENERATOR "ZIP") - SET(CPACK_NSIS_PACKAGE_NAME "${PROJECT_NAME}") - SET(ICON_PATH "${PROJECT_SOURCE_DIR}/app/${PROJECT_NAME}.ico") - SET(CPACK_NSIS_MUI_ICON ${ICON_PATH}) - SET(CPACK_NSIS_MUI_UNIICON ${ICON_PATH}) - SET(CPACK_NSIS_DISPLAY_NAME "${PROJECT_NAME}") - SET(CPACK_NSIS_CONTACT ${CPACK_PACKAGE_CONTACT}) - # Set the icon used for the Windows "Add or Remove Programs" tool. - SET(CPACK_NSIS_INSTALLED_ICON_NAME bin\\\\${PROJECT_NAME}.exe) - SET(CPACK_PACKAGE_EXECUTABLES "${PROJECT_NAME}" "${PROJECT_NAME}" ${CPACK_PACKAGE_EXECUTABLES}) - SET(CPACK_CREATE_DESKTOP_LINKS "${PROJECT_NAME}" ${CPACK_CREATE_DESKTOP_LINKS}) - SET(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}") - ELSEIF(APPLE) - IF(BUILD_AS_BUNDLE) - # On APPLE and if BUILD_AS_BUNDLE=ON, the project is created as a bundle - # over the main app (see ./src).Here we package only this bundle. Note - # that we set CMAKE_INSTALL_PREFIX to "/" when packaging to DragNDrop... - SET(CPACK_GENERATOR "DragNDrop") - ELSE() - SET(CPACK_GENERATOR "PackageMaker;TBZ2") - ENDIF() - - SET(CPACK_SOURCE_GENERATOR "TBZ2") - - SET(CPACK_PACKAGE_ICON "${PROJECT_SOURCE_DIR}/app/${PROJECT_NAME}.icns") - ELSE() - SET(CPACK_SOURCE_GENERATOR "ZIP") - ENDIF() - - INCLUDE(CPack) - - ####################### - # OUTPUT INFO - ####################### - MESSAGE(STATUS "--------------------------------------------") - MESSAGE(STATUS "Info :") - MESSAGE(STATUS " CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}") - MESSAGE(STATUS " CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}") - MESSAGE(STATUS " PROJECT_VERSION = ${PROJECT_VERSION}") - - IF(OpenCV_VERSION_MAJOR EQUAL 2) - IF(OPENCV_NONFREE_FOUND) - MESSAGE(STATUS " With OpenCV 2 nonfree module (SIFT/SURF) = YES") - ELSE() - MESSAGE(STATUS " With OpenCV 2 nonfree module (SIFT/SURF) = NO (not found)") - ENDIF() - ELSE() - IF(OPENCV_XFEATURES2D_FOUND) - MESSAGE(STATUS " With OpenCV ${OpenCV_VERSION} xfeatures2d module (BRIEF/FREAK/KAZE) = YES") - ELSE() - MESSAGE(STATUS " With OpenCV ${OpenCV_VERSION} xfeatures2d module (BRIEF/FREAK/KAZE) = NO (not found)") - ENDIF() - IF(OpenCV_VERSION VERSION_GREATER "4.2.0") - IF(NONFREE) - MESSAGE(STATUS " With OpenCV ${OpenCV_VERSION} nonfree module (SURF) = YES") - ELSE() - MESSAGE(STATUS " With OpenCV ${OpenCV_VERSION} nonfree module (SURF) = NO") - ENDIF() - ELSEIF() - IF(NONFREE) - MESSAGE(STATUS " With OpenCV ${OpenCV_VERSION} nonfree module (SIFT/SURF) = YES") - ELSE() - MESSAGE(STATUS " With OpenCV ${OpenCV_VERSION} nonfree module (SIFT/SURF) = NO") - ENDIF() - ENDIF() - ENDIF() - - IF(QT4_FOUND) - MESSAGE(STATUS " With Qt4 = YES") - ELSEIF(Qt5_FOUND) - MESSAGE(STATUS " With Qt5 = YES") - ELSE() - MESSAGE(STATUS " With Qt = NO (Qt not found)") - ENDIF() - - IF(Tcmalloc_FOUND) - MESSAGE(STATUS " With tcmalloc = YES") - ELSE() - MESSAGE(STATUS " With tcmalloc = NO (tcmalloc not found)") - ENDIF(Tcmalloc_FOUND) - - IF(TORCH_FOUND) - MESSAGE(STATUS " With Torch = YES") - ELSE() - MESSAGE(STATUS " With Torch = NO (libtorch not found)") - ENDIF(TORCH_FOUND) - - IF(APPLE) - MESSAGE(STATUS " BUILD_AS_BUNDLE = ${BUILD_AS_BUNDLE}") - ENDIF(APPLE) - MESSAGE(STATUS "--------------------------------------------") - -ELSEIF(CATKIN_BUILD) - #ROS Catkin build - - ## Find catkin macros and libraries - ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) - ## is used, also find other catkin packages - find_package(catkin REQUIRED COMPONENTS - cv_bridge roscpp sensor_msgs std_msgs image_transport message_filters tf message_generation - ) - - ## Generate messages in the 'msg' folder - add_message_files( - FILES - ObjectsStamped.msg - DetectionInfo.msg - ) - - ## Generate added messages and services with any dependencies listed here - generate_messages( - DEPENDENCIES - std_msgs - sensor_msgs - ) - - ################################### - ## catkin specific configuration ## - ################################### - ## The catkin_package macro generates cmake config files for your package - ## Declare things to be passed to dependent projects - ## INCLUDE_DIRS: uncomment this if you package contains header files - ## LIBRARIES: libraries you create in this project that dependent projects also need - ## CATKIN_DEPENDS: catkin_packages dependent projects also need - ## DEPENDS: system dependencies of this project that dependent projects also need - catkin_package( - CATKIN_DEPENDS cv_bridge roscpp sensor_msgs std_msgs image_transport message_filters tf message_runtime - DEPENDS OpenCV - ) - - ########### - ## Build ## - ########### - ADD_SUBDIRECTORY( src ) - - ############# - ## Install ## - ############# - ## Mark other files for installation (e.g. launch and bag files, etc.) - install(DIRECTORY - launch/ros1 - DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch - ) -ELSE() # COLCON_BUILD - #ROS Colcon build - - find_package(ament_cmake REQUIRED) - find_package(builtin_interfaces REQUIRED) - find_package(rosidl_default_generators REQUIRED) - find_package(rclcpp REQUIRED) - find_package(rclcpp_components REQUIRED) - find_package(cv_bridge REQUIRED) - find_package(sensor_msgs REQUIRED) - find_package(std_msgs REQUIRED) - find_package(image_transport REQUIRED) - find_package(message_filters REQUIRED) - find_package(tf2 REQUIRED) - find_package(tf2_ros REQUIRED) - find_package(tf2_geometry_msgs REQUIRED) - find_package(geometry_msgs REQUIRED) - - ## Generate messages and services - rosidl_generate_interfaces(${PROJECT_NAME} - msg/ObjectsStamped.msg - msg/DetectionInfo.msg - DEPENDENCIES std_msgs sensor_msgs - ) - ament_export_dependencies(rosidl_default_runtime) - - ########### - ## Build ## - ########### - ADD_SUBDIRECTORY( src ) - - ############# - ## Install ## - ############# - install(DIRECTORY - launch/ros2/. - DESTINATION share/${PROJECT_NAME}/launch - ) - - ament_package() -ENDIF() - diff --git a/find-object/FindObjectConfig.cmake.in b/find-object/FindObjectConfig.cmake.in deleted file mode 100644 index f9d908e5..00000000 --- a/find-object/FindObjectConfig.cmake.in +++ /dev/null @@ -1,10 +0,0 @@ -# - Config file for the FindObject package -# It defines the following variables -# FindObject_INCLUDE_DIRS - include directories for FindObject -# FindObject_LIBRARIES - libraries to link against - -# Compute paths -get_filename_component(FindObject_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) -set(FindObject_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@") - -find_library(FindObject_LIBRARIES NAMES find_object NO_DEFAULT_PATH HINTS "@CONF_LIB_DIR@") \ No newline at end of file diff --git a/find-object/FindObjectConfigVersion.cmake.in b/find-object/FindObjectConfigVersion.cmake.in deleted file mode 100644 index 22ffec0f..00000000 --- a/find-object/FindObjectConfigVersion.cmake.in +++ /dev/null @@ -1,11 +0,0 @@ -set(PACKAGE_VERSION "@PROJECT_VERSION@") - -# Check whether the requested PACKAGE_FIND_VERSION is compatible -if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") - set(PACKAGE_VERSION_COMPATIBLE FALSE) -else() - set(PACKAGE_VERSION_COMPATIBLE TRUE) - if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") - set(PACKAGE_VERSION_EXACT TRUE) - endif() -endif() diff --git a/find-object/LICENSE b/find-object/LICENSE deleted file mode 100644 index 871d6f6e..00000000 --- a/find-object/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the Universite de Sherbrooke nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/find-object/README.md b/find-object/README.md deleted file mode 100644 index c547630c..00000000 --- a/find-object/README.md +++ /dev/null @@ -1,92 +0,0 @@ -# find-object - - - - - - - - - - - - -
LinuxBuild Status
Build Status
Build Status -
WindowsBuild Status -
- -## Standalone -Find-Object project, visit the [home page](http://introlab.github.io/find-object/) for more information. - -## ROS1 - -### Install - -Binaries: -```bash -sudo apt-get install ros-$ROS_DISTRO-find-object-2d -``` - -Source: - - * To include `xfeatures2d` and/or `nonfree` modules of OpenCV, to avoid conflicts with `cv_bridge`, build same OpenCV version that is used by `cv_bridge`. Install it in `/usr/local` (default). - -```bash -cd ~/catkin_ws -git clone https://github.com/introlab/find-object.git src/find_object_2d -catkin_make -``` - -### Run -```bash -roscore -# Launch your preferred usb camera driver -rosrun uvc_camera uvc_camera_node -rosrun find_object_2d find_object_2d image:=image_raw -``` -See [find_object_2d](http://wiki.ros.org/find_object_2d) for more information. - -## ROS2 - -### Install - -Binaries: -```bash -To come... -``` - -Source: - -```bash -cd ~/ros2_ws -git clone https://github.com/introlab/find-object.git src/find_object_2d -colcon build -``` - -### Run -```bash -# Launch your preferred usb camera driver -ros2 launch realsense2_camera rs_launch.py - -# Launch find_object_2d node: -ros2 launch find_object_2d find_object_2d.launch.py image:=/camera/color/image_raw - -# Draw objects detected on an image: -ros2 run find_object_2d print_objects_detected --ros-args -r image:=/camera/color/image_raw -``` -#### 3D Pose (TF) -A RGB-D camera is required. Example with Realsense D400 camera: -```bash -# Launch your preferred usb camera driver -ros2 launch realsense2_camera rs_launch.py align_depth.enable:=true - -# Launch find_object_2d node: -ros2 launch find_object_2d find_object_3d.launch.py \ - rgb_topic:=/camera/color/image_raw \ - depth_topic:=/camera/aligned_depth_to_color/image_raw \ - camera_info_topic:=/camera/color/camera_info - -# Show 3D pose in camera frame: -ros2 run find_object_2d tf_example -``` -See [find_object_2d](http://wiki.ros.org/find_object_2d) for more information (same parameters/topics are used between ROS1 and ROS2 versions). diff --git a/find-object/Version.h.in b/find-object/Version.h.in deleted file mode 100644 index 31bfe1de..00000000 --- a/find-object/Version.h.in +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef VERSION_H_ -#define VERSION_H_ - -// This is auto-generated! -#define FINDOBJECT_VERSION "@PROJECT_VERSION@" - -#define FINDOBJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ -#define FINDOBJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@ -#define FINDOBJECT_VERSION_PATCH @PROJECT_VERSION_PATCH@ - -#define FINDOBJECT_VERSION_COMPARE(major, minor, patch) (major>=@PROJECT_VERSION_MAJOR@ || (major==@PROJECT_VERSION_MAJOR@ && minor>=@PROJECT_VERSION_MINOR@) || (major==@PROJECT_VERSION_MAJOR@ && minor==@PROJECT_VERSION_MINOR@ && patch >=@PROJECT_VERSION_PATCH@)) - -#define FINDOBJECT_NONFREE @NONFREE@ -#define FINDOBJECT_TORCH @TORCH@ - -#endif /* VERSION_H_ */ - diff --git a/find-object/app/CMakeLists.txt b/find-object/app/CMakeLists.txt deleted file mode 100644 index d8cda88f..00000000 --- a/find-object/app/CMakeLists.txt +++ /dev/null @@ -1,164 +0,0 @@ - -SET(headers_ui - TcpServerPool.h -) - -IF(QT4_FOUND) - QT4_WRAP_CPP(moc_srcs ${headers_ui}) -ELSE() - QT5_WRAP_CPP(moc_srcs ${headers_ui}) -ENDIF() - -SET(INCLUDE_DIRS - ${CMAKE_CURRENT_SOURCE_DIR}/../include - ${CMAKE_CURRENT_SOURCE_DIR} - ${OpenCV_INCLUDE_DIRS} -) - -IF(QT4_FOUND) - INCLUDE(${QT_USE_FILE}) -ENDIF(QT4_FOUND) - -SET(LIBRARIES - ${QT_LIBRARIES} - ${OpenCV_LIBS} -) - -if(Tcmalloc_FOUND) - SET(LIBRARIES - ${LIBARIES} - ${Tcmalloc_LIBRARIES} - ) -endif(Tcmalloc_FOUND) - - -#include files -INCLUDE_DIRECTORIES(${INCLUDE_DIRS}) - -SET(SRC_FILES main.cpp ${moc_srcs} ) - -# For Apple set the icns file containing icons -IF(APPLE AND BUILD_AS_BUNDLE) - # set how it shows up in the Info.plist file - SET(MACOSX_BUNDLE_ICON_FILE ${PROJECT_NAME}.icns) - # set where in the bundle to put the icns file - SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources) - # include the icns file in the target - SET(SRC_FILES ${SRC_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.icns) -ENDIF(APPLE AND BUILD_AS_BUNDLE) - -# Add exe icon resource -IF(WIN32) - IF( MINGW ) - # resource compilation for MinGW - ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/AppIco.o - COMMAND windres.exe -I${CMAKE_CURRENT_SOURCE_DIR} -i${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.rc - -o ${CMAKE_CURRENT_BINARY_DIR}/AppIco.o ) - SET(SRC_FILES ${SRC_FILES} ${CMAKE_CURRENT_BINARY_DIR}/AppIco.o) - ELSE( MINGW ) - SET(SRC_FILES ${SRC_FILES} ${PROJECT_NAME}.rc) # Error on visual studio 2008 - ENDIF( MINGW ) -ENDIF(WIN32) - -# create an executable file -IF(APPLE AND BUILD_AS_BUNDLE) - ADD_EXECUTABLE(find_object_app MACOSX_BUNDLE ${SRC_FILES}) -ELSEIF(MINGW) - ADD_EXECUTABLE(find_object_app WIN32 ${SRC_FILES}) -ELSE() - ADD_EXECUTABLE(find_object_app ${SRC_FILES}) -ENDIF() -# Linking with Qt libraries -TARGET_LINK_LIBRARIES(find_object_app find_object ${LIBRARIES}) -IF(Qt5_FOUND) - QT5_USE_MODULES(find_object_app Widgets Core Gui Network PrintSupport) -ENDIF(Qt5_FOUND) - -IF(APPLE AND BUILD_AS_BUNDLE) - SET_TARGET_PROPERTIES(find_object_app PROPERTIES - OUTPUT_NAME ${CMAKE_BUNDLE_NAME}) -ELSEIF(WIN32) - SET_TARGET_PROPERTIES(find_object_app PROPERTIES - OUTPUT_NAME ${PROJECT_NAME}) -ELSE() - SET_TARGET_PROPERTIES(find_object_app PROPERTIES - OUTPUT_NAME ${PROJECT_PREFIX}) -ENDIF() - -#--------------------------- -# Installation stuff -#--------------------------- -INSTALL(TARGETS find_object_app - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime - BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime) - -#--------------------------- -# Dependencies packaging -#--------------------------- -IF(APPLE AND BUILD_AS_BUNDLE) - INSTALL(CODE "execute_process(COMMAND ln -s \"../MacOS/${CMAKE_BUNDLE_NAME}\" ${PROJECT_NAME} - WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin)") -ENDIF(APPLE AND BUILD_AS_BUNDLE) - -IF((APPLE AND BUILD_AS_BUNDLE) OR WIN32) - SET(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}") - SET(plugin_dest_dir bin) - SET(qtconf_dest_dir bin) - IF(APPLE) - SET(plugin_dest_dir MacOS) - SET(qtconf_dest_dir Resources) - SET(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/MacOS/${CMAKE_BUNDLE_NAME}") - ENDIF(APPLE) - - # Install needed Qt plugins by copying directories from the qt installation - # One can cull what gets copied by using 'REGEX "..." EXCLUDE' - # Exclude debug libraries - IF(QT_PLUGINS_DIR) - INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/imageformats" - DESTINATION ${plugin_dest_dir}/plugins - COMPONENT runtime - REGEX ".*d4.dll" EXCLUDE - REGEX ".*d4.a" EXCLUDE) - ELSE() - #Qt5 - foreach(plugin ${Qt5Gui_PLUGINS}) - get_target_property(plugin_loc ${plugin} LOCATION) - get_filename_component(plugin_dir ${plugin_loc} DIRECTORY) - string(REPLACE "plugins" ";" loc_list ${plugin_dir}) - list(GET loc_list 1 plugin_type) - #MESSAGE(STATUS "Qt5 plugin \"${plugin_loc}\" installed in \"${plugin_dest_dir}/plugins${plugin_type}\"") - INSTALL(FILES ${plugin_loc} - DESTINATION ${plugin_dest_dir}/plugins${plugin_type} - COMPONENT runtime) - endforeach() - ENDIF() - - # install a qt.conf file - # this inserts some cmake code into the install script to write the file - SET(QT_CONF_FILE [Paths]\nPlugins=plugins) - IF(APPLE) - SET(QT_CONF_FILE [Paths]\nPlugins=MacOS/plugins) - ENDIF(APPLE) - INSTALL(CODE " - file(WRITE \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"${QT_CONF_FILE}\") - " COMPONENT runtime) - - # directories to look for dependencies - SET(DIRS ${QT_LIBRARY_DIRS} ${PROJECT_SOURCE_DIR}/bin) - IF(APPLE) - SET(DIRS ${DIRS} /usr/local /usr/local/lib) - ENDIF(APPLE) - - # Now the work of copying dependencies into the bundle/package - # The quotes are escaped and variables to use at install time have their $ escaped - # An alternative is the do a configure_file() on a script and use install(SCRIPT ...). - # Note that the image plugins depend on QtSvg and QtXml, and it got those copied - # over. - # To find dependencies, cmake use "otool" on Apple and "dumpbin" on Windows (make sure you have one of them). - install(CODE " - file(GLOB_RECURSE QTPLUGINS \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/plugins/*${CMAKE_SHARED_LIBRARY_SUFFIX}\") - include(\"BundleUtilities\") - fixup_bundle(\"${APPS}\" \"\${QTPLUGINS}\" \"${DIRS}\") - " COMPONENT runtime) -ENDIF((APPLE AND BUILD_AS_BUNDLE) OR WIN32) - diff --git a/find-object/app/Find-Object.icns b/find-object/app/Find-Object.icns deleted file mode 100644 index a0d1e741..00000000 Binary files a/find-object/app/Find-Object.icns and /dev/null differ diff --git a/find-object/app/Find-Object.ico b/find-object/app/Find-Object.ico deleted file mode 100644 index a4d84855..00000000 Binary files a/find-object/app/Find-Object.ico and /dev/null differ diff --git a/find-object/app/Find-Object.ifx b/find-object/app/Find-Object.ifx deleted file mode 100644 index 773ed036..00000000 Binary files a/find-object/app/Find-Object.ifx and /dev/null differ diff --git a/find-object/app/Find-Object.rc b/find-object/app/Find-Object.rc deleted file mode 100644 index 1809e18d..00000000 --- a/find-object/app/Find-Object.rc +++ /dev/null @@ -1 +0,0 @@ -IDI_ICON1 ICON DISCARDABLE "Find-Object.ico" diff --git a/find-object/app/TcpServerPool.h b/find-object/app/TcpServerPool.h deleted file mode 100644 index 98306d5a..00000000 --- a/find-object/app/TcpServerPool.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * TcpServerPool.h - * - * Created on: Nov 29, 2015 - * Author: mathieu - */ - -#ifndef TCPSERVERPOOL_H_ -#define TCPSERVERPOOL_H_ - -#include -#include -#include -#include -#include - -class FindObjectWorker : public QObject -{ - Q_OBJECT; - -public: - FindObjectWorker( - find_object::FindObject * sharedFindObject, - QSemaphore * sharedSemaphore, - int maxSemaphoreResources, - QObject * parent = 0) : - QObject(parent), - sharedFindObject_(sharedFindObject), - sharedSemaphore_(sharedSemaphore), - maxSemaphoreResources_(maxSemaphoreResources) - { - UASSERT(sharedFindObject != 0); - UASSERT(sharedSemaphore != 0); - UASSERT(maxSemaphoreResources > 0); - } - -public Q_SLOTS: - void detect(const cv::Mat & image) - { - sharedSemaphore_->acquire(1); - UINFO("Thread %p detecting...", (void *)this->thread()); - find_object::DetectionInfo info; - sharedFindObject_->detect(image, info); - Q_EMIT objectsFound(info); - sharedSemaphore_->release(1); - } - - void addObjectAndUpdate(const cv::Mat & image, int id, const QString & filePath) - { - //block everyone! - sharedSemaphore_->acquire(maxSemaphoreResources_); - UINFO("Thread %p adding object %d (%s)...", (void *)this->thread(), id, filePath.toStdString().c_str()); - sharedFindObject_->addObjectAndUpdate(image, id, filePath); - sharedSemaphore_->release(maxSemaphoreResources_); - } - void removeObjectAndUpdate(int id) - { - //block everyone! - sharedSemaphore_->acquire(maxSemaphoreResources_); - UINFO("Thread %p removing object %d...", (void *)this->thread(), id); - sharedFindObject_->removeObjectAndUpdate(id); - sharedSemaphore_->release(maxSemaphoreResources_); - } - -Q_SIGNALS: - void objectsFound(const find_object::DetectionInfo &); - -private: - find_object::FindObject * sharedFindObject_; //shared findobject - QSemaphore * sharedSemaphore_; - int maxSemaphoreResources_; -}; - -class TcpServerPool : public QObject -{ - Q_OBJECT; -public: - TcpServerPool(find_object::FindObject * sharedFindObject, int threads, int port) : - sharedSemaphore_(threads) - { - UASSERT(sharedFindObject != 0); - UASSERT(threads>=1); - - qRegisterMetaType("cv::Mat"); - - threadPool_.resize(threads); - for(int i=0; igetPort(), - tcpServer->getHostAddress().toString().toStdString().c_str()); - - threadPool_[i] = new QThread(this); - FindObjectWorker * worker = new FindObjectWorker(sharedFindObject, &sharedSemaphore_, threads); - - tcpServer->moveToThread(threadPool_[i]); - worker->moveToThread(threadPool_[i]); - connect(threadPool_[i], SIGNAL(finished()), tcpServer, SLOT(deleteLater())); - connect(threadPool_[i], SIGNAL(finished()), worker, SLOT(deleteLater())); - - // connect stuff: - QObject::connect(worker, SIGNAL(objectsFound(find_object::DetectionInfo)), tcpServer, SLOT(publishDetectionInfo(find_object::DetectionInfo))); - QObject::connect(tcpServer, SIGNAL(detectObject(const cv::Mat &)), worker, SLOT(detect(const cv::Mat &))); - QObject::connect(tcpServer, SIGNAL(addObject(const cv::Mat &, int, const QString &)), worker, SLOT(addObjectAndUpdate(const cv::Mat &, int, const QString &))); - QObject::connect(tcpServer, SIGNAL(removeObject(int)), worker, SLOT(removeObjectAndUpdate(int))); - threadPool_[i]->start(); - } - } - - virtual ~TcpServerPool() - { - for(int i=0; iquit(); - threadPool_[i]->wait(); - } - } - -private: - QVector threadPool_; - QSemaphore sharedSemaphore_; -}; - - - -#endif /* TCPSERVERPOOL_H_ */ diff --git a/find-object/app/main.cpp b/find-object/app/main.cpp deleted file mode 100644 index 9ee019d2..00000000 --- a/find-object/app/main.cpp +++ /dev/null @@ -1,685 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include -#include -#include -#include -#include -#include "find_object/MainWindow.h" -#include "find_object/Settings.h" -#include "find_object/FindObject.h" -#include "find_object/Camera.h" -#include "find_object/TcpServer.h" -#include "find_object/JsonWriter.h" -#include "find_object/utilite/ULogger.h" -#include "TcpServerPool.h" - -bool running = true; - -#ifdef WIN32 -#include -BOOL WINAPI my_handler(DWORD signal) -{ - if (signal == CTRL_C_EVENT) - { - printf("\nCtrl-C caught! Quitting application...\n"); - QCoreApplication::quit(); - } - return TRUE; - running = false; -} -#else -#include -void my_handler(int s) -{ - printf("\nCtrl-C caught! Quitting application...\n"); - QCoreApplication::quit(); - running = false; -} -inline void Sleep(unsigned int ms) -{ - struct timespec req; - struct timespec rem; - req.tv_sec = ms / 1000; - req.tv_nsec = (ms - req.tv_sec * 1000) * 1000 * 1000; - nanosleep (&req, &rem); -} -#endif - -void setupQuitSignal() -{ -// Catch ctrl-c to close Qt -#ifdef WIN32 - if (!SetConsoleCtrlHandler(my_handler, TRUE)) - { - UERROR("Could not set control (ctrl-c) handler"); - } -#else - struct sigaction sigIntHandler; - sigIntHandler.sa_handler = my_handler; - sigemptyset(&sigIntHandler.sa_mask); - sigIntHandler.sa_flags = 0; - sigaction(SIGINT, &sigIntHandler, NULL); -#endif -} - -void showUsage() -{ - printf("\nUsage:\n" -#ifdef WIN32 - " Find-Object.exe [options]\n" -#else - " find_object [options]\n" -#endif - "Options:\n" - " --console Don't use the GUI (by default the camera will be\n" - " started automatically). Option --objects must also be\n" - " used with valid objects.\n" - " --session \"path\" Path to a session to load (*.bin). Use \"--session_new\" to\n" - " create a session instead (will be saved to \"path\" on exit, only\n" - " on console mode).\n" - " --object \"path\" Path to an object to detect.\n" - " --objects \"path\" Directory of the objects to detect (--object is ignored).\n" - " --config \"path\" Path to configuration file (default: %s).\n" - " If set to \"\", default parameters are used\n" - " without saving modified parameters on closing.\n" - " --scene \"path\" Path to a scene image file.\n" - " --vocabulary \"path\" Path to a vocabulary file (*.yaml *.xml). Parameters \"General/invertedSearch\"\n" - " and \"General/vocabularyFixed\" will be also enabled. Ignored if \"--session\" is set.\n" - " --images_not_saved Don't keep images in RAM after the features are extracted (only\n" - " in console mode). Images won't be saved if an output session is set.\n" - " --tcp_threads # Number of TCP threads (default 1, only in --console mode). \"--General/port\" parameter should not be 0.\n" - " Port numbers start from \"General/port\" value. \"Detect\" TCP service can be\n" - " executed at the same time by multiple threads. \"Add/Remove\" TCP services\n" - " cannot be called by multiple threads, so calling these services on a port\n " - " will block all other threads on the other ports.\n" - " --debug Show debug log.\n" - " --log-time Show log with time.\n" - " --params Show all parameters.\n" - " --defaults Use default parameters (--config is ignored).\n" - " --My/Parameter \"value\" Set find-Object's parameter (look --params for parameters' name).\n" - " It will override the one in --config. Example to set 4 threads:\n" - " $ find_object --General/threads 4\n" - " --json \"path\" Path to an output JSON file (only in --console mode with --scene).\n" - " --help Show usage.\n" - , find_object::Settings::iniDefaultPath().toStdString().c_str()); - exit(-1); -} - -int main(int argc, char* argv[]) -{ - ULogger::setType(ULogger::kTypeConsole); - ULogger::setLevel(ULogger::kInfo); - ULogger::setPrintWhere(false); - ULogger::setPrintTime(false); - - ////////////////////////// - // parse options BEGIN - ////////////////////////// - bool guiMode = true; - QString sessionPath = ""; - bool sessionNew = false; - QString objectsPath = ""; - QString objectPath = ""; - QString scenePath = ""; - QString configPath = ""; - QString vocabularyPath = ""; - QString jsonPath; - find_object::ParametersMap customParameters; - bool imagesSaved = true; - int tcpThreads = 1; - - for(int i=1; i= 1!\n"); - showUsage(); - } - } - else - { - showUsage(); - } - continue; - } - if(strcmp(argv[i], "--params") == 0) - { - find_object::ParametersMap parameters = find_object::Settings::getDefaultParameters(); - for(find_object::ParametersMap::iterator iter=parameters.begin(); iter!=parameters.end(); ++iter) - { - std::string str = "Param: " + iter.key().toStdString() + " = \"" + iter.value().toString().toStdString() + "\""; - std::cout << - str << - std::setw(60 - str.size()) << - " [" << - find_object::Settings::getDescriptions().value(iter.key()).toStdString().c_str() << - "]" << - std::endl; - } - UINFO("Node will now exit after showing default Find-Object's parameters because " - "argument \"--params\" is detected!"); - exit(0); - } - - // Check for custom parameters: - find_object::ParametersMap parameters = find_object::Settings::getDefaultParameters(); - QString name = argv[i]; - if(name.size() > 2) - { - //strip the "--" - name.remove(0, 2); - if(parameters.contains(name)) - { - ++i; - if(i < argc) - { - customParameters.insert(name, argv[i]); - } - else - { - showUsage(); - } - continue; - } - } - - UERROR("Unrecognized option : %s", argv[i]); - showUsage(); - } - - UINFO("Options:"); - UINFO(" GUI mode = %s", guiMode?"true":"false"); - if(!sessionPath.isEmpty()) - { - if(sessionNew) - { - UINFO(" Session path: \"%s\" [NEW]", sessionPath.toStdString().c_str()); - if(configPath.isEmpty() && guiMode) - { - configPath = find_object::Settings::iniDefaultPath(); - } - } - else - { - UINFO(" Session path: \"%s\"", sessionPath.toStdString().c_str()); - if(!vocabularyPath.isEmpty()) - { - UWARN("Vocabulary \"%s\" is not loaded as a session \"%s\" is already " - "loaded, ignoring vocabulary file...", - vocabularyPath.toStdString().c_str(), - sessionPath.toStdString().c_str()); - vocabularyPath.clear(); - } - if(!configPath.isEmpty()) - { - UWARN("A session \"%s\" is loaded and a config file is also used, " - "the parameters of the session will be overwritten by " - "those in the config file \"%s\".", - sessionPath.toStdString().c_str(), - configPath.toStdString().c_str()); - } - } - } - else if(configPath.isEmpty() && guiMode) - { - configPath = find_object::Settings::iniDefaultPath(); - } - if(!objectsPath.isEmpty()) - { - UINFO(" Objects path: \"%s\"", objectsPath.toStdString().c_str()); - } - else if(!objectPath.isEmpty()) - { - UINFO(" Object path: \"%s\"", objectPath.toStdString().c_str()); - } - UINFO(" Scene path: \"%s\"", scenePath.toStdString().c_str()); - if(!guiMode) - { - UINFO(" JSON path: \"%s\"", jsonPath.toStdString().c_str()); - } - UINFO(" Settings path: \"%s\"", configPath.toStdString().c_str()); - UINFO(" Vocabulary path: \"%s\"", vocabularyPath.toStdString().c_str()); - - if(!vocabularyPath.isEmpty()) - { - if(customParameters.contains(find_object::Settings::kGeneral_vocabularyFixed())) - { - UWARN("\"General/vocabularyFixed\" custom parameter overwritten as a fixed vocabulary is used."); - } - if(customParameters.contains(find_object::Settings::kGeneral_invertedSearch())) - { - UWARN("\"General/invertedSearch\" custom parameter overwritten as a fixed vocabulary is used."); - } - customParameters[find_object::Settings::kGeneral_vocabularyFixed()] = true; - customParameters[find_object::Settings::kGeneral_invertedSearch()] = true; - } - - for(find_object::ParametersMap::iterator iter= customParameters.begin(); iter!=customParameters.end(); ++iter) - { - UINFO(" Param \"%s\"=\"%s\"", iter.key().toStdString().c_str(), iter.value().toString().toStdString().c_str()); - } - - ////////////////////////// - // parse options END - ////////////////////////// - - // Load settings, should be loaded before creating other objects - find_object::ParametersMap parameters; - if(!configPath.isEmpty()) - { - parameters = find_object::Settings::init(configPath); - } - - // Override custom parameters: - for(find_object::ParametersMap::iterator iter= customParameters.begin(); iter!=customParameters.end(); ++iter) - { - find_object::Settings::setParameter(iter.key(), iter.value()); - parameters.insert(iter.key(), iter.value()); - } - - - // Create FindObject - find_object::FindObject * findObject = new find_object::FindObject(guiMode || imagesSaved); - - // Load objects if path is set - int objectsLoaded = 0; - if(!sessionPath.isEmpty() && !sessionNew) - { - if(!findObject->loadSession(sessionPath, parameters)) - { - UERROR("Could not load session \"%s\"", sessionPath.toStdString().c_str()); - } - else - { - objectsLoaded = findObject->objects().size(); - } - } - else if(!vocabularyPath.isEmpty() && !findObject->loadVocabulary(vocabularyPath)) - { - UERROR("Failed to load vocabulary \"%s\"", vocabularyPath.toStdString().c_str()); - } - - if(!objectsPath.isEmpty()) - { - if(!vocabularyPath.isEmpty() && !findObject->loadVocabulary(vocabularyPath)) - { - UERROR("Failed to load vocabulary \"%s\"", vocabularyPath.toStdString().c_str()); - } - objectsLoaded = findObject->loadObjects(objectsPath); - if(!objectsLoaded) - { - UWARN("No objects loaded from \"%s\"", objectsPath.toStdString().c_str()); - } - } - else if(!objectPath.isEmpty()) - { - if(!vocabularyPath.isEmpty() && !findObject->loadVocabulary(vocabularyPath)) - { - UERROR("Failed to load vocabulary \"%s\"", vocabularyPath.toStdString().c_str()); - } - - const find_object::ObjSignature * obj = findObject->addObject(objectPath); - if(obj) - { - ++objectsLoaded; - findObject->updateObjects(); - findObject->updateVocabulary(); - } - else - { - UWARN("No object loaded from \"%s\"", objectsPath.toStdString().c_str()); - } - } - - cv::Mat scene; - if(!scenePath.isEmpty()) - { - scene = cv::imread(scenePath.toStdString()); - if(scene.empty()) - { - UERROR("Failed to load scene \"%s\"", scenePath.toStdString().c_str()); - } - } - - if(guiMode) - { - QApplication app(argc, argv); - find_object::MainWindow mainWindow(findObject, 0); // ownership transfered - - app.connect( &app, SIGNAL( lastWindowClosed() ), &app, SLOT( quit() ) ); - mainWindow.show(); - - if(!scene.empty()) - { - mainWindow.update(scene); - } - - app.exec(); - - // Save settings - find_object::Settings::saveSettings(); - } - else - { - QCoreApplication app(argc, argv); - - if(!scene.empty()) - { - // process the scene and exit - QTime time; - time.start(); - find_object::DetectionInfo info; - findObject->detect(scene, info); - - if(info.objDetected_.size() > 1) - { - UINFO("%d objects detected! (%d ms)", (int)info.objDetected_.size(), time.elapsed()); - } - else if(info.objDetected_.size() == 1) - { - UINFO("Object %d detected! (%d ms)", (int)info.objDetected_.begin().key(), time.elapsed()); - } - else if(find_object::Settings::getGeneral_sendNoObjDetectedEvents()) - { - UINFO("No objects detected. (%d ms)", time.elapsed()); - } - - if(!jsonPath.isEmpty()) - { - find_object::JsonWriter::write(info, jsonPath); - UINFO("JSON written to \"%s\"", jsonPath.toStdString().c_str()); - } - } - else - { - TcpServerPool tcpServerPool(findObject, tcpThreads, find_object::Settings::getGeneral_port()); - - setupQuitSignal(); - - //If TCP camera is used - find_object::Camera * camera = 0; - if(find_object::Settings::getCamera_6useTcpCamera()) - { - camera = new find_object::Camera(); - - // [Camera] ---Image---> [FindObject] - QObject::connect(camera, SIGNAL(imageReceived(const cv::Mat &)), findObject, SLOT(detect(const cv::Mat &))); - QObject::connect(camera, SIGNAL(finished()), &app, SLOT(quit())); - - if(!camera->start()) - { - UERROR("Camera initialization failed!"); - running = false; - } - } - - // start processing! - if(running) - { - app.exec(); - - if(!sessionPath.isEmpty()) - { - if(findObject->isSessionModified()) - { - UINFO("The session has been modified, updating the session file..."); - if(findObject->saveSession(sessionPath)) - { - UINFO("Session \"%s\" successfully saved (%d objects)!", - sessionPath.toStdString().c_str(), findObject->objects().size()); - } - } - else if(sessionNew) - { - UINFO("The session has not been modified, session file not created..."); - } - } - } - - // cleanup - if(camera) - { - camera->stop(); - delete camera; - } - } - - delete findObject; - } - return 0; -} diff --git a/find-object/bin/.gitignore b/find-object/bin/.gitignore deleted file mode 100644 index bef66adf..00000000 --- a/find-object/bin/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore -!box_in_scene.png -!box.png -!multi-objs -!multi-scene.jpg diff --git a/find-object/bin/box.png b/find-object/bin/box.png deleted file mode 100644 index 6f01082f..00000000 Binary files a/find-object/bin/box.png and /dev/null differ diff --git a/find-object/bin/box_in_scene.png b/find-object/bin/box_in_scene.png deleted file mode 100644 index cff246a3..00000000 Binary files a/find-object/bin/box_in_scene.png and /dev/null differ diff --git a/find-object/bin/multi-objs/38.bmp b/find-object/bin/multi-objs/38.bmp deleted file mode 100644 index 8f034516..00000000 Binary files a/find-object/bin/multi-objs/38.bmp and /dev/null differ diff --git a/find-object/bin/multi-objs/39.bmp b/find-object/bin/multi-objs/39.bmp deleted file mode 100644 index 38e1ffbc..00000000 Binary files a/find-object/bin/multi-objs/39.bmp and /dev/null differ diff --git a/find-object/bin/multi-scene.jpg b/find-object/bin/multi-scene.jpg deleted file mode 100644 index 45a411a5..00000000 Binary files a/find-object/bin/multi-scene.jpg and /dev/null differ diff --git a/find-object/build/.empty b/find-object/build/.empty deleted file mode 100644 index e69de29b..00000000 diff --git a/find-object/build/.gitignore b/find-object/build/.gitignore deleted file mode 100644 index 5e7d2734..00000000 --- a/find-object/build/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore diff --git a/find-object/cmake_modules/FindTcmalloc.cmake b/find-object/cmake_modules/FindTcmalloc.cmake deleted file mode 100644 index fbfe24fb..00000000 --- a/find-object/cmake_modules/FindTcmalloc.cmake +++ /dev/null @@ -1,34 +0,0 @@ -# - Find Tcmalloc -# Find the native Tcmalloc library -# -# Tcmalloc_LIBRARIES - List of libraries when using Tcmalloc. -# Tcmalloc_FOUND - True if Tcmalloc found. - -if (USE_TCMALLOC) - set(Tcmalloc_NAMES tcmalloc) -else () - set(Tcmalloc_NAMES tcmalloc_minimal tcmalloc) -endif () - -find_library(Tcmalloc_LIBRARY NAMES ${Tcmalloc_NAMES}) - -if (Tcmalloc_LIBRARY) - set(Tcmalloc_FOUND TRUE) - set( Tcmalloc_LIBRARIES ${Tcmalloc_LIBRARY} ) -else () - set(Tcmalloc_FOUND FALSE) - set( Tcmalloc_LIBRARIES ) -endif () - -if (Tcmalloc_FOUND) - message(STATUS "Found Tcmalloc: ${Tcmalloc_LIBRARY}") -else () - message(STATUS "Not Found Tcmalloc: ${Tcmalloc_LIBRARY}") - if (Tcmalloc_FIND_REQUIRED) - message(STATUS "Looked for Tcmalloc libraries named ${Tcmalloc_NAMES}.") - message(FATAL_ERROR "Could NOT find Tcmalloc library") - endif () -endif () - -mark_as_advanced(Tcmalloc_LIBRARY) - diff --git a/find-object/cmake_uninstall.cmake.in b/find-object/cmake_uninstall.cmake.in deleted file mode 100644 index 14e60101..00000000 --- a/find-object/cmake_uninstall.cmake.in +++ /dev/null @@ -1,27 +0,0 @@ -# ----------------------------------------------- -# File that provides "make uninstall" target -# We use the file 'install_manifest.txt' -# ----------------------------------------------- -IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") - MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") -ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") - -FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) -STRING(REGEX REPLACE "\n" ";" files "${files}") -FOREACH(file ${files}) - MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") - IF(EXISTS "$ENV{DESTDIR}${file}") - EXEC_PROGRAM( - "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" - OUTPUT_VARIABLE rm_out - RETURN_VALUE rm_retval - ) - IF(NOT "${rm_retval}" STREQUAL 0) - MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") - ENDIF(NOT "${rm_retval}" STREQUAL 0) - ELSE(EXISTS "$ENV{DESTDIR}${file}") - MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") - ENDIF(EXISTS "$ENV{DESTDIR}${file}") -ENDFOREACH(file) - - diff --git a/find-object/example/CMakeLists.txt b/find-object/example/CMakeLists.txt deleted file mode 100644 index 61dd9fa6..00000000 --- a/find-object/example/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ - -SET(SRC_FILES - main.cpp -) - -SET(INCLUDE_DIRS - ${CMAKE_CURRENT_SOURCE_DIR} - ${OpenCV_INCLUDE_DIRS} - ${CMAKE_CURRENT_SOURCE_DIR}/../include -) - -IF(QT4_FOUND) - INCLUDE(${QT_USE_FILE}) -ENDIF(QT4_FOUND) - -SET(LIBRARIES - ${OpenCV_LIBS} - ${QT_LIBRARIES} -) - -# Make sure the compiler can find include files from our library. -INCLUDE_DIRECTORIES(${INCLUDE_DIRS}) - -# Add binary called "example" that is built from the source file "main.cpp". -# The extension is automatically found. -ADD_EXECUTABLE(example ${SRC_FILES}) -TARGET_LINK_LIBRARIES(example find_object ${LIBRARIES}) -IF(Qt5_FOUND) - QT5_USE_MODULES(example Widgets Core Gui Network PrintSupport) -ENDIF(Qt5_FOUND) - -SET_TARGET_PROPERTIES( example - PROPERTIES OUTPUT_NAME ${PROJECT_PREFIX}-example) - -INSTALL(TARGETS example - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime - BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime) - diff --git a/find-object/example/main.cpp b/find-object/example/main.cpp deleted file mode 100644 index 7e47b1e1..00000000 --- a/find-object/example/main.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include - -// Qt stuff -#include -#include -#include -#include -#include -#include - -// OpenCV stuff -#include -#include -#include -#include // for homography - -#include - -#ifdef HAVE_OPENCV_NONFREE - #if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >=4 - #include - #include - #endif -#endif -#ifdef HAVE_OPENCV_XFEATURES2D - #include - #include -#endif - - -// From this project -#include "find_object/ObjWidget.h" -#include "find_object/QtOpenCV.h" - -using namespace find_object; - -void showUsage() -{ - printf("\n"); - printf("Usage :\n"); - printf(" ./example object.png scene.png\n"); - exit(1); -} - -int main(int argc, char * argv[]) -{ - if(argc<3) - { - showUsage(); - } - QTime time; - - // GUI stuff - QApplication app(argc, argv); - - time.start(); - //Load as grayscale - cv::Mat objectImg = cv::imread(argv[1], cv::IMREAD_GRAYSCALE); - cv::Mat sceneImg = cv::imread(argv[2], cv::IMREAD_GRAYSCALE); - - if(!objectImg.empty() && !sceneImg.empty()) - { - printf("Loading images: %d ms\n", time.restart()); - std::vector objectKeypoints; - std::vector sceneKeypoints; - cv::Mat objectDescriptors; - cv::Mat sceneDescriptors; - - //////////////////////////// - // EXTRACT KEYPOINTS - //////////////////////////// - cv::Ptr detector; - // The detector can be any of (see OpenCV features2d.hpp): -#if CV_MAJOR_VERSION == 2 - // detector = cv::Ptr(new cv::DenseFeatureDetector()); - // detector = cv::Ptr(new cv::FastFeatureDetector()); - // detector = cv::Ptr(new cv::GFTTDetector()); - // detector = cv::Ptr(new cv::MSER()); - // detector = cv::Ptr(new cv::ORB()); - detector = cv::Ptr(new cv::SIFT()); - // detector = cv::Ptr(new cv::StarFeatureDetector()); - // detector = cv::Ptr(new cv::SURF(600.0)); - // detector = cv::Ptr(new cv::BRISK()); -#elif CV_MAJOR_VERSION < 4 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION < 3) - detector = cv::xfeatures2d::SIFT::create(); -#else // >= 4.3.0 - detector = cv::SIFT::create(); -#endif - detector->detect(objectImg, objectKeypoints); - printf("Object: %d keypoints detected in %d ms\n", (int)objectKeypoints.size(), time.restart()); - detector->detect(sceneImg, sceneKeypoints); - printf("Scene: %d keypoints detected in %d ms\n", (int)sceneKeypoints.size(), time.restart()); - - //////////////////////////// - // EXTRACT DESCRIPTORS - //////////////////////////// - cv::Ptr extractor; -#if CV_MAJOR_VERSION == 2 - // The extractor can be any of (see OpenCV features2d.hpp): - // extractor = cv::Ptr(new cv::BriefDescriptorExtractor()); - // extractor = cv::Ptr(new cv::ORB()); - extractor = cv::Ptr(new cv::SIFT()); - // extractor = cv::Ptr(new cv::SURF(600.0)); - // extractor = cv::Ptr(new cv::BRISK()); - // extractor = cv::Ptr(new cv::FREAK()); -#elif CV_MAJOR_VERSION < 4 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION < 3) - extractor = cv::xfeatures2d::SIFT::create(); -#else // >= 4.3.0 - extractor = cv::SIFT::create(); -#endif - extractor->compute(objectImg, objectKeypoints, objectDescriptors); - printf("Object: %d descriptors extracted in %d ms\n", objectDescriptors.rows, time.restart()); - extractor->compute(sceneImg, sceneKeypoints, sceneDescriptors); - printf("Scene: %d descriptors extracted in %d ms\n", sceneDescriptors.rows, time.restart()); - - //////////////////////////// - // NEAREST NEIGHBOR MATCHING USING FLANN LIBRARY (included in OpenCV) - //////////////////////////// - cv::Mat results; - cv::Mat dists; - std::vector > matches; - int k=2; // find the 2 nearest neighbors - bool useBFMatcher = false; // SET TO TRUE TO USE BRUTE FORCE MATCHER - if(objectDescriptors.type()==CV_8U) - { - // Binary descriptors detected (from ORB, Brief, BRISK, FREAK) - printf("Binary descriptors detected...\n"); - if(useBFMatcher) - { - cv::BFMatcher matcher(cv::NORM_HAMMING); // use cv::NORM_HAMMING2 for ORB descriptor with WTA_K == 3 or 4 (see ORB constructor) - matcher.knnMatch(objectDescriptors, sceneDescriptors, matches, k); - } - else - { - // Create Flann LSH index - cv::flann::Index flannIndex(sceneDescriptors, cv::flann::LshIndexParams(12, 20, 2), cvflann::FLANN_DIST_HAMMING); - printf("Time creating FLANN LSH index = %d ms\n", time.restart()); - - // search (nearest neighbor) - flannIndex.knnSearch(objectDescriptors, results, dists, k, cv::flann::SearchParams() ); - } - } - else - { - // assume it is CV_32F - printf("Float descriptors detected...\n"); - if(useBFMatcher) - { - cv::BFMatcher matcher(cv::NORM_L2); - matcher.knnMatch(objectDescriptors, sceneDescriptors, matches, k); - } - else - { - // Create Flann KDTree index - cv::flann::Index flannIndex(sceneDescriptors, cv::flann::KDTreeIndexParams(), cvflann::FLANN_DIST_EUCLIDEAN); - printf("Time creating FLANN KDTree index = %d ms\n", time.restart()); - - // search (nearest neighbor) - flannIndex.knnSearch(objectDescriptors, results, dists, k, cv::flann::SearchParams() ); - } - } - printf("Time nearest neighbor search = %d ms\n", time.restart()); - - // Conversion to CV_32F if needed - if(dists.type() == CV_32S) - { - cv::Mat temp; - dists.convertTo(temp, CV_32F); - dists = temp; - } - - - //////////////////////////// - // PROCESS NEAREST NEIGHBOR RESULTS - //////////////////////////// - // Set gui data - ObjWidget objWidget(0, objectKeypoints, QMultiMap(), cvtCvMat2QImage(objectImg)); - ObjWidget sceneWidget(0, sceneKeypoints, QMultiMap(), cvtCvMat2QImage(sceneImg)); - - // Find correspondences by NNDR (Nearest Neighbor Distance Ratio) - float nndrRatio = 0.8f; - std::vector mpts_1, mpts_2; // Used for homography - std::vector indexes_1, indexes_2; // Used for homography - std::vector outlier_mask; // Used for homography - // Check if this descriptor matches with those of the objects - if(!useBFMatcher) - { - for(int i=0; i(i,0), dists.at(i,1)); - if(results.at(i,0) >= 0 && results.at(i,1) >= 0 && - dists.at(i,0) <= nndrRatio * dists.at(i,1)) - { - mpts_1.push_back(objectKeypoints.at(i).pt); - indexes_1.push_back(i); - - mpts_2.push_back(sceneKeypoints.at(results.at(i,0)).pt); - indexes_2.push_back(results.at(i,0)); - } - } - } - else - { - for(unsigned int i=0; i= minInliers) - { - time.start(); - cv::Mat H = findHomography(mpts_1, - mpts_2, - cv::RANSAC, - 1.0, - outlier_mask); - printf("Time finding homography = %d ms\n", time.restart()); - int inliers=0, outliers=0; - for(unsigned int k=0; k(0,0), H.at(1,0), H.at(2,0), - H.at(0,1), H.at(1,1), H.at(2,1), - H.at(0,2), H.at(1,2), H.at(2,2)); - - // GUI : Change color and add homography rectangle - QColor color(Qt::green); - int alpha = 130; - color.setAlpha(alpha); - for(unsigned int k=0; ksetPen(rectPen); - rectItem->setTransform(hTransform); - sceneWidget.addRect(rectItem); - printf("Inliers=%d Outliers=%d\n", inliers, outliers); - } - else - { - printf("Not enough matches (%d) for homography...\n", (int)mpts_1.size()); - } - - // Wait for gui - objWidget.setGraphicsViewMode(false); - objWidget.setWindowTitle("Object"); - if(objWidget.pixmap().width() <= 800) - { - objWidget.setMinimumSize(objWidget.pixmap().width(), objWidget.pixmap().height()); - } - else - { - objWidget.setMinimumSize(800, 600); - objWidget.setAutoScale(false); - } - - sceneWidget.setGraphicsViewMode(false); - sceneWidget.setWindowTitle("Scene"); - if(sceneWidget.pixmap().width() <= 800) - { - sceneWidget.setMinimumSize(sceneWidget.pixmap().width(), sceneWidget.pixmap().height()); - } - else - { - sceneWidget.setMinimumSize(800, 600); - sceneWidget.setAutoScale(false); - } - - sceneWidget.show(); - objWidget.show(); - - int r = app.exec(); - printf("Closing...\n"); - - return r; - } - else - { - printf("Images are not valid!\n"); - showUsage(); - } - - return 1; -} diff --git a/find-object/include/find_object/.gitignore b/find-object/include/find_object/.gitignore deleted file mode 100644 index 3503265b..00000000 --- a/find-object/include/find_object/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/Version.h diff --git a/find-object/include/find_object/Camera.h b/find-object/include/find_object/Camera.h deleted file mode 100644 index bd739522..00000000 --- a/find-object/include/find_object/Camera.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef CAMERA_H_ -#define CAMERA_H_ - -#include -#include "find_object/FindObjectExp.h" // DLL export/import defines -#include -#include -#include -#include - -namespace find_object { - -class CameraTcpServer; - -class FINDOBJECT_EXP Camera : public QObject { - Q_OBJECT -public: - Camera(QObject * parent = 0); - virtual ~Camera(); - - virtual bool start(); - virtual void stop(); - virtual bool isRunning() {return cameraTimer_.isActive();} - - void pause(); - int getTotalFrames(); - int getCurrentFrameIndex(); - int getPort(); - void moveToFrame(int frame); - -Q_SIGNALS: - void imageReceived(const cv::Mat & image); - void imageReceived(const cv::Mat & image, const find_object::Header & header, const cv::Mat & depth, float depthConstant); - void finished(); - -public Q_SLOTS: - virtual void updateImageRate(); - virtual void takeImage(); - -protected: - void startTimer(); - void stopTimer(); - -private: - cv::VideoCapture capture_; - QTimer cameraTimer_; - QList images_; - unsigned int currentImageIndex_; - CameraTcpServer * cameraTcpServer_; -}; - -} // namespace find_object - -#endif /* CAMERA_H_ */ diff --git a/find-object/include/find_object/DetectionInfo.h b/find-object/include/find_object/DetectionInfo.h deleted file mode 100644 index 9ce34057..00000000 --- a/find-object/include/find_object/DetectionInfo.h +++ /dev/null @@ -1,164 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef DETECTIONINFO_H_ -#define DETECTIONINFO_H_ - -#include -#include -#include -#include -#include -#include - -namespace find_object { - -class DetectionInfo -{ -public: - enum TimeStamp{ - kTimeKeypointDetection, - kTimeDescriptorExtraction, - kTimeSubPixelRefining, - kTimeSkewAffine, - kTimeIndexing, - kTimeMatching, - kTimeHomography, - kTimeTotal - }; - enum RejectedCode{ - kRejectedUndef, - kRejectedLowMatches, - kRejectedLowInliers, - kRejectedSuperposed, - kRejectedAllInliers, - kRejectedNotValid, - kRejectedCornersOutside, - kRejectedByAngle - }; - -public: - DetectionInfo() : - minMatchedDistance_(-1), - maxMatchedDistance_(-1) - {} - -public: - // Those maps have the same size - QMultiMap objDetected_; - QMultiMap objDetectedSizes_; // Object ID match the number of detected objects - QMultiMap objDetectedFilePaths_; // Object ID match the number of detected objects - QMultiMap objDetectedInliersCount_; // ObjectID match the number of detected objects - QMultiMap objDetectedOutliersCount_; // ObjectID match the number of detected objects - QMultiMap > objDetectedInliers_; // ObjectID Map< ObjectDescriptorIndex, SceneDescriptorIndex >, match the number of detected objects - QMultiMap > objDetectedOutliers_; // ObjectID Map< ObjectDescriptorIndex, SceneDescriptorIndex >, match the number of detected objects - - QMap timeStamps_; - std::vector sceneKeypoints_; - cv::Mat sceneDescriptors_; - QMultiMap sceneWords_; - QMap > matches_; // ObjectID Map< ObjectDescriptorIndex, SceneDescriptorIndex >, match the number of objects - - // Those maps have the same size - QMultiMap > rejectedInliers_; // ObjectID Map< ObjectDescriptorIndex, SceneDescriptorIndex > - QMultiMap > rejectedOutliers_; // ObjectID Map< ObjectDescriptorIndex, SceneDescriptorIndex > - QMultiMap rejectedCodes_; // ObjectID rejected code - - float minMatchedDistance_; - float maxMatchedDistance_; -}; - -inline QDataStream & operator<<(QDataStream &out, const DetectionInfo & info) -{ - out << quint32(info.objDetected_.size()); - - QMultiMap::const_iterator iterInliers = info.objDetectedInliersCount_.constBegin(); - QMultiMap::const_iterator iterOutliers = info.objDetectedOutliersCount_.constBegin(); - QMultiMap::const_iterator iterSizes = info.objDetectedSizes_.constBegin(); - QMultiMap::const_iterator iterFilenames = info.objDetectedFilePaths_.constBegin(); - for(QMultiMap::const_iterator iter=info.objDetected_.constBegin(); - iter!=info.objDetected_.constEnd(); - ++iter) - { - // ID - out << iter.key(); - - // Size - out << iterSizes.value(); - - // Transform - out << iter.value(); - - // Filename - out << iterFilenames.value(); - - // inliers and outliers count - out << iterInliers.value(); - out << iterOutliers.value(); - - ++iterInliers; - ++iterOutliers; - ++iterSizes; - ++iterFilenames; - } - return out; -} - -inline QDataStream & operator>>(QDataStream &in, DetectionInfo & info) -{ - QDataStream::Status oldStatus = in.status(); - in.resetStatus(); - info = DetectionInfo(); - - quint32 n; - in >> n; - - for (quint32 i = 0; i < n; ++i) { - if (in.status() != QDataStream::Ok) - break; - - int id; - QSize size; - QTransform homography; - QString filename; - int inliers, outliers; - in >> id >> size >> homography >> filename >> inliers >> outliers; - info.objDetected_.insert(id, homography); - info.objDetectedSizes_.insert(id, size); - info.objDetectedFilePaths_.insert(id, filename); - info.objDetectedInliersCount_.insert(id, inliers); - info.objDetectedOutliersCount_.insert(id, outliers); - } - if (in.status() != QDataStream::Ok) - info = DetectionInfo(); - if (oldStatus != QDataStream::Ok) - in.setStatus(oldStatus); - return in; -} - -} // namespace find_object - -#endif /* DETECTIONINFO_H_ */ diff --git a/find-object/include/find_object/FindObject.h b/find-object/include/find_object/FindObject.h deleted file mode 100644 index d8702315..00000000 --- a/find-object/include/find_object/FindObject.h +++ /dev/null @@ -1,116 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef FINDOBJECT_H_ -#define FINDOBJECT_H_ - -#include -#include "find_object/FindObjectExp.h" // DLL export/import defines - -#include "find_object/DetectionInfo.h" -#include "find_object/Settings.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace find_object { - -class ObjSignature; -class Vocabulary; -class Feature2D; - -class FINDOBJECT_EXP FindObject : public QObject -{ - Q_OBJECT; -public: - static void affineSkew(float tilt, - float phi, - const cv::Mat & image, - cv::Mat & skewImage, - cv::Mat & skewMask, - cv::Mat & Ai); - -public: - FindObject(bool keepImagesInRAM_ = true, QObject * parent = 0); - virtual ~FindObject(); - - bool loadSession(const QString & path, const ParametersMap & customParameters = ParametersMap()); - bool saveSession(const QString & path); - bool isSessionModified() const {return sessionModified_;} - - bool saveVocabulary(const QString & filePath) const; - bool loadVocabulary(const QString & filePath); - - int loadObjects(const QString & dirPath, bool recursive = false); // call updateObjects() - const ObjSignature * addObject(const QString & filePath); - const ObjSignature * addObject(const cv::Mat & image, int id=0, const QString & filePath = QString()); - bool addObject(ObjSignature * obj); // take ownership when true is returned - void removeObject(int id); - void removeAllObjects(); - - bool detect(const cv::Mat & image, find_object::DetectionInfo & info) const; - - void updateDetectorExtractor(); - void updateObjects(const QList & ids = QList()); - void updateVocabulary(const QList & ids = QList()); - - const QMap & objects() const {return objects_;} - const Vocabulary * vocabulary() const {return vocabulary_;} - -public Q_SLOTS: - void addObjectAndUpdate(const cv::Mat & image, int id=0, const QString & filePath = QString()); - void removeObjectAndUpdate(int id); - void detect(const cv::Mat & image); // emit objectsFound() - void detect(const cv::Mat & image, const find_object::Header & header, const cv::Mat & depth, float depthConstant); // emit objectsFound() - -Q_SIGNALS: - void objectsFound(const find_object::DetectionInfo &, const find_object::Header &, const cv::Mat &, float); - -private: - void clearVocabulary(); - -private: - QMap objects_; - Vocabulary * vocabulary_; - QMap objectsDescriptors_; - QMap dataRange_; // - Feature2D * detector_; - Feature2D * extractor_; - bool sessionModified_; - bool keepImagesInRAM_; -}; - -} // namespace find_object - -#endif /* FINDOBJECT_H_ */ diff --git a/find-object/include/find_object/FindObjectExp.h b/find-object/include/find_object/FindObjectExp.h deleted file mode 100644 index d1b41793..00000000 --- a/find-object/include/find_object/FindObjectExp.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef FINDOBJECTEXP_H -#define FINDOBJECTEXP_H - -#if defined(_WIN32) - #if defined(find_object_EXPORTS) - #define FINDOBJECT_EXP __declspec( dllexport ) - #else - #define FINDOBJECT_EXP __declspec( dllimport ) - #endif -#else - #define FINDOBJECT_EXP -#endif - -#endif // RTABMAPEXP_H diff --git a/find-object/include/find_object/Header.h b/find-object/include/find_object/Header.h deleted file mode 100644 index a08a4296..00000000 --- a/find-object/include/find_object/Header.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -Copyright (c) 2011-2021, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef INCLUDE_FIND_OBJECT_HEADER_H_ -#define INCLUDE_FIND_OBJECT_HEADER_H_ - -#include -#include - -namespace find_object { - -class Header { -public: - Header() : - sec_(0), - nsec_(0) - { - } - Header(const char * frameId, uint64_t sec, uint64_t nsec) : - frameId_(frameId), - sec_(sec), - nsec_(nsec) - { - } - QString frameId_; - uint64_t sec_; - uint64_t nsec_; -}; - -} - -#endif /* INCLUDE_FIND_OBJECT_HEADER_H_ */ diff --git a/find-object/include/find_object/JsonWriter.h b/find-object/include/find_object/JsonWriter.h deleted file mode 100644 index 9de2f361..00000000 --- a/find-object/include/find_object/JsonWriter.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef JSONWRITER_H_ -#define JSONWRITER_H_ - -#include "find_object/FindObjectExp.h" // DLL export/import defines - -#include "find_object/DetectionInfo.h" - -namespace find_object { - -class FINDOBJECT_EXP JsonWriter -{ -public: - static void write(const DetectionInfo & info, const QString & path); -}; - -} // namespace find_object - - -#endif /* JSONWRITER_H_ */ diff --git a/find-object/include/find_object/MainWindow.h b/find-object/include/find_object/MainWindow.h deleted file mode 100644 index c7195c9d..00000000 --- a/find-object/include/find_object/MainWindow.h +++ /dev/null @@ -1,152 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef MAINWINDOW_H_ -#define MAINWINDOW_H_ - -#include "find_object/FindObjectExp.h" // DLL export/import defines - -#include "find_object/DetectionInfo.h" -#include "find_object/Header.h" - -#include -#include -#include -#include -#include -#include - -#include - -namespace rtabmap -{ -class PdfPlotCurve; -} - -class Ui_mainWindow; -class QLabel; - -namespace find_object { - -class ObjWidget; -class Camera; -class ParametersToolBox; -class AboutDialog; -class TcpServer; -class KeypointDetector; -class DescriptorExtractor; -class Vocabulary; -class FindObject; - -class FINDOBJECT_EXP MainWindow : public QMainWindow -{ - Q_OBJECT - -public: - MainWindow(find_object::FindObject * findObject, find_object::Camera * camera = 0, QWidget * parent = 0); - virtual ~MainWindow(); - - void setSourceImageText(const QString & text); - -protected: - virtual void closeEvent(QCloseEvent * event); - virtual void keyPressEvent(QKeyEvent *event); - -public Q_SLOTS: - void startProcessing(); - void stopProcessing(); - void pauseProcessing(); - void update(const cv::Mat & image); - void update(const cv::Mat & image, const find_object::Header & header, const cv::Mat & depth, float depthConstant); - -private Q_SLOTS: - void loadSession(); - void saveSession(); - void loadSettings(); - void saveSettings(); - void loadObjects(); - bool saveObjects(); - void loadVocabulary(); - void saveVocabulary(); - void addObjectFromScene(); - void addObjectsFromFiles(const QStringList & fileNames); - void addObjectsFromFiles(); - void addObjectFromTcp(const cv::Mat & image, int id, const QString & filePath); - void loadSceneFromFile(const QStringList & fileNames); - void loadSceneFromFile(); - void setupCameraFromVideoFile(); - void setupCameraFromImagesDirectory(); - void setupCameraFromTcpIp(); - void removeObject(find_object::ObjWidget * object); - void removeObject(int id); - void removeAllObjects(); - void updateObjectsSize(); - void updateMirrorView(); - void showHideControls(); - void showObjectsFeatures(); - void hideObjectsFeatures(); - void updateObjects(); - void notifyParametersChanged(const QStringList & param); - void moveCameraFrame(int frame); - void rectHovered(int objId); - -Q_SIGNALS: - void objectsFound(const find_object::DetectionInfo &, const find_object::Header & header, const cv::Mat & depth, float depthConstant); - -private: - bool loadSettings(const QString & path); - bool saveSettings(const QString & path) const; - int loadObjects(const QString & dirPath, bool recursive = false); - int saveObjects(const QString & dirPath); - void setupTCPServer(); - int addObjectFromFile(const QString & filePath); - void showObject(find_object::ObjWidget * obj); - void updateObjectSize(find_object::ObjWidget * obj); - void updateVocabulary(const QList & ids = QList()); - void updateObjects(const QList & ids); - -private: - Ui_mainWindow * ui_; - Camera * camera_; - FindObject * findObject_; - rtabmap::PdfPlotCurve * likelihoodCurve_; - rtabmap::PdfPlotCurve * inliersCurve_; - AboutDialog * aboutDialog_; - QMap objWidgets_; - QTime updateRate_; - QTime refreshStartTime_; - int lowestRefreshRate_; - bool objectsModified_; - QMap imagesMap_; - QMap lastObjectsUpdateParameters_; // ParametersMap - TcpServer * tcpServer_; - cv::Mat sceneImage_; -}; - -} // namespace find_object - -#endif /* MainWindow_H_ */ diff --git a/find-object/include/find_object/ObjWidget.h b/find-object/include/find_object/ObjWidget.h deleted file mode 100644 index 73c2b75d..00000000 --- a/find-object/include/find_object/ObjWidget.h +++ /dev/null @@ -1,151 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef OBJWIDGET_H_ -#define OBJWIDGET_H_ - -#include "find_object/FindObjectExp.h" // DLL export/import defines - -#include -#include -#include - -class QAction; -class QMenu; -class QGraphicsView; -class QGraphicsScene; -class QGraphicsRectItem; -class QGraphicsItem; -class QLabel; - -namespace find_object { - -class KeypointItem; -class ImageKptsView; - -class FINDOBJECT_EXP ObjWidget : public QWidget -{ - Q_OBJECT - -public: - ObjWidget(QWidget * parent = 0); - ObjWidget(int id, const std::vector & keypoints, const QMultiMap & words, const QImage & image, QWidget * parent = 0); - virtual ~ObjWidget(); - - void setId(int id); - void updateImage(const QImage & image); - void updateData(const std::vector & keypoints, const QMultiMap & words=QMultiMap()); - void updateWords(const QMultiMap & words); - void setTextLabel(const QString & text); - void resetKptsColor(); - void resetKptsWordID(); - void setKptColor(int index, const QColor & color); - void setKptWordID(int index, int wordId); - void setGraphicsViewMode(bool on); - void setAutoScale(bool autoScale); - void setSizedFeatures(bool on); - void setMirrorView(bool on); - void setAlpha(int alpha); - void setDeletable(bool deletable); - void setImageShown(bool shown); - void setFeaturesShown(bool shown); - void addRect(QGraphicsRectItem * rect); - void clearRoiSelection() {mousePressedPos_ = mouseCurrentPos_ = QPoint();update();} - - int id() const {return id_;} - const QColor & color() const {return color_;} - const std::vector keypoints() const {return keypoints_;} - const QMap & words() const {return words_;} - const QPixmap & pixmap() const {return pixmap_;} - QColor defaultColor(int id) const; - bool isImageShown() const; - bool isFeaturesShown() const; - bool isSizedFeatures() const; - bool isMirrorView() const; - //QGraphicsScene * scene() const; - std::vector selectedKeypoints() const; - QList selectedItems() const; - - QPixmap getSceneAsPixmap(); - -protected: - virtual void paintEvent(QPaintEvent *event); - virtual void contextMenuEvent(QContextMenuEvent * event); - virtual void resizeEvent(QResizeEvent* event); - virtual void mousePressEvent(QMouseEvent * event); - virtual void mouseMoveEvent(QMouseEvent * event); - virtual void mouseReleaseEvent(QMouseEvent * event); - -Q_SIGNALS: - void removalTriggered(find_object::ObjWidget *); - void selectionChanged(); - void roiChanged(const cv::Rect &); - -private: - void setupGraphicsView(); - void drawKeypoints(QPainter * painter = 0); - void setupUi(); - void updateItemsShown(); - void computeScaleOffsets(float & scale, float & offsetX, float & offsetY); - -private: - int id_; - std::vector keypoints_; - QMap words_; // - QPixmap pixmap_; - QRect rect_; - QList keypointItems_; - QGraphicsView * graphicsView_; - QVector kptColors_; - QList rectItems_; - bool graphicsViewInitialized_; - int alpha_; - QLabel * label_; - QColor color_; - - // menu stuff - QString savedFileName_; - QMenu * menu_; - QAction * showImage_; - QAction * showFeatures_; - QAction * saveImage_; - QAction * mirrorView_; - QAction * delete_; - QAction * graphicsViewMode_; - QAction * autoScale_; - QAction * sizedFeatures_; - QAction * setAlpha_; - QAction * setColor_; - - // selection stuff - QPoint mousePressedPos_; - QPoint mouseCurrentPos_; -}; - -} // namespace find_object - -#endif /* OBJWIDGET_H_ */ diff --git a/find-object/include/find_object/QtOpenCV.h b/find-object/include/find_object/QtOpenCV.h deleted file mode 100644 index 3faacc0d..00000000 --- a/find-object/include/find_object/QtOpenCV.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef QTOPENCV_H -#define QTOPENCV_H - -#include "find_object/FindObjectExp.h" // DLL export/import defines - -#include -#include - -namespace find_object { - -// Convert OpenCV matrix to QImage -FINDOBJECT_EXP QImage cvtCvMat2QImage(const cv::Mat & image, bool isBgr = true); - -// Convert QImage to OpenCV matrix -FINDOBJECT_EXP cv::Mat cvtQImage2CvMat(const QImage & image); - -#if CV_MAJOR_VERSION < 3 -// Convert IplImage to QImage -FINDOBJECT_EXP QImage cvtIplImage2QImage(const IplImage * image); - -// Convert QImage to IplImage -FINDOBJECT_EXP IplImage * cvtQImage2IplImage(const QImage & image); -#endif - -} // namespace find_object - -#endif // QTOPENCV_H diff --git a/find-object/include/find_object/Settings.h b/find-object/include/find_object/Settings.h deleted file mode 100644 index ccf70015..00000000 --- a/find-object/include/find_object/Settings.h +++ /dev/null @@ -1,404 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef SETTINGS_H_ -#define SETTINGS_H_ - -#include "find_object/FindObjectExp.h" // DLL export/import defines -#include "find_object/Version.h" // DLL export/import defines - -#include -#include -#include -#include - -namespace find_object { - -class Feature2D; - -typedef QMap ParametersMap; // Key, value -typedef QMap ParametersType; // Key, type -typedef QMap DescriptionsMap; // Key, description - -typedef unsigned int uint; - -// MACRO BEGIN - -#define PARAMETER_GETTER_bool(PREFIX, NAME) \ - static bool get##PREFIX##_##NAME() {return parameters_.value(#PREFIX "/" #NAME).toBool();} -#define PARAMETER_GETTER_int(PREFIX, NAME) \ - static int get##PREFIX##_##NAME() {return parameters_.value(#PREFIX "/" #NAME).toInt();} -#define PARAMETER_GETTER_uint(PREFIX, NAME) \ - static uint get##PREFIX##_##NAME() {return parameters_.value(#PREFIX "/" #NAME).toUInt();} -#define PARAMETER_GETTER_float(PREFIX, NAME) \ - static float get##PREFIX##_##NAME() {return parameters_.value(#PREFIX "/" #NAME).toFloat();} -#define PARAMETER_GETTER_double(PREFIX, NAME) \ - static double get##PREFIX##_##NAME() {return parameters_.value(#PREFIX "/" #NAME).toDouble();} -#define PARAMETER_GETTER_QString(PREFIX, NAME) \ - static QString get##PREFIX##_##NAME() {return parameters_.value(#PREFIX "/" #NAME).toString();} - -#define PARAMETER(PREFIX, NAME, TYPE, DEFAULT_VALUE, DESCRIPTION) \ - public: \ - static QString k##PREFIX##_##NAME() {return QString(#PREFIX "/" #NAME);} \ - static TYPE default##PREFIX##_##NAME() {return DEFAULT_VALUE;} \ - static QString type##PREFIX##_##NAME() {return QString(#TYPE);} \ - static QString description##PREFIX##_##NAME() {return QString(DESCRIPTION);} \ - PARAMETER_GETTER_##TYPE(PREFIX, NAME) \ - static void set##PREFIX##_##NAME(const TYPE & value) {parameters_[#PREFIX "/" #NAME] = value;} \ - private: \ - class Dummy##PREFIX##_##NAME { \ - public: \ - Dummy##PREFIX##_##NAME() { \ - defaultParameters_.insert(#PREFIX "/" #NAME, QVariant(DEFAULT_VALUE)); \ - parameters_.insert(#PREFIX "/" #NAME, DEFAULT_VALUE); \ - parametersType_.insert(#PREFIX "/" #NAME, #TYPE); \ - descriptions_.insert(#PREFIX "/" #NAME, DESCRIPTION);} \ - }; \ - Dummy##PREFIX##_##NAME dummy##PREFIX##_##NAME; - -#define PARAMETER_COND(PREFIX, NAME, TYPE, COND, DEFAULT_VALUE1, DEFAULT_VALUE2, DESCRIPTION) \ - public: \ - static QString k##PREFIX##_##NAME() {return QString(#PREFIX "/" #NAME);} \ - static TYPE default##PREFIX##_##NAME() {return COND?DEFAULT_VALUE1:DEFAULT_VALUE2;} \ - static QString type##PREFIX##_##NAME() {return QString(#TYPE);} \ - static QString description##PREFIX##_##NAME() {return QString(DESCRIPTION);} \ - PARAMETER_GETTER_##TYPE(PREFIX, NAME) \ - static void set##PREFIX##_##NAME(const TYPE & value) {parameters_[#PREFIX "/" #NAME] = value;} \ - private: \ - class Dummy##PREFIX##_##NAME { \ - public: \ - Dummy##PREFIX##_##NAME() { \ - defaultParameters_.insert(#PREFIX "/" #NAME, QVariant(COND?DEFAULT_VALUE1:DEFAULT_VALUE2)); \ - parameters_.insert(#PREFIX "/" #NAME, COND?DEFAULT_VALUE1:DEFAULT_VALUE2); \ - parametersType_.insert(#PREFIX "/" #NAME, #TYPE); \ - descriptions_.insert(#PREFIX "/" #NAME, DESCRIPTION);} \ - }; \ - Dummy##PREFIX##_##NAME dummy##PREFIX##_##NAME; -// MACRO END - -class FINDOBJECT_EXP Settings -{ - PARAMETER(Camera, 1deviceId, int, 0, "Device ID (default 0)."); - PARAMETER(Camera, 2imageWidth, int, 0, "Image width (0 means default width from camera)."); - PARAMETER(Camera, 3imageHeight, int, 0, "Image height (0 means default height from camera)."); - PARAMETER(Camera, 4imageRate, double, 10.0, "Image rate in Hz (0 Hz means as fast as possible)."); // Hz - PARAMETER(Camera, 5mediaPath, QString, "", "Video file or directory of images. If set, the camera is not used. See General->videoFormats and General->imageFormats for available formats."); - PARAMETER(Camera, 6useTcpCamera, bool, false, "Use TCP/IP input camera."); - PARAMETER(Camera, 8port, int, 0, "The images server's port when useTcpCamera is checked. Only one client at the same time is allowed."); - PARAMETER(Camera, 9queueSize, int, 1, "Maximum images buffered from TCP. If 0, all images are buffered."); - - //List format : [Index:item0;item1;item3;...] -#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11))) -#if CV_MAJOR_VERSION >= 3 // NONFREE=SURF, DEFAULT=KAZE - PARAMETER_COND(Feature2D, 1Detector, QString, FINDOBJECT_NONFREE, "7:Dense;Fast;GFTT;MSER;ORB;SIFT;Star;SURF;BRISK;AGAST;KAZE;AKAZE;SuperPointTorch" , "10:Dense;Fast;GFTT;MSER;ORB;SIFT;Star;SURF;BRISK;AGAST;KAZE;AKAZE;SuperPointTorch", "Keypoint detector."); - PARAMETER_COND(Feature2D, 2Descriptor, QString, FINDOBJECT_NONFREE, "3:Brief;ORB;SIFT;SURF;BRISK;FREAK;KAZE;AKAZE;LUCID;LATCH;DAISY;SuperPointTorch", "6:Brief;ORB;SIFT;SURF;BRISK;FREAK;KAZE;AKAZE;LUCID;LATCH;DAISY;SuperPointTorch", "Keypoint descriptor."); -#else // NONFREE=SURF, DEFAULT=ORB - PARAMETER_COND(Feature2D, 1Detector, QString, FINDOBJECT_NONFREE, "7:Dense;Fast;GFTT;MSER;ORB;SIFT;Star;SURF;BRISK;AGAST;KAZE;AKAZE;SuperPointTorch" , "4:Dense;Fast;GFTT;MSER;ORB;SIFT;Star;SURF;BRISK;AGAST;KAZE;AKAZE;SuperPointTorch", "Keypoint detector."); - PARAMETER_COND(Feature2D, 2Descriptor, QString, FINDOBJECT_NONFREE, "3:Brief;ORB;SIFT;SURF;BRISK;FREAK;KAZE;AKAZE;LUCID;LATCH;DAISY;SuperPointTorch", "1:Brief;ORB;SIFT;SURF;BRISK;FREAK;KAZE;AKAZE;LUCID;LATCH;DAISY;SuperPointTorch", "Keypoint descriptor."); -#endif -#else // >=4.4 >=3.4.11: NONFREE=SURF, DEFAULT=SIFT - PARAMETER_COND(Feature2D, 1Detector, QString, FINDOBJECT_NONFREE, "7:Dense;Fast;GFTT;MSER;ORB;SIFT;Star;SURF;BRISK;AGAST;KAZE;AKAZE;SuperPointTorch" , "5:Dense;Fast;GFTT;MSER;ORB;SIFT;Star;SURF;BRISK;AGAST;KAZE;AKAZE;SuperPointTorch", "Keypoint detector."); - PARAMETER_COND(Feature2D, 2Descriptor, QString, FINDOBJECT_NONFREE, "3:Brief;ORB;SIFT;SURF;BRISK;FREAK;KAZE;AKAZE;LUCID;LATCH;DAISY;SuperPointTorch", "2:Brief;ORB;SIFT;SURF;BRISK;FREAK;KAZE;AKAZE;LUCID;LATCH;DAISY;SuperPointTorch", "Keypoint descriptor."); -#endif - PARAMETER(Feature2D, 3MaxFeatures, int, 0, "Maximum features per image. If the number of features extracted is over this threshold, only X features with the highest response are kept. 0 means all features are kept."); - PARAMETER(Feature2D, 4Affine, bool, false, "(ASIFT) Extract features on multiple affine transformations of the image."); - PARAMETER(Feature2D, 5AffineCount, int, 6, "(ASIFT) Higher the value, more affine transformations will be done."); - PARAMETER(Feature2D, 6SubPix, bool, false, "Refines the corner locations. With SIFT/SURF, features are already subpixel, so no need to activate this."); - PARAMETER(Feature2D, 7SubPixWinSize, int, 3, "Half of the side length of the search window. For example, if winSize=Size(5,5) , then a 5*2+1 x 5*2+1 = 11 x 11 search window is used."); - PARAMETER(Feature2D, 8SubPixIterations, int, 30, "The process of corner position refinement stops after X iterations."); - PARAMETER(Feature2D, 9SubPixEps, float, 0.02f, "The process of corner position refinement stops when the corner position moves by less than epsilon on some iteration."); - - PARAMETER(Feature2D, Brief_bytes, int, 32, "Bytes is a length of descriptor in bytes. It can be equal 16, 32 or 64 bytes."); - -#if CV_MAJOR_VERSION < 3 - PARAMETER(Feature2D, Dense_initFeatureScale, float, 1.f, ""); - PARAMETER(Feature2D, Dense_featureScaleLevels, int, 1, ""); - PARAMETER(Feature2D, Dense_featureScaleMul, float, 0.1f, ""); - PARAMETER(Feature2D, Dense_initXyStep, int, 6, ""); - PARAMETER(Feature2D, Dense_initImgBound, int, 0, ""); - PARAMETER(Feature2D, Dense_varyXyStepWithScale, bool, true, ""); - PARAMETER(Feature2D, Dense_varyImgBoundWithScale, bool, false, ""); -#endif - - PARAMETER(Feature2D, Fast_threshold, int, 10, "Threshold on difference between intensity of the central pixel and pixels of a circle around this pixel."); - PARAMETER(Feature2D, Fast_nonmaxSuppression, bool, true, "If true, non-maximum suppression is applied to detected corners (keypoints)."); - PARAMETER(Feature2D, Fast_gpu, bool, false, "GPU-FAST: Use GPU version of FAST. This option is enabled only if OpenCV is built with CUDA and GPUs are detected."); - PARAMETER(Feature2D, Fast_keypointsRatio, double, 0.05, "Used with FAST GPU (OpenCV 2)."); - PARAMETER(Feature2D, Fast_maxNpoints, int, 5000, "Used with FAST GPU (OpenCV 3)."); - - PARAMETER(Feature2D, AGAST_threshold, int, 10, "Threshold on difference between intensity of the central pixel and pixels of a circle around this pixel."); - PARAMETER(Feature2D, AGAST_nonmaxSuppression, bool, true, "If true, non-maximum suppression is applied to detected corners (keypoints)."); - - PARAMETER(Feature2D, KAZE_extended, bool, false, "Set to enable extraction of extended (128-byte) descriptor."); - PARAMETER(Feature2D, KAZE_upright, bool, false, "Set to enable use of upright descriptors (non rotation-invariant)."); - PARAMETER(Feature2D, KAZE_threshold, float, 0.001f, "Detector response threshold to accept point"); - PARAMETER(Feature2D, KAZE_nOctaves, int, 4, "Maximum octave evolution of the image."); - PARAMETER(Feature2D, KAZE_nOctaveLayers, int, 4, "Default number of sublevels per scale level."); - - PARAMETER(Feature2D, AKAZE_descriptorSize, int, 0, "Size of the descriptor in bits. 0 -> Full size."); - PARAMETER(Feature2D, AKAZE_descriptorChannels, int, 3, "Number of channels in the descriptor (1, 2, 3)."); - PARAMETER(Feature2D, AKAZE_threshold, float, 0.001f, "Detector response threshold to accept point."); - PARAMETER(Feature2D, AKAZE_nOctaves, int, 4, "Maximum octave evolution of the image."); - PARAMETER(Feature2D, AKAZE_nOctaveLayers, int, 4, "Default number of sublevels per scale level."); - - PARAMETER(Feature2D, GFTT_maxCorners, int, 1000, "Maximum number of corners to return. If there are more corners than are found, the strongest of them is returned."); - PARAMETER(Feature2D, GFTT_qualityLevel, double, 0.01, "Parameter characterizing the minimal accepted quality of image corners. The parameter value is multiplied by the best corner quality measure, which is the minimal eigenvalue (see cornerMinEigenVal ) or the Harris function response (see cornerHarris ). The corners with the quality measure less than the product are rejected. For example, if the best corner has the quality measure = 1500, and the qualityLevel=0.01 , then all the corners with the quality measure less than 15 are rejected."); - PARAMETER(Feature2D, GFTT_minDistance, double, 1, "Minimum possible Euclidean distance between the returned corners."); - PARAMETER(Feature2D, GFTT_blockSize, int, 3, "Size of an average block for computing a derivative covariation matrix over each pixel neighborhood. See cornerEigenValsAndVecs."); - PARAMETER(Feature2D, GFTT_useHarrisDetector, bool, false, "Parameter indicating whether to use a Harris detector (see cornerHarris) or cornerMinEigenVal."); - PARAMETER(Feature2D, GFTT_k, double, 0.04, "Free parameter of the Harris detector."); - - PARAMETER(Feature2D, ORB_nFeatures, int, 500, "The maximum number of features to retain."); - PARAMETER(Feature2D, ORB_scaleFactor, float, 1.2f, "Pyramid decimation ratio, greater than 1. scaleFactor==2 means the classical pyramid, where each next level has 4x less pixels than the previous, but such a big scale factor will degrade feature matching scores dramatically. On the other hand, too close to 1 scale factor will mean that to cover certain scale range you will need more pyramid levels and so the speed will suffer."); - PARAMETER(Feature2D, ORB_nLevels, int, 8, "The number of pyramid levels. The smallest level will have linear size equal to input_image_linear_size/pow(scaleFactor, nlevels)."); - PARAMETER(Feature2D, ORB_edgeThreshold, int, 31, "This is size of the border where the features are not detected. It should roughly match the patchSize parameter."); - PARAMETER(Feature2D, ORB_firstLevel, int, 0, "It should be 0 in the current implementation."); - PARAMETER(Feature2D, ORB_WTA_K, int, 2, "The number of points that produce each element of the oriented BRIEF descriptor. The default value 2 means the BRIEF where we take a random point pair and compare their brightnesses, so we get 0/1 response. Other possible values are 3 and 4. For example, 3 means that we take 3 random points (of course, those point coordinates are random, but they are generated from the pre-defined seed, so each element of BRIEF descriptor is computed deterministically from the pixel rectangle), find point of maximum brightness and output index of the winner (0, 1 or 2). Such output will occupy 2 bits, and therefore it will need a special variant of Hamming distance, denoted as NORM_HAMMING2 (2 bits per bin). When WTA_K=4, we take 4 random points to compute each bin (that will also occupy 2 bits with possible values 0, 1, 2 or 3)."); - PARAMETER(Feature2D, ORB_scoreType, int, 0, "The default HARRIS_SCORE=0 means that Harris algorithm is used to rank features (the score is written to KeyPoint::score and is used to retain best nfeatures features); FAST_SCORE=1 is alternative value of the parameter that produces slightly less stable keypoints, but it is a little faster to compute."); - PARAMETER(Feature2D, ORB_patchSize, int, 31, "size of the patch used by the oriented BRIEF descriptor. Of course, on smaller pyramid layers the perceived image area covered by a feature will be larger."); - PARAMETER(Feature2D, ORB_gpu, bool, false, "GPU-ORB: Use GPU version of ORB. This option is enabled only if OpenCV is built with CUDA and GPUs are detected."); - PARAMETER(Feature2D, ORB_blurForDescriptor, bool, false, "GPU-ORB: blurForDescriptor parameter (OpenCV 3)."); - - PARAMETER(Feature2D, MSER_delta, int, 5, ""); - PARAMETER(Feature2D, MSER_minArea, int, 60, ""); - PARAMETER(Feature2D, MSER_maxArea, int, 14400, ""); - PARAMETER(Feature2D, MSER_maxVariation, double, 0.25, ""); - PARAMETER(Feature2D, MSER_minDiversity, double, 0.2, ""); - PARAMETER(Feature2D, MSER_maxEvolution, int, 200, ""); - PARAMETER(Feature2D, MSER_areaThreshold, double, 1.01, ""); - PARAMETER(Feature2D, MSER_minMargin, double, 0.003, ""); - PARAMETER(Feature2D, MSER_edgeBlurSize, int, 5, ""); - - PARAMETER(Feature2D, SIFT_nfeatures, int, 0, "The number of best features to retain. The features are ranked by their scores (measured in SIFT algorithm as the local contrast)."); - PARAMETER(Feature2D, SIFT_nOctaveLayers, int, 3, "The number of layers in each octave. 3 is the value used in D. Lowe paper. The number of octaves is computed automatically from the image resolution."); - PARAMETER(Feature2D, SIFT_contrastThreshold, double, 0.04, "The contrast threshold used to filter out weak features in semi-uniform (low-contrast) regions. The larger the threshold, the less features are produced by the detector."); - PARAMETER(Feature2D, SIFT_edgeThreshold, double, 10, "The threshold used to filter out edge-like features. Note that the its meaning is different from the contrastThreshold, i.e. the larger the edgeThreshold, the less features are filtered out (more features are retained)."); - PARAMETER(Feature2D, SIFT_sigma, double, 1.6, "The sigma of the Gaussian applied to the input image at the octave #0. If your image is captured with a weak camera with soft lenses, you might want to reduce the number."); - PARAMETER(Feature2D, SIFT_rootSIFT, bool, false, "RootSIFT descriptors."); - - PARAMETER(Feature2D, SURF_hessianThreshold, double, 600.0, "Threshold for hessian keypoint detector used in SURF."); - PARAMETER(Feature2D, SURF_nOctaves, int, 4, "Number of pyramid octaves the keypoint detector will use."); - PARAMETER(Feature2D, SURF_nOctaveLayers, int, 2, "Number of octave layers within each octave."); - PARAMETER(Feature2D, SURF_extended, bool, true, "Extended descriptor flag (true - use extended 128-element descriptors; false - use 64-element descriptors)."); - PARAMETER(Feature2D, SURF_upright, bool, false, "Up-right or rotated features flag (true - do not compute orientation of features; false - compute orientation)."); - PARAMETER(Feature2D, SURF_gpu, bool, false, "GPU-SURF: Use GPU version of SURF. This option is enabled only if OpenCV is built with CUDA and GPUs are detected."); - PARAMETER(Feature2D, SURF_keypointsRatio, float, 0.01f, "Used with SURF GPU."); - - PARAMETER(Feature2D, Star_maxSize, int, 45, ""); - PARAMETER(Feature2D, Star_responseThreshold, int, 30, ""); - PARAMETER(Feature2D, Star_lineThresholdProjected, int, 10, ""); - PARAMETER(Feature2D, Star_lineThresholdBinarized, int, 8, ""); - PARAMETER(Feature2D, Star_suppressNonmaxSize, int, 5, ""); - - PARAMETER(Feature2D, BRISK_thresh, int, 30, "FAST/AGAST detection threshold score."); - PARAMETER(Feature2D, BRISK_octaves, int, 3, "Detection octaves. Use 0 to do single scale."); - PARAMETER(Feature2D, BRISK_patternScale, float, 1.0f, "Apply this scale to the pattern used for sampling the neighbourhood of a keypoint."); - - PARAMETER(Feature2D, FREAK_orientationNormalized, bool, true, "Enable orientation normalization."); - PARAMETER(Feature2D, FREAK_scaleNormalized, bool, true, "Enable scale normalization."); - PARAMETER(Feature2D, FREAK_patternScale, float, 22.0f, "Scaling of the description pattern."); - PARAMETER(Feature2D, FREAK_nOctaves, int, 4, "Number of octaves covered by the detected keypoints."); - - PARAMETER(Feature2D, LUCID_kernel, int, 1, "Kernel for descriptor construction, where 1=3x3, 2=5x5, 3=7x7 and so forth."); - PARAMETER(Feature2D, LUCID_blur_kernel, int, 2, "Kernel for blurring image prior to descriptor construction, where 1=3x3, 2=5x5, 3=7x7 and so forth."); - - PARAMETER(Feature2D, LATCH_bytes, int, 32, "Size of the descriptor - can be 64, 32, 16, 8, 4, 2 or 1."); - PARAMETER(Feature2D, LATCH_rotationInvariance, bool, true, "Whether or not the descriptor should compansate for orientation changes."); - PARAMETER(Feature2D, LATCH_half_ssd_size, int, 3, "The size of half of the mini-patches size. For example, if we would like to compare triplets of patches of size 7x7x then the half_ssd_size should be (7-1)/2 = 3."); - - PARAMETER(Feature2D, DAISY_radius, float, 15, "Radius of the descriptor at the initial scale."); - PARAMETER(Feature2D, DAISY_q_radius, int, 3, "Amount of radial range division quantity."); - PARAMETER(Feature2D, DAISY_q_theta, int, 8, "Amount of angular range division quantity."); - PARAMETER(Feature2D, DAISY_q_hist, int, 8, "Amount of gradient orientations range division quantity."); - PARAMETER(Feature2D, DAISY_interpolation, bool, true, "Switch to disable interpolation for speed improvement at minor quality loss."); - PARAMETER(Feature2D, DAISY_use_orientation, bool, false, "Sample patterns using keypoints orientation, disabled by default."); - - PARAMETER(Feature2D, SuperPointTorch_modelPath, QString, "", "[Required] Path to pre-trained weights Torch file of SuperPoint (*.pt)."); - PARAMETER(Feature2D, SuperPointTorch_threshold, float, 0.2, "Detector response threshold to accept keypoint."); - PARAMETER(Feature2D, SuperPointTorch_NMS, bool, true, "If true, non-maximum suppression is applied to detected keypoints."); - PARAMETER(Feature2D, SuperPointTorch_NMS_radius, int, 4, "[%s=true] Minimum distance (pixels) between keypoints"); - PARAMETER(Feature2D, SuperPointTorch_cuda, bool, false, "Use Cuda device for Torch, otherwise CPU device is used by default."); - - PARAMETER_COND(NearestNeighbor, 1Strategy, QString, FINDOBJECT_NONFREE || CV_MAJOR_VERSION >= 3, "1:Linear;KDTree;KMeans;Composite;Autotuned;Lsh;BruteForce", "6:Linear;KDTree;KMeans;Composite;Autotuned;Lsh;BruteForce", "Nearest neighbor strategy."); - PARAMETER_COND(NearestNeighbor, 2Distance_type, QString, FINDOBJECT_NONFREE || CV_MAJOR_VERSION >= 3, "0:EUCLIDEAN_L2;MANHATTAN_L1;MINKOWSKI;MAX;HIST_INTERSECT;HELLINGER;CHI_SQUARE_CS;KULLBACK_LEIBLER_KL;HAMMING", "1:EUCLIDEAN_L2;MANHATTAN_L1;MINKOWSKI;MAX;HIST_INTERSECT;HELLINGER;CHI_SQUARE_CS;KULLBACK_LEIBLER_KL;HAMMING", "Distance type."); - PARAMETER(NearestNeighbor, 3nndrRatioUsed, bool, true, "Nearest neighbor distance ratio approach to accept the best match."); - PARAMETER(NearestNeighbor, 4nndrRatio, float, 0.8f, "Nearest neighbor distance ratio."); - PARAMETER(NearestNeighbor, 5minDistanceUsed, bool, false, "Minimum distance with the nearest descriptor to accept a match."); - PARAMETER(NearestNeighbor, 6minDistance, float, 1.6f, "Minimum distance. You can look at top of this panel where minimum and maximum distances are shown to properly set this parameter depending of the descriptor used."); - PARAMETER(NearestNeighbor, 7ConvertBinToFloat, bool, false, "Convert binary descriptor to float before quantization, so you can use FLANN strategies with them."); - - - PARAMETER(NearestNeighbor, BruteForce_gpu, bool, false, "Brute force GPU"); - - PARAMETER(NearestNeighbor, search_checks, int, 32, "The number of times the tree(s) in the index should be recursively traversed. A higher value for this parameter would give better search precision, but also take more time. If automatic configuration was used when the index was created, the number of checks required to achieve the specified precision was also computed, in which case this parameter is ignored."); - PARAMETER(NearestNeighbor, search_eps, float, 0, ""); - PARAMETER(NearestNeighbor, search_sorted, bool, true, ""); - - PARAMETER(NearestNeighbor, KDTree_trees, int, 4, "The number of parallel kd-trees to use. Good values are in the range [1..16]."); - - PARAMETER(NearestNeighbor, Composite_trees, int, 4, "The number of parallel kd-trees to use. Good values are in the range [1..16]."); - PARAMETER(NearestNeighbor, Composite_branching, int, 32, "The branching factor to use for the hierarchical k-means tree."); - PARAMETER(NearestNeighbor, Composite_iterations, int, 11, "The maximum number of iterations to use in the k-means clustering stage when building the k-means tree. A value of -1 used here means that the k-means clustering should be iterated until convergence."); - PARAMETER(NearestNeighbor, Composite_centers_init, QString, "0:RANDOM;GONZALES;KMEANSPP", "The algorithm to use for selecting the initial centers when performing a k-means clustering step. The possible values are CENTERS_RANDOM (picks the initial cluster centers randomly), CENTERS_GONZALES (picks the initial centers using Gonzales’ algorithm) and CENTERS_KMEANSPP (picks the initial centers using the algorithm suggested in arthur_kmeanspp_2007 )."); - PARAMETER(NearestNeighbor, Composite_cb_index, double, 0.2, "This parameter (cluster boundary index) influences the way exploration is performed in the hierarchical kmeans tree. When cb_index is zero the next kmeans domain to be explored is chosen to be the one with the closest center. A value greater then zero also takes into account the size of the domain."); - - PARAMETER(NearestNeighbor, Autotuned_target_precision, double, 0.8, "Is a number between 0 and 1 specifying the percentage of the approximate nearest-neighbor searches that return the exact nearest-neighbor. Using a higher value for this parameter gives more accurate results, but the search takes longer. The optimum value usually depends on the application."); - PARAMETER(NearestNeighbor, Autotuned_build_weight, double, 0.01, "Specifies the importance of the index build time raported to the nearest-neighbor search time. In some applications it’s acceptable for the index build step to take a long time if the subsequent searches in the index can be performed very fast. In other applications it’s required that the index be build as fast as possible even if that leads to slightly longer search times."); - PARAMETER(NearestNeighbor, Autotuned_memory_weight, double, 0, "Is used to specify the tradeoff between time (index build time and search time) and memory used by the index. A value less than 1 gives more importance to the time spent and a value greater than 1 gives more importance to the memory usage."); - PARAMETER(NearestNeighbor, Autotuned_sample_fraction, double, 0.1, "Is a number between 0 and 1 indicating what fraction of the dataset to use in the automatic parameter configuration algorithm. Running the algorithm on the full dataset gives the most accurate results, but for very large datasets can take longer than desired. In such case using just a fraction of the data helps speeding up this algorithm while still giving good approximations of the optimum parameters."); - - PARAMETER(NearestNeighbor, KMeans_branching, int, 32, "The branching factor to use for the hierarchical k-means tree."); - PARAMETER(NearestNeighbor, KMeans_iterations, int, 11, "The maximum number of iterations to use in the k-means clustering stage when building the k-means tree. A value of -1 used here means that the k-means clustering should be iterated until convergence."); - PARAMETER(NearestNeighbor, KMeans_centers_init, QString, "0:RANDOM;GONZALES;KMEANSPP", "The algorithm to use for selecting the initial centers when performing a k-means clustering step. The possible values are CENTERS_RANDOM (picks the initial cluster centers randomly), CENTERS_GONZALES (picks the initial centers using Gonzales’ algorithm) and CENTERS_KMEANSPP (picks the initial centers using the algorithm suggested in arthur_kmeanspp_2007 )."); - PARAMETER(NearestNeighbor, KMeans_cb_index, double, 0.2, "This parameter (cluster boundary index) influences the way exploration is performed in the hierarchical kmeans tree. When cb_index is zero the next kmeans domain to be explored is chosen to be the one with the closest center. A value greater then zero also takes into account the size of the domain."); - - PARAMETER(NearestNeighbor, Lsh_table_number, int, 12, "The number of hash tables to use (between 10 and 30 usually)."); - PARAMETER(NearestNeighbor, Lsh_key_size, int, 20, "The size of the hash key in bits (between 10 and 20 usually)."); - PARAMETER(NearestNeighbor, Lsh_multi_probe_level, int, 2, "The number of bits to shift to check for neighboring buckets (0 is regular LSH, 2 is recommended)."); - - PARAMETER(General, autoStartCamera, bool, false, "Automatically start the camera when the application is opened."); - PARAMETER(General, autoUpdateObjects, bool, true, "Automatically update objects on every parameter changes, otherwise you would need to press \"Update objects\" on the objects panel."); - PARAMETER(General, nextObjID, uint, 1, "Next object ID to use."); - PARAMETER(General, imageFormats, QString, "*.png *.jpg *.bmp *.tiff *.ppm *.pgm", "Image formats supported."); - PARAMETER(General, videoFormats, QString, "*.avi *.m4v *.mp4", "Video formats supported."); - PARAMETER(General, mirrorView, bool, false, "Flip the camera image horizontally (like all webcam applications)."); - PARAMETER(General, invertedSearch, bool, true, "Instead of matching descriptors from the objects to those in a vocabulary created with descriptors extracted from the scene, we create a vocabulary from all the objects' descriptors and we match scene's descriptors to this vocabulary. It is the inverted search mode."); - PARAMETER(General, controlsShown, bool, false, "Show play/image seek controls (useful with video file and directory of images modes)."); - PARAMETER(General, threads, int, 1, "Number of threads used for objects matching and homography computation. 0 means as many threads as objects. On InvertedSearch mode, multi-threading has only effect on homography computation."); - PARAMETER(General, multiDetection, bool, false, "Multiple detection of the same object."); - PARAMETER(General, multiDetectionRadius, int, 30, "Ignore detection of the same object in X pixels radius of the previous detections."); - PARAMETER(General, port, int, 0, "Port on objects detected are published. If port=0, a port is chosen automatically.") - PARAMETER(General, autoScroll, bool, true, "Auto scroll to detected object in Objects panel."); - PARAMETER(General, vocabularyFixed, bool, false, "If the vocabulary is fixed, no new words will be added to it when adding new objects."); - PARAMETER(General, vocabularyIncremental, bool, false, "The vocabulary is created incrementally. When new objects are added, their descriptors are compared to those already in vocabulary to find if the visual word already exist or not. \"NearestNeighbor/nndrRatio\" and \"NearestNeighbor/minDistance\" are used to compare descriptors."); - PARAMETER(General, vocabularyUpdateMinWords, int, 2000, "When the vocabulary is incremental (see \"General/vocabularyIncremental\"), after X words added to vocabulary, the internal index is updated with new words. This parameter lets avoiding to reconstruct the whole nearest neighbor index after each time descriptors of an object are added to vocabulary. 0 means no incremental update."); - PARAMETER(General, sendNoObjDetectedEvents, bool, true, "When there are no objects detected, send an empty object detection event."); - PARAMETER(General, autoPauseOnDetection, bool, false, "Auto pause the camera when an object is detected."); - PARAMETER(General, autoScreenshotPath, QString, "", "Path to a directory to save screenshot of the current camera view when there is a detection."); - PARAMETER(General, debug, bool, false, "Show debug logs on terminal."); - - PARAMETER(Homography, homographyComputed, bool, true, "Compute homography? On ROS, this is required to publish objects detected."); - PARAMETER(Homography, method, QString, "1:LMEDS;RANSAC;RHO", "Type of the robust estimation algorithm: least-median algorithm or RANSAC algorithm."); - PARAMETER(Homography, ransacReprojThr, double, 3.0, "Maximum allowed reprojection error to treat a point pair as an inlier (used in the RANSAC method only). It usually makes sense to set this parameter somewhere in the range of 1 to 10."); -#if CV_MAJOR_VERSION >= 3 - PARAMETER(Homography, maxIterations, int, 2000, "The maximum number of RANSAC iterations, 2000 is the maximum it can be."); - PARAMETER(Homography, confidence, double, 0.995, "Confidence level, between 0 and 1."); -#endif - PARAMETER(Homography, minimumInliers, int, 10, "Minimum inliers to accept the homography. Value must be >= 4."); - PARAMETER(Homography, ignoreWhenAllInliers, bool, false, "Ignore homography when all features are inliers (sometimes when the homography doesn't converge, it returns the best homography with all features as inliers)."); - PARAMETER(Homography, rectBorderWidth, int, 4, "Homography rectangle border width."); - PARAMETER(Homography, allCornersVisible, bool, false, "All corners of the detected object must be visible in the scene."); - PARAMETER(Homography, minAngle, int, 0, "(Degrees) Homography minimum angle. Set 0 to disable. When the angle is very small, this is a good indication that the homography is wrong. A good value is over 60 degrees."); - PARAMETER(Homography, opticalFlow, bool, false, "Activate optical flow to refine matched features before computing the homography."); - PARAMETER(Homography, opticalFlowWinSize, int, 16, "Size of the search window at each pyramid level."); - PARAMETER(Homography, opticalFlowMaxLevel, int, 3, "0-based maximal pyramid level number; if set to 0, pyramids are not used (single level), if set to 1, two levels are used, and so on; if pyramids are passed to input then algorithm will use as many levels as pyramids have but no more than maxLevel."); - PARAMETER(Homography, opticalFlowIterations, int, 30, "Specifying the termination criteria of the iterative search algorithm (after the specified maximum number of iterations)."); - PARAMETER(Homography, opticalFlowEps, float, 0.01f, "Specifying the termination criteria of the iterative search algorithm (when the search window moves by less than epsilon)."); - -public: - virtual ~Settings(){} - - static QString workingDirectory(); - static QString iniDefaultPath(); - static QString iniDefaultFileName() {return "config.ini";} - static QString iniPath(); - - static ParametersMap init(const QString & fileName); - - static ParametersMap loadSettings(const QString & fileName = QString()); - static void loadWindowSettings(QByteArray & windowGeometry, QByteArray & windowState, const QString & fileName = QString()); - static void saveSettings(const QString & fileName = QString()); - static void saveWindowSettings(const QByteArray & windowGeometry, const QByteArray & windowState, const QString & fileName = QString()); - - static const ParametersMap & getDefaultParameters() {return defaultParameters_;} - static const ParametersMap & getParameters() {return parameters_;} - static const ParametersType & getParametersType() {return parametersType_;} - static const DescriptionsMap & getDescriptions() {return descriptions_;} - static void setParameter(const QString & key, const QVariant & value) {if(parameters_.contains(key))parameters_[key] = value;} - static void resetParameter(const QString & key) {if(defaultParameters_.contains(key)) parameters_.insert(key, defaultParameters_.value(key));} - static QVariant getParameter(const QString & key) {return parameters_.value(key, QVariant());} - - static Feature2D * createKeypointDetector(); - static Feature2D * createDescriptorExtractor(); - - static QString currentDescriptorType(); - static QString currentDetectorType(); - static QString currentNearestNeighborType(); - - static bool isBruteForceNearestNeighbor(); - static cv::flann::IndexParams * createFlannIndexParams(); - static cvflann::flann_distance_t getFlannDistanceType(); - - static int getHomographyMethod(); - -private: - Settings(){} - -private: - static ParametersMap defaultParameters_; - static ParametersMap parameters_; - static ParametersType parametersType_; - static DescriptionsMap descriptions_; - static Settings dummyInit_; - static QString iniPath_; -}; - -class Feature2D -{ -public: -#if CV_MAJOR_VERSION < 3 - Feature2D(cv::Ptr featureDetector); - Feature2D(cv::Ptr descriptorExtractor); -#endif - Feature2D(cv::Ptr feature2D); - Feature2D() {} - virtual ~Feature2D() {} - - virtual void detect(const cv::Mat & image, - std::vector & keypoints, - const cv::Mat & mask = cv::Mat()); - - virtual void compute(const cv::Mat & image, - std::vector & keypoints, - cv::Mat & descriptors); - - virtual void detectAndCompute(const cv::Mat & image, - std::vector & keypoints, - cv::Mat & descriptors, - const cv::Mat & mask = cv::Mat()); - -private: -#if CV_MAJOR_VERSION < 3 - cv::Ptr featureDetector_; - cv::Ptr descriptorExtractor_; -#endif - cv::Ptr feature2D_; -}; - -} // namespace find_object - -#endif /* SETTINGS_H_ */ diff --git a/find-object/include/find_object/TcpServer.h b/find-object/include/find_object/TcpServer.h deleted file mode 100644 index 5a82f9ad..00000000 --- a/find-object/include/find_object/TcpServer.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef TCPSERVER_H_ -#define TCPSERVER_H_ - -#include "find_object/FindObjectExp.h" // DLL export/import defines - -#include "find_object/DetectionInfo.h" -#include - -#include - -namespace find_object { - -class QNetworkSession; - -class FINDOBJECT_EXP TcpServer : public QTcpServer -{ - Q_OBJECT - -public: - enum Service { - kAddObject, // id fileName imageSize image - kRemoveObject, // id - kDetectObject // image - }; - -public: - TcpServer(quint16 port = 0, QObject * parent = 0); - - QHostAddress getHostAddress() const; - quint16 getPort() const; - -public Q_SLOTS: - void publishDetectionInfo(const find_object::DetectionInfo & info); - -private Q_SLOTS: - void addClient(); - void readReceivedData(); - void displayError(QAbstractSocket::SocketError socketError); - void connectionLost(); - -Q_SIGNALS: - void addObject(const cv::Mat &, int, const QString &); - void removeObject(int); - void detectObject(const cv::Mat &); - -private: - QMap blockSizes_; -}; - -} // namespace find_object - -#endif /* TCPSERVER_H_ */ diff --git a/find-object/include/find_object/utilite/UDestroyer.h b/find-object/include/find_object/utilite/UDestroyer.h deleted file mode 100644 index de0ad8e3..00000000 --- a/find-object/include/find_object/utilite/UDestroyer.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -* utilite is a cross-platform library with -* useful utilities for fast and small developing. -* Copyright (C) 2010 Mathieu Labbe -* -* utilite is free library: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* utilite is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this program. If not, see . -*/ - -#ifndef UDESTROYER_H -#define UDESTROYER_H - -//#include "utilite/UtiLiteExp.h" // DLL export/import defines - -/** - * This class is used to delete a dynamically created - * objects. It was mainly designed to remove dynamically created Singleton. - * Created on the stack of a Singleton, when the - * application is finished, his destructor make sure that the - * Singleton is deleted. - * - */ -template -class UDestroyer -{ -public: - /** - * The constructor. Set the doomed object (take ownership of the object). The object is deleted - * when this object is deleted. - */ - UDestroyer(T* doomed = 0) : doomed_(doomed) {} - - ~UDestroyer() - { - if(doomed_) - { - delete doomed_; - doomed_ = 0; - } - } - - /** - * Set the doomed object. If a doomed object is already set, the function returns false. - * @param doomed the doomed object - * @return false if an object is already set and the new object is not null, otherwise true - */ - bool setDoomed(T* doomed) - { - if(doomed_ && doomed) - { - return false; - } - doomed_ = doomed; - return true; - } - -private: - // Prevent users from making copies of a - // Destroyer to avoid double deletion: - UDestroyer(const UDestroyer&); - void operator=(const UDestroyer&); - -private: - T* doomed_; -}; - -#endif // UDESTROYER_H diff --git a/find-object/include/find_object/utilite/ULogger.h b/find-object/include/find_object/utilite/ULogger.h deleted file mode 100644 index f9269b35..00000000 --- a/find-object/include/find_object/utilite/ULogger.h +++ /dev/null @@ -1,536 +0,0 @@ -/* -* utilite is a cross-platform library with -* useful utilities for fast and small developing. -* Copyright (C) 2010 Mathieu Labbe -* -* utilite is free library: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* utilite is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this program. If not, see . -*/ - -#ifndef ULOGGER_H -#define ULOGGER_H - -#include "find_object/FindObjectExp.h" // DLL export/import defines - -#include "find_object/utilite/UMutex.h" -#include "find_object/utilite/UDestroyer.h" - -#include -#include -#include -#include - -#include - -#if _MSC_VER - #undef min - #undef max -#endif - -/** - * \file ULogger.h - * \brief ULogger class and convenient macros - * - * This contains macros useful for logging a message anywhere in the - * application. Once the ULogger is set, use these macros like a printf to - * print debug messages. -*/ - -/* - * Convenient macros for logging... - */ -#define ULOGGER_LOG(level, ...) ULogger::write(level, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__) - -#define ULOGGER_DEBUG(...) ULOGGER_LOG(ULogger::kDebug, __VA_ARGS__) -#define ULOGGER_INFO(...) ULOGGER_LOG(ULogger::kInfo, __VA_ARGS__) -#define ULOGGER_WARN(...) ULOGGER_LOG(ULogger::kWarning, __VA_ARGS__) -#define ULOGGER_ERROR(...) ULOGGER_LOG(ULogger::kError, __VA_ARGS__) -#define ULOGGER_FATAL(...) ULOGGER_LOG(ULogger::kFatal, __VA_ARGS__) - -#define UDEBUG(...) ULOGGER_DEBUG(__VA_ARGS__) -#define UINFO(...) ULOGGER_INFO(__VA_ARGS__) -#define UWARN(...) ULOGGER_WARN(__VA_ARGS__) -#define UERROR(...) ULOGGER_ERROR(__VA_ARGS__) -#define UFATAL(...) ULOGGER_FATAL(__VA_ARGS__) - -#define UASSERT(condition) if(!(condition)) ULogger::write(ULogger::kFatal, __FILE__, __LINE__, __FUNCTION__, "Condition (%s) not met!", #condition) -#define UASSERT_MSG(condition, msg_str) if(!(condition)) ULogger::write(ULogger::kFatal, __FILE__, __LINE__, __FUNCTION__, "Condition (%s) not met! [%s]", #condition, msg_str) - -/** - * \def UDEBUG(...) - * Print a debug level message in the logger. Format is the same as a printf: - * @code - * UDEBUG("This is a debug message with the number %d", 42); - * @endcode - */ -/** - * \def UINFO(...) - * Print a information level message in the logger. Format is the same as a printf: - * @code - * UINFO("This is a information message with the number %d", 42); - * @endcode - */ -/** - * \def UWARN(...) - * Print a warning level message in the logger. Format is the same as a printf: - * @code - * UWARN("This is a warning message with the number %d", 42); - * @endcode - */ -/** - * \def UERROR(...) - * Print an error level message in the logger. Format is the same as a printf: - * @code - * UERROR("This is an error message with the number %d", 42); - * @endcode - */ -/** - * \def UFATAL(...) - * Print a fatal error level message in the logger. The application will exit on - * fatal error. Format is the same as a printf: - * @code - * UFATAL("This is a fatal error message with the number %d", 42); - * @endcode - */ -/** - * \def UASSERT(condition, ...) - * Print a fatal error level message in the logger if condition is not met. The application will exit on - * fatal error. Format is the same as a printf: - * @code - * UASSERT(a!=42, "This is a fatal error message with the number %d", 42); - * @endcode - */ - - -/** - * This class is used to log messages with time on a console, in a file - * and/or with an event. At the start of the application, call - * ULogger::setType() with the type of the logger you want (see ULogger::Type, the type of the output - * can be changed at the run-time.). To use it, - * simply call the convenient macros UDEBUG(), UINFO(), UWARN(), UERROR(), UFATAL() depending of - * the severity of the message. You can disable some messages by setting the logger - * level ULogger::setLevel() to severity you want, defined by ULogger::Level. A fatal message - * will make the application to exit, printing the message on console (whatever the logger type) and - * posting a ULogEvent (synchronously... see UEventsManager::post()) before exiting. - * - * The display of the logged messages can be modified: - * - If you don't want the level label, set ULogger::setPrintLevel() to false. - * - If you don't want the time label, set ULogger::setPrintTime() to false. - * - If you don't want the end of line added, set ULogger::setPrintEndline() to false. - * - If you don't the full path of the message, set ULogger::setPrintWhereFullPath() to false. - * - If you don't the path of the message, set ULogger::setPrintWhere() to false. - * - * When using a file logger (kTypeLogger), it can be useful in some - * application to buffer messages before writing them to hard drive (avoiding - * hard drive latencies). You can set ULogger::setBuffered() to true to do that. When the - * buffered messages will be written to file on appllciation exit (ULogger destructor) or when - * ULogger::flush() is called. - * - * If you want the application to exit on a lower severity level than kFatal, - * you can set ULogger::setExitLevel() to any ULogger::Type you want. - * - * Example: - * @code - * #include - * int main(int argc, char * argv[]) - * { - * // Set the logger type. The choices are kTypeConsole, - * // kTypeFile or kTypeNoLog (nothing is logged). - * ULogger::setType(ULogger::kTypeConsole); - * - * // Set the logger severity level (kDebug, kInfo, kWarning, kError, kFatal). - * // All log entries under the severity level are not logged. Here, - * // only debug messages are not logged. - * ULogger::setLevel(ULogger::kInfo); - * - * // Use a predefined Macro to easy logging. It can be - * // called anywhere in the application as the logger is - * // a Singleton. - * UDEBUG("This message won't be logged because the " - * "severity level of the logger is set to kInfo."); - * - * UINFO("This message is logged."); - * - * UWARN("A warning message..."); - * - * UERROR("An error message with code %d.", 42); - * - * return 0; - * } - * @endcode - * Output: - * @code - * [ INFO] (2010-09-25 18:08:20) main.cpp:18::main() This message is logged. - * [ WARN] (2010-09-25 18:08:20) main.cpp:20::main() A warning message... - * [ERROR] (2010-09-25 18:08:20) main.cpp:22::main() An error message with code 42. - * @endcode - * - * Another useful form of the ULogger is to use it with the UTimer class. Here an example: - * @code - * #include - * #include - * ... - * UTimer timer; // automatically starts - * // do some works for part A - * UINFO("Time for part A = %f s", timer.ticks()); - * // do some works for part B - * UINFO("Time for part B = %f s", timer.ticks()); - * // do some works for part C - * UINFO("Time for part C = %f s", timer.ticks()); - * ... - * @endcode - * - * @see setType() - * @see setLevel() - * @see UDEBUG(), UINFO(), UWARN(), UERROR(), UFATAL() - * - */ -class FINDOBJECT_EXP ULogger -{ - -public: - /** - * The default log file name. - */ - static const std::string kDefaultLogFileName; - - /** - * Loggers available: - * @code - * kTypeNoLog, kTypeConsole, kTypeFile - * @endcode - */ - enum Type{kTypeNoLog, kTypeConsole, kTypeFile}; - - /** - * Logger levels, from lowest severity to highest: - * @code - * kDebug, kInfo, kWarning, kError, kFatal - * @endcode - */ - enum Level{kDebug, kInfo, kWarning, kError, kFatal}; - - /** - * Set the type of the logger. When using kTypeFile, the parameter "fileName" would be - * changed (default is "./ULog.txt"), and optionally "append" if we want the - * logger to append messages to file or to overwrite the file. - * @param type the ULogger::Type of the logger. - * @param fileName file name used with a file logger type. - * @param append if true, the file isn't overwritten, otherwise it is. - * - * TODO : Can it be useful to have 2 or more types at the same time ? Print - * in console and file at the same time. - */ - static void setType(Type type, const std::string &fileName = kDefaultLogFileName, bool append = true); - static Type type() {return type_;} - - // Setters - /** - * Print time: default true. - * @param printTime true to print time, otherwise set to false. - */ - static void setPrintTime(bool printTime) {printTime_ = printTime;} - static bool isPrintTime() {return printTime_;} - - /** - * Print level: default true. - * @param printLevel true to print level, otherwise set to false. - */ - static void setPrintLevel(bool printLevel) {printLevel_ = printLevel;} - static bool isPrintLevel() {return printLevel_;} - - /** - * Print end of line: default true. - * @param printLevel true to print end of line, otherwise set to false. - */ - static void setPrintEndline(bool printEndline) {printEndline_ = printEndline;} - static bool isPrintEndLine() {return printEndline_;} - - /** - * Print text with color: default true. - * Dark green for Debug, white for Info, yellow for Warning, red for Error and Fatal. - * @param printColored true to print text with color, otherwise set to false. - */ - static void setPrintColored(bool printColored) {printColored_ = printColored;} - static bool isPrintColored() {return printColored_;} - - /** - * Print where is this message in source code: default true. - * @param printWhere true to print where, otherwise set to false. - */ - static void setPrintWhere(bool printWhere) {printWhere_ = printWhere;} - static bool isPrintWhere() {return printWhere_;} - - /** - * Print the full path: default true. ULogger::setPrintWhere() must be true to have path printed. - * @param printWhereFullPath true to print the full path, otherwise set to false. - */ - static void setPrintWhereFullPath(bool printWhereFullPath) {printWhereFullPath_ = printWhereFullPath;} - static bool isPrintWhereFullPath() {return printWhereFullPath_;} - - /** - * Set is the logger buffers messages, default false. When true, the messages are - * buffered until the application is closed or ULogger::flush() is called. - * @see ULogger::flush() - * @param buffered true to buffer messages, otherwise set to false. - */ - static void setBuffered(bool buffered); - static bool isBuffered() {return buffered_;} - - /** - * Set logger level: default kInfo. All messages over the severity set - * are printed, other are ignored. The severity is from the lowest to - * highest: - * - kDebug - * - kInfo - * - kWarning - * - kError - * - kFatal - * @param level the minimum level of the messages printed. - */ - static void setLevel(ULogger::Level level) {level_ = level;} - static ULogger::Level level() {return level_;} - - /** - * Make application to exit when a log with level is written (useful for debugging). The message is printed to - * console (whatever the logger type) and an ULogEvent is sent (synchronously... see UEventsManager::post()) before exiting. - * - * Note : A kFatal level will always exit whatever the level specified here. - */ - static void setExitLevel(ULogger::Level exitLevel) {exitLevel_ = exitLevel;} - static ULogger::Level exitLevel() {return exitLevel_;} - - /** - * An ULogEvent is sent on each message logged at the specified level. - * Note : On message with level >= exitLevel, the event is sent synchronously (see UEventsManager::post()). - * @see ULogEvent - * @see setExitLevel() - */ - static void setEventLevel(ULogger::Level eventSentLevel) {eventLevel_ = eventSentLevel;} - static ULogger::Level eventLevel() {return eventLevel_;} - - /** - * Reset to default parameters. - */ - static void reset(); - - /** - * Flush buffered messages. - * @see setBuffered() - */ - static void flush(); - - /** - * Write a message directly to logger without level handling. - * @param msg the message to write. - * @param ... the variable arguments - * @deprecated use UDEBUG(), UINFO(), UWARN(), UERROR() or UFATAL() - */ - static void write(const char* msg, ...); - - /* - * Write a message to logger: use UDEBUG(), UINFO(), UWARN(), UERROR() or UFATAL() instead. - * @param level the log level of this message - * @param file the file path - * @param line the line in the file - * @param function the function name in which the message is logged - * @param msg the message to write - * @param ... the variable arguments - */ - static void write(ULogger::Level level, - const char * file, - int line, - const char *function, - const char* msg, - ...); - - /** - * Get the time in the format "2008-7-13 12:23:44". - * @param timeStr string were the time will be copied. - * @return the number of characters written, or 0 if an error occurred. - */ - static int getTime(std::string &timeStr); - -protected: - /* - * This method is used to have a reference on the - * Logger. When no Logger exists, one is - * created. There is only one instance in the application. - * Must be protected by loggerMutex_. - * See the Singleton pattern for further explanation. - * - * @return the reference on the Logger - */ - static ULogger* getInstance(); - - /* - * Called only once in getInstance(). It can't be instanciated - * by the user. - * - * @see getInstance() - */ - ULogger() {} - - /* - * Only called by a Destroyer. - * @see Destroyer - */ - virtual ~ULogger(); - - /* - * Flush buffered messages - */ - void _flush(); - - /* - * A Destroyer is used to remove a dynamicaly created - * Singleton. It is friend here to have access to the - * destructor. - * - * @see Destroyer - */ - friend class UDestroyer; - - /* - * The log file name. - */ - static std::string logFileName_; - - /* - * Default true, it doesn't overwrite the file. - */ - static bool append_; - -private: - /* - * Create an instance according to type. See the Abstract factory - * pattern for further explanation. - * @see type_ - * @return the reference on the new logger - */ - static ULogger* createInstance(); - - /* - * Write a message on the output with the format : - * "A message". Inherited class - * must override this method to output the message. It - * does nothing by default. - * @param msg the message to write. - * @param arg the variable arguments - */ - virtual void _write(const char* msg, va_list arg) {} // Do nothing by default - virtual void _writeStr(const char* msg) {} // Do nothing by default - -private: - /* - * The Logger instance pointer. - */ - static ULogger* instance_; - - /* - * The Logger's destroyer - */ - static UDestroyer destroyer_; - - /* - * If the logger prints the time for each message. - * Default is true. - */ - static bool printTime_; - - /* - * If the logger prints the level for each message. - * Default is true. - */ - static bool printLevel_; - - /* - * If the logger prints the end line for each message. - * Default is true. - */ - static bool printEndline_; - - /* - * If the logger prints text with color. - * Default is true. - */ - static bool printColored_; - - /* - * If the logger prints where the message is logged (fileName::function():line). - * Default is true. - */ - static bool printWhere_; - - /* - * If the logger prints the full path of the source file - * where the message is written. Only works when - * "printWhere_" is true. - * Default is false. - */ - static bool printWhereFullPath_; - - /* - * If the logger limit the size of the "where" path to - * characters. If the path is over 8 characters, a "~" - * is added. Only works when "printWhereFullPath_" is false. - * Default is false. - */ - static bool limitWhereLength_; - - /* - * The type of the logger. - */ - static Type type_; - - /* - * The severity of the log. - */ - static Level level_; - - /* - * The severity at which the application exits. - * Note : A FATAL level will always exit whatever the level specified here. - */ - static Level exitLevel_; - - /* - * The severity at which the message is also sent in a ULogEvent. - */ - static Level eventLevel_; - - static const char * levelName_[5]; - - /* - * Mutex used when accessing public functions. - */ - static UMutex loggerMutex_; - - /* - * If the logger prints messages only when ULogger::flush() is called. - * Default is false. - */ - static bool buffered_; - - static std::string bufferedMsgs_; - - /* - * State attribute. This state happens when an exit level - * message is received. - * Messages received during this state are not logged. - * @see exitLevel_ - */ - static bool exitingState_; -}; - -#endif // ULOGGER_H diff --git a/find-object/include/find_object/utilite/UMutex.h b/find-object/include/find_object/utilite/UMutex.h deleted file mode 100644 index bb1fceaf..00000000 --- a/find-object/include/find_object/utilite/UMutex.h +++ /dev/null @@ -1,179 +0,0 @@ -/* -* utilite is a cross-platform library with -* useful utilities for fast and small developing. -* Copyright (C) 2010 Mathieu Labbe -* -* utilite is free library: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* utilite is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this program. If not, see . -*/ - -#ifndef UMUTEX_H -#define UMUTEX_H - -#include - -#ifdef WIN32 - #include "find_object/utilite/UWin32.h" -#else - #include -#endif - - -/** - * A mutex class. - * - * On a lock() call, the calling thread is blocked if the - * UMutex was previously locked by another thread. It is unblocked when unlock() is called. - * - * On Unix (not yet tested on Windows), UMutex is recursive: the same thread can - * call multiple times lock() without being blocked. - * - * Example: - * @code - * UMutex m; // Mutex shared with another thread(s). - * ... - * m.lock(); - * // Data is protected here from the second thread - * //(assuming the second one protects also with the same mutex the same data). - * m.unlock(); - * - * @endcode - * - * @see USemaphore - */ -class UMutex -{ - -public: - - /** - * The constructor. - */ - UMutex() - { -#ifdef WIN32 - InitializeCriticalSection(&C); -#else - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&M,&attr); - pthread_mutexattr_destroy(&attr); -#endif - } - - virtual ~UMutex() - { -#ifdef WIN32 - DeleteCriticalSection(&C); -#else - pthread_mutex_unlock(&M); pthread_mutex_destroy(&M); -#endif - } - - /** - * Lock the mutex. - */ - int lock() const - { -#ifdef WIN32 - EnterCriticalSection(&C); return 0; -#else - return pthread_mutex_lock(&M); -#endif - } - -#ifdef WIN32 - #if(_WIN32_WINNT >= 0x0400) - int lockTry() const - { - return (TryEnterCriticalSection(&C)?0:EBUSY); - } - #endif -#else - int lockTry() const - { - return pthread_mutex_trylock(&M); - } -#endif - - /** - * Unlock the mutex. - */ - int unlock() const - { -#ifdef WIN32 - LeaveCriticalSection(&C); return 0; -#else - return pthread_mutex_unlock(&M); -#endif - } - - private: -#ifdef WIN32 - mutable CRITICAL_SECTION C; -#else - mutable pthread_mutex_t M; -#endif - void operator=(UMutex &M) {} - UMutex( const UMutex &M ) {} -}; - -/** - * Automatically lock the referenced mutex on constructor and unlock mutex on destructor. - * - * Example: - * @code - * UMutex m; // Mutex shared with another thread(s). - * ... - * int myMethod() - * { - * UScopeMutex sm(m); // automatically lock the mutex m - * if(cond1) - * { - * return 1; // automatically unlock the mutex m - * } - * else if(cond2) - * { - * return 2; // automatically unlock the mutex m - * } - * return 0; // automatically unlock the mutex m - * } - * - * @endcode - * - * @see UMutex - */ -class UScopeMutex -{ -public: - UScopeMutex(const UMutex & mutex) : - mutex_(mutex) - { - mutex_.lock(); - } - // backward compatibility - UScopeMutex(UMutex * mutex) : - mutex_(*mutex) - { - mutex_.lock(); - } - ~UScopeMutex() - { - mutex_.unlock(); - } -private: - const UMutex & mutex_; -}; - -#endif // UMUTEX_H diff --git a/find-object/include/find_object/utilite/UWin32.h b/find-object/include/find_object/utilite/UWin32.h deleted file mode 100644 index 49d02b69..00000000 --- a/find-object/include/find_object/utilite/UWin32.h +++ /dev/null @@ -1,62 +0,0 @@ -///////////////////////////////////////////////////////////////////// -// Written by Phillip Sitbon -// Copyright 2003 -// -// Win32.h -// - Windows includes -// -///////////////////////////////////////////////////////////////////// -#ifndef _U_Win32_ -#define _U_Win32_ - - #if !defined(_WINDOWS_) - // WIN32 Excludes - #ifdef WIN32_LEAN_AND_MEAN - # define VC_EXTRALEAN - # define WIN32_LEAN_AND_MEAN - # define _PRSHT_H_ - # define NOGDICAPMASKS // CC_*, LC_*, PC_*, CP_*, TC_*, RC_ - # define NOVIRTUALKEYCODES // VK_* - # define NOWINMESSAGES // WM_*, EM_*, LB_*, CB_* - # define NOWINSTYLES // WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_* - # define NOSYSMETRICS // SM_* - # define NOMENUS // MF_* - # define NOICONS // IDI_* - # define NOKEYSTATES // MK_* - # define NOSYSCOMMANDS // SC_* - # define NORASTEROPS // Binary and Tertiary raster ops - # define NOSHOWWINDOW // SW_* - # define OEMRESOURCE // OEM Resource values - # define NOATOM // Atom Manager routines - # define NOCLIPBOARD // Clipboard routines - # define NOCOLOR // Screen colors - # define NOCTLMGR // Control and Dialog routines - # define NODRAWTEXT // DrawText() and DT_* - # define NOGDI // All GDI defines and routines - # define NOKERNEL // All KERNEL defines and routines - # define NOUSER // All USER defines and routines - # define NONLS // All NLS defines and routines - # define NOMB // MB_* and MessageBox() - # define NOMEMMGR // GMEM_*, LMEM_*, GHND, LHND, associated routines - # define NOMETAFILE // typedef METAFILEPICT - # define NOMINMAX // Macros min(a,b) and max(a,b) - # define NOMSG // typedef MSG and associated routines - # define NOOPENFILE // OpenFile(), OemToAnsi, AnsiToOem, and OF_* - # define NOSCROLL // SB_* and scrolling routines - # define NOSERVICE // All Service Controller routines, SERVICE_ equates, etc. - # define NOSOUND // Sound driver routines - # define NOTEXTMETRIC // typedef TEXTMETRIC and associated routines - # define NOWH // SetWindowsHook and WH_* - # define NOWINOFFSETS // GWL_*, GCL_*, associated routines - # define NOCOMM // COMM driver routines - # define NOKANJI // Kanji support stuff. - # define NOHELP // Help engine interface. - # define NOPROFILER // Profiler interface. - # define NODEFERWINDOWPOS // DeferWindowPos routines - # define NOMCX // Modem Configuration Extensions - #endif // WIN32_LEAN_AND_MEAN - // - # include - #endif - -#endif // !_U_Win32_ diff --git a/find-object/launch/ros1/find_object_2d.launch b/find-object/launch/ros1/find_object_2d.launch deleted file mode 100644 index 649a821e..00000000 --- a/find-object/launch/ros1/find_object_2d.launch +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/find-object/launch/ros1/find_object_3d.launch b/find-object/launch/ros1/find_object_3d.launch deleted file mode 100644 index eb544568..00000000 --- a/find-object/launch/ros1/find_object_3d.launch +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/find-object/launch/ros1/find_object_3d_kinect2.launch b/find-object/launch/ros1/find_object_3d_kinect2.launch deleted file mode 100644 index 56289880..00000000 --- a/find-object/launch/ros1/find_object_3d_kinect2.launch +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/find-object/launch/ros1/find_object_3d_zed.launch b/find-object/launch/ros1/find_object_3d_zed.launch deleted file mode 100644 index 5fb63e6f..00000000 --- a/find-object/launch/ros1/find_object_3d_zed.launch +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/find-object/launch/ros2/find_object_2d.launch.py b/find-object/launch/ros2/find_object_2d.launch.py deleted file mode 100644 index 504242ff..00000000 --- a/find-object/launch/ros2/find_object_2d.launch.py +++ /dev/null @@ -1,30 +0,0 @@ - -from launch import LaunchDescription -from launch.actions import DeclareLaunchArgument, SetEnvironmentVariable -from launch.substitutions import LaunchConfiguration -from launch_ros.actions import Node - -def generate_launch_description(): - - return LaunchDescription([ - - SetEnvironmentVariable('RCUTILS_LOGGING_USE_STDOUT', '1'), - SetEnvironmentVariable('RCUTILS_LOGGING_BUFFERED_STREAM', '0'), - - # Launch arguments - DeclareLaunchArgument('gui', default_value='true', description='Launch GUI.'), - DeclareLaunchArgument('image_topic', default_value='image', description='Image topic to subscribe to.'), - DeclareLaunchArgument('objects_path', default_value='~/objects', description='Directory containing objects to load on initialization.'), - DeclareLaunchArgument('settings_path', default_value='~/.ros/find_object_2d.ini', description='Config file.'), - - # Nodes to launch - Node( - package='find_object_2d', executable='find_object_2d', output='screen', - parameters=[{ - 'gui':LaunchConfiguration('gui'), - 'objects_path':LaunchConfiguration('objects_path'), - 'settings_path':LaunchConfiguration('settings_path') - }], - remappings=[ - ('image', LaunchConfiguration('image_topic'))]), - ]) diff --git a/find-object/launch/ros2/find_object_3d.launch.py b/find-object/launch/ros2/find_object_3d.launch.py deleted file mode 100644 index e883486f..00000000 --- a/find-object/launch/ros2/find_object_3d.launch.py +++ /dev/null @@ -1,42 +0,0 @@ - -from launch import LaunchDescription -from launch.actions import DeclareLaunchArgument, SetEnvironmentVariable -from launch.substitutions import LaunchConfiguration -from launch_ros.actions import Node - -def generate_launch_description(): - - return LaunchDescription([ - - SetEnvironmentVariable('RCUTILS_LOGGING_USE_STDOUT', '1'), - SetEnvironmentVariable('RCUTILS_LOGGING_BUFFERED_STREAM', '0'), - - # Launch arguments - DeclareLaunchArgument('gui', default_value='true', description='Launch GUI.'), - DeclareLaunchArgument('approx_sync', default_value='true', description=''), - DeclareLaunchArgument('pnp', default_value='true', description=''), - DeclareLaunchArgument('object_prefix', default_value='object', description='TF prefix of objects.'), - DeclareLaunchArgument('objects_path', default_value='~/objects', description='Directory containing objects to load on initialization.'), - DeclareLaunchArgument('settings_path', default_value='~/.ros/find_object_2d.ini', description='Config file.'), - - DeclareLaunchArgument('rgb_topic', default_value='camera/rgb/image_rect_color', description='Image topic.'), - DeclareLaunchArgument('depth_topic', default_value='camera/depth_registered/image_raw', description='Registered depth topic.'), - DeclareLaunchArgument('camera_info_topic', default_value='camera/rgb/camera_info', description='Camera info topic.'), - - # Nodes to launch - Node( - package='find_object_2d', executable='find_object_2d', output='screen', - parameters=[{ - 'subscribe_depth':True, - 'gui':LaunchConfiguration('gui'), - 'approx_sync':LaunchConfiguration('approx_sync'), - 'pnp':LaunchConfiguration('pnp'), - 'object_prefix':LaunchConfiguration('object_prefix'), - 'objects_path':LaunchConfiguration('objects_path'), - 'settings_path':LaunchConfiguration('settings_path') - }], - remappings=[ - ('rgb/image_rect_color', LaunchConfiguration('rgb_topic')), - ('depth_registered/image_raw', LaunchConfiguration('depth_topic')), - ('depth_registered/camera_info', LaunchConfiguration('camera_info_topic'))]), - ]) diff --git a/find-object/msg/DetectionInfo.msg b/find-object/msg/DetectionInfo.msg deleted file mode 100644 index d9825f05..00000000 --- a/find-object/msg/DetectionInfo.msg +++ /dev/null @@ -1,12 +0,0 @@ - -std_msgs/Header header - -# All arrays should have the same size -std_msgs/Int32[] ids -std_msgs/Int32[] widths -std_msgs/Int32[] heights -std_msgs/String[] file_paths -std_msgs/Int32[] inliers -std_msgs/Int32[] outliers -# 3x3 homography matrix: [h11, h12, h13, h21, h22, h23, h31, h32, h33] (h31 = dx and h32 = dy, see QTransform) -std_msgs/Float32MultiArray[] homographies diff --git a/find-object/msg/ObjectsStamped.msg b/find-object/msg/ObjectsStamped.msg deleted file mode 100644 index c1d191a9..00000000 --- a/find-object/msg/ObjectsStamped.msg +++ /dev/null @@ -1,5 +0,0 @@ -# objects format: -# [ObjectId1, objectWidth, objectHeight, h11, h12, h13, h21, h22, h23, h31, h32, h33, ObjectId2...] -# where h## is a 3x3 homography matrix (h31 = dx and h32 = dy, see QTransform) -std_msgs/Header header -std_msgs/Float32MultiArray objects \ No newline at end of file diff --git a/find-object/package.xml b/find-object/package.xml deleted file mode 100644 index 2d8c135c..00000000 --- a/find-object/package.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - find_object_2d - 0.7.0 - The find_object_2d package - Mathieu Labbe - Mathieu Labbe - BSD - https://github.com/introlab/find-object/issues - https://github.com/introlab/find-object - - catkin - ament_cmake - - roscpp - tf - rclcpp - tf2 - tf2_ros - tf2_geometry_msgs - - ros_environment - builtin_interfaces - rosidl_default_generators - rosidl_default_runtime - rosidl_interface_packages - - message_generation - qtbase5-dev - cv_bridge - sensor_msgs - std_msgs - std_srvs - geometry_msgs - image_transport - message_filters - - message_runtime - qtbase5-dev - cv_bridge - sensor_msgs - std_msgs - std_srvs - geometry_msgs - image_transport - message_filters - - - catkin - ament_cmake - - diff --git a/find-object/snap/snapcraft.yaml.in b/find-object/snap/snapcraft.yaml.in deleted file mode 100644 index 932ad263..00000000 --- a/find-object/snap/snapcraft.yaml.in +++ /dev/null @@ -1,67 +0,0 @@ -name: find-object -base: core18 -version: '@PROJECT_VERSION@+git' -summary: Find-Object project, visit http://introlab.github.io/find-object/ -description: | - Features: - - You can change any parameters at runtime, make it easier to test feature detectors and descriptors without always recompiling. - - Detectors/descriptors supported (from OpenCV): BRIEF, Dense, FAST, GoodFeaturesToTrack, MSER, ORB, SIFT, STAR, SURF, FREAK and BRISK. - - Sample code with the OpenCV C++ interface below... - - For an example of an application using SURF descriptors: see my project RTAB-Map (an appearance-based loop closure detector for SLAM). - -grade: devel # must be 'stable' to release into candidate/stable channels -confinement: devmode # use 'strict' once you have the right plugs and slots - -apps: - find-object: - command: desktop-launch find_object - plugs: [unity7, x11, opengl, home, network, network-bind, removable-media, raw-usb, wayland, desktop-legacy, desktop] - -parts: - desktop-qt5: - source: https://github.com/ubuntu/snapcraft-desktop-helpers.git - source-subdir: qt - plugin: make - make-parameters: ["FLAVOR=qt5"] - build-packages: - - qtbase5-dev - - dpkg-dev - stage-packages: - - libxkbcommon0 - - ttf-ubuntu-font-family - - dmz-cursor-theme - - light-themes - - adwaita-icon-theme - - gnome-themes-standard - - shared-mime-info - - libqt5gui5 - - libgdk-pixbuf2.0-0 - - libgtk2.0-0 - - libqt5svg5 # for loading icon themes which are svg - - try: [appmenu-qt5] # not available on core18 - - locales-all - - find-object: - after: [desktop-qt5] - plugin: cmake - source: . - build-packages: - - libopencv-dev - - qtbase5-dev - organize: - usr/lib/x86_64-linux-gnu/blas/libblas.so.3: usr/lib/x86_64-linux-gnu/libblas.so.3 - usr/lib/x86_64-linux-gnu/blas/libblas.so.3.7.1: usr/lib/x86_64-linux-gnu/libblas.so.3.7.1 - usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3: usr/lib/x86_64-linux-gnu/liblapack.so.3 - usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.7.1: usr/lib/x86_64-linux-gnu/liblapack.so.3.7.1 - stage-packages: - - libopencv-calib3d3.2 - - libopencv-core3.2 - - libopencv-features2d3.2 - - libopencv-flann3.2 - - libopencv-imgcodecs3.2 - - libopencv-imgproc3.2 - - libopencv-video3.2 - - libqt5core5a - - libqt5gui5 - - libqt5network5 - - libqt5widgets5 diff --git a/find-object/src/AboutDialog.cpp b/find-object/src/AboutDialog.cpp deleted file mode 100644 index 9a805816..00000000 --- a/find-object/src/AboutDialog.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "AboutDialog.h" -#include "ui_aboutDialog.h" -#include -#include "find_object/Version.h" - -namespace find_object { - -AboutDialog::AboutDialog(QWidget * parent) : - QDialog(parent) -{ - ui_ = new Ui_aboutDialog(); - ui_->setupUi(this); - ui_->label_version->setText(PROJECT_VERSION); - - QString cv_version = CV_VERSION; - #if FINDOBJECT_NONFREE == 1 - cv_version.append(" [With nonfree]"); - #else - cv_version.append(" [Without nonfree]"); - #endif - - ui_->label_version_opencv->setText(cv_version); - ui_->label_version_qt->setText(QT_VERSION_STR); -} - -AboutDialog::~AboutDialog() -{ - delete ui_; -} - -} diff --git a/find-object/src/AboutDialog.h b/find-object/src/AboutDialog.h deleted file mode 100644 index 2d99fbc4..00000000 --- a/find-object/src/AboutDialog.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef ABOUTDIALOG_H_ -#define ABOUTDIALOG_H_ - -#include -#include - -class Ui_aboutDialog; - -namespace find_object { - -class AboutDialog : public QDialog -{ - Q_OBJECT - -public: - AboutDialog(QWidget * parent = 0); - - virtual ~AboutDialog(); - -private: - Ui_aboutDialog * ui_; -}; - -} // namespace find_object - -#endif /* ABOUTDIALOG_H_ */ diff --git a/find-object/src/AddObjectDialog.cpp b/find-object/src/AddObjectDialog.cpp deleted file mode 100644 index 7e097b0a..00000000 --- a/find-object/src/AddObjectDialog.cpp +++ /dev/null @@ -1,461 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "find_object/Camera.h" -#include "find_object/Settings.h" -#include "find_object/utilite/ULogger.h" -#include "find_object/ObjWidget.h" -#include "find_object/QtOpenCV.h" - -#include "AddObjectDialog.h" -#include "ui_addObjectDialog.h" -#include "KeypointItem.h" -#include "ObjSignature.h" - -#include - -#include -#include -#include - -#include -#include -#include - -namespace find_object { - -AddObjectDialog::AddObjectDialog(Camera * camera, const cv::Mat & image, bool mirrorView, QWidget * parent, Qt::WindowFlags f) : - QDialog(parent, f), - camera_(camera), - objWidget_(0), - objSignature_(0) -{ - ui_ = new Ui_addObjectDialog(); - ui_->setupUi(this); - - detector_ = Settings::createKeypointDetector(); - extractor_ = Settings::createDescriptorExtractor(); - UASSERT(detector_ != 0 && extractor_ != 0); - - connect(ui_->pushButton_cancel, SIGNAL(clicked()), this, SLOT(cancel())); - connect(ui_->pushButton_back, SIGNAL(clicked()), this, SLOT(back())); - connect(ui_->pushButton_next, SIGNAL(clicked()), this, SLOT(next())); - connect(ui_->pushButton_takePicture, SIGNAL(clicked()), this, SLOT(takePicture())); - connect(ui_->comboBox_selection, SIGNAL(currentIndexChanged(int)), this, SLOT(changeSelectionMode())); - - connect(ui_->cameraView, SIGNAL(selectionChanged()), this, SLOT(updateNextButton())); - connect(ui_->cameraView, SIGNAL(roiChanged(const cv::Rect &)), this, SLOT(updateNextButton(const cv::Rect &))); - ui_->cameraView->setMirrorView(mirrorView); - - if((camera_ && camera_->isRunning()) || image.empty()) - { - this->setState(kTakePicture); - } - else if(!image.empty()) - { - update(image); - this->setState(kSelectFeatures); - } -} - -AddObjectDialog::~AddObjectDialog() -{ - delete detector_; - delete extractor_; - if(objWidget_) - { - delete objWidget_; - objWidget_ = 0; - } - if(objSignature_) - { - delete objSignature_; - objSignature_ = 0; - } - delete ui_; -} - -void AddObjectDialog::retrieveObject(ObjWidget ** widget, ObjSignature ** signature) -{ - *widget = objWidget_; - objWidget_= 0; - *signature = objSignature_; - objSignature_ = 0; -} - -void AddObjectDialog::closeEvent(QCloseEvent* event) -{ - if(camera_) - { - disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); - disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)), this, SLOT(update(const cv::Mat &, const find_object::Header &, const cv::Mat &, float))); - } - QDialog::closeEvent(event); -} - -void AddObjectDialog::next() -{ - setState(state_+1); -} -void AddObjectDialog::back() -{ - setState(state_-1); -} -void AddObjectDialog::cancel() -{ - this->reject(); -} -void AddObjectDialog::takePicture() -{ - next(); -} - -void AddObjectDialog::updateNextButton() -{ - updateNextButton(cv::Rect()); -} - -void AddObjectDialog::updateNextButton(const cv::Rect & rect) -{ - roi_ = rect; - if(roi_.height && roi_.width && cameraImage_.cols) - { - //clip roi - if( roi_.x >= cameraImage_.cols || - roi_.x+roi_.width <= 0 || - roi_.y >= cameraImage_.rows || - roi_.y+roi_.height <= 0) - { - //Not valid... - roi_ = cv::Rect(); - } - else - { - if(roi_.x < 0) - { - roi_.x = 0; - } - if(roi_.x + roi_.width > cameraImage_.cols) - { - roi_.width = cameraImage_.cols - roi_.x; - } - if(roi_.y < 0) - { - roi_.y = 0; - } - if(roi_.y + roi_.height > cameraImage_.rows) - { - roi_.height = cameraImage_.rows - roi_.y; - } - } - } - if(state_ == kSelectFeatures) - { - if(ui_->comboBox_selection->currentIndex() == 1) - { - if(ui_->cameraView->selectedItems().size() > 0) - { - ui_->pushButton_next->setEnabled(true); - } - else - { - ui_->pushButton_next->setEnabled(false); - } - } - else - { - if(roi_.width == 0 || roi_.height == 0) - { - ui_->pushButton_next->setEnabled(false); - } - else - { - ui_->pushButton_next->setEnabled(true); - } - } - } -} - -void AddObjectDialog::changeSelectionMode() -{ - this->setState(kSelectFeatures); -} - -void AddObjectDialog::setState(int state) -{ - state_ = state; - if(state == kTakePicture) - { - ui_->pushButton_cancel->setEnabled(true); - ui_->pushButton_back->setEnabled(false); - ui_->pushButton_next->setEnabled(false); - ui_->pushButton_takePicture->setEnabled(true); - ui_->label_instruction->setText(tr("Place the object in front of the camera and click \"Take picture\".")); - ui_->pushButton_next->setText(tr("Next")); - ui_->cameraView->setVisible(true); - ui_->cameraView->clearRoiSelection(); - ui_->objectView->setVisible(false); - ui_->cameraView->setGraphicsViewMode(false); - ui_->comboBox_selection->setVisible(false); - if(!camera_ || !camera_->start()) - { - QMessageBox::critical(this, tr("Camera error"), tr("Camera is not started!")); - ui_->pushButton_takePicture->setEnabled(false); - } - else - { - connect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); - connect(camera_, SIGNAL(imageReceived(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)), this, SLOT(update(const cv::Mat &, const find_object::Header &, const cv::Mat &, float))); - } - } - else if(state == kSelectFeatures) - { - if(camera_) - { - disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); - disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)), this, SLOT(update(const cv::Mat &, const find_object::Header &, const cv::Mat &, float))); - camera_->pause(); - } - - ui_->pushButton_cancel->setEnabled(true); - ui_->pushButton_back->setEnabled(camera_); - ui_->pushButton_next->setEnabled(false); - ui_->pushButton_takePicture->setEnabled(false); - ui_->pushButton_next->setText(tr("Next")); - ui_->cameraView->setVisible(true); - ui_->cameraView->clearRoiSelection(); - ui_->objectView->setVisible(false); - ui_->comboBox_selection->setVisible(true); - - if(ui_->comboBox_selection->currentIndex() == 1) - { - ui_->label_instruction->setText(tr("Select features representing the object.")); - ui_->cameraView->setGraphicsViewMode(true); - } - else - { - ui_->label_instruction->setText(tr("Select region representing the object.")); - ui_->cameraView->setGraphicsViewMode(false); - } - updateNextButton(cv::Rect()); - } - else if(state == kVerifySelection) - { - if(camera_) - { - disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); - disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)), this, SLOT(update(const cv::Mat &, const find_object::Header &, const cv::Mat &, float))); - camera_->pause(); - } - - ui_->pushButton_cancel->setEnabled(true); - ui_->pushButton_back->setEnabled(true); - ui_->pushButton_takePicture->setEnabled(false); - ui_->pushButton_next->setText(tr("End")); - ui_->cameraView->setVisible(true); - ui_->objectView->setVisible(true); - ui_->objectView->setMirrorView(ui_->cameraView->isMirrorView()); - ui_->objectView->setSizedFeatures(ui_->cameraView->isSizedFeatures()); - ui_->comboBox_selection->setVisible(false); - if(ui_->comboBox_selection->currentIndex() == 1) - { - ui_->cameraView->setGraphicsViewMode(true); - } - else - { - ui_->cameraView->setGraphicsViewMode(false); - } - - std::vector selectedKeypoints = ui_->cameraView->selectedKeypoints(); - - // Select keypoints - if(!cameraImage_.empty() && - ((ui_->comboBox_selection->currentIndex() == 1 && selectedKeypoints.size()) || - (ui_->comboBox_selection->currentIndex() == 0 && roi_.width && roi_.height))) - { - if(ui_->comboBox_selection->currentIndex() == 1) - { - roi_ = computeROI(selectedKeypoints); - } - - cv::Mat imgRoi = cv::Mat(cameraImage_, roi_).clone(); - - if(ui_->comboBox_selection->currentIndex() == 1) - { - if(roi_.x != 0 || roi_.y != 0) - { - for(unsigned int i=0; idetect(imgRoi, selectedKeypoints); - } - ui_->objectView->updateImage(cvtCvMat2QImage(imgRoi)); - ui_->objectView->updateData(selectedKeypoints, QMultiMap()); - ui_->objectView->setMinimumSize(roi_.width, roi_.height); - ui_->objectView->update(); - ui_->pushButton_next->setEnabled(true); - } - else - { - UINFO("Please select items"); - ui_->pushButton_next->setEnabled(false); - } - ui_->label_instruction->setText(tr("Selection : %1 features").arg(selectedKeypoints.size())); - } - else if(state == kClosing) - { - std::vector keypoints = ui_->objectView->keypoints(); - if((ui_->comboBox_selection->currentIndex() == 1 && keypoints.size()) || - (ui_->comboBox_selection->currentIndex() == 0 && roi_.width && roi_.height)) - { - cv::Mat descriptors; - cv::Mat imgRoi(cameraImage_, roi_); - if(keypoints.size()) - { - // Extract descriptors - if(Settings::currentDetectorType() == Settings::currentDescriptorType()) - { - detector_->compute(imgRoi, keypoints, descriptors); - } - else - { - extractor_->compute(imgRoi, keypoints, descriptors); - } - - if(keypoints.size() != (unsigned int)descriptors.rows) - { - UERROR("keypoints=%d != descriptors=%d", (int)keypoints.size(), descriptors.rows); - } - } - - if(objWidget_) - { - delete objWidget_; - objWidget_ = 0; - } - if(objSignature_) - { - delete objSignature_; - objSignature_ = 0; - } - objSignature_ = new ObjSignature(0, imgRoi.clone(), ""); - objSignature_->setData(keypoints, descriptors); - objWidget_ = new ObjWidget(0, keypoints, QMultiMap(), cvtCvMat2QImage(imgRoi.clone())); - - this->accept(); - } - } -} - -void AddObjectDialog::update(const cv::Mat & image) -{ - update(image, Header(), cv::Mat(), 0.0); -} - -void AddObjectDialog::update(const cv::Mat & image, const Header & header, const cv::Mat & depth, float depthConstant) -{ - cameraImage_ = cv::Mat(); - if(!image.empty()) - { - // convert to grayscale - if(image.channels() != 1 || image.depth() != CV_8U) - { - cv::cvtColor(image, cameraImage_, CV_BGR2GRAY); - } - else - { - cameraImage_ = image.clone(); - } - - // Extract keypoints - std::vector keypoints; - detector_->detect(cameraImage_, keypoints); - - ui_->cameraView->updateImage(cvtCvMat2QImage(cameraImage_)); - ui_->cameraView->updateData(keypoints, QMultiMap()); - ui_->cameraView->update(); - } - else - { - UWARN("Camera cannot get more images (maybe the end of stream is reached)..."); - camera_->stop(); - } -} - -cv::Rect AddObjectDialog::computeROI(const std::vector & kpts) -{ - cv::Rect roi(0,0,0,0); - int x1=0,x2=0,h1=0,h2=0; - for(unsigned int i=0; i int(kpts.at(i).pt.x - radius)) - { - x1 = int(kpts.at(i).pt.x - radius); - } - else if(x2 < int(kpts.at(i).pt.x + radius)) - { - x2 = int(kpts.at(i).pt.x + radius); - } - if(h1 > int(kpts.at(i).pt.y - radius)) - { - h1 = int(kpts.at(i).pt.y - radius); - } - else if(h2 < int(kpts.at(i).pt.y + radius)) - { - h2 = int(kpts.at(i).pt.y + radius); - } - } - roi.x = x1; - roi.y = h1; - roi.width = x2-x1; - roi.height = h2-h1; - //UINFO("ptx=%d, pty=%d", (int)kpts.at(i).pt.x, (int)kpts.at(i).pt.y); - //UINFO("x=%d, y=%d, w=%d, h=%d", roi.x, roi.y, roi.width, roi.height); - } - - return roi; -} - -} // namespace find_object diff --git a/find-object/src/AddObjectDialog.h b/find-object/src/AddObjectDialog.h deleted file mode 100644 index b75d9c97..00000000 --- a/find-object/src/AddObjectDialog.h +++ /dev/null @@ -1,91 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef ADDOBJECTDIALOG_H_ -#define ADDOBJECTDIALOG_H_ - -#include -#include -#include -#include -#include "find_object/Header.h" - -class Ui_addObjectDialog; - -namespace find_object { - -class ObjWidget; -class Camera; -class KeypointItem; -class Feature2D; -class ObjSignature; - -class AddObjectDialog : public QDialog { - - Q_OBJECT - -public: - AddObjectDialog(Camera * camera, const cv::Mat & image, bool mirrorView, QWidget * parent = 0, Qt::WindowFlags f = 0); - virtual ~AddObjectDialog(); - - // ownership transferred to caller - void retrieveObject(ObjWidget ** widget, ObjSignature ** signature); - -private Q_SLOTS: - void update(const cv::Mat &); - void update(const cv::Mat &, const find_object::Header &, const cv::Mat &, float); - void next(); - void back(); - void cancel(); - void takePicture(); - void updateNextButton(); - void updateNextButton(const cv::Rect &); - void changeSelectionMode(); - -protected: - virtual void closeEvent(QCloseEvent* event); - -private: - void setState(int state); - cv::Rect computeROI(const std::vector & kpts); -private: - Ui_addObjectDialog * ui_; - Camera * camera_; - ObjWidget * objWidget_; - ObjSignature * objSignature_; - cv::Mat cameraImage_; - cv::Rect roi_; - Feature2D * detector_; - Feature2D * extractor_; - - enum State{kTakePicture, kSelectFeatures, kVerifySelection, kClosing}; - int state_; -}; - -} // namespace find_object - -#endif /* ADDOBJECTDIALOG_H_ */ diff --git a/find-object/src/CMakeLists.txt b/find-object/src/CMakeLists.txt deleted file mode 100644 index c6a95a69..00000000 --- a/find-object/src/CMakeLists.txt +++ /dev/null @@ -1,281 +0,0 @@ - - -### Qt Gui stuff ### -SET(headers_ui - ../include/${PROJECT_PREFIX}/MainWindow.h - ../include/${PROJECT_PREFIX}/FindObject.h - ../include/${PROJECT_PREFIX}/Camera.h - ../include/${PROJECT_PREFIX}/TcpServer.h - ../include/${PROJECT_PREFIX}/ObjWidget.h - ./AddObjectDialog.h - ./CameraTcpServer.h - ./ParametersToolBox.h - ./AboutDialog.h - ./RectItem.h - ./ImageDropWidget.h - ./rtabmap/PdfPlot.h - ./utilite/UPlot.h -) -IF(CATKIN_BUILD) - SET(headers_ui - ${headers_ui} - ./ros1/CameraROS.h - ./ros1/FindObjectROS.h - ) -ENDIF(CATKIN_BUILD) -IF(COLCON_BUILD) - SET(headers_ui - ${headers_ui} - ./ros2/CameraROS.h - ./ros2/FindObjectROS.h - ) -ENDIF(COLCON_BUILD) - -SET(uis - ./ui/mainWindow.ui - ./ui/addObjectDialog.ui - ./ui/aboutDialog.ui -) - -SET(qrc - ./resources.qrc -) - -IF(QT4_FOUND) - # generate rules for building source files from the resources - QT4_ADD_RESOURCES(srcs_qrc ${qrc}) - - #Generate .h files from the .ui files - QT4_WRAP_UI(moc_uis ${uis}) - - #This will generate moc_* for Qt - QT4_WRAP_CPP(moc_srcs ${headers_ui}) - ### Qt Gui stuff end### -ELSE() - QT5_ADD_RESOURCES(srcs_qrc ${qrc}) - QT5_WRAP_UI(moc_uis ${uis}) - QT5_WRAP_CPP(moc_srcs ${headers_ui}) -ENDIF() - -SET(SRC_FILES - ./MainWindow.cpp - ./AddObjectDialog.cpp - ./KeypointItem.cpp - ./RectItem.cpp - ./QtOpenCV.cpp - ./Camera.cpp - ./CameraTcpServer.cpp - ./ParametersToolBox.cpp - ./Settings.cpp - ./ObjWidget.cpp - ./ImageDropWidget.cpp - ./FindObject.cpp - ./AboutDialog.cpp - ./TcpServer.cpp - ./Vocabulary.cpp - ./JsonWriter.cpp - ./utilite/ULogger.cpp - ./utilite/UPlot.cpp - ./utilite/UDirectory.cpp - ./utilite/UFile.cpp - ./utilite/UConversion.cpp - ./rtabmap/PdfPlot.cpp - ./json/jsoncpp.cpp - ./Compression.cpp - ${moc_srcs} - ${moc_uis} - ${srcs_qrc} -) -IF(CATKIN_BUILD) - SET(SRC_FILES - ${SRC_FILES} - ./ros1/CameraROS.cpp - ./ros1/FindObjectROS.cpp - ) -ENDIF(CATKIN_BUILD) -IF(COLCON_BUILD) - SET(SRC_FILES - ${SRC_FILES} - ./ros2/CameraROS.cpp - ./ros2/FindObjectROS.cpp - ) -ENDIF(COLCON_BUILD) - -SET(INCLUDE_DIRS - ${CMAKE_CURRENT_SOURCE_DIR}/../include - ${CMAKE_CURRENT_SOURCE_DIR} - ${OpenCV_INCLUDE_DIRS} - ${CMAKE_CURRENT_BINARY_DIR} # for qt ui generated in binary dir - ${ZLIB_INCLUDE_DIRS} -) - -IF(QT4_FOUND) - INCLUDE(${QT_USE_FILE}) -ENDIF(QT4_FOUND) - -SET(LIBRARIES - ${QT_LIBRARIES} - ${OpenCV_LIBS} - ${ZLIB_LIBRARIES} -) -IF(CATKIN_BUILD) - SET(LIBRARIES - ${LIBRARIES} - ${catkin_LIBRARIES} - ) -ENDIF(CATKIN_BUILD) -IF(COLCON_BUILD) - SET(AMENT_LIBRARIES - rclcpp - rclcpp_components - cv_bridge - sensor_msgs - std_msgs - image_transport - message_filters - tf2 - tf2_ros - tf2_geometry_msgs - geometry_msgs - ) -ENDIF(COLCON_BUILD) - - -IF(TORCH_FOUND) - SET(LIBRARIES - ${LIBRARIES} - ${TORCH_LIBRARIES} - ) - SET(SRC_FILES - ${SRC_FILES} - superpoint_torch/SuperPoint.cc - ) - SET(INCLUDE_DIRS - ${TORCH_INCLUDE_DIRS} - ${CMAKE_CURRENT_SOURCE_DIR}/superpoint_torch - ${INCLUDE_DIRS} - ) - ADD_DEFINITIONS("-DWITH_TORCH") -ENDIF(TORCH_FOUND) - - -#include files -INCLUDE_DIRECTORIES(${INCLUDE_DIRS}) - -IF(CATKIN_BUILD) - INCLUDE_DIRECTORIES(SYSTEM ${catkin_INCLUDE_DIRS}) -ENDIF(CATKIN_BUILD) - -# create a library from the source files -ADD_LIBRARY(find_object ${SRC_FILES}) -# Linking with Qt libraries -IF(Qt5_FOUND) - QT5_USE_MODULES(find_object Widgets Core Gui Network PrintSupport) -ENDIF(Qt5_FOUND) - -IF(NOT COLCON_BUILD) - TARGET_LINK_LIBRARIES(find_object ${LIBRARIES}) -ENDIF() -IF(CATKIN_BUILD) - set_target_properties(find_object PROPERTIES OUTPUT_NAME find_object_2d) - add_dependencies(find_object ${${PROJECT_NAME}_EXPORTED_TARGETS}) -ENDIF(CATKIN_BUILD) -IF(COLCON_BUILD) - ament_target_dependencies(find_object ${AMENT_LIBRARIES}) - - if("$ENV{ROS_DISTRO}" STRGREATER_EQUAL "humble") - rosidl_get_typesupport_target(cpp_typesupport_target ${PROJECT_NAME} "rosidl_typesupport_cpp") - target_link_libraries(find_object ${cpp_typesupport_target} ${LIBRARIES}) - else() - # foxy, galatic - target_link_libraries(find_object ${LIBRARIES}) - rosidl_target_interfaces(find_object ${PROJECT_NAME} "rosidl_typesupport_cpp") - - function(rosidl_get_typesupport_target var generate_interfaces_target typesupport_name) - rosidl_target_interfaces(${var} ${generate_interfaces_target} ${typesupport_name}) - endfunction() - add_definitions(-DPRE_ROS_HUMBLE) - endif() -ENDIF(COLCON_BUILD) - -IF(NOT ROS_BUILD) - INSTALL(TARGETS find_object - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime - LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel - ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) - - install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../include/ DESTINATION "${INSTALL_INCLUDE_DIR}" COMPONENT devel FILES_MATCHING PATTERN "*.h" PATTERN ".svn" EXCLUDE) -ELSEIF(CATKIN_BUILD) - add_executable(find_object_2d ros1/find_object_2d_node.cpp) - target_link_libraries(find_object_2d find_object ${LIBRARIES}) - - add_executable(print_objects_detected ros1/print_objects_detected_node.cpp) - target_link_libraries(print_objects_detected ${LIBRARIES}) - add_dependencies(print_objects_detected ${${PROJECT_NAME}_EXPORTED_TARGETS}) - - add_executable(tf_example ros1/tf_example_node.cpp) - target_link_libraries(tf_example ${LIBRARIES}) - add_dependencies(tf_example ${${PROJECT_NAME}_EXPORTED_TARGETS}) - - IF(Qt5_FOUND) - QT5_USE_MODULES(find_object_2d Widgets Core Gui Network PrintSupport) - QT5_USE_MODULES(print_objects_detected Widgets Core Gui Network PrintSupport) - QT5_USE_MODULES(tf_example Widgets Core Gui Network PrintSupport) - ENDIF(Qt5_FOUND) - - ## Mark executables and/or libraries for installation - install(TARGETS - find_object - find_object_2d - print_objects_detected - tf_example - ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} - LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} - RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} - ) -ELSE() # COLCON_BUILD - add_executable(find_object_2d_node ros2/find_object_2d_node.cpp) - set_target_properties(find_object_2d_node PROPERTIES OUTPUT_NAME find_object_2d) - ament_target_dependencies(find_object_2d_node ${AMENT_LIBRARIES}) - target_link_libraries(find_object_2d_node find_object ${LIBRARIES}) - - add_executable(print_objects_detected ros2/print_objects_detected_node.cpp) - ament_target_dependencies(print_objects_detected ${AMENT_LIBRARIES}) - target_link_libraries(print_objects_detected find_object ${LIBRARIES}) - - add_executable(tf_example ros2/tf_example_node.cpp) - ament_target_dependencies(tf_example ${AMENT_LIBRARIES}) - target_link_libraries(tf_example find_object ${LIBRARIES}) - - # Only required when using messages built from the same package - # https://index.ros.org/doc/ros2/Tutorials/Rosidl-Tutorial/ - get_default_rmw_implementation(rmw_implementation) - find_package("${rmw_implementation}" REQUIRED) - get_rmw_typesupport(typesupport_impls "${rmw_implementation}" LANGUAGE "cpp") - - foreach(typesupport_impl ${typesupport_impls}) - rosidl_get_typesupport_target(find_object_2d_node - ${PROJECT_NAME} ${typesupport_impl} - ) - rosidl_get_typesupport_target(print_objects_detected - ${PROJECT_NAME} ${typesupport_impl} - ) - rosidl_get_typesupport_target(tf_example - ${PROJECT_NAME} ${typesupport_impl} - ) - endforeach() - - ## Mark executables and/or libraries for installation - install(TARGETS - find_object - ARCHIVE DESTINATION lib - LIBRARY DESTINATION lib - RUNTIME DESTINATION bin - ) - install(TARGETS - find_object_2d_node - print_objects_detected - tf_example - DESTINATION lib/${PROJECT_NAME} - ) -ENDIF() diff --git a/find-object/src/Camera.cpp b/find-object/src/Camera.cpp deleted file mode 100644 index 6630b6b3..00000000 --- a/find-object/src/Camera.cpp +++ /dev/null @@ -1,296 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "find_object/Camera.h" -#include "find_object/Settings.h" -#include "find_object/utilite/ULogger.h" -#include "find_object/QtOpenCV.h" - -#include -#include -#if CV_MAJOR_VERSION > 3 -#include -#endif -#include -#include "utilite/UDirectory.h" -#include "CameraTcpServer.h" - -namespace find_object { - -Camera::Camera(QObject * parent) : - QObject(parent), - currentImageIndex_(0), - cameraTcpServer_(0) -{ - qRegisterMetaType("cv::Mat"); - connect(&cameraTimer_, SIGNAL(timeout()), this, SLOT(takeImage())); -} - -Camera::~Camera() -{ - this->stop(); -} - -void Camera::stop() -{ - stopTimer(); - capture_.release(); - images_.clear(); - currentImageIndex_ = 0; - if(cameraTcpServer_) - { - cameraTcpServer_->close(); - delete cameraTcpServer_; - cameraTcpServer_ = 0; - } -} - -void Camera::pause() -{ - stopTimer(); -} - -int Camera::getTotalFrames() -{ - if(images_.size()) - { - return images_.size(); - } - else if(capture_.isOpened()) - { - return (int)capture_.get(CV_CAP_PROP_FRAME_COUNT); - } - return 0; -} - -int Camera::getCurrentFrameIndex() -{ - if(images_.size()) - { - return currentImageIndex_; - } - else if(capture_.isOpened()) - { - return (int)capture_.get(CV_CAP_PROP_POS_FRAMES); - } - return 0; -} - -void Camera::moveToFrame(int frame) -{ - if(frame < images_.size()) - { - currentImageIndex_ = frame; - } - else if(capture_.isOpened() && frame < (int)capture_.get(CV_CAP_PROP_FRAME_COUNT)) - { - capture_.set(CV_CAP_PROP_POS_FRAMES, frame); - } -} - -int Camera::getPort() -{ - if(cameraTcpServer_) - { - return cameraTcpServer_->getPort(); - } - return 0; -} - -void Camera::takeImage() -{ - cv::Mat img; - if(capture_.isOpened()) - { - capture_.read(img);// capture a frame - } - else if(!images_.empty()) - { - if(currentImageIndex_ < (unsigned int)images_.size()) - { - img = cv::imread(images_[currentImageIndex_++]); - } - } - else if(cameraTcpServer_) - { - img = cameraTcpServer_->getImage(); - if(cameraTcpServer_->imagesBuffered() > 0 && Settings::getCamera_9queueSize() == 0) - { - UWARN("%d images buffered so far...", cameraTcpServer_->imagesBuffered()); - } - } - - if(img.empty()) - { - if(cameraTcpServer_) - { - if(!cameraTcpServer_->isConnected()) - { - cameraTcpServer_->waitForNewConnection(100); - } - } - else - { - // In case of a directory of images or a video - this->stop(); - Q_EMIT finished(); // notify that there are no more images - } - } - else - { - //resize - if( Settings::getCamera_2imageWidth() && - Settings::getCamera_3imageHeight() && - Settings::getCamera_2imageWidth() != img.cols && - Settings::getCamera_3imageHeight() != img.rows) - { - cv::Mat resampled; - cv::resize(img, resampled, cv::Size(Settings::getCamera_2imageWidth(), Settings::getCamera_3imageHeight())); - Q_EMIT imageReceived(resampled); - } - else if(capture_.isOpened()) - { - Q_EMIT imageReceived(img.clone()); // clone required with VideoCapture::read() - } - else - { - Q_EMIT imageReceived(img); // clone not required with cv::imread() - } - } -} - -bool Camera::start() -{ - if(!capture_.isOpened() && images_.empty() && cameraTcpServer_ == 0) - { - if(Settings::getCamera_6useTcpCamera()) - { - cameraTcpServer_ = new CameraTcpServer(Settings::getCamera_8port(), this); - if(!cameraTcpServer_->isListening()) - { - UWARN("CameraTCP: Cannot listen to port %d", cameraTcpServer_->getPort()); - delete cameraTcpServer_; - cameraTcpServer_ = 0; - } - else - { - UINFO("CameraTCP: listening to port %d (IP=%s)", - cameraTcpServer_->getPort(), - cameraTcpServer_->getHostAddress().toString().toStdString().c_str()); - } - } - else - { - QString path = Settings::getCamera_5mediaPath(); - if(UDirectory::exists(path.toStdString())) - { - //Images directory - QString ext = Settings::getGeneral_imageFormats(); - ext.remove('*'); - ext.remove('.'); - UDirectory dir(path.toStdString(), ext.toStdString()); // this will load fileNames matching the extensions (in natural order) - const std::list & fileNames = dir.getFileNames(); - currentImageIndex_ = 0; - images_.clear(); - // Modify to have full path - for(std::list::const_iterator iter = fileNames.begin(); iter!=fileNames.end(); ++iter) - { - images_.append(path.toStdString() + UDirectory::separator() + *iter); - } - UINFO("Camera: Reading %d images from directory \"%s\"...", (int)images_.size(), path.toStdString().c_str()); - if(images_.isEmpty()) - { - UWARN("Camera: Directory \"%s\" is empty (no images matching the \"%s\" extensions). " - "If you want to disable loading automatically this directory, " - "clear the Camera/mediaPath parameter. By default, webcam will be used instead of the directory.", - path.toStdString().c_str(), - ext.toStdString().c_str()); - } - } - else if(!path.isEmpty()) - { - //Video file - capture_.open(path.toStdString().c_str()); - if(!capture_.isOpened()) - { - UWARN("Camera: Cannot open file \"%s\". If you want to disable loading " - "automatically this video file, clear the Camera/mediaPath parameter. " - "By default, webcam will be used instead of the file.", path.toStdString().c_str()); - } - else - { - UINFO("Camera: Reading from video file \"%s\"...", path.toStdString().c_str()); - } - } - if(!capture_.isOpened() && images_.empty()) - { - //set camera device - capture_.open(Settings::getCamera_1deviceId()); - if(Settings::getCamera_2imageWidth() && Settings::getCamera_3imageHeight()) - { - capture_.set(CV_CAP_PROP_FRAME_WIDTH, double(Settings::getCamera_2imageWidth())); - capture_.set(CV_CAP_PROP_FRAME_HEIGHT, double(Settings::getCamera_3imageHeight())); - } - UINFO("Camera: Reading from camera device %d...", Settings::getCamera_1deviceId()); - } - } - } - if(!capture_.isOpened() && images_.empty() && cameraTcpServer_ == 0) - { - UERROR("Camera: Failed to open a capture object!"); - return false; - } - - startTimer(); - return true; -} - -void Camera::startTimer() -{ - updateImageRate(); - cameraTimer_.start(); -} - -void Camera::stopTimer() -{ - cameraTimer_.stop(); -} - -void Camera::updateImageRate() -{ - if(Settings::getCamera_4imageRate()) - { - cameraTimer_.setInterval((int)(1000.0/Settings::getCamera_4imageRate())); - } - else - { - cameraTimer_.setInterval(0); - } -} - -} // namespace find_object - diff --git a/find-object/src/CameraTcpServer.cpp b/find-object/src/CameraTcpServer.cpp deleted file mode 100644 index ca4fadb2..00000000 --- a/find-object/src/CameraTcpServer.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#include "find_object/Settings.h" -#include "find_object/utilite/ULogger.h" - -#include "CameraTcpServer.h" -#include -#include -#include - -namespace find_object { - -CameraTcpServer::CameraTcpServer(quint16 port, QObject *parent) : - QTcpServer(parent), - blockSize_(0) -{ - if (!this->listen(QHostAddress::Any, port)) - { - UERROR("Unable to start the Camera TCP server: %s", this->errorString().toStdString().c_str()); - return; - } -} - -cv::Mat CameraTcpServer::getImage() -{ - cv::Mat img; - if(images_.size()) - { - // if queue changed after tcp connection ended with images still in the buffer - int queue = Settings::getCamera_9queueSize(); - while(queue > 0 && images_.size() > queue) - { - images_.pop_front(); - } - - img = images_.front(); - images_.pop_front(); - } - if(this->findChildren().size() == 1) - { - this->findChildren().first()->waitForReadyRead(100); - } - return img; -} - -bool CameraTcpServer::isConnected() const -{ - return this->findChildren().size() > 0; -} - -QHostAddress CameraTcpServer::getHostAddress() const -{ - QHostAddress hostAddress; - - QList ipAddressesList = QNetworkInterface::allAddresses(); - // use the first non-localhost IPv4 address - for (int i = 0; i < ipAddressesList.size(); ++i) - { - if (ipAddressesList.at(i) != QHostAddress::LocalHost && ipAddressesList.at(i).toIPv4Address()) - { - hostAddress = ipAddressesList.at(i).toString(); - break; - } - } - - // if we did not find one, use IPv4 localhost - if (hostAddress.isNull()) - { - hostAddress = QHostAddress(QHostAddress::LocalHost); - } - - return hostAddress; -} - -quint16 CameraTcpServer::getPort() const -{ - return this->serverPort(); -} -#if QT_VERSION >= 0x050000 -void CameraTcpServer::incomingConnection(qintptr socketDescriptor) -#else -void CameraTcpServer::incomingConnection(int socketDescriptor) -#endif -{ - QList clients = this->findChildren(); - if(clients.size() >= 1) - { - UWARN("A client is already connected. Only one connection allowed at the same time."); - QTcpSocket socket; - socket.setSocketDescriptor(socketDescriptor); - socket.close(); // close without sending an acknowledge - } - else - { - QTcpSocket * socket = new QTcpSocket(this); - connect(socket, SIGNAL(readyRead()), this, SLOT(readReceivedData())); - connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError))); - connect(socket, SIGNAL(disconnected()), this, SLOT(connectionLost())); - socket->setSocketDescriptor(socketDescriptor); - socket->write(QByteArray("1")); // send acknowledge - } -} - -void CameraTcpServer::readReceivedData() -{ - QTcpSocket * client = (QTcpSocket*)sender(); - QDataStream in(client); - in.setVersion(QDataStream::Qt_4_0); - - if (blockSize_ == 0) - { - if (client->bytesAvailable() < (int)sizeof(quint64)) - { - return; - } - - in >> blockSize_; - } - - if (client->bytesAvailable() < (int)blockSize_) - { - return; - } - - std::vector buf(blockSize_); - in.readRawData((char*)buf.data(), blockSize_); - images_.push_back(cv::imdecode(buf, cv::IMREAD_UNCHANGED)); - int queue = Settings::getCamera_9queueSize(); - while(queue > 0 && images_.size() > queue) - { - images_.pop_front(); - } - blockSize_ = 0; -} - -void CameraTcpServer::displayError(QAbstractSocket::SocketError socketError) -{ - switch (socketError) - { - case QAbstractSocket::RemoteHostClosedError: - break; - case QAbstractSocket::HostNotFoundError: - UWARN("CameraTcp: Tcp error: The host was not found. Please " - "check the host name and port settings.\n"); - break; - case QAbstractSocket::ConnectionRefusedError: - UWARN("CameraTcp: The connection was refused by the peer. " - "Make sure your images server is running, " - "and check that the host name and port " - "settings are correct."); - break; - default: - //UERROR("The following error occurred: %s.", this->errorString().toStdString().c_str()); - break; - } -} - -void CameraTcpServer::connectionLost() -{ - //printf("[WARNING] CameraTcp: Connection lost!\n"); - ((QTcpSocket*)sender())->close(); - sender()->deleteLater(); - blockSize_ = 0; // reset -} - -} // namespace find_object diff --git a/find-object/src/CameraTcpServer.h b/find-object/src/CameraTcpServer.h deleted file mode 100644 index af1581cf..00000000 --- a/find-object/src/CameraTcpServer.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef CAMERATCPCLIENT_H_ -#define CAMERATCPCLIENT_H_ - -#include -#include -#include - -namespace find_object { - -class CameraTcpServer : public QTcpServer -{ - Q_OBJECT; -public: - CameraTcpServer(quint16 port = 0, QObject * parent = 0); - cv::Mat getImage(); - int imagesBuffered() const {return images_.size();} - bool isConnected() const; - - QHostAddress getHostAddress() const; - quint16 getPort() const; - -protected: -#if QT_VERSION >= 0x050000 - virtual void incomingConnection ( qintptr socketDescriptor ); -#else - virtual void incomingConnection ( int socketDescriptor ); -#endif - -private Q_SLOTS: - void readReceivedData(); - void displayError(QAbstractSocket::SocketError socketError); - void connectionLost(); - -private: - quint64 blockSize_; - QVector images_; -}; - -} // namespace find_object - -#endif /* CAMERATCPCLIENT_H_ */ diff --git a/find-object/src/Compression.cpp b/find-object/src/Compression.cpp deleted file mode 100644 index dfcd89e9..00000000 --- a/find-object/src/Compression.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Compression.cpp - * - * Created on: Sep 10, 2018 - * Author: labm2414 - */ - -#include -#include -#include "find_object/utilite/ULogger.h" - -namespace find_object { - -std::vector compressData(const cv::Mat & data) -{ - std::vector bytes; - if(!data.empty()) - { - uLong sourceLen = uLong(data.total())*uLong(data.elemSize()); - uLong destLen = compressBound(sourceLen); - bytes.resize(destLen); - int errCode = compress( - (Bytef *)bytes.data(), - &destLen, - (const Bytef *)data.data, - sourceLen); - - bytes.resize(destLen+3*sizeof(int)); - *((int*)&bytes[destLen]) = data.rows; - *((int*)&bytes[destLen+sizeof(int)]) = data.cols; - *((int*)&bytes[destLen+2*sizeof(int)]) = data.type(); - - if(errCode == Z_MEM_ERROR) - { - UERROR("Z_MEM_ERROR : Insufficient memory."); - } - else if(errCode == Z_BUF_ERROR) - { - UERROR("Z_BUF_ERROR : The buffer dest was not large enough to hold the uncompressed data."); - } - } - return bytes; -} - -cv::Mat uncompressData(const unsigned char * bytes, unsigned long size) -{ - cv::Mat data; - if(bytes && size>=3*sizeof(int)) - { - //last 3 int elements are matrix size and type - int height = *((int*)&bytes[size-3*sizeof(int)]); - int width = *((int*)&bytes[size-2*sizeof(int)]); - int type = *((int*)&bytes[size-1*sizeof(int)]); - - data = cv::Mat(height, width, type); - uLongf totalUncompressed = uLongf(data.total())*uLongf(data.elemSize()); - - int errCode = uncompress( - (Bytef*)data.data, - &totalUncompressed, - (const Bytef*)bytes, - uLong(size)); - - if(errCode == Z_MEM_ERROR) - { - UERROR("Z_MEM_ERROR : Insufficient memory."); - } - else if(errCode == Z_BUF_ERROR) - { - UERROR("Z_BUF_ERROR : The buffer dest was not large enough to hold the uncompressed data."); - } - else if(errCode == Z_DATA_ERROR) - { - UERROR("Z_DATA_ERROR : The compressed data (referenced by source) was corrupted."); - } - } - return data; -} -} /* namespace find_object */ diff --git a/find-object/src/Compression.h b/find-object/src/Compression.h deleted file mode 100644 index 1676c8ea..00000000 --- a/find-object/src/Compression.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Compression.h - * - * Created on: Sep 10, 2018 - * Author: labm2414 - */ - -#ifndef SRC_COMPRESSION_H_ -#define SRC_COMPRESSION_H_ - -#include - -namespace find_object { - -std::vector compressData(const cv::Mat & data); -cv::Mat uncompressData(const unsigned char * bytes, unsigned long size); - -} - -#endif /* SRC_COMPRESSION_H_ */ diff --git a/find-object/src/FindObject.cpp b/find-object/src/FindObject.cpp deleted file mode 100644 index 77701157..00000000 --- a/find-object/src/FindObject.cpp +++ /dev/null @@ -1,1829 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "find_object/FindObject.h" -#include "find_object/Settings.h" -#include "find_object/utilite/ULogger.h" -#include "utilite/UConversion.h" - -#include "ObjSignature.h" -#include "utilite/UDirectory.h" -#include "Vocabulary.h" - -#include -#include -#include -#include -#include -#include -#include - -#if CV_MAJOR_VERSION > 3 -#include -#endif - -namespace find_object { - -FindObject::FindObject(bool keepImagesInRAM, QObject * parent) : - QObject(parent), - vocabulary_(new Vocabulary()), - detector_(Settings::createKeypointDetector()), - extractor_(Settings::createDescriptorExtractor()), - sessionModified_(false), - keepImagesInRAM_(keepImagesInRAM) -{ - qRegisterMetaType("find_object::DetectionInfo"); - qRegisterMetaType("find_object::Header"); - UASSERT(detector_ != 0 && extractor_ != 0); - - if(Settings::getGeneral_debug()) - { - ULogger::setPrintWhere(true); - ULogger::setLevel(ULogger::kDebug); - } - else - { - ULogger::setPrintWhere(false); - ULogger::setLevel(ULogger::kInfo); - } -} - -FindObject::~FindObject() { - delete detector_; - delete extractor_; - delete vocabulary_; - objectsDescriptors_.clear(); -} - -bool FindObject::loadSession(const QString & path, const ParametersMap & customParameters) -{ - if(QFile::exists(path) && !path.isEmpty() && QFileInfo(path).suffix().compare("bin") == 0) - { - QFile file(path); - file.open(QIODevice::ReadOnly); - QDataStream in(&file); - - ParametersMap parameters; - - // load parameters - in >> parameters; - for(QMap::iterator iter=parameters.begin(); iter!=parameters.end(); ++iter) - { - QMap::const_iterator cter = customParameters.find(iter.key()); - if(cter != customParameters.constEnd()) - { - Settings::setParameter(cter.key(), cter.value()); - } - else - { - Settings::setParameter(iter.key(), iter.value()); - } - } - - updateDetectorExtractor(); - - // load vocabulary - vocabulary_->load(in); - - // load objects - while(!in.atEnd()) - { - ObjSignature * obj = new ObjSignature(); - obj->load(in, !keepImagesInRAM_); - if(obj->id() >= 0) - { - objects_.insert(obj->id(), obj); - } - else - { - UERROR("Failed to load and object!"); - delete obj; - } - } - file.close(); - - if(!Settings::getGeneral_invertedSearch()) - { - // this will fill objectsDescriptors_ matrix - updateVocabulary(); - } - sessionModified_ = false; - return true; - } - else - { - UERROR("Invalid session file (should be *.bin): \"%s\"", path.toStdString().c_str()); - } - return false; -} - -bool FindObject::saveSession(const QString & path) -{ - if(!path.isEmpty() && QFileInfo(path).suffix().compare("bin") == 0) - { - QFile file(path); - file.open(QIODevice::WriteOnly); - QDataStream out(&file); - - // save parameters - out << Settings::getParameters(); - - // save vocabulary - vocabulary_->save(out); - - // save objects - for(QMultiMap::const_iterator iter=objects_.constBegin(); iter!=objects_.constEnd(); ++iter) - { - iter.value()->save(out); - } - - file.close(); - sessionModified_ = false; - return true; - } - UERROR("Path \"%s\" not valid (should be *.bin)", path.toStdString().c_str()); - return false; -} - -bool FindObject::saveVocabulary(const QString & filePath) const -{ - if(!filePath.isEmpty() && QFileInfo(filePath).suffix().compare("bin") == 0) - { - QFile file(filePath); - file.open(QIODevice::WriteOnly); - QDataStream out(&file); - - // ignore parameters - out << ParametersMap(); - - // save vocabulary - vocabulary_->save(out, true); - - file.close(); - return true; - } - else - { - return vocabulary_->save(filePath); - } - return false; -} - -bool FindObject::loadVocabulary(const QString & filePath) -{ - if(!Settings::getGeneral_vocabularyFixed() || !Settings::getGeneral_invertedSearch()) - { - UWARN("Doesn't make sense to load a vocabulary if \"General/vocabularyFixed\" and \"General/invertedSearch\" are not enabled! It will " - "be cleared at the time the objects are updated."); - } - - if(QFile::exists(filePath) && !filePath.isEmpty() && QFileInfo(filePath).suffix().compare("bin") == 0) - { - //binary format (from session format) - QFile file(filePath); - file.open(QIODevice::ReadOnly); - QDataStream in(&file); - - ParametersMap parameters; - // ignore parameters - in >> parameters; - - // load vocabulary - vocabulary_->load(in, true); - file.close(); - - return true; - } - else - { - //yaml/xml format - if(vocabulary_->load(filePath)) - { - if(objects_.size()) - { - updateVocabulary(); - } - return true; - } - } - return false; -} - -int FindObject::loadObjects(const QString & dirPath, bool recursive) -{ - QString formats = Settings::getGeneral_imageFormats().remove('*').remove('.'); - - QStringList paths; - paths.append(dirPath); - - QList idsLoaded; - while(paths.size()) - { - QString currentDir = paths.front(); - UDirectory dir(currentDir.toStdString(), formats.toStdString()); - if(dir.isValid()) - { - const std::list & names = dir.getFileNames(); // sorted in natural order - for(std::list::const_iterator iter=names.begin(); iter!=names.end(); ++iter) - { - const ObjSignature * s = this->addObject((currentDir.toStdString()+dir.separator()+*iter).c_str()); - if(s) - { - idsLoaded.push_back(s->id()); - } - } - } - - paths.pop_front(); - - if(recursive) - { - QDir d(currentDir); - QStringList subDirs = d.entryList(QDir::AllDirs|QDir::NoDotAndDotDot, QDir::Name); - for(int i=subDirs.size()-1; i>=0; --i) - { - paths.prepend(currentDir+QDir::separator()+subDirs[i]); - } - } - } - - if(idsLoaded.size()) - { - this->updateObjects(idsLoaded); - this->updateVocabulary(idsLoaded); - } - - return idsLoaded.size(); -} - -const ObjSignature * FindObject::addObject(const QString & filePath) -{ - if(!filePath.isNull()) - { - cv::Mat img = cv::imread(filePath.toStdString().c_str(), cv::IMREAD_GRAYSCALE); - if(!img.empty()) - { - int id = 0; - QFileInfo file(filePath); - QStringList list = file.fileName().split('.'); - if(list.size()) - { - bool ok = false; - id = list.front().toInt(&ok); - if(ok && id>0) - { - if(objects_.contains(id)) - { - UWARN("Object %d already added, a new ID will be generated (new id=%d).", id, Settings::getGeneral_nextObjID()); - id = 0; - } - } - else - { - id = 0; - } - } - else - { - UERROR("File name doesn't contain \".\" (\"%s\")", filePath.toStdString().c_str()); - } - - const ObjSignature * s = this->addObject(img, id, filePath); - if(s) - { - UINFO("Added object %d (%s)", s->id(), filePath.toStdString().c_str()); - return s; - } - } - else - { - UERROR("Could not read image \"%s\"", filePath.toStdString().c_str()); - } - } - else - { - UERROR("File path is null!?"); - } - return 0; -} - -const ObjSignature * FindObject::addObject(const cv::Mat & image, int id, const QString & filePath) -{ - UASSERT(id >= 0); - ObjSignature * s = new ObjSignature(id, image, filePath); - if(!this->addObject(s)) - { - delete s; - return 0; - } - return s; -} - -bool FindObject::addObject(ObjSignature * obj) -{ - UASSERT(obj != 0 && obj->id() >= 0); - if(obj->id() && objects_.contains(obj->id())) - { - UERROR("object with id %d already added!", obj->id()); - return false; - } - else if(obj->id() == 0) - { - obj->setId(Settings::getGeneral_nextObjID()); - } - - Settings::setGeneral_nextObjID(obj->id()+1); - - objects_.insert(obj->id(), obj); - - return true; -} - -void FindObject::removeObject(int id) -{ - if(objects_.contains(id)) - { - delete objects_.value(id); - objects_.remove(id); - clearVocabulary(); - } -} - -void FindObject::removeAllObjects() -{ - qDeleteAll(objects_); - objects_.clear(); - clearVocabulary(); -} - -void FindObject::addObjectAndUpdate(const cv::Mat & image, int id, const QString & filePath) -{ - const ObjSignature * s = this->addObject(image, id, filePath); - if(s) - { - QList ids; - ids.push_back(s->id()); - updateObjects(ids); - updateVocabulary(ids); - } -} - -void FindObject::removeObjectAndUpdate(int id) -{ - if(objects_.contains(id)) - { - delete objects_.value(id); - objects_.remove(id); - } - updateVocabulary(); -} - -void FindObject::updateDetectorExtractor() -{ - delete detector_; - delete extractor_; - detector_ = Settings::createKeypointDetector(); - extractor_ = Settings::createDescriptorExtractor(); - UASSERT(detector_ != 0 && extractor_ != 0); -} - -std::vector limitKeypoints(const std::vector & keypoints, int maxKeypoints) -{ - std::vector kptsKept; - if(maxKeypoints > 0 && (int)keypoints.size() > maxKeypoints) - { - // Sort words by response - std::multimap reponseMap; // - for(unsigned int i = 0; i (fabs(keypoints[i].response), i)); - } - - // Remove them - std::multimap::reverse_iterator iter = reponseMap.rbegin(); - kptsKept.resize(maxKeypoints); - for(unsigned int k=0; k < kptsKept.size() && iter!=reponseMap.rend(); ++k, ++iter) - { - kptsKept[k] = keypoints[iter->second]; - } - } - else - { - kptsKept = keypoints; - } - return kptsKept; -} - -void limitKeypoints(std::vector & keypoints, cv::Mat & descriptors, int maxKeypoints) -{ - UASSERT((int)keypoints.size() == descriptors.rows); - std::vector kptsKept; - cv::Mat descriptorsKept; - if(maxKeypoints > 0 && (int)keypoints.size() > maxKeypoints) - { - descriptorsKept = cv::Mat(0, descriptors.cols, descriptors.type()); - - // Sort words by response - std::multimap reponseMap; // - for(unsigned int i = 0; i (fabs(keypoints[i].response), i)); - } - - // Remove them - std::multimap::reverse_iterator iter = reponseMap.rbegin(); - kptsKept.resize(maxKeypoints); - descriptorsKept.reserve(maxKeypoints); - for(unsigned int k=0; k < kptsKept.size() && iter!=reponseMap.rend(); ++k, ++iter) - { - kptsKept[k] = keypoints[iter->second]; - descriptorsKept.push_back(descriptors.row(iter->second)); - } - } - keypoints = kptsKept; - descriptors = descriptorsKept; - UASSERT_MSG((int)keypoints.size() == descriptors.rows, uFormat("%d vs %d", (int)keypoints.size(), descriptors.rows).c_str()); -} - -void computeFeatures( - Feature2D * detector, - Feature2D * extractor, - const cv::Mat & image, - const cv::Mat & mask, - std::vector & keypoints, - cv::Mat & descriptors, - int & timeDetection, - int & timeExtraction) -{ - QTime timeStep; - timeStep.start(); - keypoints.clear(); - descriptors = cv::Mat(); - - int maxFeatures = Settings::getFeature2D_3MaxFeatures(); - if(Settings::currentDetectorType() == Settings::currentDescriptorType()) - { - detector->detectAndCompute(image, keypoints, descriptors, mask); - UASSERT_MSG((int)keypoints.size() == descriptors.rows, uFormat("%d vs %d", (int)keypoints.size(), descriptors.rows).c_str()); - if(maxFeatures > 0 && (int)keypoints.size() > maxFeatures) - { - limitKeypoints(keypoints, descriptors, maxFeatures); - } - timeDetection=timeStep.restart(); - timeExtraction = 0; - } - else - { - detector->detect(image, keypoints, mask); - if(maxFeatures > 0 && (int)keypoints.size() > maxFeatures) - { - keypoints = limitKeypoints(keypoints, maxFeatures); - } - timeDetection=timeStep.restart(); - - //Extract descriptors - try - { - extractor->compute(image, keypoints, descriptors); - UASSERT_MSG((int)keypoints.size() == descriptors.rows, uFormat("%d vs %d", (int)keypoints.size(), descriptors.rows).c_str()); - } - catch(cv::Exception & e) - { - UERROR("Descriptor exception: %s. Maybe some keypoints are invalid " - "for the selected descriptor extractor.", e.what()); - descriptors = cv::Mat(); - keypoints.clear(); - } - catch ( const std::exception& e ) - { - // standard exceptions - UERROR("Descriptor exception: %s. Maybe some keypoints are invalid " - "for the selected descriptor extractor.", e.what()); - descriptors = cv::Mat(); - keypoints.clear(); - } - timeExtraction+=timeStep.restart(); - } - - if( Settings::getFeature2D_SIFT_rootSIFT() && - Settings::currentDescriptorType() == "SIFT" && - !descriptors.empty()) - { - UINFO("Performing RootSIFT..."); - // see http://www.pyimagesearch.com/2015/04/13/implementing-rootsift-in-python-and-opencv/ - // apply the Hellinger kernel by first L1-normalizing and taking the - // square-root - for(int i=0; i(0,0) = A.at(1,1) = 1; - skewMask = cv::Mat::ones(h, w, CV_8U) * 255; - if(phi != 0.0) - { - phi = phi*CV_PI/180.0f; // deg2rad - float s = std::sin(phi); - float c = std::cos(phi); - cv::Mat A22 = (cv::Mat_(2, 2) << - c, -s, - s, c); - cv::Mat cornersIn = (cv::Mat_(4, 2) << - 0,0, - w,0, - w,h, - 0,h); - cv::Mat cornersOut = cornersIn * A22.t(); - cv::Rect rect = cv::boundingRect(cornersOut.reshape(2,4)); - A = (cv::Mat_(2, 3) << - c, -s, -rect.x, - s, c, -rect.y); - cv::warpAffine(image, skewImage, A, cv::Size(rect.width, rect.height), cv::INTER_LINEAR, cv::BORDER_REPLICATE); - } - else - { - skewImage = image; - } - if(tilt != 1.0) - { - float s = 0.8*std::sqrt(tilt*tilt-1); - cv::Mat out, out2; - cv::GaussianBlur(skewImage, out, cv::Size(0, 0), s, 0.01); - cv::resize(out, out2, cv::Size(0, 0), 1.0/tilt, 1.0, cv::INTER_NEAREST); - skewImage = out2; - A.row(0) /= tilt; - } - if(phi != 0.0 || tilt != 1.0) - { - cv::Mat mask = skewMask; - cv::warpAffine(mask, skewMask, A, skewImage.size(), cv::INTER_NEAREST); - } - cv::invertAffineTransform(A, Ai); -} - -class AffineExtractionThread : public QThread -{ -public: - AffineExtractionThread( - Feature2D * detector, - Feature2D * extractor, - const cv::Mat & image, - float tilt, - float phi) : - detector_(detector), - extractor_(extractor), - image_(image), - tilt_(tilt), - phi_(phi), - timeSkewAffine_(0), - timeDetection_(0), - timeExtraction_(0), - timeSubPix_(0) - { - UASSERT(detector && extractor); - } - const cv::Mat & image() const {return image_;} - const std::vector & keypoints() const {return keypoints_;} - const cv::Mat & descriptors() const {return descriptors_;} - - int timeSkewAffine() const {return timeSkewAffine_;} - int timeDetection() const {return timeDetection_;} - int timeExtraction() const {return timeExtraction_;} - int timeSubPix() const {return timeSubPix_;} - -protected: - virtual void run() - { - QTime timeStep; - timeStep.start(); - cv::Mat skewImage, skewMask, Ai; - FindObject::affineSkew(tilt_, phi_, image_, skewImage, skewMask, Ai); - timeSkewAffine_=timeStep.restart(); - - //Detect features - computeFeatures( - detector_, - extractor_, - skewImage, - skewMask, - keypoints_, - descriptors_, - timeDetection_, - timeExtraction_); - timeStep.start(); - - // Transform points to original image coordinates - for(unsigned int i=0; i(3, 1) << keypoints_[i].pt.x, keypoints_[i].pt.y, 1); - cv::Mat pa = Ai * p; - keypoints_[i].pt.x = pa.at(0,0); - keypoints_[i].pt.y = pa.at(1,0); - } - - if(keypoints_.size() && Settings::getFeature2D_6SubPix()) - { - // Sub pixel should be done after descriptors extraction - std::vector corners; - cv::KeyPoint::convert(keypoints_, corners); - cv::cornerSubPix(image_, - corners, - cv::Size(Settings::getFeature2D_7SubPixWinSize(), Settings::getFeature2D_7SubPixWinSize()), - cv::Size(-1,-1), - cv::TermCriteria( CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, Settings::getFeature2D_8SubPixIterations(), Settings::getFeature2D_9SubPixEps() )); - UASSERT(corners.size() == keypoints_.size()); - for(unsigned int i=0; i keypoints_; - cv::Mat descriptors_; - - int timeSkewAffine_; - int timeDetection_; - int timeExtraction_; - int timeSubPix_; -}; - -class ExtractFeaturesThread : public QThread -{ -public: - ExtractFeaturesThread( - Feature2D * detector, - Feature2D * extractor, - int objectId, - const cv::Mat & image) : - detector_(detector), - extractor_(extractor), - objectId_(objectId), - image_(image), - timeSkewAffine_(0), - timeDetection_(0), - timeExtraction_(0), - timeSubPix_(0) - { - UASSERT(detector && extractor); - UASSERT_MSG(!image.empty() && image.type() == CV_8UC1, - uFormat("Image of object %d is null or not type CV_8UC1!?!? (cols=%d, rows=%d, type=%d)", - objectId, image.cols, image.rows, image.type()).c_str()); - } - virtual ~ExtractFeaturesThread() {} - int objectId() const {return objectId_;} - const cv::Mat & image() const {return image_;} - const std::vector & keypoints() const {return keypoints_;} - const cv::Mat & descriptors() const {return descriptors_;} - - int timeSkewAffine() const {return timeSkewAffine_;} - int timeDetection() const {return timeDetection_;} - int timeExtraction() const {return timeExtraction_;} - int timeSubPix() const {return timeSubPix_;} - -protected: - virtual void run() - { - QTime time; - time.start(); - UDEBUG("Extracting descriptors from object %d...", objectId_); - - QTime timeStep; - timeStep.start(); - - if(!Settings::getFeature2D_4Affine()) - { - computeFeatures( - detector_, - extractor_, - image_, - cv::Mat(), - keypoints_, - descriptors_, - timeDetection_, - timeExtraction_); - timeStep.start(); - - if(keypoints_.size()) - { - UDEBUG("Detected %d features from object %d...", (int)keypoints_.size(), objectId_); - if(Settings::getFeature2D_6SubPix()) - { - // Sub pixel should be done after descriptors extraction - std::vector corners; - cv::KeyPoint::convert(keypoints_, corners); - cv::cornerSubPix(image_, - corners, - cv::Size(Settings::getFeature2D_7SubPixWinSize(), Settings::getFeature2D_7SubPixWinSize()), - cv::Size(-1,-1), - cv::TermCriteria( CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, Settings::getFeature2D_8SubPixIterations(), Settings::getFeature2D_9SubPixEps() )); - UASSERT(corners.size() == keypoints_.size()); - for(unsigned int i=0; i tilts; - std::vector phis; - tilts.push_back(1.0f); - phis.push_back(0.0f); - int nTilt = Settings::getFeature2D_5AffineCount(); - for(int t=1; t threads; - - for(unsigned int k=i; kstart(); - } - - for(int k=0; kwait(); - - keypoints_.insert(keypoints_.end(), threads[k]->keypoints().begin(), threads[k]->keypoints().end()); - descriptors_.push_back(threads[k]->descriptors()); - - timeSkewAffine_ += threads[k]->timeSkewAffine(); - timeDetection_ += threads[k]->timeDetection(); - timeExtraction_ += threads[k]->timeExtraction(); - timeSubPix_ += threads[k]->timeSubPix(); - - delete threads[k]; - } - } - } - - UINFO("%d descriptors extracted from object %d (in %d ms)", descriptors_.rows, objectId_, time.elapsed()); - } -private: - Feature2D * detector_; - Feature2D * extractor_; - int objectId_; - cv::Mat image_; - std::vector keypoints_; - cv::Mat descriptors_; - - int timeSkewAffine_; - int timeDetection_; - int timeExtraction_; - int timeSubPix_; -}; - -void FindObject::updateObjects(const QList & ids) -{ - UINFO("Update %d objects...", ids.size()); - QList objectsList; - if(ids.size()) - { - for(int i=0; i threads; - for(int k=i; kimage().empty()) - { - threads.push_back(new ExtractFeaturesThread(detector_, extractor_, objectsList.at(k)->id(), objectsList.at(k)->image())); - threads.back()->start(); - } - else - { - objects_.value(objectsList.at(k)->id())->setData(std::vector(), cv::Mat()); - if(keepImagesInRAM_) - { - UERROR("Empty image detected for object %d!? No features can be detected.", objectsList.at(k)->id()); - - } - else - { - UWARN("Empty image detected for object %d! No features can be detected. Note that images are in not kept in RAM.", objectsList.at(k)->id()); - } - } - } - - for(int j=0; jwait(); - - int id = threads[j]->objectId(); - - objects_.value(id)->setData(threads[j]->keypoints(), threads[j]->descriptors()); - - if(!keepImagesInRAM_) - { - objects_.value(id)->removeImage(); - } - delete threads[j]; - } - } - UINFO("Features extraction from %d objects... done! (%d ms)", objectsList.size(), time.elapsed()); - } - } - else - { - UINFO("No objects to update..."); - } -} - -void FindObject::clearVocabulary() -{ - objectsDescriptors_.clear(); - dataRange_.clear(); - vocabulary_->clear(); -} - -void FindObject::updateVocabulary(const QList & ids) -{ - int count = 0; - int dim = -1; - int type = -1; - QList objectsList; - if(ids.size()) - { - for(int i=0; isize()) - { - dim = vocabulary_->dim(); - type = vocabulary_->type(); - } - } - else - { - clearVocabulary(); - objectsList = objects_.values(); - } - - // Get the total size and verify descriptors - for(int i=0; idescriptors().empty()) - { - if(dim >= 0 && objectsList.at(i)->descriptors().cols != dim) - { - UERROR("Descriptors of the objects are not all the same size! Objects " - "opened must have all the same size (and from the same descriptor extractor)."); - return; - } - dim = objectsList.at(i)->descriptors().cols; - if(type >= 0 && objectsList.at(i)->descriptors().type() != type) - { - UERROR("Descriptors of the objects are not all the same type! Objects opened " - "must have been processed by the same descriptor extractor."); - return; - } - type = objectsList.at(i)->descriptors().type(); - count += objectsList.at(i)->descriptors().rows; - } - } - - UINFO("Updating vocabulary with %d objects and %d descriptors...", ids.size(), count); - - // Copy data - if(count) - { - UINFO("Updating global descriptors matrix: Objects=%d, total descriptors=%d, dim=%d, type=%d", - (int)objects_.size(), count, dim, type); - if(!Settings::getGeneral_invertedSearch()) - { - if(Settings::getGeneral_threads() == 1) - { - // If only one thread, put all descriptors in the same cv::Mat - int row = 0; - bool vocabularyEmpty = objectsDescriptors_.size() == 0; - if(vocabularyEmpty) - { - UASSERT(objectsDescriptors_.size() == 0); - objectsDescriptors_.insert(0, cv::Mat(count, dim, type)); - } - else - { - row = objectsDescriptors_.begin().value().rows; - } - for(int i=0; isetWords(QMultiMap()); - if(objectsList.at(i)->descriptors().rows) - { - if(vocabularyEmpty) - { - cv::Mat dest(objectsDescriptors_.begin().value(), cv::Range(row, row+objectsList.at(i)->descriptors().rows)); - objectsList.at(i)->descriptors().copyTo(dest); - } - else - { - UASSERT_MSG(objectsDescriptors_.begin().value().cols == objectsList.at(i)->descriptors().cols, - uFormat("%d vs %d", objectsDescriptors_.begin().value().cols, objectsList.at(i)->descriptors().cols).c_str()); - UASSERT(objectsDescriptors_.begin().value().type() == objectsList.at(i)->descriptors().type()); - objectsDescriptors_.begin().value().push_back(objectsList.at(i)->descriptors()); - } - - row += objectsList.at(i)->descriptors().rows; - // dataRange contains the upper_bound for each - // object (the last descriptors position in the - // global object descriptors matrix) - if(objectsList.at(i)->descriptors().rows) - { - dataRange_.insert(row-1, objectsList.at(i)->id()); - } - } - } - } - else - { - for(int i=0; isetWords(QMultiMap()); - objectsDescriptors_.insert(objectsList.at(i)->id(), objectsList.at(i)->descriptors()); - } - } - } - else - { - // Inverted index on (vocabulary) - sessionModified_ = true; - QTime time; - time.start(); - bool incremental = Settings::getGeneral_vocabularyIncremental() && !Settings::getGeneral_vocabularyFixed(); - if(incremental) - { - UINFO("Creating incremental vocabulary..."); - } - else if(Settings::getGeneral_vocabularyFixed()) - { - UINFO("Updating vocabulary correspondences only (vocabulary is fixed)..."); - } - else - { - UINFO("Creating vocabulary..."); - } - QTime localTime; - localTime.start(); - int updateVocabularyMinWords = Settings::getGeneral_vocabularyUpdateMinWords(); - int addedWords = 0; - for(int i=0; idescriptors().rows == (int)objectsList[i]->keypoints().size()); - QMultiMap words = vocabulary_->addWords(objectsList[i]->descriptors(), objectsList.at(i)->id()); - objectsList[i]->setWords(words); - addedWords += words.uniqueKeys().size(); - bool updated = false; - if(incremental && addedWords && addedWords >= updateVocabularyMinWords) - { - vocabulary_->update(); - addedWords = 0; - updated = true; - } - UINFO("Object %d, %d words from %d descriptors (%d words, %d ms) %s", - objectsList[i]->id(), - words.uniqueKeys().size(), - objectsList[i]->descriptors().rows, - vocabulary_->size(), - localTime.restart(), - updated?"updated":""); - } - if(addedWords && !Settings::getGeneral_vocabularyFixed()) - { - if(!incremental) - { - UINFO("Updating vocabulary..."); - } - vocabulary_->update(); - } - - if(incremental) - { - UINFO("Creating incremental vocabulary... done! size=%d (%d ms)", vocabulary_->size(), time.elapsed()); - } - else if(Settings::getGeneral_vocabularyFixed()) - { - UINFO("Updating vocabulary correspondences only (vocabulary is fixed)... done! size=%d (%d ms)", vocabulary_->size(), time.elapsed()); - } - else - { - UINFO("Creating vocabulary... done! size=%d (%d ms)", vocabulary_->size(), time.elapsed()); - } - } - } -} - -class SearchThread: public QThread -{ -public: - SearchThread(Vocabulary * vocabulary, int objectId, const cv::Mat * descriptors, const QMultiMap * sceneWords) : - vocabulary_(vocabulary), - objectId_(objectId), - descriptors_(descriptors), - sceneWords_(sceneWords), - minMatchedDistance_(-1.0f), - maxMatchedDistance_(-1.0f) - { - UASSERT(descriptors); - } - virtual ~SearchThread() {} - - int getObjectId() const {return objectId_;} - float getMinMatchedDistance() const {return minMatchedDistance_;} - float getMaxMatchedDistance() const {return maxMatchedDistance_;} - const QMultiMap & getMatches() const {return matches_;} - -protected: - virtual void run() - { - //QTime time; - //time.start(); - - cv::Mat results; - cv::Mat dists; - - //match objects to scene - int k = Settings::getNearestNeighbor_3nndrRatioUsed()?2:1; - results = cv::Mat(descriptors_->rows, k, CV_32SC1); // results index - dists = cv::Mat(descriptors_->rows, k, CV_32FC1); // Distance results are CV_32FC1 - vocabulary_->search(*descriptors_, results, dists, k); - - // PROCESS RESULTS - // Get all matches for each object - for(int i=0; i(i,0) <= Settings::getNearestNeighbor_4nndrRatio() * dists.at(i,1)) - { - matched = true; - } - if((matched || !Settings::getNearestNeighbor_3nndrRatioUsed()) && - Settings::getNearestNeighbor_5minDistanceUsed()) - { - if(dists.at(i,0) <= Settings::getNearestNeighbor_6minDistance()) - { - matched = true; - } - else - { - matched = false; - } - } - if(!matched && !Settings::getNearestNeighbor_3nndrRatioUsed() && !Settings::getNearestNeighbor_5minDistanceUsed()) - { - matched = true; // no criterion, match to the nearest descriptor - } - if(minMatchedDistance_ == -1 || minMatchedDistance_ > dists.at(i,0)) - { - minMatchedDistance_ = dists.at(i,0); - } - if(maxMatchedDistance_ == -1 || maxMatchedDistance_ < dists.at(i,0)) - { - maxMatchedDistance_ = dists.at(i,0); - } - - int wordId = results.at(i,0); - if(matched && sceneWords_->count(wordId) == 1) - { - matches_.insert(i, sceneWords_->value(wordId)); - matches_.insert(i, results.at(i,0)); - } - } - - //UINFO("Search Object %d time=%d ms", objectIndex_, time.elapsed()); - } -private: - Vocabulary * vocabulary_; // would be const but flann search() method is not const!? - int objectId_; - const cv::Mat * descriptors_; - const QMultiMap * sceneWords_; // - - float minMatchedDistance_; - float maxMatchedDistance_; - QMultiMap matches_; -}; - -class HomographyThread: public QThread -{ -public: - HomographyThread( - const QMultiMap * matches, // - int objectId, - const std::vector * kptsA, - const std::vector * kptsB, - const cv::Mat & imageA, // image only required if opticalFlow is on - const cv::Mat & imageB) : // image only required if opticalFlow is on - matches_(matches), - objectId_(objectId), - kptsA_(kptsA), - kptsB_(kptsB), - imageA_(imageA), - imageB_(imageB), - code_(DetectionInfo::kRejectedUndef) - { - UASSERT(matches && kptsA && kptsB); - } - virtual ~HomographyThread() {} - - int getObjectId() const {return objectId_;} - const std::vector & getIndexesA() const {return indexesA_;} - const std::vector & getIndexesB() const {return indexesB_;} - const std::vector & getOutlierMask() const {return outlierMask_;} - QMultiMap getInliers() const {return inliers_;} - QMultiMap getOutliers() const {return outliers_;} - const cv::Mat & getHomography() const {return h_;} - DetectionInfo::RejectedCode rejectedCode() const {return code_;} - -protected: - virtual void run() - { - //QTime time; - //time.start(); - - std::vector mpts_1(matches_->size()); - std::vector mpts_2(matches_->size()); - indexesA_.resize(matches_->size()); - indexesB_.resize(matches_->size()); - - UDEBUG("Fill matches..."); - int j=0; - for(QMultiMap::const_iterator iter = matches_->begin(); iter!=matches_->end(); ++iter) - { - UASSERT_MSG(iter.key() < (int)kptsA_->size(), uFormat("key=%d size=%d", iter.key(),(int)kptsA_->size()).c_str()); - UASSERT_MSG(iter.value() < (int)kptsB_->size(), uFormat("key=%d size=%d", iter.value(),(int)kptsB_->size()).c_str()); - mpts_1[j] = kptsA_->at(iter.key()).pt; - indexesA_[j] = iter.key(); - mpts_2[j] = kptsB_->at(iter.value()).pt; - indexesB_[j] = iter.value(); - ++j; - } - - if((int)mpts_1.size() >= Settings::getHomography_minimumInliers()) - { - if(Settings::getHomography_opticalFlow()) - { - UASSERT(!imageA_.empty() && !imageB_.empty()); - - cv::Mat imageA = imageA_; - cv::Mat imageB = imageB_; - if(imageA_.cols < imageB_.cols && imageA_.rows < imageB_.rows) - { - // padding, optical flow wants images of the same size - imageA = cv::Mat::zeros(imageB_.size(), imageA_.type()); - imageA_.copyTo(imageA(cv::Rect(0,0,imageA_.cols, imageA_.rows))); - } - if(imageA.size() == imageB.size()) - { - UDEBUG("Optical flow..."); - //refine matches - std::vector status; - std::vector err; - cv::calcOpticalFlowPyrLK( - imageA, - imageB_, - mpts_1, - mpts_2, - status, - err, - cv::Size(Settings::getHomography_opticalFlowWinSize(), Settings::getHomography_opticalFlowWinSize()), - Settings::getHomography_opticalFlowMaxLevel(), - cv::TermCriteria(cv::TermCriteria::COUNT+cv::TermCriteria::EPS, Settings::getHomography_opticalFlowIterations(), Settings::getHomography_opticalFlowEps()), - cv::OPTFLOW_LK_GET_MIN_EIGENVALS | cv::OPTFLOW_USE_INITIAL_FLOW, 1e-4); - } - else - { - UERROR("Object's image should be less/equal size of the scene image to use Optical Flow."); - } - } - - UDEBUG("Find homography... begin"); -#if CV_MAJOR_VERSION < 3 - h_ = findHomography(mpts_1, - mpts_2, - Settings::getHomographyMethod(), - Settings::getHomography_ransacReprojThr(), - outlierMask_); -#else - h_ = findHomography(mpts_1, - mpts_2, - Settings::getHomographyMethod(), - Settings::getHomography_ransacReprojThr(), - outlierMask_, - Settings::getHomography_maxIterations(), - Settings::getHomography_confidence()); -#endif - UDEBUG("Find homography... end"); - - UASSERT(outlierMask_.size() == 0 || outlierMask_.size() == mpts_1.size()); - for(unsigned int k=0; k * matches_; - int objectId_; - const std::vector * kptsA_; - const std::vector * kptsB_; - cv::Mat imageA_; - cv::Mat imageB_; - DetectionInfo::RejectedCode code_; - - std::vector indexesA_; - std::vector indexesB_; - std::vector outlierMask_; - QMultiMap inliers_; - QMultiMap outliers_; - cv::Mat h_; -}; - -void FindObject::detect(const cv::Mat & image) -{ - detect(image, Header(), cv::Mat(), 0.0); -} - -void FindObject::detect(const cv::Mat & image, const Header & header, const cv::Mat & depth, float depthConstant) -{ - QTime time; - time.start(); - DetectionInfo info; - this->detect(image, info); - - if(info.objDetected_.size() > 1) - { - UINFO("(%s) %d objects detected! (%d ms)", - QTime::currentTime().toString("HH:mm:ss.zzz").toStdString().c_str(), - (int)info.objDetected_.size(), - time.elapsed()); - } - else if(info.objDetected_.size() == 1) - { - UINFO("(%s) Object %d detected! (%d ms)", - QTime::currentTime().toString("HH:mm:ss.zzz").toStdString().c_str(), - (int)info.objDetected_.begin().key(), - time.elapsed()); - } - else if(Settings::getGeneral_sendNoObjDetectedEvents()) - { - UINFO("(%s) No objects detected. (%d ms)", - QTime::currentTime().toString("HH:mm:ss.zzz").toStdString().c_str(), - time.elapsed()); - } - - if(info.objDetected_.size() > 0 || Settings::getGeneral_sendNoObjDetectedEvents()) - { - Q_EMIT objectsFound(info, header, depth, depthConstant); - } -} - -bool FindObject::detect(const cv::Mat & image, find_object::DetectionInfo & info) const -{ - QTime totalTime; - totalTime.start(); - - // reset statistics - info = DetectionInfo(); - - bool success = false; - if(!image.empty()) - { - //Convert to grayscale - cv::Mat grayscaleImg; - if(image.channels() != 1 || image.depth() != CV_8U) - { - cv::cvtColor(image, grayscaleImg, cv::COLOR_BGR2GRAY); - } - else - { - grayscaleImg = image; - } - - // DETECT FEATURES AND EXTRACT DESCRIPTORS - UDEBUG("DETECT FEATURES AND EXTRACT DESCRIPTORS FROM THE SCENE"); - ExtractFeaturesThread extractThread(detector_, extractor_, -1, grayscaleImg); - extractThread.start(); - extractThread.wait(); - info.sceneKeypoints_ = extractThread.keypoints(); - info.sceneDescriptors_ = extractThread.descriptors(); - UASSERT_MSG((int)extractThread.keypoints().size() == extractThread.descriptors().rows, uFormat("%d vs %d", (int)extractThread.keypoints().size(), extractThread.descriptors().rows).c_str()); - info.timeStamps_.insert(DetectionInfo::kTimeKeypointDetection, extractThread.timeDetection()); - info.timeStamps_.insert(DetectionInfo::kTimeDescriptorExtraction, extractThread.timeExtraction()); - info.timeStamps_.insert(DetectionInfo::kTimeSubPixelRefining, extractThread.timeSubPix()); - info.timeStamps_.insert(DetectionInfo::kTimeSkewAffine, extractThread.timeSkewAffine()); - - bool consistentNNData = (vocabulary_->size()!=0 && vocabulary_->wordToObjects().begin().value()!=-1 && Settings::getGeneral_invertedSearch()) || - ((vocabulary_->size()==0 || vocabulary_->wordToObjects().begin().value()==-1) && !Settings::getGeneral_invertedSearch()); - - bool descriptorsValid = !Settings::getGeneral_invertedSearch() && - !objectsDescriptors_.empty() && - objectsDescriptors_.begin().value().cols == info.sceneDescriptors_.cols && - objectsDescriptors_.begin().value().type() == info.sceneDescriptors_.type(); - - bool vocabularyValid = Settings::getGeneral_invertedSearch() && - vocabulary_->size() && - !vocabulary_->indexedDescriptors().empty() && - vocabulary_->indexedDescriptors().cols == info.sceneDescriptors_.cols && - (vocabulary_->indexedDescriptors().type() == info.sceneDescriptors_.type() || - (Settings::getNearestNeighbor_7ConvertBinToFloat() && vocabulary_->indexedDescriptors().type() == CV_32FC1)); - - // COMPARE - UDEBUG("COMPARE"); - if((descriptorsValid || vocabularyValid) && - info.sceneKeypoints_.size() && - consistentNNData) - { - success = true; - QTime time; - time.start(); - - QMultiMap words; - - if(!Settings::getGeneral_invertedSearch()) - { - vocabulary_->clear(); - // CREATE INDEX for the scene - UDEBUG("CREATE INDEX FOR THE SCENE"); - words = vocabulary_->addWords(info.sceneDescriptors_, -1); - vocabulary_->update(); - info.timeStamps_.insert(DetectionInfo::kTimeIndexing, time.restart()); - info.sceneWords_ = words; - } - - for(QMap::const_iterator iter=objects_.begin(); iter!=objects_.end(); ++iter) - { - info.matches_.insert(iter.key(), QMultiMap()); - } - - if(Settings::getGeneral_invertedSearch() || Settings::getGeneral_threads() == 1) - { - cv::Mat results; - cv::Mat dists; - // DO NEAREST NEIGHBOR - UDEBUG("DO NEAREST NEIGHBOR"); - int k = Settings::getNearestNeighbor_3nndrRatioUsed()?2:1; - if(!Settings::getGeneral_invertedSearch()) - { - //match objects to scene - results = cv::Mat(objectsDescriptors_.begin().value().rows, k, CV_32SC1); // results index - dists = cv::Mat(objectsDescriptors_.begin().value().rows, k, CV_32FC1); // Distance results are CV_32FC1 - vocabulary_->search(objectsDescriptors_.begin().value(), results, dists, k); - } - else - { - //match scene to objects - results = cv::Mat(info.sceneDescriptors_.rows, k, CV_32SC1); // results index - dists = cv::Mat(info.sceneDescriptors_.rows, k, CV_32FC1); // Distance results are CV_32FC1 - vocabulary_->search(info.sceneDescriptors_, results, dists, k); - } - - // PROCESS RESULTS - UDEBUG("PROCESS RESULTS"); - // Get all matches for each object - for(int i=0; i(i,0) <= Settings::getNearestNeighbor_4nndrRatio() * dists.at(i,1)) - { - matched = true; - } - if((matched || !Settings::getNearestNeighbor_3nndrRatioUsed()) && - Settings::getNearestNeighbor_5minDistanceUsed()) - { - if(dists.at(i,0) <= Settings::getNearestNeighbor_6minDistance()) - { - matched = true; - } - else - { - matched = false; - } - } - if(!matched && - !Settings::getNearestNeighbor_3nndrRatioUsed() && - !Settings::getNearestNeighbor_5minDistanceUsed() && - dists.at(i,0) >= 0.0f) - { - matched = true; // no criterion, match to the nearest descriptor - } - if(info.minMatchedDistance_ == -1 || info.minMatchedDistance_ > dists.at(i,0)) - { - info.minMatchedDistance_ = dists.at(i,0); - } - if(info.maxMatchedDistance_ == -1 || info.maxMatchedDistance_ < dists.at(i,0)) - { - info.maxMatchedDistance_ = dists.at(i,0); - } - - if(matched) - { - int wordId = results.at(i,0); - if(Settings::getGeneral_invertedSearch()) - { - info.sceneWords_.insertMulti(wordId, i); - QList objIds = vocabulary_->wordToObjects().values(wordId); - for(int j=0; jwordToObjects().count(wordId, objIds[j]) == 1) - { - info.matches_.find(objIds[j]).value().insert(objects_.value(objIds[j])->words().value(wordId), i); - } - } - } - else - { - QMap::const_iterator iter = dataRange_.lowerBound(i); - int objectId = iter.value(); - int fisrtObjectDescriptorIndex = (iter == dataRange_.begin())?0:(--iter).key()+1; - int objectDescriptorIndex = i - fisrtObjectDescriptorIndex; - - if(words.count(wordId) == 1) - { - info.matches_.find(objectId).value().insert(objectDescriptorIndex, words.value(wordId)); - } - } - } - } - } - else - { - //multi-threaded, match objects to scene - UDEBUG("MULTI-THREADED, MATCH OBJECTS TO SCENE"); - int threadCounts = Settings::getGeneral_threads(); - if(threadCounts == 0) - { - threadCounts = (int)objectsDescriptors_.size(); - } - - QList objectsDescriptorsId = objectsDescriptors_.keys(); - QList objectsDescriptorsMat = objectsDescriptors_.values(); - for(int j=0; j threads; - - for(int k=j; kstart(); - } - - for(int k=0; kwait(); - info.matches_[threads[k]->getObjectId()] = threads[k]->getMatches(); - - if(info.minMatchedDistance_ == -1 || info.minMatchedDistance_ > threads[k]->getMinMatchedDistance()) - { - info.minMatchedDistance_ = threads[k]->getMinMatchedDistance(); - } - if(info.maxMatchedDistance_ == -1 || info.maxMatchedDistance_ < threads[k]->getMaxMatchedDistance()) - { - info.maxMatchedDistance_ = threads[k]->getMaxMatchedDistance(); - } - delete threads[k]; - } - - } - } - - info.timeStamps_.insert(DetectionInfo::kTimeMatching, time.restart()); - - // Homographies - if(Settings::getHomography_homographyComputed()) - { - // HOMOGRAPHY - UDEBUG("COMPUTE HOMOGRAPHY"); - int threadCounts = Settings::getGeneral_threads(); - if(threadCounts == 0) - { - threadCounts = info.matches_.size(); - } - QList matchesId = info.matches_.keys(); - QList > matchesList = info.matches_.values(); - for(int i=0; i threads; - - UDEBUG("Creating/Starting homography threads (%d)...", threadCounts); - for(int k=i; kkeypoints(), - &info.sceneKeypoints_, - objects_.value(objectId)->image(), - grayscaleImg)); - threads.back()->start(); - } - UDEBUG("Started homography threads"); - - for(int j=0; jwait(); - UDEBUG("Processing results of homography thread %d", j); - - int id = threads[j]->getObjectId(); - QTransform hTransform; - DetectionInfo::RejectedCode code = DetectionInfo::kRejectedUndef; - if(threads[j]->getHomography().empty()) - { - code = threads[j]->rejectedCode(); - } - if(code == DetectionInfo::kRejectedUndef && - threads[j]->getInliers().size() < Settings::getHomography_minimumInliers() ) - { - code = DetectionInfo::kRejectedLowInliers; - } - if(code == DetectionInfo::kRejectedUndef) - { - const cv::Mat & H = threads[j]->getHomography(); - UASSERT(H.cols == 3 && H.rows == 3 && H.type()==CV_64FC1); - hTransform = QTransform( - H.at(0,0), H.at(1,0), H.at(2,0), - H.at(0,1), H.at(1,1), H.at(2,1), - H.at(0,2), H.at(1,2), H.at(2,2)); - - // is homography valid? - // Here we use mapToScene() from QGraphicsItem instead - // of QTransform::map() because if the homography is not valid, - // huge errors are set by the QGraphicsItem and not by QTransform::map(); - UASSERT(objects_.contains(id)); - QRectF objectRect = objects_.value(id)->rect(); - QGraphicsRectItem item(objectRect); - item.setTransform(hTransform); - QPolygonF rectH = item.mapToScene(item.rect()); - - // If a point is outside of 2x times the surface of the scene, homography is invalid. - for(int p=0; p image.cols*2 && rectH.at(p).x() > objectRect.width()*2) || - (rectH.at(p).y() < -image.rows && rectH.at(p).x() < -objectRect.height()) || - (rectH.at(p).y() > image.rows*2 && rectH.at(p).x() > objectRect.height()*2)) - { - code= DetectionInfo::kRejectedNotValid; - break; - } - } - - // angle - if(code == DetectionInfo::kRejectedUndef && - Settings::getHomography_minAngle() > 0) - { - for(int a=0; a 180.0-minAngle) - { - code = DetectionInfo::kRejectedByAngle; - break; - } - } - } - - // multi detection - if(code == DetectionInfo::kRejectedUndef && - Settings::getGeneral_multiDetection()) - { - int distance = Settings::getGeneral_multiDetectionRadius(); // in pixels - // Get the outliers and recompute homography with them - matchesList.push_back(threads[j]->getOutliers()); - matchesId.push_back(id); - - // compute distance from previous added same objects... - QMultiMap::iterator objIter = info.objDetected_.find(id); - for(;objIter!=info.objDetected_.end() && objIter.key() == id; ++objIter) - { - qreal dx = objIter.value().m31() - hTransform.m31(); - qreal dy = objIter.value().m32() - hTransform.m32(); - int d = (int)sqrt(dx*dx + dy*dy); - if(d < distance) - { - distance = d; - } - } - - if(distance < Settings::getGeneral_multiDetectionRadius()) - { - code = DetectionInfo::kRejectedSuperposed; - } - } - - // Corners visible - if(code == DetectionInfo::kRejectedUndef && - Settings::getHomography_allCornersVisible()) - { - // Now verify if all corners are in the scene - QRectF sceneRect(0,0,image.cols, image.rows); - for(int p=0; prect().size()); - info.objDetectedInliers_.insert(id, threads[j]->getInliers()); - info.objDetectedOutliers_.insert(id, threads[j]->getOutliers()); - info.objDetectedInliersCount_.insert(id, threads[j]->getInliers().size()); - info.objDetectedOutliersCount_.insert(id, threads[j]->getOutliers().size()); - info.objDetectedFilePaths_.insert(id, objects_.value(id)->filePath()); - } - else - { - //Rejected! - info.rejectedInliers_.insert(id, threads[j]->getInliers()); - info.rejectedOutliers_.insert(id, threads[j]->getOutliers()); - info.rejectedCodes_.insert(id, code); - } - delete threads[j]; - } - UDEBUG("Processed matches %d", i+1); - } - info.timeStamps_.insert(DetectionInfo::kTimeHomography, time.restart()); - } - } - else if((descriptorsValid || vocabularyValid) && info.sceneKeypoints_.size()) - { - UWARN("Cannot search, objects must be updated"); - } - else if(info.sceneKeypoints_.size() == 0) - { - // Accept but warn the user - UWARN("No features detected in the scene!?!"); - success = true; - } - } - - info.timeStamps_.insert(DetectionInfo::kTimeTotal, totalTime.elapsed()); - - return success; -} - -} // namespace find_object diff --git a/find-object/src/ImageDropWidget.cpp b/find-object/src/ImageDropWidget.cpp deleted file mode 100644 index bd9ca634..00000000 --- a/find-object/src/ImageDropWidget.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * ImageDropWidget.cpp - * - * Created on: Dec 22, 2014 - * Author: mathieu - */ - -#include -#include -#include -#include -#include -#include - -namespace find_object { - -ImageDropWidget::ImageDropWidget(QWidget *parent, Qt::WindowFlags flags) : - QWidget(parent, flags) -{ - setAcceptDrops(true); -} - -ImageDropWidget::~ImageDropWidget() -{ -} - -void ImageDropWidget::dragEnterEvent(QDragEnterEvent *event) -{ - if (event->mimeData()->hasUrls()) - { - event->acceptProposedAction(); - } -} - -void ImageDropWidget::dropEvent(QDropEvent *event) -{ - QStringList fileNames; - - QStringList extensions = Settings::getGeneral_imageFormats().split(" "); - - QList urls = event->mimeData()->urls(); - for(int i=0; iacceptProposedAction(); -} - -} - diff --git a/find-object/src/ImageDropWidget.h b/find-object/src/ImageDropWidget.h deleted file mode 100644 index 04cdf699..00000000 --- a/find-object/src/ImageDropWidget.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * ImageDropWidget.h - * - * Created on: Dec 22, 2014 - * Author: mathieu - */ - -#ifndef IMAGEDROPWIDGET_H_ -#define IMAGEDROPWIDGET_H_ - -#include - -namespace find_object { - -class ImageDropWidget : public QWidget { - - Q_OBJECT; - -public: - ImageDropWidget(QWidget *parent = 0, Qt::WindowFlags flags = 0); - virtual ~ImageDropWidget(); - -Q_SIGNALS: - void imagesReceived(const QStringList &); - - -protected: - virtual void dragEnterEvent(QDragEnterEvent *event); - virtual void dropEvent(QDropEvent *event); -}; - -} - -#endif /* IMAGEDROPWIDGET_H_ */ diff --git a/find-object/src/JsonWriter.cpp b/find-object/src/JsonWriter.cpp deleted file mode 100644 index abda143a..00000000 --- a/find-object/src/JsonWriter.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "find_object/JsonWriter.h" -#include "find_object/utilite/ULogger.h" - -#include -#include -#include - -#include "json/json.h" - -namespace find_object { - -void JsonWriter::write(const DetectionInfo & info, const QString & path) -{ - if(!path.isEmpty()) - { - Json::Value root; - - if(info.objDetected_.size()) - { - Json::Value detections; - - QMultiMap::const_iterator iterInliers = info.objDetectedInliersCount_.constBegin(); - QMultiMap::const_iterator iterOutliers = info.objDetectedOutliersCount_.constBegin(); - QMultiMap::const_iterator iterSizes = info.objDetectedSizes_.constBegin(); - QMultiMap::const_iterator iterFilePaths = info.objDetectedFilePaths_.constBegin(); - for(QMultiMap::const_iterator iter = info.objDetected_.constBegin(); iter!= info.objDetected_.end();) - { - char index = 'a'; - int id = iter.key(); - while(iter != info.objDetected_.constEnd() && id == iter.key()) - { - QString name = QString("object_%1%2").arg(id).arg(info.objDetected_.count(id)>1?QString(index++):""); - detections.append(name.toStdString()); - - Json::Value homography; - homography.append(iter.value().m11()); - homography.append(iter.value().m12()); - homography.append(iter.value().m13()); - homography.append(iter.value().m21()); - homography.append(iter.value().m22()); - homography.append(iter.value().m23()); - homography.append(iter.value().m31()); // dx - homography.append(iter.value().m32()); // dy - homography.append(iter.value().m33()); - root[name.toStdString()]["width"] = iterSizes.value().width(); - root[name.toStdString()]["height"] = iterSizes.value().height(); - root[name.toStdString()]["homography"] = homography; - root[name.toStdString()]["inliers"] = iterInliers.value(); - root[name.toStdString()]["outliers"] = iterOutliers.value(); - root[name.toStdString()]["filepath"] = iterFilePaths.value().toStdString(); - QString filename; - if(!iterFilePaths.value().isEmpty()) - { - QFileInfo file(iterFilePaths.value()); - filename=file.fileName(); - } - root[name.toStdString()]["filename"] = filename.toStdString(); - - ++iter; - ++iterInliers; - ++iterOutliers; - ++iterSizes; - ++iterFilePaths; - } - } - root["objects"] = detections; - } - - if(info.matches_.size()) - { - Json::Value matchesValues; - const QMap > & matches = info.matches_; - for(QMap >::const_iterator iter = matches.constBegin(); - iter != matches.end(); - ++iter) - { - QString name = QString("matches_%1").arg(iter.key()); - root[name.toStdString()] = iter.value().size(); - matchesValues.append(name.toStdString()); - } - root["matches"] = matchesValues; - } - - // write in a nice readible way - Json::StyledWriter styledWriter; - //std::cout << styledWriter.write(root); - QFile file(path); - file.open(QIODevice::WriteOnly | QIODevice::Text); - QTextStream out(&file); - out << styledWriter.write(root).c_str(); - file.close(); - } -} - -} // namespace find_object diff --git a/find-object/src/KeypointItem.cpp b/find-object/src/KeypointItem.cpp deleted file mode 100644 index ec1834c4..00000000 --- a/find-object/src/KeypointItem.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "KeypointItem.h" - -#include -#include -#include - -namespace find_object { - -KeypointItem::KeypointItem(int id, qreal x, qreal y, int r, const cv::KeyPoint & kpt, int wordID, const QColor & color, QGraphicsItem * parent) : - QGraphicsEllipseItem(x, y, r, r, parent), - placeHolder_(0), - id_(id), - kpt_(kpt), - wordID_(wordID) -{ - this->setPen(QPen(color)); - this->setBrush(QBrush(color)); - this->setAcceptHoverEvents(true); - this->setFlag(QGraphicsItem::ItemIsFocusable, true); - this->setFlag(QGraphicsItem::ItemIsSelectable, true); -} - -KeypointItem::~KeypointItem() -{ -} - -void KeypointItem::setColor(const QColor & color) -{ - this->setPen(QPen(color)); - this->setBrush(QBrush(color)); - if(placeHolder_) - { - QList items = placeHolder_->childItems(); - if(items.size()) - { - ((QGraphicsTextItem *)items.front())->setDefaultTextColor(this->pen().color().rgb()); - } - } -} - -void KeypointItem::showDescription() -{ - if(!placeHolder_ || !placeHolder_->isVisible()) - { - if(!placeHolder_) - { - QString info = QString( "Keypoint = %1\n" - "Word = %2\n" - "Response = %3\n" - "Angle = %4\n" - "X = %5\n" - "Y = %6\n" - "Size = %7").arg(id_).arg(wordID_).arg(kpt_.response).arg(kpt_.angle).arg(kpt_.pt.x).arg(kpt_.pt.y).arg(kpt_.size); - - placeHolder_ = new QGraphicsRectItem(); - placeHolder_->setVisible(false); - this->scene()->addItem(placeHolder_); - placeHolder_->setBrush(QBrush(QColor ( 0, 0, 0, 170 ))); // Black transparent background - QGraphicsTextItem * text = new QGraphicsTextItem(placeHolder_); - text->setDefaultTextColor(this->pen().color().rgb()); - text->setPlainText(info); - placeHolder_->setRect(text->boundingRect()); - } - - - QPen pen = this->pen(); - this->setPen(QPen(pen.color(), pen.width()+2)); - placeHolder_->setZValue(this->zValue()+1); - placeHolder_->setPos(this->mapToScene(0,0)); - placeHolder_->setVisible(true); - } -} - -void KeypointItem::hideDescription() -{ - if(placeHolder_ && placeHolder_->isVisible()) - { - placeHolder_->setVisible(false); - this->setPen(QPen(pen().color(), pen().width()-2)); - } -} - -void KeypointItem::hoverEnterEvent ( QGraphicsSceneHoverEvent * event ) -{ - this->showDescription(); - QGraphicsEllipseItem::hoverEnterEvent(event); -} - -void KeypointItem::hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ) -{ - if(!this->hasFocus()) - { - this->hideDescription(); - } - QGraphicsEllipseItem::hoverEnterEvent(event); -} - -void KeypointItem::focusInEvent ( QFocusEvent * event ) -{ - this->showDescription(); - QGraphicsEllipseItem::focusInEvent(event); -} - -void KeypointItem::focusOutEvent ( QFocusEvent * event ) -{ - this->hideDescription(); - QGraphicsEllipseItem::focusOutEvent(event); -} - -} // namespace find_object diff --git a/find-object/src/KeypointItem.h b/find-object/src/KeypointItem.h deleted file mode 100644 index 63367347..00000000 --- a/find-object/src/KeypointItem.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef KEYPOINTITEM_H_ -#define KEYPOINTITEM_H_ - -#include -#include -#include -#include -#include - -namespace find_object { - -class KeypointItem : public QGraphicsEllipseItem -{ -public: - KeypointItem(int id, qreal x, qreal y, int r, const cv::KeyPoint & kpt, int wordID = -1, const QColor & color = Qt::green, QGraphicsItem * parent = 0); - virtual ~KeypointItem(); - - void setColor(const QColor & color); - void setWordID(int id) {wordID_ = id;} - int wordID() const {return wordID_;} - int id() const {return id_;} - -protected: - virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event ); - virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ); - virtual void focusInEvent ( QFocusEvent * event ); - virtual void focusOutEvent ( QFocusEvent * event ); - -private: - void showDescription(); - void hideDescription(); - -private: - QGraphicsRectItem * placeHolder_; - int id_; - cv::KeyPoint kpt_; - int wordID_; -}; - -} // namespace find_object - -#endif /* KEYPOINTITEM_H_ */ diff --git a/find-object/src/MainWindow.cpp b/find-object/src/MainWindow.cpp deleted file mode 100644 index 6c6830a9..00000000 --- a/find-object/src/MainWindow.cpp +++ /dev/null @@ -1,1709 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "find_object/MainWindow.h" -#include "find_object/Camera.h" -#include "find_object/Settings.h" -#include "find_object/TcpServer.h" -#include "find_object/FindObject.h" -#include "find_object/utilite/ULogger.h" -#include "find_object/ObjWidget.h" -#include "find_object/QtOpenCV.h" - -#include "AddObjectDialog.h" -#include "ui_mainWindow.h" -#include "KeypointItem.h" -#include "RectItem.h" -#include "ParametersToolBox.h" -#include "AboutDialog.h" -#include "rtabmap/PdfPlot.h" -#include "Vocabulary.h" -#include "ObjSignature.h" - -#include -#include - -#include "opencv2/calib3d/calib3d.hpp" -#include "opencv2/imgproc/imgproc.hpp" -#include -#if CV_MAJOR_VERSION < 3 -#include -#else -#include -#endif - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "utilite/UDirectory.h" - -namespace find_object { - -// Camera ownership transferred -MainWindow::MainWindow(FindObject * findObject, Camera * camera, QWidget * parent) : - QMainWindow(parent), - camera_(camera), - findObject_(findObject), - likelihoodCurve_(0), - inliersCurve_(0), - lowestRefreshRate_(99), - objectsModified_(false), - tcpServer_(0) -{ - UASSERT(findObject_ != 0); - - ui_ = new Ui_mainWindow(); - ui_->setupUi(this); - aboutDialog_ = new AboutDialog(this); - this->setStatusBar(new QStatusBar()); - - likelihoodCurve_ = new rtabmap::PdfPlotCurve("Likelihood", &imagesMap_, this); - inliersCurve_ = new rtabmap::PdfPlotCurve("Inliers", &imagesMap_, this); - likelihoodCurve_->setPen(QPen(Qt::blue)); - inliersCurve_->setPen(QPen(Qt::red)); - ui_->likelihoodPlot->addCurve(likelihoodCurve_, false); - ui_->likelihoodPlot->addCurve(inliersCurve_, false); - ui_->likelihoodPlot->setGraphicsView(true); - - ui_->dockWidget_statistics->setVisible(false); - ui_->dockWidget_parameters->setVisible(false); - ui_->dockWidget_plot->setVisible(false); - ui_->widget_controls->setVisible(false); - - QByteArray geometry; - QByteArray state; - Settings::loadWindowSettings(geometry, state); - this->restoreGeometry(geometry); - this->restoreState(state); - lastObjectsUpdateParameters_ = Settings::getParameters(); - - ui_->toolBox->setupUi(); - - if(!camera_) - { - camera_ = new Camera(this); - } - else - { - camera_->setParent(this); - ui_->toolBox->getParameterWidget(Settings::kCamera_1deviceId())->setEnabled(false); - ui_->toolBox->getParameterWidget(Settings::kCamera_2imageWidth())->setEnabled(false); - ui_->toolBox->getParameterWidget(Settings::kCamera_3imageHeight())->setEnabled(false); - ui_->toolBox->getParameterWidget(Settings::kCamera_5mediaPath())->setEnabled(false); - ui_->toolBox->getParameterWidget(Settings::kCamera_6useTcpCamera())->setEnabled(false); - ui_->toolBox->getParameterWidget(Settings::kCamera_8port())->setEnabled(false); - ui_->toolBox->getParameterWidget(Settings::kCamera_9queueSize())->setEnabled(false); - ui_->actionCamera_from_video_file->setVisible(false); - ui_->actionCamera_from_TCP_IP->setVisible(false); - ui_->actionCamera_from_directory_of_images->setVisible(false); - ui_->actionLoad_scene_from_file->setVisible(false); - } - -#if CV_MAJOR_VERSION < 3 - if(cv::gpu::getCudaEnabledDeviceCount() == 0) -#else - if(cv::cuda::getCudaEnabledDeviceCount() == 0) -#endif - { -#if FINDOBJECT_NONFREE == 1 - ui_->toolBox->updateParameter(Settings::kFeature2D_SURF_gpu()); - ui_->toolBox->getParameterWidget(Settings::kFeature2D_SURF_gpu())->setEnabled(false); - ui_->toolBox->getParameterWidget(Settings::kFeature2D_SURF_keypointsRatio())->setEnabled(false); -#endif - ui_->toolBox->updateParameter(Settings::kFeature2D_Fast_gpu()); - ui_->toolBox->updateParameter(Settings::kFeature2D_ORB_gpu()); - ui_->toolBox->updateParameter(Settings::kNearestNeighbor_BruteForce_gpu()); - ui_->toolBox->getParameterWidget(Settings::kFeature2D_Fast_gpu())->setEnabled(false); - ui_->toolBox->getParameterWidget(Settings::kFeature2D_Fast_keypointsRatio())->setEnabled(false); - ui_->toolBox->getParameterWidget(Settings::kFeature2D_ORB_gpu())->setEnabled(false); - ui_->toolBox->getParameterWidget(Settings::kNearestNeighbor_BruteForce_gpu())->setEnabled(false); - } - - connect((QDoubleSpinBox*)ui_->toolBox->getParameterWidget(Settings::kCamera_4imageRate()), - SIGNAL(editingFinished()), - camera_, - SLOT(updateImageRate())); - ui_->menuView->addAction(ui_->dockWidget_statistics->toggleViewAction()); - ui_->menuView->addAction(ui_->dockWidget_parameters->toggleViewAction()); - ui_->menuView->addAction(ui_->dockWidget_objects->toggleViewAction()); - ui_->menuView->addAction(ui_->dockWidget_plot->toggleViewAction()); - connect(ui_->toolBox, SIGNAL(parametersChanged(const QStringList &)), this, SLOT(notifyParametersChanged(const QStringList &))); - - ui_->imageView_source->setTextLabel(tr("Press \"space\" to start the camera or drop an image here...")); - ui_->imageView_source->setMirrorView(Settings::getGeneral_mirrorView()); - connect((QCheckBox*)ui_->toolBox->getParameterWidget(Settings::kGeneral_mirrorView()), - SIGNAL(stateChanged(int)), - this, - SLOT(updateMirrorView())); - - ui_->widget_controls->setVisible(Settings::getGeneral_controlsShown()); - connect((QCheckBox*)ui_->toolBox->getParameterWidget(Settings::kGeneral_controlsShown()), - SIGNAL(stateChanged(int)), - this, - SLOT(showHideControls())); - - //buttons - connect(ui_->pushButton_restoreDefaults, SIGNAL(clicked()), ui_->toolBox, SLOT(resetCurrentPage())); - connect(ui_->pushButton_updateObjects, SIGNAL(clicked()), this, SLOT(updateObjects())); - connect(ui_->horizontalSlider_objectsSize, SIGNAL(valueChanged(int)), this, SLOT(updateObjectsSize())); - - ui_->actionStop_camera->setEnabled(false); - ui_->actionPause_camera->setEnabled(false); - ui_->actionSave_objects->setEnabled(false); - ui_->actionSave_session->setEnabled(false); - - // Actions - connect(ui_->actionAdd_object_from_scene, SIGNAL(triggered()), this, SLOT(addObjectFromScene())); - connect(ui_->actionAdd_objects_from_files, SIGNAL(triggered()), this, SLOT(addObjectsFromFiles())); - connect(ui_->actionLoad_scene_from_file, SIGNAL(triggered()), this, SLOT(loadSceneFromFile())); - connect(ui_->actionStart_camera, SIGNAL(triggered()), this, SLOT(startProcessing())); - connect(ui_->actionStop_camera, SIGNAL(triggered()), this, SLOT(stopProcessing())); - connect(ui_->actionPause_camera, SIGNAL(triggered()), this, SLOT(pauseProcessing())); - connect(ui_->actionExit, SIGNAL(triggered()), this, SLOT(close())); - connect(ui_->actionSave_objects, SIGNAL(triggered()), this, SLOT(saveObjects())); - connect(ui_->actionLoad_objects, SIGNAL(triggered()), this, SLOT(loadObjects())); - connect(ui_->actionCamera_from_video_file, SIGNAL(triggered()), this, SLOT(setupCameraFromVideoFile())); - connect(ui_->actionCamera_from_directory_of_images, SIGNAL(triggered()), this, SLOT(setupCameraFromImagesDirectory())); - connect(ui_->actionCamera_from_TCP_IP, SIGNAL(triggered()), this, SLOT(setupCameraFromTcpIp())); - connect(ui_->actionAbout, SIGNAL(triggered()), aboutDialog_ , SLOT(exec())); - connect(ui_->actionRestore_all_default_settings, SIGNAL(triggered()), ui_->toolBox, SLOT(resetAllPages())); - connect(ui_->actionRemove_all_objects, SIGNAL(triggered()), this, SLOT(removeAllObjects())); - connect(ui_->actionSave_settings, SIGNAL(triggered()), this, SLOT(saveSettings())); - connect(ui_->actionLoad_settings, SIGNAL(triggered()), this, SLOT(loadSettings())); - connect(ui_->actionSave_session, SIGNAL(triggered()), this, SLOT(saveSession())); - connect(ui_->actionLoad_session, SIGNAL(triggered()), this, SLOT(loadSession())); - connect(ui_->actionSave_vocabulary, SIGNAL(triggered()), this, SLOT(saveVocabulary())); - connect(ui_->actionLoad_vocabulary, SIGNAL(triggered()), this, SLOT(loadVocabulary())); - connect(ui_->actionShow_objects_features, SIGNAL(triggered()), this, SLOT(showObjectsFeatures())); - connect(ui_->actionHide_objects_features, SIGNAL(triggered()), this, SLOT(hideObjectsFeatures())); - - connect(ui_->pushButton_play, SIGNAL(clicked()), this, SLOT(startProcessing())); - connect(ui_->pushButton_stop, SIGNAL(clicked()), this, SLOT(stopProcessing())); - connect(ui_->pushButton_pause, SIGNAL(clicked()), this, SLOT(pauseProcessing())); - connect(ui_->horizontalSlider_frames, SIGNAL(valueChanged(int)), this, SLOT(moveCameraFrame(int))); - connect(ui_->horizontalSlider_frames, SIGNAL(valueChanged(int)), ui_->label_frame, SLOT(setNum(int))); - ui_->pushButton_play->setVisible(true); - ui_->pushButton_pause->setVisible(false); - ui_->pushButton_stop->setEnabled(false); - ui_->horizontalSlider_frames->setEnabled(false); - ui_->label_frame->setVisible(false); - - ui_->objects_area->addAction(ui_->actionAdd_object_from_scene); - ui_->objects_area->addAction(ui_->actionAdd_objects_from_files); - ui_->objects_area->setContextMenuPolicy(Qt::ActionsContextMenu); - - ui_->actionStart_camera->setShortcut(Qt::Key_Space); - ui_->actionPause_camera->setShortcut(Qt::Key_Space); - - ui_->actionCamera_from_video_file->setChecked(!Settings::getCamera_5mediaPath().isEmpty() && !UDirectory::exists(Settings::getCamera_5mediaPath().toStdString())); - ui_->actionCamera_from_directory_of_images->setChecked(!Settings::getCamera_5mediaPath().isEmpty() && UDirectory::exists(Settings::getCamera_5mediaPath().toStdString())); - ui_->actionCamera_from_TCP_IP->setChecked(Settings::getCamera_6useTcpCamera()); - - ui_->label_ipAddress->setTextInteractionFlags(Qt::TextSelectableByMouse); - ui_->label_port->setTextInteractionFlags(Qt::TextSelectableByMouse); - setupTCPServer(); - - if(findObject_->objects().size()) - { - UINFO("Creating %d object widgets...", findObject_->objects().size()); - // show objects already loaded in FindObject - int i=0; - for(QMap::const_iterator iter = findObject_->objects().constBegin(); - iter!=findObject_->objects().constEnd(); - ++iter) - { - ObjWidget * obj = new ObjWidget(iter.key(), iter.value()->keypoints(), iter.value()->words(), iter.value()->image().empty()?QImage():cvtCvMat2QImage(iter.value()->image())); - objWidgets_.insert(obj->id(), obj); - this->showObject(obj); - ++i; - if(i % 100 == 0) - { - UINFO("Created %d/%d widgets...", i, findObject_->objects().size()); - } - } - UINFO("Creating %d object widgets... done!", findObject_->objects().size()); - ui_->actionSave_objects->setEnabled(true); - ui_->actionSave_session->setEnabled(true); - } - if(findObject_->vocabulary()->size()) - { - ui_->label_vocabularySize->setNum(findObject_->vocabulary()->size()); - ui_->actionSave_session->setEnabled(true); - } - - - if(Settings::getGeneral_autoStartCamera()) - { - // Set 1 msec to see state on the status bar. - QTimer::singleShot(1, this, SLOT(startProcessing())); - } - - //Setup drag and drop images - connect(ui_->imageDrop_objects, SIGNAL(imagesReceived(const QStringList &)), this, SLOT(addObjectsFromFiles(const QStringList &))); - connect(ui_->imageDrop_scene, SIGNAL(imagesReceived(const QStringList &)), this, SLOT(loadSceneFromFile(const QStringList &))); - - ui_->imageView_source->setFocus(); -} - -MainWindow::~MainWindow() -{ - disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); - disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)), this, SLOT(update(const cv::Mat &, const find_object::Header &, const cv::Mat &, float))); - disconnect(camera_, SIGNAL(finished()), this, SLOT(stopProcessing())); - camera_->stop(); - qDeleteAll(objWidgets_); - objWidgets_.clear(); - delete ui_; - delete findObject_; -} - -void MainWindow::closeEvent(QCloseEvent * event) -{ - bool quit = true; - this->stopProcessing(); - if(objectsModified_ && this->isVisible() && objWidgets_.size()) - { - int ret = QMessageBox::question(this, tr("Save new objects"), tr("Do you want to save added objects?"), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - switch(ret) - { - case QMessageBox::Yes: - quit = this->saveObjects(); - break; - case QMessageBox::Cancel: - quit = false; - break; - case QMessageBox::No: - default: - break; - } - } - if(quit) - { - Settings::saveWindowSettings(this->saveGeometry(), this->saveState()); - event->accept(); - } - else - { - event->ignore(); - } -} - -void MainWindow::keyPressEvent(QKeyEvent *event) -{ - //catch ctrl-s to save settings - if(event->key() == Qt::Key_Space) - { - if(ui_->actionStart_camera->isEnabled()) - { - startProcessing(); - } - else if(ui_->actionPause_camera->isEnabled()) - { - pauseProcessing(); - } - } -} - -void MainWindow::setupTCPServer() -{ - if(tcpServer_) - { - tcpServer_->close(); - delete tcpServer_; - } - tcpServer_ = new TcpServer(Settings::getGeneral_port(), this); - connect(this, SIGNAL(objectsFound(const find_object::DetectionInfo &, const find_object::Header &, const cv::Mat &, float)), tcpServer_, SLOT(publishDetectionInfo(find_object::DetectionInfo))); - ui_->label_ipAddress->setText(tcpServer_->getHostAddress().toString()); - ui_->label_port->setNum(tcpServer_->getPort()); - UINFO("Detection sent on port: %d (IP=%s)", tcpServer_->getPort(), tcpServer_->getHostAddress().toString().toStdString().c_str()); - - //connect services - connect(tcpServer_, SIGNAL(addObject(const cv::Mat &, int, const QString &)), this, SLOT(addObjectFromTcp(const cv::Mat &, int, const QString &))); - connect(tcpServer_, SIGNAL(removeObject(int)), this, SLOT(removeObject(int))); -} - -void MainWindow::setSourceImageText(const QString & text) -{ - ui_->imageView_source->setTextLabel(text); -} - -void MainWindow::loadSession() -{ - if(objWidgets_.size()) - { - QMessageBox::StandardButton b = QMessageBox::question(this, tr("Loading session..."), - tr("There are some objects (%1) already loaded, they will be " - "deleted when loading the session. Do you want to continue?").arg(objWidgets_.size()), - QMessageBox::Yes | QMessageBox::No, QMessageBox::NoButton); - if(b != QMessageBox::Yes) - { - return; - } - } - - QString path = QFileDialog::getOpenFileName(this, tr("Load session..."), Settings::workingDirectory(), "*.bin"); - if(!path.isEmpty()) - { - qDeleteAll(objWidgets_); - objWidgets_.clear(); - ui_->actionSave_objects->setEnabled(false); - findObject_->removeAllObjects(); - - if(findObject_->loadSession(path)) - { - //update parameters tool box - const ParametersMap & parameters = Settings::getParameters(); - for(ParametersMap::const_iterator iter = parameters.begin(); iter!= parameters.constEnd(); ++iter) - { - ui_->toolBox->updateParameter(iter.key()); - } - - //update object widgets - for(QMap::const_iterator iter=findObject_->objects().constBegin(); iter!=findObject_->objects().constEnd();++iter) - { - if(iter.value()) - { - ObjWidget * obj = new ObjWidget(iter.key(), iter.value()->keypoints(), iter.value()->words(), cvtCvMat2QImage(iter.value()->image())); - objWidgets_.insert(obj->id(), obj); - ui_->actionSave_objects->setEnabled(true); - ui_->actionSave_session->setEnabled(true); - this->showObject(obj); - - //update object labels - QLabel * title = this->findChild(QString("%1title").arg(iter.value()->id())); - title->setText(QString("%1 (%2)").arg(iter.value()->id()).arg(QString::number(iter.value()->keypoints().size()))); - } - - } - - QMessageBox::information(this, tr("Session loaded!"), tr("Session \"%1\" successfully loaded (%2 objects, %3 vocabulary words)!").arg(path).arg(objWidgets_.size()).arg(findObject_->vocabulary()->size())); - - if(!camera_->isRunning() && !sceneImage_.empty()) - { - this->update(sceneImage_); - } - } - } -} -void MainWindow::saveSession() -{ - QString path = QFileDialog::getSaveFileName(this, tr("Save session..."), Settings::workingDirectory(), "*.bin"); - if(!path.isEmpty()) - { - if(QFileInfo(path).suffix().compare("bin") != 0) - { - path.append(".bin"); - } - - if(findObject_->saveSession(path)) - { - QMessageBox::information(this, tr("Session saved!"), tr("Session \"%1\" successfully saved (%2 objects, %3 vocabulary words)!").arg(path).arg(objWidgets_.size()).arg(findObject_->vocabulary()->size())); - } - } -} - -void MainWindow::loadSettings() -{ - QString path = QFileDialog::getOpenFileName(this, tr("Load settings..."), Settings::workingDirectory(), "*.ini"); - if(!path.isEmpty()) - { - if(QFileInfo(path).suffix().compare("ini") != 0) - { - path.append(".ini"); - } - loadSettings(path); - } -} -void MainWindow::saveSettings() -{ - QString path = QFileDialog::getSaveFileName(this, tr("Save settings..."), Settings::workingDirectory(), "*.ini"); - if(!path.isEmpty()) - { - if(QFileInfo(path).suffix().compare("ini") != 0) - { - path.append(".ini"); - } - saveSettings(path); - } -} - -bool MainWindow::loadSettings(const QString & path) -{ - if(!path.isEmpty() && QFileInfo(path).suffix().compare("ini") == 0) - { - QByteArray geometry; - QByteArray state; - Settings::loadSettings(path); - Settings::loadWindowSettings(geometry, state, path); - this->restoreGeometry(geometry); - this->restoreState(state); - - //update parameters tool box - const ParametersMap & parameters = Settings::getParameters(); - for(ParametersMap::const_iterator iter = parameters.begin(); iter!= parameters.constEnd(); ++iter) - { - ui_->toolBox->updateParameter(iter.key()); - } - - return true; - } - UERROR("Path \"%s\" not valid (should be *.ini)", path.toStdString().c_str()); - return false; -} - -bool MainWindow::saveSettings(const QString & path) const -{ - if(!path.isEmpty() && QFileInfo(path).suffix().compare("ini") == 0) - { - Settings::saveSettings(path); - Settings::saveWindowSettings(this->saveGeometry(), this->saveState(), path); - return true; - } - UERROR("Path \"%s\" not valid (should be *.ini)", path.toStdString().c_str()); - return false; -} - -int MainWindow::loadObjects(const QString & dirPath, bool recursive) -{ - QList loadedObjects; - QString formats = Settings::getGeneral_imageFormats().remove('*').remove('.'); - - QStringList paths; - paths.append(dirPath); - - while(paths.size()) - { - QString currentDir = paths.front(); - UDirectory dir(currentDir.toStdString(), formats.toStdString()); - if(dir.isValid()) - { - const std::list & names = dir.getFileNames(); // sorted in natural order - for(std::list::const_iterator iter=names.begin(); iter!=names.end(); ++iter) - { - int id = this->addObjectFromFile((currentDir.toStdString()+dir.separator()+*iter).c_str()); - if(id >= 0) - { - loadedObjects.push_back(id); - } - } - } - - paths.pop_front(); - - if(recursive) - { - QDir d(currentDir); - QStringList subDirs = d.entryList(QDir::AllDirs|QDir::NoDotAndDotDot, QDir::Name); - for(int i=subDirs.size()-1; i>=0; --i) - { - paths.prepend(currentDir + QDir::separator() + subDirs[i]); - } - } - } - - if(loadedObjects.size()) - { - this->updateObjects(loadedObjects); - } - - return loadedObjects.size(); -} - -int MainWindow::saveObjects(const QString & dirPath) -{ - int count = 0; - QDir dir(dirPath); - if(dir.exists()) - { - for(QMap::const_iterator iter=objWidgets_.constBegin(); iter!=objWidgets_.constEnd(); ++iter) - { - if(iter.value()->pixmap().save(QString("%1/%2.png").arg(dirPath).arg(iter.key()))) - { - ++count; - } - else - { - UERROR("Failed to save object %d", iter.key()); - } - } - objectsModified_ = false; - } - return count; -} - -void MainWindow::loadObjects() -{ - QString dirPath = QFileDialog::getExistingDirectory(this, tr("Loading objects... Select a directory."), Settings::workingDirectory()); - if(!dirPath.isEmpty()) - { - QDir d(dirPath); - bool recursive = false; - if(d.entryList(QDir::AllDirs | QDir::NoDotAndDotDot).size()) - { - QMessageBox::StandardButton b = QMessageBox::question( - this, - tr("Loading objects..."), - tr("The current directory contains subdirectories. Load objects recursively?"), - QMessageBox::Yes|QMessageBox::No, - QMessageBox::No); - recursive = b == QMessageBox::Yes; - } - - int count = loadObjects(dirPath, recursive); - if(count) - { - QMessageBox::information(this, tr("Loading..."), tr("%1 objects loaded from \"%2\".").arg(count).arg(dirPath)); - } - else - { - QMessageBox::information(this, tr("Loading..."), tr("No objects loaded from \"%1\"!").arg(dirPath)); - } - } -} -bool MainWindow::saveObjects() -{ - QString dirPath = QFileDialog::getExistingDirectory(this, tr("Saving objects... Select a directory."), Settings::workingDirectory()); - if(!dirPath.isEmpty()) - { - int count = saveObjects(dirPath); - if(count) - { - QMessageBox::information(this, tr("Saving..."), tr("%1 objects saved to \"%2\".").arg(count).arg(dirPath)); - } - else - { - QMessageBox::warning(this, tr("Saving..."), tr("No objects saved to %1!").arg(dirPath)); - } - return count > 0; - } - return false; -} - -void MainWindow::loadVocabulary() -{ - if(!Settings::getGeneral_vocabularyFixed() || - !Settings::getGeneral_invertedSearch()) - { - QMessageBox::StandardButton b = QMessageBox::question(this, tr("Load vocabulary..."), - tr("Parameters \"General/vocabularyFixed\" and \"General/invertedSearch\" should be enabled to load a vocabulary. " - "Do you want to enable them now?"), - QMessageBox::Cancel | QMessageBox::Yes); - if(b == QMessageBox::Yes) - { - Settings::setGeneral_vocabularyFixed(true); - Settings::setGeneral_invertedSearch(true); - } - } - if(Settings::getGeneral_vocabularyFixed() && - Settings::getGeneral_invertedSearch()) - { - QString path = QFileDialog::getOpenFileName(this, tr("Load vocabulary..."), Settings::workingDirectory(), "Data (*.yaml *.xml *.bin)"); - if(!path.isEmpty()) - { - if(findObject_->loadVocabulary(path)) - { - ui_->label_vocabularySize->setNum(findObject_->vocabulary()->size()); - ui_->actionSave_session->setEnabled(findObject_->vocabulary()->size() || findObject_->objects().size()); - QMessageBox::information(this, tr("Loading..."), tr("Vocabulary loaded from \"%1\" (%2 words).").arg(path).arg(findObject_->vocabulary()->size())); - } - else - { - QMessageBox::warning(this, tr("Loading..."), tr("Failed to load vocabulary \"%1\"!").arg(path)); - } - } - } -} - -void MainWindow::saveVocabulary() -{ - if(findObject_->vocabulary()->size() == 0) - { - QMessageBox::warning(this, tr("Saving vocabulary..."), tr("Vocabulary is empty!")); - return; - } - QString path = QFileDialog::getSaveFileName(this, tr("Save vocabulary..."), Settings::workingDirectory(), "Data (*.yaml *.xml *.bin)"); - if(!path.isEmpty()) - { - if( QFileInfo(path).suffix().compare("yaml") != 0 && - QFileInfo(path).suffix().compare("xml") != 0 && - QFileInfo(path).suffix().compare("bin") != 0) - { - path.append(".yaml"); - } - if(findObject_->saveVocabulary(path)) - { - QMessageBox::information(this, tr("Saving..."), tr("Vocabulary saved to \"%1\" (%2 words).").arg(path).arg(findObject_->vocabulary()->size())); - } - else - { - QMessageBox::warning(this, tr("Saving..."), tr("Failed to save vocabulary \"%1\"!").arg(path)); - } - } -} - -void MainWindow::removeObject(find_object::ObjWidget * object) -{ - if(object) - { - objWidgets_.remove(object->id()); - if(objWidgets_.size() == 0) - { - ui_->actionSave_objects->setEnabled(false); - ui_->actionSave_session->setEnabled(false); - } - findObject_->removeObject(object->id()); - object->deleteLater(); - if(Settings::getGeneral_autoUpdateObjects()) - { - this->updateVocabulary(); - } - if(!camera_->isRunning() && !sceneImage_.empty()) - { - this->update(sceneImage_); - } - } -} - -void MainWindow::removeObject(int id) -{ - if(objWidgets_.contains(id)) - { - removeObject(objWidgets_[id]); - } - else - { - UERROR("Remove object: Object %d not found!", id); - } -} - -void MainWindow::removeAllObjects() -{ - qDeleteAll(objWidgets_); - objWidgets_.clear(); - ui_->actionSave_objects->setEnabled(false); - findObject_->removeAllObjects(); - if(!camera_->isRunning() && !sceneImage_.empty()) - { - this->update(sceneImage_); - } -} - -void MainWindow::updateObjectsSize() -{ - for(QMap::iterator iter=objWidgets_.begin(); iter!=objWidgets_.end(); ++iter) - { - updateObjectSize(iter.value()); - } -} - -void MainWindow::updateObjectSize(ObjWidget * obj) -{ - if(obj) - { - int value = ui_->horizontalSlider_objectsSize->value(); - if((obj->pixmap().width()*value)/100 > 4 && (obj->pixmap().height()*value)/100 > 4) - { - obj->setVisible(true); - obj->setMinimumSize((obj->pixmap().width()*value)/100, (obj->pixmap().height())*value/100); - } - else - { - obj->setVisible(false); - } - } -} - -void MainWindow::updateMirrorView() -{ - bool mirrorView = Settings::getGeneral_mirrorView(); - ui_->imageView_source->setMirrorView(mirrorView); - for(QMap::iterator iter=objWidgets_.begin(); iter!=objWidgets_.end(); ++iter) - { - iter.value()->setMirrorView(mirrorView); - } -} - -void MainWindow::showHideControls() -{ - ui_->widget_controls->setVisible(Settings::getGeneral_controlsShown()); -} - -void MainWindow::showObjectsFeatures() -{ - for(QMap::iterator iter=objWidgets_.begin(); iter!=objWidgets_.end(); ++iter) - { - iter.value()->setFeaturesShown(true); - } -} - -void MainWindow::hideObjectsFeatures() -{ - for(QMap::iterator iter=objWidgets_.begin(); iter!=objWidgets_.end(); ++iter) - { - iter.value()->setFeaturesShown(false); - } -} - -void MainWindow::addObjectFromScene() -{ - disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); - disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)), this, SLOT(update(const cv::Mat &, const find_object::Header &, const cv::Mat &, float))); - disconnect(camera_, SIGNAL(finished()), this, SLOT(stopProcessing())); - AddObjectDialog * dialog; - bool resumeCamera = camera_->isRunning(); - if(camera_->isRunning() || sceneImage_.empty()) - { - dialog = new AddObjectDialog(camera_, cv::Mat(), ui_->imageView_source->isMirrorView(), this); - } - else - { - dialog = new AddObjectDialog(0, sceneImage_, ui_->imageView_source->isMirrorView(), this); - } - if(dialog->exec() == QDialog::Accepted) - { - ObjWidget * obj = 0; - ObjSignature * signature = 0; - dialog->retrieveObject(&obj, &signature); - UASSERT(obj!=0 && signature!=0); - findObject_->addObject(signature); - obj->setId(signature->id()); - objWidgets_.insert(obj->id(), obj); - ui_->actionSave_objects->setEnabled(true); - ui_->actionSave_session->setEnabled(true); - showObject(obj); - QList ids; - ids.push_back(obj->id()); - updateVocabulary(ids); - objectsModified_ = true; - } - if(resumeCamera || sceneImage_.empty()) - { - this->startProcessing(); - } - else - { - connect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &)), Qt::UniqueConnection); - connect(camera_, SIGNAL(imageReceived(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)), this, SLOT(update(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)), Qt::UniqueConnection); - connect(camera_, SIGNAL(finished()), this, SLOT(stopProcessing()), Qt::UniqueConnection); - if(!sceneImage_.empty()) - { - this->update(sceneImage_); - } - } - delete dialog; -} - -void MainWindow::addObjectsFromFiles(const QStringList & fileNames) -{ - if(fileNames.size()) - { - QList ids; - for(int i=0; iaddObjectFromFile(fileNames.at(i)); - if(id >= 0) - { - ids.push_back(id); - } - } - if(ids.size()) - { - objectsModified_ = true; - updateObjects(ids); - } - } -} - -void MainWindow::addObjectsFromFiles() -{ - addObjectsFromFiles(QFileDialog::getOpenFileNames(this, tr("Add objects..."), Settings::workingDirectory(), tr("Image Files (%1)").arg(Settings::getGeneral_imageFormats()))); -} - -int MainWindow::addObjectFromFile(const QString & filePath) -{ - const ObjSignature * s = findObject_->addObject(filePath); - if(s) - { - ObjWidget * obj = new ObjWidget(s->id(), std::vector(), QMultiMap(), cvtCvMat2QImage(s->image())); - objWidgets_.insert(obj->id(), obj); - ui_->actionSave_objects->setEnabled(true); - ui_->actionSave_session->setEnabled(true); - this->showObject(obj); - return s->id(); - } - else - { - QMessageBox::critical(this, tr("Error adding object"), tr("Failed to add object from \"%1\"").arg(filePath)); - return -1; - } -} - -void MainWindow::addObjectFromTcp(const cv::Mat & image, int id, const QString & filePath) -{ - if(objWidgets_.contains(id)) - { - UERROR("Add Object: Object %d is already added.", id); - } - const ObjSignature * s = findObject_->addObject(image, id, filePath); - if(s) - { - ObjWidget * obj = new ObjWidget(s->id(), std::vector(), QMultiMap(), cvtCvMat2QImage(s->image())); - objWidgets_.insert(obj->id(), obj); - ui_->actionSave_objects->setEnabled(true); - ui_->actionSave_session->setEnabled(true); - this->showObject(obj); - QList ids; - ids.push_back(obj->id()); - updateObjects(ids); - } - else - { - UERROR("Add Object: Error adding object %d.", id); - } -} - -void MainWindow::loadSceneFromFile(const QStringList & fileNames) -{ - //take the first - if(fileNames.size()) - { - cv::Mat img = cv::imread(fileNames.first().toStdString().c_str()); - if(!img.empty()) - { - this->update(img); - ui_->label_timeRefreshRate->setVisible(false); - } - } -} - -void MainWindow::loadSceneFromFile() -{ - QString fileName = QFileDialog::getOpenFileName(this, tr("Load scene..."), Settings::workingDirectory(), tr("Image Files (%1)").arg(Settings::getGeneral_imageFormats())); - if(!fileName.isEmpty()) - { - cv::Mat img = cv::imread(fileName.toStdString().c_str()); - if(!img.empty()) - { - this->update(img); - ui_->label_timeRefreshRate->setVisible(false); - } - } -} - -void MainWindow::setupCameraFromVideoFile() -{ - if(!ui_->actionCamera_from_video_file->isChecked()) - { - Settings::setCamera_5mediaPath(""); - ui_->toolBox->updateParameter(Settings::kCamera_5mediaPath()); - } - else - { - QString fileName = QFileDialog::getOpenFileName(this, tr("Setup camera from video file..."), Settings::workingDirectory(), tr("Video Files (%1)").arg(Settings::getGeneral_videoFormats())); - if(!fileName.isEmpty()) - { - Settings::setCamera_6useTcpCamera(false); - ui_->toolBox->updateParameter(Settings::kCamera_6useTcpCamera()); - - Settings::setCamera_5mediaPath(fileName); - ui_->toolBox->updateParameter(Settings::kCamera_5mediaPath()); - if(camera_->isRunning()) - { - this->stopProcessing(); - this->startProcessing(); - } - Settings::setGeneral_controlsShown(true); - ui_->toolBox->updateParameter(Settings::kGeneral_controlsShown()); - } - } - ui_->actionCamera_from_video_file->setChecked(!Settings::getCamera_5mediaPath().isEmpty()); - ui_->actionCamera_from_directory_of_images->setChecked(false); - ui_->actionCamera_from_TCP_IP->setChecked(false); -} - -void MainWindow::setupCameraFromImagesDirectory() -{ - if(!ui_->actionCamera_from_directory_of_images->isChecked()) - { - Settings::setCamera_5mediaPath(""); - ui_->toolBox->updateParameter(Settings::kCamera_5mediaPath()); - } - else - { - QString directory = QFileDialog::getExistingDirectory(this, tr("Setup camera from directory of images..."), Settings::workingDirectory()); - if(!directory.isEmpty()) - { - Settings::setCamera_6useTcpCamera(false); - ui_->toolBox->updateParameter(Settings::kCamera_6useTcpCamera()); - - Settings::setCamera_5mediaPath(directory); - ui_->toolBox->updateParameter(Settings::kCamera_5mediaPath()); - if(camera_->isRunning()) - { - this->stopProcessing(); - this->startProcessing(); - } - Settings::setGeneral_controlsShown(true); - ui_->toolBox->updateParameter(Settings::kGeneral_controlsShown()); - } - } - ui_->actionCamera_from_directory_of_images->setChecked(!Settings::getCamera_5mediaPath().isEmpty()); - ui_->actionCamera_from_video_file->setChecked(false); - ui_->actionCamera_from_TCP_IP->setChecked(false); -} - -void MainWindow::setupCameraFromTcpIp() -{ - if(!ui_->actionCamera_from_TCP_IP->isChecked()) - { - Settings::setCamera_6useTcpCamera(false); - ui_->toolBox->updateParameter(Settings::kCamera_6useTcpCamera()); - } - else - { - bool ok; - int port = QInputDialog::getInt(this, tr("Server port..."), "Port: ", Settings::getCamera_8port(), 1, USHRT_MAX, 1, &ok); - - if(ok) - { - int queue = QInputDialog::getInt(this, tr("Queue size..."), "Images buffer size (0 means infinite): ", Settings::getCamera_9queueSize(), 0, 2147483647, 1, &ok); - if(ok) - { - Settings::setCamera_6useTcpCamera(true); - ui_->toolBox->updateParameter(Settings::kCamera_6useTcpCamera()); - Settings::setCamera_8port(port); - ui_->toolBox->updateParameter(Settings::kCamera_8port()); - Settings::setCamera_9queueSize(queue); - ui_->toolBox->updateParameter(Settings::kCamera_9queueSize()); - if(camera_->isRunning()) - { - this->stopProcessing(); - } - this->startProcessing(); - } - } - } - ui_->actionCamera_from_directory_of_images->setChecked(false); - ui_->actionCamera_from_video_file->setChecked(false); - ui_->actionCamera_from_TCP_IP->setChecked(Settings::getCamera_6useTcpCamera()); -} - -void MainWindow::showObject(ObjWidget * obj) -{ - if(obj) - { - obj->setGraphicsViewMode(false); - obj->setMirrorView(ui_->imageView_source->isMirrorView()); - QList objs = ui_->objects_area->findChildren(); - QVBoxLayout * vLayout = new QVBoxLayout(); - ui_->toolBox->updateParameter(Settings::kGeneral_nextObjID()); - - QLabel * title = new QLabel(QString("%1 (%2)").arg(obj->id()).arg(obj->keypoints().size()), this); - QLabel * detectedLabel = new QLabel(this); - title->setObjectName(QString("%1title").arg(obj->id())); - detectedLabel->setObjectName(QString("%1detection").arg(obj->id())); - QHBoxLayout * hLayout = new QHBoxLayout(); - hLayout->addWidget(title); - hLayout->addStretch(1); - hLayout->addStretch(1); - hLayout->addWidget(detectedLabel); - vLayout->addLayout(hLayout); - vLayout->addWidget(obj); - obj->setDeletable(true); - connect(obj, SIGNAL(removalTriggered(find_object::ObjWidget*)), this, SLOT(removeObject(find_object::ObjWidget*))); - connect(obj, SIGNAL(destroyed(QObject *)), title, SLOT(deleteLater())); - connect(obj, SIGNAL(destroyed(QObject *)), detectedLabel, SLOT(deleteLater())); - connect(obj, SIGNAL(destroyed(QObject *)), vLayout, SLOT(deleteLater())); - ui_->verticalLayout_objects->insertLayout(ui_->verticalLayout_objects->count()-1, vLayout); - - QByteArray ba; - if(obj->pixmap().width() > 0) - { - QBuffer buffer(&ba); - buffer.open(QIODevice::WriteOnly); - obj->pixmap().scaledToWidth(128).save(&buffer, "JPEG"); // writes image into JPEG format - } - imagesMap_.insert(obj->id(), ba); - - // update objects size slider - int objectsPanelWidth = ui_->dockWidget_objects->width(); - if(objectsPanelWidth > 0 && (obj->pixmap().width()*ui_->horizontalSlider_objectsSize->value()) / 100 > objectsPanelWidth) - { - ui_->horizontalSlider_objectsSize->setValue((objectsPanelWidth * 100) / obj->pixmap().width()); - } - else - { - updateObjectSize(obj); - } - } -} - -void MainWindow::updateObjects() -{ - updateObjects(QList()); -} - -void MainWindow::updateObjects(const QList & ids) -{ - if(objWidgets_.size()) - { - this->statusBar()->showMessage(tr("Updating %1 objects...").arg(ids.size()==0?objWidgets_.size():ids.size())); - - findObject_->updateObjects(ids); - - QList idsTmp = ids; - if(idsTmp.size() == 0) - { - idsTmp = objWidgets_.keys(); - } - - QList signatures = findObject_->objects().values(); - for(int i=0; iid())) - { - objWidgets_.value(signatures[i]->id())->updateData(signatures[i]->keypoints()); - - //update object labels - QLabel * title = this->findChild(QString("%1title").arg(signatures[i]->id())); - title->setText(QString("%1 (%2)").arg(signatures[i]->id()).arg(QString::number(signatures[i]->keypoints().size()))); - - QLabel * label = this->findChild(QString("%1detection").arg(signatures[i]->id())); - label->clear(); - } - } - - updateVocabulary(ids); - - if(!camera_->isRunning() && !sceneImage_.empty()) - { - this->update(sceneImage_); - } - this->statusBar()->clearMessage(); - } -} - -void MainWindow::updateVocabulary(const QList & ids) -{ - this->statusBar()->showMessage(tr("Updating vocabulary...")); - - QTime time; - time.start(); - findObject_->updateVocabulary(ids); - - QList idsTmp = ids; - if(idsTmp.size() == 0) - { - idsTmp = objWidgets_.keys(); - } - QList signatures = findObject_->objects().values(); - for(int i=0; iid())) - { - objWidgets_.value(signatures[i]->id())->updateWords(signatures[i]->words()); - } - } - - ui_->label_timeIndexing->setNum(time.elapsed()); - ui_->label_vocabularySize->setNum(findObject_->vocabulary()->size()); - if(ids.size() && findObject_->vocabulary()->size() == 0 && Settings::getGeneral_vocabularyFixed() && Settings::getGeneral_invertedSearch()) - { - QMessageBox::warning(this, tr("Vocabulary update"), tr("\"General/VocabularyFixed=true\" and the " - "vocabulary is empty. New features cannot be matched to any words in the vocabulary.")); - } - lastObjectsUpdateParameters_ = Settings::getParameters(); - this->statusBar()->clearMessage(); - ui_->dockWidget_objects->update(); -} - -void MainWindow::startProcessing() -{ - UINFO("Starting camera..."); - bool updateStatusMessage = this->statusBar()->currentMessage().isEmpty(); - if(updateStatusMessage) - { - this->statusBar()->showMessage(tr("Starting camera...")); - } - if(camera_->start()) - { - connect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &)), Qt::UniqueConnection); - connect(camera_, SIGNAL(imageReceived(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)), this, SLOT(update(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)), Qt::UniqueConnection); - connect(camera_, SIGNAL(finished()), this, SLOT(stopProcessing()), Qt::UniqueConnection); - ui_->actionStop_camera->setEnabled(true); - ui_->actionPause_camera->setEnabled(true); - ui_->actionStart_camera->setEnabled(false); - ui_->actionLoad_scene_from_file->setEnabled(false); - ui_->actionCamera_from_directory_of_images->setEnabled(false); - ui_->actionCamera_from_video_file->setEnabled(false); - ui_->actionCamera_from_TCP_IP->setEnabled(false); - ui_->label_timeRefreshRate->setVisible(true); - - //update control bar - ui_->pushButton_play->setVisible(false); - ui_->pushButton_pause->setVisible(true); - ui_->pushButton_stop->setEnabled(true); - int totalFrames = camera_->getTotalFrames(); - if(totalFrames>0) - { - ui_->label_frame->setVisible(true); - ui_->horizontalSlider_frames->setEnabled(true); - ui_->horizontalSlider_frames->setMaximum(totalFrames-1); - } - - //update camera port if TCP is used - ui_->label_port_image->setText("-"); - if(Settings::getCamera_6useTcpCamera() && camera_->getPort()) - { - ui_->label_port_image->setNum(camera_->getPort()); - } - - if(updateStatusMessage) - { - this->statusBar()->showMessage(tr("Camera started."), 2000); - } - } - else - { - if(updateStatusMessage) - { - this->statusBar()->clearMessage(); - } - - if(Settings::getCamera_6useTcpCamera()) - { - QMessageBox::critical(this, tr("Camera error"), tr("Camera initialization failed! (with port %1)").arg(Settings::getCamera_8port())); - } - else - { - QMessageBox::critical(this, tr("Camera error"), tr("Camera initialization failed! (with device %1)").arg(Settings::getCamera_1deviceId())); - } - } -} - -void MainWindow::stopProcessing() -{ - if(camera_) - { - disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); - disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)), this, SLOT(update(const cv::Mat &, const find_object::Header &, const cv::Mat &, float))); - disconnect(camera_, SIGNAL(finished()), this, SLOT(stopProcessing())); - camera_->stop(); - } - ui_->actionStop_camera->setEnabled(false); - ui_->actionPause_camera->setEnabled(false); - ui_->actionStart_camera->setEnabled(true); - ui_->actionLoad_scene_from_file->setEnabled(true); - ui_->actionCamera_from_directory_of_images->setEnabled(true); - ui_->actionCamera_from_video_file->setEnabled(true); - ui_->actionCamera_from_TCP_IP->setEnabled(true); - ui_->pushButton_play->setVisible(true); - ui_->pushButton_pause->setVisible(false); - ui_->pushButton_stop->setEnabled(false); - ui_->horizontalSlider_frames->setEnabled(false); - ui_->horizontalSlider_frames->setValue(0); - ui_->label_frame->setVisible(false); - ui_->label_port_image->setText("-"); -} - -void MainWindow::pauseProcessing() -{ - ui_->actionStop_camera->setEnabled(true); - ui_->actionPause_camera->setEnabled(true); - ui_->actionStart_camera->setEnabled(false); - if(camera_->isRunning()) - { - ui_->pushButton_play->setVisible(true); - ui_->pushButton_pause->setVisible(false); - camera_->pause(); - } - else - { - ui_->pushButton_play->setVisible(false); - ui_->pushButton_pause->setVisible(true); - camera_->start(); - } -} - -void MainWindow::moveCameraFrame(int frame) -{ - if(ui_->horizontalSlider_frames->isEnabled()) - { - camera_->moveToFrame(frame); - if(!camera_->isRunning()) - { - camera_->takeImage(); - } - } -} - -void MainWindow::rectHovered(int objId) -{ - if(objId>=0 && Settings::getGeneral_autoScroll()) - { - QLabel * label = ui_->dockWidget_objects->findChild(QString("%1title").arg(objId)); - if(label) - { - ui_->objects_area->verticalScrollBar()->setValue(label->pos().y()); - } - } -} - -void MainWindow::update(const cv::Mat & image) -{ - update(image, Header(), cv::Mat(), 0.0); -} - -void MainWindow::update(const cv::Mat & image, const Header & header, const cv::Mat & depth, float depthConstant) -{ - if(image.empty()) - { - UWARN("The image received is empty..."); - return; - } - sceneImage_ = image.clone(); - - // reset objects color - for(QMap::iterator iter=objWidgets_.begin(); iter!=objWidgets_.end(); ++iter) - { - iter.value()->resetKptsColor(); - if(!Settings::getGeneral_invertedSearch()) - { - iter.value()->resetKptsWordID(); - } - } - - QTime guiRefreshTime; - - DetectionInfo info; - if(findObject_->detect(sceneImage_, info)) - { - guiRefreshTime.start(); - ui_->label_timeDetection->setNum(info.timeStamps_.value(DetectionInfo::kTimeKeypointDetection, 0)); - ui_->label_timeSkewAffine->setNum(info.timeStamps_.value(DetectionInfo::kTimeSkewAffine, 0)); - ui_->label_timeExtraction->setNum(info.timeStamps_.value(DetectionInfo::kTimeDescriptorExtraction, 0)); - ui_->label_timeSubPix->setNum(info.timeStamps_.value(DetectionInfo::kTimeSubPixelRefining, 0)); - ui_->imageView_source->updateImage(cvtCvMat2QImage(sceneImage_)); - ui_->imageView_source->updateData(info.sceneKeypoints_, info.sceneWords_); - if(!findObject_->vocabulary()->size()) - { - ui_->label_timeIndexing->setNum(info.timeStamps_.value(DetectionInfo::kTimeIndexing, 0)); - } - ui_->label_timeMatching->setNum(info.timeStamps_.value(DetectionInfo::kTimeMatching, 0)); - ui_->label_timeHomographies->setNum(info.timeStamps_.value(DetectionInfo::kTimeHomography, 0)); - - ui_->label_vocabularySize->setNum(findObject_->vocabulary()->size()); - - // Colorize features matched - const QMap > & matches = info.matches_; - QMap scores; - int maxScoreId = -1; - int maxScore = 0; - for(QMap >::const_iterator jter=matches.constBegin(); jter!=matches.end();++jter) - { - scores.insert(jter.key(), jter.value().size()); - if(maxScoreId == -1 || maxScore < jter.value().size()) - { - maxScoreId = jter.key(); - maxScore = jter.value().size(); - } - - int id = jter.key(); - QLabel * label = ui_->dockWidget_objects->findChild(QString("%1detection").arg(id)); - if(!Settings::getHomography_homographyComputed()) - { - label->setText(QString("%1 matches").arg(jter.value().size())); - - ObjWidget * obj = objWidgets_.value(id); - UASSERT(obj != 0); - - for(QMultiMap::const_iterator iter = jter.value().constBegin(); iter!= jter.value().constEnd(); ++iter) - { - obj->setKptColor(iter.key(), obj->color()); - ui_->imageView_source->setKptColor(iter.value(), obj->color()); - if(!Settings::getGeneral_invertedSearch()) - { - obj->setKptWordID(iter.key(), ui_->imageView_source->words().value(iter.value(), -1)); - } - } - } - else if(!info.objDetected_.contains(id)) - { - // Homography could not be computed... - QLabel * label = ui_->dockWidget_objects->findChild(QString("%1detection").arg(id)); - QMultiMap rejectedInliers = info.rejectedInliers_.value(id); - QMultiMap rejectedOutliers = info.rejectedOutliers_.value(id); - int rejectedCode = info.rejectedCodes_.value(id); - if(rejectedCode == DetectionInfo::kRejectedLowMatches) - { - label->setText(QString("Too low matches (%1)").arg(jter.value().size())); - } - else if(rejectedCode == DetectionInfo::kRejectedAllInliers) - { - label->setText(QString("Ignored, all inliers (%1 in %2 out)").arg(rejectedInliers.size()).arg(rejectedOutliers.size())); - } - else if(rejectedCode == DetectionInfo::kRejectedNotValid) - { - label->setText(QString("Not valid homography (%1 in %2 out)").arg(rejectedInliers.size()).arg(rejectedOutliers.size())); - } - else if(rejectedCode == DetectionInfo::kRejectedLowInliers) - { - label->setText(QString("Too low inliers (%1 in %2 out)").arg(rejectedInliers.size()).arg(rejectedOutliers.size())); - } - else if(rejectedCode == DetectionInfo::kRejectedCornersOutside) - { - label->setText(QString("Corners not visible (%1 in %2 out)").arg(rejectedInliers.size()).arg(rejectedOutliers.size())); - } - else if(rejectedCode == DetectionInfo::kRejectedByAngle) - { - label->setText(QString("Angle too small (%1 in %2 out)").arg(rejectedInliers.size()).arg(rejectedOutliers.size())); - } - } - } - - if(info.objDetected_.size() && camera_->isRunning() && Settings::getGeneral_autoPauseOnDetection()) - { - this->pauseProcessing(); - } - - // Add homography rectangles when homographies are computed - int maxHomographyScoreId = -1; - int maxHomographyScore = 0; - QMultiMap >::const_iterator inliersIter = info.objDetectedInliers_.constBegin(); - QMultiMap >::const_iterator outliersIter = info.objDetectedOutliers_.constBegin(); - for(QMultiMap::iterator iter = info.objDetected_.begin(); - iter!=info.objDetected_.end(); - ++iter, ++inliersIter, ++outliersIter) - { - int id = iter.key(); - - if(maxHomographyScoreId == -1 || maxHomographyScore < inliersIter.value().size()) - { - maxHomographyScoreId = id; - maxHomographyScore = inliersIter.value().size(); - } - - ObjWidget * obj = objWidgets_.value(id); - UASSERT(obj != 0); - - // COLORIZE (should be done in the GUI thread) - QTransform hTransform = iter.value(); - - QRect rect = obj->pixmap().rect(); - // add rectangle - QPen rectPen(obj->color()); - rectPen.setWidth(Settings::getHomography_rectBorderWidth()); - if(rect.isNull()) - { - QMap::const_iterator iter = findObject_->objects().constFind(id); - if(iter!=findObject_->objects().end()) - { - rect = iter.value()->rect(); - } - } - RectItem * rectItemScene = new RectItem(id, rect); - connect(rectItemScene, SIGNAL(hovered(int)), this, SLOT(rectHovered(int))); - rectItemScene->setPen(rectPen); - rectItemScene->setTransform(hTransform); - ui_->imageView_source->addRect(rectItemScene); - - QGraphicsRectItem * rectItemObj = new QGraphicsRectItem(rect); - rectItemObj->setPen(rectPen); - obj->addRect(rectItemObj); - - for(QMultiMap::const_iterator iter = inliersIter.value().constBegin(); iter!= inliersIter.value().constEnd(); ++iter) - { - obj->setKptColor(iter.key(), obj->color()); - ui_->imageView_source->setKptColor(iter.value(), obj->color()); - if(!Settings::getGeneral_invertedSearch()) - { - obj->setKptWordID(iter.key(), ui_->imageView_source->words().value(iter.value(), -1)); - } - } - - QLabel * label = ui_->dockWidget_objects->findChild(QString("%1detection").arg(id)); - if(info.objDetected_.count(id) > 1) - { - // if a homography is already found, set the objects count - label->setText(QString("%1 objects found").arg(info.objDetected_.count(id))); - } - else - { - label->setText(QString("%1 in %2 out").arg(inliersIter.value().size()).arg(outliersIter.value().size())); - } - } - - // save screenshot of the detection - if(info.objDetected_.size() && !Settings::getGeneral_autoScreenshotPath().isEmpty()) - { - QDir dir(Settings::getGeneral_autoScreenshotPath()); - if(!dir.exists()) - { - QMessageBox::warning(this, tr("Screenshot on detection"), tr("Directory \"%1\" doesn't " - "exist, screenshot of the detection cannot be taken. Parameter \"%2\" is cleared.").arg(Settings::getGeneral_autoScreenshotPath()).arg(Settings::kGeneral_autoScreenshotPath())); - Settings::setGeneral_autoScreenshotPath(""); - ui_->toolBox->updateParameter(Settings::kGeneral_autoScreenshotPath()); - } - else - { - QString path = Settings::getGeneral_autoScreenshotPath() + QDir::separator() + (QDateTime::currentDateTime().toString("yyMMddhhmmsszzz") + ".jpg"); - if(!ui_->imageView_source->getSceneAsPixmap().save(path)) - { - UDEBUG("Failed to save screenshot \"%s\"! (%s is set)", path.toStdString().c_str(), Settings::kGeneral_autoScreenshotPath().toStdString().c_str()); - } - else - { - UINFO("Save screenshot \"%s\"! (%s is set)", path.toStdString().c_str(), Settings::kGeneral_autoScreenshotPath().toStdString().c_str()); - } - } - } - - //update likelihood plot - UDEBUG("Set likelihood score curve values (%d)", scores.size()); - likelihoodCurve_->setData(scores, QMap()); - QMap inlierScores; - for(QMap::iterator iter=scores.begin(); iter!=scores.end(); ++iter) - { - QList > values = info.objDetectedInliers_.values(iter.key()); - int maxValue = 0; - if(values.size()) - { - maxValue = values[0].size(); - for(int i=1; isetData(inlierScores, QMap()); - if(ui_->likelihoodPlot->isVisible()) - { - ui_->likelihoodPlot->update(); - } - - ui_->label_minMatchedDistance->setNum(info.minMatchedDistance_); - ui_->label_maxMatchedDistance->setNum(info.maxMatchedDistance_); - - //Scroll objects slider to the best score - if((maxScoreId>=0 || maxHomographyScoreId>=0) && Settings::getGeneral_autoScroll()) - { - QLabel * label = ui_->dockWidget_objects->findChild(QString("%1title").arg(maxHomographyScoreId>=0?maxHomographyScoreId:maxScoreId)); - if(label) - { - ui_->objects_area->verticalScrollBar()->setValue(label->pos().y()); - } - } - - // Emit homographies - if(info.objDetected_.size() > 1) - { - UINFO("(%s) %d objects detected!", - QTime::currentTime().toString("HH:mm:ss.zzz").toStdString().c_str(), - (int)info.objDetected_.size()); - } - else if(info.objDetected_.size() == 1) - { - UINFO("(%s) Object %d detected!", - QTime::currentTime().toString("HH:mm:ss.zzz").toStdString().c_str(), - (int)info.objDetected_.begin().key()); - } - else if(Settings::getGeneral_sendNoObjDetectedEvents()) - { - UINFO("(%s) No objects detected.", - QTime::currentTime().toString("HH:mm:ss.zzz").toStdString().c_str()); - } - - if(info.objDetected_.size() > 0 || Settings::getGeneral_sendNoObjDetectedEvents()) - { - Q_EMIT objectsFound(info, header, depth, depthConstant); - } - ui_->label_objectsDetected->setNum(info.objDetected_.size()); - } - else - { - guiRefreshTime.start(); - - if(findObject_->vocabulary()->size()) - { - this->statusBar()->showMessage(tr("Cannot search, objects must be updated!")); - } - ui_->label_timeDetection->setNum(info.timeStamps_.value(DetectionInfo::kTimeKeypointDetection, 0)); - ui_->label_timeSkewAffine->setNum(info.timeStamps_.value(DetectionInfo::kTimeSkewAffine, 0)); - ui_->label_timeExtraction->setNum(info.timeStamps_.value(DetectionInfo::kTimeDescriptorExtraction, 0)); - ui_->label_timeSubPix->setNum(info.timeStamps_.value(DetectionInfo::kTimeSubPixelRefining, 0)); - ui_->imageView_source->updateImage(cvtCvMat2QImage(sceneImage_)); - ui_->imageView_source->updateData(info.sceneKeypoints_, info.sceneWords_); - } - - - //Update object pictures - for(QMap::iterator iter=objWidgets_.begin(); iter!=objWidgets_.end(); ++iter) - { - iter.value()->update(); - } - - ui_->label_nfeatures->setNum((int)info.sceneKeypoints_.size()); - ui_->imageView_source->update(); - - ui_->label_detectorDescriptorType->setText(QString("%1/%2").arg(Settings::currentDetectorType()).arg(Settings::currentDescriptorType())); - - //update slider - if(ui_->horizontalSlider_frames->isEnabled()) - { - ui_->horizontalSlider_frames->blockSignals(true); - ui_->horizontalSlider_frames->setValue(camera_->getCurrentFrameIndex()-1); - ui_->label_frame->setNum(camera_->getCurrentFrameIndex()-1); - ui_->horizontalSlider_frames->blockSignals(false); - } - - ui_->label_timeTotal->setNum(info.timeStamps_.value(DetectionInfo::kTimeTotal, 0)); - int refreshRate = qRound(1000.0f/float(updateRate_.restart())); - if(refreshRate > 0 && refreshRate < lowestRefreshRate_) - { - lowestRefreshRate_ = refreshRate; - } - // Refresh the label only after each 1000 ms - if(refreshStartTime_.elapsed() > 1000) - { - if(Settings::getCamera_4imageRate()>0.0) - { - ui_->label_timeRefreshRate->setText(QString("(%1 Hz - %2 Hz)").arg(QString::number(Settings::getCamera_4imageRate())).arg(QString::number(lowestRefreshRate_))); - } - else - { - ui_->label_timeRefreshRate->setText(QString("(%2 Hz)").arg(QString::number(lowestRefreshRate_))); - } - lowestRefreshRate_ = 99; - refreshStartTime_.start(); - } - - ui_->label_timeRefreshGUI->setNum(guiRefreshTime.elapsed()); -} - -void MainWindow::notifyParametersChanged(const QStringList & paramChanged) -{ - //Selective update (to not update all objects for a simple camera's parameter modification) - bool detectorDescriptorParamsChanged = false; - bool nearestNeighborParamsChanged = false; - bool parameterChanged = false; - for(QStringList::const_iterator iter = paramChanged.begin(); iter!=paramChanged.end(); ++iter) - { - if(lastObjectsUpdateParameters_.value(*iter) != Settings::getParameter(*iter)) - { - lastObjectsUpdateParameters_[*iter] = Settings::getParameter(*iter); - parameterChanged = true; - UINFO("Parameter changed: %s -> \"%s\"", iter->toStdString().c_str(), Settings::getParameter(*iter).toString().toStdString().c_str()); - - if(iter->contains("Feature2D")) - { - detectorDescriptorParamsChanged = true; - } - else if( (iter->contains("NearestNeighbor") && Settings::getGeneral_invertedSearch()) || - iter->compare(Settings::kGeneral_invertedSearch()) == 0 || - (iter->compare(Settings::kGeneral_vocabularyIncremental()) == 0 && Settings::getGeneral_invertedSearch()) || - (iter->compare(Settings::kGeneral_vocabularyFixed()) == 0 && Settings::getGeneral_invertedSearch()) || - (iter->compare(Settings::kGeneral_threads()) == 0 && !Settings::getGeneral_invertedSearch()) ) - { - nearestNeighborParamsChanged = true; - } - - if(iter->compare(Settings::kGeneral_port()) == 0 && - Settings::getGeneral_port() != ui_->label_port->text().toInt() && - Settings::getGeneral_port() != 0) - { - setupTCPServer(); - } - } - } - - if(detectorDescriptorParamsChanged) - { - //Re-init detector and extractor - findObject_->updateDetectorExtractor(); - } - - if(Settings::getGeneral_autoUpdateObjects()) - { - if(detectorDescriptorParamsChanged) - { - this->updateObjects(); - } - else if(nearestNeighborParamsChanged) - { - this->updateVocabulary(); - } - } - else if(objWidgets_.size() && (detectorDescriptorParamsChanged || nearestNeighborParamsChanged)) - { - this->statusBar()->showMessage(tr("A parameter has changed... \"Update objects\" may be required.")); - } - - if(parameterChanged && - !camera_->isRunning() && - !sceneImage_.empty() && - !(Settings::getGeneral_autoUpdateObjects() && detectorDescriptorParamsChanged)) // already done in updateObjects() above - { - this->update(sceneImage_); - ui_->label_timeRefreshRate->setVisible(false); - } - ui_->actionCamera_from_video_file->setChecked(!Settings::getCamera_5mediaPath().isEmpty() && !UDirectory::exists(Settings::getCamera_5mediaPath().toStdString()) && !Settings::getCamera_6useTcpCamera()); - ui_->actionCamera_from_directory_of_images->setChecked(!Settings::getCamera_5mediaPath().isEmpty() && UDirectory::exists(Settings::getCamera_5mediaPath().toStdString()) && !Settings::getCamera_6useTcpCamera()); - ui_->actionCamera_from_TCP_IP->setChecked(Settings::getCamera_6useTcpCamera()); - - if(Settings::getGeneral_debug()) - { - ULogger::setPrintWhere(true); - ULogger::setLevel(ULogger::kDebug); - } - else - { - ULogger::setPrintWhere(false); - ULogger::setLevel(ULogger::kInfo); - } -} - -} // namespace find_object diff --git a/find-object/src/ObjSignature.h b/find-object/src/ObjSignature.h deleted file mode 100644 index 5ca14c92..00000000 --- a/find-object/src/ObjSignature.h +++ /dev/null @@ -1,202 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef OBJSIGNATURE_H_ -#define OBJSIGNATURE_H_ - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace find_object { - -class ObjSignature { -public: - ObjSignature() : - id_(-1) - {} - ObjSignature(int id, const cv::Mat & image, const QString & filePath) : - id_(id), - image_(image), - rect_(0,0,image.cols, image.rows), - filePath_(filePath) - {} - virtual ~ObjSignature() {} - - void setData(const std::vector & keypoints, const cv::Mat & descriptors) - { - keypoints_ = keypoints; - descriptors_ = descriptors; - } - void setWords(const QMultiMap & words) {words_ = words;} - void setId(int id) {id_ = id;} - void removeImage() {image_ = cv::Mat();} - - const QRect & rect() const {return rect_;} - - int id() const {return id_;} - const QString & filePath() const {return filePath_;} - const cv::Mat & image() const {return image_;} - const std::vector & keypoints() const {return keypoints_;} - const cv::Mat & descriptors() const {return descriptors_;} - const QMultiMap & words() const {return words_;} - - void save(QDataStream & streamPtr) const - { - streamPtr << id_; - streamPtr << filePath_; - streamPtr << (int)keypoints_.size(); - for(unsigned int j=0; j bytes = compressData(descriptors_); - - qint64 dataSize = bytes.size(); - int old = 0; - if(dataSize <= std::numeric_limits::max()) - { - // old: rows, cols, type - streamPtr << old << old << old << dataSize; - streamPtr << QByteArray::fromRawData((const char*)bytes.data(), dataSize); - } - else - { - UERROR("Descriptors (compressed) are too large (%d MB) to be saved! Limit is 2 GB (based on max QByteArray size).", - dataSize/(1024*1024)); - // old: rows, cols, type, dataSize - streamPtr << old << old << old << old; - streamPtr << QByteArray(); // empty - } - - streamPtr << words_; - - if(!image_.empty()) - { - std::vector bytes; - QString ext = QFileInfo(filePath_).suffix(); - if(ext.isEmpty()) - { - // default png - cv::imencode(".png", image_, bytes); - } - else - { - cv::imencode(std::string(".")+ext.toStdString(), image_, bytes); - } - streamPtr << QByteArray::fromRawData((const char*)bytes.data(), (int)bytes.size()); - } - else - { - streamPtr << QByteArray(); - } - - streamPtr << rect_; - } - - void load(QDataStream & streamPtr, bool ignoreImage) - { - int nKpts; - streamPtr >> id_ >> filePath_ >> nKpts; - keypoints_.resize(nKpts); - for(int i=0;i> - keypoints_[i].angle >> - keypoints_[i].class_id >> - keypoints_[i].octave >> - keypoints_[i].pt.x >> - keypoints_[i].pt.y >> - keypoints_[i].response >> - keypoints_[i].size; - } - - int rows,cols,type; - qint64 dataSize; - streamPtr >> rows >> cols >> type >> dataSize; - if(rows == 0 && cols == 0 && type == 0) - { - // compressed descriptors - UASSERT(dataSize <= std::numeric_limits::max()); - QByteArray data; - streamPtr >> data; - descriptors_ = uncompressData((unsigned const char*)data.data(), dataSize); - } - else - { - // old raw format - QByteArray data; - streamPtr >> data; - if(data.size()) - { - descriptors_ = cv::Mat(rows, cols, type, data.data()).clone(); - } - else if(dataSize) - { - UERROR("Error reading descriptor data for object=%d", id_); - } - } - - streamPtr >> words_; - - QByteArray image; - streamPtr >> image; - if(!ignoreImage && image.size()) - { - std::vector bytes(image.size()); - memcpy(bytes.data(), image.data(), image.size()); - image_ = cv::imdecode(bytes, cv::IMREAD_UNCHANGED); - } - - streamPtr >> rect_; - } - -private: - int id_; - cv::Mat image_; - QRect rect_; - QString filePath_; - std::vector keypoints_; - cv::Mat descriptors_; - QMultiMap words_; // -}; - -} // namespace find_object - -#endif /* OBJSIGNATURE_H_ */ diff --git a/find-object/src/ObjWidget.cpp b/find-object/src/ObjWidget.cpp deleted file mode 100644 index ccaef110..00000000 --- a/find-object/src/ObjWidget.cpp +++ /dev/null @@ -1,830 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "find_object/Settings.h" -#include "find_object/utilite/ULogger.h" -#include "find_object/ObjWidget.h" -#include "find_object/QtOpenCV.h" - -#include "KeypointItem.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace find_object { - -ObjWidget::ObjWidget(QWidget * parent) : - QWidget(parent), - id_(0), - graphicsView_(0), - graphicsViewInitialized_(false), - alpha_(100), - color_(Qt::red) -{ - setupUi(); -} -ObjWidget::ObjWidget(int id, const std::vector & keypoints, const QMultiMap & words, const QImage & image, QWidget * parent) : - QWidget(parent), - id_(id), - graphicsView_(0), - graphicsViewInitialized_(false), - alpha_(100), - color_(QColor((Qt::GlobalColor)((id % 10 + 7)==Qt::yellow?Qt::darkYellow:(id % 10 + 7)))) -{ - setupUi(); - this->updateImage(image); - this->updateData(keypoints, words); -} -ObjWidget::~ObjWidget() -{ -} - -void ObjWidget::setupUi() -{ - graphicsView_ = new QGraphicsView(this); - graphicsView_->setVisible(false); - graphicsView_->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); - graphicsView_->setScene(new QGraphicsScene(graphicsView_)); - - label_ = new QLabel(); - label_->setAlignment(Qt::AlignCenter); - label_->setTextInteractionFlags(Qt::TextSelectableByMouse); - - this->setLayout(new QVBoxLayout(this)); - this->layout()->addWidget(graphicsView_); - this->layout()->addWidget(label_); - this->layout()->setContentsMargins(0,0,0,0); - - menu_ = new QMenu(tr(""), this); - showImage_ = menu_->addAction(tr("Show image")); - showImage_->setCheckable(true); - showImage_->setChecked(true); - showFeatures_ = menu_->addAction(tr("Show features")); - showFeatures_->setCheckable(true); - showFeatures_->setChecked(true); - mirrorView_ = menu_->addAction(tr("Mirror view")); - mirrorView_->setCheckable(true); - mirrorView_->setChecked(false); - graphicsViewMode_ = menu_->addAction(tr("Graphics view")); - graphicsViewMode_->setCheckable(true); - graphicsViewMode_->setChecked(false); - autoScale_ = menu_->addAction(tr("Scale view")); - autoScale_->setCheckable(true); - autoScale_->setChecked(true); - autoScale_->setEnabled(false); - sizedFeatures_ = menu_->addAction(tr("Sized features")); - sizedFeatures_->setCheckable(true); - sizedFeatures_->setChecked(false); - menu_->addSeparator(); - setColor_ = menu_->addAction(tr("Set color...")); - setAlpha_ = menu_->addAction(tr("Set alpha...")); - menu_->addSeparator(); - saveImage_ = menu_->addAction(tr("Save picture...")); - menu_->addSeparator(); - delete_ = menu_->addAction(tr("Delete")); - delete_->setEnabled(false); - - this->setId(id_); - - graphicsView_->setRubberBandSelectionMode(Qt::ContainsItemShape); - graphicsView_->setDragMode(QGraphicsView::RubberBandDrag); - - connect(graphicsView_->scene(), SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged())); -} - -void ObjWidget::setId(int id) -{ - color_ = QColor((Qt::GlobalColor)((id % 10 + 7)==Qt::yellow?Qt::darkYellow:(id % 10 + 7))); - id_=id; - if(id_) - { - savedFileName_ = QString("object_%1.png").arg(id_); - } -} - -void ObjWidget::setGraphicsViewMode(bool on) -{ - graphicsViewMode_->setChecked(on); - graphicsView_->setVisible(on && graphicsView_->scene()->items().size()); - autoScale_->setEnabled(on); - //update items' color - if(on) - { - if(!graphicsViewInitialized_) - { - this->setupGraphicsView(); - } - else - { - for(int i=0; isetColor(color); - } - } - } - if(autoScale_->isChecked()) - { - graphicsView_->fitInView(graphicsView_->sceneRect(), Qt::KeepAspectRatio); - } - else - { - graphicsView_->resetTransform(); - graphicsView_->setTransform(QTransform().scale(this->isMirrorView()?-1.0:1.0, 1.0)); - } -} - -void ObjWidget::setAutoScale(bool autoScale) -{ - autoScale_->setChecked(autoScale); - if(graphicsViewMode_) - { - if(autoScale) - { - graphicsView_->fitInView(graphicsView_->sceneRect(), Qt::KeepAspectRatio); - } - else - { - graphicsView_->resetTransform(); - graphicsView_->setTransform(QTransform().scale(this->isMirrorView()?-1.0:1.0, 1.0)); - } - } -} - -void ObjWidget::setSizedFeatures(bool on) -{ - sizedFeatures_->setChecked(on); - if(graphicsViewInitialized_) - { - for(unsigned int i=0; i<(unsigned int)keypointItems_.size() && i14.0f) - { - size = keypoints_[i].size; - } - float radius = size*1.2f/9.0f*2.0f; - keypointItems_.at(i)->setRect(keypoints_[i].pt.x-radius, keypoints_[i].pt.y-radius, radius*2, radius*2); - } - } - if(!graphicsViewMode_->isChecked()) - { - this->update(); - } -} - -void ObjWidget::setMirrorView(bool on) -{ - mirrorView_->setChecked(on); - graphicsView_->setTransform(QTransform().scale(this->isMirrorView()?-1.0:1.0, 1.0)); - if(graphicsViewMode_->isChecked() && autoScale_->isChecked()) - { - graphicsView_->fitInView(graphicsView_->sceneRect(), Qt::KeepAspectRatio); - } - else if(!graphicsViewMode_->isChecked()) - { - this->update(); - } -} - -void ObjWidget::setAlpha(int alpha) -{ - if(alpha>=0 && alpha<=255) - { - alpha_ = alpha; - if(graphicsViewInitialized_) - { - for(int i=0; isetColor(color); - } - } - for(int i=0; ipen(); - QColor color = pen.color(); - color.setAlpha(alpha_); - pen.setColor(color); - rectItems_.at(i)->setPen(pen); - } - - if(!graphicsViewMode_->isChecked()) - { - this->update(); - } - } -} - -void ObjWidget::setTextLabel(const QString & text) -{ - label_->setText(text); -} - -void ObjWidget::updateImage(const QImage & image) -{ - pixmap_ = QPixmap(); - rect_ = QRect(); - if(!image.isNull()) - { - pixmap_ = QPixmap::fromImage(image); - rect_ = pixmap_.rect(); - } - label_->setVisible(image.isNull()); -} -void ObjWidget::updateData(const std::vector & keypoints, const QMultiMap & words) -{ - keypoints_ = keypoints; - kptColors_ = QVector((int)keypoints.size(), defaultColor(0)); - keypointItems_.clear(); - rectItems_.clear(); - this->updateWords(words); - graphicsView_->scene()->clear(); - graphicsViewInitialized_ = false; - mouseCurrentPos_ = mousePressedPos_; // this will reset roi selection - - //this->setMinimumSize(image_.size()); - - if(graphicsViewMode_->isChecked()) - { - this->setupGraphicsView(); - } - else - { - this->update(); - } -} - -void ObjWidget::updateWords(const QMultiMap & words) -{ - words_.clear(); - for(QMultiMap::const_iterator iter=words.begin(); iter!=words.end(); ++iter) - { - words_.insert(iter.value(), iter.key()); - } - for(int i=0; isetWordID(words_.value(i,-1)); - keypointItems_[i]->setColor(defaultColor(words_.size()?keypointItems_[i]->wordID():0)); - } - } -} - -void ObjWidget::resetKptsColor() -{ - for(int i=0; iwordID()); - keypointItems_[i]->setColor(this->defaultColor(keypointItems_[i]->wordID())); - } - else - { - kptColors_[i] = defaultColor(words_.value(i,-1)); - } - } - qDeleteAll(rectItems_.begin(), rectItems_.end()); - rectItems_.clear(); -} - -void ObjWidget::resetKptsWordID() -{ - words_.clear(); - for(int i=0; isetWordID(-1); - } -} - -void ObjWidget::setKptColor(int index, const QColor & color) -{ - if(index < kptColors_.size()) - { - kptColors_[index] = color; - } - else - { - UWARN("PROBLEM index =%d > size=%d\n", index, kptColors_.size()); - } - - if(graphicsViewMode_->isChecked()) - { - if(index < keypointItems_.size()) - { - QColor c = color; - c.setAlpha(alpha_); - keypointItems_.at(index)->setColor(c); - } - } -} - -void ObjWidget::setKptWordID(int index, int wordID) -{ - words_.insert(index, wordID); - if(index < keypointItems_.size()) - { - keypointItems_.at(index)->setWordID(wordID); - } -} - -void ObjWidget::addRect(QGraphicsRectItem * rect) -{ - if(graphicsViewInitialized_) - { - graphicsView_->scene()->addItem(rect); - } - rect->setZValue(1); - QPen pen = rect->pen(); - QColor color = pen.color(); - color.setAlpha(alpha_); - pen.setColor(color); - rect->setPen(pen); - rectItems_.append(rect); -} - -QList ObjWidget::selectedItems() const -{ - return graphicsView_->scene()->selectedItems(); -} - -bool ObjWidget::isImageShown() const -{ - return showImage_->isChecked(); -} - -bool ObjWidget::isFeaturesShown() const -{ - return showFeatures_->isChecked(); -} - -bool ObjWidget::isSizedFeatures() const -{ - return sizedFeatures_->isChecked(); -} - -bool ObjWidget::isMirrorView() const -{ - return mirrorView_->isChecked(); -} - -void ObjWidget::setDeletable(bool deletable) -{ - delete_->setEnabled(deletable); -} - -void ObjWidget::setImageShown(bool shown) -{ - showImage_->setChecked(shown); - if(graphicsViewMode_->isChecked()) - { - this->updateItemsShown(); - } - else - { - this->update(); - } -} - -void ObjWidget::setFeaturesShown(bool shown) -{ - showFeatures_->setChecked(shown); - if(graphicsViewMode_->isChecked()) - { - this->updateItemsShown(); - } - else - { - this->update(); - } -} - -void ObjWidget::computeScaleOffsets(float & scale, float & offsetX, float & offsetY) -{ - scale = 1.0f; - offsetX = 0.0f; - offsetY = 0.0f; - - if(!rect_.isNull()) - { - float w = rect_.width(); - float h = rect_.height(); - float widthRatio = float(this->rect().width()) / w; - float heightRatio = float(this->rect().height()) / h; - - //printf("w=%f, h=%f, wR=%f, hR=%f, sW=%d, sH=%d\n", w, h, widthRatio, heightRatio, this->rect().width(), this->rect().height()); - if(widthRatio < heightRatio) - { - scale = widthRatio; - } - else - { - scale = heightRatio; - } - - //printf("ratio=%f\n",ratio); - - w *= scale; - h *= scale; - - if(w < this->rect().width()) - { - offsetX = (this->rect().width() - w)/2.0f; - } - if(h < this->rect().height()) - { - offsetY = (this->rect().height() - h)/2.0f; - } - //printf("offsetX=%f, offsetY=%f\n",offsetX, offsetY); - } -} - -void ObjWidget::paintEvent(QPaintEvent *event) -{ - if(graphicsViewMode_->isChecked()) - { - QWidget::paintEvent(event); - } - else - { - if(!rect_.isNull()) - { - //Scale - float ratio, offsetX, offsetY; - this->computeScaleOffsets(ratio, offsetX, offsetY); - QPainter painter(this); - - if(mirrorView_->isChecked()) - { - painter.translate(offsetX+rect_.width()*ratio, offsetY); - painter.scale(-ratio, ratio); - } - else - { - painter.translate(offsetX, offsetY); - painter.scale(ratio, ratio); - } - - if(!pixmap_.isNull() && showImage_->isChecked()) - { - painter.drawPixmap(QPoint(0,0), pixmap_); - } - - if(showFeatures_->isChecked()) - { - drawKeypoints(&painter); - } - - for(int i=0; itransform(), true); - painter.setPen(rectItems_.at(i)->pen()); - painter.drawRect(rectItems_.at(i)->rect()); - painter.restore(); - } - - if(mouseCurrentPos_ != mousePressedPos_) - { - painter.save(); - int left, top, right, bottom; - left = mousePressedPos_.x() < mouseCurrentPos_.x() ? mousePressedPos_.x():mouseCurrentPos_.x(); - top = mousePressedPos_.y() < mouseCurrentPos_.y() ? mousePressedPos_.y():mouseCurrentPos_.y(); - right = mousePressedPos_.x() > mouseCurrentPos_.x() ? mousePressedPos_.x():mouseCurrentPos_.x(); - bottom = mousePressedPos_.y() > mouseCurrentPos_.y() ? mousePressedPos_.y():mouseCurrentPos_.y(); - if(mirrorView_->isChecked()) - { - int l = left; - left = qAbs(right - rect_.width()); - right = qAbs(l - rect_.width()); - } - painter.setPen(Qt::NoPen); - painter.setBrush(QBrush(QColor(0,0,0,100))); - painter.drawRect(0, 0, rect_.width(), top); - painter.drawRect(0, top, left, bottom-top); - painter.drawRect(right, top, rect_.width()-right, bottom-top); - painter.drawRect(0, bottom, rect_.width(), rect_.height()-bottom); - painter.restore(); - } - } - } -} - -void ObjWidget::resizeEvent(QResizeEvent* event) -{ - QWidget::resizeEvent(event); - if(graphicsViewMode_->isChecked() && autoScale_->isChecked()) - { - graphicsView_->fitInView(graphicsView_->sceneRect(), Qt::KeepAspectRatio); - } -} - -void ObjWidget::mousePressEvent(QMouseEvent * event) -{ - float scale, offsetX, offsetY; - this->computeScaleOffsets(scale, offsetX, offsetY); - mousePressedPos_.setX((event->pos().x()-offsetX)/scale); - mousePressedPos_.setY((event->pos().y()-offsetY)/scale); - mouseCurrentPos_ = mousePressedPos_; - this->update(); - QWidget::mousePressEvent(event); -} - -void ObjWidget::mouseMoveEvent(QMouseEvent * event) -{ - float scale, offsetX, offsetY; - this->computeScaleOffsets(scale, offsetX, offsetY); - mouseCurrentPos_.setX((event->pos().x()-offsetX)/scale); - mouseCurrentPos_.setY((event->pos().y()-offsetY)/scale); - this->update(); - QWidget::mouseMoveEvent(event); -} - -void ObjWidget::mouseReleaseEvent(QMouseEvent * event) -{ - if(!rect_.isNull()) - { - int left,top,bottom,right; - - left = mousePressedPos_.x() < mouseCurrentPos_.x() ? mousePressedPos_.x():mouseCurrentPos_.x(); - top = mousePressedPos_.y() < mouseCurrentPos_.y() ? mousePressedPos_.y():mouseCurrentPos_.y(); - right = mousePressedPos_.x() > mouseCurrentPos_.x() ? mousePressedPos_.x():mouseCurrentPos_.x(); - bottom = mousePressedPos_.y() > mouseCurrentPos_.y() ? mousePressedPos_.y():mouseCurrentPos_.y(); - - if(mirrorView_->isChecked()) - { - int l = left; - left = qAbs(right - rect_.width()); - right = qAbs(l - rect_.width()); - } - - Q_EMIT roiChanged(cv::Rect(left, top, right-left, bottom-top)); - } - QWidget::mouseReleaseEvent(event); -} - -void ObjWidget::contextMenuEvent(QContextMenuEvent * event) -{ - QAction * action = menu_->exec(event->globalPos()); - if(action == saveImage_) - { - QString text; - if(savedFileName_.isEmpty()) - { - savedFileName_=Settings::workingDirectory()+"/figure.png"; - } - text = QFileDialog::getSaveFileName(this, tr("Save figure to ..."), savedFileName_, "*.png *.xpm *.jpg *.pdf"); - if(!text.isEmpty()) - { - if(!text.endsWith(".png") && !text.endsWith(".xpm") && !text.endsWith(".jpg") && !text.endsWith(".pdf")) - { - text.append(".png");//default - } - savedFileName_ = text; - getSceneAsPixmap().save(text); - } - } - else if(action == showFeatures_ || action == showImage_) - { - if(graphicsViewMode_->isChecked()) - { - this->updateItemsShown(); - } - else - { - this->update(); - } - } - else if(action == mirrorView_) - { - this->setMirrorView(mirrorView_->isChecked()); - } - else if(action == delete_) - { - Q_EMIT removalTriggered(this); - } - else if(action == graphicsViewMode_) - { - this->setGraphicsViewMode(graphicsViewMode_->isChecked()); - } - else if(action == autoScale_) - { - this->setAutoScale(autoScale_->isChecked()); - } - else if(action == sizedFeatures_) - { - this->setSizedFeatures(sizedFeatures_->isChecked()); - } - else if(action == setColor_) - { - QColor color = QColorDialog::getColor(color_, this); - if(color.isValid()) - { - for(int i=0; iisChecked()) - { - keypointItems_[i]->setColor(color); - } - } - } - for(int i=0; ipen().color() == color_) - { - QPen p = rectItems_[i]->pen(); - p.setColor(color); - rectItems_[i]->setPen(p); - } - } - color_ = color; - - } - } - else if(action == setAlpha_) - { - bool ok; - int newAlpha = QInputDialog::getInt(this, tr("Set alpha"), tr("Alpha:"), alpha_, 0, 255, 5, &ok); - if(ok) - { - this->setAlpha(newAlpha); - } - } -} - -QPixmap ObjWidget::getSceneAsPixmap() -{ - if(graphicsViewMode_->isChecked()) - { - QPixmap img(graphicsView_->sceneRect().width(), graphicsView_->sceneRect().height()); - QPainter p(&img); - graphicsView_->scene()->render(&p, graphicsView_->sceneRect(), graphicsView_->sceneRect()); - return img; - } - else - { - return QPixmap::grabWidget(this); - } -} - -void ObjWidget::updateItemsShown() -{ - QList items = graphicsView_->scene()->items(); - for(int i=0; i(items.at(i))) - { - items.at(i)->setVisible(showFeatures_->isChecked()); - } - else if(qgraphicsitem_cast(items.at(i))) - { - items.at(i)->setVisible(showImage_->isChecked()); - } - } -} - -void ObjWidget::drawKeypoints(QPainter * painter) -{ - QList items; - KeypointItem * item = 0; - - int i = 0; - for(std::vector::const_iterator iter = keypoints_.begin(); iter != keypoints_.end(); ++iter, ++i ) - { - const cv::KeyPoint & r = *iter; - float size = 14; - if(r.size>14.0f && sizedFeatures_->isChecked()) - { - size = r.size; - } - float radius = size*1.2f/9.0f*2.0f; - QColor color(kptColors_.at(i).red(), kptColors_.at(i).green(), kptColors_.at(i).blue(), alpha_); - if(graphicsViewMode_->isChecked()) - { - // YELLOW = NEW and multiple times - item = new KeypointItem(i, r.pt.x-radius, r.pt.y-radius, radius*2, r, words_.value(i, -1), color); - item->setVisible(this->isFeaturesShown()); - item->setZValue(2); - graphicsView_->scene()->addItem(item); - item->setColor(defaultColor(item->wordID())); - kptColors_[i] = defaultColor(item->wordID()); - keypointItems_.append(item); - } - - if(painter) - { - painter->save(); - painter->setPen(color); - painter->setBrush(color); - painter->drawEllipse(r.pt.x-radius, r.pt.y-radius, radius*2, radius*2); - painter->restore(); - } - } -} - -QColor ObjWidget::defaultColor(int id) const -{ - QColor color(id >= 0 ? Qt::yellow : Qt::white); - color.setAlpha(alpha_); - return color; -} - -std::vector ObjWidget::selectedKeypoints() const -{ - std::vector selected; - if(graphicsViewMode_->isChecked()) - { - QList items = graphicsView_->scene()->selectedItems(); - for(int i=0; i(items.at(i))) - { - selected.push_back(keypoints_.at(((KeypointItem*)items.at(i))->id())); - } - } - } - return selected; -} - -void ObjWidget::setupGraphicsView() -{ - if(!rect_.isNull()) - { - graphicsView_->setVisible(true); - graphicsView_->scene()->setSceneRect(rect_); - QList items; - - QRectF sceneRect = graphicsView_->sceneRect(); - - QGraphicsPixmapItem * pixmapItem = graphicsView_->scene()->addPixmap(pixmap_); - pixmapItem->setVisible(this->isImageShown()); - this->drawKeypoints(); - - for(int i=0; iscene()->addItem(rectItems_.at(i)); - } - - if(autoScale_->isChecked()) - { - graphicsView_->fitInView(sceneRect, Qt::KeepAspectRatio); - } - graphicsViewInitialized_ = true; - } - else - { - graphicsView_->setVisible(false); - } -} - -} // namespace find_object - diff --git a/find-object/src/ParametersToolBox.cpp b/find-object/src/ParametersToolBox.cpp deleted file mode 100644 index e3949210..00000000 --- a/find-object/src/ParametersToolBox.cpp +++ /dev/null @@ -1,823 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "find_object/Settings.h" - -#include "ParametersToolBox.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "find_object/utilite/ULogger.h" -#include - -namespace find_object { - -ParametersToolBox::ParametersToolBox(QWidget *parent) : - QToolBox(parent) -{ -} - -ParametersToolBox::~ParametersToolBox() -{ -} - -QWidget * ParametersToolBox::getParameterWidget(const QString & key) -{ - return this->findChild(key); -} - -QStringList ParametersToolBox::resetPage(int index) -{ - QStringList paramChanged; - const QObjectList & children = this->widget(index)->children(); - for(int j=0; jobjectName(); - // ignore only the nextObjID setting, to avoid problem with saved objects - if(key.compare(Settings::kGeneral_nextObjID()) != 0) - { - QVariant value = Settings::getDefaultParameters().value(key, QVariant()); - if(value.isValid()) - { - Settings::setParameter(key, value); - - if(qobject_cast(children.at(j))) - { - if(((QComboBox*)children.at(j))->currentIndex() != value.toString().split(':').first().toInt()) - { - ((QComboBox*)children.at(j))->setCurrentIndex(value.toString().split(':').first().toInt()); - paramChanged.append(key); - } - } - else if(qobject_cast(children.at(j))) - { - if(((QSpinBox*)children.at(j))->value() != value.toInt()) - { - ((QSpinBox*)children.at(j))->setValue(value.toInt()); - paramChanged.append(key); - } - } - else if(qobject_cast(children.at(j))) - { - if(((QDoubleSpinBox*)children.at(j))->value() != value.toDouble()) - { - ((QDoubleSpinBox*)children.at(j))->setValue(value.toDouble()); - paramChanged.append(key); - } - } - else if(qobject_cast(children.at(j))) - { - if(((QCheckBox*)children.at(j))->isChecked() != value.toBool()) - { - ((QCheckBox*)children.at(j))->setChecked(value.toBool()); - paramChanged.append(key); - } - } - else if(qobject_cast(children.at(j))) - { - if(((QLineEdit*)children.at(j))->text().compare(value.toString()) != 0) - { - ((QLineEdit*)children.at(j))->setText(value.toString()); - paramChanged.append(key); - } - } - } - } - } - return paramChanged; -} - -void ParametersToolBox::resetCurrentPage() -{ - this->blockSignals(true); - QStringList paramChanged = this->resetPage(this->currentIndex()); - this->blockSignals(false); - Q_EMIT parametersChanged(paramChanged); -} - -void ParametersToolBox::resetAllPages() -{ - QStringList paramChanged; - this->blockSignals(true); - for(int i=0; i< this->count(); ++i) - { - paramChanged.append(this->resetPage(i)); - } - this->blockSignals(false); - Q_EMIT parametersChanged(paramChanged); -} - -void ParametersToolBox::updateParametersVisibility() -{ - //show/hide not used parameters - QComboBox * descriptorBox = this->findChild(Settings::kFeature2D_2Descriptor()); - QComboBox * detectorBox = this->findChild(Settings::kFeature2D_1Detector()); - if(descriptorBox && detectorBox) - { - QString group = Settings::kFeature2D_2Descriptor().split('/').first(); - QWidget * panel = 0; - for(int i=0; icount(); ++i) - { - if(this->widget(i)->objectName().compare(group) == 0) - { - panel = this->widget(i); - break; - } - } - if(panel) - { - const QObjectList & objects = panel->children(); - QString descriptorName = descriptorBox->currentText(); - QString detectorName = detectorBox->currentText(); - - for(int i=0; iobjectName().isEmpty()) - { - if(objects[i]->objectName().contains(descriptorName) || objects[i]->objectName().contains(detectorName)) - { - ((QWidget*)objects[i])->setVisible(true); - } - else if(objects[i]->objectName().contains("Fast") && detectorName == QString("ORB")) - { - ((QWidget*)objects[i])->setVisible(true); // ORB uses some FAST parameters - } - else if(!objects[i]->objectName().split('/').at(1).at(0).isDigit()) - { - ((QWidget*)objects[i])->setVisible(false); - } - } - } - } - } - - QComboBox * nnBox = this->findChild(Settings::kNearestNeighbor_1Strategy()); - if(nnBox) - { - QString group = Settings::kNearestNeighbor_1Strategy().split('/').first(); - QWidget * panel = 0; - for(int i=0; icount(); ++i) - { - if(this->widget(i)->objectName().compare(group) == 0) - { - panel = this->widget(i); - break; - } - } - if(panel) - { - const QObjectList & objects = panel->children(); - QString nnName = nnBox->currentText(); - - for(int i=0; iobjectName().isEmpty()) - { - if(objects[i]->objectName().contains(nnName)) - { - ((QWidget*)objects[i])->setVisible(true); - } - else if(!objects[i]->objectName().split('/').at(1).at(0).isDigit()) - { - ((QWidget*)objects[i])->setVisible(false); - if(nnBox->currentIndex() < 6 && objects[i]->objectName().split('/').at(1).contains("search")) - { - //show flann search parameters - ((QWidget*)objects[i])->setVisible(true); - } - } - else if(objects[i]->objectName().split('/').at(1).contains("Distance_type")) - { - // don't show distance when bruteforce is selected - ((QWidget*)objects[i])->setVisible(nnBox->currentIndex() != 6); - } - } - } - } - } -} - -void ParametersToolBox::setupUi() -{ - this->removeItem(0); // remove dummy page used in .ui - QWidget * currentItem = 0; - const ParametersMap & parameters = Settings::getParameters(); - for(ParametersMap::const_iterator iter=parameters.constBegin(); - iter!=parameters.constEnd(); - ++iter) - { - QStringList splitted = iter.key().split('/'); - QString group = splitted.first(); - QString name = splitted.last(); - if(currentItem == 0 || currentItem->objectName().compare(group) != 0) - { - currentItem = new QWidget(this); - this->addItem(currentItem, group); - currentItem->setObjectName(group); - QVBoxLayout * layout = new QVBoxLayout(currentItem); - currentItem->setLayout(layout); - layout->setContentsMargins(0,0,0,0); - layout->setSpacing(0); - layout->addSpacerItem(new QSpacerItem(0,0, QSizePolicy::Minimum, QSizePolicy::Expanding)); - - addParameter(layout, iter.key(), iter.value()); - } - else - { - addParameter((QVBoxLayout*)currentItem->layout(), iter.key(), iter.value()); - } - } - - updateParametersVisibility(); -} - -void ParametersToolBox::updateParameter(const QString & key) -{ - QWidget * widget = this->findChild(key); - QString type = Settings::getParametersType().value(key); - if(type.compare("QString") == 0) - { - QString value = Settings::getParameter(key).toString(); - if(value.contains(';')) - { - // It's a list, just change the index - QStringList splitted = value.split(':'); - ((QComboBox*)widget)->setCurrentIndex(splitted.first().toInt()); - } - else - { - ((QLineEdit*)widget)->setText(value); - } - } - else if(type.compare("int") == 0) - { - ((QSpinBox*)widget)->setValue(Settings::getParameter(key).toInt()); - } - else if(type.compare("uint") == 0) - { - ((QSpinBox*)widget)->setValue(Settings::getParameter(key).toInt()); - } - else if(type.compare("double") == 0) - { - ((QDoubleSpinBox*)widget)->setValue(Settings::getParameter(key).toDouble()); - } - else if(type.compare("float") == 0) - { - ((QDoubleSpinBox*)widget)->setValue(Settings::getParameter(key).toDouble()); - } - else if(type.compare("bool") == 0) - { - ((QCheckBox*)widget)->setChecked(Settings::getParameter(key).toBool()); - } -} - -void ParametersToolBox::addParameter(QVBoxLayout * layout, - const QString & key, - const QVariant & value) -{ - QString type = Settings::getParametersType().value(key); - if(type.compare("QString") == 0) - { - addParameter(layout, key, value.toString()); - } - else if(type.compare("int") == 0) - { - addParameter(layout, key, value.toInt()); - } - else if(type.compare("uint") == 0) - { - addParameter(layout, key, value.toInt()); - } - else if(type.compare("double") == 0) - { - addParameter(layout, key, value.toDouble()); - } - else if(type.compare("float") == 0) - { - addParameter(layout, key, value.toDouble()); - } - else if(type.compare("bool") == 0) - { - addParameter(layout, key, value.toBool()); - } -} - -void ParametersToolBox::addParameter(QVBoxLayout * layout, - const QString & key, - const QString & value) -{ - if(value.contains(';')) - { - QComboBox * widget = new QComboBox(this); - widget->setObjectName(key); - QStringList splitted = value.split(':'); - widget->addItems(splitted.last().split(';')); - - if(key.compare(Settings::kFeature2D_1Detector()) == 0) - { -#if FINDOBJECT_NONFREE == 0 -#if CV_MAJOR_VERSION < 4 || (CV_MAJOR_VERSION == 4 && (CV_MINOR_VERSION < 3 || (CV_MINOR_VERSION==3 && !defined(OPENCV_DEV)))) - widget->setItemData(5, 0, Qt::UserRole - 1); // disable SIFT -#endif - widget->setItemData(7, 0, Qt::UserRole - 1); // disable SURF -#endif -#if CV_MAJOR_VERSION < 3 - widget->setItemData(9, 0, Qt::UserRole - 1); // disable AGAST - widget->setItemData(10, 0, Qt::UserRole - 1); // disable KAZE - widget->setItemData(11, 0, Qt::UserRole - 1); // disable AKAZE -#else - widget->setItemData(0, 0, Qt::UserRole - 1); // disable Dense -#ifndef HAVE_OPENCV_XFEATURES2D - widget->setItemData(6, 0, Qt::UserRole - 1); // disable Star -#endif -#endif -#if FINDOBJECT_TORCH == 0 - widget->setItemData(12, 0, Qt::UserRole - 1); // disable SuperPointTorch -#endif - } - if(key.compare(Settings::kFeature2D_2Descriptor()) == 0) - { -#if FINDOBJECT_NONFREE == 0 -#if CV_MAJOR_VERSION < 4 || (CV_MAJOR_VERSION == 4 && (CV_MINOR_VERSION < 3 || (CV_MINOR_VERSION==3 && !defined(OPENCV_DEV)))) - widget->setItemData(2, 0, Qt::UserRole - 1); // disable SIFT -#endif - widget->setItemData(3, 0, Qt::UserRole - 1); // disable SURF -#endif -#if CV_MAJOR_VERSION < 3 - widget->setItemData(6, 0, Qt::UserRole - 1); // disable KAZE - widget->setItemData(7, 0, Qt::UserRole - 1); // disable AKAZE - widget->setItemData(8, 0, Qt::UserRole - 1); // disable LUCID - widget->setItemData(9, 0, Qt::UserRole - 1); // disable LATCH - widget->setItemData(10, 0, Qt::UserRole - 1); // disable DAISY -#else - -#ifndef HAVE_OPENCV_XFEATURES2D - widget->setItemData(0, 0, Qt::UserRole - 1); // disable Brief - widget->setItemData(5, 0, Qt::UserRole - 1); // disable Freak - widget->setItemData(8, 0, Qt::UserRole - 1); // disable LUCID - widget->setItemData(9, 0, Qt::UserRole - 1); // disable LATCH - widget->setItemData(10, 0, Qt::UserRole - 1); // disable DAISY -#endif -#endif -#if FINDOBJECT_TORCH == 0 - widget->setItemData(11, 0, Qt::UserRole - 1); // disable SuperPointTorch -#endif - } - if(key.compare(Settings::kNearestNeighbor_1Strategy()) == 0) - { -#if FINDOBJECT_NONFREE == 0 && CV_MAJOR_VERSION < 3 - // disable FLANN approaches (cannot be used with binary descriptors) - widget->setItemData(0, 0, Qt::UserRole - 1); - widget->setItemData(1, 0, Qt::UserRole - 1); - widget->setItemData(2, 0, Qt::UserRole - 1); - widget->setItemData(3, 0, Qt::UserRole - 1); - widget->setItemData(4, 0, Qt::UserRole - 1); -#endif - } - if(key.compare(Settings::kHomography_method()) == 0) - { -#if CV_MAJOR_VERSION < 3 - // disable RHO approach - widget->setItemData(2, 0, Qt::UserRole - 1); -#endif - } - - widget->setCurrentIndex(splitted.first().toInt()); - connect(widget, SIGNAL(currentIndexChanged(int)), this, SLOT(changeParameter(int))); - addParameter(layout, key, widget); - } - else - { - QLineEdit * widget = new QLineEdit(value, this); - widget->setObjectName(key); - connect(widget, SIGNAL(editingFinished()), this, SLOT(changeParameter())); - addParameter(layout, key, widget); - } -} - -void ParametersToolBox::addParameter(QVBoxLayout * layout, - const QString & key, - const double & value) -{ - QDoubleSpinBox * widget = new QDoubleSpinBox(this); - int decimals = 0; - int decimalValue = 0; - - QString str = QString::number(Settings::getDefaultParameters().value(key).toDouble()); - str.remove( QRegExp("0+$") ); - - if(!str.isEmpty()) - { - str.replace(',', '.'); - QStringList items = str.split('.'); - if(items.size() == 2) - { - decimals = items.back().length(); - decimalValue = items.back().toInt(); - } - } - - double def = Settings::getDefaultParameters().value(key).toDouble(); - if(def<0.001 || (decimals >= 4 && decimalValue>0)) - { - widget->setDecimals(5); - widget->setSingleStep(0.0001); - } - else if(def<0.01 || (decimals >= 3 && decimalValue>0)) - { - widget->setDecimals(4); - widget->setSingleStep(0.001); - } - else if(def<0.1 || (decimals >= 2 && decimalValue>0)) - { - widget->setDecimals(3); - widget->setSingleStep(0.01); - } - else if(def<1.0 || (decimals >= 1 && decimalValue>0)) - { - widget->setDecimals(2); - widget->setSingleStep(0.1); - } - else - { - widget->setDecimals(1); - } - - if(def>0.0) - { - widget->setMaximum(def*1000000.0); - } - else if(def==0.0) - { - widget->setMaximum(1000000.0); - } - else if(def<0.0) - { - widget->setMinimum(def*1000000.0); - widget->setMaximum(0.0); - } - widget->setValue(value); - widget->setObjectName(key); - connect(widget, SIGNAL(editingFinished()), this, SLOT(changeParameter())); - addParameter(layout, key, widget); -} - -void ParametersToolBox::addParameter(QVBoxLayout * layout, - const QString & key, - const int & value) -{ - QSpinBox * widget = new QSpinBox(this); - int def = Settings::getDefaultParameters().value(key).toInt(); - - if(def>0) - { - widget->setMaximum(def*1000000); - } - else if(def == 0) - { - widget->setMaximum(1000000); - } - else if(def<0) - { - widget->setMinimum(def*1000000); - widget->setMaximum(0); - } - widget->setValue(value); - widget->setObjectName(key); - connect(widget, SIGNAL(editingFinished()), this, SLOT(changeParameter())); - addParameter(layout, key, widget); -} - -void ParametersToolBox::addParameter(QVBoxLayout * layout, - const QString & key, - const bool & value) -{ - QCheckBox * widget = new QCheckBox(this); - widget->setChecked(value); - widget->setObjectName(key); - connect(widget, SIGNAL(toggled(bool)), this, SLOT(changeParameter(bool))); - addParameter(layout, key, widget); -} - -void ParametersToolBox::addParameter(QVBoxLayout * layout, const QString & key, QWidget * widget) -{ - QHBoxLayout * hLayout = new QHBoxLayout(); - layout->insertLayout(layout->count()-1, hLayout); - QString tmp = key.split('/').last(); - if(tmp.at(0).isDigit()) - { - tmp.remove(0,1); - } - QLabel * label = new QLabel(tmp, this); - label->setObjectName(key+"/label"); - label->setToolTip(QString("%1").arg(Settings::getDescriptions().value(key, ""))); - label->setTextInteractionFlags(Qt::TextSelectableByMouse); - hLayout->addWidget(label); - hLayout->addWidget(widget); -} - -void ParametersToolBox::changeParameter(const QString & value) -{ - if(sender()) - { - Settings::setParameter(sender()->objectName(), value); - QStringList paramChanged; - paramChanged.append(sender()->objectName()); - Q_EMIT parametersChanged(paramChanged); - } -} -void ParametersToolBox::changeParameter() -{ - if(sender()) - { - QDoubleSpinBox * doubleSpinBox = qobject_cast(sender()); - QSpinBox * spinBox = qobject_cast(sender()); - QLineEdit * lineEdit = qobject_cast(sender()); - if(doubleSpinBox) - { - Settings::setParameter(sender()->objectName(), doubleSpinBox->value()); - } - else if(spinBox) - { - if(spinBox->objectName().compare(Settings::kHomography_minimumInliers()) == 0 && - spinBox->value() < 4) - { - Settings::setHomography_minimumInliers(4); - spinBox->blockSignals(true); - this->updateParameter(Settings::kHomography_minimumInliers()); - spinBox->blockSignals(false); - } - else - { - Settings::setParameter(sender()->objectName(), spinBox->value()); - } - } - else if(lineEdit) - { - Settings::setParameter(sender()->objectName(), lineEdit->text()); - } - QStringList paramChanged; - paramChanged.append(sender()->objectName()); - Q_EMIT parametersChanged(paramChanged); - } -} - -void ParametersToolBox::changeParameter(bool value) -{ - if(sender()) - { - // Workaround as stateChanged(int) is not always emitted, using toggled(bool) instead - changeParameter(sender(), value?Qt::Checked:Qt::Unchecked); - } -} - -void ParametersToolBox::changeParameter(int value) -{ - if(sender()) - { - changeParameter(sender(), value); - } -} - -void ParametersToolBox::changeParameter(QObject * sender, int value) -{ - if(sender) - { - QStringList paramChanged; - QComboBox * comboBox = qobject_cast(sender); - QCheckBox * checkBox = qobject_cast(sender); - - bool descriptorChanged = false; - if(comboBox && comboBox->objectName().compare(Settings::kFeature2D_1Detector()) == 0) - { - QComboBox * descriptorBox = (QComboBox*)this->getParameterWidget(Settings::kFeature2D_2Descriptor()); - if(comboBox->objectName().compare(Settings::kFeature2D_1Detector()) == 0 && - comboBox->currentText() != descriptorBox->currentText() && - Settings::getFeature2D_2Descriptor().contains(comboBox->currentText())) - { - QMessageBox::StandardButton b = QMessageBox::question(this, - tr("Use corresponding descriptor type?"), - tr("Current selected detector type (\"%1\") has its own corresponding descriptor type.\n" - "Do you want to use its corresponding descriptor?") - .arg(comboBox->currentText()), - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); - if(b == QMessageBox::Yes) - { - int index = descriptorBox->findText(comboBox->currentText()); - if(index >= 0) - { - QStringList tmp = Settings::getFeature2D_2Descriptor().split(':'); - UASSERT(tmp.size() == 2); - QString newTmp = QString::number(index)+":"+tmp.back(); - Settings::setFeature2D_2Descriptor(newTmp); - descriptorBox->blockSignals(true); - this->updateParameter(Settings::kFeature2D_2Descriptor()); - descriptorBox->blockSignals(false); - paramChanged.append(Settings::kFeature2D_2Descriptor()); - descriptorChanged = true; - } - else - { - UERROR("Combo box detector type not found \"%s\"?!", comboBox->currentText().toStdString().c_str()); - } - } - } - } - - bool nnStrategyChanged = false; - //verify binary issue with nearest neighbor strategy - if((comboBox && (comboBox->objectName().compare(Settings::kFeature2D_2Descriptor()) == 0 || - comboBox->objectName().compare(Settings::kNearestNeighbor_1Strategy()) == 0)) || - descriptorChanged || - (checkBox && checkBox->objectName().compare(Settings::kNearestNeighbor_7ConvertBinToFloat()) == 0)) - { - QComboBox * descriptorBox = (QComboBox*)this->getParameterWidget(Settings::kFeature2D_2Descriptor()); - QComboBox * nnBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_1Strategy()); - QComboBox * distBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_2Distance_type()); - QCheckBox * binToFloatCheckbox = (QCheckBox*)this->getParameterWidget(Settings::kNearestNeighbor_7ConvertBinToFloat()); - bool isBinaryDescriptor = descriptorBox->currentText().compare("ORB") == 0 || - descriptorBox->currentText().compare("Brief") == 0 || - descriptorBox->currentText().compare("BRISK") == 0 || - descriptorBox->currentText().compare("FREAK") == 0 || - descriptorBox->currentText().compare("AKAZE") == 0 || - descriptorBox->currentText().compare("LATCH") == 0 || - descriptorBox->currentText().compare("LUCID") == 0; - bool binToFloat = binToFloatCheckbox->isChecked(); - if(isBinaryDescriptor && !binToFloat && nnBox->currentText().compare("Lsh") != 0 && nnBox->currentText().compare("BruteForce") != 0) - { - QMessageBox::warning(this, - tr("Warning"), - tr("Current selected descriptor type (\"%1\") is binary while nearest neighbor strategy is not (\"%2\").\n" - "Falling back to \"BruteForce\" nearest neighbor strategy with Hamming distance (by default).") - .arg(descriptorBox->currentText()) - .arg(nnBox->currentText())); - QString tmp = Settings::getNearestNeighbor_1Strategy(); - *tmp.begin() = '6'; // set BruteForce - Settings::setNearestNeighbor_1Strategy(tmp); - tmp = Settings::getNearestNeighbor_2Distance_type(); - *tmp.begin() = '8'; // set HAMMING - Settings::setNearestNeighbor_2Distance_type(tmp); - nnBox->blockSignals(true); - distBox->blockSignals(true); - this->updateParameter(Settings::kNearestNeighbor_1Strategy()); - this->updateParameter(Settings::kNearestNeighbor_2Distance_type()); - nnBox->blockSignals(false); - distBox->blockSignals(false); - if(sender == nnBox) - { - this->updateParametersVisibility(); - return; - } - nnStrategyChanged = true; - paramChanged.append(Settings::kNearestNeighbor_1Strategy()); - paramChanged.append(Settings::kNearestNeighbor_2Distance_type()); - } - else if((!isBinaryDescriptor || binToFloat) && nnBox->currentText().compare("Lsh") == 0) - { - if(binToFloat) - { - QMessageBox::warning(this, - tr("Warning"), - tr("Current selected descriptor type (\"%1\") is binary, but binary to float descriptors conversion is activated while nearest neighbor strategy is (\"%2\").\n" - "Disabling binary to float descriptors conversion and use Hamming distance (by default).") - .arg(descriptorBox->currentText()) - .arg(nnBox->currentText())); - - binToFloatCheckbox->blockSignals(true); - if(checkBox && checkBox->objectName().compare(Settings::kNearestNeighbor_7ConvertBinToFloat()) == 0) - { - Settings::setParameter(checkBox->objectName(), false); - value = 0; - } - else - { - paramChanged.append(Settings::kNearestNeighbor_7ConvertBinToFloat()); - } - this->updateParameter(Settings::kNearestNeighbor_7ConvertBinToFloat()); - binToFloatCheckbox->blockSignals(false); - - QString tmp = Settings::getNearestNeighbor_2Distance_type(); - *tmp.begin() = '8'; // set HAMMING - Settings::setNearestNeighbor_2Distance_type(tmp); - distBox->blockSignals(true); - this->updateParameter(Settings::kNearestNeighbor_2Distance_type()); - distBox->blockSignals(false); - paramChanged.append(Settings::kNearestNeighbor_2Distance_type()); - } - else - { - QMessageBox::warning(this, - tr("Warning"), - tr("Current selected descriptor type (\"%1\") is not binary while nearest neighbor strategy is (\"%2\").\n" - "Falling back to \"KDTree\" nearest neighbor strategy with Euclidean_L2 distance (by default).") - .arg(descriptorBox->currentText()) - .arg(nnBox->currentText())); - - QString tmp = Settings::getNearestNeighbor_1Strategy(); - *tmp.begin() = '1'; // set KDTree - Settings::setNearestNeighbor_1Strategy(tmp); - tmp = Settings::getNearestNeighbor_2Distance_type(); - *tmp.begin() = '0'; // set EUCLIDEAN_L2 - Settings::setNearestNeighbor_2Distance_type(tmp); - nnBox->blockSignals(true); - distBox->blockSignals(true); - this->updateParameter(Settings::kNearestNeighbor_1Strategy()); - this->updateParameter(Settings::kNearestNeighbor_2Distance_type()); - nnBox->blockSignals(false); - distBox->blockSignals(false); - if(sender == nnBox) - { - this->updateParametersVisibility(); - return; - } - nnStrategyChanged = true; - paramChanged.append(Settings::kNearestNeighbor_1Strategy()); - paramChanged.append(Settings::kNearestNeighbor_2Distance_type()); - } - } - } - - // Distance issue when using nearest neighbor strategy using CV_32F type, though Lsh support all type (doesn't crash at least) - if(nnStrategyChanged || - (comboBox && (comboBox->objectName().compare(Settings::kNearestNeighbor_1Strategy()) == 0 || - comboBox->objectName().compare(Settings::kNearestNeighbor_2Distance_type()) == 0))) - { - QComboBox * nnBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_1Strategy()); - QComboBox * distBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_2Distance_type()); - if(nnBox->currentText().compare("BruteForce") != 0 && nnBox->currentText().compare("Lsh") != 0 && distBox->currentIndex() > 1) - { - QMessageBox::warning(this, - tr("Warning"), - tr("Current selected nearest neighbor strategy type (\"%1\") cannot handle distance strategy (\"%2\").\n" - "Falling back to \"EUCLIDEAN_L2\" distance strategy (by default).") - .arg(nnBox->currentText()) - .arg(distBox->currentText())); - QString tmp = Settings::getNearestNeighbor_2Distance_type(); - *tmp.begin() = '0'; // set index - Settings::setNearestNeighbor_2Distance_type(tmp); - distBox->blockSignals(true); - this->updateParameter(Settings::kNearestNeighbor_2Distance_type()); - distBox->blockSignals(false); - if(sender == distBox) - { - this->updateParametersVisibility(); - return; - } - paramChanged.append(Settings::kNearestNeighbor_2Distance_type()); - } - } - - if(comboBox) - { - QStringList items; - for(int i=0; icount(); ++i) - { - items.append(comboBox->itemText(i)); - } - QString merged = QString::number(value) + QString(":") + items.join(";"); - Settings::setParameter(sender->objectName(), merged); - } - - if(checkBox) - { - Settings::setParameter(sender->objectName(), value==Qt::Checked?true:false); - } - - this->updateParametersVisibility(); - - paramChanged.append(sender->objectName()); - Q_EMIT parametersChanged(paramChanged); - } -} - -} // namespace find_object diff --git a/find-object/src/ParametersToolBox.h b/find-object/src/ParametersToolBox.h deleted file mode 100644 index 4cd85283..00000000 --- a/find-object/src/ParametersToolBox.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef PARAMETERSTOOLBOX_H_ -#define PARAMETERSTOOLBOX_H_ - -#include - -class QVBoxLayout; -class QAbstractButton; - -namespace find_object { - -class ParametersToolBox: public QToolBox -{ - Q_OBJECT - -public: - ParametersToolBox(QWidget *parent = 0); - virtual ~ParametersToolBox(); - - void setupUi(); - QWidget * getParameterWidget(const QString & key); - void updateParameter(const QString & key); - -private: - void addParameter(QVBoxLayout * layout, const QString & key, const QVariant & value); - void addParameter(QVBoxLayout * layout, const QString & key, const QString & value); - void addParameter(QVBoxLayout * layout, const QString & key, const int & value); - void addParameter(QVBoxLayout * layout, const QString & key, const double & value); - void addParameter(QVBoxLayout * layout, const QString & key, const bool & value); - void addParameter(QVBoxLayout * layout, const QString & name, QWidget * widget); - - void changeParameter(QObject * sender, int value); - -Q_SIGNALS: - void parametersChanged(const QStringList & name); - -private Q_SLOTS: - void changeParameter(); - void changeParameter(const QString & value); - void changeParameter(bool value); - void changeParameter(int value); - void resetCurrentPage(); - void resetAllPages(); - -private: - QStringList resetPage(int index); - void updateParametersVisibility(); -}; - -} // namespace find_object - -#endif /* PARAMETERSTOOLBOX_H_ */ diff --git a/find-object/src/QtOpenCV.cpp b/find-object/src/QtOpenCV.cpp deleted file mode 100644 index e5bd205f..00000000 --- a/find-object/src/QtOpenCV.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "find_object/QtOpenCV.h" -#include -#include - -namespace find_object { - -QImage cvtCvMat2QImage(const cv::Mat & image, bool isBgr) -{ - QImage qtemp; - if(!image.empty() && image.depth() == CV_8U) - { - if(image.channels()==3) - { - const unsigned char * data = image.data; - if(image.channels() == 3) - { - qtemp = QImage(image.cols, image.rows, QImage::Format_RGB32); - for(int y = 0; y < image.rows; ++y, data += image.cols*image.elemSize()) - { - for(int x = 0; x < image.cols; ++x) - { - QRgb * p = ((QRgb*)qtemp.scanLine (y)) + x; - if(isBgr) - { - *p = qRgb(data[x * image.channels()+2], data[x * image.channels()+1], data[x * image.channels()]); - } - else - { - *p = qRgb(data[x * image.channels()], data[x * image.channels()+1], data[x * image.channels()+2]); - } - } - } - } - } - else if(image.channels() == 1) - { - // mono grayscale - qtemp = QImage(image.data, image.cols, image.rows, image.cols, QImage::Format_Indexed8).copy(); - QVector my_table; - for(int i = 0; i < 256; i++) my_table.push_back(qRgb(i,i,i)); - qtemp.setColorTable(my_table); - } - else - { - printf("Wrong image format, must have 1 or 3 channels\n"); - } - } - return qtemp; -} - -cv::Mat cvtQImage2CvMat(const QImage & image) -{ - cv::Mat cvImage; - if(!image.isNull() && image.depth() == 32 && image.format() == QImage::Format_RGB32) - { - // assume RGB (3 channels) - int channels = 3; - cvImage = cv::Mat(image.height(), image.width(), CV_8UC3); - unsigned char * data = cvImage.data; - for(int y = 0; y < image.height(); ++y, data+=cvImage.cols*cvImage.elemSize()) - { - for(int x = 0; x < image.width(); ++x) - { - QRgb rgb = image.pixel(x, y); - data[x * channels+2] = qRed(rgb); //r - data[x * channels+1] = qGreen(rgb); //g - data[x * channels] = qBlue(rgb); //b - } - } - } - else - { - printf("Failed to convert image : depth=%d(!=32) format=%d(!=%d)\n", image.depth(), image.format(), QImage::Format_RGB32); - } - return cvImage; -} - -#if CV_MAJOR_VERSION < 3 -QImage cvtIplImage2QImage(const IplImage * image) -{ - QImage qtemp; - if (image && image->depth == IPL_DEPTH_8U && cvGetSize(image).width>0) - { - const char * data = image->imageData; - qtemp= QImage(image->width, image->height,QImage::Format_RGB32); - - for(int y = 0; y < image->height; ++y, data +=image->widthStep ) - { - for(int x = 0; x < image->width; ++x) - { - uint *p = (uint*)qtemp.scanLine (y) + x; - *p = qRgb(data[x * image->nChannels+2], data[x * image->nChannels+1],data[x * image->nChannels]); - } - } - } - else if(image && image->depth != IPL_DEPTH_8U) - { - printf("Wrong iplImage format, must be 8_bits\n"); - } - return qtemp; -} - -// Returned image must be released explicitly (using cvReleaseImage()). -IplImage * cvtQImage2IplImage(const QImage & image) -{ - IplImage * iplTmp = 0; - if(!image.isNull() && image.depth() == 32 && image.format() == QImage::Format_RGB32) - { - // assume RGB (3 channels) - int channels = 3; - iplTmp = cvCreateImage(cvSize(image.width(), image.height()), IPL_DEPTH_8U, channels); - char * data = iplTmp->imageData; - for(int y = 0; y < image.height(); ++y, data+=iplTmp->widthStep) - { - for(int x = 0; x < image.width(); ++x) - { - QRgb rgb = image.pixel(x, y); - data[x * channels+2] = qRed(rgb); //r - data[x * channels+1] = qGreen(rgb); //g - data[x * channels] = qBlue(rgb); //b - } - } - } - else - { - printf("Failed to convert image : depth=%d(!=32) format=%d(!=%d)\n", image.depth(), image.format(), QImage::Format_RGB32); - } - return iplTmp; -} -#endif - -} // namespace find_object diff --git a/find-object/src/RectItem.cpp b/find-object/src/RectItem.cpp deleted file mode 100644 index f249e27b..00000000 --- a/find-object/src/RectItem.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "RectItem.h" - -#include -#include -#include - -namespace find_object { - -RectItem::RectItem(int id, const QRectF &rect, QGraphicsItem * parent) : - QGraphicsRectItem(rect, parent), - placeHolder_(0), - id_(id) -{ - this->setAcceptHoverEvents(true); - this->setFlag(QGraphicsItem::ItemIsFocusable, true); - this->setFlag(QGraphicsItem::ItemIsSelectable, true); -} - -RectItem::~RectItem() -{ -} - -void RectItem::setColor(const QColor & color) -{ - this->setPen(QPen(color)); - this->setBrush(QBrush(color)); - if(placeHolder_) - { - QList items = placeHolder_->childItems(); - if(items.size()) - { - ((QGraphicsTextItem *)items.front())->setDefaultTextColor(this->pen().color().rgb()); - } - } -} - -void RectItem::showDescription() -{ - if(!placeHolder_ || !placeHolder_->isVisible()) - { - if(!placeHolder_) - { - placeHolder_ = new QGraphicsRectItem(); - placeHolder_->setVisible(false); - this->scene()->addItem(placeHolder_); - placeHolder_->setBrush(QBrush(QColor ( 0, 0, 0, 170 ))); // Black transparent background - QGraphicsTextItem * text = new QGraphicsTextItem(placeHolder_); - text->setDefaultTextColor(this->pen().color().rgb()); - QTransform t = this->transform(); - QPolygonF rectH = this->mapToScene(this->rect()); - float angle = 90.0f; - for(int a=0; a 90.0f) - { - angleTmp = 180.0f - angleTmp; - } - if(angleTmp < angle) - { - angle = angleTmp; - } - } - text->setPlainText(tr( - "Object=%1\n" - "Homography= [\n" - " %2 %3 %4\n" - " %5 %6 %7\n" - " %8 %9 %10]\n" - "Angle=%11").arg(id_) - .arg(t.m11()).arg(t.m12()).arg(t.m13()) - .arg(t.m21()).arg(t.m22()).arg(t.m23()) - .arg(t.m31()).arg(t.m32()).arg(t.m33()) - .arg(angle)); - placeHolder_->setRect(text->boundingRect()); - } - - - QPen pen = this->pen(); - this->setPen(QPen(pen.color(), pen.width()*2)); - placeHolder_->setZValue(this->zValue()+1); - placeHolder_->setPos(0,0); - placeHolder_->setVisible(true); - - Q_EMIT hovered(id_); - } -} - -void RectItem::hideDescription() -{ - if(placeHolder_ && placeHolder_->isVisible()) - { - placeHolder_->setVisible(false); - this->setPen(QPen(pen().color(), pen().width()/2)); - } -} - -void RectItem::hoverEnterEvent ( QGraphicsSceneHoverEvent * event ) -{ - this->showDescription(); - QGraphicsRectItem::hoverEnterEvent(event); -} - -void RectItem::hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ) -{ - if(!this->hasFocus()) - { - this->hideDescription(); - } - QGraphicsRectItem::hoverEnterEvent(event); -} - -void RectItem::focusInEvent ( QFocusEvent * event ) -{ - this->showDescription(); - QGraphicsRectItem::focusInEvent(event); -} - -void RectItem::focusOutEvent ( QFocusEvent * event ) -{ - this->hideDescription(); - QGraphicsRectItem::focusOutEvent(event); -} - -} // namespace find_object diff --git a/find-object/src/RectItem.h b/find-object/src/RectItem.h deleted file mode 100644 index 3316b3f3..00000000 --- a/find-object/src/RectItem.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef RECTITEM_H_ -#define RECTITEM_H_ - -#include -#include -#include -#include - -namespace find_object { - -class RectItem : public QObject, public QGraphicsRectItem -{ - Q_OBJECT; - -public: - RectItem(int id, const QRectF &rect, QGraphicsItem * parent = 0); - virtual ~RectItem(); - - void setColor(const QColor & color); - int id() const {return id_;} - -Q_SIGNALS: - void hovered(int); - -protected: - virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event ); - virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ); - virtual void focusInEvent ( QFocusEvent * event ); - virtual void focusOutEvent ( QFocusEvent * event ); - -private: - void showDescription(); - void hideDescription(); - -private: - QGraphicsRectItem * placeHolder_; - int id_; -}; - -} // namespace find_object - -#endif /* RECTITEM_H_ */ diff --git a/find-object/src/Settings.cpp b/find-object/src/Settings.cpp deleted file mode 100644 index 8f9175ca..00000000 --- a/find-object/src/Settings.cpp +++ /dev/null @@ -1,1782 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "find_object/Camera.h" -#include "find_object/Settings.h" -#include "find_object/utilite/ULogger.h" - -#include -#include -#include -#include -#include -#include - -#if CV_MAJOR_VERSION < 3 -#include -#define CVCUDA cv::gpu -#else -#include -#define CVCUDA cv::cuda -#ifdef HAVE_OPENCV_CUDAFEATURES2D -#include -#endif -#endif - -#ifdef HAVE_OPENCV_NONFREE - #if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >=4 - #include - #include - #endif -#endif -#ifdef HAVE_OPENCV_XFEATURES2D - #include - #include -#endif - -#if FINDOBJECT_TORCH == 1 -#include "superpoint_torch/SuperPoint.h" -#endif - -namespace find_object { - -ParametersMap Settings::defaultParameters_; -ParametersMap Settings::parameters_; -ParametersType Settings::parametersType_; -DescriptionsMap Settings::descriptions_; -Settings Settings::dummyInit_; -QString Settings::iniPath_; - -QString Settings::workingDirectory() -{ -#ifdef WIN32 - return QString("%1/Documents/%2").arg(QDir::homePath()).arg(PROJECT_NAME); -#else - return QString("%1").arg(QDir::homePath()); -#endif -} - -QString Settings::iniDefaultPath() -{ -#ifdef WIN32 - return QString("%1/Documents/%2/%3").arg(QDir::homePath()).arg(PROJECT_NAME).arg(Settings::iniDefaultFileName()); -#else - return QString("%1/.%2/%3").arg(QDir::homePath()).arg(PROJECT_PREFIX).arg(Settings::iniDefaultFileName()); -#endif -} - -QString Settings::iniPath() -{ - if(!iniPath_.isNull()) - { - return iniPath_; - } - return iniDefaultPath(); -} - -ParametersMap Settings::init(const QString & fileName) -{ - iniPath_ = fileName; - return loadSettings(iniPath_); -} - -ParametersMap Settings::loadSettings(const QString & fileName) -{ - ParametersMap loadedParameters; - QString path = fileName; - if(fileName.isEmpty()) - { - path = iniPath(); - } - if(!path.isEmpty()) - { - QSettings ini(path, QSettings::IniFormat); - for(ParametersMap::const_iterator iter = defaultParameters_.begin(); iter!=defaultParameters_.end(); ++iter) - { - const QString & key = iter.key(); - QVariant value = ini.value(key, QVariant()); - if(value.isValid()) - { - QString str = value.toString(); - if(str.contains(";")) - { - if(str.size() != getParameter(key).toString().size()) - { - // If a string list is modified, update the value - // Assuming format ##:VA;VB;VC - int index = str.split(':').first().toInt(); - str = getParameter(key).toString(); - str = QString::number(index)+":"+ str.split(':').back(); - value = QVariant(str); - UINFO("Updated list of parameter \"%s\"", key.toStdString().c_str()); - } - int index = str.split(':').first().toInt(); - if(key.compare(Settings::kFeature2D_1Detector()) == 0) - { -#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11))) -#if FINDOBJECT_NONFREE == 0 - if(index == 5 || index == 7) - { - index = Settings::defaultFeature2D_1Detector().split(':').first().toInt(); - UWARN("Trying to set \"%s\" to SIFT/SURF but Find-Object isn't built " - "with the nonfree module from OpenCV. Keeping default combo value: %s.", - Settings::kFeature2D_1Detector().toStdString().c_str(), - Settings::defaultFeature2D_1Detector().split(':').last().split(";").at(index).toStdString().c_str()); - } -#endif -#elif FINDOBJECT_NONFREE == 0 - if(index == 7) - { - index = Settings::defaultFeature2D_1Detector().split(':').first().toInt(); - UWARN("Trying to set \"%s\" to SURF but Find-Object isn't built " - "with the nonfree module from OpenCV. Keeping default combo value: %s.", - Settings::kFeature2D_1Detector().toStdString().c_str(), - Settings::defaultFeature2D_1Detector().split(':').last().split(";").at(index).toStdString().c_str()); - } -#endif -#if FINDOBJECT_TORCH == 0 - if(index == 12) - { - index = Settings::defaultFeature2D_1Detector().split(':').first().toInt(); - UWARN("Trying to set \"%s\" to SuperPointTorch but Find-Object isn't built " - "with the Torch. Keeping default combo value: %s.", - Settings::kFeature2D_1Detector().toStdString().c_str(), - Settings::defaultFeature2D_1Detector().split(':').last().split(";").at(index).toStdString().c_str()); - } -#endif - } - else if(key.compare(Settings::kFeature2D_2Descriptor()) == 0) - { -#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11))) -#if FINDOBJECT_NONFREE == 0 - if(index == 2 || index == 3) - { - index = Settings::defaultFeature2D_2Descriptor().split(':').first().toInt(); - UWARN("Trying to set \"%s\" to SIFT/SURF but Find-Object isn't built " - "with the nonfree module from OpenCV. Keeping default combo value: %s.", - Settings::kFeature2D_2Descriptor().toStdString().c_str(), - Settings::defaultFeature2D_2Descriptor().split(':').last().split(";").at(index).toStdString().c_str()); - } -#endif -#elif FINDOBJECT_NONFREE == 0 - if(index == 3) - { - index = Settings::defaultFeature2D_2Descriptor().split(':').first().toInt(); - UWARN("Trying to set \"%s\" to SURF but Find-Object isn't built " - "with the nonfree module from OpenCV. Keeping default combo value: %s.", - Settings::kFeature2D_2Descriptor().toStdString().c_str(), - Settings::defaultFeature2D_2Descriptor().split(':').last().split(";").at(index).toStdString().c_str()); - } -#endif -#if FINDOBJECT_TORCH == 0 - if(index == 11) - { - index = Settings::defaultFeature2D_2Descriptor().split(':').first().toInt(); - UWARN("Trying to set \"%s\" to SuperPointTorch but Find-Object isn't built " - "with the Torch. Keeping default combo value: %s.", - Settings::kFeature2D_1Detector().toStdString().c_str(), - Settings::defaultFeature2D_1Detector().split(':').last().split(";").at(index).toStdString().c_str()); - } -#endif - } - str = getParameter(key).toString(); - str = QString::number(index)+":"+ str.split(':').back(); - value = QVariant(str); - } - loadedParameters.insert(key, value); - setParameter(key, value); - } - } - - //validate descriptors and nearest neighbor compatibilities - bool isBinaryDescriptor = currentDescriptorType().compare("ORB") == 0 || - currentDescriptorType().compare("Brief") == 0 || - currentDescriptorType().compare("BRISK") == 0 || - currentDescriptorType().compare("FREAK") == 0 || - currentDescriptorType().compare("AKAZE") == 0 || - currentDescriptorType().compare("LATCH") == 0 || - currentDescriptorType().compare("LUCID") == 0; - bool binToFloat = getNearestNeighbor_7ConvertBinToFloat(); - if(isBinaryDescriptor && !binToFloat && currentNearestNeighborType().compare("Lsh") != 0 && currentNearestNeighborType().compare("BruteForce") != 0) - { - UWARN("Current selected descriptor type (\"%s\") is binary while nearest neighbor strategy is not (\"%s\").\n" - "Falling back to \"BruteForce\" nearest neighbor strategy with Hamming distance (by default).", - currentDescriptorType().toStdString().c_str(), - currentNearestNeighborType().toStdString().c_str()); - QString tmp = Settings::getNearestNeighbor_1Strategy(); - *tmp.begin() = '6'; // set BruteForce - setNearestNeighbor_1Strategy(tmp); - loadedParameters.insert(Settings::kNearestNeighbor_1Strategy(), tmp); - tmp = Settings::getNearestNeighbor_2Distance_type(); - *tmp.begin() = '8'; // set HAMMING - setNearestNeighbor_2Distance_type(tmp); - loadedParameters.insert(Settings::kNearestNeighbor_2Distance_type(), tmp); - } - - UINFO("Settings loaded from %s.", path.toStdString().c_str()); - } - else - { - parameters_ = defaultParameters_; - UINFO("Settings set to defaults."); - } - - if(CVCUDA::getCudaEnabledDeviceCount() == 0) - { -#if FINDOBJECT_NONFREE == 1 - Settings::setFeature2D_SURF_gpu(false); -#endif - Settings::setFeature2D_Fast_gpu(false); - Settings::setFeature2D_ORB_gpu(false); - Settings::setNearestNeighbor_BruteForce_gpu(false); - } - return loadedParameters; -} - -void Settings::loadWindowSettings(QByteArray & windowGeometry, QByteArray & windowState, const QString & fileName) -{ - QString path = fileName; - if(fileName.isEmpty()) - { - path = iniPath(); - } - - if(!path.isEmpty()) - { - QSettings ini(path, QSettings::IniFormat); - - QVariant value = ini.value("windowGeometry", QVariant()); - if(value.isValid()) - { - windowGeometry = value.toByteArray(); - } - - value = ini.value("windowState", QVariant()); - if(value.isValid()) - { - windowState = value.toByteArray(); - } - - UINFO("Window settings loaded from %s", path.toStdString().c_str()); - } -} - -void Settings::saveSettings(const QString & fileName) -{ - QString path = fileName; - if(fileName.isEmpty()) - { - path = iniPath(); - } - if(!path.isEmpty()) - { - QSettings ini(path, QSettings::IniFormat); - for(ParametersMap::const_iterator iter = parameters_.begin(); iter!=parameters_.end(); ++iter) - { - QString type = Settings::getParametersType().value(iter.key()); - if(type.compare("float") == 0) - { - ini.setValue(iter.key(), QString::number(iter.value().toFloat(),'g',6)); - } - else - { - ini.setValue(iter.key(), iter.value()); - } - } - UINFO("Settings saved to %s", path.toStdString().c_str()); - } -} - -void Settings::saveWindowSettings(const QByteArray & windowGeometry, const QByteArray & windowState, const QString & fileName) -{ - QString path = fileName; - if(fileName.isEmpty()) - { - path = iniPath(); - } - if(!path.isEmpty()) - { - QSettings ini(path, QSettings::IniFormat); - if(!windowGeometry.isEmpty()) - { - ini.setValue("windowGeometry", windowGeometry); - } - if(!windowState.isEmpty()) - { - ini.setValue("windowState", windowState); - } - UINFO("Window settings saved to %s", path.toStdString().c_str()); - } -} - -#if FINDOBJECT_NONFREE == 1 -class GPUSURF : public Feature2D -{ -public: - GPUSURF(double hessianThreshold, - int nOctaves, - int nOctaveLayers, - bool extended, - float keypointsRatio, - bool upright) : - surf_(hessianThreshold, - nOctaves, - nOctaveLayers, - extended, - keypointsRatio, - upright) - { - } - virtual ~GPUSURF() {} - - virtual void detect(const cv::Mat & image, - std::vector & keypoints, - const cv::Mat & mask = cv::Mat()) - { - CVCUDA::GpuMat imgGpu(image); - CVCUDA::GpuMat maskGpu(mask); - try - { - surf_(imgGpu, maskGpu, keypoints); - } - catch(cv::Exception &e) - { - UERROR("GPUSURF error: %s \n(If something about layer_rows, parameter nOctaves=%d of SURF " - "is too high for the size of the image (%d,%d).)", - e.msg.c_str(), - surf_.nOctaves, - image.cols, - image.rows); - } - } - - virtual void compute( const cv::Mat& image, - std::vector& keypoints, - cv::Mat& descriptors) - { - std::vector d; - CVCUDA::GpuMat imgGpu(image); - CVCUDA::GpuMat descriptorsGPU; - try - { - surf_(imgGpu, CVCUDA::GpuMat(), keypoints, descriptorsGPU, true); - } - catch(cv::Exception &e) - { - UERROR("GPUSURF error: %s \n(If something about layer_rows, parameter nOctaves=%d of SURF " - "is too high for the size of the image (%d,%d).)", - e.msg.c_str(), - surf_.nOctaves, - image.cols, - image.rows); - } - - // Download descriptors - if (descriptorsGPU.empty()) - descriptors = cv::Mat(); - else - { - UASSERT(descriptorsGPU.type() == CV_32F); - descriptors = cv::Mat(descriptorsGPU.size(), CV_32F); - descriptorsGPU.download(descriptors); - } - } - - virtual void detectAndCompute( const cv::Mat& image, - std::vector& keypoints, - cv::Mat& descriptors, - const cv::Mat & mask = cv::Mat()) - { - std::vector d; - CVCUDA::GpuMat imgGpu(image); - CVCUDA::GpuMat descriptorsGPU; - CVCUDA::GpuMat maskGpu(mask); - try - { - surf_(imgGpu, maskGpu, keypoints, descriptorsGPU, false); - } - catch(cv::Exception &e) - { - UERROR("GPUSURF error: %s \n(If something about layer_rows, parameter nOctaves=%d of SURF " - "is too high for the size of the image (%d,%d).)", - e.msg.c_str(), - surf_.nOctaves, - image.cols, - image.rows); - } - - // Download descriptors - if (descriptorsGPU.empty()) - descriptors = cv::Mat(); - else - { - UASSERT(descriptorsGPU.type() == CV_32F); - descriptors = cv::Mat(descriptorsGPU.size(), CV_32F); - descriptorsGPU.download(descriptors); - } - } - -private: -#if CV_MAJOR_VERSION < 3 - CVCUDA::SURF_GPU surf_; -#else - CVCUDA::SURF_CUDA surf_; -#endif -}; -#endif - -class GPUFAST : public Feature2D -{ -public: - GPUFAST(int threshold=Settings::defaultFeature2D_Fast_threshold(), - bool nonmaxSuppression=Settings::defaultFeature2D_Fast_nonmaxSuppression(), -#if CV_MAJOR_VERSION < 3 - double keypointsRatio=Settings::defaultFeature2D_Fast_keypointsRatio()) - : fast_(threshold, - nonmaxSuppression, - keypointsRatio) -#else - int max_npoints=Settings::defaultFeature2D_Fast_maxNpoints()) -#ifdef HAVE_OPENCV_CUDAFEATURES2D - : fast_(CVCUDA::FastFeatureDetector::create( - threshold, - nonmaxSuppression, - cv::FastFeatureDetector::TYPE_9_16, - max_npoints)) -#endif -#endif - { - } - virtual ~GPUFAST() {} - - virtual void detect(const cv::Mat & image, - std::vector & keypoints, - const cv::Mat & mask = cv::Mat()) - { - CVCUDA::GpuMat imgGpu(image); - CVCUDA::GpuMat maskGpu(mask); -#if CV_MAJOR_VERSION < 3 - fast_(imgGpu, maskGpu, keypoints); -#else -#ifdef HAVE_OPENCV_CUDAFEATURES2D - CVCUDA::GpuMat keypointsGpu; - fast_->detectAsync(imgGpu, keypointsGpu, maskGpu); - fast_->convert(keypointsGpu, keypoints); -#endif -#endif - } - virtual void compute( const cv::Mat& image, - std::vector& keypoints, - cv::Mat& descriptors) - { - UERROR("GPUFAST:computeDescriptors() Should not be used!"); - } - virtual void detectAndCompute( const cv::Mat& image, - std::vector& keypoints, - cv::Mat& descriptors, - const cv::Mat & mask = cv::Mat()) - { - UERROR("GPUFAST:detectAndCompute() Should not be used!"); - } - -private: -#if CV_MAJOR_VERSION < 3 - CVCUDA::FAST_GPU fast_; -#else -#ifdef HAVE_OPENCV_CUDAFEATURES2D - cv::Ptr fast_; -#endif -#endif -}; - -class GPUORB : public Feature2D -{ -public: - GPUORB(int nFeatures = Settings::defaultFeature2D_ORB_nFeatures(), - float scaleFactor = Settings::defaultFeature2D_ORB_scaleFactor(), - int nLevels = Settings::defaultFeature2D_ORB_nLevels(), - int edgeThreshold = Settings::defaultFeature2D_ORB_edgeThreshold(), - int firstLevel = Settings::defaultFeature2D_ORB_firstLevel(), - int WTA_K = Settings::defaultFeature2D_ORB_WTA_K(), - int scoreType = Settings::defaultFeature2D_ORB_scoreType(), - int patchSize = Settings::defaultFeature2D_ORB_patchSize(), - int fastThreshold = Settings::defaultFeature2D_Fast_threshold(), -#if CV_MAJOR_VERSION < 3 - bool fastNonmaxSupression = Settings::defaultFeature2D_Fast_nonmaxSuppression()) - : orb_(nFeatures, - scaleFactor, - nLevels, - edgeThreshold , - firstLevel, - WTA_K, - scoreType, - patchSize) -#else - bool blurForDescriptor = Settings::defaultFeature2D_ORB_blurForDescriptor()) -#ifdef HAVE_OPENCV_CUDAFEATURES2D - : orb_(CVCUDA::ORB::create(nFeatures, - scaleFactor, - nLevels, - edgeThreshold , - firstLevel, - WTA_K, - scoreType, - patchSize, - fastThreshold, - blurForDescriptor)) -#endif -#endif - { -#if CV_MAJOR_VERSION < 3 - orb_.setFastParams(fastThreshold, fastNonmaxSupression); -#endif - } - virtual ~GPUORB() {} - - virtual void detect(const cv::Mat & image, - std::vector & keypoints, - const cv::Mat & mask = cv::Mat()) - { - - CVCUDA::GpuMat imgGpu(image); - CVCUDA::GpuMat maskGpu(mask); - - try - { -#if CV_MAJOR_VERSION < 3 - orb_(imgGpu, maskGpu, keypoints); -#else -#ifdef HAVE_OPENCV_CUDAFEATURES2D - CVCUDA::GpuMat keypointsGpu; - orb_->detectAsync(imgGpu, keypointsGpu, maskGpu); - orb_->convert(keypointsGpu, keypoints); -#endif -#endif - } - catch(cv::Exception &e) - { - UERROR("GPUORB error: %s \n(If something about matrix size, the image/object may be too small (%d,%d).)", - e.msg.c_str(), - image.cols, - image.rows); - } - } - - virtual void compute( const cv::Mat& image, - std::vector& keypoints, - cv::Mat& descriptors) - { - std::vector d; - - CVCUDA::GpuMat imgGpu(image); - CVCUDA::GpuMat descriptorsGPU; - - try - { -#if CV_MAJOR_VERSION < 3 - orb_(imgGpu, CVCUDA::GpuMat(), keypoints, descriptorsGPU); // No option to use provided keypoints!? -#else -#ifdef HAVE_OPENCV_CUDAFEATURES2D - UERROR("OpenCV 3 ORB-GPU doesn't support extracting ORB descriptors from already extracted keypoints. " - "Use ORB as feature detector too or desactivate ORB-GPU."); - //orb_->computeAsync(imgGpu, keypoints, descriptorsGPU, true); -#endif -#endif - } - catch(cv::Exception &e) - { - UERROR("GPUORB error: %s \n(If something about matrix size, the image/object may be too small (%d,%d).)", - e.msg.c_str(), - image.cols, - image.rows); - } - // Download descriptors - if (descriptorsGPU.empty()) - descriptors = cv::Mat(); - else - { - UASSERT(descriptorsGPU.type() == CV_8U); - descriptors = cv::Mat(descriptorsGPU.size(), CV_8U); - descriptorsGPU.download(descriptors); - } - } - - virtual void detectAndCompute( const cv::Mat& image, - std::vector& keypoints, - cv::Mat& descriptors, - const cv::Mat & mask = cv::Mat()) - { - std::vector d; - - CVCUDA::GpuMat imgGpu(image); - CVCUDA::GpuMat descriptorsGPU; - CVCUDA::GpuMat maskGpu(mask); - - try - { -#if CV_MAJOR_VERSION < 3 - orb_(imgGpu, CVCUDA::GpuMat(), keypoints, descriptorsGPU); // No option to use provided keypoints!? -#else -#ifdef HAVE_OPENCV_CUDAFEATURES2D - CVCUDA::GpuMat keypointsGpu; - orb_->detectAndComputeAsync(imgGpu, maskGpu, keypointsGpu, descriptorsGPU, false); - orb_->convert(keypointsGpu, keypoints); -#endif -#endif - } - catch(cv::Exception &e) - { - UERROR("GPUORB error: %s \n(If something about matrix size, the image/object may be too small (%d,%d).)", - e.msg.c_str(), - image.cols, - image.rows); - } - // Download descriptors - if (descriptorsGPU.empty()) - descriptors = cv::Mat(); - else - { - UASSERT(descriptorsGPU.type() == CV_8U); - descriptors = cv::Mat(descriptorsGPU.size(), CV_8U); - descriptorsGPU.download(descriptors); - } - } - -private: -#if CV_MAJOR_VERSION < 3 - CVCUDA::ORB_GPU orb_; -#else -#ifdef HAVE_OPENCV_CUDAFEATURES2D - cv::Ptr orb_; -#endif -#endif -}; - -#if FINDOBJECT_TORCH == 1 -class SuperPointTorch : public Feature2D -{ -public: - SuperPointTorch( - const QString & modelPath, - float threshold = Settings::defaultFeature2D_SuperPointTorch_threshold(), - bool nms = Settings::defaultFeature2D_SuperPointTorch_NMS(), - int nmsRadius = Settings::defaultFeature2D_SuperPointTorch_NMS_radius(), - bool cuda = Settings::defaultFeature2D_SuperPointTorch_cuda()) - { - superPoint_ = cv::Ptr(new SPDetector(modelPath.toStdString(), threshold, nms, nmsRadius, cuda)); - } - - virtual ~SuperPointTorch() {} - - virtual void detect(const cv::Mat & image, - std::vector & keypoints, - const cv::Mat & mask = cv::Mat()) - { - keypoints = superPoint_->detect(image); - } - - virtual void compute( const cv::Mat& image, - std::vector& keypoints, - cv::Mat& descriptors) - { - descriptors = superPoint_->compute(keypoints); - } - - virtual void detectAndCompute( const cv::Mat& image, - std::vector& keypoints, - cv::Mat& descriptors, - const cv::Mat & mask = cv::Mat()) - { - keypoints = superPoint_->detect(image); - descriptors = superPoint_->compute(keypoints); - } -private: - cv::Ptr superPoint_; -}; -#endif - -Feature2D * Settings::createKeypointDetector() -{ - Feature2D * feature2D = 0; - QString str = getFeature2D_1Detector(); - UDEBUG("Type=%s", str.toStdString().c_str()); - QStringList split = str.split(':'); - if(split.size()==2) - { - bool ok = false; - int index = split.first().toInt(&ok); - if(ok) - { - QStringList strategies = split.last().split(';'); - - if(index>=0 && index(new cv::DenseFeatureDetector( - getFeature2D_Dense_initFeatureScale(), - getFeature2D_Dense_featureScaleLevels(), - getFeature2D_Dense_featureScaleMul(), - getFeature2D_Dense_initXyStep(), - getFeature2D_Dense_initImgBound(), - getFeature2D_Dense_varyXyStepWithScale(), - getFeature2D_Dense_varyImgBoundWithScale()))); -#else - UWARN("Find-Object is not built with OpenCV 2 so Dense cannot be used!"); -#endif - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - else if(strategies.at(index).compare("Fast") == 0) - { - if(getFeature2D_Fast_gpu() && CVCUDA::getCudaEnabledDeviceCount()) - { - feature2D = new GPUFAST( - getFeature2D_Fast_threshold(), - getFeature2D_Fast_nonmaxSuppression()); - UDEBUG("type=%s GPU", strategies.at(index).toStdString().c_str()); - } - else - { -#if CV_MAJOR_VERSION < 3 - feature2D = new Feature2D(cv::Ptr(new cv::FastFeatureDetector( - getFeature2D_Fast_threshold(), - getFeature2D_Fast_nonmaxSuppression()))); -#else - feature2D = new Feature2D(cv::FastFeatureDetector::create( - getFeature2D_Fast_threshold(), - getFeature2D_Fast_nonmaxSuppression())); -#endif - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - } - else if(strategies.at(index).compare("AGAST") == 0) - { -#if CV_MAJOR_VERSION < 3 - UWARN("Find-Object is not built with OpenCV 3 so AGAST cannot be used!"); -#else - feature2D = new Feature2D(cv::AgastFeatureDetector::create( - getFeature2D_AGAST_threshold(), - getFeature2D_AGAST_nonmaxSuppression())); -#endif - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - else if(strategies.at(index).compare("GFTT") == 0) - { -#if CV_MAJOR_VERSION < 3 - feature2D = new Feature2D(cv::Ptr(new cv::GFTTDetector( - getFeature2D_GFTT_maxCorners(), - getFeature2D_GFTT_qualityLevel(), - getFeature2D_GFTT_minDistance(), - getFeature2D_GFTT_blockSize(), - getFeature2D_GFTT_useHarrisDetector(), - getFeature2D_GFTT_k()))); -#else - feature2D = new Feature2D(cv::GFTTDetector::create( - getFeature2D_GFTT_maxCorners(), - getFeature2D_GFTT_qualityLevel(), - getFeature2D_GFTT_minDistance(), - getFeature2D_GFTT_blockSize(), - getFeature2D_GFTT_useHarrisDetector(), - getFeature2D_GFTT_k())); -#endif - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - else if(strategies.at(index).compare("MSER") == 0) - { -#if CV_MAJOR_VERSION < 3 - feature2D = new Feature2D(cv::Ptr(new cv::MSER( - getFeature2D_MSER_delta(), - getFeature2D_MSER_minArea(), - getFeature2D_MSER_maxArea(), - getFeature2D_MSER_maxVariation(), - getFeature2D_MSER_minDiversity(), - getFeature2D_MSER_maxEvolution(), - getFeature2D_MSER_areaThreshold(), - getFeature2D_MSER_minMargin(), - getFeature2D_MSER_edgeBlurSize()))); -#else - feature2D = new Feature2D(cv::MSER::create( - getFeature2D_MSER_delta(), - getFeature2D_MSER_minArea(), - getFeature2D_MSER_maxArea(), - getFeature2D_MSER_maxVariation(), - getFeature2D_MSER_minDiversity(), - getFeature2D_MSER_maxEvolution(), - getFeature2D_MSER_areaThreshold(), - getFeature2D_MSER_minMargin(), - getFeature2D_MSER_edgeBlurSize())); -#endif - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - else if(strategies.at(index).compare("ORB") == 0) - { - if(getFeature2D_ORB_gpu() && CVCUDA::getCudaEnabledDeviceCount()) - { - feature2D = new GPUORB( - getFeature2D_ORB_nFeatures(), - getFeature2D_ORB_scaleFactor(), - getFeature2D_ORB_nLevels(), - getFeature2D_ORB_edgeThreshold(), - getFeature2D_ORB_firstLevel(), - getFeature2D_ORB_WTA_K(), - getFeature2D_ORB_scoreType(), - getFeature2D_ORB_patchSize(), - getFeature2D_Fast_threshold(), -#if CV_MAJOR_VERSION < 3 - getFeature2D_Fast_nonmaxSuppression()); -#else - getFeature2D_ORB_blurForDescriptor()); -#endif - UDEBUG("type=%s (GPU)", strategies.at(index).toStdString().c_str()); - } - else - { -#if CV_MAJOR_VERSION < 3 - feature2D = new Feature2D(cv::Ptr(new cv::ORB( - getFeature2D_ORB_nFeatures(), - getFeature2D_ORB_scaleFactor(), - getFeature2D_ORB_nLevels(), - getFeature2D_ORB_edgeThreshold(), - getFeature2D_ORB_firstLevel(), - getFeature2D_ORB_WTA_K(), - getFeature2D_ORB_scoreType(), - getFeature2D_ORB_patchSize()))); -#else - feature2D = new Feature2D(cv::ORB::create( - getFeature2D_ORB_nFeatures(), - getFeature2D_ORB_scaleFactor(), - getFeature2D_ORB_nLevels(), - getFeature2D_ORB_edgeThreshold(), - getFeature2D_ORB_firstLevel(), - getFeature2D_ORB_WTA_K(), -#if CV_MAJOR_VERSION > 3 - (cv::ORB::ScoreType)getFeature2D_ORB_scoreType(), -#else - getFeature2D_ORB_scoreType(), -#endif - getFeature2D_ORB_patchSize(), - getFeature2D_Fast_threshold())); -#endif - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - } - else if(strategies.at(index).compare("Star") == 0) - { -#if CV_MAJOR_VERSION < 3 - feature2D = new Feature2D(cv::Ptr(new cv::StarFeatureDetector( - getFeature2D_Star_maxSize(), - getFeature2D_Star_responseThreshold(), - getFeature2D_Star_lineThresholdProjected(), - getFeature2D_Star_lineThresholdBinarized(), - getFeature2D_Star_suppressNonmaxSize()))); -#else -#ifdef HAVE_OPENCV_XFEATURES2D - feature2D = new Feature2D(cv::xfeatures2d::StarDetector::create( - getFeature2D_Star_maxSize(), - getFeature2D_Star_responseThreshold(), - getFeature2D_Star_lineThresholdProjected(), - getFeature2D_Star_lineThresholdBinarized(), - getFeature2D_Star_suppressNonmaxSize())); -#else - UWARN("Find-Object is not built with OpenCV xfeatures2d module so Star cannot be used!"); -#endif -#endif - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - else if(strategies.at(index).compare("BRISK") == 0) - { -#if CV_MAJOR_VERSION < 3 - feature2D = new Feature2D(cv::Ptr(new cv::BRISK( - getFeature2D_BRISK_thresh(), - getFeature2D_BRISK_octaves(), - getFeature2D_BRISK_patternScale()))); -#else - feature2D = new Feature2D(cv::BRISK::create( - getFeature2D_BRISK_thresh(), - getFeature2D_BRISK_octaves(), - getFeature2D_BRISK_patternScale())); -#endif - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - else if(strategies.at(index).compare("KAZE") == 0) - { -#if CV_MAJOR_VERSION < 3 - UWARN("Find-Object is not built with OpenCV 3 so KAZE cannot be used!"); -#else - feature2D = new Feature2D(cv::KAZE::create( - getFeature2D_KAZE_extended(), - getFeature2D_KAZE_upright(), - getFeature2D_KAZE_threshold(), - getFeature2D_KAZE_nOctaves(), - getFeature2D_KAZE_nOctaveLayers(), - cv::KAZE::DIFF_PM_G2)); // FIXME: make a parameter -#endif - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - else if(strategies.at(index).compare("AKAZE") == 0) - { -#if CV_MAJOR_VERSION < 3 - UWARN("Find-Object is not built with OpenCV 3 so AKAZE cannot be used!"); -#else - feature2D = new Feature2D(cv::AKAZE::create( - cv::AKAZE::DESCRIPTOR_MLDB, // FIXME: make a parameter - getFeature2D_AKAZE_descriptorSize(), - getFeature2D_AKAZE_descriptorChannels(), - getFeature2D_AKAZE_threshold(), - getFeature2D_AKAZE_nOctaves(), - getFeature2D_AKAZE_nOctaveLayers(), - cv::KAZE::DIFF_PM_G2)); // FIXME: make a parameter -#endif - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } -#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11))) -#if FINDOBJECT_NONFREE == 1 - else if(strategies.at(index).compare("SIFT") == 0) - { -#if CV_MAJOR_VERSION < 3 - feature2D = new Feature2D(cv::Ptr(new cv::SIFT( - getFeature2D_SIFT_nfeatures(), - getFeature2D_SIFT_nOctaveLayers(), - getFeature2D_SIFT_contrastThreshold(), - getFeature2D_SIFT_edgeThreshold(), - getFeature2D_SIFT_sigma()))); -#else - feature2D = new Feature2D(cv::xfeatures2d::SIFT::create( - getFeature2D_SIFT_nfeatures(), - getFeature2D_SIFT_nOctaveLayers(), - getFeature2D_SIFT_contrastThreshold(), - getFeature2D_SIFT_edgeThreshold(), - getFeature2D_SIFT_sigma())); -#endif - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - else if(strategies.at(index).compare("SURF") == 0) - { - if(getFeature2D_SURF_gpu() && CVCUDA::getCudaEnabledDeviceCount()) - { - feature2D = new GPUSURF( - getFeature2D_SURF_hessianThreshold(), - getFeature2D_SURF_nOctaves(), - getFeature2D_SURF_nOctaveLayers(), - getFeature2D_SURF_extended(), - getFeature2D_SURF_keypointsRatio(), - getFeature2D_SURF_upright()); - UDEBUG("type=%s (GPU)", strategies.at(index).toStdString().c_str()); - } - else - { -#if CV_MAJOR_VERSION < 3 - feature2D = new Feature2D(cv::Ptr(new cv::SURF( - getFeature2D_SURF_hessianThreshold(), - getFeature2D_SURF_nOctaves(), - getFeature2D_SURF_nOctaveLayers(), - getFeature2D_SURF_extended(), - getFeature2D_SURF_upright()))); -#else - feature2D = new Feature2D(cv::xfeatures2d::SURF::create( - getFeature2D_SURF_hessianThreshold(), - getFeature2D_SURF_nOctaves(), - getFeature2D_SURF_nOctaveLayers(), - getFeature2D_SURF_extended(), - getFeature2D_SURF_upright())); -#endif - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - } -#endif -#else // >= 4.3.0-dev - else if(strategies.at(index).compare("SIFT") == 0) - { - feature2D = new Feature2D(cv::SIFT::create( - getFeature2D_SIFT_nfeatures(), - getFeature2D_SIFT_nOctaveLayers(), - getFeature2D_SIFT_contrastThreshold(), - getFeature2D_SIFT_edgeThreshold(), - getFeature2D_SIFT_sigma())); - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } -#if FINDOBJECT_NONFREE == 1 - else if(strategies.at(index).compare("SURF") == 0) - { - if(getFeature2D_SURF_gpu() && CVCUDA::getCudaEnabledDeviceCount()) - { - feature2D = new GPUSURF( - getFeature2D_SURF_hessianThreshold(), - getFeature2D_SURF_nOctaves(), - getFeature2D_SURF_nOctaveLayers(), - getFeature2D_SURF_extended(), - getFeature2D_SURF_keypointsRatio(), - getFeature2D_SURF_upright()); - UDEBUG("type=%s (GPU)", strategies.at(index).toStdString().c_str()); - } - else - { - feature2D = new Feature2D(cv::xfeatures2d::SURF::create( - getFeature2D_SURF_hessianThreshold(), - getFeature2D_SURF_nOctaves(), - getFeature2D_SURF_nOctaveLayers(), - getFeature2D_SURF_extended(), - getFeature2D_SURF_upright())); - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - } -#endif -#endif -#if FINDOBJECT_TORCH == 1 - else if(strategies.at(index).compare("SuperPointTorch") == 0) - { - feature2D = new SuperPointTorch( - getFeature2D_SuperPointTorch_modelPath(), - getFeature2D_SuperPointTorch_threshold(), - getFeature2D_SuperPointTorch_NMS(), - getFeature2D_SuperPointTorch_NMS_radius(), - getFeature2D_SuperPointTorch_cuda()); - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } -#endif - } - } - } - - return feature2D; -} - -Feature2D * Settings::createDescriptorExtractor() -{ - Feature2D * feature2D = 0; - QString str = getFeature2D_2Descriptor(); - UDEBUG("Type=%s", str.toStdString().c_str()); - QStringList split = str.split(':'); - if(split.size()==2) - { - bool ok = false; - int index = split.first().toInt(&ok); - if(ok) - { - QStringList strategies = split.last().split(';'); - if(index>=0 && index= 4.3.0 - if(strategies.at(index).compare("SURF") == 0) - { - index = Settings::defaultFeature2D_2Descriptor().split(':').first().toInt(); - UERROR("Find-Object is not built with OpenCV nonfree module so " - "SURF cannot be used! Using default \"%s\" instead.", - strategies.at(index).toStdString().c_str()); - - } -#endif - -#if FINDOBJECT_TORCH == 0 - //check for nonfree stuff - if(strategies.at(index).compare("SuperPointTorch") == 0) - { - index = Settings::defaultFeature2D_2Descriptor().split(':').first().toInt(); - UERROR("Find-Object is not built with Torch so " - "SuperPointTorch cannot be used! Using default \"%s\" instead.", - strategies.at(index).toStdString().c_str()); - - } -#endif - -#if CV_MAJOR_VERSION < 3 - if(strategies.at(index).compare("KAZE") == 0 || - strategies.at(index).compare("AKAZE") == 0) - { - index = Settings::defaultFeature2D_2Descriptor().split(':').first().toInt(); - UERROR("Find-Object is built with OpenCV 2 so " - "KAZE/AKAZE cannot be used! Using default \"%s\" instead.", - strategies.at(index).toStdString().c_str()); - - } -#else -#ifndef HAVE_OPENCV_XFEATURES2D - if(strategies.at(index).compare("Brief") == 0 || - strategies.at(index).compare("FREAK") == 0 || - strategies.at(index).compare("LUCID") == 0 || - strategies.at(index).compare("LATCH") == 0 || - strategies.at(index).compare("DAISY") == 0) - { - index = Settings::defaultFeature2D_2Descriptor().split(':').first().toInt(); - UERROR("Find-Object is not built with OpenCV xfeatures2d module so " - "Brief/FREAK/LUCID/LATCH/DAISY cannot be used! Using default \"%s\" instead.", - strategies.at(index).toStdString().c_str()); - - } -#endif -#endif - - if(strategies.at(index).compare("Brief") == 0) - { -#if CV_MAJOR_VERSION < 3 - feature2D = new Feature2D(cv::Ptr(new cv::BriefDescriptorExtractor( - getFeature2D_Brief_bytes()))); -#else -#ifdef HAVE_OPENCV_XFEATURES2D - feature2D = new Feature2D(cv::xfeatures2d::BriefDescriptorExtractor::create( - getFeature2D_Brief_bytes())); -#else - UWARN("Find-Object is not built with OpenCV xfeatures2d module so Brief cannot be used!"); -#endif -#endif - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - else if(strategies.at(index).compare("ORB") == 0) - { - if(getFeature2D_ORB_gpu() && CVCUDA::getCudaEnabledDeviceCount()) - { - feature2D = new GPUORB( - getFeature2D_ORB_nFeatures(), - getFeature2D_ORB_scaleFactor(), - getFeature2D_ORB_nLevels(), - getFeature2D_ORB_edgeThreshold(), - getFeature2D_ORB_firstLevel(), - getFeature2D_ORB_WTA_K(), - getFeature2D_ORB_scoreType(), - getFeature2D_ORB_patchSize(), - getFeature2D_Fast_threshold(), - getFeature2D_Fast_nonmaxSuppression()); - UDEBUG("type=%s (GPU)", strategies.at(index).toStdString().c_str()); - } - else - { -#if CV_MAJOR_VERSION < 3 - feature2D = new Feature2D(cv::Ptr(new cv::ORB( - getFeature2D_ORB_nFeatures(), - getFeature2D_ORB_scaleFactor(), - getFeature2D_ORB_nLevels(), - getFeature2D_ORB_edgeThreshold(), - getFeature2D_ORB_firstLevel(), - getFeature2D_ORB_WTA_K(), - getFeature2D_ORB_scoreType(), - getFeature2D_ORB_patchSize()))); -#else - feature2D = new Feature2D(cv::ORB::create( - getFeature2D_ORB_nFeatures(), - getFeature2D_ORB_scaleFactor(), - getFeature2D_ORB_nLevels(), - getFeature2D_ORB_edgeThreshold(), - getFeature2D_ORB_firstLevel(), - getFeature2D_ORB_WTA_K(), -#if CV_MAJOR_VERSION > 3 - (cv::ORB::ScoreType)getFeature2D_ORB_scoreType(), -#else - getFeature2D_ORB_scoreType(), -#endif - getFeature2D_ORB_patchSize(), - getFeature2D_Fast_threshold())); -#endif - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - } - else if(strategies.at(index).compare("BRISK") == 0) - { -#if CV_MAJOR_VERSION < 3 - feature2D = new Feature2D(cv::Ptr(new cv::BRISK( - getFeature2D_BRISK_thresh(), - getFeature2D_BRISK_octaves(), - getFeature2D_BRISK_patternScale()))); -#else - feature2D = new Feature2D(cv::BRISK::create( - getFeature2D_BRISK_thresh(), - getFeature2D_BRISK_octaves(), - getFeature2D_BRISK_patternScale())); -#endif - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - else if(strategies.at(index).compare("KAZE") == 0) - { -#if CV_MAJOR_VERSION < 3 - UWARN("Find-Object is not built with OpenCV 3 so KAZE cannot be used!"); -#else - feature2D = new Feature2D(cv::KAZE::create( - getFeature2D_KAZE_extended(), - getFeature2D_KAZE_upright(), - getFeature2D_KAZE_threshold(), - getFeature2D_KAZE_nOctaves(), - getFeature2D_KAZE_nOctaveLayers(), - cv::KAZE::DIFF_PM_G2)); // FIXME: make a parameter -#endif - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - else if(strategies.at(index).compare("AKAZE") == 0) - { -#if CV_MAJOR_VERSION < 3 - UWARN("Find-Object is not built with OpenCV 3 so AKAZE cannot be used!"); -#else - feature2D = new Feature2D(cv::AKAZE::create( - cv::AKAZE::DESCRIPTOR_MLDB, // FIXME: make a parameter - getFeature2D_AKAZE_descriptorSize(), - getFeature2D_AKAZE_descriptorChannels(), - getFeature2D_AKAZE_threshold(), - getFeature2D_AKAZE_nOctaves(), - getFeature2D_AKAZE_nOctaveLayers(), - cv::KAZE::DIFF_PM_G2)); // FIXME: make a parameter -#endif - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - else if(strategies.at(index).compare("FREAK") == 0) - { -#if CV_MAJOR_VERSION < 3 - feature2D = new Feature2D(cv::Ptr(new cv::FREAK( - getFeature2D_FREAK_orientationNormalized(), - getFeature2D_FREAK_scaleNormalized(), - getFeature2D_FREAK_patternScale(), - getFeature2D_FREAK_nOctaves()))); -#else -#ifdef HAVE_OPENCV_XFEATURES2D - feature2D = new Feature2D(cv::xfeatures2d::FREAK::create( - getFeature2D_FREAK_orientationNormalized(), - getFeature2D_FREAK_scaleNormalized(), - getFeature2D_FREAK_patternScale(), - getFeature2D_FREAK_nOctaves())); -#else - UWARN("Find-Object is not built with OpenCV xfeatures2d module so Freak cannot be used!"); -#endif -#endif - - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } -#ifdef HAVE_OPENCV_XFEATURES2D - else if(strategies.at(index).compare("LUCID") == 0) - { - feature2D = new Feature2D(cv::xfeatures2d::LUCID::create( - getFeature2D_LUCID_kernel(), - getFeature2D_LUCID_blur_kernel())); - - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - else if(strategies.at(index).compare("LATCH") == 0) - { - feature2D = new Feature2D(cv::xfeatures2d::LATCH::create( - getFeature2D_LATCH_bytes(), - getFeature2D_LATCH_rotationInvariance(), - getFeature2D_LATCH_half_ssd_size())); - - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - else if(strategies.at(index).compare("DAISY") == 0) - { - feature2D = new Feature2D(cv::xfeatures2d::DAISY::create( - getFeature2D_DAISY_radius(), - getFeature2D_DAISY_q_radius(), - getFeature2D_DAISY_q_theta(), - getFeature2D_DAISY_q_hist(), - cv::xfeatures2d::DAISY::NRM_NONE, - cv::noArray(), - getFeature2D_DAISY_interpolation(), - getFeature2D_DAISY_use_orientation())); - - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } -#endif -#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11))) -#if FINDOBJECT_NONFREE == 1 - else if(strategies.at(index).compare("SIFT") == 0) - { -#if CV_MAJOR_VERSION < 3 - feature2D = new Feature2D(cv::Ptr(new cv::SIFT( - getFeature2D_SIFT_nfeatures(), - getFeature2D_SIFT_nOctaveLayers(), - getFeature2D_SIFT_contrastThreshold(), - getFeature2D_SIFT_edgeThreshold(), - getFeature2D_SIFT_sigma()))); -#else - feature2D = new Feature2D(cv::xfeatures2d::SIFT::create( - getFeature2D_SIFT_nfeatures(), - getFeature2D_SIFT_nOctaveLayers(), - getFeature2D_SIFT_contrastThreshold(), - getFeature2D_SIFT_edgeThreshold(), - getFeature2D_SIFT_sigma())); -#endif - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - else if(strategies.at(index).compare("SURF") == 0) - { - if(getFeature2D_SURF_gpu() && CVCUDA::getCudaEnabledDeviceCount()) - { - feature2D = new GPUSURF( - getFeature2D_SURF_hessianThreshold(), - getFeature2D_SURF_nOctaves(), - getFeature2D_SURF_nOctaveLayers(), - getFeature2D_SURF_extended(), - getFeature2D_SURF_keypointsRatio(), - getFeature2D_SURF_upright()); - UDEBUG("type=%s (GPU)", strategies.at(index).toStdString().c_str()); - } - else - { -#if CV_MAJOR_VERSION < 3 - feature2D = new Feature2D(cv::Ptr(new cv::SURF( - getFeature2D_SURF_hessianThreshold(), - getFeature2D_SURF_nOctaves(), - getFeature2D_SURF_nOctaveLayers(), - getFeature2D_SURF_extended(), - getFeature2D_SURF_upright()))); -#else - feature2D = new Feature2D(cv::xfeatures2d::SURF::create( - getFeature2D_SURF_hessianThreshold(), - getFeature2D_SURF_nOctaves(), - getFeature2D_SURF_nOctaveLayers(), - getFeature2D_SURF_extended(), - getFeature2D_SURF_upright())); -#endif - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - } -#endif -#else // >= 4.3.0-dev - else if(strategies.at(index).compare("SIFT") == 0) - { - feature2D = new Feature2D(cv::SIFT::create( - getFeature2D_SIFT_nfeatures(), - getFeature2D_SIFT_nOctaveLayers(), - getFeature2D_SIFT_contrastThreshold(), - getFeature2D_SIFT_edgeThreshold(), - getFeature2D_SIFT_sigma())); - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } -#if FINDOBJECT_NONFREE == 1 - else if(strategies.at(index).compare("SURF") == 0) - { - if(getFeature2D_SURF_gpu() && CVCUDA::getCudaEnabledDeviceCount()) - { - feature2D = new GPUSURF( - getFeature2D_SURF_hessianThreshold(), - getFeature2D_SURF_nOctaves(), - getFeature2D_SURF_nOctaveLayers(), - getFeature2D_SURF_extended(), - getFeature2D_SURF_keypointsRatio(), - getFeature2D_SURF_upright()); - UDEBUG("type=%s (GPU)", strategies.at(index).toStdString().c_str()); - } - else - { - feature2D = new Feature2D(cv::xfeatures2d::SURF::create( - getFeature2D_SURF_hessianThreshold(), - getFeature2D_SURF_nOctaves(), - getFeature2D_SURF_nOctaveLayers(), - getFeature2D_SURF_extended(), - getFeature2D_SURF_upright())); - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } - } -#endif -#endif - -#if FINDOBJECT_TORCH == 1 - else if(strategies.at(index).compare("SuperPointTorch") == 0) - { - feature2D = new SuperPointTorch( - getFeature2D_SuperPointTorch_modelPath(), - getFeature2D_SuperPointTorch_threshold(), - getFeature2D_SuperPointTorch_NMS(), - getFeature2D_SuperPointTorch_NMS_radius(), - getFeature2D_SuperPointTorch_cuda()); - UDEBUG("type=%s", strategies.at(index).toStdString().c_str()); - } -#endif - } - } - } - - return feature2D; -} - -QString Settings::currentDetectorType() -{ - int index = getFeature2D_1Detector().split(':').first().toInt(); - return getFeature2D_1Detector().split(':').last().split(';').at(index); -} - -QString Settings::currentDescriptorType() -{ - int index = getFeature2D_2Descriptor().split(':').first().toInt(); - return getFeature2D_2Descriptor().split(':').last().split(';').at(index); -} - -QString Settings::currentNearestNeighborType() -{ - int index = getNearestNeighbor_1Strategy().split(':').first().toInt(); - return getNearestNeighbor_1Strategy().split(':').last().split(';').at(index); -} - -bool Settings::isBruteForceNearestNeighbor() -{ - bool bruteForce = false; - QString str = getNearestNeighbor_1Strategy(); - QStringList split = str.split(':'); - if(split.size()==2) - { - bool ok = false; - int index = split.first().toInt(&ok); - if(ok) - { - QStringList strategies = split.last().split(';'); - if(strategies.size() >= 7 && index == 6) - { - bruteForce = true; - } - } - } - return bruteForce; -} - -cv::flann::IndexParams * Settings::createFlannIndexParams() -{ - cv::flann::IndexParams * params = 0; - QString str = getNearestNeighbor_1Strategy(); - QStringList split = str.split(':'); - if(split.size()==2) - { - bool ok = false; - int index = split.first().toInt(&ok); - if(ok) - { - QStringList strategies = split.last().split(';'); - if(strategies.size() >= 6 && index>=0 && index<6) - { - switch(index) - { - case 0: - if(strategies.at(index).compare("Linear") == 0) - { - UDEBUG("type=%s", "Linear"); - params = new cv::flann::LinearIndexParams(); - } - break; - case 1: - if(strategies.at(index).compare("KDTree") == 0) - { - UDEBUG("type=%s", "KDTree"); - params = new cv::flann::KDTreeIndexParams( - getNearestNeighbor_KDTree_trees()); - } - break; - case 2: - if(strategies.at(index).compare("KMeans") == 0) - { - cvflann::flann_centers_init_t centers_init = cvflann::FLANN_CENTERS_RANDOM; - QString str = getNearestNeighbor_KMeans_centers_init(); - QStringList split = str.split(':'); - if(split.size()==2) - { - bool ok = false; - int index = split.first().toInt(&ok); - if(ok) - { - centers_init = (cvflann::flann_centers_init_t)index; - } - } - UDEBUG("type=%s", "KMeans"); - params = new cv::flann::KMeansIndexParams( - getNearestNeighbor_KMeans_branching(), - getNearestNeighbor_KMeans_iterations(), - centers_init, - getNearestNeighbor_KMeans_cb_index()); - } - break; - case 3: - if(strategies.at(index).compare("Composite") == 0) - { - cvflann::flann_centers_init_t centers_init = cvflann::FLANN_CENTERS_RANDOM; - QString str = getNearestNeighbor_Composite_centers_init(); - QStringList split = str.split(':'); - if(split.size()==2) - { - bool ok = false; - int index = split.first().toInt(&ok); - if(ok) - { - centers_init = (cvflann::flann_centers_init_t)index; - } - } - UDEBUG("type=%s", "Composite"); - params = new cv::flann::CompositeIndexParams( - getNearestNeighbor_Composite_trees(), - getNearestNeighbor_Composite_branching(), - getNearestNeighbor_Composite_iterations(), - centers_init, - getNearestNeighbor_Composite_cb_index()); - } - break; - case 4: - if(strategies.at(index).compare("Autotuned") == 0) - { - UDEBUG("type=%s", "Autotuned"); - params = new cv::flann::AutotunedIndexParams( - getNearestNeighbor_Autotuned_target_precision(), - getNearestNeighbor_Autotuned_build_weight(), - getNearestNeighbor_Autotuned_memory_weight(), - getNearestNeighbor_Autotuned_sample_fraction()); - } - break; - case 5: - if(strategies.at(index).compare("Lsh") == 0) - { - UDEBUG("type=%s", "Lsh"); - params = new cv::flann::LshIndexParams( - getNearestNeighbor_Lsh_table_number(), - getNearestNeighbor_Lsh_key_size(), - getNearestNeighbor_Lsh_multi_probe_level()); - - } - break; - default: - break; - } - } - } - } - if(!params) - { - UERROR("NN strategy not found !? Using default KDTRee..."); - params = new cv::flann::KDTreeIndexParams(); - } - return params ; -} - -cvflann::flann_distance_t Settings::getFlannDistanceType() -{ - cvflann::flann_distance_t distance = cvflann::FLANN_DIST_L2; - QString str = getNearestNeighbor_2Distance_type(); - QStringList split = str.split(':'); - if(split.size()==2) - { - bool ok = false; - int index = split.first().toInt(&ok); - if(ok) - { - QStringList strategies = split.last().split(';'); - if(strategies.size() == 9 && index>=0 && index<=8) - { - distance = (cvflann::flann_distance_t)(index+1); - } - } - } - return distance; -} - -int Settings::getHomographyMethod() -{ - int method = cv::RANSAC; - QString str = getHomography_method(); - QStringList split = str.split(':'); - if(split.size()==2) - { - bool ok = false; - int index = split.first().toInt(&ok); - if(ok) - { - QStringList strategies = split.last().split(';'); - if(strategies.size() == 2 && index>=0 && index<2) - { - switch(method) - { -#if CV_MAJOR_VERSION >= 3 - case 2: - method = cv::RHO; - break; -#endif - case 0: - method = cv::LMEDS; - break; - default: - method = cv::RANSAC; - break; - } - } - } - } - UDEBUG("method=%d", method); - return method; -} - -#if CV_MAJOR_VERSION < 3 -Feature2D::Feature2D(cv::Ptr featureDetector) : - featureDetector_(featureDetector) -{ - UASSERT(!featureDetector_.empty()); -} -Feature2D::Feature2D(cv::Ptr descriptorExtractor) : - descriptorExtractor_(descriptorExtractor) -{ - UASSERT(!descriptorExtractor_.empty()); -} -#endif -Feature2D::Feature2D(cv::Ptr feature2D) : - feature2D_(feature2D) -{ - UASSERT(!feature2D_.empty()); -} - -void Feature2D::detect(const cv::Mat & image, - std::vector & keypoints, - const cv::Mat & mask) -{ -#if CV_MAJOR_VERSION < 3 - if(!featureDetector_.empty()) - { - featureDetector_->detect(image, keypoints, mask); - } - else -#endif - if(!feature2D_.empty()) - { - feature2D_->detect(image, keypoints, mask); - } - else - { - UERROR("Feature2D not set!?!?"); - } -} - -void Feature2D::compute(const cv::Mat & image, - std::vector & keypoints, - cv::Mat & descriptors) -{ -#if CV_MAJOR_VERSION < 3 - if(!descriptorExtractor_.empty()) - { - descriptorExtractor_->compute(image, keypoints, descriptors); - } - else -#endif - if(!feature2D_.empty()) - { - feature2D_->compute(image, keypoints, descriptors); - } - else - { - UERROR("Feature2D not set!?!?"); - } -} - -void Feature2D::detectAndCompute(const cv::Mat & image, - std::vector & keypoints, - cv::Mat & descriptors, - const cv::Mat & mask) -{ - if(!feature2D_.empty()) - { -#if CV_MAJOR_VERSION < 3 - (*feature2D_)(image, mask, keypoints, descriptors); -#else - feature2D_->detectAndCompute(image, mask, keypoints, descriptors); -#endif - } - else - { - UERROR("Cannot use Feature2D::detectAndCompute() if feature2D member is not set."); - } -} - -} // namespace find_object diff --git a/find-object/src/TcpServer.cpp b/find-object/src/TcpServer.cpp deleted file mode 100644 index a0d8bbc5..00000000 --- a/find-object/src/TcpServer.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#include "find_object/TcpServer.h" -#include "find_object/utilite/ULogger.h" - -#include -#include -#include -#include - -namespace find_object { - -TcpServer::TcpServer(quint16 port, QObject * parent) : - QTcpServer(parent) -{ - if (!this->listen(QHostAddress::Any, port)) - { - UERROR("Unable to start the TCP server: %s", this->errorString().toStdString().c_str()); - return; - } - - connect(this, SIGNAL(newConnection()), this, SLOT(addClient())); -} - -QHostAddress TcpServer::getHostAddress() const -{ - QHostAddress hostAddress; - - QList ipAddressesList = QNetworkInterface::allAddresses(); - // use the first non-localhost IPv4 address - for (int i = 0; i < ipAddressesList.size(); ++i) - { - if (ipAddressesList.at(i) != QHostAddress::LocalHost && ipAddressesList.at(i).toIPv4Address()) - { - hostAddress = ipAddressesList.at(i).toString(); - break; - } - } - - // if we did not find one, use IPv4 localhost - if (hostAddress.isNull()) - { - hostAddress = QHostAddress(QHostAddress::LocalHost); - } - - return hostAddress; -} - -quint16 TcpServer::getPort() const -{ - return this->serverPort(); -} - -void TcpServer::publishDetectionInfo(const DetectionInfo & info) -{ - QList clients = this->findChildren(); - if(clients.size()) - { - UINFO("TCP server: Publish detected objects"); - QByteArray block; - QDataStream out(&block, QIODevice::WriteOnly); - out.setVersion(QDataStream::Qt_4_0); - out << (quint16)0; - - out << info; - - out.device()->seek(0); - out << (quint16)(block.size() - sizeof(quint16)); - - for(QList::iterator iter = clients.begin(); iter!=clients.end(); ++iter) - { - (*iter)->write(block); - } - } -} - -void TcpServer::addClient() -{ - while(this->hasPendingConnections()) - { - QTcpSocket * client = this->nextPendingConnection(); - connect(client, SIGNAL(readyRead()), this, SLOT(readReceivedData())); - connect(client, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError))); - connect(client, SIGNAL(disconnected()), this, SLOT(connectionLost())); - } -} - -void TcpServer::readReceivedData() -{ - QTcpSocket * client = (QTcpSocket*)sender(); - QDataStream in(client); - in.setVersion(QDataStream::Qt_4_0); - - if (blockSizes_.value(client->socketDescriptor(), 0) == 0) - { - if (client->bytesAvailable() < (int)sizeof(quint64)) - { - return; - } - - in >> blockSizes_[client->socketDescriptor()]; - } - - if (client->bytesAvailable() < (int)blockSizes_[client->socketDescriptor()]) - { - return; - } - - quint32 serviceType; - in >> serviceType; - - bool ok = true; - if(serviceType == kAddObject) - { - int id; - in >> id; - QString fileName; - in >> fileName; - quint64 imageSize; - in >> imageSize; - std::vector buf(imageSize); - in.readRawData((char*)buf.data(), imageSize); - cv::Mat image = cv::imdecode(buf, cv::IMREAD_UNCHANGED); - - UINFO("TCP service: Add %d \"%s\"", id, fileName.toStdString().c_str()); - Q_EMIT addObject(image, id, fileName); - } - else if(serviceType == kRemoveObject) - { - int id; - in >> id; - - UINFO("TCP service: Remove %d", id); - Q_EMIT removeObject(id); - } - else if(serviceType == kDetectObject) - { - std::vector buf(blockSizes_[client->socketDescriptor()]); - in.readRawData((char*)buf.data(), blockSizes_[client->socketDescriptor()]-sizeof(quint32)); - cv::Mat image = cv::imdecode(buf, cv::IMREAD_UNCHANGED); - - UINFO("TCP service: Detect object"); - Q_EMIT detectObject(image); - } - else - { - UERROR("Unknown service type called %d", serviceType); - ok = false; - } - - blockSizes_.remove(client->socketDescriptor()); - client->write(QByteArray(ok?"1":"0")); // send acknowledge -} - -void TcpServer::displayError(QAbstractSocket::SocketError socketError) -{ - switch (socketError) - { - case QAbstractSocket::RemoteHostClosedError: - break; - case QAbstractSocket::HostNotFoundError: - UWARN("CameraTcp: Tcp error: The host was not found. Please " - "check the host name and port settings.\n"); - break; - case QAbstractSocket::ConnectionRefusedError: - UWARN("CameraTcp: The connection was refused by the peer. " - "Make sure your images server is running, " - "and check that the host name and port " - "settings are correct."); - break; - default: - //UERROR("The following error occurred: %s.", this->errorString().toStdString().c_str()); - break; - } -} - -void TcpServer::connectionLost() -{ - //printf("[WARNING] CameraTcp: Connection lost!\n"); - blockSizes_.remove(((QTcpSocket*)sender())->socketDescriptor()); - ((QTcpSocket*)sender())->close(); - sender()->deleteLater(); -} - -} // namespace find_object diff --git a/find-object/src/Vocabulary.cpp b/find-object/src/Vocabulary.cpp deleted file mode 100644 index 803b5551..00000000 --- a/find-object/src/Vocabulary.cpp +++ /dev/null @@ -1,534 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "find_object/Settings.h" - -#include "find_object/utilite/ULogger.h" -#include "Compression.h" -#include "Vocabulary.h" -#include -#include -#include -#include -#if CV_MAJOR_VERSION < 3 -#include -#define CVCUDA cv::gpu -#else -#include -#define CVCUDA cv::cuda -#ifdef HAVE_OPENCV_CUDAFEATURES2D -#include -#endif -#endif - -namespace find_object { - -Vocabulary::Vocabulary() -{ -} - -Vocabulary::~Vocabulary() -{ -} - -void Vocabulary::clear() -{ - wordToObjects_.clear(); - notIndexedDescriptors_ = cv::Mat(); - notIndexedWordIds_.clear(); - - if(Settings::getGeneral_vocabularyFixed() && Settings::getGeneral_invertedSearch()) - { - this->update(); // if vocabulary structure has changed - - // If the dictionary is fixed, don't clear indexed descriptors - return; - } - - indexedDescriptors_ = cv::Mat(); -} - -void Vocabulary::save(QDataStream & streamSessionPtr, bool saveVocabularyOnly) const -{ - // save index - if(saveVocabularyOnly) - { - QMultiMap dummy; - streamSessionPtr << dummy; - } - else - { - UINFO("Saving %d object references...", wordToObjects_.size()); - streamSessionPtr << wordToObjects_; - } - - // save words - qint64 rawDataSize = indexedDescriptors_.rows * indexedDescriptors_.cols * indexedDescriptors_.elemSize(); - UINFO("Compressing words... (%dx%d, %d MB)", indexedDescriptors_.rows, indexedDescriptors_.cols, rawDataSize/(1024*1024)); - std::vector bytes = compressData(indexedDescriptors_); - qint64 dataSize = bytes.size(); - UINFO("Compressed = %d MB", dataSize/(1024*1024)); - int old = 0; - if(dataSize <= std::numeric_limits::max()) - { - // old: rows, cols, type - streamSessionPtr << old << old << old << dataSize; - streamSessionPtr << QByteArray::fromRawData((const char*)bytes.data(), dataSize); - } - else - { - UERROR("Vocabulary (compressed) is too large (%d MB) to be saved! Limit is 2 GB (based on max QByteArray size).", - dataSize/(1024*1024)); - // old: rows, cols, type, dataSize - streamSessionPtr << old << old << old << old; - streamSessionPtr << QByteArray(); // empty - } -} - -void Vocabulary::load(QDataStream & streamSessionPtr, bool loadVocabularyOnly) -{ - // load index - if(loadVocabularyOnly) - { - QMultiMap dummy; - streamSessionPtr >> dummy; - // clear index - wordToObjects_.clear(); - } - else - { - UINFO("Loading words to objects references..."); - streamSessionPtr >> wordToObjects_; - UINFO("Loaded %d object references...", wordToObjects_.size()); - } - - // load words - int rows,cols,type; - qint64 dataSize; - streamSessionPtr >> rows >> cols >> type >> dataSize; - if(rows == 0 && cols == 0 && type == 0) - { - // compressed vocabulary - UINFO("Loading words... (compressed format: %d MB)", dataSize/(1024*1024)); - UASSERT(dataSize <= std::numeric_limits::max()); - QByteArray data; - streamSessionPtr >> data; - UINFO("Uncompress vocabulary..."); - indexedDescriptors_ = uncompressData((unsigned const char*)data.data(), dataSize); - UINFO("Words: %dx%d (%d MB)", indexedDescriptors_.rows, indexedDescriptors_.cols, - (indexedDescriptors_.rows * indexedDescriptors_.cols * indexedDescriptors_.elemSize()) / (1024*1024)); - } - else - { - // old raw format - UINFO("Loading words... (old format: %dx%d (%d MB))", rows, cols, dataSize/(1024*1024)); - QByteArray data; - streamSessionPtr >> data; - UINFO("Allocate memory..."); - if(data.size()) - { - indexedDescriptors_ = cv::Mat(rows, cols, type, data.data()).clone(); - } - else if(dataSize) - { - UERROR("Error reading vocabulary data..."); - } - } - - UINFO("Update vocabulary index..."); - update(); -} - -bool Vocabulary::save(const QString & filename) const -{ - // save descriptors - cv::FileStorage fs(filename.toStdString(), cv::FileStorage::WRITE); - if(fs.isOpened()) - { - fs << "Descriptors" << indexedDescriptors_; - return true; - } - else - { - UERROR("Failed to open vocabulary file \"%s\"", filename.toStdString().c_str()); - } - return false; -} - -bool Vocabulary::load(const QString & filename) -{ - // save descriptors - cv::FileStorage fs(filename.toStdString(), cv::FileStorage::READ); - if(fs.isOpened()) - { - cv::Mat tmp; - fs["Descriptors"] >> tmp; - - if(!tmp.empty()) - { - // clear index - wordToObjects_.clear(); - indexedDescriptors_ = tmp; - update(); - return true; - } - else - { - UERROR("Failed to read \"Descriptors\" matrix field (doesn't exist or is empty) from vocabulary file \"%s\"", filename.toStdString().c_str()); - } - } - else - { - UERROR("Failed to open vocabulary file \"%s\"", filename.toStdString().c_str()); - } - return false; -} - -QMultiMap Vocabulary::addWords(const cv::Mat & descriptorsIn, int objectId) -{ - QMultiMap words; - if (descriptorsIn.empty()) - { - return words; - } - - cv::Mat descriptors; - if(descriptorsIn.type() == CV_8U && Settings::getNearestNeighbor_7ConvertBinToFloat()) - { - descriptorsIn.convertTo(descriptors, CV_32F); - } - else - { - descriptors = descriptorsIn; - } - - if(Settings::getGeneral_vocabularyIncremental() || Settings::getGeneral_vocabularyFixed()) - { - int k = 2; - cv::Mat results; - cv::Mat dists; - - bool globalSearch = false; - if(!indexedDescriptors_.empty() && indexedDescriptors_.rows >= (int)k) - { - if(indexedDescriptors_.type() != descriptors.type() || indexedDescriptors_.cols != descriptors.cols) - { - if(Settings::getGeneral_vocabularyFixed()) - { - UERROR("Descriptors (type=%d size=%d) to search in vocabulary are not the same type/size as those in the vocabulary (type=%d size=%d)! Empty words returned.", - descriptors.type(), descriptors.cols, indexedDescriptors_.type(), indexedDescriptors_.cols); - return words; - } - else - { - UFATAL("Descriptors (type=%d size=%d) to search in vocabulary are not the same type/size as those in the vocabulary (type=%d size=%d)!", - descriptors.type(), descriptors.cols, indexedDescriptors_.type(), indexedDescriptors_.cols); - } - } - - this->search(descriptors, results, dists, k); - - if( dists.type() == CV_32S ) - { - cv::Mat temp; - dists.convertTo(temp, CV_32F); - dists = temp; - } - - globalSearch = true; - } - - if(!Settings::getGeneral_vocabularyFixed()) - { - notIndexedWordIds_.reserve(notIndexedWordIds_.size() + descriptors.rows); - notIndexedDescriptors_.reserve(notIndexedDescriptors_.rows + descriptors.rows); - } - int matches = 0; - for(int i = 0; i < descriptors.rows; ++i) - { - QMultiMap fullResults; // nearest descriptors sorted by distance - if(notIndexedDescriptors_.rows) - { - UASSERT(notIndexedDescriptors_.type() == descriptors.type() && notIndexedDescriptors_.cols == descriptors.cols); - - // Check if this descriptor matches with a word not already added to the vocabulary - // Do linear search only - cv::Mat tmpResults; - cv::Mat tmpDists; - if(descriptors.type()==CV_8U) - { - //normType – One of NORM_L1, NORM_L2, NORM_HAMMING, NORM_HAMMING2. L1 and L2 norms are - // preferable choices for SIFT and SURF descriptors, NORM_HAMMING should be - // used with ORB, BRISK and BRIEF, NORM_HAMMING2 should be used with ORB - // when WTA_K==3 or 4 (see ORB::ORB constructor description). - int normType = cv::NORM_HAMMING; - if(Settings::currentDescriptorType().compare("ORB") && - (Settings::getFeature2D_ORB_WTA_K()==3 || Settings::getFeature2D_ORB_WTA_K()==4)) - { - normType = cv::NORM_HAMMING2; - } - - cv::batchDistance( descriptors.row(i), - notIndexedDescriptors_, - tmpDists, - CV_32S, - tmpResults, - normType, - notIndexedDescriptors_.rows>=k?k:1, - cv::Mat(), - 0, - false); - } - else - { - cv::flann::Index tmpIndex; -#if CV_MAJOR_VERSION == 2 and CV_MINOR_VERSION == 4 and CV_SUBMINOR_VERSION >= 12 - tmpIndex.build(notIndexedDescriptors_, cv::Mat(), cv::flann::LinearIndexParams(), cvflann::FLANN_DIST_L2); -#else - tmpIndex.build(notIndexedDescriptors_, cv::flann::LinearIndexParams(), cvflann::FLANN_DIST_L2); -#endif - tmpIndex.knnSearch(descriptors.row(i), tmpResults, tmpDists, notIndexedDescriptors_.rows>1?k:1, cvflann::FLANN_DIST_L2); - } - - if( tmpDists.type() == CV_32S ) - { - cv::Mat temp; - tmpDists.convertTo(temp, CV_32F); - tmpDists = temp; - } - - for(int j = 0; j < tmpResults.cols; ++j) - { - if(tmpResults.at(0,j) >= 0) - { - //printf("local i=%d, j=%d, tmpDist=%f tmpResult=%d\n", i ,j, tmpDists.at(0,j), tmpResults.at(0,j)); - fullResults.insert(tmpDists.at(0,j), notIndexedWordIds_.at(tmpResults.at(0,j))); - } - } - } - - if(globalSearch) - { - for(int j=0; j(i,j) >= 0) - { - //printf("global i=%d, j=%d, dist=%f\n", i ,j, dists.at(i,j)); - fullResults.insert(dists.at(i,j), results.at(i,j)); - } - } - } - - bool matched = false; - if(Settings::getNearestNeighbor_3nndrRatioUsed() && - fullResults.size() >= 2 && - fullResults.begin().key() <= Settings::getNearestNeighbor_4nndrRatio() * (++fullResults.begin()).key()) - { - matched = true; - } - if((matched || !Settings::getNearestNeighbor_3nndrRatioUsed()) && - Settings::getNearestNeighbor_5minDistanceUsed()) - { - if(fullResults.begin().key() <= Settings::getNearestNeighbor_6minDistance()) - { - matched = true; - } - else - { - matched = false; - } - } - if(!matched && !Settings::getNearestNeighbor_3nndrRatioUsed() && !Settings::getNearestNeighbor_5minDistanceUsed()) - { - matched = true; // no criterion, match to the nearest descriptor - } - - if(matched) - { - words.insert(fullResults.begin().value(), i); - wordToObjects_.insert(fullResults.begin().value(), objectId); - ++matches; - } - else if(!Settings::getGeneral_invertedSearch() || !Settings::getGeneral_vocabularyFixed()) - { - //concatenate new words - notIndexedWordIds_.push_back(indexedDescriptors_.rows + notIndexedDescriptors_.rows); - notIndexedDescriptors_.push_back(descriptors.row(i)); - words.insert(notIndexedWordIds_.back(), i); - wordToObjects_.insert(notIndexedWordIds_.back(), objectId); - } - else - { - words.insert(-1, i); // invalid word - } - } - } - else - { - for(int i = 0; i < descriptors.rows; ++i) - { - wordToObjects_.insert(indexedDescriptors_.rows + notIndexedDescriptors_.rows+i, objectId); - words.insert(indexedDescriptors_.rows + notIndexedDescriptors_.rows+i, i); - notIndexedWordIds_.push_back(indexedDescriptors_.rows + notIndexedDescriptors_.rows+i); - } - - //just concatenate descriptors - notIndexedDescriptors_.push_back(descriptors); - } - return words; -} - -void Vocabulary::update() -{ - if(!notIndexedDescriptors_.empty()) - { - if(!indexedDescriptors_.empty()) - { - UASSERT(indexedDescriptors_.cols == notIndexedDescriptors_.cols && - indexedDescriptors_.type() == notIndexedDescriptors_.type() ); - } - - //concatenate descriptors - indexedDescriptors_.push_back(notIndexedDescriptors_); - - notIndexedDescriptors_ = cv::Mat(); - notIndexedWordIds_.clear(); - } - - if(!indexedDescriptors_.empty() && !Settings::isBruteForceNearestNeighbor()) - { - cv::flann::IndexParams * params = Settings::createFlannIndexParams(); -#if CV_MAJOR_VERSION == 2 and CV_MINOR_VERSION == 4 and CV_SUBMINOR_VERSION >= 12 - flannIndex_.build(indexedDescriptors_, cv::Mat(), *params, Settings::getFlannDistanceType()); -#else - flannIndex_.build(indexedDescriptors_, *params, Settings::getFlannDistanceType()); -#endif - delete params; - } -} - -void Vocabulary::search(const cv::Mat & descriptorsIn, cv::Mat & results, cv::Mat & dists, int k) -{ - if(!indexedDescriptors_.empty()) - { - cv::Mat descriptors; - if(descriptorsIn.type() == CV_8U && Settings::getNearestNeighbor_7ConvertBinToFloat()) - { - descriptorsIn.convertTo(descriptors, CV_32F); - } - else - { - descriptors = descriptorsIn; - } - - UASSERT(descriptors.type() == indexedDescriptors_.type() && descriptors.cols == indexedDescriptors_.cols); - - if(Settings::isBruteForceNearestNeighbor()) - { - std::vector > matches; - bool isL2NotSqr = false; - if(Settings::getNearestNeighbor_BruteForce_gpu() && CVCUDA::getCudaEnabledDeviceCount()) - { - CVCUDA::GpuMat newDescriptorsGpu(descriptors); - CVCUDA::GpuMat lastDescriptorsGpu(indexedDescriptors_); -#if CV_MAJOR_VERSION < 3 - if(indexedDescriptors_.type()==CV_8U) - { - CVCUDA::BruteForceMatcher_GPU gpuMatcher; - gpuMatcher.knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k); - } - else - { - CVCUDA::BruteForceMatcher_GPU > gpuMatcher; - gpuMatcher.knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k); - isL2NotSqr = true; - } -#else -#ifdef HAVE_OPENCV_CUDAFEATURES2D - cv::Ptr gpuMatcher; - if(indexedDescriptors_.type()==CV_8U) - { - gpuMatcher = cv::cuda::DescriptorMatcher::createBFMatcher(cv::NORM_HAMMING); - gpuMatcher->knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k); - } - else - { - gpuMatcher = cv::cuda::DescriptorMatcher::createBFMatcher(cv::NORM_L2); - gpuMatcher->knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k); - isL2NotSqr = true; - } -#else - UERROR("OpenCV3 is not built with CUDAFEATURES2D module, cannot do brute force matching on GPU!"); -#endif -#endif - } - else - { - cv::BFMatcher matcher(indexedDescriptors_.type()==CV_8U?cv::NORM_HAMMING:cv::NORM_L2SQR); - matcher.knnMatch(descriptors, indexedDescriptors_, matches, k); - } - - //convert back to matrix style - results = cv::Mat((int)matches.size(), k, CV_32SC1); - dists = cv::Mat((int)matches.size(), k, CV_32FC1); - for(unsigned int i=0; i(i, j) = matches[i].at(j).trainIdx; - - if(isL2NotSqr) - { - // Make sure we use L2SQR to match FLANN - dists.at(i, j) = matches[i].at(j).distance*matches[i].at(j).distance; - } - else - { - dists.at(i, j) = matches[i].at(j).distance; - } - } - } - } - else - { - flannIndex_.knnSearch(descriptors, results, dists, k, - cv::flann::SearchParams( - Settings::getNearestNeighbor_search_checks(), - Settings::getNearestNeighbor_search_eps(), - Settings::getNearestNeighbor_search_sorted())); - } - - if( dists.type() == CV_32S ) - { - cv::Mat temp; - dists.convertTo(temp, CV_32F); - dists = temp; - } - } -} - -} // namespace find_object diff --git a/find-object/src/Vocabulary.h b/find-object/src/Vocabulary.h deleted file mode 100644 index 948e2bf1..00000000 --- a/find-object/src/Vocabulary.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef VOCABULARY_H_ -#define VOCABULARY_H_ - -#include -#include -#include - -namespace find_object { - -class Vocabulary { -public: - Vocabulary(); - virtual ~Vocabulary(); - - void clear(); - QMultiMap addWords(const cv::Mat & descriptors, int objectId); - void update(); - void search(const cv::Mat & descriptors, cv::Mat & results, cv::Mat & dists, int k); - int size() const {return indexedDescriptors_.rows + notIndexedDescriptors_.rows;} - int dim() const {return !indexedDescriptors_.empty()?indexedDescriptors_.cols:notIndexedDescriptors_.cols;} - int type() const {return !indexedDescriptors_.empty()?indexedDescriptors_.type():notIndexedDescriptors_.type();} - const QMultiMap & wordToObjects() const {return wordToObjects_;} - const cv::Mat & indexedDescriptors() const {return indexedDescriptors_;} - - void save(QDataStream & streamSessionPtr, bool saveVocabularyOnly = false) const; - void load(QDataStream & streamSessionPtr, bool loadVocabularyOnly = false); - bool save(const QString & filename) const; - bool load(const QString & filename); - -private: - cv::flann::Index flannIndex_; - cv::Mat indexedDescriptors_; - cv::Mat notIndexedDescriptors_; - QMultiMap wordToObjects_; // - QVector notIndexedWordIds_; -}; - -} // namespace find_object - -#endif /* VOCABULARY_H_ */ diff --git a/find-object/src/json/json-forwards.h b/find-object/src/json/json-forwards.h deleted file mode 100644 index 7bdab51b..00000000 --- a/find-object/src/json/json-forwards.h +++ /dev/null @@ -1,249 +0,0 @@ -/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/). -/// It is intented to be used with #include -/// This header provides forward declaration for all JsonCpp types. - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - -/* -The JsonCpp library's source code, including accompanying documentation, -tests and demonstration applications, are licensed under the following -conditions... - -The author (Baptiste Lepilleur) explicitly disclaims copyright in all -jurisdictions which recognize such a disclaimer. In such jurisdictions, -this software is released into the Public Domain. - -In jurisdictions which do not recognize Public Domain property (e.g. Germany as of -2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is -released under the terms of the MIT License (see below). - -In jurisdictions which recognize Public Domain property, the user of this -software may choose to accept it either as 1) Public Domain, 2) under the -conditions of the MIT License (see below), or 3) under the terms of dual -Public Domain/MIT License conditions described here, as they choose. - -The MIT License is about as close to Public Domain as a license can get, and is -described in clear, concise terms at: - - http://en.wikipedia.org/wiki/MIT_License - -The full text of the MIT License follows: - -======================================================================== -Copyright (c) 2007-2010 Baptiste Lepilleur - -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. -======================================================================== -(END LICENSE TEXT) - -The MIT license is compatible with both the GPL and commercial -software, affording one all of the rights of Public Domain with the -minor nuisance of being required to keep the above copyright notice -and license text in the source code. Note also that by accepting the -Public Domain "license" you can re-license your copy using whatever -license you like. - -*/ - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - - - - - -#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED -# define JSON_FORWARD_AMALGATED_H_INCLUDED -/// If defined, indicates that the source file is amalgated -/// to prevent private header inclusion. -#define JSON_IS_AMALGATED - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_CONFIG_H_INCLUDED -# define JSON_CONFIG_H_INCLUDED - -/// If defined, indicates that json library is embedded in CppTL library. -//# define JSON_IN_CPPTL 1 - -/// If defined, indicates that json may leverage CppTL library -//# define JSON_USE_CPPTL 1 -/// If defined, indicates that cpptl vector based map should be used instead of std::map -/// as Value container. -//# define JSON_USE_CPPTL_SMALLMAP 1 -/// If defined, indicates that Json specific container should be used -/// (hash table & simple deque container with customizable allocator). -/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332 -//# define JSON_VALUE_USE_INTERNAL_MAP 1 -/// Force usage of standard new/malloc based allocator instead of memory pool based allocator. -/// The memory pools allocator used optimization (initializing Value and ValueInternalLink -/// as if it was a POD) that may cause some validation tool to report errors. -/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined. -//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1 - -/// If defined, indicates that Json use exception to report invalid type manipulation -/// instead of C assert macro. -# define JSON_USE_EXCEPTION 1 - -/// If defined, indicates that the source file is amalgated -/// to prevent private header inclusion. -/// Remarks: it is automatically defined in the generated amalgated header. -#define JSON_IS_AMALGAMATION - - -# ifdef JSON_IN_CPPTL -# include -# ifndef JSON_USE_CPPTL -# define JSON_USE_CPPTL 1 -# endif -# endif - -# ifdef JSON_IN_CPPTL -# define JSON_API CPPTL_API -# elif defined(JSON_DLL_BUILD) -# define JSON_API __declspec(dllexport) -# elif defined(JSON_DLL) -# define JSON_API __declspec(dllimport) -# else -# define JSON_API -# endif - -// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for integer -// Storages, and 64 bits integer support is disabled. -// #define JSON_NO_INT64 1 - -#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 -// Microsoft Visual Studio 6 only support conversion from __int64 to double -// (no conversion from unsigned __int64). -#define JSON_USE_INT64_DOUBLE_CONVERSION 1 -#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 - -#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 -/// Indicates that the following function is deprecated. -# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) -#endif - -#if !defined(JSONCPP_DEPRECATED) -# define JSONCPP_DEPRECATED(message) -#endif // if !defined(JSONCPP_DEPRECATED) - -namespace Json { - typedef int Int; - typedef unsigned int UInt; -# if defined(JSON_NO_INT64) - typedef int LargestInt; - typedef unsigned int LargestUInt; -# undef JSON_HAS_INT64 -# else // if defined(JSON_NO_INT64) - // For Microsoft Visual use specific types as long long is not supported -# if defined(_MSC_VER) // Microsoft Visual Studio - typedef __int64 Int64; - typedef unsigned __int64 UInt64; -# else // if defined(_MSC_VER) // Other platforms, use long long - typedef long long int Int64; - typedef unsigned long long int UInt64; -# endif // if defined(_MSC_VER) - typedef Int64 LargestInt; - typedef UInt64 LargestUInt; -# define JSON_HAS_INT64 -# endif // if defined(JSON_NO_INT64) -} // end namespace Json - - -#endif // JSON_CONFIG_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_FORWARDS_H_INCLUDED -# define JSON_FORWARDS_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -# include "config.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - - // writer.h - class FastWriter; - class StyledWriter; - - // reader.h - class Reader; - - // features.h - class Features; - - // value.h - typedef unsigned int ArrayIndex; - class StaticString; - class Path; - class PathArgument; - class Value; - class ValueIteratorBase; - class ValueIterator; - class ValueConstIterator; -#ifdef JSON_VALUE_USE_INTERNAL_MAP - class ValueMapAllocator; - class ValueInternalLink; - class ValueInternalArray; - class ValueInternalMap; -#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP - -} // namespace Json - - -#endif // JSON_FORWARDS_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - - - - - -#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED diff --git a/find-object/src/json/json.h b/find-object/src/json/json.h deleted file mode 100644 index 00583210..00000000 --- a/find-object/src/json/json.h +++ /dev/null @@ -1,1855 +0,0 @@ -/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/). -/// It is intented to be used with #include - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - -/* -The JsonCpp library's source code, including accompanying documentation, -tests and demonstration applications, are licensed under the following -conditions... - -The author (Baptiste Lepilleur) explicitly disclaims copyright in all -jurisdictions which recognize such a disclaimer. In such jurisdictions, -this software is released into the Public Domain. - -In jurisdictions which do not recognize Public Domain property (e.g. Germany as of -2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is -released under the terms of the MIT License (see below). - -In jurisdictions which recognize Public Domain property, the user of this -software may choose to accept it either as 1) Public Domain, 2) under the -conditions of the MIT License (see below), or 3) under the terms of dual -Public Domain/MIT License conditions described here, as they choose. - -The MIT License is about as close to Public Domain as a license can get, and is -described in clear, concise terms at: - - http://en.wikipedia.org/wiki/MIT_License - -The full text of the MIT License follows: - -======================================================================== -Copyright (c) 2007-2010 Baptiste Lepilleur - -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. -======================================================================== -(END LICENSE TEXT) - -The MIT license is compatible with both the GPL and commercial -software, affording one all of the rights of Public Domain with the -minor nuisance of being required to keep the above copyright notice -and license text in the source code. Note also that by accepting the -Public Domain "license" you can re-license your copy using whatever -license you like. - -*/ - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - - - - - -#ifndef JSON_AMALGATED_H_INCLUDED -# define JSON_AMALGATED_H_INCLUDED -/// If defined, indicates that the source file is amalgated -/// to prevent private header inclusion. -#define JSON_IS_AMALGATED - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_CONFIG_H_INCLUDED -# define JSON_CONFIG_H_INCLUDED - -/// If defined, indicates that json library is embedded in CppTL library. -//# define JSON_IN_CPPTL 1 - -/// If defined, indicates that json may leverage CppTL library -//# define JSON_USE_CPPTL 1 -/// If defined, indicates that cpptl vector based map should be used instead of std::map -/// as Value container. -//# define JSON_USE_CPPTL_SMALLMAP 1 -/// If defined, indicates that Json specific container should be used -/// (hash table & simple deque container with customizable allocator). -/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332 -//# define JSON_VALUE_USE_INTERNAL_MAP 1 -/// Force usage of standard new/malloc based allocator instead of memory pool based allocator. -/// The memory pools allocator used optimization (initializing Value and ValueInternalLink -/// as if it was a POD) that may cause some validation tool to report errors. -/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined. -//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1 - -/// If defined, indicates that Json use exception to report invalid type manipulation -/// instead of C assert macro. -# define JSON_USE_EXCEPTION 1 - -/// If defined, indicates that the source file is amalgated -/// to prevent private header inclusion. -/// Remarks: it is automatically defined in the generated amalgated header. -#define JSON_IS_AMALGAMATION - - -# ifdef JSON_IN_CPPTL -# include -# ifndef JSON_USE_CPPTL -# define JSON_USE_CPPTL 1 -# endif -# endif - -# ifdef JSON_IN_CPPTL -# define JSON_API CPPTL_API -# elif defined(JSON_DLL_BUILD) -# define JSON_API __declspec(dllexport) -# elif defined(JSON_DLL) -# define JSON_API __declspec(dllimport) -# else -# define JSON_API -# endif - -// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for integer -// Storages, and 64 bits integer support is disabled. -// #define JSON_NO_INT64 1 - -#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 -// Microsoft Visual Studio 6 only support conversion from __int64 to double -// (no conversion from unsigned __int64). -#define JSON_USE_INT64_DOUBLE_CONVERSION 1 -#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 - -#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 -/// Indicates that the following function is deprecated. -# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) -#endif - -#if !defined(JSONCPP_DEPRECATED) -# define JSONCPP_DEPRECATED(message) -#endif // if !defined(JSONCPP_DEPRECATED) - -namespace Json { - typedef int Int; - typedef unsigned int UInt; -# if defined(JSON_NO_INT64) - typedef int LargestInt; - typedef unsigned int LargestUInt; -# undef JSON_HAS_INT64 -# else // if defined(JSON_NO_INT64) - // For Microsoft Visual use specific types as long long is not supported -# if defined(_MSC_VER) // Microsoft Visual Studio - typedef __int64 Int64; - typedef unsigned __int64 UInt64; -# else // if defined(_MSC_VER) // Other platforms, use long long - typedef long long int Int64; - typedef unsigned long long int UInt64; -# endif // if defined(_MSC_VER) - typedef Int64 LargestInt; - typedef UInt64 LargestUInt; -# define JSON_HAS_INT64 -# endif // if defined(JSON_NO_INT64) -} // end namespace Json - - -#endif // JSON_CONFIG_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_FORWARDS_H_INCLUDED -# define JSON_FORWARDS_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -# include "config.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - - // writer.h - class FastWriter; - class StyledWriter; - - // reader.h - class Reader; - - // features.h - class Features; - - // value.h - typedef unsigned int ArrayIndex; - class StaticString; - class Path; - class PathArgument; - class Value; - class ValueIteratorBase; - class ValueIterator; - class ValueConstIterator; -#ifdef JSON_VALUE_USE_INTERNAL_MAP - class ValueMapAllocator; - class ValueInternalLink; - class ValueInternalArray; - class ValueInternalMap; -#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP - -} // namespace Json - - -#endif // JSON_FORWARDS_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/features.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_FEATURES_H_INCLUDED -# define CPPTL_JSON_FEATURES_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -# include "forwards.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - - /** \brief Configuration passed to reader and writer. - * This configuration object can be used to force the Reader or Writer - * to behave in a standard conforming way. - */ - class JSON_API Features - { - public: - /** \brief A configuration that allows all features and assumes all strings are UTF-8. - * - C & C++ comments are allowed - * - Root object can be any JSON value - * - Assumes Value strings are encoded in UTF-8 - */ - static Features all(); - - /** \brief A configuration that is strictly compatible with the JSON specification. - * - Comments are forbidden. - * - Root object must be either an array or an object value. - * - Assumes Value strings are encoded in UTF-8 - */ - static Features strictMode(); - - /** \brief Initialize the configuration like JsonConfig::allFeatures; - */ - Features(); - - /// \c true if comments are allowed. Default: \c true. - bool allowComments_; - - /// \c true if root must be either an array or an object value. Default: \c false. - bool strictRoot_; - }; - -} // namespace Json - -#endif // CPPTL_JSON_FEATURES_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/features.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/value.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_H_INCLUDED -# define CPPTL_JSON_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -# include "forwards.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -# include -# include - -# ifndef JSON_USE_CPPTL_SMALLMAP -# include -# else -# include -# endif -# ifdef JSON_USE_CPPTL -# include -# endif - -/** \brief JSON (JavaScript Object Notation). - */ -namespace Json { - - /** \brief Type of the value held by a Value object. - */ - enum ValueType - { - nullValue = 0, ///< 'null' value - intValue, ///< signed integer value - uintValue, ///< unsigned integer value - realValue, ///< double value - stringValue, ///< UTF-8 string value - booleanValue, ///< bool value - arrayValue, ///< array value (ordered list) - objectValue ///< object value (collection of name/value pairs). - }; - - enum CommentPlacement - { - commentBefore = 0, ///< a comment placed on the line before a value - commentAfterOnSameLine, ///< a comment just after a value on the same line - commentAfter, ///< a comment on the line after a value (only make sense for root value) - numberOfCommentPlacement - }; - -//# ifdef JSON_USE_CPPTL -// typedef CppTL::AnyEnumerator EnumMemberNames; -// typedef CppTL::AnyEnumerator EnumValues; -//# endif - - /** \brief Lightweight wrapper to tag static string. - * - * Value constructor and objectValue member assignement takes advantage of the - * StaticString and avoid the cost of string duplication when storing the - * string or the member name. - * - * Example of usage: - * \code - * Json::Value aValue( StaticString("some text") ); - * Json::Value object; - * static const StaticString code("code"); - * object[code] = 1234; - * \endcode - */ - class JSON_API StaticString - { - public: - explicit StaticString( const char *czstring ) - : str_( czstring ) - { - } - - operator const char *() const - { - return str_; - } - - const char *c_str() const - { - return str_; - } - - private: - const char *str_; - }; - - /** \brief Represents a JSON value. - * - * This class is a discriminated union wrapper that can represents a: - * - signed integer [range: Value::minInt - Value::maxInt] - * - unsigned integer (range: 0 - Value::maxUInt) - * - double - * - UTF-8 string - * - boolean - * - 'null' - * - an ordered list of Value - * - collection of name/value pairs (javascript object) - * - * The type of the held value is represented by a #ValueType and - * can be obtained using type(). - * - * values of an #objectValue or #arrayValue can be accessed using operator[]() methods. - * Non const methods will automatically create the a #nullValue element - * if it does not exist. - * The sequence of an #arrayValue will be automatically resize and initialized - * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. - * - * The get() methods can be used to obtanis default value in the case the required element - * does not exist. - * - * It is possible to iterate over the list of a #objectValue values using - * the getMemberNames() method. - */ - class JSON_API Value - { - friend class ValueIteratorBase; -# ifdef JSON_VALUE_USE_INTERNAL_MAP - friend class ValueInternalLink; - friend class ValueInternalMap; -# endif - public: - typedef std::vector Members; - typedef ValueIterator iterator; - typedef ValueConstIterator const_iterator; - typedef Json::UInt UInt; - typedef Json::Int Int; -# if defined(JSON_HAS_INT64) - typedef Json::UInt64 UInt64; - typedef Json::Int64 Int64; -#endif // defined(JSON_HAS_INT64) - typedef Json::LargestInt LargestInt; - typedef Json::LargestUInt LargestUInt; - typedef Json::ArrayIndex ArrayIndex; - - static const Value null; - /// Minimum signed integer value that can be stored in a Json::Value. - static const LargestInt minLargestInt; - /// Maximum signed integer value that can be stored in a Json::Value. - static const LargestInt maxLargestInt; - /// Maximum unsigned integer value that can be stored in a Json::Value. - static const LargestUInt maxLargestUInt; - - /// Minimum signed int value that can be stored in a Json::Value. - static const Int minInt; - /// Maximum signed int value that can be stored in a Json::Value. - static const Int maxInt; - /// Maximum unsigned int value that can be stored in a Json::Value. - static const UInt maxUInt; - - /// Minimum signed 64 bits int value that can be stored in a Json::Value. - static const Int64 minInt64; - /// Maximum signed 64 bits int value that can be stored in a Json::Value. - static const Int64 maxInt64; - /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. - static const UInt64 maxUInt64; - - private: -#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION -# ifndef JSON_VALUE_USE_INTERNAL_MAP - class CZString - { - public: - enum DuplicationPolicy - { - noDuplication = 0, - duplicate, - duplicateOnCopy - }; - CZString( ArrayIndex index ); - CZString( const char *cstr, DuplicationPolicy allocate ); - CZString( const CZString &other ); - ~CZString(); - CZString &operator =( const CZString &other ); - bool operator<( const CZString &other ) const; - bool operator==( const CZString &other ) const; - ArrayIndex index() const; - const char *c_str() const; - bool isStaticString() const; - private: - void swap( CZString &other ); - const char *cstr_; - ArrayIndex index_; - }; - - public: -# ifndef JSON_USE_CPPTL_SMALLMAP - typedef std::map ObjectValues; -# else - typedef CppTL::SmallMap ObjectValues; -# endif // ifndef JSON_USE_CPPTL_SMALLMAP -# endif // ifndef JSON_VALUE_USE_INTERNAL_MAP -#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - - public: - /** \brief Create a default Value of the given type. - - This is a very useful constructor. - To create an empty array, pass arrayValue. - To create an empty object, pass objectValue. - Another Value can then be set to this one by assignment. - This is useful since clear() and resize() will not alter types. - - Examples: - \code - Json::Value null_value; // null - Json::Value arr_value(Json::arrayValue); // [] - Json::Value obj_value(Json::objectValue); // {} - \endcode - */ - Value( ValueType type = nullValue ); - Value( Int value ); - Value( UInt value ); -#if defined(JSON_HAS_INT64) - Value( Int64 value ); - Value( UInt64 value ); -#endif // if defined(JSON_HAS_INT64) - Value( double value ); - Value( const char *value ); - Value( const char *beginValue, const char *endValue ); - /** \brief Constructs a value from a static string. - - * Like other value string constructor but do not duplicate the string for - * internal storage. The given string must remain alive after the call to this - * constructor. - * Example of usage: - * \code - * Json::Value aValue( StaticString("some text") ); - * \endcode - */ - Value( const StaticString &value ); - Value( const std::string &value ); -# ifdef JSON_USE_CPPTL - Value( const CppTL::ConstString &value ); -# endif - Value( bool value ); - Value( const Value &other ); - ~Value(); - - Value &operator=( const Value &other ); - /// Swap values. - /// \note Currently, comments are intentionally not swapped, for - /// both logic and efficiency. - void swap( Value &other ); - - ValueType type() const; - - bool operator <( const Value &other ) const; - bool operator <=( const Value &other ) const; - bool operator >=( const Value &other ) const; - bool operator >( const Value &other ) const; - - bool operator ==( const Value &other ) const; - bool operator !=( const Value &other ) const; - - int compare( const Value &other ) const; - - const char *asCString() const; - std::string asString() const; -# ifdef JSON_USE_CPPTL - CppTL::ConstString asConstString() const; -# endif - Int asInt() const; - UInt asUInt() const; - Int64 asInt64() const; - UInt64 asUInt64() const; - LargestInt asLargestInt() const; - LargestUInt asLargestUInt() const; - float asFloat() const; - double asDouble() const; - bool asBool() const; - - bool isNull() const; - bool isBool() const; - bool isInt() const; - bool isUInt() const; - bool isIntegral() const; - bool isDouble() const; - bool isNumeric() const; - bool isString() const; - bool isArray() const; - bool isObject() const; - - bool isConvertibleTo( ValueType other ) const; - - /// Number of values in array or object - ArrayIndex size() const; - - /// \brief Return true if empty array, empty object, or null; - /// otherwise, false. - bool empty() const; - - /// Return isNull() - bool operator!() const; - - /// Remove all object members and array elements. - /// \pre type() is arrayValue, objectValue, or nullValue - /// \post type() is unchanged - void clear(); - - /// Resize the array to size elements. - /// New elements are initialized to null. - /// May only be called on nullValue or arrayValue. - /// \pre type() is arrayValue or nullValue - /// \post type() is arrayValue - void resize( ArrayIndex size ); - - /// Access an array element (zero based index ). - /// If the array contains less than index element, then null value are inserted - /// in the array so that its size is index+1. - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - Value &operator[]( ArrayIndex index ); - - /// Access an array element (zero based index ). - /// If the array contains less than index element, then null value are inserted - /// in the array so that its size is index+1. - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - Value &operator[]( int index ); - - /// Access an array element (zero based index ) - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - const Value &operator[]( ArrayIndex index ) const; - - /// Access an array element (zero based index ) - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - const Value &operator[]( int index ) const; - - /// If the array contains at least index+1 elements, returns the element value, - /// otherwise returns defaultValue. - Value get( ArrayIndex index, - const Value &defaultValue ) const; - /// Return true if index < size(). - bool isValidIndex( ArrayIndex index ) const; - /// \brief Append value to array at the end. - /// - /// Equivalent to jsonvalue[jsonvalue.size()] = value; - Value &append( const Value &value ); - - /// Access an object value by name, create a null member if it does not exist. - Value &operator[]( const char *key ); - /// Access an object value by name, returns null if there is no member with that name. - const Value &operator[]( const char *key ) const; - /// Access an object value by name, create a null member if it does not exist. - Value &operator[]( const std::string &key ); - /// Access an object value by name, returns null if there is no member with that name. - const Value &operator[]( const std::string &key ) const; - /** \brief Access an object value by name, create a null member if it does not exist. - - * If the object as no entry for that name, then the member name used to store - * the new entry is not duplicated. - * Example of use: - * \code - * Json::Value object; - * static const StaticString code("code"); - * object[code] = 1234; - * \endcode - */ - Value &operator[]( const StaticString &key ); -# ifdef JSON_USE_CPPTL - /// Access an object value by name, create a null member if it does not exist. - Value &operator[]( const CppTL::ConstString &key ); - /// Access an object value by name, returns null if there is no member with that name. - const Value &operator[]( const CppTL::ConstString &key ) const; -# endif - /// Return the member named key if it exist, defaultValue otherwise. - Value get( const char *key, - const Value &defaultValue ) const; - /// Return the member named key if it exist, defaultValue otherwise. - Value get( const std::string &key, - const Value &defaultValue ) const; -# ifdef JSON_USE_CPPTL - /// Return the member named key if it exist, defaultValue otherwise. - Value get( const CppTL::ConstString &key, - const Value &defaultValue ) const; -# endif - /// \brief Remove and return the named member. - /// - /// Do nothing if it did not exist. - /// \return the removed Value, or null. - /// \pre type() is objectValue or nullValue - /// \post type() is unchanged - Value removeMember( const char* key ); - /// Same as removeMember(const char*) - Value removeMember( const std::string &key ); - - /// Return true if the object has a member named key. - bool isMember( const char *key ) const; - /// Return true if the object has a member named key. - bool isMember( const std::string &key ) const; -# ifdef JSON_USE_CPPTL - /// Return true if the object has a member named key. - bool isMember( const CppTL::ConstString &key ) const; -# endif - - /// \brief Return a list of the member names. - /// - /// If null, return an empty list. - /// \pre type() is objectValue or nullValue - /// \post if type() was nullValue, it remains nullValue - Members getMemberNames() const; - -//# ifdef JSON_USE_CPPTL -// EnumMemberNames enumMemberNames() const; -// EnumValues enumValues() const; -//# endif - - /// Comments must be //... or /* ... */ - void setComment( const char *comment, - CommentPlacement placement ); - /// Comments must be //... or /* ... */ - void setComment( const std::string &comment, - CommentPlacement placement ); - bool hasComment( CommentPlacement placement ) const; - /// Include delimiters and embedded newlines. - std::string getComment( CommentPlacement placement ) const; - - std::string toStyledString() const; - - const_iterator begin() const; - const_iterator end() const; - - iterator begin(); - iterator end(); - - private: - Value &resolveReference( const char *key, - bool isStatic ); - -# ifdef JSON_VALUE_USE_INTERNAL_MAP - inline bool isItemAvailable() const - { - return itemIsUsed_ == 0; - } - - inline void setItemUsed( bool isUsed = true ) - { - itemIsUsed_ = isUsed ? 1 : 0; - } - - inline bool isMemberNameStatic() const - { - return memberNameIsStatic_ == 0; - } - - inline void setMemberNameIsStatic( bool isStatic ) - { - memberNameIsStatic_ = isStatic ? 1 : 0; - } -# endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP - - private: - struct CommentInfo - { - CommentInfo(); - ~CommentInfo(); - - void setComment( const char *text ); - - char *comment_; - }; - - //struct MemberNamesTransform - //{ - // typedef const char *result_type; - // const char *operator()( const CZString &name ) const - // { - // return name.c_str(); - // } - //}; - - union ValueHolder - { - LargestInt int_; - LargestUInt uint_; - double real_; - bool bool_; - char *string_; -# ifdef JSON_VALUE_USE_INTERNAL_MAP - ValueInternalArray *array_; - ValueInternalMap *map_; -#else - ObjectValues *map_; -# endif - } value_; - ValueType type_ : 8; - int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. -# ifdef JSON_VALUE_USE_INTERNAL_MAP - unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container. - int memberNameIsStatic_ : 1; // used by the ValueInternalMap container. -# endif - CommentInfo *comments_; - }; - - - /** \brief Experimental and untested: represents an element of the "path" to access a node. - */ - class PathArgument - { - public: - friend class Path; - - PathArgument(); - PathArgument( ArrayIndex index ); - PathArgument( const char *key ); - PathArgument( const std::string &key ); - - private: - enum Kind - { - kindNone = 0, - kindIndex, - kindKey - }; - std::string key_; - ArrayIndex index_; - Kind kind_; - }; - - /** \brief Experimental and untested: represents a "path" to access a node. - * - * Syntax: - * - "." => root node - * - ".[n]" => elements at index 'n' of root node (an array value) - * - ".name" => member named 'name' of root node (an object value) - * - ".name1.name2.name3" - * - ".[0][1][2].name1[3]" - * - ".%" => member name is provided as parameter - * - ".[%]" => index is provied as parameter - */ - class Path - { - public: - Path( const std::string &path, - const PathArgument &a1 = PathArgument(), - const PathArgument &a2 = PathArgument(), - const PathArgument &a3 = PathArgument(), - const PathArgument &a4 = PathArgument(), - const PathArgument &a5 = PathArgument() ); - - const Value &resolve( const Value &root ) const; - Value resolve( const Value &root, - const Value &defaultValue ) const; - /// Creates the "path" to access the specified node and returns a reference on the node. - Value &make( Value &root ) const; - - private: - typedef std::vector InArgs; - typedef std::vector Args; - - void makePath( const std::string &path, - const InArgs &in ); - void addPathInArg( const std::string &path, - const InArgs &in, - InArgs::const_iterator &itInArg, - PathArgument::Kind kind ); - void invalidPath( const std::string &path, - int location ); - - Args args_; - }; - - - -#ifdef JSON_VALUE_USE_INTERNAL_MAP - /** \brief Allocator to customize Value internal map. - * Below is an example of a simple implementation (default implementation actually - * use memory pool for speed). - * \code - class DefaultValueMapAllocator : public ValueMapAllocator - { - public: // overridden from ValueMapAllocator - virtual ValueInternalMap *newMap() - { - return new ValueInternalMap(); - } - - virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) - { - return new ValueInternalMap( other ); - } - - virtual void destructMap( ValueInternalMap *map ) - { - delete map; - } - - virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) - { - return new ValueInternalLink[size]; - } - - virtual void releaseMapBuckets( ValueInternalLink *links ) - { - delete [] links; - } - - virtual ValueInternalLink *allocateMapLink() - { - return new ValueInternalLink(); - } - - virtual void releaseMapLink( ValueInternalLink *link ) - { - delete link; - } - }; - * \endcode - */ - class JSON_API ValueMapAllocator - { - public: - virtual ~ValueMapAllocator(); - virtual ValueInternalMap *newMap() = 0; - virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0; - virtual void destructMap( ValueInternalMap *map ) = 0; - virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0; - virtual void releaseMapBuckets( ValueInternalLink *links ) = 0; - virtual ValueInternalLink *allocateMapLink() = 0; - virtual void releaseMapLink( ValueInternalLink *link ) = 0; - }; - - /** \brief ValueInternalMap hash-map bucket chain link (for internal use only). - * \internal previous_ & next_ allows for bidirectional traversal. - */ - class JSON_API ValueInternalLink - { - public: - enum { itemPerLink = 6 }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture. - enum InternalFlags { - flagAvailable = 0, - flagUsed = 1 - }; - - ValueInternalLink(); - - ~ValueInternalLink(); - - Value items_[itemPerLink]; - char *keys_[itemPerLink]; - ValueInternalLink *previous_; - ValueInternalLink *next_; - }; - - - /** \brief A linked page based hash-table implementation used internally by Value. - * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked - * list in each bucket to handle collision. There is an addional twist in that - * each node of the collision linked list is a page containing a fixed amount of - * value. This provides a better compromise between memory usage and speed. - * - * Each bucket is made up of a chained list of ValueInternalLink. The last - * link of a given bucket can be found in the 'previous_' field of the following bucket. - * The last link of the last bucket is stored in tailLink_ as it has no following bucket. - * Only the last link of a bucket may contains 'available' item. The last link always - * contains at least one element unless is it the bucket one very first link. - */ - class JSON_API ValueInternalMap - { - friend class ValueIteratorBase; - friend class Value; - public: - typedef unsigned int HashKey; - typedef unsigned int BucketIndex; - -# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - struct IteratorState - { - IteratorState() - : map_(0) - , link_(0) - , itemIndex_(0) - , bucketIndex_(0) - { - } - ValueInternalMap *map_; - ValueInternalLink *link_; - BucketIndex itemIndex_; - BucketIndex bucketIndex_; - }; -# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - - ValueInternalMap(); - ValueInternalMap( const ValueInternalMap &other ); - ValueInternalMap &operator =( const ValueInternalMap &other ); - ~ValueInternalMap(); - - void swap( ValueInternalMap &other ); - - BucketIndex size() const; - - void clear(); - - bool reserveDelta( BucketIndex growth ); - - bool reserve( BucketIndex newItemCount ); - - const Value *find( const char *key ) const; - - Value *find( const char *key ); - - Value &resolveReference( const char *key, - bool isStatic ); - - void remove( const char *key ); - - void doActualRemove( ValueInternalLink *link, - BucketIndex index, - BucketIndex bucketIndex ); - - ValueInternalLink *&getLastLinkInBucket( BucketIndex bucketIndex ); - - Value &setNewItem( const char *key, - bool isStatic, - ValueInternalLink *link, - BucketIndex index ); - - Value &unsafeAdd( const char *key, - bool isStatic, - HashKey hashedKey ); - - HashKey hash( const char *key ) const; - - int compare( const ValueInternalMap &other ) const; - - private: - void makeBeginIterator( IteratorState &it ) const; - void makeEndIterator( IteratorState &it ) const; - static bool equals( const IteratorState &x, const IteratorState &other ); - static void increment( IteratorState &iterator ); - static void incrementBucket( IteratorState &iterator ); - static void decrement( IteratorState &iterator ); - static const char *key( const IteratorState &iterator ); - static const char *key( const IteratorState &iterator, bool &isStatic ); - static Value &value( const IteratorState &iterator ); - static int distance( const IteratorState &x, const IteratorState &y ); - - private: - ValueInternalLink *buckets_; - ValueInternalLink *tailLink_; - BucketIndex bucketsSize_; - BucketIndex itemCount_; - }; - - /** \brief A simplified deque implementation used internally by Value. - * \internal - * It is based on a list of fixed "page", each page contains a fixed number of items. - * Instead of using a linked-list, a array of pointer is used for fast item look-up. - * Look-up for an element is as follow: - * - compute page index: pageIndex = itemIndex / itemsPerPage - * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage] - * - * Insertion is amortized constant time (only the array containing the index of pointers - * need to be reallocated when items are appended). - */ - class JSON_API ValueInternalArray - { - friend class Value; - friend class ValueIteratorBase; - public: - enum { itemsPerPage = 8 }; // should be a power of 2 for fast divide and modulo. - typedef Value::ArrayIndex ArrayIndex; - typedef unsigned int PageIndex; - -# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - struct IteratorState // Must be a POD - { - IteratorState() - : array_(0) - , currentPageIndex_(0) - , currentItemIndex_(0) - { - } - ValueInternalArray *array_; - Value **currentPageIndex_; - unsigned int currentItemIndex_; - }; -# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - - ValueInternalArray(); - ValueInternalArray( const ValueInternalArray &other ); - ValueInternalArray &operator =( const ValueInternalArray &other ); - ~ValueInternalArray(); - void swap( ValueInternalArray &other ); - - void clear(); - void resize( ArrayIndex newSize ); - - Value &resolveReference( ArrayIndex index ); - - Value *find( ArrayIndex index ) const; - - ArrayIndex size() const; - - int compare( const ValueInternalArray &other ) const; - - private: - static bool equals( const IteratorState &x, const IteratorState &other ); - static void increment( IteratorState &iterator ); - static void decrement( IteratorState &iterator ); - static Value &dereference( const IteratorState &iterator ); - static Value &unsafeDereference( const IteratorState &iterator ); - static int distance( const IteratorState &x, const IteratorState &y ); - static ArrayIndex indexOf( const IteratorState &iterator ); - void makeBeginIterator( IteratorState &it ) const; - void makeEndIterator( IteratorState &it ) const; - void makeIterator( IteratorState &it, ArrayIndex index ) const; - - void makeIndexValid( ArrayIndex index ); - - Value **pages_; - ArrayIndex size_; - PageIndex pageCount_; - }; - - /** \brief Experimental: do not use. Allocator to customize Value internal array. - * Below is an example of a simple implementation (actual implementation use - * memory pool). - \code -class DefaultValueArrayAllocator : public ValueArrayAllocator -{ -public: // overridden from ValueArrayAllocator - virtual ~DefaultValueArrayAllocator() - { - } - - virtual ValueInternalArray *newArray() - { - return new ValueInternalArray(); - } - - virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) - { - return new ValueInternalArray( other ); - } - - virtual void destruct( ValueInternalArray *array ) - { - delete array; - } - - virtual void reallocateArrayPageIndex( Value **&indexes, - ValueInternalArray::PageIndex &indexCount, - ValueInternalArray::PageIndex minNewIndexCount ) - { - ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; - if ( minNewIndexCount > newIndexCount ) - newIndexCount = minNewIndexCount; - void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); - if ( !newIndexes ) - throw std::bad_alloc(); - indexCount = newIndexCount; - indexes = static_cast( newIndexes ); - } - virtual void releaseArrayPageIndex( Value **indexes, - ValueInternalArray::PageIndex indexCount ) - { - if ( indexes ) - free( indexes ); - } - - virtual Value *allocateArrayPage() - { - return static_cast( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) ); - } - - virtual void releaseArrayPage( Value *value ) - { - if ( value ) - free( value ); - } -}; - \endcode - */ - class JSON_API ValueArrayAllocator - { - public: - virtual ~ValueArrayAllocator(); - virtual ValueInternalArray *newArray() = 0; - virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) = 0; - virtual void destructArray( ValueInternalArray *array ) = 0; - /** \brief Reallocate array page index. - * Reallocates an array of pointer on each page. - * \param indexes [input] pointer on the current index. May be \c NULL. - * [output] pointer on the new index of at least - * \a minNewIndexCount pages. - * \param indexCount [input] current number of pages in the index. - * [output] number of page the reallocated index can handle. - * \b MUST be >= \a minNewIndexCount. - * \param minNewIndexCount Minimum number of page the new index must be able to - * handle. - */ - virtual void reallocateArrayPageIndex( Value **&indexes, - ValueInternalArray::PageIndex &indexCount, - ValueInternalArray::PageIndex minNewIndexCount ) = 0; - virtual void releaseArrayPageIndex( Value **indexes, - ValueInternalArray::PageIndex indexCount ) = 0; - virtual Value *allocateArrayPage() = 0; - virtual void releaseArrayPage( Value *value ) = 0; - }; -#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP - - - /** \brief base class for Value iterators. - * - */ - class ValueIteratorBase - { - public: - typedef unsigned int size_t; - typedef int difference_type; - typedef ValueIteratorBase SelfType; - - ValueIteratorBase(); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - explicit ValueIteratorBase( const Value::ObjectValues::iterator ¤t ); -#else - ValueIteratorBase( const ValueInternalArray::IteratorState &state ); - ValueIteratorBase( const ValueInternalMap::IteratorState &state ); -#endif - - bool operator ==( const SelfType &other ) const - { - return isEqual( other ); - } - - bool operator !=( const SelfType &other ) const - { - return !isEqual( other ); - } - - difference_type operator -( const SelfType &other ) const - { - return computeDistance( other ); - } - - /// Return either the index or the member name of the referenced value as a Value. - Value key() const; - - /// Return the index of the referenced Value. -1 if it is not an arrayValue. - UInt index() const; - - /// Return the member name of the referenced Value. "" if it is not an objectValue. - const char *memberName() const; - - protected: - Value &deref() const; - - void increment(); - - void decrement(); - - difference_type computeDistance( const SelfType &other ) const; - - bool isEqual( const SelfType &other ) const; - - void copy( const SelfType &other ); - - private: -#ifndef JSON_VALUE_USE_INTERNAL_MAP - Value::ObjectValues::iterator current_; - // Indicates that iterator is for a null value. - bool isNull_; -#else - union - { - ValueInternalArray::IteratorState array_; - ValueInternalMap::IteratorState map_; - } iterator_; - bool isArray_; -#endif - }; - - /** \brief const iterator for object and array value. - * - */ - class ValueConstIterator : public ValueIteratorBase - { - friend class Value; - public: - typedef unsigned int size_t; - typedef int difference_type; - typedef const Value &reference; - typedef const Value *pointer; - typedef ValueConstIterator SelfType; - - ValueConstIterator(); - private: - /*! \internal Use by Value to create an iterator. - */ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - explicit ValueConstIterator( const Value::ObjectValues::iterator ¤t ); -#else - ValueConstIterator( const ValueInternalArray::IteratorState &state ); - ValueConstIterator( const ValueInternalMap::IteratorState &state ); -#endif - public: - SelfType &operator =( const ValueIteratorBase &other ); - - SelfType operator++( int ) - { - SelfType temp( *this ); - ++*this; - return temp; - } - - SelfType operator--( int ) - { - SelfType temp( *this ); - --*this; - return temp; - } - - SelfType &operator--() - { - decrement(); - return *this; - } - - SelfType &operator++() - { - increment(); - return *this; - } - - reference operator *() const - { - return deref(); - } - }; - - - /** \brief Iterator for object and array value. - */ - class ValueIterator : public ValueIteratorBase - { - friend class Value; - public: - typedef unsigned int size_t; - typedef int difference_type; - typedef Value &reference; - typedef Value *pointer; - typedef ValueIterator SelfType; - - ValueIterator(); - ValueIterator( const ValueConstIterator &other ); - ValueIterator( const ValueIterator &other ); - private: - /*! \internal Use by Value to create an iterator. - */ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - explicit ValueIterator( const Value::ObjectValues::iterator ¤t ); -#else - ValueIterator( const ValueInternalArray::IteratorState &state ); - ValueIterator( const ValueInternalMap::IteratorState &state ); -#endif - public: - - SelfType &operator =( const SelfType &other ); - - SelfType operator++( int ) - { - SelfType temp( *this ); - ++*this; - return temp; - } - - SelfType operator--( int ) - { - SelfType temp( *this ); - --*this; - return temp; - } - - SelfType &operator--() - { - decrement(); - return *this; - } - - SelfType &operator++() - { - increment(); - return *this; - } - - reference operator *() const - { - return deref(); - } - }; - - -} // namespace Json - - -#endif // CPPTL_JSON_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/value.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/reader.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_READER_H_INCLUDED -# define CPPTL_JSON_READER_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -# include "features.h" -# include "value.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -# include -# include -# include -# include - -namespace Json { - - /** \brief Unserialize a JSON document into a Value. - * - */ - class JSON_API Reader - { - public: - typedef char Char; - typedef const Char *Location; - - /** \brief Constructs a Reader allowing all features - * for parsing. - */ - Reader(); - - /** \brief Constructs a Reader allowing the specified feature set - * for parsing. - */ - Reader( const Features &features ); - - /** \brief Read a Value from a JSON document. - * \param document UTF-8 encoded string containing the document to read. - * \param root [out] Contains the root value of the document if it was - * successfully parsed. - * \param collectComments \c true to collect comment and allow writing them back during - * serialization, \c false to discard comments. - * This parameter is ignored if Features::allowComments_ - * is \c false. - * \return \c true if the document was successfully parsed, \c false if an error occurred. - */ - bool parse( const std::string &document, - Value &root, - bool collectComments = true ); - - /** \brief Read a Value from a JSON document. - * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the document to read. - * \param endDoc Pointer on the end of the UTF-8 encoded string of the document to read. - \ Must be >= beginDoc. - * \param root [out] Contains the root value of the document if it was - * successfully parsed. - * \param collectComments \c true to collect comment and allow writing them back during - * serialization, \c false to discard comments. - * This parameter is ignored if Features::allowComments_ - * is \c false. - * \return \c true if the document was successfully parsed, \c false if an error occurred. - */ - bool parse( const char *beginDoc, const char *endDoc, - Value &root, - bool collectComments = true ); - - /// \brief Parse from input stream. - /// \see Json::operator>>(std::istream&, Json::Value&). - bool parse( std::istream &is, - Value &root, - bool collectComments = true ); - - /** \brief Returns a user friendly string that list errors in the parsed document. - * \return Formatted error message with the list of errors with their location in - * the parsed document. An empty string is returned if no error occurred - * during parsing. - * \deprecated Use getFormattedErrorMessages() instead (typo fix). - */ - JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead") - std::string getFormatedErrorMessages() const; - - /** \brief Returns a user friendly string that list errors in the parsed document. - * \return Formatted error message with the list of errors with their location in - * the parsed document. An empty string is returned if no error occurred - * during parsing. - */ - std::string getFormattedErrorMessages() const; - - private: - enum TokenType - { - tokenEndOfStream = 0, - tokenObjectBegin, - tokenObjectEnd, - tokenArrayBegin, - tokenArrayEnd, - tokenString, - tokenNumber, - tokenTrue, - tokenFalse, - tokenNull, - tokenArraySeparator, - tokenMemberSeparator, - tokenComment, - tokenError - }; - - class Token - { - public: - TokenType type_; - Location start_; - Location end_; - }; - - class ErrorInfo - { - public: - Token token_; - std::string message_; - Location extra_; - }; - - typedef std::deque Errors; - - bool expectToken( TokenType type, Token &token, const char *message ); - bool readToken( Token &token ); - void skipSpaces(); - bool match( Location pattern, - int patternLength ); - bool readComment(); - bool readCStyleComment(); - bool readCppStyleComment(); - bool readString(); - void readNumber(); - bool readValue(); - bool readObject( Token &token ); - bool readArray( Token &token ); - bool decodeNumber( Token &token ); - bool decodeString( Token &token ); - bool decodeString( Token &token, std::string &decoded ); - bool decodeDouble( Token &token ); - bool decodeUnicodeCodePoint( Token &token, - Location ¤t, - Location end, - unsigned int &unicode ); - bool decodeUnicodeEscapeSequence( Token &token, - Location ¤t, - Location end, - unsigned int &unicode ); - bool addError( const std::string &message, - Token &token, - Location extra = 0 ); - bool recoverFromError( TokenType skipUntilToken ); - bool addErrorAndRecover( const std::string &message, - Token &token, - TokenType skipUntilToken ); - void skipUntilSpace(); - Value ¤tValue(); - Char getNextChar(); - void getLocationLineAndColumn( Location location, - int &line, - int &column ) const; - std::string getLocationLineAndColumn( Location location ) const; - void addComment( Location begin, - Location end, - CommentPlacement placement ); - void skipCommentTokens( Token &token ); - - typedef std::stack Nodes; - Nodes nodes_; - Errors errors_; - std::string document_; - Location begin_; - Location end_; - Location current_; - Location lastValueEnd_; - Value *lastValue_; - std::string commentsBefore_; - Features features_; - bool collectComments_; - }; - - /** \brief Read from 'sin' into 'root'. - - Always keep comments from the input JSON. - - This can be used to read a file into a particular sub-object. - For example: - \code - Json::Value root; - cin >> root["dir"]["file"]; - cout << root; - \endcode - Result: - \verbatim - { - "dir": { - "file": { - // The input stream JSON would be nested here. - } - } - } - \endverbatim - \throw std::exception on parse error. - \see Json::operator<<() - */ - std::istream& operator>>( std::istream&, Value& ); - -} // namespace Json - -#endif // CPPTL_JSON_READER_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/reader.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/writer.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_WRITER_H_INCLUDED -# define JSON_WRITER_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -# include "value.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -# include -# include -# include - -namespace Json { - - class Value; - - /** \brief Abstract class for writers. - */ - class JSON_API Writer - { - public: - virtual ~Writer(); - - virtual std::string write( const Value &root ) = 0; - }; - - /** \brief Outputs a Value in JSON format without formatting (not human friendly). - * - * The JSON document is written in a single line. It is not intended for 'human' consumption, - * but may be usefull to support feature such as RPC where bandwith is limited. - * \sa Reader, Value - */ - class JSON_API FastWriter : public Writer - { - public: - FastWriter(); - virtual ~FastWriter(){} - - void enableYAMLCompatibility(); - - public: // overridden from Writer - virtual std::string write( const Value &root ); - - private: - void writeValue( const Value &value ); - - std::string document_; - bool yamlCompatiblityEnabled_; - }; - - /** \brief Writes a Value in JSON format in a human friendly way. - * - * The rules for line break and indent are as follow: - * - Object value: - * - if empty then print {} without indent and line break - * - if not empty the print '{', line break & indent, print one value per line - * and then unindent and line break and print '}'. - * - Array value: - * - if empty then print [] without indent and line break - * - if the array contains no object value, empty array or some other value types, - * and all the values fit on one lines, then print the array on a single line. - * - otherwise, it the values do not fit on one line, or the array contains - * object or non empty array, then print one value per line. - * - * If the Value have comments then they are outputed according to their #CommentPlacement. - * - * \sa Reader, Value, Value::setComment() - */ - class JSON_API StyledWriter: public Writer - { - public: - StyledWriter(); - virtual ~StyledWriter(){} - - public: // overridden from Writer - /** \brief Serialize a Value in JSON format. - * \param root Value to serialize. - * \return String containing the JSON document that represents the root value. - */ - virtual std::string write( const Value &root ); - - private: - void writeValue( const Value &value ); - void writeArrayValue( const Value &value ); - bool isMultineArray( const Value &value ); - void pushValue( const std::string &value ); - void writeIndent(); - void writeWithIndent( const std::string &value ); - void indent(); - void unindent(); - void writeCommentBeforeValue( const Value &root ); - void writeCommentAfterValueOnSameLine( const Value &root ); - bool hasCommentForValue( const Value &value ); - static std::string normalizeEOL( const std::string &text ); - - typedef std::vector ChildValues; - - ChildValues childValues_; - std::string document_; - std::string indentString_; - int rightMargin_; - int indentSize_; - bool addChildValues_; - }; - - /** \brief Writes a Value in JSON format in a human friendly way, - to a stream rather than to a string. - * - * The rules for line break and indent are as follow: - * - Object value: - * - if empty then print {} without indent and line break - * - if not empty the print '{', line break & indent, print one value per line - * and then unindent and line break and print '}'. - * - Array value: - * - if empty then print [] without indent and line break - * - if the array contains no object value, empty array or some other value types, - * and all the values fit on one lines, then print the array on a single line. - * - otherwise, it the values do not fit on one line, or the array contains - * object or non empty array, then print one value per line. - * - * If the Value have comments then they are outputed according to their #CommentPlacement. - * - * \param indentation Each level will be indented by this amount extra. - * \sa Reader, Value, Value::setComment() - */ - class JSON_API StyledStreamWriter - { - public: - StyledStreamWriter( std::string indentation="\t" ); - ~StyledStreamWriter(){} - - public: - /** \brief Serialize a Value in JSON format. - * \param out Stream to write to. (Can be ostringstream, e.g.) - * \param root Value to serialize. - * \note There is no point in deriving from Writer, since write() should not return a value. - */ - void write( std::ostream &out, const Value &root ); - - private: - void writeValue( const Value &value ); - void writeArrayValue( const Value &value ); - bool isMultineArray( const Value &value ); - void pushValue( const std::string &value ); - void writeIndent(); - void writeWithIndent( const std::string &value ); - void indent(); - void unindent(); - void writeCommentBeforeValue( const Value &root ); - void writeCommentAfterValueOnSameLine( const Value &root ); - bool hasCommentForValue( const Value &value ); - static std::string normalizeEOL( const std::string &text ); - - typedef std::vector ChildValues; - - ChildValues childValues_; - std::ostream* document_; - std::string indentString_; - int rightMargin_; - std::string indentation_; - bool addChildValues_; - }; - -# if defined(JSON_HAS_INT64) - std::string JSON_API valueToString( Int value ); - std::string JSON_API valueToString( UInt value ); -# endif // if defined(JSON_HAS_INT64) - std::string JSON_API valueToString( LargestInt value ); - std::string JSON_API valueToString( LargestUInt value ); - std::string JSON_API valueToString( double value ); - std::string JSON_API valueToString( bool value ); - std::string JSON_API valueToQuotedString( const char *value ); - - /// \brief Output using the StyledStreamWriter. - /// \see Json::operator>>() - std::ostream& operator<<( std::ostream&, const Value &root ); - -} // namespace Json - - - -#endif // JSON_WRITER_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/writer.h -// ////////////////////////////////////////////////////////////////////// - - - - - -#endif //ifndef JSON_AMALGATED_H_INCLUDED diff --git a/find-object/src/json/jsoncpp.cpp b/find-object/src/json/jsoncpp.cpp deleted file mode 100644 index e9d3c209..00000000 --- a/find-object/src/json/jsoncpp.cpp +++ /dev/null @@ -1,4230 +0,0 @@ -/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/). -/// It is intented to be used with #include - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - -/* -The JsonCpp library's source code, including accompanying documentation, -tests and demonstration applications, are licensed under the following -conditions... - -The author (Baptiste Lepilleur) explicitly disclaims copyright in all -jurisdictions which recognize such a disclaimer. In such jurisdictions, -this software is released into the Public Domain. - -In jurisdictions which do not recognize Public Domain property (e.g. Germany as of -2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is -released under the terms of the MIT License (see below). - -In jurisdictions which recognize Public Domain property, the user of this -software may choose to accept it either as 1) Public Domain, 2) under the -conditions of the MIT License (see below), or 3) under the terms of dual -Public Domain/MIT License conditions described here, as they choose. - -The MIT License is about as close to Public Domain as a license can get, and is -described in clear, concise terms at: - - http://en.wikipedia.org/wiki/MIT_License - -The full text of the MIT License follows: - -======================================================================== -Copyright (c) 2007-2010 Baptiste Lepilleur - -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. -======================================================================== -(END LICENSE TEXT) - -The MIT license is compatible with both the GPL and commercial -software, affording one all of the rights of Public Domain with the -minor nuisance of being required to keep the above copyright notice -and license text in the source code. Note also that by accepting the -Public Domain "license" you can re-license your copy using whatever -license you like. - -*/ - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - - - - - - -#include - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_tool.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED -# define LIB_JSONCPP_JSON_TOOL_H_INCLUDED - -/* This header provides common string manipulation support, such as UTF-8, - * portable conversion from/to string... - * - * It is an internal header that must not be exposed. - */ - -namespace Json { - -/// Converts a unicode code-point to UTF-8. -static inline std::string -codePointToUTF8(unsigned int cp) -{ - std::string result; - - // based on description from http://en.wikipedia.org/wiki/UTF-8 - - if (cp <= 0x7f) - { - result.resize(1); - result[0] = static_cast(cp); - } - else if (cp <= 0x7FF) - { - result.resize(2); - result[1] = static_cast(0x80 | (0x3f & cp)); - result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); - } - else if (cp <= 0xFFFF) - { - result.resize(3); - result[2] = static_cast(0x80 | (0x3f & cp)); - result[1] = 0x80 | static_cast((0x3f & (cp >> 6))); - result[0] = 0xE0 | static_cast((0xf & (cp >> 12))); - } - else if (cp <= 0x10FFFF) - { - result.resize(4); - result[3] = static_cast(0x80 | (0x3f & cp)); - result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); - result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); - result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); - } - - return result; -} - - -/// Returns true if ch is a control character (in range [0,32[). -static inline bool -isControlCharacter(char ch) -{ - return ch > 0 && ch <= 0x1F; -} - - -enum { - /// Constant that specify the size of the buffer that must be passed to uintToString. - uintToStringBufferSize = 3*sizeof(LargestUInt)+1 -}; - -// Defines a char buffer for use with uintToString(). -typedef char UIntToStringBuffer[uintToStringBufferSize]; - - -/** Converts an unsigned integer to string. - * @param value Unsigned interger to convert to string - * @param current Input/Output string buffer. - * Must have at least uintToStringBufferSize chars free. - */ -static inline void -uintToString( LargestUInt value, - char *¤t ) -{ - *--current = 0; - do - { - *--current = char(value % 10) + '0'; - value /= 10; - } - while ( value != 0 ); -} - -} // namespace Json { - -#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_tool.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_reader.cpp -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -# include -# include -# include "json_tool.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include -#include - -#if _MSC_VER >= 1400 // VC++ 8.0 -#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated. -#endif - -namespace Json { - -// Implementation of class Features -// //////////////////////////////// - -Features::Features() - : allowComments_( true ) - , strictRoot_( false ) -{ -} - - -Features -Features::all() -{ - return Features(); -} - - -Features -Features::strictMode() -{ - Features features; - features.allowComments_ = false; - features.strictRoot_ = true; - return features; -} - -// Implementation of class Reader -// //////////////////////////////// - - -static inline bool -in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 ) -{ - return c == c1 || c == c2 || c == c3 || c == c4; -} - -static inline bool -in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 ) -{ - return c == c1 || c == c2 || c == c3 || c == c4 || c == c5; -} - - -static bool -containsNewLine( Reader::Location begin, - Reader::Location end ) -{ - for ( ;begin < end; ++begin ) - if ( *begin == '\n' || *begin == '\r' ) - return true; - return false; -} - - -// Class Reader -// ////////////////////////////////////////////////////////////////// - -Reader::Reader() - : features_( Features::all() ) -{ -} - - -Reader::Reader( const Features &features ) - : features_( features ) -{ -} - - -bool -Reader::parse( const std::string &document, - Value &root, - bool collectComments ) -{ - document_ = document; - const char *begin = document_.c_str(); - const char *end = begin + document_.length(); - return parse( begin, end, root, collectComments ); -} - - -bool -Reader::parse( std::istream& sin, - Value &root, - bool collectComments ) -{ - //std::istream_iterator begin(sin); - //std::istream_iterator end; - // Those would allow streamed input from a file, if parse() were a - // template function. - - // Since std::string is reference-counted, this at least does not - // create an extra copy. - std::string doc; - std::getline(sin, doc, (char)EOF); - return parse( doc, root, collectComments ); -} - -bool -Reader::parse( const char *beginDoc, const char *endDoc, - Value &root, - bool collectComments ) -{ - if ( !features_.allowComments_ ) - { - collectComments = false; - } - - begin_ = beginDoc; - end_ = endDoc; - collectComments_ = collectComments; - current_ = begin_; - lastValueEnd_ = 0; - lastValue_ = 0; - commentsBefore_ = ""; - errors_.clear(); - while ( !nodes_.empty() ) - nodes_.pop(); - nodes_.push( &root ); - - bool successful = readValue(); - Token token; - skipCommentTokens( token ); - if ( collectComments_ && !commentsBefore_.empty() ) - root.setComment( commentsBefore_, commentAfter ); - if ( features_.strictRoot_ ) - { - if ( !root.isArray() && !root.isObject() ) - { - // Set error location to start of doc, ideally should be first token found in doc - token.type_ = tokenError; - token.start_ = beginDoc; - token.end_ = endDoc; - addError( "A valid JSON document must be either an array or an object value.", - token ); - return false; - } - } - return successful; -} - - -bool -Reader::readValue() -{ - Token token; - skipCommentTokens( token ); - bool successful = true; - - if ( collectComments_ && !commentsBefore_.empty() ) - { - currentValue().setComment( commentsBefore_, commentBefore ); - commentsBefore_ = ""; - } - - - switch ( token.type_ ) - { - case tokenObjectBegin: - successful = readObject( token ); - break; - case tokenArrayBegin: - successful = readArray( token ); - break; - case tokenNumber: - successful = decodeNumber( token ); - break; - case tokenString: - successful = decodeString( token ); - break; - case tokenTrue: - currentValue() = true; - break; - case tokenFalse: - currentValue() = false; - break; - case tokenNull: - currentValue() = Value(); - break; - default: - return addError( "Syntax error: value, object or array expected.", token ); - } - - if ( collectComments_ ) - { - lastValueEnd_ = current_; - lastValue_ = ¤tValue(); - } - - return successful; -} - - -void -Reader::skipCommentTokens( Token &token ) -{ - if ( features_.allowComments_ ) - { - do - { - readToken( token ); - } - while ( token.type_ == tokenComment ); - } - else - { - readToken( token ); - } -} - - -bool -Reader::expectToken( TokenType type, Token &token, const char *message ) -{ - readToken( token ); - if ( token.type_ != type ) - return addError( message, token ); - return true; -} - - -bool -Reader::readToken( Token &token ) -{ - skipSpaces(); - token.start_ = current_; - Char c = getNextChar(); - bool ok = true; - switch ( c ) - { - case '{': - token.type_ = tokenObjectBegin; - break; - case '}': - token.type_ = tokenObjectEnd; - break; - case '[': - token.type_ = tokenArrayBegin; - break; - case ']': - token.type_ = tokenArrayEnd; - break; - case '"': - token.type_ = tokenString; - ok = readString(); - break; - case '/': - token.type_ = tokenComment; - ok = readComment(); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - token.type_ = tokenNumber; - readNumber(); - break; - case 't': - token.type_ = tokenTrue; - ok = match( "rue", 3 ); - break; - case 'f': - token.type_ = tokenFalse; - ok = match( "alse", 4 ); - break; - case 'n': - token.type_ = tokenNull; - ok = match( "ull", 3 ); - break; - case ',': - token.type_ = tokenArraySeparator; - break; - case ':': - token.type_ = tokenMemberSeparator; - break; - case 0: - token.type_ = tokenEndOfStream; - break; - default: - ok = false; - break; - } - if ( !ok ) - token.type_ = tokenError; - token.end_ = current_; - return true; -} - - -void -Reader::skipSpaces() -{ - while ( current_ != end_ ) - { - Char c = *current_; - if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' ) - ++current_; - else - break; - } -} - - -bool -Reader::match( Location pattern, - int patternLength ) -{ - if ( end_ - current_ < patternLength ) - return false; - int index = patternLength; - while ( index-- ) - if ( current_[index] != pattern[index] ) - return false; - current_ += patternLength; - return true; -} - - -bool -Reader::readComment() -{ - Location commentBegin = current_ - 1; - Char c = getNextChar(); - bool successful = false; - if ( c == '*' ) - successful = readCStyleComment(); - else if ( c == '/' ) - successful = readCppStyleComment(); - if ( !successful ) - return false; - - if ( collectComments_ ) - { - CommentPlacement placement = commentBefore; - if ( lastValueEnd_ && !containsNewLine( lastValueEnd_, commentBegin ) ) - { - if ( c != '*' || !containsNewLine( commentBegin, current_ ) ) - placement = commentAfterOnSameLine; - } - - addComment( commentBegin, current_, placement ); - } - return true; -} - - -void -Reader::addComment( Location begin, - Location end, - CommentPlacement placement ) -{ - assert( collectComments_ ); - if ( placement == commentAfterOnSameLine ) - { - assert( lastValue_ != 0 ); - lastValue_->setComment( std::string( begin, end ), placement ); - } - else - { - if ( !commentsBefore_.empty() ) - commentsBefore_ += "\n"; - commentsBefore_ += std::string( begin, end ); - } -} - - -bool -Reader::readCStyleComment() -{ - while ( current_ != end_ ) - { - Char c = getNextChar(); - if ( c == '*' && *current_ == '/' ) - break; - } - return getNextChar() == '/'; -} - - -bool -Reader::readCppStyleComment() -{ - while ( current_ != end_ ) - { - Char c = getNextChar(); - if ( c == '\r' || c == '\n' ) - break; - } - return true; -} - - -void -Reader::readNumber() -{ - while ( current_ != end_ ) - { - if ( !(*current_ >= '0' && *current_ <= '9') && - !in( *current_, '.', 'e', 'E', '+', '-' ) ) - break; - ++current_; - } -} - -bool -Reader::readString() -{ - Char c = 0; - while ( current_ != end_ ) - { - c = getNextChar(); - if ( c == '\\' ) - getNextChar(); - else if ( c == '"' ) - break; - } - return c == '"'; -} - - -bool -Reader::readObject( Token &/*tokenStart*/ ) -{ - Token tokenName; - std::string name; - currentValue() = Value( objectValue ); - while ( readToken( tokenName ) ) - { - bool initialTokenOk = true; - while ( tokenName.type_ == tokenComment && initialTokenOk ) - initialTokenOk = readToken( tokenName ); - if ( !initialTokenOk ) - break; - if ( tokenName.type_ == tokenObjectEnd && name.empty() ) // empty object - return true; - if ( tokenName.type_ != tokenString ) - break; - - name = ""; - if ( !decodeString( tokenName, name ) ) - return recoverFromError( tokenObjectEnd ); - - Token colon; - if ( !readToken( colon ) || colon.type_ != tokenMemberSeparator ) - { - return addErrorAndRecover( "Missing ':' after object member name", - colon, - tokenObjectEnd ); - } - Value &value = currentValue()[ name ]; - nodes_.push( &value ); - bool ok = readValue(); - nodes_.pop(); - if ( !ok ) // error already set - return recoverFromError( tokenObjectEnd ); - - Token comma; - if ( !readToken( comma ) - || ( comma.type_ != tokenObjectEnd && - comma.type_ != tokenArraySeparator && - comma.type_ != tokenComment ) ) - { - return addErrorAndRecover( "Missing ',' or '}' in object declaration", - comma, - tokenObjectEnd ); - } - bool finalizeTokenOk = true; - while ( comma.type_ == tokenComment && - finalizeTokenOk ) - finalizeTokenOk = readToken( comma ); - if ( comma.type_ == tokenObjectEnd ) - return true; - } - return addErrorAndRecover( "Missing '}' or object member name", - tokenName, - tokenObjectEnd ); -} - - -bool -Reader::readArray( Token &/*tokenStart*/ ) -{ - currentValue() = Value( arrayValue ); - skipSpaces(); - if ( *current_ == ']' ) // empty array - { - Token endArray; - readToken( endArray ); - return true; - } - int index = 0; - for (;;) - { - Value &value = currentValue()[ index++ ]; - nodes_.push( &value ); - bool ok = readValue(); - nodes_.pop(); - if ( !ok ) // error already set - return recoverFromError( tokenArrayEnd ); - - Token token; - // Accept Comment after last item in the array. - ok = readToken( token ); - while ( token.type_ == tokenComment && ok ) - { - ok = readToken( token ); - } - bool badTokenType = ( token.type_ != tokenArraySeparator && - token.type_ != tokenArrayEnd ); - if ( !ok || badTokenType ) - { - return addErrorAndRecover( "Missing ',' or ']' in array declaration", - token, - tokenArrayEnd ); - } - if ( token.type_ == tokenArrayEnd ) - break; - } - return true; -} - - -bool -Reader::decodeNumber( Token &token ) -{ - bool isDouble = false; - for ( Location inspect = token.start_; inspect != token.end_; ++inspect ) - { - isDouble = isDouble - || in( *inspect, '.', 'e', 'E', '+' ) - || ( *inspect == '-' && inspect != token.start_ ); - } - if ( isDouble ) - return decodeDouble( token ); - // Attempts to parse the number as an integer. If the number is - // larger than the maximum supported value of an integer then - // we decode the number as a double. - Location current = token.start_; - bool isNegative = *current == '-'; - if ( isNegative ) - ++current; - Value::LargestUInt maxIntegerValue = isNegative ? Value::LargestUInt(-Value::minLargestInt) - : Value::maxLargestUInt; - Value::LargestUInt threshold = maxIntegerValue / 10; - Value::UInt lastDigitThreshold = Value::UInt( maxIntegerValue % 10 ); - assert( lastDigitThreshold >=0 && lastDigitThreshold <= 9 ); - Value::LargestUInt value = 0; - while ( current < token.end_ ) - { - Char c = *current++; - if ( c < '0' || c > '9' ) - return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token ); - Value::UInt digit(c - '0'); - if ( value >= threshold ) - { - // If the current digit is not the last one, or if it is - // greater than the last digit of the maximum integer value, - // the parse the number as a double. - if ( current != token.end_ || digit > lastDigitThreshold ) - { - return decodeDouble( token ); - } - } - value = value * 10 + digit; - } - if ( isNegative ) - currentValue() = -Value::LargestInt( value ); - else if ( value <= Value::LargestUInt(Value::maxInt) ) - currentValue() = Value::LargestInt( value ); - else - currentValue() = value; - return true; -} - - -bool -Reader::decodeDouble( Token &token ) -{ - double value = 0; - const int bufferSize = 32; - int count; - int length = int(token.end_ - token.start_); - if ( length <= bufferSize ) - { - Char buffer[bufferSize+1]; - memcpy( buffer, token.start_, length ); - buffer[length] = 0; - count = sscanf( buffer, "%lf", &value ); - } - else - { - std::string buffer( token.start_, token.end_ ); - count = sscanf( buffer.c_str(), "%lf", &value ); - } - - if ( count != 1 ) - return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token ); - currentValue() = value; - return true; -} - - -bool -Reader::decodeString( Token &token ) -{ - std::string decoded; - if ( !decodeString( token, decoded ) ) - return false; - currentValue() = decoded; - return true; -} - - -bool -Reader::decodeString( Token &token, std::string &decoded ) -{ - decoded.reserve( token.end_ - token.start_ - 2 ); - Location current = token.start_ + 1; // skip '"' - Location end = token.end_ - 1; // do not include '"' - while ( current != end ) - { - Char c = *current++; - if ( c == '"' ) - break; - else if ( c == '\\' ) - { - if ( current == end ) - return addError( "Empty escape sequence in string", token, current ); - Char escape = *current++; - switch ( escape ) - { - case '"': decoded += '"'; break; - case '/': decoded += '/'; break; - case '\\': decoded += '\\'; break; - case 'b': decoded += '\b'; break; - case 'f': decoded += '\f'; break; - case 'n': decoded += '\n'; break; - case 'r': decoded += '\r'; break; - case 't': decoded += '\t'; break; - case 'u': - { - unsigned int unicode; - if ( !decodeUnicodeCodePoint( token, current, end, unicode ) ) - return false; - decoded += codePointToUTF8(unicode); - } - break; - default: - return addError( "Bad escape sequence in string", token, current ); - } - } - else - { - decoded += c; - } - } - return true; -} - -bool -Reader::decodeUnicodeCodePoint( Token &token, - Location ¤t, - Location end, - unsigned int &unicode ) -{ - - if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) ) - return false; - if (unicode >= 0xD800 && unicode <= 0xDBFF) - { - // surrogate pairs - if (end - current < 6) - return addError( "additional six characters expected to parse unicode surrogate pair.", token, current ); - unsigned int surrogatePair; - if (*(current++) == '\\' && *(current++)== 'u') - { - if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair )) - { - unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); - } - else - return false; - } - else - return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current ); - } - return true; -} - -bool -Reader::decodeUnicodeEscapeSequence( Token &token, - Location ¤t, - Location end, - unsigned int &unicode ) -{ - if ( end - current < 4 ) - return addError( "Bad unicode escape sequence in string: four digits expected.", token, current ); - unicode = 0; - for ( int index =0; index < 4; ++index ) - { - Char c = *current++; - unicode *= 16; - if ( c >= '0' && c <= '9' ) - unicode += c - '0'; - else if ( c >= 'a' && c <= 'f' ) - unicode += c - 'a' + 10; - else if ( c >= 'A' && c <= 'F' ) - unicode += c - 'A' + 10; - else - return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current ); - } - return true; -} - - -bool -Reader::addError( const std::string &message, - Token &token, - Location extra ) -{ - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = extra; - errors_.push_back( info ); - return false; -} - - -bool -Reader::recoverFromError( TokenType skipUntilToken ) -{ - int errorCount = int(errors_.size()); - Token skip; - for (;;) - { - if ( !readToken(skip) ) - errors_.resize( errorCount ); // discard errors caused by recovery - if ( skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream ) - break; - } - errors_.resize( errorCount ); - return false; -} - - -bool -Reader::addErrorAndRecover( const std::string &message, - Token &token, - TokenType skipUntilToken ) -{ - addError( message, token ); - return recoverFromError( skipUntilToken ); -} - - -Value & -Reader::currentValue() -{ - return *(nodes_.top()); -} - - -Reader::Char -Reader::getNextChar() -{ - if ( current_ == end_ ) - return 0; - return *current_++; -} - - -void -Reader::getLocationLineAndColumn( Location location, - int &line, - int &column ) const -{ - Location current = begin_; - Location lastLineStart = current; - line = 0; - while ( current < location && current != end_ ) - { - Char c = *current++; - if ( c == '\r' ) - { - if ( *current == '\n' ) - ++current; - lastLineStart = current; - ++line; - } - else if ( c == '\n' ) - { - lastLineStart = current; - ++line; - } - } - // column & line start at 1 - column = int(location - lastLineStart) + 1; - ++line; -} - - -std::string -Reader::getLocationLineAndColumn( Location location ) const -{ - int line, column; - getLocationLineAndColumn( location, line, column ); - char buffer[18+16+16+1]; - sprintf( buffer, "Line %d, Column %d", line, column ); - return buffer; -} - - -// Deprecated. Preserved for backward compatibility -std::string -Reader::getFormatedErrorMessages() const -{ - return getFormattedErrorMessages(); -} - - -std::string -Reader::getFormattedErrorMessages() const -{ - std::string formattedMessage; - for ( Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError ) - { - const ErrorInfo &error = *itError; - formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n"; - formattedMessage += " " + error.message_ + "\n"; - if ( error.extra_ ) - formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n"; - } - return formattedMessage; -} - - -std::istream& operator>>( std::istream &sin, Value &root ) -{ - Json::Reader reader; - bool ok = reader.parse(sin, root, true); - //JSON_ASSERT( ok ); - if (!ok) throw std::runtime_error(reader.getFormattedErrorMessages()); - return sin; -} - - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_reader.cpp -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_batchallocator.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED -# define JSONCPP_BATCHALLOCATOR_H_INCLUDED - -# include -# include - -# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - -namespace Json { - -/* Fast memory allocator. - * - * This memory allocator allocates memory for a batch of object (specified by - * the page size, the number of object in each page). - * - * It does not allow the destruction of a single object. All the allocated objects - * can be destroyed at once. The memory can be either released or reused for future - * allocation. - * - * The in-place new operator must be used to construct the object using the pointer - * returned by allocate. - */ -template -class BatchAllocator -{ -public: - typedef AllocatedType Type; - - BatchAllocator( unsigned int objectsPerPage = 255 ) - : freeHead_( 0 ) - , objectsPerPage_( objectsPerPage ) - { -// printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() ); - assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space. - assert( objectsPerPage >= 16 ); - batches_ = allocateBatch( 0 ); // allocated a dummy page - currentBatch_ = batches_; - } - - ~BatchAllocator() - { - for ( BatchInfo *batch = batches_; batch; ) - { - BatchInfo *nextBatch = batch->next_; - free( batch ); - batch = nextBatch; - } - } - - /// allocate space for an array of objectPerAllocation object. - /// @warning it is the responsability of the caller to call objects constructors. - AllocatedType *allocate() - { - if ( freeHead_ ) // returns node from free list. - { - AllocatedType *object = freeHead_; - freeHead_ = *(AllocatedType **)object; - return object; - } - if ( currentBatch_->used_ == currentBatch_->end_ ) - { - currentBatch_ = currentBatch_->next_; - while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ ) - currentBatch_ = currentBatch_->next_; - - if ( !currentBatch_ ) // no free batch found, allocate a new one - { - currentBatch_ = allocateBatch( objectsPerPage_ ); - currentBatch_->next_ = batches_; // insert at the head of the list - batches_ = currentBatch_; - } - } - AllocatedType *allocated = currentBatch_->used_; - currentBatch_->used_ += objectPerAllocation; - return allocated; - } - - /// Release the object. - /// @warning it is the responsability of the caller to actually destruct the object. - void release( AllocatedType *object ) - { - assert( object != 0 ); - *(AllocatedType **)object = freeHead_; - freeHead_ = object; - } - -private: - struct BatchInfo - { - BatchInfo *next_; - AllocatedType *used_; - AllocatedType *end_; - AllocatedType buffer_[objectPerAllocation]; - }; - - // disabled copy constructor and assignement operator. - BatchAllocator( const BatchAllocator & ); - void operator =( const BatchAllocator &); - - static BatchInfo *allocateBatch( unsigned int objectsPerPage ) - { - const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation - + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage; - BatchInfo *batch = static_cast( malloc( mallocSize ) ); - batch->next_ = 0; - batch->used_ = batch->buffer_; - batch->end_ = batch->buffer_ + objectsPerPage; - return batch; - } - - BatchInfo *batches_; - BatchInfo *currentBatch_; - /// Head of a single linked list within the allocated space of freeed object - AllocatedType *freeHead_; - unsigned int objectsPerPage_; -}; - - -} // namespace Json - -# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION - -#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED - - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_batchallocator.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_valueiterator.inl -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -// included by json_value.cpp - -namespace Json { - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueIteratorBase -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueIteratorBase::ValueIteratorBase() -#ifndef JSON_VALUE_USE_INTERNAL_MAP - : current_() - , isNull_( true ) -{ -} -#else - : isArray_( true ) - , isNull_( true ) -{ - iterator_.array_ = ValueInternalArray::IteratorState(); -} -#endif - - -#ifndef JSON_VALUE_USE_INTERNAL_MAP -ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator ¤t ) - : current_( current ) - , isNull_( false ) -{ -} -#else -ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state ) - : isArray_( true ) -{ - iterator_.array_ = state; -} - - -ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state ) - : isArray_( false ) -{ - iterator_.map_ = state; -} -#endif - -Value & -ValueIteratorBase::deref() const -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - return current_->second; -#else - if ( isArray_ ) - return ValueInternalArray::dereference( iterator_.array_ ); - return ValueInternalMap::value( iterator_.map_ ); -#endif -} - - -void -ValueIteratorBase::increment() -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - ++current_; -#else - if ( isArray_ ) - ValueInternalArray::increment( iterator_.array_ ); - ValueInternalMap::increment( iterator_.map_ ); -#endif -} - - -void -ValueIteratorBase::decrement() -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - --current_; -#else - if ( isArray_ ) - ValueInternalArray::decrement( iterator_.array_ ); - ValueInternalMap::decrement( iterator_.map_ ); -#endif -} - - -ValueIteratorBase::difference_type -ValueIteratorBase::computeDistance( const SelfType &other ) const -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP -# ifdef JSON_USE_CPPTL_SMALLMAP - return current_ - other.current_; -# else - // Iterator for null value are initialized using the default - // constructor, which initialize current_ to the default - // std::map::iterator. As begin() and end() are two instance - // of the default std::map::iterator, they can not be compared. - // To allow this, we handle this comparison specifically. - if ( isNull_ && other.isNull_ ) - { - return 0; - } - - - // Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL, - // which is the one used by default). - // Using a portable hand-made version for non random iterator instead: - // return difference_type( std::distance( current_, other.current_ ) ); - difference_type myDistance = 0; - for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it ) - { - ++myDistance; - } - return myDistance; -# endif -#else - if ( isArray_ ) - return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ ); - return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ ); -#endif -} - - -bool -ValueIteratorBase::isEqual( const SelfType &other ) const -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - if ( isNull_ ) - { - return other.isNull_; - } - return current_ == other.current_; -#else - if ( isArray_ ) - return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ ); - return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ ); -#endif -} - - -void -ValueIteratorBase::copy( const SelfType &other ) -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - current_ = other.current_; -#else - if ( isArray_ ) - iterator_.array_ = other.iterator_.array_; - iterator_.map_ = other.iterator_.map_; -#endif -} - - -Value -ValueIteratorBase::key() const -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - const Value::CZString czstring = (*current_).first; - if ( czstring.c_str() ) - { - if ( czstring.isStaticString() ) - return Value( StaticString( czstring.c_str() ) ); - return Value( czstring.c_str() ); - } - return Value( czstring.index() ); -#else - if ( isArray_ ) - return Value( ValueInternalArray::indexOf( iterator_.array_ ) ); - bool isStatic; - const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic ); - if ( isStatic ) - return Value( StaticString( memberName ) ); - return Value( memberName ); -#endif -} - - -UInt -ValueIteratorBase::index() const -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - const Value::CZString czstring = (*current_).first; - if ( !czstring.c_str() ) - return czstring.index(); - return Value::UInt( -1 ); -#else - if ( isArray_ ) - return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) ); - return Value::UInt( -1 ); -#endif -} - - -const char * -ValueIteratorBase::memberName() const -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - const char *name = (*current_).first.c_str(); - return name ? name : ""; -#else - if ( !isArray_ ) - return ValueInternalMap::key( iterator_.map_ ); - return ""; -#endif -} - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueConstIterator -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueConstIterator::ValueConstIterator() -{ -} - - -#ifndef JSON_VALUE_USE_INTERNAL_MAP -ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator ¤t ) - : ValueIteratorBase( current ) -{ -} -#else -ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state ) - : ValueIteratorBase( state ) -{ -} - -ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state ) - : ValueIteratorBase( state ) -{ -} -#endif - -ValueConstIterator & -ValueConstIterator::operator =( const ValueIteratorBase &other ) -{ - copy( other ); - return *this; -} - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueIterator -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueIterator::ValueIterator() -{ -} - - -#ifndef JSON_VALUE_USE_INTERNAL_MAP -ValueIterator::ValueIterator( const Value::ObjectValues::iterator ¤t ) - : ValueIteratorBase( current ) -{ -} -#else -ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state ) - : ValueIteratorBase( state ) -{ -} - -ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state ) - : ValueIteratorBase( state ) -{ -} -#endif - -ValueIterator::ValueIterator( const ValueConstIterator &other ) - : ValueIteratorBase( other ) -{ -} - -ValueIterator::ValueIterator( const ValueIterator &other ) - : ValueIteratorBase( other ) -{ -} - -ValueIterator & -ValueIterator::operator =( const SelfType &other ) -{ - copy( other ); - return *this; -} - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_valueiterator.inl -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_value.cpp -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -# include -# include -# ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR -# include "json_batchallocator.h" -# endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include -#ifdef JSON_USE_CPPTL -# include -#endif -#include // size_t - -#define JSON_ASSERT_UNREACHABLE assert( false ) -#define JSON_ASSERT( condition ) assert( condition ); // @todo <= change this into an exception throw -#define JSON_FAIL_MESSAGE( message ) throw std::runtime_error( message ); -#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) JSON_FAIL_MESSAGE( message ) - -namespace Json { - -const Value Value::null; -const Int Value::minInt = Int( ~(UInt(-1)/2) ); -const Int Value::maxInt = Int( UInt(-1)/2 ); -const UInt Value::maxUInt = UInt(-1); -const Int64 Value::minInt64 = Int64( ~(UInt64(-1)/2) ); -const Int64 Value::maxInt64 = Int64( UInt64(-1)/2 ); -const UInt64 Value::maxUInt64 = UInt64(-1); -const LargestInt Value::minLargestInt = LargestInt( ~(LargestUInt(-1)/2) ); -const LargestInt Value::maxLargestInt = LargestInt( LargestUInt(-1)/2 ); -const LargestUInt Value::maxLargestUInt = LargestUInt(-1); - - -/// Unknown size marker -static const unsigned int unknown = (unsigned)-1; - - -/** Duplicates the specified string value. - * @param value Pointer to the string to duplicate. Must be zero-terminated if - * length is "unknown". - * @param length Length of the value. if equals to unknown, then it will be - * computed using strlen(value). - * @return Pointer on the duplicate instance of string. - */ -static inline char * -duplicateStringValue( const char *value, - unsigned int length = unknown ) -{ - if ( length == unknown ) - length = (unsigned int)strlen(value); - char *newString = static_cast( malloc( length + 1 ) ); - JSON_ASSERT_MESSAGE( newString != 0, "Failed to allocate string value buffer" ); - memcpy( newString, value, length ); - newString[length] = 0; - return newString; -} - - -/** Free the string duplicated by duplicateStringValue(). - */ -static inline void -releaseStringValue( char *value ) -{ - if ( value ) - free( value ); -} - -} // namespace Json - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ValueInternals... -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -#if !defined(JSON_IS_AMALGAMATION) -# ifdef JSON_VALUE_USE_INTERNAL_MAP -# include "json_internalarray.inl" -# include "json_internalmap.inl" -# endif // JSON_VALUE_USE_INTERNAL_MAP - -# include "json_valueiterator.inl" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::CommentInfo -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - - -Value::CommentInfo::CommentInfo() - : comment_( 0 ) -{ -} - -Value::CommentInfo::~CommentInfo() -{ - if ( comment_ ) - releaseStringValue( comment_ ); -} - - -void -Value::CommentInfo::setComment( const char *text ) -{ - if ( comment_ ) - releaseStringValue( comment_ ); - JSON_ASSERT( text != 0 ); - JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /"); - // It seems that /**/ style comments are acceptable as well. - comment_ = duplicateStringValue( text ); -} - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::CZString -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -# ifndef JSON_VALUE_USE_INTERNAL_MAP - -// Notes: index_ indicates if the string was allocated when -// a string is stored. - -Value::CZString::CZString( ArrayIndex index ) - : cstr_( 0 ) - , index_( index ) -{ -} - -Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate ) - : cstr_( allocate == duplicate ? duplicateStringValue(cstr) - : cstr ) - , index_( allocate ) -{ -} - -Value::CZString::CZString( const CZString &other ) -: cstr_( other.index_ != noDuplication && other.cstr_ != 0 - ? duplicateStringValue( other.cstr_ ) - : other.cstr_ ) - , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate) - : other.index_ ) -{ -} - -Value::CZString::~CZString() -{ - if ( cstr_ && index_ == duplicate ) - releaseStringValue( const_cast( cstr_ ) ); -} - -void -Value::CZString::swap( CZString &other ) -{ - std::swap( cstr_, other.cstr_ ); - std::swap( index_, other.index_ ); -} - -Value::CZString & -Value::CZString::operator =( const CZString &other ) -{ - CZString temp( other ); - swap( temp ); - return *this; -} - -bool -Value::CZString::operator<( const CZString &other ) const -{ - if ( cstr_ ) - return strcmp( cstr_, other.cstr_ ) < 0; - return index_ < other.index_; -} - -bool -Value::CZString::operator==( const CZString &other ) const -{ - if ( cstr_ ) - return strcmp( cstr_, other.cstr_ ) == 0; - return index_ == other.index_; -} - - -ArrayIndex -Value::CZString::index() const -{ - return index_; -} - - -const char * -Value::CZString::c_str() const -{ - return cstr_; -} - -bool -Value::CZString::isStaticString() const -{ - return index_ == noDuplication; -} - -#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::Value -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -/*! \internal Default constructor initialization must be equivalent to: - * memset( this, 0, sizeof(Value) ) - * This optimization is used in ValueInternalMap fast allocator. - */ -Value::Value( ValueType type ) - : type_( type ) - , allocated_( 0 ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - switch ( type ) - { - case nullValue: - break; - case intValue: - case uintValue: - value_.int_ = 0; - break; - case realValue: - value_.real_ = 0.0; - break; - case stringValue: - value_.string_ = 0; - break; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues(); - break; -#else - case arrayValue: - value_.array_ = arrayAllocator()->newArray(); - break; - case objectValue: - value_.map_ = mapAllocator()->newMap(); - break; -#endif - case booleanValue: - value_.bool_ = false; - break; - default: - JSON_ASSERT_UNREACHABLE; - } -} - - -#if defined(JSON_HAS_INT64) -Value::Value( UInt value ) - : type_( uintValue ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.uint_ = value; -} - -Value::Value( Int value ) - : type_( intValue ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.int_ = value; -} - -#endif // if defined(JSON_HAS_INT64) - - -Value::Value( Int64 value ) - : type_( intValue ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.int_ = value; -} - - -Value::Value( UInt64 value ) - : type_( uintValue ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.uint_ = value; -} - -Value::Value( double value ) - : type_( realValue ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.real_ = value; -} - -Value::Value( const char *value ) - : type_( stringValue ) - , allocated_( true ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.string_ = duplicateStringValue( value ); -} - - -Value::Value( const char *beginValue, - const char *endValue ) - : type_( stringValue ) - , allocated_( true ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.string_ = duplicateStringValue( beginValue, - (unsigned int)(endValue - beginValue) ); -} - - -Value::Value( const std::string &value ) - : type_( stringValue ) - , allocated_( true ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.string_ = duplicateStringValue( value.c_str(), - (unsigned int)value.length() ); - -} - -Value::Value( const StaticString &value ) - : type_( stringValue ) - , allocated_( false ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.string_ = const_cast( value.c_str() ); -} - - -# ifdef JSON_USE_CPPTL -Value::Value( const CppTL::ConstString &value ) - : type_( stringValue ) - , allocated_( true ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.string_ = duplicateStringValue( value, value.length() ); -} -# endif - -Value::Value( bool value ) - : type_( booleanValue ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.bool_ = value; -} - - -Value::Value( const Value &other ) - : type_( other.type_ ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - switch ( type_ ) - { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - value_ = other.value_; - break; - case stringValue: - if ( other.value_.string_ ) - { - value_.string_ = duplicateStringValue( other.value_.string_ ); - allocated_ = true; - } - else - value_.string_ = 0; - break; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues( *other.value_.map_ ); - break; -#else - case arrayValue: - value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ ); - break; - case objectValue: - value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ ); - break; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - if ( other.comments_ ) - { - comments_ = new CommentInfo[numberOfCommentPlacement]; - for ( int comment =0; comment < numberOfCommentPlacement; ++comment ) - { - const CommentInfo &otherComment = other.comments_[comment]; - if ( otherComment.comment_ ) - comments_[comment].setComment( otherComment.comment_ ); - } - } -} - - -Value::~Value() -{ - switch ( type_ ) - { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - break; - case stringValue: - if ( allocated_ ) - releaseStringValue( value_.string_ ); - break; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - delete value_.map_; - break; -#else - case arrayValue: - arrayAllocator()->destructArray( value_.array_ ); - break; - case objectValue: - mapAllocator()->destructMap( value_.map_ ); - break; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - - if ( comments_ ) - delete[] comments_; -} - -Value & -Value::operator=( const Value &other ) -{ - Value temp( other ); - swap( temp ); - return *this; -} - -void -Value::swap( Value &other ) -{ - ValueType temp = type_; - type_ = other.type_; - other.type_ = temp; - std::swap( value_, other.value_ ); - int temp2 = allocated_; - allocated_ = other.allocated_; - other.allocated_ = temp2; -} - -ValueType -Value::type() const -{ - return type_; -} - - -int -Value::compare( const Value &other ) const -{ - if ( *this < other ) - return -1; - if ( *this > other ) - return 1; - return 0; -} - - -bool -Value::operator <( const Value &other ) const -{ - int typeDelta = type_ - other.type_; - if ( typeDelta ) - return typeDelta < 0 ? true : false; - switch ( type_ ) - { - case nullValue: - return false; - case intValue: - return value_.int_ < other.value_.int_; - case uintValue: - return value_.uint_ < other.value_.uint_; - case realValue: - return value_.real_ < other.value_.real_; - case booleanValue: - return value_.bool_ < other.value_.bool_; - case stringValue: - return ( value_.string_ == 0 && other.value_.string_ ) - || ( other.value_.string_ - && value_.string_ - && strcmp( value_.string_, other.value_.string_ ) < 0 ); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - { - int delta = int( value_.map_->size() - other.value_.map_->size() ); - if ( delta ) - return delta < 0; - return (*value_.map_) < (*other.value_.map_); - } -#else - case arrayValue: - return value_.array_->compare( *(other.value_.array_) ) < 0; - case objectValue: - return value_.map_->compare( *(other.value_.map_) ) < 0; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable -} - -bool -Value::operator <=( const Value &other ) const -{ - return !(other < *this); -} - -bool -Value::operator >=( const Value &other ) const -{ - return !(*this < other); -} - -bool -Value::operator >( const Value &other ) const -{ - return other < *this; -} - -bool -Value::operator ==( const Value &other ) const -{ - //if ( type_ != other.type_ ) - // GCC 2.95.3 says: - // attempt to take address of bit-field structure member `Json::Value::type_' - // Beats me, but a temp solves the problem. - int temp = other.type_; - if ( type_ != temp ) - return false; - switch ( type_ ) - { - case nullValue: - return true; - case intValue: - return value_.int_ == other.value_.int_; - case uintValue: - return value_.uint_ == other.value_.uint_; - case realValue: - return value_.real_ == other.value_.real_; - case booleanValue: - return value_.bool_ == other.value_.bool_; - case stringValue: - return ( value_.string_ == other.value_.string_ ) - || ( other.value_.string_ - && value_.string_ - && strcmp( value_.string_, other.value_.string_ ) == 0 ); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - return value_.map_->size() == other.value_.map_->size() - && (*value_.map_) == (*other.value_.map_); -#else - case arrayValue: - return value_.array_->compare( *(other.value_.array_) ) == 0; - case objectValue: - return value_.map_->compare( *(other.value_.map_) ) == 0; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable -} - -bool -Value::operator !=( const Value &other ) const -{ - return !( *this == other ); -} - -const char * -Value::asCString() const -{ - JSON_ASSERT( type_ == stringValue ); - return value_.string_; -} - - -std::string -Value::asString() const -{ - switch ( type_ ) - { - case nullValue: - return ""; - case stringValue: - return value_.string_ ? value_.string_ : ""; - case booleanValue: - return value_.bool_ ? "true" : "false"; - case intValue: - case uintValue: - case realValue: - case arrayValue: - case objectValue: - JSON_FAIL_MESSAGE( "Type is not convertible to string" ); - default: - JSON_ASSERT_UNREACHABLE; - } - return ""; // unreachable -} - -# ifdef JSON_USE_CPPTL -CppTL::ConstString -Value::asConstString() const -{ - return CppTL::ConstString( asString().c_str() ); -} -# endif - - -Value::Int -Value::asInt() const -{ - switch ( type_ ) - { - case nullValue: - return 0; - case intValue: - JSON_ASSERT_MESSAGE( value_.int_ >= minInt && value_.int_ <= maxInt, "unsigned integer out of signed int range" ); - return Int(value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE( value_.uint_ <= UInt(maxInt), "unsigned integer out of signed int range" ); - return Int(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE( value_.real_ >= minInt && value_.real_ <= maxInt, "Real out of signed integer range" ); - return Int( value_.real_ ); - case booleanValue: - return value_.bool_ ? 1 : 0; - case stringValue: - case arrayValue: - case objectValue: - JSON_FAIL_MESSAGE( "Type is not convertible to int" ); - default: - JSON_ASSERT_UNREACHABLE; - } - return 0; // unreachable; -} - - -Value::UInt -Value::asUInt() const -{ - switch ( type_ ) - { - case nullValue: - return 0; - case intValue: - JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" ); - JSON_ASSERT_MESSAGE( value_.int_ <= maxUInt, "signed integer out of UInt range" ); - return UInt(value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE( value_.uint_ <= maxUInt, "unsigned integer out of UInt range" ); - return UInt(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE( value_.real_ >= 0 && value_.real_ <= maxUInt, "Real out of unsigned integer range" ); - return UInt( value_.real_ ); - case booleanValue: - return value_.bool_ ? 1 : 0; - case stringValue: - case arrayValue: - case objectValue: - JSON_FAIL_MESSAGE( "Type is not convertible to uint" ); - default: - JSON_ASSERT_UNREACHABLE; - } - return 0; // unreachable; -} - - -# if defined(JSON_HAS_INT64) - -Value::Int64 -Value::asInt64() const -{ - switch ( type_ ) - { - case nullValue: - return 0; - case intValue: - return value_.int_; - case uintValue: - JSON_ASSERT_MESSAGE( value_.uint_ <= UInt64(maxInt64), "unsigned integer out of Int64 range" ); - return value_.uint_; - case realValue: - JSON_ASSERT_MESSAGE( value_.real_ >= minInt64 && value_.real_ <= maxInt64, "Real out of Int64 range" ); - return Int( value_.real_ ); - case booleanValue: - return value_.bool_ ? 1 : 0; - case stringValue: - case arrayValue: - case objectValue: - JSON_FAIL_MESSAGE( "Type is not convertible to Int64" ); - default: - JSON_ASSERT_UNREACHABLE; - } - return 0; // unreachable; -} - - -Value::UInt64 -Value::asUInt64() const -{ - switch ( type_ ) - { - case nullValue: - return 0; - case intValue: - JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to UInt64" ); - return value_.int_; - case uintValue: - return value_.uint_; - case realValue: - JSON_ASSERT_MESSAGE( value_.real_ >= 0 && value_.real_ <= maxUInt64, "Real out of UInt64 range" ); - return UInt( value_.real_ ); - case booleanValue: - return value_.bool_ ? 1 : 0; - case stringValue: - case arrayValue: - case objectValue: - JSON_FAIL_MESSAGE( "Type is not convertible to UInt64" ); - default: - JSON_ASSERT_UNREACHABLE; - } - return 0; // unreachable; -} -# endif // if defined(JSON_HAS_INT64) - - -LargestInt -Value::asLargestInt() const -{ -#if defined(JSON_NO_INT64) - return asInt(); -#else - return asInt64(); -#endif -} - - -LargestUInt -Value::asLargestUInt() const -{ -#if defined(JSON_NO_INT64) - return asUInt(); -#else - return asUInt64(); -#endif -} - - -double -Value::asDouble() const -{ - switch ( type_ ) - { - case nullValue: - return 0.0; - case intValue: - return static_cast( value_.int_ ); - case uintValue: -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast( value_.uint_ ); -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast( Int(value_.uint_/2) ) * 2 + Int(value_.uint_ & 1); -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - case realValue: - return value_.real_; - case booleanValue: - return value_.bool_ ? 1.0 : 0.0; - case stringValue: - case arrayValue: - case objectValue: - JSON_FAIL_MESSAGE( "Type is not convertible to double" ); - default: - JSON_ASSERT_UNREACHABLE; - } - return 0; // unreachable; -} - -float -Value::asFloat() const -{ - switch ( type_ ) - { - case nullValue: - return 0.0f; - case intValue: - return static_cast( value_.int_ ); - case uintValue: -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast( value_.uint_ ); -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast( Int(value_.uint_/2) ) * 2 + Int(value_.uint_ & 1); -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - case realValue: - return static_cast( value_.real_ ); - case booleanValue: - return value_.bool_ ? 1.0f : 0.0f; - case stringValue: - case arrayValue: - case objectValue: - JSON_FAIL_MESSAGE( "Type is not convertible to float" ); - default: - JSON_ASSERT_UNREACHABLE; - } - return 0.0f; // unreachable; -} - -bool -Value::asBool() const -{ - switch ( type_ ) - { - case nullValue: - return false; - case intValue: - case uintValue: - return value_.int_ != 0; - case realValue: - return value_.real_ != 0.0; - case booleanValue: - return value_.bool_; - case stringValue: - return value_.string_ && value_.string_[0] != 0; - case arrayValue: - case objectValue: - return value_.map_->size() != 0; - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable; -} - - -bool -Value::isConvertibleTo( ValueType other ) const -{ - switch ( type_ ) - { - case nullValue: - return true; - case intValue: - return ( other == nullValue && value_.int_ == 0 ) - || other == intValue - || ( other == uintValue && value_.int_ >= 0 ) - || other == realValue - || other == stringValue - || other == booleanValue; - case uintValue: - return ( other == nullValue && value_.uint_ == 0 ) - || ( other == intValue && value_.uint_ <= (unsigned)maxInt ) - || other == uintValue - || other == realValue - || other == stringValue - || other == booleanValue; - case realValue: - return ( other == nullValue && value_.real_ == 0.0 ) - || ( other == intValue && value_.real_ >= minInt && value_.real_ <= maxInt ) - || ( other == uintValue && value_.real_ >= 0 && value_.real_ <= maxUInt ) - || other == realValue - || other == stringValue - || other == booleanValue; - case booleanValue: - return ( other == nullValue && value_.bool_ == false ) - || other == intValue - || other == uintValue - || other == realValue - || other == stringValue - || other == booleanValue; - case stringValue: - return other == stringValue - || ( other == nullValue && (!value_.string_ || value_.string_[0] == 0) ); - case arrayValue: - return other == arrayValue - || ( other == nullValue && value_.map_->size() == 0 ); - case objectValue: - return other == objectValue - || ( other == nullValue && value_.map_->size() == 0 ); - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable; -} - - -/// Number of values in array or object -ArrayIndex -Value::size() const -{ - switch ( type_ ) - { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - case stringValue: - return 0; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: // size of the array is highest index + 1 - if ( !value_.map_->empty() ) - { - ObjectValues::const_iterator itLast = value_.map_->end(); - --itLast; - return (*itLast).first.index()+1; - } - return 0; - case objectValue: - return ArrayIndex( value_.map_->size() ); -#else - case arrayValue: - return Int( value_.array_->size() ); - case objectValue: - return Int( value_.map_->size() ); -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - return 0; // unreachable; -} - - -bool -Value::empty() const -{ - if ( isNull() || isArray() || isObject() ) - return size() == 0u; - else - return false; -} - - -bool -Value::operator!() const -{ - return isNull(); -} - - -void -Value::clear() -{ - JSON_ASSERT( type_ == nullValue || type_ == arrayValue || type_ == objectValue ); - - switch ( type_ ) - { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - value_.map_->clear(); - break; -#else - case arrayValue: - value_.array_->clear(); - break; - case objectValue: - value_.map_->clear(); - break; -#endif - default: - break; - } -} - -void -Value::resize( ArrayIndex newSize ) -{ - JSON_ASSERT( type_ == nullValue || type_ == arrayValue ); - if ( type_ == nullValue ) - *this = Value( arrayValue ); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - ArrayIndex oldSize = size(); - if ( newSize == 0 ) - clear(); - else if ( newSize > oldSize ) - (*this)[ newSize - 1 ]; - else - { - for ( ArrayIndex index = newSize; index < oldSize; ++index ) - { - value_.map_->erase( index ); - } - assert( size() == newSize ); - } -#else - value_.array_->resize( newSize ); -#endif -} - - -Value & -Value::operator[]( ArrayIndex index ) -{ - JSON_ASSERT( type_ == nullValue || type_ == arrayValue ); - if ( type_ == nullValue ) - *this = Value( arrayValue ); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString key( index ); - ObjectValues::iterator it = value_.map_->lower_bound( key ); - if ( it != value_.map_->end() && (*it).first == key ) - return (*it).second; - - ObjectValues::value_type defaultValue( key, null ); - it = value_.map_->insert( it, defaultValue ); - return (*it).second; -#else - return value_.array_->resolveReference( index ); -#endif -} - - -Value & -Value::operator[]( int index ) -{ - JSON_ASSERT( index >= 0 ); - return (*this)[ ArrayIndex(index) ]; -} - - -const Value & -Value::operator[]( ArrayIndex index ) const -{ - JSON_ASSERT( type_ == nullValue || type_ == arrayValue ); - if ( type_ == nullValue ) - return null; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString key( index ); - ObjectValues::const_iterator it = value_.map_->find( key ); - if ( it == value_.map_->end() ) - return null; - return (*it).second; -#else - Value *value = value_.array_->find( index ); - return value ? *value : null; -#endif -} - - -const Value & -Value::operator[]( int index ) const -{ - JSON_ASSERT( index >= 0 ); - return (*this)[ ArrayIndex(index) ]; -} - - -Value & -Value::operator[]( const char *key ) -{ - return resolveReference( key, false ); -} - - -Value & -Value::resolveReference( const char *key, - bool isStatic ) -{ - JSON_ASSERT( type_ == nullValue || type_ == objectValue ); - if ( type_ == nullValue ) - *this = Value( objectValue ); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString actualKey( key, isStatic ? CZString::noDuplication - : CZString::duplicateOnCopy ); - ObjectValues::iterator it = value_.map_->lower_bound( actualKey ); - if ( it != value_.map_->end() && (*it).first == actualKey ) - return (*it).second; - - ObjectValues::value_type defaultValue( actualKey, null ); - it = value_.map_->insert( it, defaultValue ); - Value &value = (*it).second; - return value; -#else - return value_.map_->resolveReference( key, isStatic ); -#endif -} - - -Value -Value::get( ArrayIndex index, - const Value &defaultValue ) const -{ - const Value *value = &((*this)[index]); - return value == &null ? defaultValue : *value; -} - - -bool -Value::isValidIndex( ArrayIndex index ) const -{ - return index < size(); -} - - - -const Value & -Value::operator[]( const char *key ) const -{ - JSON_ASSERT( type_ == nullValue || type_ == objectValue ); - if ( type_ == nullValue ) - return null; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString actualKey( key, CZString::noDuplication ); - ObjectValues::const_iterator it = value_.map_->find( actualKey ); - if ( it == value_.map_->end() ) - return null; - return (*it).second; -#else - const Value *value = value_.map_->find( key ); - return value ? *value : null; -#endif -} - - -Value & -Value::operator[]( const std::string &key ) -{ - return (*this)[ key.c_str() ]; -} - - -const Value & -Value::operator[]( const std::string &key ) const -{ - return (*this)[ key.c_str() ]; -} - -Value & -Value::operator[]( const StaticString &key ) -{ - return resolveReference( key, true ); -} - - -# ifdef JSON_USE_CPPTL -Value & -Value::operator[]( const CppTL::ConstString &key ) -{ - return (*this)[ key.c_str() ]; -} - - -const Value & -Value::operator[]( const CppTL::ConstString &key ) const -{ - return (*this)[ key.c_str() ]; -} -# endif - - -Value & -Value::append( const Value &value ) -{ - return (*this)[size()] = value; -} - - -Value -Value::get( const char *key, - const Value &defaultValue ) const -{ - const Value *value = &((*this)[key]); - return value == &null ? defaultValue : *value; -} - - -Value -Value::get( const std::string &key, - const Value &defaultValue ) const -{ - return get( key.c_str(), defaultValue ); -} - -Value -Value::removeMember( const char* key ) -{ - JSON_ASSERT( type_ == nullValue || type_ == objectValue ); - if ( type_ == nullValue ) - return null; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString actualKey( key, CZString::noDuplication ); - ObjectValues::iterator it = value_.map_->find( actualKey ); - if ( it == value_.map_->end() ) - return null; - Value old(it->second); - value_.map_->erase(it); - return old; -#else - Value *value = value_.map_->find( key ); - if (value){ - Value old(*value); - value_.map_.remove( key ); - return old; - } else { - return null; - } -#endif -} - -Value -Value::removeMember( const std::string &key ) -{ - return removeMember( key.c_str() ); -} - -# ifdef JSON_USE_CPPTL -Value -Value::get( const CppTL::ConstString &key, - const Value &defaultValue ) const -{ - return get( key.c_str(), defaultValue ); -} -# endif - -bool -Value::isMember( const char *key ) const -{ - const Value *value = &((*this)[key]); - return value != &null; -} - - -bool -Value::isMember( const std::string &key ) const -{ - return isMember( key.c_str() ); -} - - -# ifdef JSON_USE_CPPTL -bool -Value::isMember( const CppTL::ConstString &key ) const -{ - return isMember( key.c_str() ); -} -#endif - -Value::Members -Value::getMemberNames() const -{ - JSON_ASSERT( type_ == nullValue || type_ == objectValue ); - if ( type_ == nullValue ) - return Value::Members(); - Members members; - members.reserve( value_.map_->size() ); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - ObjectValues::const_iterator it = value_.map_->begin(); - ObjectValues::const_iterator itEnd = value_.map_->end(); - for ( ; it != itEnd; ++it ) - members.push_back( std::string( (*it).first.c_str() ) ); -#else - ValueInternalMap::IteratorState it; - ValueInternalMap::IteratorState itEnd; - value_.map_->makeBeginIterator( it ); - value_.map_->makeEndIterator( itEnd ); - for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) ) - members.push_back( std::string( ValueInternalMap::key( it ) ) ); -#endif - return members; -} -// -//# ifdef JSON_USE_CPPTL -//EnumMemberNames -//Value::enumMemberNames() const -//{ -// if ( type_ == objectValue ) -// { -// return CppTL::Enum::any( CppTL::Enum::transform( -// CppTL::Enum::keys( *(value_.map_), CppTL::Type() ), -// MemberNamesTransform() ) ); -// } -// return EnumMemberNames(); -//} -// -// -//EnumValues -//Value::enumValues() const -//{ -// if ( type_ == objectValue || type_ == arrayValue ) -// return CppTL::Enum::anyValues( *(value_.map_), -// CppTL::Type() ); -// return EnumValues(); -//} -// -//# endif - - -bool -Value::isNull() const -{ - return type_ == nullValue; -} - - -bool -Value::isBool() const -{ - return type_ == booleanValue; -} - - -bool -Value::isInt() const -{ - return type_ == intValue; -} - - -bool -Value::isUInt() const -{ - return type_ == uintValue; -} - - -bool -Value::isIntegral() const -{ - return type_ == intValue - || type_ == uintValue - || type_ == booleanValue; -} - - -bool -Value::isDouble() const -{ - return type_ == realValue; -} - - -bool -Value::isNumeric() const -{ - return isIntegral() || isDouble(); -} - - -bool -Value::isString() const -{ - return type_ == stringValue; -} - - -bool -Value::isArray() const -{ - return type_ == nullValue || type_ == arrayValue; -} - - -bool -Value::isObject() const -{ - return type_ == nullValue || type_ == objectValue; -} - - -void -Value::setComment( const char *comment, - CommentPlacement placement ) -{ - if ( !comments_ ) - comments_ = new CommentInfo[numberOfCommentPlacement]; - comments_[placement].setComment( comment ); -} - - -void -Value::setComment( const std::string &comment, - CommentPlacement placement ) -{ - setComment( comment.c_str(), placement ); -} - - -bool -Value::hasComment( CommentPlacement placement ) const -{ - return comments_ != 0 && comments_[placement].comment_ != 0; -} - -std::string -Value::getComment( CommentPlacement placement ) const -{ - if ( hasComment(placement) ) - return comments_[placement].comment_; - return ""; -} - - -std::string -Value::toStyledString() const -{ - StyledWriter writer; - return writer.write( *this ); -} - - -Value::const_iterator -Value::begin() const -{ - switch ( type_ ) - { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if ( value_.array_ ) - { - ValueInternalArray::IteratorState it; - value_.array_->makeBeginIterator( it ); - return const_iterator( it ); - } - break; - case objectValue: - if ( value_.map_ ) - { - ValueInternalMap::IteratorState it; - value_.map_->makeBeginIterator( it ); - return const_iterator( it ); - } - break; -#else - case arrayValue: - case objectValue: - if ( value_.map_ ) - return const_iterator( value_.map_->begin() ); - break; -#endif - default: - break; - } - return const_iterator(); -} - -Value::const_iterator -Value::end() const -{ - switch ( type_ ) - { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if ( value_.array_ ) - { - ValueInternalArray::IteratorState it; - value_.array_->makeEndIterator( it ); - return const_iterator( it ); - } - break; - case objectValue: - if ( value_.map_ ) - { - ValueInternalMap::IteratorState it; - value_.map_->makeEndIterator( it ); - return const_iterator( it ); - } - break; -#else - case arrayValue: - case objectValue: - if ( value_.map_ ) - return const_iterator( value_.map_->end() ); - break; -#endif - default: - break; - } - return const_iterator(); -} - - -Value::iterator -Value::begin() -{ - switch ( type_ ) - { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if ( value_.array_ ) - { - ValueInternalArray::IteratorState it; - value_.array_->makeBeginIterator( it ); - return iterator( it ); - } - break; - case objectValue: - if ( value_.map_ ) - { - ValueInternalMap::IteratorState it; - value_.map_->makeBeginIterator( it ); - return iterator( it ); - } - break; -#else - case arrayValue: - case objectValue: - if ( value_.map_ ) - return iterator( value_.map_->begin() ); - break; -#endif - default: - break; - } - return iterator(); -} - -Value::iterator -Value::end() -{ - switch ( type_ ) - { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if ( value_.array_ ) - { - ValueInternalArray::IteratorState it; - value_.array_->makeEndIterator( it ); - return iterator( it ); - } - break; - case objectValue: - if ( value_.map_ ) - { - ValueInternalMap::IteratorState it; - value_.map_->makeEndIterator( it ); - return iterator( it ); - } - break; -#else - case arrayValue: - case objectValue: - if ( value_.map_ ) - return iterator( value_.map_->end() ); - break; -#endif - default: - break; - } - return iterator(); -} - - -// class PathArgument -// ////////////////////////////////////////////////////////////////// - -PathArgument::PathArgument() - : kind_( kindNone ) -{ -} - - -PathArgument::PathArgument( ArrayIndex index ) - : index_( index ) - , kind_( kindIndex ) -{ -} - - -PathArgument::PathArgument( const char *key ) - : key_( key ) - , kind_( kindKey ) -{ -} - - -PathArgument::PathArgument( const std::string &key ) - : key_( key.c_str() ) - , kind_( kindKey ) -{ -} - -// class Path -// ////////////////////////////////////////////////////////////////// - -Path::Path( const std::string &path, - const PathArgument &a1, - const PathArgument &a2, - const PathArgument &a3, - const PathArgument &a4, - const PathArgument &a5 ) -{ - InArgs in; - in.push_back( &a1 ); - in.push_back( &a2 ); - in.push_back( &a3 ); - in.push_back( &a4 ); - in.push_back( &a5 ); - makePath( path, in ); -} - - -void -Path::makePath( const std::string &path, - const InArgs &in ) -{ - const char *current = path.c_str(); - const char *end = current + path.length(); - InArgs::const_iterator itInArg = in.begin(); - while ( current != end ) - { - if ( *current == '[' ) - { - ++current; - if ( *current == '%' ) - addPathInArg( path, in, itInArg, PathArgument::kindIndex ); - else - { - ArrayIndex index = 0; - for ( ; current != end && *current >= '0' && *current <= '9'; ++current ) - index = index * 10 + ArrayIndex(*current - '0'); - args_.push_back( index ); - } - if ( current == end || *current++ != ']' ) - invalidPath( path, int(current - path.c_str()) ); - } - else if ( *current == '%' ) - { - addPathInArg( path, in, itInArg, PathArgument::kindKey ); - ++current; - } - else if ( *current == '.' ) - { - ++current; - } - else - { - const char *beginName = current; - while ( current != end && !strchr( "[.", *current ) ) - ++current; - args_.push_back( std::string( beginName, current ) ); - } - } -} - - -void -Path::addPathInArg( const std::string &path, - const InArgs &in, - InArgs::const_iterator &itInArg, - PathArgument::Kind kind ) -{ - if ( itInArg == in.end() ) - { - // Error: missing argument %d - } - else if ( (*itInArg)->kind_ != kind ) - { - // Error: bad argument type - } - else - { - args_.push_back( **itInArg ); - } -} - - -void -Path::invalidPath( const std::string &path, - int location ) -{ - // Error: invalid path. -} - - -const Value & -Path::resolve( const Value &root ) const -{ - const Value *node = &root; - for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it ) - { - const PathArgument &arg = *it; - if ( arg.kind_ == PathArgument::kindIndex ) - { - if ( !node->isArray() || node->isValidIndex( arg.index_ ) ) - { - // Error: unable to resolve path (array value expected at position... - } - node = &((*node)[arg.index_]); - } - else if ( arg.kind_ == PathArgument::kindKey ) - { - if ( !node->isObject() ) - { - // Error: unable to resolve path (object value expected at position...) - } - node = &((*node)[arg.key_]); - if ( node == &Value::null ) - { - // Error: unable to resolve path (object has no member named '' at position...) - } - } - } - return *node; -} - - -Value -Path::resolve( const Value &root, - const Value &defaultValue ) const -{ - const Value *node = &root; - for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it ) - { - const PathArgument &arg = *it; - if ( arg.kind_ == PathArgument::kindIndex ) - { - if ( !node->isArray() || node->isValidIndex( arg.index_ ) ) - return defaultValue; - node = &((*node)[arg.index_]); - } - else if ( arg.kind_ == PathArgument::kindKey ) - { - if ( !node->isObject() ) - return defaultValue; - node = &((*node)[arg.key_]); - if ( node == &Value::null ) - return defaultValue; - } - } - return *node; -} - - -Value & -Path::make( Value &root ) const -{ - Value *node = &root; - for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it ) - { - const PathArgument &arg = *it; - if ( arg.kind_ == PathArgument::kindIndex ) - { - if ( !node->isArray() ) - { - // Error: node is not an array at position ... - } - node = &((*node)[arg.index_]); - } - else if ( arg.kind_ == PathArgument::kindKey ) - { - if ( !node->isObject() ) - { - // Error: node is not an object at position... - } - node = &((*node)[arg.key_]); - } - } - return *node; -} - - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_value.cpp -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_writer.cpp -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -# include -# include "json_tool.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include -#include -#include - -#if _MSC_VER >= 1400 // VC++ 8.0 -#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated. -#endif - -namespace Json { - -static bool containsControlCharacter( const char* str ) -{ - while ( *str ) - { - if ( isControlCharacter( *(str++) ) ) - return true; - } - return false; -} - - -std::string valueToString( LargestInt value ) -{ - UIntToStringBuffer buffer; - char *current = buffer + sizeof(buffer); - bool isNegative = value < 0; - if ( isNegative ) - value = -value; - uintToString( LargestUInt(value), current ); - if ( isNegative ) - *--current = '-'; - assert( current >= buffer ); - return current; -} - - -std::string valueToString( LargestUInt value ) -{ - UIntToStringBuffer buffer; - char *current = buffer + sizeof(buffer); - uintToString( value, current ); - assert( current >= buffer ); - return current; -} - -#if defined(JSON_HAS_INT64) - -std::string valueToString( Int value ) -{ - return valueToString( LargestInt(value) ); -} - - -std::string valueToString( UInt value ) -{ - return valueToString( LargestUInt(value) ); -} - -#endif // # if defined(JSON_HAS_INT64) - - -std::string valueToString( double value ) -{ - char buffer[32]; -#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning. - sprintf_s(buffer, sizeof(buffer), "%#.16g", value); -#else - sprintf(buffer, "%#.16g", value); -#endif - char* ch = buffer + strlen(buffer) - 1; - if (*ch != '0') return buffer; // nothing to truncate, so save time - while(ch > buffer && *ch == '0'){ - --ch; - } - char* last_nonzero = ch; - while(ch >= buffer){ - switch(*ch){ - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - --ch; - continue; - case '.': - // Truncate zeroes to save bytes in output, but keep one. - *(last_nonzero+2) = '\0'; - return buffer; - default: - return buffer; - } - } - return buffer; -} - - -std::string valueToString( bool value ) -{ - return value ? "true" : "false"; -} - -std::string valueToQuotedString( const char *value ) -{ - // Not sure how to handle unicode... - if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value )) - return std::string("\"") + value + "\""; - // We have to walk value and escape any special characters. - // Appending to std::string is not efficient, but this should be rare. - // (Note: forward slashes are *not* rare, but I am not escaping them.) - std::string::size_type maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL - std::string result; - result.reserve(maxsize); // to avoid lots of mallocs - result += "\""; - for (const char* c=value; *c != 0; ++c) - { - switch(*c) - { - case '\"': - result += "\\\""; - break; - case '\\': - result += "\\\\"; - break; - case '\b': - result += "\\b"; - break; - case '\f': - result += "\\f"; - break; - case '\n': - result += "\\n"; - break; - case '\r': - result += "\\r"; - break; - case '\t': - result += "\\t"; - break; - //case '/': - // Even though \/ is considered a legal escape in JSON, a bare - // slash is also legal, so I see no reason to escape it. - // (I hope I am not misunderstanding something. - // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); - result += oss.str(); - } - else - { - result += *c; - } - break; - } - } - result += "\""; - return result; -} - -// Class Writer -// ////////////////////////////////////////////////////////////////// -Writer::~Writer() -{ -} - - -// Class FastWriter -// ////////////////////////////////////////////////////////////////// - -FastWriter::FastWriter() - : yamlCompatiblityEnabled_( false ) -{ -} - - -void -FastWriter::enableYAMLCompatibility() -{ - yamlCompatiblityEnabled_ = true; -} - - -std::string -FastWriter::write( const Value &root ) -{ - document_ = ""; - writeValue( root ); - document_ += "\n"; - return document_; -} - - -void -FastWriter::writeValue( const Value &value ) -{ - switch ( value.type() ) - { - case nullValue: - document_ += "null"; - break; - case intValue: - document_ += valueToString( value.asLargestInt() ); - break; - case uintValue: - document_ += valueToString( value.asLargestUInt() ); - break; - case realValue: - document_ += valueToString( value.asDouble() ); - break; - case stringValue: - document_ += valueToQuotedString( value.asCString() ); - break; - case booleanValue: - document_ += valueToString( value.asBool() ); - break; - case arrayValue: - { - document_ += "["; - int size = value.size(); - for ( int index =0; index < size; ++index ) - { - if ( index > 0 ) - document_ += ","; - writeValue( value[index] ); - } - document_ += "]"; - } - break; - case objectValue: - { - Value::Members members( value.getMemberNames() ); - document_ += "{"; - for ( Value::Members::iterator it = members.begin(); - it != members.end(); - ++it ) - { - const std::string &name = *it; - if ( it != members.begin() ) - document_ += ","; - document_ += valueToQuotedString( name.c_str() ); - document_ += yamlCompatiblityEnabled_ ? ": " - : ":"; - writeValue( value[name] ); - } - document_ += "}"; - } - break; - } -} - - -// Class StyledWriter -// ////////////////////////////////////////////////////////////////// - -StyledWriter::StyledWriter() - : rightMargin_( 74 ) - , indentSize_( 3 ) -{ -} - - -std::string -StyledWriter::write( const Value &root ) -{ - document_ = ""; - addChildValues_ = false; - indentString_ = ""; - writeCommentBeforeValue( root ); - writeValue( root ); - writeCommentAfterValueOnSameLine( root ); - document_ += "\n"; - return document_; -} - - -void -StyledWriter::writeValue( const Value &value ) -{ - switch ( value.type() ) - { - case nullValue: - pushValue( "null" ); - break; - case intValue: - pushValue( valueToString( value.asLargestInt() ) ); - break; - case uintValue: - pushValue( valueToString( value.asLargestUInt() ) ); - break; - case realValue: - pushValue( valueToString( value.asDouble() ) ); - break; - case stringValue: - pushValue( valueToQuotedString( value.asCString() ) ); - break; - case booleanValue: - pushValue( valueToString( value.asBool() ) ); - break; - case arrayValue: - writeArrayValue( value); - break; - case objectValue: - { - Value::Members members( value.getMemberNames() ); - if ( members.empty() ) - pushValue( "{}" ); - else - { - writeWithIndent( "{" ); - indent(); - Value::Members::iterator it = members.begin(); - for (;;) - { - const std::string &name = *it; - const Value &childValue = value[name]; - writeCommentBeforeValue( childValue ); - writeWithIndent( valueToQuotedString( name.c_str() ) ); - document_ += " : "; - writeValue( childValue ); - if ( ++it == members.end() ) - { - writeCommentAfterValueOnSameLine( childValue ); - break; - } - document_ += ","; - writeCommentAfterValueOnSameLine( childValue ); - } - unindent(); - writeWithIndent( "}" ); - } - } - break; - } -} - - -void -StyledWriter::writeArrayValue( const Value &value ) -{ - unsigned size = value.size(); - if ( size == 0 ) - pushValue( "[]" ); - else - { - bool isArrayMultiLine = isMultineArray( value ); - if ( isArrayMultiLine ) - { - writeWithIndent( "[" ); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index =0; - for (;;) - { - const Value &childValue = value[index]; - writeCommentBeforeValue( childValue ); - if ( hasChildValue ) - writeWithIndent( childValues_[index] ); - else - { - writeIndent(); - writeValue( childValue ); - } - if ( ++index == size ) - { - writeCommentAfterValueOnSameLine( childValue ); - break; - } - document_ += ","; - writeCommentAfterValueOnSameLine( childValue ); - } - unindent(); - writeWithIndent( "]" ); - } - else // output on a single line - { - assert( childValues_.size() == size ); - document_ += "[ "; - for ( unsigned index =0; index < size; ++index ) - { - if ( index > 0 ) - document_ += ", "; - document_ += childValues_[index]; - } - document_ += " ]"; - } - } -} - - -bool -StyledWriter::isMultineArray( const Value &value ) -{ - int size = value.size(); - bool isMultiLine = size*3 >= rightMargin_ ; - childValues_.clear(); - for ( int index =0; index < size && !isMultiLine; ++index ) - { - const Value &childValue = value[index]; - isMultiLine = isMultiLine || - ( (childValue.isArray() || childValue.isObject()) && - childValue.size() > 0 ); - } - if ( !isMultiLine ) // check if line length > max line length - { - childValues_.reserve( size ); - addChildValues_ = true; - int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]' - for ( int index =0; index < size && !isMultiLine; ++index ) - { - writeValue( value[index] ); - lineLength += int( childValues_[index].length() ); - isMultiLine = isMultiLine && hasCommentForValue( value[index] ); - } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; - } - return isMultiLine; -} - - -void -StyledWriter::pushValue( const std::string &value ) -{ - if ( addChildValues_ ) - childValues_.push_back( value ); - else - document_ += value; -} - - -void -StyledWriter::writeIndent() -{ - if ( !document_.empty() ) - { - char last = document_[document_.length()-1]; - if ( last == ' ' ) // already indented - return; - if ( last != '\n' ) // Comments may add new-line - document_ += '\n'; - } - document_ += indentString_; -} - - -void -StyledWriter::writeWithIndent( const std::string &value ) -{ - writeIndent(); - document_ += value; -} - - -void -StyledWriter::indent() -{ - indentString_ += std::string( indentSize_, ' ' ); -} - - -void -StyledWriter::unindent() -{ - assert( int(indentString_.size()) >= indentSize_ ); - indentString_.resize( indentString_.size() - indentSize_ ); -} - - -void -StyledWriter::writeCommentBeforeValue( const Value &root ) -{ - if ( !root.hasComment( commentBefore ) ) - return; - document_ += normalizeEOL( root.getComment( commentBefore ) ); - document_ += "\n"; -} - - -void -StyledWriter::writeCommentAfterValueOnSameLine( const Value &root ) -{ - if ( root.hasComment( commentAfterOnSameLine ) ) - document_ += " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) ); - - if ( root.hasComment( commentAfter ) ) - { - document_ += "\n"; - document_ += normalizeEOL( root.getComment( commentAfter ) ); - document_ += "\n"; - } -} - - -bool -StyledWriter::hasCommentForValue( const Value &value ) -{ - return value.hasComment( commentBefore ) - || value.hasComment( commentAfterOnSameLine ) - || value.hasComment( commentAfter ); -} - - -std::string -StyledWriter::normalizeEOL( const std::string &text ) -{ - std::string normalized; - normalized.reserve( text.length() ); - const char *begin = text.c_str(); - const char *end = begin + text.length(); - const char *current = begin; - while ( current != end ) - { - char c = *current++; - if ( c == '\r' ) // mac or dos EOL - { - if ( *current == '\n' ) // convert dos EOL - ++current; - normalized += '\n'; - } - else // handle unix EOL & other char - normalized += c; - } - return normalized; -} - - -// Class StyledStreamWriter -// ////////////////////////////////////////////////////////////////// - -StyledStreamWriter::StyledStreamWriter( std::string indentation ) - : document_(NULL) - , rightMargin_( 74 ) - , indentation_( indentation ) -{ -} - - -void -StyledStreamWriter::write( std::ostream &out, const Value &root ) -{ - document_ = &out; - addChildValues_ = false; - indentString_ = ""; - writeCommentBeforeValue( root ); - writeValue( root ); - writeCommentAfterValueOnSameLine( root ); - *document_ << "\n"; - document_ = NULL; // Forget the stream, for safety. -} - - -void -StyledStreamWriter::writeValue( const Value &value ) -{ - switch ( value.type() ) - { - case nullValue: - pushValue( "null" ); - break; - case intValue: - pushValue( valueToString( value.asLargestInt() ) ); - break; - case uintValue: - pushValue( valueToString( value.asLargestUInt() ) ); - break; - case realValue: - pushValue( valueToString( value.asDouble() ) ); - break; - case stringValue: - pushValue( valueToQuotedString( value.asCString() ) ); - break; - case booleanValue: - pushValue( valueToString( value.asBool() ) ); - break; - case arrayValue: - writeArrayValue( value); - break; - case objectValue: - { - Value::Members members( value.getMemberNames() ); - if ( members.empty() ) - pushValue( "{}" ); - else - { - writeWithIndent( "{" ); - indent(); - Value::Members::iterator it = members.begin(); - for (;;) - { - const std::string &name = *it; - const Value &childValue = value[name]; - writeCommentBeforeValue( childValue ); - writeWithIndent( valueToQuotedString( name.c_str() ) ); - *document_ << " : "; - writeValue( childValue ); - if ( ++it == members.end() ) - { - writeCommentAfterValueOnSameLine( childValue ); - break; - } - *document_ << ","; - writeCommentAfterValueOnSameLine( childValue ); - } - unindent(); - writeWithIndent( "}" ); - } - } - break; - } -} - - -void -StyledStreamWriter::writeArrayValue( const Value &value ) -{ - unsigned size = value.size(); - if ( size == 0 ) - pushValue( "[]" ); - else - { - bool isArrayMultiLine = isMultineArray( value ); - if ( isArrayMultiLine ) - { - writeWithIndent( "[" ); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index =0; - for (;;) - { - const Value &childValue = value[index]; - writeCommentBeforeValue( childValue ); - if ( hasChildValue ) - writeWithIndent( childValues_[index] ); - else - { - writeIndent(); - writeValue( childValue ); - } - if ( ++index == size ) - { - writeCommentAfterValueOnSameLine( childValue ); - break; - } - *document_ << ","; - writeCommentAfterValueOnSameLine( childValue ); - } - unindent(); - writeWithIndent( "]" ); - } - else // output on a single line - { - assert( childValues_.size() == size ); - *document_ << "[ "; - for ( unsigned index =0; index < size; ++index ) - { - if ( index > 0 ) - *document_ << ", "; - *document_ << childValues_[index]; - } - *document_ << " ]"; - } - } -} - - -bool -StyledStreamWriter::isMultineArray( const Value &value ) -{ - int size = value.size(); - bool isMultiLine = size*3 >= rightMargin_ ; - childValues_.clear(); - for ( int index =0; index < size && !isMultiLine; ++index ) - { - const Value &childValue = value[index]; - isMultiLine = isMultiLine || - ( (childValue.isArray() || childValue.isObject()) && - childValue.size() > 0 ); - } - if ( !isMultiLine ) // check if line length > max line length - { - childValues_.reserve( size ); - addChildValues_ = true; - int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]' - for ( int index =0; index < size && !isMultiLine; ++index ) - { - writeValue( value[index] ); - lineLength += int( childValues_[index].length() ); - isMultiLine = isMultiLine && hasCommentForValue( value[index] ); - } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; - } - return isMultiLine; -} - - -void -StyledStreamWriter::pushValue( const std::string &value ) -{ - if ( addChildValues_ ) - childValues_.push_back( value ); - else - *document_ << value; -} - - -void -StyledStreamWriter::writeIndent() -{ - /* - Some comments in this method would have been nice. ;-) - - if ( !document_.empty() ) - { - char last = document_[document_.length()-1]; - if ( last == ' ' ) // already indented - return; - if ( last != '\n' ) // Comments may add new-line - *document_ << '\n'; - } - */ - *document_ << '\n' << indentString_; -} - - -void -StyledStreamWriter::writeWithIndent( const std::string &value ) -{ - writeIndent(); - *document_ << value; -} - - -void -StyledStreamWriter::indent() -{ - indentString_ += indentation_; -} - - -void -StyledStreamWriter::unindent() -{ - assert( indentString_.size() >= indentation_.size() ); - indentString_.resize( indentString_.size() - indentation_.size() ); -} - - -void -StyledStreamWriter::writeCommentBeforeValue( const Value &root ) -{ - if ( !root.hasComment( commentBefore ) ) - return; - *document_ << normalizeEOL( root.getComment( commentBefore ) ); - *document_ << "\n"; -} - - -void -StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root ) -{ - if ( root.hasComment( commentAfterOnSameLine ) ) - *document_ << " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) ); - - if ( root.hasComment( commentAfter ) ) - { - *document_ << "\n"; - *document_ << normalizeEOL( root.getComment( commentAfter ) ); - *document_ << "\n"; - } -} - - -bool -StyledStreamWriter::hasCommentForValue( const Value &value ) -{ - return value.hasComment( commentBefore ) - || value.hasComment( commentAfterOnSameLine ) - || value.hasComment( commentAfter ); -} - - -std::string -StyledStreamWriter::normalizeEOL( const std::string &text ) -{ - std::string normalized; - normalized.reserve( text.length() ); - const char *begin = text.c_str(); - const char *end = begin + text.length(); - const char *current = begin; - while ( current != end ) - { - char c = *current++; - if ( c == '\r' ) // mac or dos EOL - { - if ( *current == '\n' ) // convert dos EOL - ++current; - normalized += '\n'; - } - else // handle unix EOL & other char - normalized += c; - } - return normalized; -} - - -std::ostream& operator<<( std::ostream &sout, const Value &root ) -{ - Json::StyledStreamWriter writer; - writer.write(sout, root); - return sout; -} - - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_writer.cpp -// ////////////////////////////////////////////////////////////////////// - - - - - diff --git a/find-object/src/resources.qrc b/find-object/src/resources.qrc deleted file mode 100644 index 579bf5b0..00000000 --- a/find-object/src/resources.qrc +++ /dev/null @@ -1,8 +0,0 @@ - - - resources/Find-Object.png - resources/TheWorkingGroup_video_pause.ico - resources/TheWorkingGroup_video_play.ico - resources/TheWorkingGroup_video_stop.ico - - diff --git a/find-object/src/resources/Find-Object.png b/find-object/src/resources/Find-Object.png deleted file mode 100644 index 72ff182e..00000000 Binary files a/find-object/src/resources/Find-Object.png and /dev/null differ diff --git a/find-object/src/resources/TheWorkingGroup_video_pause.ico b/find-object/src/resources/TheWorkingGroup_video_pause.ico deleted file mode 100644 index 17accbfa..00000000 Binary files a/find-object/src/resources/TheWorkingGroup_video_pause.ico and /dev/null differ diff --git a/find-object/src/resources/TheWorkingGroup_video_play.ico b/find-object/src/resources/TheWorkingGroup_video_play.ico deleted file mode 100644 index 1bdf4b6a..00000000 Binary files a/find-object/src/resources/TheWorkingGroup_video_play.ico and /dev/null differ diff --git a/find-object/src/resources/TheWorkingGroup_video_stop.ico b/find-object/src/resources/TheWorkingGroup_video_stop.ico deleted file mode 100644 index 364eef42..00000000 Binary files a/find-object/src/resources/TheWorkingGroup_video_stop.ico and /dev/null differ diff --git a/find-object/src/ros1/CameraROS.cpp b/find-object/src/ros1/CameraROS.cpp deleted file mode 100644 index da1ca00c..00000000 --- a/find-object/src/ros1/CameraROS.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "find_object/Settings.h" - -#include -#include "CameraROS.h" -#include - -using namespace find_object; - -CameraROS::CameraROS(bool subscribeDepth, QObject * parent) : - Camera(parent), - subscribeDepth_(subscribeDepth), - approxSync_(0), - exactSync_(0) -{ - ros::NodeHandle nh; // public - ros::NodeHandle pnh("~"); // private - - qRegisterMetaType("ros::Time"); - qRegisterMetaType("cv::Mat"); - - if(!subscribeDepth_) - { - image_transport::ImageTransport it(nh); - imageSub_ = it.subscribe(nh.resolveName("image"), 1, &CameraROS::imgReceivedCallback, this); - } - else - { - int queueSize = 10; - bool approxSync = true; - pnh.param("queue_size", queueSize, queueSize); - pnh.param("approx_sync", approxSync, approxSync); - ROS_INFO("find_object_ros: queue_size = %d", queueSize); - ROS_INFO("find_object_ros: approx_sync = %s", approxSync?"true":"false"); - - ros::NodeHandle rgb_nh(nh, "rgb"); - ros::NodeHandle rgb_pnh(pnh, "rgb"); - ros::NodeHandle depth_nh(nh, "depth_registered"); - ros::NodeHandle depth_pnh(pnh, "depth_registered"); - image_transport::ImageTransport rgb_it(rgb_nh); - image_transport::ImageTransport depth_it(depth_nh); - image_transport::TransportHints hintsRgb("raw", ros::TransportHints(), rgb_pnh); - image_transport::TransportHints hintsDepth("raw", ros::TransportHints(), depth_pnh); - - rgbSub_.subscribe(rgb_it, rgb_nh.resolveName("image_rect_color"), 1, hintsRgb); - depthSub_.subscribe(depth_it, depth_nh.resolveName("image_raw"), 1, hintsDepth); - cameraInfoSub_.subscribe(depth_nh, "camera_info", 1); - if(approxSync) - { - approxSync_ = new message_filters::Synchronizer(MyApproxSyncPolicy(queueSize), rgbSub_, depthSub_, cameraInfoSub_); - approxSync_->registerCallback(boost::bind(&CameraROS::imgDepthReceivedCallback, this, - boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3)); - } - else - { - exactSync_ = new message_filters::Synchronizer(MyExactSyncPolicy(queueSize), rgbSub_, depthSub_, cameraInfoSub_); - exactSync_->registerCallback(boost::bind(&CameraROS::imgDepthReceivedCallback, this, - boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3)); - } - } -} -CameraROS::~CameraROS() -{ - delete approxSync_; - delete exactSync_; -} - -QStringList CameraROS::subscribedTopics() const -{ - QStringList topics; - if(subscribeDepth_) - { - topics.append(rgbSub_.getTopic().c_str()); - topics.append(depthSub_.getTopic().c_str()); - topics.append(cameraInfoSub_.getTopic().c_str()); - } - else - { - topics.append(imageSub_.getTopic().c_str()); - } - return topics; -} - -bool CameraROS::start() -{ - this->startTimer(); - return true; -} - -void CameraROS::stop() -{ - this->stopTimer(); -} - -void CameraROS::takeImage() -{ - ros::spinOnce(); -} - -void CameraROS::imgReceivedCallback(const sensor_msgs::ImageConstPtr & msg) -{ - if(msg->data.size()) - { - cv::Mat image; - cv_bridge::CvImageConstPtr imgPtr = cv_bridge::toCvShare(msg); - try - { - if(msg->encoding.compare(sensor_msgs::image_encodings::MONO8) == 0 || - msg->encoding.compare(sensor_msgs::image_encodings::MONO16) == 0) - { - image = cv_bridge::cvtColor(imgPtr, "mono8")->image; - } - else - { - image = cv_bridge::cvtColor(imgPtr, "bgr8")->image; - } - - Q_EMIT imageReceived(image, Header(msg->header.frame_id.c_str(), msg->header.stamp.sec, msg->header.stamp.nsec), cv::Mat(), 0.0f); - } - catch(const cv_bridge::Exception & e) - { - ROS_ERROR("find_object_ros: Could not convert input image to mono8 or bgr8 format, encoding detected is %s... cv_bridge exception: %s", msg->encoding.c_str(), e.what()); - } - } -} - -void CameraROS::imgDepthReceivedCallback( - const sensor_msgs::ImageConstPtr& rgbMsg, - const sensor_msgs::ImageConstPtr& depthMsg, - const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg) -{ - if(depthMsg->encoding.compare(sensor_msgs::image_encodings::TYPE_16UC1)!=0 && - depthMsg->encoding.compare(sensor_msgs::image_encodings::TYPE_32FC1)!=0) - { - ROS_ERROR("find_object_ros: Depth image type must be 32FC1 or 16UC1"); - return; - } - - if(rgbMsg->data.size()) - { - cv_bridge::CvImageConstPtr ptr = cv_bridge::toCvShare(rgbMsg); - cv_bridge::CvImageConstPtr ptrDepth = cv_bridge::toCvShare(depthMsg); - float depthConstant = 1.0f/cameraInfoMsg->K[4]; - - cv::Mat image; - cv_bridge::CvImageConstPtr imgPtr = cv_bridge::toCvShare(rgbMsg); - try - { - if(rgbMsg->encoding.compare(sensor_msgs::image_encodings::MONO8) == 0 || - rgbMsg->encoding.compare(sensor_msgs::image_encodings::MONO16) == 0) - { - image = cv_bridge::cvtColor(imgPtr, "mono8")->image; - } - else - { - image = cv_bridge::cvtColor(imgPtr, "bgr8")->image; - } - - Q_EMIT imageReceived(image, Header(rgbMsg->header.frame_id.c_str(), rgbMsg->header.stamp.sec, rgbMsg->header.stamp.nsec), ptrDepth->image, depthConstant); - } - catch(const cv_bridge::Exception & e) - { - ROS_ERROR("find_object_ros: Could not convert input image to mono8 or bgr8 format, encoding detected is %s... cv_bridge exception: %s", rgbMsg->encoding.c_str(), e.what()); - } - } - - -} diff --git a/find-object/src/ros1/CameraROS.h b/find-object/src/ros1/CameraROS.h deleted file mode 100644 index 2419ec1d..00000000 --- a/find-object/src/ros1/CameraROS.h +++ /dev/null @@ -1,91 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef CAMERAROS_H_ -#define CAMERAROS_H_ - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "find_object/Camera.h" -#include - -class CameraROS : public find_object::Camera { - Q_OBJECT -public: - CameraROS(bool subscribeDepth, QObject * parent = 0); - virtual ~CameraROS(); - - virtual bool start(); - virtual void stop(); - - QStringList subscribedTopics() const; - -private Q_SLOTS: - virtual void takeImage(); - -private: - void imgReceivedCallback(const sensor_msgs::ImageConstPtr & msg); - void imgDepthReceivedCallback( - const sensor_msgs::ImageConstPtr& rgbMsg, - const sensor_msgs::ImageConstPtr& depthMsg, - const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg); - -private: - bool subscribeDepth_; - image_transport::Subscriber imageSub_; - - image_transport::SubscriberFilter rgbSub_; - image_transport::SubscriberFilter depthSub_; - message_filters::Subscriber cameraInfoSub_; - - typedef message_filters::sync_policies::ApproximateTime< - sensor_msgs::Image, - sensor_msgs::Image, - sensor_msgs::CameraInfo> MyApproxSyncPolicy; - message_filters::Synchronizer * approxSync_; - - typedef message_filters::sync_policies::ExactTime< - sensor_msgs::Image, - sensor_msgs::Image, - sensor_msgs::CameraInfo> MyExactSyncPolicy; - message_filters::Synchronizer * exactSync_; -}; - -#endif /* CAMERAROS_H_ */ diff --git a/find-object/src/ros1/FindObjectROS.cpp b/find-object/src/ros1/FindObjectROS.cpp deleted file mode 100644 index d814534d..00000000 --- a/find-object/src/ros1/FindObjectROS.cpp +++ /dev/null @@ -1,350 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "FindObjectROS.h" -#include -#include "find_object_2d/ObjectsStamped.h" -#include "find_object_2d/DetectionInfo.h" - -#include - -using namespace find_object; - -FindObjectROS::FindObjectROS(QObject * parent) : - FindObject(true, parent), - objFramePrefix_("object"), - usePnP_(true) -{ - ros::NodeHandle pnh("~"); // public - pnh.param("object_prefix", objFramePrefix_, objFramePrefix_); - pnh.param("pnp", usePnP_, usePnP_); - ROS_INFO("object_prefix = %s", objFramePrefix_.c_str()); - ROS_INFO("pnp = %s", usePnP_?"true":"false"); - - ros::NodeHandle nh; // public - - pub_ = nh.advertise("objects", 1); - pubStamped_ = nh.advertise("objectsStamped", 1); - pubInfo_ = nh.advertise("info", 1); - - this->connect(this, SIGNAL(objectsFound(const find_object::DetectionInfo &, const find_object::Header &, const cv::Mat &, float)), this, SLOT(publish(const find_object::DetectionInfo &, const find_object::Header &, const cv::Mat &, float))); -} - -void FindObjectROS::publish(const find_object::DetectionInfo & info, const Header & header, const cv::Mat & depth, float depthConstant) -{ - // send tf before the message - if(info.objDetected_.size() && !depth.empty() && depthConstant != 0.0f) - { - std::vector transforms; - char multiSubId = 'b'; - int previousId = -1; - QMultiMap::const_iterator iterSizes=info.objDetectedSizes_.constBegin(); - for(QMultiMap::const_iterator iter=info.objDetected_.constBegin(); - iter!=info.objDetected_.constEnd(); - ++iter, ++iterSizes) - { - // get data - int id = iter.key(); - float objectWidth = iterSizes->width(); - float objectHeight = iterSizes->height(); - - QString multiSuffix; - if(id == previousId) - { - multiSuffix = QString("_") + multiSubId++; - } - else - { - multiSubId = 'b'; - } - previousId = id; - - // Find center of the object - QPointF center = iter->map(QPointF(objectWidth/2, objectHeight/2)); - cv::Vec3f center3D = this->getDepth(depth, - center.x()+0.5f, center.y()+0.5f, - float(depth.cols/2)-0.5f, float(depth.rows/2)-0.5f, - 1.0f/depthConstant, 1.0f/depthConstant); - - cv::Vec3f axisEndX; - cv::Vec3f axisEndY; - if(!usePnP_) - { - QPointF xAxis = iter->map(QPointF(3*objectWidth/4, objectHeight/2)); - axisEndX = this->getDepth(depth, - xAxis.x()+0.5f, xAxis.y()+0.5f, - float(depth.cols/2)-0.5f, float(depth.rows/2)-0.5f, - 1.0f/depthConstant, 1.0f/depthConstant); - - QPointF yAxis = iter->map(QPointF(objectWidth/2, 3*objectHeight/4)); - axisEndY = this->getDepth(depth, - yAxis.x()+0.5f, yAxis.y()+0.5f, - float(depth.cols/2)-0.5f, float(depth.rows/2)-0.5f, - 1.0f/depthConstant, 1.0f/depthConstant); - } - - if((std::isfinite(center3D.val[2]) && usePnP_) || - (std::isfinite(center3D.val[0]) && std::isfinite(center3D.val[1]) && std::isfinite(center3D.val[2]) && - std::isfinite(axisEndX.val[0]) && std::isfinite(axisEndX.val[1]) && std::isfinite(axisEndX.val[2]) && - std::isfinite(axisEndY.val[0]) && std::isfinite(axisEndY.val[1]) && std::isfinite(axisEndY.val[2]))) - { - tf::StampedTransform transform; - transform.setIdentity(); - transform.child_frame_id_ = QString("%1_%2%3").arg(objFramePrefix_.c_str()).arg(id).arg(multiSuffix).toStdString(); - transform.frame_id_ = header.frameId_.toStdString(); - transform.stamp_.sec = header.sec_; - transform.stamp_.nsec = header.nsec_; - - tf::Quaternion q; - if(usePnP_) - { - std::vector objectPoints(4); - std::vector imagePoints(4); - - objectPoints[0] = cv::Point3f(-0.5, -(objectHeight/objectWidth)/2.0f,0); - objectPoints[1] = cv::Point3f(0.5,-(objectHeight/objectWidth)/2.0f,0); - objectPoints[2] = cv::Point3f(0.5,(objectHeight/objectWidth)/2.0f,0); - objectPoints[3] = cv::Point3f(-0.5,(objectHeight/objectWidth)/2.0f,0); - - QPointF pt = iter->map(QPointF(0, 0)); - imagePoints[0] = cv::Point2f(pt.x(), pt.y()); - pt = iter->map(QPointF(objectWidth, 0)); - imagePoints[1] = cv::Point2f(pt.x(), pt.y()); - pt = iter->map(QPointF(objectWidth, objectHeight)); - imagePoints[2] = cv::Point2f(pt.x(), pt.y()); - pt = iter->map(QPointF(0, objectHeight)); - imagePoints[3] = cv::Point2f(pt.x(), pt.y()); - - cv::Mat cameraMatrix = cv::Mat::eye(3,3,CV_64FC1); - cameraMatrix.at(0,0) = 1.0f/depthConstant; - cameraMatrix.at(1,1) = 1.0f/depthConstant; - cameraMatrix.at(0,2) = float(depth.cols/2)-0.5f; - cameraMatrix.at(1,2) = float(depth.rows/2)-0.5f; - cv::Mat distCoeffs; - - cv::Mat rvec(1,3, CV_64FC1); - cv::Mat tvec(1,3, CV_64FC1); - cv::solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec); - - cv::Mat R; - cv::Rodrigues(rvec, R); - tf::Matrix3x3 rotationMatrix( - R.at(0,0), R.at(0,1), R.at(0,2), - R.at(1,0), R.at(1,1), R.at(1,2), - R.at(2,0), R.at(2,1), R.at(2,2)); - rotationMatrix.getRotation(q); - transform.setOrigin(tf::Vector3( - tvec.at(0)*(center3D.val[2]/tvec.at(2)), - tvec.at(1)*(center3D.val[2]/tvec.at(2)), - tvec.at(2)*(center3D.val[2]/tvec.at(2)))); - } - else - { - tf::Vector3 xAxis(axisEndX.val[0] - center3D.val[0], axisEndX.val[1] - center3D.val[1], axisEndX.val[2] - center3D.val[2]); - xAxis.normalize(); - tf::Vector3 yAxis(axisEndY.val[0] - center3D.val[0], axisEndY.val[1] - center3D.val[1], axisEndY.val[2] - center3D.val[2]); - yAxis.normalize(); - tf::Vector3 zAxis = xAxis.cross(yAxis); - zAxis.normalize(); - tf::Matrix3x3 rotationMatrix( - xAxis.x(), yAxis.x() ,zAxis.x(), - xAxis.y(), yAxis.y(), zAxis.y(), - xAxis.z(), yAxis.z(), zAxis.z()); - rotationMatrix.getRotation(q); - transform.setOrigin(tf::Vector3(center3D.val[0], center3D.val[1], center3D.val[2])); - } - - // set x axis going front of the object, with z up and z left - q *= tf::createQuaternionFromRPY(CV_PI/2.0, CV_PI/2.0, 0); - transform.setRotation(q.normalized()); - transforms.push_back(transform); - } - else - { - ROS_WARN("Object %d detected, center 2D at (%f,%f), but invalid depth, cannot set frame \"%s\"! " - "(maybe object is too near of the camera or bad depth image)\n", - id, - center.x(), center.y(), - QString("%1_%2").arg(objFramePrefix_.c_str()).arg(id).toStdString().c_str()); - } - } - if(transforms.size()) - { - tfBroadcaster_.sendTransform(transforms); - } - } - - if(pub_.getNumSubscribers() || pubStamped_.getNumSubscribers() || pubInfo_.getNumSubscribers()) - { - std_msgs::Float32MultiArray msg; - find_object_2d::ObjectsStamped msgStamped; - find_object_2d::DetectionInfo infoMsg; - if(pubInfo_.getNumSubscribers()) - { - infoMsg.ids.resize(info.objDetected_.size()); - infoMsg.widths.resize(info.objDetected_.size()); - infoMsg.heights.resize(info.objDetected_.size()); - infoMsg.file_paths.resize(info.objDetected_.size()); - infoMsg.inliers.resize(info.objDetected_.size()); - infoMsg.outliers.resize(info.objDetected_.size()); - infoMsg.homographies.resize(info.objDetected_.size()); - } - msg.data = std::vector(info.objDetected_.size()*12); - msgStamped.objects.data = std::vector(info.objDetected_.size()*12); - - ROS_ASSERT(info.objDetected_.size() == info.objDetectedSizes_.size() && - info.objDetected_.size() == info.objDetectedFilePaths_.size() && - info.objDetected_.size() == info.objDetectedInliersCount_.size() && - info.objDetected_.size() == info.objDetectedOutliersCount_.size()); - - int infoIndex=0; - int i=0; - QMultiMap::const_iterator iterSizes=info.objDetectedSizes_.constBegin(); - QMultiMap::const_iterator iterFilePaths=info.objDetectedFilePaths_.constBegin(); - QMultiMap::const_iterator iterInliers=info.objDetectedInliersCount_.constBegin(); - QMultiMap::const_iterator iterOutliers=info.objDetectedOutliersCount_.constBegin(); - for(QMultiMap::const_iterator iter=info.objDetected_.constBegin(); - iter!=info.objDetected_.constEnd(); - ++iter, ++iterSizes, ++iterFilePaths, ++infoIndex, ++iterInliers, ++iterOutliers) - { - if(pub_.getNumSubscribers() || pubStamped_.getNumSubscribers()) - { - msg.data[i] = msgStamped.objects.data[i] = iter.key(); ++i; - msg.data[i] = msgStamped.objects.data[i] = iterSizes->width(); ++i; - msg.data[i] = msgStamped.objects.data[i] = iterSizes->height(); ++i; - msg.data[i] = msgStamped.objects.data[i] = iter->m11(); ++i; - msg.data[i] = msgStamped.objects.data[i] = iter->m12(); ++i; - msg.data[i] = msgStamped.objects.data[i] = iter->m13(); ++i; - msg.data[i] = msgStamped.objects.data[i] = iter->m21(); ++i; - msg.data[i] = msgStamped.objects.data[i] = iter->m22(); ++i; - msg.data[i] = msgStamped.objects.data[i] = iter->m23(); ++i; - msg.data[i] = msgStamped.objects.data[i] = iter->m31(); ++i;// dx - msg.data[i] = msgStamped.objects.data[i] = iter->m32(); ++i;// dy - msg.data[i] = msgStamped.objects.data[i] = iter->m33(); ++i; - } - - if(pubInfo_.getNumSubscribers()) - { - infoMsg.ids[infoIndex].data = iter.key(); - infoMsg.widths[infoIndex].data = iterSizes->width(); - infoMsg.heights[infoIndex].data = iterSizes->height(); - infoMsg.file_paths[infoIndex].data = iterFilePaths.value().toStdString(); - infoMsg.inliers[infoIndex].data = iterInliers.value(); - infoMsg.outliers[infoIndex].data = iterOutliers.value(); - infoMsg.homographies[infoIndex].data.resize(9); - infoMsg.homographies[infoIndex].data[0] = iter->m11(); - infoMsg.homographies[infoIndex].data[1] = iter->m12(); - infoMsg.homographies[infoIndex].data[2] = iter->m13(); - infoMsg.homographies[infoIndex].data[3] = iter->m21(); - infoMsg.homographies[infoIndex].data[4] = iter->m22(); - infoMsg.homographies[infoIndex].data[5] = iter->m23(); - infoMsg.homographies[infoIndex].data[6] = iter->m31(); - infoMsg.homographies[infoIndex].data[7] = iter->m32(); - infoMsg.homographies[infoIndex].data[8] = iter->m33(); - } - } - if(pub_.getNumSubscribers()) - { - pub_.publish(msg); - } - if(pubStamped_.getNumSubscribers()) - { - // use same header as the input image (for synchronization and frame reference) - msgStamped.header.frame_id = header.frameId_.toStdString(); - msgStamped.header.stamp.sec = header.sec_; - msgStamped.header.stamp.nsec = header.nsec_; - pubStamped_.publish(msgStamped); - } - if(pubInfo_.getNumSubscribers()) - { - // use same header as the input image (for synchronization and frame reference) - infoMsg.header.frame_id = header.frameId_.toStdString(); - infoMsg.header.stamp.sec = header.sec_; - infoMsg.header.stamp.nsec = header.nsec_; - pubInfo_.publish(infoMsg); - } - } -} - -cv::Vec3f FindObjectROS::getDepth(const cv::Mat & depthImage, - int x, int y, - float cx, float cy, - float fx, float fy) -{ - if(!(x >=0 && x=0 && y::quiet_NaN (), - std::numeric_limits::quiet_NaN (), - std::numeric_limits::quiet_NaN ()); - } - - - cv::Vec3f pt; - - // Use correct principal point from calibration - float center_x = cx; //cameraInfo.K.at(2) - float center_y = cy; //cameraInfo.K.at(5) - - bool isInMM = depthImage.type() == CV_16UC1; // is in mm? - - // Combine unit conversion (if necessary) with scaling by focal length for computing (X,Y) - float unit_scaling = isInMM?0.001f:1.0f; - float constant_x = unit_scaling / fx; //cameraInfo.K.at(0) - float constant_y = unit_scaling / fy; //cameraInfo.K.at(4) - float bad_point = std::numeric_limits::quiet_NaN (); - - float depth; - bool isValid; - if(isInMM) - { - depth = (float)depthImage.at(y,x); - isValid = depth != 0.0f; - } - else - { - depth = depthImage.at(y,x); - isValid = std::isfinite(depth) && depth > 0.0f; - } - - // Check for invalid measurements - if (!isValid) - { - pt.val[0] = pt.val[1] = pt.val[2] = bad_point; - } - else - { - // Fill in XYZ - pt.val[0] = (float(x) - center_x) * depth * constant_x; - pt.val[1] = (float(y) - center_y) * depth * constant_y; - pt.val[2] = depth*unit_scaling; - } - return pt; -} diff --git a/find-object/src/ros1/FindObjectROS.h b/find-object/src/ros1/FindObjectROS.h deleted file mode 100644 index cc50aff8..00000000 --- a/find-object/src/ros1/FindObjectROS.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef FINDOBJECTROS_H_ -#define FINDOBJECTROS_H_ - -#include -#include -#include -#include "find_object/FindObject.h" - -#include -#include -#include -#include -#include - -class FindObjectROS : public find_object::FindObject -{ - Q_OBJECT; - -public: - FindObjectROS(QObject * parent = 0); - virtual ~FindObjectROS() {} - -public Q_SLOTS: - void publish(const find_object::DetectionInfo & info, const find_object::Header & header, const cv::Mat & depth, float depthConstant); - -private: - cv::Vec3f getDepth(const cv::Mat & depthImage, - int x, int y, - float cx, float cy, - float fx, float fy); - - -private: - ros::Publisher pub_; - ros::Publisher pubStamped_; - ros::Publisher pubInfo_; - - std::string objFramePrefix_; - bool usePnP_; - tf::TransformBroadcaster tfBroadcaster_; - -}; - -#endif /* FINDOBJECTROS_H_ */ diff --git a/find-object/src/ros1/find_object_2d_node.cpp b/find-object/src/ros1/find_object_2d_node.cpp deleted file mode 100644 index 4d782062..00000000 --- a/find-object/src/ros1/find_object_2d_node.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include -#include -#include -#include -#include "find_object/MainWindow.h" -#include "ParametersToolBox.h" -#include "find_object/Settings.h" -#include - -using namespace find_object; - -bool gui; -std::string settingsPath; - -void my_handler_gui(int s){ - QApplication::closeAllWindows(); - QApplication::quit(); -} -void my_handler(int s){ - QCoreApplication::quit(); -} - -void setupQuitSignal(bool gui) -{ - // Catch ctrl-c to close the gui - struct sigaction sigIntHandler; - if(gui) - { - sigIntHandler.sa_handler = my_handler_gui; - } - else - { - sigIntHandler.sa_handler = my_handler; - } - sigemptyset(&sigIntHandler.sa_mask); - sigIntHandler.sa_flags = 0; - sigaction(SIGINT, &sigIntHandler, NULL); -} - -int main(int argc, char** argv) -{ - ros::init(argc, argv, "find_object_2d"); - - gui = true; - std::string objectsPath; - std::string sessionPath; - settingsPath = QDir::homePath().append("/.ros/find_object_2d.ini").toStdString(); - bool subscribeDepth = false; - - ros::NodeHandle nh("~"); - - nh.param("gui", gui, gui); - nh.param("objects_path", objectsPath, objectsPath); - nh.param("session_path", sessionPath, sessionPath); - nh.param("settings_path", settingsPath, settingsPath); - nh.param("subscribe_depth", subscribeDepth, subscribeDepth); - - ROS_INFO("gui=%d", (int)gui); - ROS_INFO("objects_path=%s", objectsPath.c_str()); - ROS_INFO("session_path=%s", sessionPath.c_str()); - ROS_INFO("settings_path=%s", settingsPath.c_str()); - ROS_INFO("subscribe_depth = %s", subscribeDepth?"true":"false"); - - if(settingsPath.empty()) - { - settingsPath = QDir::homePath().append("/.ros/find_object_2d.ini").toStdString(); - } - else - { - if(!sessionPath.empty()) - { - ROS_WARN("\"settings_path\" parameter is ignored when \"session_path\" is set."); - } - - QString path = settingsPath.c_str(); - if(path.contains('~')) - { - path.replace('~', QDir::homePath()); - settingsPath = path.toStdString(); - } - } - - // Load settings, should be loaded before creating other objects - Settings::init(settingsPath.c_str()); - - FindObjectROS * findObjectROS = new FindObjectROS(); - if(!sessionPath.empty()) - { - if(!objectsPath.empty()) - { - ROS_WARN("\"objects_path\" parameter is ignored when \"session_path\" is set."); - } - if(!findObjectROS->loadSession(sessionPath.c_str())) - { - ROS_ERROR("Failed to load session \"%s\"", sessionPath.c_str()); - } - } - else if(!objectsPath.empty()) - { - QString path = objectsPath.c_str(); - if(path.contains('~')) - { - path.replace('~', QDir::homePath()); - } - if(!findObjectROS->loadObjects(path)) - { - ROS_ERROR("No objects loaded from path \"%s\"", path.toStdString().c_str()); - } - } - - CameraROS * camera = new CameraROS(subscribeDepth); - - // Catch ctrl-c to close the gui - setupQuitSignal(gui); - - if(gui) - { - QApplication app(argc, argv); - MainWindow mainWindow(findObjectROS, camera); // take ownership - - QObject::connect( - &mainWindow, - SIGNAL(objectsFound(const find_object::DetectionInfo &, const find_object::Header &, const cv::Mat &, float)), - findObjectROS, - SLOT(publish(const find_object::DetectionInfo &, const find_object::Header &, const cv::Mat &, float))); - - QStringList topics = camera->subscribedTopics(); - if(topics.size() == 1) - { - mainWindow.setSourceImageText(mainWindow.tr( - "Find-Object subscribed to %1 topic.
" - "You can remap the topic when starting the node:
\"rosrun find_object_2d find_object_2d image:=your/image/topic\".
" - "
").arg(topics.first())); - } - else if(topics.size() == 3) - { - mainWindow.setSourceImageText(mainWindow.tr( - "Find-Object subscribed to :
%1
%2
%3
" - "
").arg(topics.at(0)).arg(topics.at(1)).arg(topics.at(2))); - } - mainWindow.show(); - app.connect( &app, SIGNAL( lastWindowClosed() ), &app, SLOT( quit() ) ); - - // loop - mainWindow.startProcessing(); - app.exec(); - Settings::saveSettings(); - } - else - { - QCoreApplication app(argc, argv); - - // connect stuff: - QObject::connect(camera, SIGNAL(imageReceived(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)), findObjectROS, SLOT(detect(const cv::Mat &, const find_object::Header &, const cv::Mat &, float))); - - //loop - camera->start(); - app.exec(); - - delete camera; - delete findObjectROS; - } - return 0; -} diff --git a/find-object/src/ros1/print_objects_detected_node.cpp b/find-object/src/ros1/print_objects_detected_node.cpp deleted file mode 100644 index e067cc82..00000000 --- a/find-object/src/ros1/print_objects_detected_node.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -image_transport::Publisher imagePub; - -/** - * IMPORTANT : - * Parameter General/MirrorView must be false - * Parameter Homography/homographyComputed must be true - */ -void objectsDetectedCallback( - const std_msgs::Float32MultiArrayConstPtr & msg) -{ - printf("---\n"); - const std::vector & data = msg->data; - if(data.size()) - { - for(unsigned int i=0; i 0) - { - const std::vector & data = objectsMsg->objects.data; - if(data.size()) - { - for(unsigned int i=0; i(0,0) = data[i+3]; - cvHomography.at(1,0) = data[i+4]; - cvHomography.at(2,0) = data[i+5]; - cvHomography.at(0,1) = data[i+6]; - cvHomography.at(1,1) = data[i+7]; - cvHomography.at(2,1) = data[i+8]; - cvHomography.at(0,2) = data[i+9]; - cvHomography.at(1,2) = data[i+10]; - cvHomography.at(2,2) = data[i+11]; - std::vector inPts, outPts; - inPts.push_back(cv::Point2f(0,0)); - inPts.push_back(cv::Point2f(objectWidth,0)); - inPts.push_back(cv::Point2f(objectWidth,objectHeight)); - inPts.push_back(cv::Point2f(0,objectHeight)); - inPts.push_back(cv::Point2f(objectWidth/2,objectHeight/2)); - cv::perspectiveTransform(inPts, outPts, cvHomography); - - cv_bridge::CvImageConstPtr imageDepthPtr = cv_bridge::toCvShare(imageMsg); - - cv_bridge::CvImage img; - img = *imageDepthPtr; - std::vector outPtsInt; - outPtsInt.push_back(outPts[0]); - outPtsInt.push_back(outPts[1]); - outPtsInt.push_back(outPts[2]); - outPtsInt.push_back(outPts[3]); - QColor color(QColor((Qt::GlobalColor)((id % 10 + 7)==Qt::yellow?Qt::darkYellow:(id % 10 + 7)))); - cv::Scalar cvColor(color.red(), color.green(), color.blue()); - cv::polylines(img.image, outPtsInt, true, cvColor, 3); - cv::Point2i center = outPts[4]; - cv::putText(img.image, QString("(%1, %2)").arg(center.x).arg(center.y).toStdString(), center, cv::FONT_HERSHEY_SIMPLEX, 0.6, cvColor, 2); - cv::circle(img.image, center, 1, cvColor, 3); - imagePub.publish(img.toImageMsg()); - } - } - } -} - -typedef message_filters::sync_policies::ExactTime MyExactSyncPolicy; - -int main(int argc, char** argv) -{ - ros::init(argc, argv, "objects_detected"); - - ros::NodeHandle nh; - image_transport::ImageTransport it(nh); - - // Simple subscriber - ros::Subscriber sub; - sub = nh.subscribe("objects", 1, objectsDetectedCallback); - - // Synchronized image + objects example - image_transport::SubscriberFilter imageSub; - imageSub.subscribe(it, nh.resolveName("image"), 1); - message_filters::Subscriber objectsSub; - objectsSub.subscribe(nh, "objectsStamped", 1); - message_filters::Synchronizer exactSync(MyExactSyncPolicy(10), imageSub, objectsSub); - exactSync.registerCallback(boost::bind(&imageObjectsDetectedCallback, - boost::placeholders::_1, boost::placeholders::_2)); - - imagePub = it.advertise("image_with_objects", 1); - - ros::spin(); - - return 0; -} diff --git a/find-object/src/ros1/tf_example_node.cpp b/find-object/src/ros1/tf_example_node.cpp deleted file mode 100644 index c09b414f..00000000 --- a/find-object/src/ros1/tf_example_node.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include -#include -#include -#include - -class TfExample -{ -public: - TfExample() : - objFramePrefix_("object") - { - ros::NodeHandle pnh("~"); - pnh.param("target_frame_id", targetFrameId_, targetFrameId_); - pnh.param("object_prefix", objFramePrefix_, objFramePrefix_); - - ros::NodeHandle nh; - subs_ = nh.subscribe("objectsStamped", 1, &TfExample::objectsDetectedCallback, this); - } - - // Here I synchronize with the ObjectsStamped topic to - // know when the TF is ready and for which objects - void objectsDetectedCallback(const find_object_2d::ObjectsStampedConstPtr & msg) - { - if(msg->objects.data.size()) - { - std::string targetFrameId = targetFrameId_; - if(targetFrameId.empty()) - { - targetFrameId = msg->header.frame_id; - } - char multiSubId = 'b'; - int previousId = -1; - for(unsigned int i=0; iobjects.data.size(); i+=12) - { - // get data - int id = (int)msg->objects.data[i]; - - QString multiSuffix; - if(id == previousId) - { - multiSuffix = QString("_") + multiSubId++; - } - else - { - multiSubId = 'b'; - } - previousId = id; - - // "object_1", "object_1_b", "object_1_c", "object_2" - std::string objectFrameId = QString("%1_%2%3").arg(objFramePrefix_.c_str()).arg(id).arg(multiSuffix).toStdString(); - - tf::StampedTransform pose; - try - { - // Get transformation from "object_#" frame to target frame - // The timestamp matches the one sent over TF - tfListener_.lookupTransform(targetFrameId, objectFrameId, msg->header.stamp, pose); - } - catch(tf::TransformException & ex) - { - ROS_WARN("%s",ex.what()); - continue; - } - - // Here "pose" is the position of the object "id" in target frame. - ROS_INFO("%s [x,y,z] [x,y,z,w] in \"%s\" frame: [%f,%f,%f] [%f,%f,%f,%f]", - objectFrameId.c_str(), targetFrameId.c_str(), - pose.getOrigin().x(), pose.getOrigin().y(), pose.getOrigin().z(), - pose.getRotation().x(), pose.getRotation().y(), pose.getRotation().z(), pose.getRotation().w()); - } - } - } - -private: - std::string targetFrameId_; - std::string objFramePrefix_; - ros::Subscriber subs_; - tf::TransformListener tfListener_; -}; - -int main(int argc, char * argv[]) -{ - ros::init(argc, argv, "tf_example_node"); - - TfExample sync; - ros::spin(); -} diff --git a/find-object/src/ros2/CameraROS.cpp b/find-object/src/ros2/CameraROS.cpp deleted file mode 100644 index dc76ea9c..00000000 --- a/find-object/src/ros2/CameraROS.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "CameraROS.h" -#include "find_object/Settings.h" - -#include -#include - -using namespace find_object; - -CameraROS::CameraROS(bool subscribeDepth, rclcpp::Node * node) : - node_(node), - subscribeDepth_(subscribeDepth), - approxSync_(0), - exactSync_(0) -{ - qRegisterMetaType("ros::Time"); - qRegisterMetaType("cv::Mat"); - - if(!subscribeDepth_) - { - image_transport::TransportHints hints(node); - imageSub_ = image_transport::create_subscription(node, "image", std::bind(&CameraROS::imgReceivedCallback, this, std::placeholders::_1), hints.getTransport(), rclcpp::QoS(1).reliability((rmw_qos_reliability_policy_t)1).get_rmw_qos_profile()); - } - else - { - int queueSize = 10; - bool approxSync = true; - queueSize = node->declare_parameter("queue_size", queueSize); - approxSync = node->declare_parameter("approx_sync", approxSync); - RCLCPP_INFO(node->get_logger(), "find_object_ros: queue_size = %d", queueSize); - RCLCPP_INFO(node->get_logger(), "find_object_ros: approx_sync = %s", approxSync?"true":"false"); - - - image_transport::TransportHints hints(node); - rgbSub_.subscribe(node, "rgb/image_rect_color", hints.getTransport(), rclcpp::QoS(1).reliability((rmw_qos_reliability_policy_t)1).get_rmw_qos_profile()); - depthSub_.subscribe(node, "depth_registered/image_raw", hints.getTransport(), rclcpp::QoS(1).reliability((rmw_qos_reliability_policy_t)1).get_rmw_qos_profile()); - cameraInfoSub_.subscribe(node, "depth_registered/camera_info", rclcpp::QoS(1).reliability((rmw_qos_reliability_policy_t)1).get_rmw_qos_profile()); - - if(approxSync) - { - approxSync_ = new message_filters::Synchronizer(MyApproxSyncPolicy(queueSize), rgbSub_, depthSub_, cameraInfoSub_); - approxSync_->registerCallback(std::bind(&CameraROS::imgDepthReceivedCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - } - else - { - exactSync_ = new message_filters::Synchronizer(MyExactSyncPolicy(queueSize), rgbSub_, depthSub_, cameraInfoSub_); - exactSync_->registerCallback(std::bind(&CameraROS::imgDepthReceivedCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - } - } -} -CameraROS::~CameraROS() -{ - delete approxSync_; - delete exactSync_; -} - -void CameraROS::setupExecutor(std::shared_ptr node) -{ - executor_.add_node(node); -} - -QStringList CameraROS::subscribedTopics() const -{ - QStringList topics; - if(subscribeDepth_) - { - topics.append(rgbSub_.getTopic().c_str()); - topics.append(depthSub_.getTopic().c_str()); - topics.append(cameraInfoSub_.getSubscriber()->get_topic_name()); - } - else - { - topics.append(imageSub_.getTopic().c_str()); - } - return topics; -} - -bool CameraROS::start() -{ - this->startTimer(); - return true; -} - -void CameraROS::stop() -{ - this->stopTimer(); -} - -void CameraROS::takeImage() -{ - executor_.spin_some(); -} - -void CameraROS::imgReceivedCallback(const sensor_msgs::msg::Image::ConstSharedPtr msg) -{ - if(msg->data.size()) - { - cv::Mat image; - cv_bridge::CvImageConstPtr imgPtr = cv_bridge::toCvShare(msg); - try - { - if(msg->encoding.compare(sensor_msgs::image_encodings::MONO8) == 0 || - msg->encoding.compare(sensor_msgs::image_encodings::MONO16) == 0) - { - image = cv_bridge::cvtColor(imgPtr, "mono8")->image; - } - else - { - image = cv_bridge::cvtColor(imgPtr, "bgr8")->image; - } - - Q_EMIT imageReceived(image, Header(msg->header.frame_id.c_str(), msg->header.stamp.sec, msg->header.stamp.nanosec), cv::Mat(), 0.0f); - } - catch(const cv_bridge::Exception & e) - { - RCLCPP_ERROR(node_->get_logger(), "find_object_ros: Could not convert input image to mono8 or bgr8 format, encoding detected is %s... cv_bridge exception: %s", msg->encoding.c_str(), e.what()); - } - } -} - -void CameraROS::imgDepthReceivedCallback( - const sensor_msgs::msg::Image::ConstSharedPtr rgbMsg, - const sensor_msgs::msg::Image::ConstSharedPtr depthMsg, - const sensor_msgs::msg::CameraInfo::ConstSharedPtr cameraInfoMsg) -{ - if(depthMsg->encoding.compare(sensor_msgs::image_encodings::TYPE_16UC1)!=0 && - depthMsg->encoding.compare(sensor_msgs::image_encodings::TYPE_32FC1)!=0) - { - RCLCPP_ERROR(node_->get_logger(), "find_object_ros: Depth image type must be 32FC1 or 16UC1"); - return; - } - - if(rgbMsg->data.size()) - { - cv_bridge::CvImageConstPtr ptr = cv_bridge::toCvShare(rgbMsg); - cv_bridge::CvImageConstPtr ptrDepth = cv_bridge::toCvShare(depthMsg); - float depthConstant = 1.0f/cameraInfoMsg->k[4]; - - cv::Mat image; - cv_bridge::CvImageConstPtr imgPtr = cv_bridge::toCvShare(rgbMsg); - try - { - if(rgbMsg->encoding.compare(sensor_msgs::image_encodings::MONO8) == 0 || - rgbMsg->encoding.compare(sensor_msgs::image_encodings::MONO16) == 0) - { - image = cv_bridge::cvtColor(imgPtr, "mono8")->image; - } - else - { - image = cv_bridge::cvtColor(imgPtr, "bgr8")->image; - } - - Q_EMIT imageReceived(image, Header(rgbMsg->header.frame_id.c_str(), rgbMsg->header.stamp.sec, rgbMsg->header.stamp.nanosec), ptrDepth->image, depthConstant); - } - catch(const cv_bridge::Exception & e) - { - RCLCPP_ERROR(node_->get_logger(), "find_object_ros: Could not convert input image to mono8 or bgr8 format, encoding detected is %s... cv_bridge exception: %s", rgbMsg->encoding.c_str(), e.what()); - } - } - - -} diff --git a/find-object/src/ros2/CameraROS.h b/find-object/src/ros2/CameraROS.h deleted file mode 100644 index c9e0f2c1..00000000 --- a/find-object/src/ros2/CameraROS.h +++ /dev/null @@ -1,93 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef CAMERAROS_H_ -#define CAMERAROS_H_ - -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "find_object/Camera.h" -#include - -class CameraROS : public find_object::Camera { - Q_OBJECT -public: - CameraROS(bool subscribeDepth, rclcpp::Node * node); - virtual ~CameraROS(); - void setupExecutor(std::shared_ptr node); - - virtual bool start(); - virtual void stop(); - - QStringList subscribedTopics() const; - -private Q_SLOTS: - virtual void takeImage(); - -private: - void imgReceivedCallback(const sensor_msgs::msg::Image::ConstSharedPtr msg); - void imgDepthReceivedCallback( - const sensor_msgs::msg::Image::ConstSharedPtr rgbMsg, - const sensor_msgs::msg::Image::ConstSharedPtr depthMsg, - const sensor_msgs::msg::CameraInfo::ConstSharedPtr cameraInfoMsg); - -private: - rclcpp::Node * node_; - rclcpp::executors::SingleThreadedExecutor executor_; - bool subscribeDepth_; - image_transport::Subscriber imageSub_; - - image_transport::SubscriberFilter rgbSub_; - image_transport::SubscriberFilter depthSub_; - message_filters::Subscriber cameraInfoSub_; - - typedef message_filters::sync_policies::ApproximateTime< - sensor_msgs::msg::Image, - sensor_msgs::msg::Image, - sensor_msgs::msg::CameraInfo> MyApproxSyncPolicy; - message_filters::Synchronizer * approxSync_; - - typedef message_filters::sync_policies::ExactTime< - sensor_msgs::msg::Image, - sensor_msgs::msg::Image, - sensor_msgs::msg::CameraInfo> MyExactSyncPolicy; - message_filters::Synchronizer * exactSync_; -}; - -#endif /* CAMERAROS_H_ */ diff --git a/find-object/src/ros2/FindObjectROS.cpp b/find-object/src/ros2/FindObjectROS.cpp deleted file mode 100644 index cc6d2a56..00000000 --- a/find-object/src/ros2/FindObjectROS.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "FindObjectROS.h" - -#include -#include -#include -#include -#ifdef PRE_ROS_HUMBLE -#include -#else -#include -#endif - -#include - -using namespace find_object; - -FindObjectROS::FindObjectROS(rclcpp::Node * node) : - FindObject(true), - node_(node), - objFramePrefix_("object"), - usePnP_(true) -{ - tfBroadcaster_ = std::make_shared(node); - - objFramePrefix_ = node->declare_parameter("object_prefix", objFramePrefix_); - usePnP_ = node->declare_parameter("pnp", usePnP_); - RCLCPP_INFO(node->get_logger(), "object_prefix = %s", objFramePrefix_.c_str()); - RCLCPP_INFO(node->get_logger(), "pnp = %s", usePnP_?"true":"false"); - - pub_ = node->create_publisher("objects", rclcpp::QoS(1).reliability((rmw_qos_reliability_policy_t)1)); - pubStamped_ = node->create_publisher("objectsStamped", rclcpp::QoS(1).reliability((rmw_qos_reliability_policy_t)1)); - pubInfo_ = node->create_publisher("info", rclcpp::QoS(1).reliability((rmw_qos_reliability_policy_t)1)); - - this->connect(this, SIGNAL(objectsFound(const find_object::DetectionInfo &, const find_object::Header &, const cv::Mat &, float)), this, SLOT(publish(const find_object::DetectionInfo &, const find_object::Header &, const cv::Mat &, float))); -} - -void FindObjectROS::publish(const find_object::DetectionInfo & info, const Header & header, const cv::Mat & depth, float depthConstant) -{ - // send tf before the message - if(info.objDetected_.size() && !depth.empty() && depthConstant != 0.0f) - { - std::vector transforms; - char multiSubId = 'b'; - int previousId = -1; - QMultiMap::const_iterator iterSizes=info.objDetectedSizes_.constBegin(); - for(QMultiMap::const_iterator iter=info.objDetected_.constBegin(); - iter!=info.objDetected_.constEnd(); - ++iter, ++iterSizes) - { - // get data - int id = iter.key(); - float objectWidth = iterSizes->width(); - float objectHeight = iterSizes->height(); - - QString multiSuffix; - if(id == previousId) - { - multiSuffix = QString("_") + multiSubId++; - } - else - { - multiSubId = 'b'; - } - previousId = id; - - // Find center of the object - QPointF center = iter->map(QPointF(objectWidth/2, objectHeight/2)); - cv::Vec3f center3D = this->getDepth(depth, - center.x()+0.5f, center.y()+0.5f, - float(depth.cols/2)-0.5f, float(depth.rows/2)-0.5f, - 1.0f/depthConstant, 1.0f/depthConstant); - - cv::Vec3f axisEndX; - cv::Vec3f axisEndY; - if(!usePnP_) - { - QPointF xAxis = iter->map(QPointF(3*objectWidth/4, objectHeight/2)); - axisEndX = this->getDepth(depth, - xAxis.x()+0.5f, xAxis.y()+0.5f, - float(depth.cols/2)-0.5f, float(depth.rows/2)-0.5f, - 1.0f/depthConstant, 1.0f/depthConstant); - - QPointF yAxis = iter->map(QPointF(objectWidth/2, 3*objectHeight/4)); - axisEndY = this->getDepth(depth, - yAxis.x()+0.5f, yAxis.y()+0.5f, - float(depth.cols/2)-0.5f, float(depth.rows/2)-0.5f, - 1.0f/depthConstant, 1.0f/depthConstant); - } - - if((std::isfinite(center3D.val[2]) && usePnP_) || - (std::isfinite(center3D.val[0]) && std::isfinite(center3D.val[1]) && std::isfinite(center3D.val[2]) && - std::isfinite(axisEndX.val[0]) && std::isfinite(axisEndX.val[1]) && std::isfinite(axisEndX.val[2]) && - std::isfinite(axisEndY.val[0]) && std::isfinite(axisEndY.val[1]) && std::isfinite(axisEndY.val[2]))) - { - geometry_msgs::msg::TransformStamped transform; - transform.transform.rotation.x=0; - transform.transform.rotation.y=0; - transform.transform.rotation.z=0; - transform.transform.rotation.w=1; - transform.transform.translation.x=0; - transform.transform.translation.y=0; - transform.transform.translation.z=0; - transform.child_frame_id = QString("%1_%2%3").arg(objFramePrefix_.c_str()).arg(id).arg(multiSuffix).toStdString(); - transform.header.frame_id = header.frameId_.toStdString(); - transform.header.stamp.sec = header.sec_; - transform.header.stamp.nanosec = header.nsec_; - - tf2::Quaternion q; - if(usePnP_) - { - std::vector objectPoints(4); - std::vector imagePoints(4); - - objectPoints[0] = cv::Point3f(-0.5, -(objectHeight/objectWidth)/2.0f,0); - objectPoints[1] = cv::Point3f(0.5,-(objectHeight/objectWidth)/2.0f,0); - objectPoints[2] = cv::Point3f(0.5,(objectHeight/objectWidth)/2.0f,0); - objectPoints[3] = cv::Point3f(-0.5,(objectHeight/objectWidth)/2.0f,0); - - QPointF pt = iter->map(QPointF(0, 0)); - imagePoints[0] = cv::Point2f(pt.x(), pt.y()); - pt = iter->map(QPointF(objectWidth, 0)); - imagePoints[1] = cv::Point2f(pt.x(), pt.y()); - pt = iter->map(QPointF(objectWidth, objectHeight)); - imagePoints[2] = cv::Point2f(pt.x(), pt.y()); - pt = iter->map(QPointF(0, objectHeight)); - imagePoints[3] = cv::Point2f(pt.x(), pt.y()); - - cv::Mat cameraMatrix = cv::Mat::eye(3,3,CV_64FC1); - cameraMatrix.at(0,0) = 1.0f/depthConstant; - cameraMatrix.at(1,1) = 1.0f/depthConstant; - cameraMatrix.at(0,2) = float(depth.cols/2)-0.5f; - cameraMatrix.at(1,2) = float(depth.rows/2)-0.5f; - cv::Mat distCoeffs; - - cv::Mat rvec(1,3, CV_64FC1); - cv::Mat tvec(1,3, CV_64FC1); - cv::solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec); - - cv::Mat R; - cv::Rodrigues(rvec, R); - tf2::Matrix3x3 rotationMatrix( - R.at(0,0), R.at(0,1), R.at(0,2), - R.at(1,0), R.at(1,1), R.at(1,2), - R.at(2,0), R.at(2,1), R.at(2,2)); - rotationMatrix.getRotation(q); - transform.transform.translation.x = tvec.at(0)*(center3D.val[2]/tvec.at(2)); - transform.transform.translation.y = tvec.at(1)*(center3D.val[2]/tvec.at(2)); - transform.transform.translation.z = tvec.at(2)*(center3D.val[2]/tvec.at(2)); - } - else - { - tf2::Vector3 xAxis(axisEndX.val[0] - center3D.val[0], axisEndX.val[1] - center3D.val[1], axisEndX.val[2] - center3D.val[2]); - xAxis.normalize(); - tf2::Vector3 yAxis(axisEndY.val[0] - center3D.val[0], axisEndY.val[1] - center3D.val[1], axisEndY.val[2] - center3D.val[2]); - yAxis.normalize(); - tf2::Vector3 zAxis = xAxis.cross(yAxis); - zAxis.normalize(); - tf2::Matrix3x3 rotationMatrix( - xAxis.x(), yAxis.x() ,zAxis.x(), - xAxis.y(), yAxis.y(), zAxis.y(), - xAxis.z(), yAxis.z(), zAxis.z()); - rotationMatrix.getRotation(q); - transform.transform.translation.x = center3D.val[0]; - transform.transform.translation.y = center3D.val[1]; - transform.transform.translation.z = center3D.val[2]; - } - - // set x axis going front of the object, with z up and y left - tf2::Quaternion q2; - q2.setRPY(CV_PI/2.0, CV_PI/2.0, 0); - q *= q2; - transform.transform.rotation = tf2::toMsg(q.normalized()); - transforms.push_back(transform); - } - else - { - RCLCPP_WARN(node_->get_logger(), "Object %d detected, center 2D at (%f,%f), but invalid depth, cannot set frame \"%s\"! " - "(maybe object is too near of the camera or bad depth image)\n", - id, - center.x(), center.y(), - QString("%1_%2").arg(objFramePrefix_.c_str()).arg(id).toStdString().c_str()); - } - } - if(transforms.size()) - { - tfBroadcaster_->sendTransform(transforms); - } - } - - if(pub_->get_subscription_count() || pubStamped_->get_subscription_count() || pubInfo_->get_subscription_count()) - { - std_msgs::msg::Float32MultiArray msg; - find_object_2d::msg::ObjectsStamped msgStamped; - find_object_2d::msg::DetectionInfo infoMsg; - if(pubInfo_->get_subscription_count()) - { - infoMsg.ids.resize(info.objDetected_.size()); - infoMsg.widths.resize(info.objDetected_.size()); - infoMsg.heights.resize(info.objDetected_.size()); - infoMsg.file_paths.resize(info.objDetected_.size()); - infoMsg.inliers.resize(info.objDetected_.size()); - infoMsg.outliers.resize(info.objDetected_.size()); - infoMsg.homographies.resize(info.objDetected_.size()); - } - msg.data = std::vector(info.objDetected_.size()*12); - msgStamped.objects.data = std::vector(info.objDetected_.size()*12); - - Q_ASSERT(info.objDetected_.size() == info.objDetectedSizes_.size() && - info.objDetected_.size() == info.objDetectedFilePaths_.size() && - info.objDetected_.size() == info.objDetectedInliersCount_.size() && - info.objDetected_.size() == info.objDetectedOutliersCount_.size()); - - int infoIndex=0; - int i=0; - QMultiMap::const_iterator iterSizes=info.objDetectedSizes_.constBegin(); - QMultiMap::const_iterator iterFilePaths=info.objDetectedFilePaths_.constBegin(); - QMultiMap::const_iterator iterInliers=info.objDetectedInliersCount_.constBegin(); - QMultiMap::const_iterator iterOutliers=info.objDetectedOutliersCount_.constBegin(); - for(QMultiMap::const_iterator iter=info.objDetected_.constBegin(); - iter!=info.objDetected_.constEnd(); - ++iter, ++iterSizes, ++iterFilePaths, ++infoIndex, ++iterInliers, ++iterOutliers) - { - if(pub_->get_subscription_count() || pubStamped_->get_subscription_count()) - { - msg.data[i] = msgStamped.objects.data[i] = iter.key(); ++i; - msg.data[i] = msgStamped.objects.data[i] = iterSizes->width(); ++i; - msg.data[i] = msgStamped.objects.data[i] = iterSizes->height(); ++i; - msg.data[i] = msgStamped.objects.data[i] = iter->m11(); ++i; - msg.data[i] = msgStamped.objects.data[i] = iter->m12(); ++i; - msg.data[i] = msgStamped.objects.data[i] = iter->m13(); ++i; - msg.data[i] = msgStamped.objects.data[i] = iter->m21(); ++i; - msg.data[i] = msgStamped.objects.data[i] = iter->m22(); ++i; - msg.data[i] = msgStamped.objects.data[i] = iter->m23(); ++i; - msg.data[i] = msgStamped.objects.data[i] = iter->m31(); ++i;// dx - msg.data[i] = msgStamped.objects.data[i] = iter->m32(); ++i;// dy - msg.data[i] = msgStamped.objects.data[i] = iter->m33(); ++i; - } - - if(pubInfo_->get_subscription_count()) - { - infoMsg.ids[infoIndex].data = iter.key(); - infoMsg.widths[infoIndex].data = iterSizes->width(); - infoMsg.heights[infoIndex].data = iterSizes->height(); - infoMsg.file_paths[infoIndex].data = iterFilePaths.value().toStdString(); - infoMsg.inliers[infoIndex].data = iterInliers.value(); - infoMsg.outliers[infoIndex].data = iterOutliers.value(); - infoMsg.homographies[infoIndex].data.resize(9); - infoMsg.homographies[infoIndex].data[0] = iter->m11(); - infoMsg.homographies[infoIndex].data[1] = iter->m12(); - infoMsg.homographies[infoIndex].data[2] = iter->m13(); - infoMsg.homographies[infoIndex].data[3] = iter->m21(); - infoMsg.homographies[infoIndex].data[4] = iter->m22(); - infoMsg.homographies[infoIndex].data[5] = iter->m23(); - infoMsg.homographies[infoIndex].data[6] = iter->m31(); - infoMsg.homographies[infoIndex].data[7] = iter->m32(); - infoMsg.homographies[infoIndex].data[8] = iter->m33(); - } - } - if(pub_->get_subscription_count()) - { - pub_->publish(msg); - } - if(pubStamped_->get_subscription_count()) - { - // use same header as the input image (for synchronization and frame reference) - msgStamped.header.frame_id = header.frameId_.toStdString(); - msgStamped.header.stamp.sec = header.sec_; - msgStamped.header.stamp.nanosec = header.nsec_; - pubStamped_->publish(msgStamped); - } - if(pubInfo_->get_subscription_count()) - { - // use same header as the input image (for synchronization and frame reference) - infoMsg.header.frame_id = header.frameId_.toStdString(); - infoMsg.header.stamp.sec = header.sec_; - infoMsg.header.stamp.nanosec = header.nsec_; - pubInfo_->publish(infoMsg); - } - } -} - -cv::Vec3f FindObjectROS::getDepth(const cv::Mat & depthImage, - int x, int y, - float cx, float cy, - float fx, float fy) -{ - if(!(x >=0 && x=0 && yget_logger(), "Point must be inside the image (x=%d, y=%d), image size=(%d,%d)", - x, y, - depthImage.cols, depthImage.rows); - return cv::Vec3f( - std::numeric_limits::quiet_NaN (), - std::numeric_limits::quiet_NaN (), - std::numeric_limits::quiet_NaN ()); - } - - - cv::Vec3f pt; - - // Use correct principal point from calibration - float center_x = cx; //cameraInfo.K.at(2) - float center_y = cy; //cameraInfo.K.at(5) - - bool isInMM = depthImage.type() == CV_16UC1; // is in mm? - - // Combine unit conversion (if necessary) with scaling by focal length for computing (X,Y) - float unit_scaling = isInMM?0.001f:1.0f; - float constant_x = unit_scaling / fx; //cameraInfo.K.at(0) - float constant_y = unit_scaling / fy; //cameraInfo.K.at(4) - float bad_point = std::numeric_limits::quiet_NaN (); - - float depth; - bool isValid; - if(isInMM) - { - depth = (float)depthImage.at(y,x); - isValid = depth != 0.0f; - } - else - { - depth = depthImage.at(y,x); - isValid = std::isfinite(depth) && depth > 0.0f; - } - - // Check for invalid measurements - if (!isValid) - { - pt.val[0] = pt.val[1] = pt.val[2] = bad_point; - } - else - { - // Fill in XYZ - pt.val[0] = (float(x) - center_x) * depth * constant_x; - pt.val[1] = (float(y) - center_y) * depth * constant_y; - pt.val[2] = depth*unit_scaling; - } - return pt; -} diff --git a/find-object/src/ros2/FindObjectROS.h b/find-object/src/ros2/FindObjectROS.h deleted file mode 100644 index 73c3fc81..00000000 --- a/find-object/src/ros2/FindObjectROS.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef FINDOBJECTROS_H_ -#define FINDOBJECTROS_H_ - -#include -#include -#include -#include "find_object/FindObject.h" - -#include -#include "find_object_2d/msg/objects_stamped.hpp" -#include "find_object_2d/msg/detection_info.hpp" - -#include -#include -#include -#include -#include - -class FindObjectROS : public find_object::FindObject -{ - Q_OBJECT; - -public: - FindObjectROS(rclcpp::Node * node); - virtual ~FindObjectROS() {} - -public Q_SLOTS: - void publish(const find_object::DetectionInfo & info, const find_object::Header & header, const cv::Mat & depth, float depthConstant); - -private: - cv::Vec3f getDepth(const cv::Mat & depthImage, - int x, int y, - float cx, float cy, - float fx, float fy); - -private: - rclcpp::Node * node_; - rclcpp::Publisher::SharedPtr pub_; - rclcpp::Publisher::SharedPtr pubStamped_; - rclcpp::Publisher::SharedPtr pubInfo_; - - std::string objFramePrefix_; - bool usePnP_; - std::shared_ptr tfBroadcaster_; - -}; - -#endif /* FINDOBJECTROS_H_ */ diff --git a/find-object/src/ros2/find_object_2d_node.cpp b/find-object/src/ros2/find_object_2d_node.cpp deleted file mode 100644 index 2cecc544..00000000 --- a/find-object/src/ros2/find_object_2d_node.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "CameraROS.h" -#include "FindObjectROS.h" - -#include -#include -#include "find_object/MainWindow.h" -#include "ParametersToolBox.h" -#include "find_object/Settings.h" -#include - -void my_handler_gui(int s){ - QApplication::closeAllWindows(); - QApplication::quit(); -} -void my_handler(int s){ - QCoreApplication::quit(); -} - -void setupQuitSignal(bool gui) -{ - // Catch ctrl-c to close the gui - struct sigaction sigIntHandler; - if(gui) - { - sigIntHandler.sa_handler = my_handler_gui; - } - else - { - sigIntHandler.sa_handler = my_handler; - } - sigemptyset(&sigIntHandler.sa_mask); - sigIntHandler.sa_flags = 0; - sigaction(SIGINT, &sigIntHandler, NULL); -} - -class FindObjectNode : public rclcpp::Node { - -public: - FindObjectNode() : - rclcpp::Node("find_object_2d"), - findObjectROS_(0), - camera_(0), - gui_(true) - { - std::string objectsPath; - std::string sessionPath; - std::string settingsPath = QDir::homePath().append("/.ros/find_object_2d.ini").toStdString(); - bool subscribeDepth = false; - - gui_ = this->declare_parameter("gui", gui_); - objectsPath = this->declare_parameter("objects_path", objectsPath); - sessionPath = this->declare_parameter("session_path", sessionPath); - settingsPath = this->declare_parameter("settings_path", settingsPath); - subscribeDepth = this->declare_parameter("subscribe_depth", subscribeDepth); - - RCLCPP_INFO(this->get_logger(), "gui=%d", gui_?1:0); - RCLCPP_INFO(this->get_logger(), "objects_path=%s", objectsPath.c_str()); - RCLCPP_INFO(this->get_logger(), "session_path=%s", sessionPath.c_str()); - RCLCPP_INFO(this->get_logger(), "settings_path=%s", settingsPath.c_str()); - RCLCPP_INFO(this->get_logger(), "subscribe_depth = %s", subscribeDepth?"true":"false"); - - if(settingsPath.empty()) - { - settingsPath = QDir::homePath().append("/.ros/find_object_2d.ini").toStdString(); - } - else - { - if(!sessionPath.empty()) - { - RCLCPP_WARN(this->get_logger(), "\"settings_path\" parameter is ignored when \"session_path\" is set."); - } - - QString path = settingsPath.c_str(); - if(path.contains('~')) - { - path.replace('~', QDir::homePath()); - settingsPath = path.toStdString(); - } - } - - // Load settings, should be loaded before creating other objects - find_object::Settings::init(settingsPath.c_str()); - - findObjectROS_ = new FindObjectROS(this); - if(!sessionPath.empty()) - { - if(!objectsPath.empty()) - { - RCLCPP_WARN(this->get_logger(), "\"objects_path\" parameter is ignored when \"session_path\" is set."); - } - if(!findObjectROS_->loadSession(sessionPath.c_str())) - { - RCLCPP_ERROR(this->get_logger(), "Failed to load session \"%s\"", sessionPath.c_str()); - } - } - else if(!objectsPath.empty()) - { - QString path = objectsPath.c_str(); - if(path.contains('~')) - { - path.replace('~', QDir::homePath()); - } - if(!findObjectROS_->loadObjects(path)) - { - RCLCPP_ERROR(this->get_logger(), "No objects loaded from path \"%s\"", path.toStdString().c_str()); - } - } - camera_ = new CameraROS(subscribeDepth, this); - - // Catch ctrl-c to close the gui - setupQuitSignal(gui_); - } - - void exec(int argc, char ** argv, std::shared_ptr node) - { - camera_->setupExecutor(node); - if(gui_) - { - QApplication app(argc, argv); - find_object::MainWindow mainWindow(findObjectROS_, camera_); // take ownership - - QObject::connect( - &mainWindow, - SIGNAL(objectsFound(const find_object::DetectionInfo &, const find_object::Header &, const cv::Mat &, float)), - findObjectROS_, - SLOT(publish(const find_object::DetectionInfo &, const find_object::Header &, const cv::Mat &, float))); - - QStringList topics = camera_->subscribedTopics(); - if(topics.size() == 1) - { - mainWindow.setSourceImageText(mainWindow.tr( - "Find-Object subscribed to %1 topic.
" - "You can remap the topic when starting the node:
\"rosrun find_object_2d find_object_2d image:=your/image/topic\".
" - "
").arg(topics.first())); - } - else if(topics.size() == 3) - { - mainWindow.setSourceImageText(mainWindow.tr( - "Find-Object subscribed to :
%1
%2
%3
" - "
").arg(topics.at(0)).arg(topics.at(1)).arg(topics.at(2))); - } - mainWindow.show(); - app.connect( &app, SIGNAL( lastWindowClosed() ), &app, SLOT( quit() ) ); - - // mainWindow has ownership - findObjectROS_ = 0; - camera_ = 0; - - // loop - mainWindow.startProcessing(); - app.exec(); - find_object::Settings::saveSettings(); - } - else - { - QCoreApplication app(argc, argv); - - // connect stuff: - QObject::connect(camera_, SIGNAL(imageReceived(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)), findObjectROS_, SLOT(detect(const cv::Mat &, const find_object::Header &, const cv::Mat &, float))); - - //loop - camera_->start(); - app.exec(); - - delete camera_; - camera_=0; - delete findObjectROS_; - findObjectROS_=0; - } - } - - virtual ~FindObjectNode() - { - delete findObjectROS_; - delete camera_; - } - -private: - FindObjectROS * findObjectROS_; - CameraROS * camera_; - bool gui_; -}; - -int main(int argc, char** argv) -{ - rclcpp::init(argc, argv); - auto node = std::make_shared(); - node->exec(argc, argv, node); - rclcpp::shutdown(); -} diff --git a/find-object/src/ros2/print_objects_detected_node.cpp b/find-object/src/ros2/print_objects_detected_node.cpp deleted file mode 100644 index 7d9cafb4..00000000 --- a/find-object/src/ros2/print_objects_detected_node.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class PrintObjects: public rclcpp::Node -{ -public: - PrintObjects() : - Node("objects_detected") - { - image_transport::TransportHints hints(this); - - imagePub_ = image_transport::create_publisher(this, "image_with_objects", rclcpp::QoS(1).reliability((rmw_qos_reliability_policy_t)1).get_rmw_qos_profile()); - - // Simple subscriber - sub_ = create_subscription("objects", rclcpp::QoS(1).reliability((rmw_qos_reliability_policy_t)1), std::bind(&PrintObjects::objectsDetectedCallback, this, std::placeholders::_1)); - - // Synchronized image + objects example - imageSub_.subscribe(this, "image", hints.getTransport(), rclcpp::QoS(1).reliability((rmw_qos_reliability_policy_t)1).get_rmw_qos_profile()); - objectsSub_.subscribe(this, "objectsStamped", rclcpp::QoS(1).reliability((rmw_qos_reliability_policy_t)1).get_rmw_qos_profile()); - - exactSync_ = new message_filters::Synchronizer(MyExactSyncPolicy(10), imageSub_, objectsSub_); - exactSync_->registerCallback(std::bind(&PrintObjects::imageObjectsDetectedCallback, this, std::placeholders::_1, std::placeholders::_2)); - } - - virtual ~PrintObjects() - { - delete exactSync_; - } - - /** - * IMPORTANT : - * Parameter General/MirrorView must be false - * Parameter Homography/homographyComputed must be true - */ - void objectsDetectedCallback( - const std_msgs::msg::Float32MultiArray::ConstSharedPtr msg) - { - printf("---\n"); - const std::vector & data = msg->data; - if(data.size()) - { - for(unsigned int i=0; i 0) - { - const std::vector & data = objectsMsg->objects.data; - if(data.size()) - { - for(unsigned int i=0; i(0,0) = data[i+3]; - cvHomography.at(1,0) = data[i+4]; - cvHomography.at(2,0) = data[i+5]; - cvHomography.at(0,1) = data[i+6]; - cvHomography.at(1,1) = data[i+7]; - cvHomography.at(2,1) = data[i+8]; - cvHomography.at(0,2) = data[i+9]; - cvHomography.at(1,2) = data[i+10]; - cvHomography.at(2,2) = data[i+11]; - std::vector inPts, outPts; - inPts.push_back(cv::Point2f(0,0)); - inPts.push_back(cv::Point2f(objectWidth,0)); - inPts.push_back(cv::Point2f(objectWidth,objectHeight)); - inPts.push_back(cv::Point2f(0,objectHeight)); - inPts.push_back(cv::Point2f(objectWidth/2,objectHeight/2)); - cv::perspectiveTransform(inPts, outPts, cvHomography); - - cv_bridge::CvImageConstPtr imageDepthPtr = cv_bridge::toCvShare(imageMsg); - - cv_bridge::CvImage img; - img = *imageDepthPtr; - std::vector outPtsInt; - outPtsInt.push_back(outPts[0]); - outPtsInt.push_back(outPts[1]); - outPtsInt.push_back(outPts[2]); - outPtsInt.push_back(outPts[3]); - QColor color(QColor((Qt::GlobalColor)((id % 10 + 7)==Qt::yellow?Qt::darkYellow:(id % 10 + 7)))); - cv::Scalar cvColor(color.red(), color.green(), color.blue()); - cv::polylines(img.image, outPtsInt, true, cvColor, 3); - cv::Point2i center = outPts[4]; - cv::putText(img.image, QString("(%1, %2)").arg(center.x).arg(center.y).toStdString(), center, cv::FONT_HERSHEY_SIMPLEX, 0.6, cvColor, 2); - cv::circle(img.image, center, 1, cvColor, 3); - imagePub_.publish(img.toImageMsg()); - } - } - } - } - -private: - typedef message_filters::sync_policies::ExactTime< - sensor_msgs::msg::Image, - find_object_2d::msg::ObjectsStamped> MyExactSyncPolicy; - message_filters::Synchronizer * exactSync_; - image_transport::Publisher imagePub_; - image_transport::SubscriberFilter imageSub_; - message_filters::Subscriber objectsSub_; - rclcpp::Subscription::SharedPtr sub_; - -}; - - -int main(int argc, char** argv) -{ - rclcpp::init(argc, argv); - rclcpp::spin(std::make_shared()); - rclcpp::shutdown(); - - return 0; -} diff --git a/find-object/src/ros2/tf_example_node.cpp b/find-object/src/ros2/tf_example_node.cpp deleted file mode 100644 index 7def21d0..00000000 --- a/find-object/src/ros2/tf_example_node.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include -#include -#include -#include -#include -#include - -class TfExample : public rclcpp::Node -{ -public: - TfExample() : - Node("tf_example_node"), - objFramePrefix_("object") - { - tfBuffer_ = std::make_shared(this->get_clock()); - //auto timer_interface = std::make_shared( - // this->get_node_base_interface(), - // this->get_node_timers_interface()); - //tfBuffer_->setCreateTimerInterface(timer_interface); - tfListener_ = std::make_shared(*tfBuffer_); - - targetFrameId_ = this->declare_parameter("target_frame_id", targetFrameId_); - objFramePrefix_ = this->declare_parameter("object_prefix", objFramePrefix_); - - subs_ = create_subscription("objectsStamped", rclcpp::QoS(5).reliability((rmw_qos_reliability_policy_t)1), std::bind(&TfExample::objectsDetectedCallback, this, std::placeholders::_1)); - } - - // Here I synchronize with the ObjectsStamped topic to - // know when the TF is ready and for which objects - void objectsDetectedCallback(const find_object_2d::msg::ObjectsStamped::ConstSharedPtr msg) - { - if(msg->objects.data.size()) - { - std::string targetFrameId = targetFrameId_; - if(targetFrameId.empty()) - { - targetFrameId = msg->header.frame_id; - } - char multiSubId = 'b'; - int previousId = -1; - for(unsigned int i=0; iobjects.data.size(); i+=12) - { - // get data - int id = (int)msg->objects.data[i]; - - QString multiSuffix; - if(id == previousId) - { - multiSuffix = QString("_") + multiSubId++; - } - else - { - multiSubId = 'b'; - } - previousId = id; - - // "object_1", "object_1_b", "object_1_c", "object_2" - std::string objectFrameId = QString("%1_%2%3").arg(objFramePrefix_.c_str()).arg(id).arg(multiSuffix).toStdString(); - - geometry_msgs::msg::TransformStamped pose; - try - { - // Get transformation from "object_#" frame to target frame - // The timestamp matches the one sent over TF - pose = tfBuffer_->lookupTransform(targetFrameId, objectFrameId, tf2_ros::fromMsg(msg->header.stamp)); - } - catch(tf2::TransformException & ex) - { - RCLCPP_WARN(this->get_logger(), "%s",ex.what()); - continue; - } - - // Here "pose" is the position of the object "id" in target frame. - RCLCPP_INFO(this->get_logger(), "%s [x,y,z] [x,y,z,w] in \"%s\" frame: [%f,%f,%f] [%f,%f,%f,%f]", - objectFrameId.c_str(), targetFrameId.c_str(), - pose.transform.translation.x, pose.transform.translation.y, pose.transform.translation.z, - pose.transform.rotation.x, pose.transform.rotation.y, pose.transform.rotation.z, pose.transform.rotation.w); - } - } - } - -private: - std::string targetFrameId_; - std::string objFramePrefix_; - rclcpp::Subscription::SharedPtr subs_; - std::shared_ptr tfBuffer_; - std::shared_ptr tfListener_; -}; - -int main(int argc, char * argv[]) -{ - rclcpp::init(argc, argv); - rclcpp::spin(std::make_shared()); - rclcpp::shutdown(); -} diff --git a/find-object/src/rtabmap/PdfPlot.cpp b/find-object/src/rtabmap/PdfPlot.cpp deleted file mode 100644 index 57bd16b8..00000000 --- a/find-object/src/rtabmap/PdfPlot.cpp +++ /dev/null @@ -1,161 +0,0 @@ -// Taken from RTAB-Map library r606 [www.rtabmap.googlecode.com] - -/* - * Copyright (C) 2010-2011, Mathieu Labbe and IntRoLab - Universite de Sherbrooke - * - * This file is part of RTAB-Map. - * - * RTAB-Map is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * RTAB-Map is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RTAB-Map. If not, see . - */ - -#include "PdfPlot.h" -#include "find_object/utilite/ULogger.h" - -namespace rtabmap { - -PdfPlotItem::PdfPlotItem(float dataX, float dataY, float width, int childCount) : - UPlotItem(dataX, dataY, width), - _img(0), - _imagesRef(0) -{ - setLikelihood(dataX, dataY, childCount); - _text = new QGraphicsTextItem(this); - _text->setVisible(false); -} - -PdfPlotItem::~PdfPlotItem() -{ - -} - -void PdfPlotItem::setLikelihood(int id, float value, int childCount) -{ - if(_img && id != this->data().x()) - { - delete _img; - _img = 0; - } - this->setData(QPointF(id, value)); - _childCount = childCount; -} - -void PdfPlotItem::showDescription(bool shown) -{ - if(shown) - { - if(!_img && _imagesRef) - { - QImage img; - QMap::const_iterator iter = _imagesRef->find(int(this->data().x())); - if(iter != _imagesRef->constEnd()) - { - if(img.loadFromData(iter.value(), "JPEG")) - { - QPixmap scaled = QPixmap::fromImage(img).scaledToWidth(128); - _img = new QGraphicsPixmapItem(scaled, this); - _img->setVisible(false); - } - } - } - - if(_img) - _text->setPos(this->mapFromScene(4+150,0)); - else - _text->setPos(this->mapFromScene(4,0)); - if(_childCount >= 0) - { - _text->setPlainText(QString("ID = %1\nValue = %2\nWeight = %3").arg(this->data().x()).arg(this->data().y()).arg(_childCount)); - } - else - { - _text->setPlainText(QString("ID = %1\nValue = %2").arg(this->data().x()).arg(this->data().y())); - } - _text->setVisible(true); - if(_img) - { - _img->setPos(this->mapFromScene(4,0)); - _img->setVisible(true); - } - } - else - { - _text->setVisible(false); - if(_img) - _img->setVisible(false); - } - UPlotItem::showDescription(shown); -} - - - - - -PdfPlotCurve::PdfPlotCurve(const QString & name, const QMap * imagesMapRef = 0, QObject * parent) : - UPlotCurve(name, parent), - _imagesMapRef(imagesMapRef) -{ - -} - -PdfPlotCurve::~PdfPlotCurve() -{ - -} - -void PdfPlotCurve::clear() -{ - UPlotCurve::clear(); -} - -void PdfPlotCurve::setData(const QMap & dataMap, const QMap & weightsMap) -{ - ULOGGER_DEBUG("dataMap=%d, weightsMap=%d", dataMap.size(), weightsMap.size()); - if(dataMap.size() > 0) - { - //match the size of the current data - int margin = int((_items.size()+1)/2) - dataMap.size(); - - while(margin < 0) - { - PdfPlotItem * newItem = new PdfPlotItem(0, 0, 2, 0); - newItem->setImagesRef(_imagesMapRef); - this->_addValue(newItem); - ++margin; - } - - while(margin > 0) - { - this->removeItem(0); - --margin; - } - - ULOGGER_DEBUG("itemsize=%d", _items.size()); - - // update values - QList::iterator iter = _items.begin(); - for(QMap::const_iterator i=dataMap.begin(); i!=dataMap.end(); ++i) - { - UASSERT(iter!= _items.end()); - ((PdfPlotItem*)*iter)->setLikelihood(i.key(), i.value(), weightsMap.value(i.key(),-1)); - //2 times... - ++iter; - ++iter; - } - //reset minMax, this will force the plot to update the axes - this->updateMinMax(); - Q_EMIT dataChanged(this); - } -} - -} diff --git a/find-object/src/rtabmap/PdfPlot.h b/find-object/src/rtabmap/PdfPlot.h deleted file mode 100644 index 0c62403a..00000000 --- a/find-object/src/rtabmap/PdfPlot.h +++ /dev/null @@ -1,69 +0,0 @@ -// Taken from RTAB-Map library r606 [www.rtabmap.googlecode.com] - -/* - * Copyright (C) 2010-2011, Mathieu Labbe and IntRoLab - Universite de Sherbrooke - * - * This file is part of RTAB-Map. - * - * RTAB-Map is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * RTAB-Map is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RTAB-Map. If not, see . - */ - -#ifndef PDFPLOT_H_ -#define PDFPLOT_H_ - -#include "utilite/UPlot.h" - -namespace rtabmap { - -class PdfPlotItem : public UPlotItem -{ -public: - PdfPlotItem(float dataX, float dataY, float width, int childCount = -1); - virtual ~PdfPlotItem(); - - void setLikelihood(int id, float value, int childCount); - void setImagesRef(const QMap * imagesRef) {_imagesRef = imagesRef;} - - float value() const {return this->data().y();} - int id() const {return this->data().x();} - -protected: - virtual void showDescription(bool shown); - -private: - QGraphicsTextItem * _text; - QGraphicsPixmapItem * _img; - int _childCount; - const QMap * _imagesRef; - -}; - -class PdfPlotCurve : public UPlotCurve -{ - Q_OBJECT - -public: - PdfPlotCurve(const QString & name, const QMap * imagesMapRef, QObject * parent = 0); - virtual ~PdfPlotCurve(); - - virtual void clear(); - void setData(const QMap & dataMap, const QMap & weightsMap); - -private: - const QMap * _imagesMapRef; -}; - -} - -#endif /* PDFPLOT_H_ */ diff --git a/find-object/src/superpoint_torch/SuperPoint.cc b/find-object/src/superpoint_torch/SuperPoint.cc deleted file mode 100644 index 107bd5bb..00000000 --- a/find-object/src/superpoint_torch/SuperPoint.cc +++ /dev/null @@ -1,355 +0,0 @@ -/** - * Original code from https://github.com/KinglittleQ/SuperPoint_SLAM - */ - -#include -#include - - -namespace find_object -{ - -const int c1 = 64; -const int c2 = 64; -const int c3 = 128; -const int c4 = 128; -const int c5 = 256; -const int d1 = 256; - - - -SuperPoint::SuperPoint() - : conv1a(torch::nn::Conv2dOptions( 1, c1, 3).stride(1).padding(1)), - conv1b(torch::nn::Conv2dOptions(c1, c1, 3).stride(1).padding(1)), - - conv2a(torch::nn::Conv2dOptions(c1, c2, 3).stride(1).padding(1)), - conv2b(torch::nn::Conv2dOptions(c2, c2, 3).stride(1).padding(1)), - - conv3a(torch::nn::Conv2dOptions(c2, c3, 3).stride(1).padding(1)), - conv3b(torch::nn::Conv2dOptions(c3, c3, 3).stride(1).padding(1)), - - conv4a(torch::nn::Conv2dOptions(c3, c4, 3).stride(1).padding(1)), - conv4b(torch::nn::Conv2dOptions(c4, c4, 3).stride(1).padding(1)), - - convPa(torch::nn::Conv2dOptions(c4, c5, 3).stride(1).padding(1)), - convPb(torch::nn::Conv2dOptions(c5, 65, 1).stride(1).padding(0)), - - convDa(torch::nn::Conv2dOptions(c4, c5, 3).stride(1).padding(1)), - convDb(torch::nn::Conv2dOptions(c5, d1, 1).stride(1).padding(0)) - - { - register_module("conv1a", conv1a); - register_module("conv1b", conv1b); - - register_module("conv2a", conv2a); - register_module("conv2b", conv2b); - - register_module("conv3a", conv3a); - register_module("conv3b", conv3b); - - register_module("conv4a", conv4a); - register_module("conv4b", conv4b); - - register_module("convPa", convPa); - register_module("convPb", convPb); - - register_module("convDa", convDa); - register_module("convDb", convDb); - } - - -std::vector SuperPoint::forward(torch::Tensor x) { - - x = torch::relu(conv1a->forward(x)); - x = torch::relu(conv1b->forward(x)); - x = torch::max_pool2d(x, 2, 2); - - x = torch::relu(conv2a->forward(x)); - x = torch::relu(conv2b->forward(x)); - x = torch::max_pool2d(x, 2, 2); - - x = torch::relu(conv3a->forward(x)); - x = torch::relu(conv3b->forward(x)); - x = torch::max_pool2d(x, 2, 2); - - x = torch::relu(conv4a->forward(x)); - x = torch::relu(conv4b->forward(x)); - - auto cPa = torch::relu(convPa->forward(x)); - auto semi = convPb->forward(cPa); // [B, 65, H/8, W/8] - - auto cDa = torch::relu(convDa->forward(x)); - auto desc = convDb->forward(cDa); // [B, d1, H/8, W/8] - - auto dn = torch::norm(desc, 2, 1); - desc = desc.div(torch::unsqueeze(dn, 1)); - - semi = torch::softmax(semi, 1); - semi = semi.slice(1, 0, 64); - semi = semi.permute({0, 2, 3, 1}); // [B, H/8, W/8, 64] - - - int Hc = semi.size(1); - int Wc = semi.size(2); - semi = semi.contiguous().view({-1, Hc, Wc, 8, 8}); - semi = semi.permute({0, 1, 3, 2, 4}); - semi = semi.contiguous().view({-1, Hc * 8, Wc * 8}); // [B, H, W] - - - std::vector ret; - ret.push_back(semi); - ret.push_back(desc); - - return ret; - } - -void NMS(const std::vector & ptsIn, - const cv::Mat & conf, - const cv::Mat & descriptorsIn, - std::vector & ptsOut, - cv::Mat & descriptorsOut, - int border, int dist_thresh, int img_width, int img_height); - -SPDetector::SPDetector(const std::string & modelPath, float threshold, bool nms, int minDistance, bool cuda) : - threshold_(threshold), - nms_(nms), - minDistance_(minDistance), - detected_(false) -{ - UDEBUG("modelPath=%s thr=%f nms=%d cuda=%d", modelPath.c_str(), threshold, nms?1:0, cuda?1:0); - if(modelPath.empty()) - { - return; - } - model_ = std::make_shared(); - torch::load(model_, modelPath); - - if(cuda && !torch::cuda::is_available()) - { - UWARN("Cuda option is enabled but torch doesn't have cuda support on this platform, using CPU instead."); - } - cuda_ = cuda && torch::cuda::is_available(); - torch::Device device(cuda_?torch::kCUDA:torch::kCPU); - model_->to(device); -} - -SPDetector::~SPDetector() -{ -} - -std::vector SPDetector::detect(const cv::Mat &img) -{ - detected_ = false; - if(model_) - { - torch::NoGradGuard no_grad_guard; - auto x = torch::from_blob(img.data, {1, 1, img.rows, img.cols}, torch::kByte); - x = x.to(torch::kFloat) / 255; - - torch::Device device(cuda_?torch::kCUDA:torch::kCPU); - x = x.set_requires_grad(false); - auto out = model_->forward(x.to(device)); - - prob_ = out[0].squeeze(0); // [H, W] - desc_ = out[1]; // [1, 256, H/8, W/8] - - auto kpts = (prob_ > threshold_); - kpts = torch::nonzero(kpts); // [n_keypoints, 2] (y, x) - - std::vector keypoints_no_nms; - for (int i = 0; i < kpts.size(0); i++) { - float response = prob_[kpts[i][0]][kpts[i][1]].item(); - keypoints_no_nms.push_back(cv::KeyPoint(kpts[i][1].item(), kpts[i][0].item(), 8, -1, response)); - } - - detected_ = true; - if (nms_ && !keypoints_no_nms.empty()) { - cv::Mat conf(keypoints_no_nms.size(), 1, CV_32F); - for (size_t i = 0; i < keypoints_no_nms.size(); i++) { - int x = keypoints_no_nms[i].pt.x; - int y = keypoints_no_nms[i].pt.y; - conf.at(i, 0) = prob_[y][x].item(); - } - - int border = 0; - int dist_thresh = minDistance_; - int height = img.rows; - int width = img.cols; - - std::vector keypoints; - cv::Mat descEmpty; - NMS(keypoints_no_nms, conf, descEmpty, keypoints, descEmpty, border, dist_thresh, width, height); - return keypoints; - } - else { - return keypoints_no_nms; - } - } - else - { - UERROR("No model is loaded!"); - return std::vector(); - } -} - -cv::Mat SPDetector::compute(const std::vector &keypoints) -{ - if(!detected_) - { - UERROR("SPDetector has been reset before extracting the descriptors! detect() should be called before compute()."); - return cv::Mat(); - } - if(model_.get()) - { - cv::Mat kpt_mat(keypoints.size(), 2, CV_32F); // [n_keypoints, 2] (y, x) - - for (size_t i = 0; i < keypoints.size(); i++) { - kpt_mat.at(i, 0) = (float)keypoints[i].pt.y; - kpt_mat.at(i, 1) = (float)keypoints[i].pt.x; - } - - auto fkpts = torch::from_blob(kpt_mat.data, {(long int)keypoints.size(), 2}, torch::kFloat); - - torch::Device device(cuda_?torch::kCUDA:torch::kCPU); - auto grid = torch::zeros({1, 1, fkpts.size(0), 2}).to(device); // [1, 1, n_keypoints, 2] - grid[0][0].slice(1, 0, 1) = 2.0 * fkpts.slice(1, 1, 2) / prob_.size(1) - 1; // x - grid[0][0].slice(1, 1, 2) = 2.0 * fkpts.slice(1, 0, 1) / prob_.size(0) - 1; // y - - auto desc = torch::grid_sampler(desc_, grid, 0, 0, true); // [1, 256, 1, n_keypoints] - desc = desc.squeeze(0).squeeze(1); // [256, n_keypoints] - - // normalize to 1 - auto dn = torch::norm(desc, 2, 1); - desc = desc.div(torch::unsqueeze(dn, 1)); - - desc = desc.transpose(0, 1).contiguous(); // [n_keypoints, 256] - if(cuda_) - desc = desc.to(torch::kCPU); - - cv::Mat desc_mat(cv::Size(desc.size(1), desc.size(0)), CV_32FC1, desc.data()); - - return desc_mat.clone(); - } - else - { - UERROR("No model is loaded!"); - return cv::Mat(); - } -} - -void NMS(const std::vector & ptsIn, - const cv::Mat & conf, - const cv::Mat & descriptorsIn, - std::vector & ptsOut, - cv::Mat & descriptorsOut, - int border, int dist_thresh, int img_width, int img_height) -{ - - std::vector pts_raw; - - for (size_t i = 0; i < ptsIn.size(); i++) - { - int u = (int) ptsIn[i].pt.x; - int v = (int) ptsIn[i].pt.y; - - pts_raw.push_back(cv::Point2f(u, v)); - } - - //Grid Value Legend: - // 255 : Kept. - // 0 : Empty or suppressed. - // 100 : To be processed (converted to either kept or suppressed). - cv::Mat grid = cv::Mat(cv::Size(img_width, img_height), CV_8UC1); - cv::Mat inds = cv::Mat(cv::Size(img_width, img_height), CV_16UC1); - - cv::Mat confidence = cv::Mat(cv::Size(img_width, img_height), CV_32FC1); - - grid.setTo(0); - inds.setTo(0); - confidence.setTo(0); - - for (size_t i = 0; i < pts_raw.size(); i++) - { - int uu = (int) pts_raw[i].x; - int vv = (int) pts_raw[i].y; - - grid.at(vv, uu) = 100; - inds.at(vv, uu) = i; - - confidence.at(vv, uu) = conf.at(i, 0); - } - - // debug - //cv::Mat confidenceVis = confidence.clone() * 255; - //confidenceVis.convertTo(confidenceVis, CV_8UC1); - //cv::imwrite("confidence.bmp", confidenceVis); - //cv::imwrite("grid_in.bmp", grid); - - cv::copyMakeBorder(grid, grid, dist_thresh, dist_thresh, dist_thresh, dist_thresh, cv::BORDER_CONSTANT, 0); - - for (size_t i = 0; i < pts_raw.size(); i++) - { - // account for top left padding - int uu = (int) pts_raw[i].x + dist_thresh; - int vv = (int) pts_raw[i].y + dist_thresh; - float c = confidence.at(vv-dist_thresh, uu-dist_thresh); - - if (grid.at(vv, uu) == 100) // If not yet suppressed. - { - for(int k = -dist_thresh; k < (dist_thresh+1); k++) - { - for(int j = -dist_thresh; j < (dist_thresh+1); j++) - { - if(j==0 && k==0) - continue; - - if ( confidence.at(vv + k - dist_thresh, uu + j - dist_thresh) <= c ) - { - grid.at(vv + k, uu + j) = 0; - } - } - } - grid.at(vv, uu) = 255; - } - } - - size_t valid_cnt = 0; - std::vector select_indice; - - grid = cv::Mat(grid, cv::Rect(dist_thresh, dist_thresh, img_width, img_height)); - - //debug - //cv::imwrite("grid_nms.bmp", grid); - - for (int v = 0; v < img_height; v++) - { - for (int u = 0; u < img_width; u++) - { - if (grid.at(v,u) == 255) - { - int select_ind = (int) inds.at(v, u); - float response = conf.at(select_ind, 0); - ptsOut.push_back(cv::KeyPoint(pts_raw[select_ind], 8.0f, -1, response)); - - select_indice.push_back(select_ind); - valid_cnt++; - } - } - } - - if(!descriptorsIn.empty()) - { - UASSERT(descriptorsIn.rows == (int)ptsIn.size()); - descriptorsOut.create(select_indice.size(), 256, CV_32F); - - for (size_t i=0; i(i, j) = descriptorsIn.at(select_indice[i], j); - } - } - } -} - -} diff --git a/find-object/src/superpoint_torch/SuperPoint.h b/find-object/src/superpoint_torch/SuperPoint.h deleted file mode 100644 index fa66d134..00000000 --- a/find-object/src/superpoint_torch/SuperPoint.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Original code from https://github.com/KinglittleQ/SuperPoint_SLAM - */ - -#ifndef SUPERPOINT_H -#define SUPERPOINT_H - - -#include -#include - -#include - -#ifdef EIGEN_MPL2_ONLY -#undef EIGEN_MPL2_ONLY -#endif - - -namespace find_object -{ - -struct SuperPoint : torch::nn::Module { - SuperPoint(); - - std::vector forward(torch::Tensor x); - - - torch::nn::Conv2d conv1a; - torch::nn::Conv2d conv1b; - - torch::nn::Conv2d conv2a; - torch::nn::Conv2d conv2b; - - torch::nn::Conv2d conv3a; - torch::nn::Conv2d conv3b; - - torch::nn::Conv2d conv4a; - torch::nn::Conv2d conv4b; - - torch::nn::Conv2d convPa; - torch::nn::Conv2d convPb; - - // descriptor - torch::nn::Conv2d convDa; - torch::nn::Conv2d convDb; - -}; - -class SPDetector { -public: - SPDetector(const std::string & modelPath, float threshold = 0.2f, bool nms = true, int minDistance = 4, bool cuda = false); - virtual ~SPDetector(); - std::vector detect(const cv::Mat &img); - cv::Mat compute(const std::vector &keypoints); - - void setThreshold(float threshold) {threshold_ = threshold;} - void SetNMS(bool enabled) {nms_ = enabled;} - void setMinDistance(float minDistance) {minDistance_ = minDistance;} - -private: - std::shared_ptr model_; - torch::Tensor prob_; - torch::Tensor desc_; - - float threshold_; - bool nms_; - int minDistance_; - bool cuda_; - - bool detected_; -}; - -} - -#endif diff --git a/find-object/src/ui/aboutDialog.ui b/find-object/src/ui/aboutDialog.ui deleted file mode 100644 index b11cb80b..00000000 --- a/find-object/src/ui/aboutDialog.ui +++ /dev/null @@ -1,265 +0,0 @@ - - - aboutDialog - - - - 0 - 0 - 527 - 289 - - - - - 0 - 0 - - - - About Find-Object - - - - - - - - - 100 - 100 - - - - - - - :/images/resources/Find-Object.png - - - true - - - - - - - QFrame::Box - - - QFrame::Raised - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600;">Find-Object</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - true - - - - - - - - - Author : - - - - - - - Link : - - - - - - - Version : - - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://code.google.com/p/find-object"><span style=" text-decoration: underline; color:#0000ff;">Home page</span></a></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - true - - - - - - - Mathieu Labbé, matlabbe@gmail.com - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - OpenCV version : - - - - - - - Qt version : - - - - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 1 - - - - - - - - - - - :/images/IntRoLabSmall.png - - - Qt::AlignCenter - - - - - - - Copyright (C) 2011-2015 IntRoLab - Université de Sherbrooke - - - Qt::AlignCenter - - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Close - - - - - - - - - - - - - buttonBox - accepted() - aboutDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - aboutDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/find-object/src/ui/addObjectDialog.ui b/find-object/src/ui/addObjectDialog.ui deleted file mode 100644 index 6ee59a70..00000000 --- a/find-object/src/ui/addObjectDialog.ui +++ /dev/null @@ -1,109 +0,0 @@ - - - addObjectDialog - - - - 0 - 0 - 527 - 420 - - - - Add object - - - - - - - - (Instructions) - - - - - - - - Select region - - - - - Select keypoints - - - - - - - - - - - - - - - - - - - - - - Cancel - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Back - - - - - - - Take picture - - - - - - - End - - - - - - - - - - find_object::ObjWidget - QWidget -
find_object/ObjWidget.h
- 1 -
-
- - -
diff --git a/find-object/src/ui/mainWindow.ui b/find-object/src/ui/mainWindow.ui deleted file mode 100644 index 29e111d9..00000000 --- a/find-object/src/ui/mainWindow.ui +++ /dev/null @@ -1,941 +0,0 @@ - - - mainWindow - - - - 0 - 0 - 881 - 552 - - - - Find-Object - - - - :/images/resources/Find-Object.png:/images/resources/Find-Object.png - - - - - 0 - - - 0 - - - - - - 0 - - - 0 - - - - - - - - 75 - true - - - - Camera - - - - - - - (0 Hz - 0 Hz) - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - 0 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - features - - - - - - - - - - - - - - - 0 - - - - - - 0 - 0 - - - - - 24 - 24 - - - - - - - - :/images/resources/TheWorkingGroup_video_play.ico:/images/resources/TheWorkingGroup_video_play.ico - - - - - - - - 24 - 24 - - - - - - - - :/images/resources/TheWorkingGroup_video_pause.ico:/images/resources/TheWorkingGroup_video_pause.ico - - - - - - - - 24 - 24 - - - - - - - - :/images/resources/TheWorkingGroup_video_stop.ico:/images/resources/TheWorkingGroup_video_stop.ico - - - - - - - Qt::ClickFocus - - - 0 - - - Qt::Horizontal - - - - - - - 0 - - - - - - - - - - - - - - - - - 0 - 0 - 881 - 22 - - - - - File - - - - - - - - - - - - - - - - - - Edit - - - - - - - - - - - - - - - - - - - - View - - - - - - - - ? - - - - - - - - - - - - 360 - 168 - - - - false - - - Parameters - - - 2 - - - - - 0 - - - 0 - - - - - 0 - - - - - 0 - 0 - 348 - 76 - - - - Dummy - - - - - - - - - Restore defaults - - - - - - - - - - 208 - 196 - - - - Objects - - - 1 - - - - - 0 - - - - - - 0 - - - 0 - - - - - - 150 - 0 - - - - true - - - - - 0 - 0 - 222 - 425 - - - - - 0 - - - 0 - - - - - Qt::Vertical - - - - 20 - 230 - - - - - - - - - - - - 12 - - - - - Update objects - - - - - - - - 20 - 0 - - - - Qt::ClickFocus - - - 100 - - - 100 - - - Qt::Horizontal - - - - - - - - - - - - - - Likelihood - - - 8 - - - - - 0 - - - 0 - - - - - - - - - - Statistics - - - 2 - - - - - - - 6 - - - 0 - - - - - 000 - - - - - - - 000 - - - - - - - ms - - - - - - - ms - - - - - - - ms - - - - - - - Vocabulary size - - - - - - - 000 - - - - - - - IP address - - - - - - - Output detection port - - - - - - - 0.0.0.0 - - - - - - - 0 - - - - - - - Objects detected - - - - - - - 000 - - - - - - - 000 - - - - - - - Input image port - - - - - - - - - - - - - - - Affine transforms - - - - - - - Descriptors indexing - - - - - - - ms - - - - - - - 000 - - - - - - - Min matched distance - - - - - - - Max matched distance - - - - - - - 000 - - - - - - - Homograhies - - - - - - - Descriptors extraction - - - - - - - ms - - - - - - - 000 - - - - - - - ms - - - - - - - Features detection - - - - - - - 000 - - - - - - - Descriptors matching - - - - - - - Total - - - - - - - 000 - - - - - - - 000 - - - - - - - ms - - - - - - - Refresh GUI - - - - - - - 000 - - - - - - - ms - - - - - - - Features sub pixel refining - - - - - - - 000 - - - - - - - ms - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - Exit - - - - - Add object from scene... - - - - - Start camera - - - - - Stop camera - - - - - Save objects... - - - - - Load objects... - - - - - About... - - - - - Restore all default settings - - - - - Add objects from files... - - - - - Camera from single file... - - - - - Pause camera - - - - - true - - - Camera from video file... - - - - - Remove all objects - - - - - true - - - Camera from directory of images... - - - - - Save settings... - - - - - Load settings... - - - - - true - - - Camera from TCP/IP... - - - - - Load session... - - - - - Save session... - - - - - Hide objects features - - - - - Show objects features - - - - - Load vocabulary... - - - - - Save vocabulary... - - - - - - find_object::ObjWidget - QWidget -
find_object/ObjWidget.h
- 1 -
- - find_object::ParametersToolBox - QToolBox -
ParametersToolBox.h
- 1 -
- - UPlot - QWidget -
utilite/UPlot.h
- 1 -
- - find_object::ImageDropWidget - QWidget -
ImageDropWidget.h
- 1 -
-
- - - - -
diff --git a/find-object/src/utilite/UConversion.cpp b/find-object/src/utilite/UConversion.cpp deleted file mode 100644 index 97296e50..00000000 --- a/find-object/src/utilite/UConversion.cpp +++ /dev/null @@ -1,326 +0,0 @@ -// Taken from UtiLite library r266 [www.utilite.googlecode.com] -/* -* utilite is a cross-platform library with -* useful utilities for fast and small developing. -* Copyright (C) 2010 Mathieu Labbe -* -* utilite is free library: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* utilite is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this program. If not, see . -*/ - -#include "utilite/UConversion.h" - -#include -#include -#include - -#ifdef WIN32 -#include -#endif - -std::string uReplaceChar(const std::string & str, char before, char after) -{ - std::string result = str; - for(unsigned int i=0; i= 'a' && result[i]<='z') - { - result[i] = result[i] - 'a' + 'A'; - } - } - return result; -} - -std::string uToLowerCase(const std::string & str) -{ - std::string result = str; - for(unsigned int i=0; i= 'A' && result[i]<='Z') - { - result[i] = result[i] - 'A' + 'a'; - } - } - return result; -} - -std::string uNumber2Str(unsigned int number) -{ - std::stringstream s; - s << number; - return s.str(); -} - -std::string uNumber2Str(int number) -{ - std::stringstream s; - s << number; - return s.str(); -} - -std::string uNumber2Str(float number) -{ - std::stringstream s; - s << number; - return s.str(); -} - -std::string uNumber2Str(double number) -{ - std::stringstream s; - s << number; - return s.str(); -} - -std::string uBool2Str(bool boolean) -{ - std::string s; - if(boolean) - { - s = "true"; - } - else - { - s = "false"; - } - return s; -} - -bool uStr2Bool(const char * str) -{ - return !(str && (strcmp(str, "false") == 0 || strcmp(str, "FALSE") == 0 || strcmp(str, "0") == 0)); -} - -std::string uBytes2Hex(const char * bytes, unsigned int bytesLen) -{ - std::string hex; - if(!bytes || bytesLen == 0) - { - return hex; - } - const unsigned char * bytes_u = (const unsigned char*)(bytes); - - hex.resize(bytesLen*2); - char * pHex = &hex[0]; - const unsigned char * pEnd = (bytes_u + bytesLen); - for(const unsigned char * pChar = bytes_u; pChar != pEnd; ++pChar, pHex += 2) - { - pHex[0] = uHex2Ascii(*pChar, 0); - pHex[1] = uHex2Ascii(*pChar, 1); - } - return hex; -} - -std::vector uHex2Bytes(const std::string & hex) -{ - return uHex2Bytes(&hex[0], (int)hex.length()); -} - -std::vector uHex2Bytes(const char * hex, int hexLen) -{ - std::vector bytes; - if(!hex || hexLen % 2 || hexLen == 0) - { - return bytes; // must be pair - } - - unsigned int bytesLen = hexLen / 2; - bytes.resize(bytesLen); - unsigned char * pBytes = (unsigned char *)&bytes[0]; - const unsigned char * pHex = (const unsigned char *)hex; - - unsigned char * pEnd = (pBytes + bytesLen); - for(unsigned char * pChar = pBytes; pChar != pEnd; pChar++, pHex += 2) - { - *pChar = (uAscii2Hex(pHex[0]) << 4) | uAscii2Hex(pHex[1]); - } - return bytes; -} - -// The hex str MUST not contains any null values (0x00) -std::string uHex2Str(const std::string & hex) -{ - std::vector bytes = uHex2Bytes(hex); - return std::string(&bytes[0], bytes.size()); -} - -static const char HEX2ASCII[256][2] = -{ - {'0','0'},{'0','1'},{'0','2'},{'0','3'},{'0','4'},{'0','5'},{'0','6'},{'0','7'},{'0','8'},{'0','9'},{'0','A'},{'0','B'},{'0','C'},{'0','D'},{'0','E'},{'0','F'}, - {'1','0'},{'1','1'},{'1','2'},{'1','3'},{'1','4'},{'1','5'},{'1','6'},{'1','7'},{'1','8'},{'1','9'},{'1','A'},{'1','B'},{'1','C'},{'1','D'},{'1','E'},{'1','F'}, - {'2','0'},{'2','1'},{'2','2'},{'2','3'},{'2','4'},{'2','5'},{'2','6'},{'2','7'},{'2','8'},{'2','9'},{'2','A'},{'2','B'},{'2','C'},{'2','D'},{'2','E'},{'2','F'}, - {'3','0'},{'3','1'},{'3','2'},{'3','3'},{'3','4'},{'3','5'},{'3','6'},{'3','7'},{'3','8'},{'3','9'},{'3','A'},{'3','B'},{'3','C'},{'3','D'},{'3','E'},{'3','F'}, - {'4','0'},{'4','1'},{'4','2'},{'4','3'},{'4','4'},{'4','5'},{'4','6'},{'4','7'},{'4','8'},{'4','9'},{'4','A'},{'4','B'},{'4','C'},{'4','D'},{'4','E'},{'4','F'}, - {'5','0'},{'5','1'},{'5','2'},{'5','3'},{'5','4'},{'5','5'},{'5','6'},{'5','7'},{'5','8'},{'5','9'},{'5','A'},{'5','B'},{'5','C'},{'5','D'},{'5','E'},{'5','F'}, - {'6','0'},{'6','1'},{'6','2'},{'6','3'},{'6','4'},{'6','5'},{'6','6'},{'6','7'},{'6','8'},{'6','9'},{'6','A'},{'6','B'},{'6','C'},{'6','D'},{'6','E'},{'6','F'}, - {'7','0'},{'7','1'},{'7','2'},{'7','3'},{'7','4'},{'7','5'},{'7','6'},{'7','7'},{'7','8'},{'7','9'},{'7','A'},{'7','B'},{'7','C'},{'7','D'},{'7','E'},{'7','F'}, - {'8','0'},{'8','1'},{'8','2'},{'8','3'},{'8','4'},{'8','5'},{'8','6'},{'8','7'},{'8','8'},{'8','9'},{'8','A'},{'8','B'},{'8','C'},{'8','D'},{'8','E'},{'8','F'}, - {'9','0'},{'9','1'},{'9','2'},{'9','3'},{'9','4'},{'9','5'},{'9','6'},{'9','7'},{'9','8'},{'9','9'},{'9','A'},{'9','B'},{'9','C'},{'9','D'},{'9','E'},{'9','F'}, - {'A','0'},{'A','1'},{'A','2'},{'A','3'},{'A','4'},{'A','5'},{'A','6'},{'A','7'},{'A','8'},{'A','9'},{'A','A'},{'A','B'},{'A','C'},{'A','D'},{'A','E'},{'A','F'}, - {'B','0'},{'B','1'},{'B','2'},{'B','3'},{'B','4'},{'B','5'},{'B','6'},{'B','7'},{'B','8'},{'B','9'},{'B','A'},{'B','B'},{'B','C'},{'B','D'},{'B','E'},{'B','F'}, - {'C','0'},{'C','1'},{'C','2'},{'C','3'},{'C','4'},{'C','5'},{'C','6'},{'C','7'},{'C','8'},{'C','9'},{'C','A'},{'C','B'},{'C','C'},{'C','D'},{'C','E'},{'C','F'}, - {'D','0'},{'D','1'},{'D','2'},{'D','3'},{'D','4'},{'D','5'},{'D','6'},{'D','7'},{'D','8'},{'D','9'},{'D','A'},{'D','B'},{'D','C'},{'D','D'},{'D','E'},{'D','F'}, - {'E','0'},{'E','1'},{'E','2'},{'E','3'},{'E','4'},{'E','5'},{'E','6'},{'E','7'},{'E','8'},{'E','9'},{'E','A'},{'E','B'},{'E','C'},{'E','D'},{'E','E'},{'E','F'}, - {'F','0'},{'F','1'},{'F','2'},{'F','3'},{'F','4'},{'F','5'},{'F','6'},{'F','7'},{'F','8'},{'F','9'},{'F','A'},{'F','B'},{'F','C'},{'F','D'},{'F','E'},{'F','F'} -}; - -unsigned char uHex2Ascii(const unsigned char & c, bool rightPart) -{ - if(rightPart) - { - return HEX2ASCII[c][1]; - } - else - { - return HEX2ASCII[c][0]; - } -} - -unsigned char uAscii2Hex(const unsigned char & c) -{ - switch(c) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return c-'0'; - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - return c-'A'+10; - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - return c-'a'+10; - default: - return 0x00; - } -} - -std::string uFormatv (const char *fmt, va_list args) -{ - // Allocate a buffer on the stack that's big enough for us almost - // all the time. Be prepared to allocate dynamically if it doesn't fit. - size_t size = 1024; - std::vector dynamicbuf(size); - char *buf = &dynamicbuf[0]; - - va_list argsTmp; - - while (1) { -#if defined(WIN32) && !defined(__MINGW32__) - argsTmp = args; -#else - va_copy(argsTmp, args); -#endif - - // Try to vsnprintf into our buffer. -#ifdef _MSC_VER - int needed = (int)vsnprintf_s(buf, size, _TRUNCATE, fmt, argsTmp); -#else - int needed = (int)vsnprintf(buf, size, fmt, argsTmp); -#endif - - va_end(argsTmp); - // NB. C99 (which modern Linux and OS X follow) says vsnprintf - // failure returns the length it would have needed. But older - // glibc and current Windows return -1 for failure, i.e., not - // telling us how much was needed. - if (needed < (int)size-1 && needed >= 0) { - // It fit fine so we're done. - return std::string (buf, (size_t) needed); - } - - // vsnprintf reported that it wanted to write more characters - // than we allotted. So try again using a dynamic buffer. This - // doesn't happen very often if we chose our initial size well. - size = needed>=0?needed+2:size*2; - dynamicbuf.resize (size); - buf = &dynamicbuf[0]; - } - return std::string(); // would not reach this, but for compiler complaints... -} - -std::string uFormat (const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - std::string buf = uFormatv(fmt, args); - va_end(args); - return buf; -} - -#ifdef WIN32 -// returned whar_t * must be deleted : delete [] wText; -wchar_t * createWCharFromChar(const char * text) -{ - DWORD length = MultiByteToWideChar (CP_ACP, 0, text, -1, NULL, 0); - wchar_t * wText = new wchar_t[length]; - MultiByteToWideChar (CP_ACP, 0, text, -1, wText, length ); - return wText; -} - -// returned char * must be deleted : delete [] text; -char * createCharFromWChar(const wchar_t * wText) -{ - DWORD length = WideCharToMultiByte (CP_ACP, 0, wText, -1, NULL, 0, NULL, NULL); - char * text = new char[length]; - WideCharToMultiByte (CP_ACP, 0, wText, -1, text, length, NULL, NULL); - return text; -} -#endif diff --git a/find-object/src/utilite/UConversion.h b/find-object/src/utilite/UConversion.h deleted file mode 100644 index d717e891..00000000 --- a/find-object/src/utilite/UConversion.h +++ /dev/null @@ -1,253 +0,0 @@ -/* -* utilite is a cross-platform library with -* useful utilities for fast and small developing. -* Copyright (C) 2010 Mathieu Labbe -* -* utilite is free library: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* utilite is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this program. If not, see . -*/ - -#ifndef UCONVERSION_H -#define UCONVERSION_H - -//#include "utilite/UtiLiteExp.h" // DLL export/import defines - -#include -#include -#include - -/** - * \file UConversion.h - * \brief Some conversion functions - * - * This contains functions to do some convenient conversion like - * uNumber2str(), uBytes2Hex() or uHex2Bytes(). -*/ - -/** - * Replace old characters in a string to new ones. - * Example : - * @code - * std::string str = "Hello"; - * uReplaceChar(str, 'l', 'p'); - * // The results is str = "Heppo"; - * @endcode - * - * @param str the string - * @param before the character to be replaced by the new one - * @param after the new character replacing the old one - * @return the modified string - */ -std::string uReplaceChar(const std::string & str, char before, char after); - -/** - * Replace old characters in a string with the specified string. - * Example : - * @code - * std::string str = "Hello"; - * uReplaceChar(str, 'o', "oween"); - * // The results is str = "Helloween"; - * @endcode - * - * @param str the string - * @param before the character to be replaced by the new one - * @param after the new string replacing the old character - * @return the modified string - */ -std::string uReplaceChar(const std::string & str, char before, const std::string & after); - -/** - * Transform characters from a string to upper case. - * Example : - * @code - * std::string str = "hello!"; - * str = uToUpperCase(str); - * //str is now equal to "HELLO!" - * @endcode - * @param str the string - * @return the modified string - */ -std::string uToUpperCase(const std::string & str); - -/** - * Transform characters from a string to lower case. - * Example : - * @code - * std::string str = "HELLO!"; - * str = uToLowerCase(str, false); - * //str is now equal to "hello!" - * @endcode - * @param str the string - * @return the modified string - */ -std::string uToLowerCase(const std::string & str); - -/** - * Convert a number (unsigned int) to a string. - * @param number the number to convert in a string - * @return the string - */ -std::string uNumber2Str(unsigned int number); -/** - * Convert a number (int) to a string. - * @param number the number to convert in a string - * @return the string - */ -std::string uNumber2Str(int number); -/** - * Convert a number (float) to a string. - * @param number the number to convert in a string - * @return the string - */ -std::string uNumber2Str(float number); -/** - * Convert a number (double) to a string. - * @param number the number to convert in a string - * @return the string - */ -std::string uNumber2Str(double number); - -/** - * Convert a bool to a string. - * The format used is "true" and "false". - * @param boolean the boolean to convert in a string - * @return the string - */ -std::string uBool2Str(bool boolean); -/** - * Convert a string to a boolean. - * The format used is : - * "false", "FALSE" or "0" give false. All others give true. - * @param str the string to convert in a boolean - * @return the boolean - */ -bool uStr2Bool(const char * str); - -/** - * Convert a bytes array to an hexadecimal string. - * The resulting string is twice the size of the bytes array. The hexadecimal - * Characters are in upper case. - * Example : - * @code - * char bytes[] = {0x3F}; - * std::string hex = uBytes2Hex(bytes, 1); - * // The string constains "3F". - * @endcode - * - * @param bytes the bytes array - * @param bytesLen the length of the bytes array - * @return the hexadecimal string - */ -std::string uBytes2Hex(const char * bytes, unsigned int bytesLen); -/** - * Convert an hexadecimal string to a bytes array. - * The string must be pair length. The hexadecimal - * Characters can be in upper or lower case. - * Example : - * @code - * std::string hex = "1f3B"; - * std::vector bytes = uHex2Bytes(hex); - * // The array contains {0x1F, 0x3B}. - * @endcode - * - * @param hex the hexadecimal string - * @return the bytes array - */ -std::vector uHex2Bytes(const std::string & hex); -/** - * Convert an hexadecimal string to a bytes array. - * The string must be pair length. The hexadecimal - * Characters can be in upper or lower case. - * Example : - * @code - * std::vector bytes = uHex2Bytes("1f3B", 4); - * // The array contains {0x1F, 0x3B}. - * @endcode - * - * @param hex the hexadecimal string - * @param bytesLen the hexadecimal string length - * @return the bytes array - */ -std::vector uHex2Bytes(const char * hex, int hexLen); - -/** - * Convert an hexadecimal string to an ascii string. A convenient way - * when using only strings. - * The hexadecimal str MUST not contains any null values 0x00 ("00"). - * Think to use of hex2bytes() to handle 0x00 values. - * Characters can be in upper or lower case. - * Example : - * @code - * std::string str = uHex2Str("48656C6C4F21"); - * // The string contains "Hello!". - * @endcode - * - * @see hex2bytes - * @param hex the hexadecimal string - * @return the ascii string - */ -std::string uHex2Str(const std::string & hex); - -/** - * Convert hexadecimal (left or right part) value to an ascii character. - * Example : - * @code - * unsigned char F = uHex2Ascii(0xFA, false); - * unsigned char A = uHex2Ascii(0xFA, true); - * @endcode - * @see ascii2hex - * @param c the hexadecimal value - * @param rightPart If we want the character corresponding to the right of left part (4 bits) of the byte value. - * @return the ascii character (in upper case) - */ -unsigned char uHex2Ascii(const unsigned char & c, bool rightPart); - -/** - * Convert an ascii character to an hexadecimal value (right 4 bits). - * Characters can be in upper or lower case. - * Example : - * @code - * unsigned char hex = uAscii2Hex('F'); - * // The results is hex = 0x0F; - * @endcode - * @see hex2ascii - * @param c the ascii character - * @return the hexadecimal value - */ -unsigned char uAscii2Hex(const unsigned char & c); - -/** - * Format a string like printf, and return it as a std::string - */ -std::string uFormatv (const char *fmt, va_list ap); - -/** - * Format a string like printf, and return it as a std::string - */ -std::string uFormat (const char *fmt, ...); - -#ifdef WIN32 -/** - * Convert multi-byte string to unicode (wide-char) string. - * Note that returned whar_t * must be deleted : delete [] wText; - */ -wchar_t * createWCharFromChar(const char * text); - -/** - * Convert unicode (wide-char) string to multi-byte string. - * Note that returned char * must be deleted : delete [] text; - */ -char * createCharFromWChar(const wchar_t * wText); -#endif - -#endif /* UCONVERSION_H */ diff --git a/find-object/src/utilite/UDirectory.cpp b/find-object/src/utilite/UDirectory.cpp deleted file mode 100644 index 7ada8ade..00000000 --- a/find-object/src/utilite/UDirectory.cpp +++ /dev/null @@ -1,372 +0,0 @@ -// Taken from UtiLite library r266 [www.utilite.googlecode.com] - -/* -* utilite is a cross-platform library with -* useful utilities for fast and small developing. -* Copyright (C) 2010 Mathieu Labbe -* -* utilite is free library: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* utilite is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this program. If not, see . -*/ - -#include "utilite/UDirectory.h" - -#ifdef WIN32 - #include - #include - #include - #include -#else - #include - #include - #include - #include - #include - #include - #include - #include -#endif - -#include "utilite/UStl.h" -#include "utilite/UFile.h" -#include "utilite/UDirectory.h" -#include "utilite/UConversion.h" - -#ifdef WIN32 - -bool sortCallback(const std::string & a, const std::string & b) -{ - return uStrNumCmp(a,b) < 0; -} -#elif __APPLE__ -int sortCallback(const struct dirent ** a, const struct dirent ** b) -{ - return uStrNumCmp((*a)->d_name, (*b)->d_name); -} -#else -int sortCallback( const dirent ** a, const dirent ** b) -{ - return uStrNumCmp((*a)->d_name, (*b)->d_name); -} -#endif - -UDirectory::UDirectory(const std::string & path, const std::string & extensions) -{ - extensions_ = uListToVector(uSplit(extensions, ' ')); - path_ = path; - iFileName_ = fileNames_.begin(); - this->update(); -} - -UDirectory::UDirectory(const UDirectory & dir) -{ - *this = dir; -} - -UDirectory & UDirectory::operator=(const UDirectory & dir) -{ - extensions_ = dir.extensions_; - path_ = dir.path_; - fileNames_ = dir.fileNames_; - for(iFileName_=fileNames_.begin(); iFileName_!=fileNames_.end(); ++iFileName_) - { - if(iFileName_->compare(*dir.iFileName_) == 0) - { - break; - } - } - return *this; -} - -UDirectory::~UDirectory() -{ -} - -void UDirectory::setPath(const std::string & path, const std::string & extensions) -{ - extensions_ = uListToVector(uSplit(extensions, ' ')); - path_ = path; - fileNames_.clear(); - iFileName_ = fileNames_.begin(); - this->update(); -} - -void UDirectory::update() -{ - if(exists(path_)) - { - std::string lastName; - bool endOfDir = false; - if(iFileName_ != fileNames_.end()) - { - //Record the last file name - lastName = *iFileName_; - } - else if(fileNames_.size()) - { - lastName = *fileNames_.rbegin(); - endOfDir = true; - } - fileNames_.clear(); -#ifdef WIN32 - WIN32_FIND_DATA fileInformation; - #ifdef UNICODE - wchar_t * pathAll = createWCharFromChar((path_+"\\*").c_str()); - HANDLE hFile = ::FindFirstFile(pathAll, &fileInformation); - delete [] pathAll; - #else - HANDLE hFile = ::FindFirstFile((path_+"\\*").c_str(), &fileInformation); - #endif - if(hFile != INVALID_HANDLE_VALUE) - { - do - { - #ifdef UNICODE - char * fileName = createCharFromWChar(fileInformation.cFileName); - fileNames_.push_back(fileName); - delete [] fileName; - #else - fileNames_.push_back(fileInformation.cFileName); - #endif - } while(::FindNextFile(hFile, &fileInformation) == TRUE); - ::FindClose(hFile); - std::vector vFileNames = uListToVector(fileNames_); - std::sort(vFileNames.begin(), vFileNames.end(), sortCallback); - fileNames_ = uVectorToList(vFileNames); - } -#else - int nameListSize; - struct dirent ** nameList = 0; - nameListSize = scandir(path_.c_str(), &nameList, 0, sortCallback); - if(nameList && nameListSize>0) - { - for (int i=0;id_name); - free(nameList[i]); - } - free(nameList); - } -#endif - - //filter extensions... - std::list::iterator iter = fileNames_.begin(); - bool valid; - while(iter!=fileNames_.end()) - { - valid = false; - if(extensions_.size() == 0 && - iter->compare(".") != 0 && - iter->compare("..") != 0) - { - valid = true; - } - for(unsigned int i=0; i::iterator iter=fileNames_.begin(); iter!=fileNames_.end(); ++iter) - { - if(lastName.compare(*iter) == 0) - { - found = true; - iFileName_ = iter; - break; - } - } - if(endOfDir && found) - { - ++iFileName_; - } - else if(endOfDir && fileNames_.size()) - { - iFileName_ = --fileNames_.end(); - } - } - } -} - -bool UDirectory::isValid() -{ - return exists(path_); -} - -std::string UDirectory::getNextFileName() -{ - std::string fileName; - if(iFileName_ != fileNames_.end()) - { - fileName = *iFileName_; - ++iFileName_; - } - return fileName; -} - -void UDirectory::rewind() -{ - iFileName_ = fileNames_.begin(); -} - - -bool UDirectory::exists(const std::string & dirPath) -{ - bool r = false; -#if WIN32 - #ifdef UNICODE - wchar_t * wDirPath = createWCharFromChar(dirPath.c_str()); - DWORD dwAttrib = GetFileAttributes(wDirPath); - delete [] wDirPath; - #else - DWORD dwAttrib = GetFileAttributes(dirPath.c_str()); - #endif - r = (dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); -#else - DIR *dp; - if((dp = opendir(dirPath.c_str())) != NULL) - { - r = true; - closedir(dp); - } -#endif - return r; -} - -// return the directory path of the file -std::string UDirectory::getDir(const std::string & filePath) -{ - std::string dir = filePath; - int i=(int)dir.size()-1; - for(; i>=0; --i) - { - if(dir[i] == '/' || dir[i] == '\\') - { - //remove separators... - dir[i] = 0; - --i; - while(i>=0 && (dir[i] == '/' || dir[i] == '\\')) - { - dir[i] = 0; - --i; - } - break; - } - else - { - dir[i] = 0; - } - } - - if(i<0) - { - dir = "."; - } - else - { - dir.resize(i+1); - } - - return dir; -} - -std::string UDirectory::currentDir(bool trailingSeparator) -{ - std::string dir; - char * buffer; - -#ifdef WIN32 - buffer = _getcwd(NULL, 0); -#else - buffer = getcwd(NULL, MAXPATHLEN); -#endif - - if( buffer != NULL ) - { - dir = buffer; - free(buffer); - if(trailingSeparator) - { - dir += separator(); - } - } - - return dir; -} - -bool UDirectory::makeDir(const std::string & dirPath) -{ - int status; -#if WIN32 - status = _mkdir(dirPath.c_str()); -#else - status = mkdir(dirPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); -#endif - return status==0; -} - -bool UDirectory::removeDir(const std::string & dirPath) -{ - int status; -#if WIN32 - status = _rmdir(dirPath.c_str()); -#else - status = rmdir(dirPath.c_str()); -#endif - return status==0; -} - -std::string UDirectory::homeDir() -{ - std::string path; -#if WIN32 - #ifdef UNICODE - wchar_t wProfilePath[250]; - ExpandEnvironmentStrings(L"%userprofile%",wProfilePath,250); - char * profilePath = createCharFromWChar(wProfilePath); - path = profilePath; - delete [] profilePath; - #else - char profilePath[250]; - ExpandEnvironmentStrings("%userprofile%",profilePath,250); - path = profilePath; - #endif -#else - path = getenv("HOME"); -#endif - return path; -} - -std::string UDirectory::separator() -{ -#ifdef WIN32 - return "\\"; -#else - return "/"; -#endif -} diff --git a/find-object/src/utilite/UDirectory.h b/find-object/src/utilite/UDirectory.h deleted file mode 100644 index 0711cdd6..00000000 --- a/find-object/src/utilite/UDirectory.h +++ /dev/null @@ -1,139 +0,0 @@ -// Taken from UtiLite library r185 [www.utilite.googlecode.com] - -/* -* utilite is a cross-platform library with -* useful utilities for fast and small developing. -* Copyright (C) 2010 Mathieu Labbe -* -* utilite is free library: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* utilite is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this program. If not, see . -*/ - -#ifndef UDIRECTORY_H -#define UDIRECTORY_H - -//#include "utilite/UtiLiteExp.h" // DLL export/import defines - -#include -#include -#include - -/** - * Class UDirectory. - * - * This class can be used to get file names in a directory. - */ -class UDirectory -{ -public: - /** - * Check if a directory exists. - * @param dirPath the directory path - * @return true if the directory exists - */ - static bool exists(const std::string & dirPath); - - /** - * Get the directory path of a file path. - * @param filePath the file path - * @return the directory path of the file - */ - static std::string getDir(const std::string & filePath); - - /** - * Get the current directory. - * @param trailingSeparator If true, a '/' is added to the path. - * @return the current directory - */ - static std::string currentDir(bool trailingSeparator = false); - - /** - * Make a directory. - * @param dirPath the directory path - * @return true on success, false otherwise. - */ - static bool makeDir(const std::string & dirPath); - - /** - * Remove a directory. - * @param dirPath the directory path - * @return true on success, false otherwise. - */ - static bool removeDir(const std::string & dirPath); - - /** - * Return the "home" directory. - * @return the directory path. - */ - static std::string homeDir(); - - /** - * Return \ (Win32) or / (Unix) depending of the platform. - */ - static std::string separator(); - -public: - /** - * Create a UDirectory object with path initialized to an existing "path" and with filter "extensions". - * @param path the path to an existing directory - * @param extensions filter to get only file names with the extensions specified, format is a - * list of extensions separated by a space: "jpg bmp" get only file names finishing by jpg or bmp. - */ - UDirectory(const std::string & path = "", const std::string & extensions = ""); - UDirectory(const UDirectory & dir); - UDirectory & operator=(const UDirectory & dir); - ~UDirectory(); - - /** - * Set path of the directory. - * @param path the new directory path. - */ - void setPath(const std::string & path, const std::string & extensions = ""); - - /** - * Update indexed file names (if the directory changed). - */ - void update(); - - /** - * Check is the directory exists. - * @return if directory exists. - */ - bool isValid(); - - /** - * Get the next file name. - * @return the next file name - */ - std::string getNextFileName(); - - /** - * Get all file names. - * @see UDirectory() - * @return all the file names in directory matching the set extensions. - */ - const std::list & getFileNames() const {return fileNames_;} - - /** - * Return the pointer of file names to beginning. - */ - void rewind(); - -private: - std::string path_; - std::vector extensions_; - std::list fileNames_; - std::list::iterator iFileName_; -}; - -#endif /* UDIRECTORY_H */ diff --git a/find-object/src/utilite/UFile.cpp b/find-object/src/utilite/UFile.cpp deleted file mode 100644 index 0de771ba..00000000 --- a/find-object/src/utilite/UFile.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// Taken from UtiLite library r185 [www.utilite.googlecode.com] - -/* -* utilite is a cross-platform library with -* useful utilities for fast and small developing. -* Copyright (C) 2010 Mathieu Labbe -* -* utilite is free library: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* utilite is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this program. If not, see . -*/ - -#include "utilite/UFile.h" - -#include -#include "utilite/UStl.h" - -bool UFile::exists(const std::string &filePath) -{ - bool fileExists = false; - std::ifstream in(filePath.c_str(), std::ios::in); - if (in.is_open()) - { - fileExists = true; - in.close(); - } - return fileExists; -} - -long UFile::length(const std::string &filePath) -{ - long fileSize = 0; - FILE* fp = 0; -#ifdef _MSC_VER - fopen_s(&fp, filePath.c_str(), "rb"); -#else - fp = fopen(filePath.c_str(), "rb"); -#endif - if(fp == NULL) - { - return 0; - } - - fseek(fp , 0 , SEEK_END); - fileSize = ftell(fp); - fclose(fp); - - return fileSize; -} - -int UFile::erase(const std::string &filePath) -{ - return remove(filePath.c_str()); -} - -int UFile::rename(const std::string &oldFilePath, - const std::string &newFilePath) -{ - return ::rename(oldFilePath.c_str(), newFilePath.c_str()); -} - -std::string UFile::getName(const std::string & filePath) -{ - std::string fullPath = filePath; - std::string name; - for(int i=(int)fullPath.size()-1; i>=0; --i) - { - if(fullPath[i] == '/' || fullPath[i] == '\\') - { - break; - } - else - { - name.insert(name.begin(), fullPath[i]); - } - } - return name; -} - -std::string UFile::getExtension(const std::string &filePath) -{ - std::list list = uSplit(filePath, '.'); - if(list.size()) - { - return list.back(); - } - return ""; -} diff --git a/find-object/src/utilite/UFile.h b/find-object/src/utilite/UFile.h deleted file mode 100644 index 9ed8f7ec..00000000 --- a/find-object/src/utilite/UFile.h +++ /dev/null @@ -1,137 +0,0 @@ -// Taken from UtiLite library r185 [www.utilite.googlecode.com] - -/* -* utilite is a cross-platform library with -* useful utilities for fast and small developing. -* Copyright (C) 2010 Mathieu Labbe -* -* utilite is free library: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* utilite is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this program. If not, see . -*/ - -#ifndef FILE_H -#define FILE_H - -//#include "utilite/UtiLiteExp.h" // DLL export/import defines - -#include "utilite/UDirectory.h" -#include - -/** - * Class UFile. - * - * This class can be used to modify/erase files on hard drive. - */ -class UFile -{ -public: - /** - * Check if a file exists. - * @param filePath the file path - * @return true if the file exists, otherwise false. - */ - static bool exists(const std::string &filePath); - - /** - * Get the file length. - * @param filePath the file path - * @return long the length of the file in bytes. Return -1 if the file doesn't exist. - */ - static long length(const std::string &filePath); - - /** - * Erase a file. - * @param filePath the file path - * @return 0 if success. - */ - static int erase(const std::string &filePath); - - /** - * Rename a file. - * @param oldFilePath the old file path - * @param newFilePath the new file path - * @return 0 if success. - */ - static int rename(const std::string &oldFilePath, - const std::string &newFilePath); - - /** - * Get the file name from a file path (with extension). - * @param filePath the file path - * @return the file name. - */ - static std::string getName(const std::string & filePath); - - static std::string getExtension(const std::string &filePath); - -public: - /** - * Create a UFile object with path initialized to an existing file . - * @param path the path to an existing file - */ - UFile(const std::string & path) : path_(path) {} - ~UFile() {} - - /** - * Check if the file exists. Same as exists(). - * @return true if the path exits - */ - bool isValid() {return exists(path_);} - - /** - * Check if the file exists. - * @return true if the path exits - */ - bool exists() {return exists(path_);} - - /** - * Get the length of the file. - * @return long the length of the file in bytes. Return -1 if the file doesn't exist. - */ - long length() {return length(path_);} - - /** - * Rename the file name. The path stays the same. - * @param the new name - */ - int rename(const std::string &newName) - { - std::string ext = this->getExtension(); - std::string newPath = UDirectory::getDir(path_) + std::string("/") + newName; - if(ext.size()) - { - newPath += std::string(".") + getExtension(path_); - } - int result = rename(path_, newPath); - if(result == 0) - { - path_ = newPath; - } - return result; - } - /** - * Get the file name without the path. - * @return the file name - */ - std::string getName() {return getName(path_);} - /** - * Get the file extension. - * @return the file extension - */ - std::string getExtension() {return getExtension(path_);} - -private: - std::string path_; -}; - -#endif diff --git a/find-object/src/utilite/ULogger.cpp b/find-object/src/utilite/ULogger.cpp deleted file mode 100644 index 984e47c4..00000000 --- a/find-object/src/utilite/ULogger.cpp +++ /dev/null @@ -1,591 +0,0 @@ -/* -* utilite is a cross-platform library with -* useful utilities for fast and small developing. -* Copyright (C) 2010 Mathieu Labbe -* -* utilite is free library: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* utilite is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this program. If not, see . -*/ - -#include "find_object/utilite/ULogger.h" - -#include "utilite/UConversion.h" -#include "utilite/UFile.h" -#include "utilite/UStl.h" -#include -#include -#include - -#ifndef WIN32 -#include -#endif - -#ifdef WIN32 -#include -#define COLOR_NORMAL FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED -#define COLOR_RED FOREGROUND_RED | FOREGROUND_INTENSITY -#define COLOR_GREEN FOREGROUND_GREEN -#define COLOR_YELLOW FOREGROUND_GREEN | FOREGROUND_RED -#else -#define COLOR_NORMAL "\033[0m" -#define COLOR_RED "\033[31m" -#define COLOR_GREEN "\033[32m" -#define COLOR_YELLOW "\033[33m" -#endif - -bool ULogger::append_ = true; -bool ULogger::printTime_ = true; -bool ULogger::printLevel_ = true; -bool ULogger::printEndline_ = true; -bool ULogger::printColored_ = true; -bool ULogger::printWhere_ = true; -bool ULogger::printWhereFullPath_ = false; -bool ULogger::limitWhereLength_ = false; -bool ULogger::buffered_ = false; -bool ULogger::exitingState_ = false; -ULogger::Level ULogger::level_ = kWarning; -ULogger::Level ULogger::exitLevel_ = kFatal; -ULogger::Level ULogger::eventLevel_ = kFatal; -const char * ULogger::levelName_[5] = {"DEBUG", " INFO", " WARN", "ERROR", "FATAL"}; -ULogger* ULogger::instance_ = 0; -UDestroyer ULogger::destroyer_; -ULogger::Type ULogger::type_ = ULogger::kTypeConsole; -UMutex ULogger::loggerMutex_; -const std::string ULogger::kDefaultLogFileName = "./ULog.txt"; -std::string ULogger::logFileName_; -std::string ULogger::bufferedMsgs_; - -/** - * This class is used to write logs in the console. This class cannot - * be directly used, use ULogger::setType() to console type to print in - * console and use macro UDEBUG(), UINFO()... to print messages. - * @see ULogger - */ -class UConsoleLogger : public ULogger -{ -public : - virtual ~UConsoleLogger() {this->_flush();} - -protected: - /** - * Only the Logger can create inherited - * loggers according to the Abstract factory patterns. - */ - friend class ULogger; - - UConsoleLogger() {} - -private: - virtual void _write(const char* msg, va_list arg) - { - vprintf(msg, arg); - } - virtual void _writeStr(const char* msg) - { - printf("%s", msg); - } -}; - -/** - * This class is used to write logs in a file. This class cannot - * be directly used, use ULogger::setType() to file type to print in - * a file and use macro UDEBUG(), UINFO()... to print messages. - * @see ULogger - */ -class UFileLogger : public ULogger -{ -public: - virtual ~UFileLogger() - { - this->_flush(); - if(fout_) - { - fclose(fout_); - } - } - -protected: - /** - * Only the Logger can create inherited - * loggers according to the Abstract factory patterns. - */ - friend class ULogger; - - /** - * The UFileLogger constructor. - * @param fileName the file name - * @param append if true append logs in the file, - * ortherwise it overrides the file. - * - */ - UFileLogger(const std::string &fileName, bool append) - { - fileName_ = fileName; - - if(!append) { - std::ofstream fileToClear(fileName_.c_str(), std::ios::out); - fileToClear.clear(); - fileToClear.close(); - } - -#ifdef _MSC_VER - fopen_s(&fout_, fileName_.c_str(), "a"); -#else - fout_ = fopen(fileName_.c_str(), "a"); -#endif - - if(!fout_) { - printf("FileLogger : Cannot open file : %s\n", fileName_.c_str()); // TODO send Event instead, or return error code - return; - } - } - -private: - virtual void _write(const char* msg, va_list arg) - { - if(fout_) - { - vfprintf(fout_, msg, arg); - } - } - virtual void _writeStr(const char* msg) - { - if(fout_) - { - fprintf(fout_, "%s", msg); - } - } - -private: - std::string fileName_; ///< the file name - FILE* fout_; - std::string bufferedMsgs_; -}; - -void ULogger::setType(Type type, const std::string &fileName, bool append) -{ - ULogger::flush(); - loggerMutex_.lock(); - { - // instance not yet created - if(!instance_) - { - type_ = type; - logFileName_ = fileName; - append_ = append; - instance_ = createInstance(); - } - // type changed - else if(type_ != type || (type_ == kTypeFile && logFileName_.compare(fileName)!=0)) - { - destroyer_.setDoomed(0); - delete instance_; - instance_ = 0; - type_ = type; - logFileName_ = fileName; - append_ = append; - instance_ = createInstance(); - } - } - loggerMutex_.unlock(); -} - -void ULogger::reset() -{ - ULogger::setType(ULogger::kTypeNoLog); - append_ = true; - printTime_ = true; - printLevel_ = true; - printEndline_ = true; - printColored_ = true; - printWhere_ = true; - printWhereFullPath_ = false; - limitWhereLength_ = false; - level_ = kInfo; // By default, we show all info msgs + upper level (Warning, Error) - logFileName_ = ULogger::kDefaultLogFileName; -} - -void ULogger::setBuffered(bool buffered) -{ - if(!buffered) - { - ULogger::flush(); - } - buffered_ = buffered; -} - - -void ULogger::flush() -{ - loggerMutex_.lock(); - if(!instance_ || bufferedMsgs_.size()==0) - { - loggerMutex_.unlock(); - return; - } - - instance_->_flush(); - loggerMutex_.unlock(); -} - -void ULogger::_flush() -{ - ULogger::getInstance()->_writeStr(bufferedMsgs_.c_str()); - bufferedMsgs_.clear(); -} - -void ULogger::write(const char* msg, ...) -{ - loggerMutex_.lock(); - if(!instance_) - { - loggerMutex_.unlock(); - return; - } - - std::string endline = ""; - if(printEndline_) { - endline = "\r\n"; - } - - std::string time = ""; - if(printTime_) - { - getTime(time); - time.append(" - "); - } - - - if(printTime_) - { - if(buffered_) - { - bufferedMsgs_.append(time.c_str()); - } - else - { - ULogger::getInstance()->_writeStr(time.c_str()); - } - } - - va_list args; - va_start(args, msg); - if(buffered_) - { - bufferedMsgs_.append(uFormatv(msg, args)); - } - else - { - ULogger::getInstance()->_write(msg, args); - } - va_end(args); - if(printEndline_) - { - if(buffered_) - { - bufferedMsgs_.append(endline.c_str()); - } - else - { - ULogger::getInstance()->_writeStr(endline.c_str()); - } - } - loggerMutex_.unlock(); - -} - -void ULogger::write(ULogger::Level level, - const char * file, - int line, - const char * function, - const char* msg, - ...) -{ - if(exitingState_) - { - // Ignore messages after a fatal exit... - return; - } - loggerMutex_.lock(); - if(type_ == kTypeNoLog && level < kFatal) - { - loggerMutex_.unlock(); - return; - } - if(strlen(msg) == 0 && !printWhere_ && level < exitLevel_) - { - loggerMutex_.unlock(); - // No need to show an empty message if we don't print where. - return; - } - - if(level >= level_) - { -#ifdef WIN32 - int color = 0; -#else - const char* color = NULL; -#endif - switch(level) - { - case kDebug: - color = COLOR_GREEN; - break; - case kInfo: - color = COLOR_NORMAL; - break; - case kWarning: - color = COLOR_YELLOW; - break; - case kError: - case kFatal: - color = COLOR_RED; - break; - default: - break; - } - - std::string endline = ""; - if(printEndline_) { - endline = "\r\n"; - } - - std::string time = ""; - if(printTime_) - { - time.append("("); - getTime(time); - time.append(") "); - } - - std::string levelStr = ""; - if(printLevel_) - { - const int bufSize = 30; - char buf[bufSize] = {0}; - -#ifdef _MSC_VER - sprintf_s(buf, bufSize, "[%s]", levelName_[level]); -#else - snprintf(buf, bufSize, "[%s]", levelName_[level]); -#endif - levelStr = buf; - levelStr.append(" "); - } - - std::string whereStr = ""; - if(printWhere_) - { - whereStr.append(""); - //File - if(printWhereFullPath_) - { - whereStr.append(file); - } - else - { - std::string fileName = UFile::getName(file); - if(limitWhereLength_ && fileName.size() > 8) - { - fileName.erase(8); - fileName.append("~"); - } - whereStr.append(fileName); - } - - //Line - whereStr.append(":"); - std::string lineStr = uNumber2Str(line); - whereStr.append(lineStr); - - //Function - whereStr.append("::"); - std::string funcStr = function; - if(!printWhereFullPath_ && limitWhereLength_ && funcStr.size() > 8) - { - funcStr.erase(8); - funcStr.append("~"); - } - funcStr.append("()"); - whereStr.append(funcStr); - - whereStr.append(" "); - } - - va_list args; - - if(type_ != kTypeNoLog) - { - va_start(args, msg); -#ifdef WIN32 - HANDLE H = GetStdHandle(STD_OUTPUT_HANDLE); -#endif - if(type_ == ULogger::kTypeConsole && printColored_) - { -#ifdef WIN32 - SetConsoleTextAttribute(H,color); -#else - if(buffered_) - { - bufferedMsgs_.append(color); - } - else - { - ULogger::getInstance()->_writeStr(color); - } -#endif - } - - if(buffered_) - { - bufferedMsgs_.append(levelStr.c_str()); - bufferedMsgs_.append(time.c_str()); - bufferedMsgs_.append(whereStr.c_str()); - bufferedMsgs_.append(uFormatv(msg, args)); - } - else - { - ULogger::getInstance()->_writeStr(levelStr.c_str()); - ULogger::getInstance()->_writeStr(time.c_str()); - ULogger::getInstance()->_writeStr(whereStr.c_str()); - ULogger::getInstance()->_write(msg, args); - } - if(type_ == ULogger::kTypeConsole && printColored_) - { -#ifdef WIN32 - SetConsoleTextAttribute(H,COLOR_NORMAL); -#else - if(buffered_) - { - bufferedMsgs_.append(COLOR_NORMAL); - } - else - { - ULogger::getInstance()->_writeStr(COLOR_NORMAL); - } -#endif - } - if(buffered_) - { - bufferedMsgs_.append(endline.c_str()); - } - else - { - ULogger::getInstance()->_writeStr(endline.c_str()); - } - va_end (args); - } - - if(level >= exitLevel_) - { - printf("\n*******\n%s message occurred! Application will now exit.\n", levelName_[level]); - if(type_ != kTypeConsole) - { - printf(" %s%s%s\n", levelStr.c_str(), time.c_str(), whereStr.c_str()); - va_start(args, msg); - vprintf(msg, args); - va_end(args); - } - printf("*******\n"); - destroyer_.setDoomed(0); - delete instance_; // If a FileLogger is used, this will close the file. - instance_ = 0; - //======================================================================== - // EXIT APPLICATION - exit(1); - //======================================================================== - } - } - loggerMutex_.unlock(); -} - -int ULogger::getTime(std::string &timeStr) -{ - if(!printTime_) { - return 0; - } - struct tm timeinfo; - const int bufSize = 30; - char buf[bufSize] = {0}; - -#if _MSC_VER - time_t rawtime; - time(&rawtime); - localtime_s (&timeinfo, &rawtime ); - int result = sprintf_s(buf, bufSize, "%d-%s%d-%s%d %s%d:%s%d:%s%d", - timeinfo.tm_year+1900, - (timeinfo.tm_mon+1) < 10 ? "0":"", timeinfo.tm_mon+1, - (timeinfo.tm_mday) < 10 ? "0":"", timeinfo.tm_mday, - (timeinfo.tm_hour) < 10 ? "0":"", timeinfo.tm_hour, - (timeinfo.tm_min) < 10 ? "0":"", timeinfo.tm_min, - (timeinfo.tm_sec) < 10 ? "0":"", timeinfo.tm_sec); -#elif WIN32 - time_t rawtime; - time(&rawtime); - timeinfo = *localtime (&rawtime); - int result = snprintf(buf, bufSize, "%d-%s%d-%s%d %s%d:%s%d:%s%d", - timeinfo.tm_year+1900, - (timeinfo.tm_mon+1) < 10 ? "0":"", timeinfo.tm_mon+1, - (timeinfo.tm_mday) < 10 ? "0":"", timeinfo.tm_mday, - (timeinfo.tm_hour) < 10 ? "0":"", timeinfo.tm_hour, - (timeinfo.tm_min) < 10 ? "0":"", timeinfo.tm_min, - (timeinfo.tm_sec) < 10 ? "0":"", timeinfo.tm_sec); - #else - struct timeval rawtime; - gettimeofday(&rawtime, NULL); - localtime_r (&rawtime.tv_sec, &timeinfo); - int result = snprintf(buf, bufSize, "%d-%s%d-%s%d %s%d:%s%d:%s%d.%s%d", - timeinfo.tm_year+1900, - (timeinfo.tm_mon+1) < 10 ? "0":"", timeinfo.tm_mon+1, - (timeinfo.tm_mday) < 10 ? "0":"", timeinfo.tm_mday, - (timeinfo.tm_hour) < 10 ? "0":"", timeinfo.tm_hour, - (timeinfo.tm_min) < 10 ? "0":"", timeinfo.tm_min, - (timeinfo.tm_sec) < 10 ? "0":"", timeinfo.tm_sec, - (rawtime.tv_usec/1000) < 10 ? "00":(rawtime.tv_usec/1000) < 100?"0":"", int(rawtime.tv_usec/1000)); -#endif - if(result) - { - timeStr.append(buf); - } - return result; -} - -ULogger* ULogger::getInstance() -{ - if(!instance_) - { - instance_ = createInstance(); - } - return instance_; -} - -ULogger* ULogger::createInstance() -{ - ULogger* instance = 0; - if(type_ == ULogger::kTypeConsole) - { - instance = new UConsoleLogger(); - } - else if(type_ == ULogger::kTypeFile) - { - instance = new UFileLogger(logFileName_, append_); - } - destroyer_.setDoomed(instance); - return instance; -} - -ULogger::~ULogger() -{ - instance_ = 0; - //printf("Logger is destroyed...\n\r"); -} diff --git a/find-object/src/utilite/UPlot.cpp b/find-object/src/utilite/UPlot.cpp deleted file mode 100644 index 32f78567..00000000 --- a/find-object/src/utilite/UPlot.cpp +++ /dev/null @@ -1,2562 +0,0 @@ -// Taken from UtiLite library r186 [www.utilite.googlecode.com] - -/* -* utilite is a cross-platform library with -* useful utilities for fast and small developing. -* Copyright (C) 2010 Mathieu Labbe -* -* utilite is free library: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* utilite is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this program. If not, see . -*/ - -#include "utilite/UPlot.h" -//#include "utilite/ULogger.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef QT_SVG_LIB -#include -#endif -#include - -#define PRINT_DEBUG 0 -#define ULOGGER_ERROR(A, ...) -#define ULOGGER_WARN(A, ...) - -UPlotItem::UPlotItem(qreal dataX, qreal dataY, qreal width) : - QGraphicsEllipseItem(0, 0, width, width, 0), - _previousItem(0), - _nextItem(0) -{ - _data.setX(dataX); - _data.setY(dataY); - this->setZValue(1); - this->setAcceptHoverEvents(true); - _text = new QGraphicsTextItem(this); - _text->setPlainText(QString("(%1,%2)").arg(_data.x()).arg(_data.y())); - _text->setVisible(false); - this->setFlag(QGraphicsItem::ItemIsFocusable, true); -} - -UPlotItem::UPlotItem(const QPointF & data, qreal width) : - QGraphicsEllipseItem(0, 0, width, width, 0), - _data(data), - _previousItem(0), - _nextItem(0) -{ - this->setZValue(1); - this->setAcceptHoverEvents(true); - _text = new QGraphicsTextItem(this); - _text->setPlainText(QString("(%1,%2)").arg(_data.x()).arg(_data.y())); - _text->setVisible(false); - this->setFlag(QGraphicsItem::ItemIsFocusable, true); -} - -UPlotItem::~UPlotItem() -{ - if(_previousItem && _nextItem) - { - _previousItem->setNextItem(_nextItem); - _nextItem->setPreviousItem(_previousItem); - } - else if(_previousItem) - { - _previousItem->setNextItem(0); - } - else if(_nextItem) - { - _nextItem->setPreviousItem(0); - } -} - -void UPlotItem::setData(const QPointF & data) -{ - _data = data; -} - -void UPlotItem::setNextItem(UPlotItem * nextItem) -{ - if(_nextItem != nextItem) - { - _nextItem = nextItem; - if(nextItem) - { - nextItem->setPreviousItem(this); - } - } -} - -void UPlotItem::setPreviousItem(UPlotItem * previousItem) -{ - if(_previousItem != previousItem) - { - _previousItem = previousItem; - if(previousItem) - { - previousItem->setNextItem(this); - } - } -} - -void UPlotItem::showDescription(bool shown) -{ - _text->setPlainText(QString("(%1,%2)").arg(_data.x()).arg(_data.y())); - if(shown) - { - this->setPen(QPen(Qt::black, 2)); - if(this->scene()) - { - QRectF rect = this->scene()->sceneRect(); - QPointF p = this->pos(); - QRectF br = _text->boundingRect(); - - // Make sure the text is always in the scene - if(p.x() - br.width() < 0) - { - p.setX(0); - } - else if(p.x() + br.width() > rect.width()) - { - p.setX(rect.width() - br.width()); - } - else - { - p.setX(p.x() - br.width()); - } - - if(p.y() - br.height() < 0) - { - p.setY(0); - } - else - { - p.setY(p.y() - br.height()); - } - - _text->setPos(this->mapFromScene(p)); - } - - _text->setVisible(true); - } - else - { - this->setPen(QPen(Qt::black, 1)); - _text->setVisible(false); - } -} - -void UPlotItem::hoverEnterEvent(QGraphicsSceneHoverEvent * event) -{ - QGraphicsScene * scene = this->scene(); - if(scene && scene->focusItem() == 0) - { - this->showDescription(true); - } - else - { - this->setPen(QPen(Qt::black, 2)); - } - QGraphicsEllipseItem::hoverEnterEvent(event); -} - -void UPlotItem::hoverLeaveEvent(QGraphicsSceneHoverEvent * event) -{ - if(!this->hasFocus()) - { - this->showDescription(false); - } - QGraphicsEllipseItem::hoverEnterEvent(event); -} - -void UPlotItem::focusInEvent(QFocusEvent * event) -{ - this->showDescription(true); - QGraphicsEllipseItem::focusInEvent(event); -} - -void UPlotItem::focusOutEvent(QFocusEvent * event) -{ - this->showDescription(false); - QGraphicsEllipseItem::focusOutEvent(event); -} - -void UPlotItem::keyReleaseEvent(QKeyEvent * keyEvent) -{ - //Get the next/previous visible item - if(keyEvent->key() == Qt::Key_Right) - { - UPlotItem * next = _nextItem; - while(next && !next->isVisible()) - { - next = next->nextItem(); - } - if(next && next->isVisible()) - { - this->clearFocus(); - next->setFocus(); - } - } - else if(keyEvent->key() == Qt::Key_Left) - { - UPlotItem * previous = _previousItem; - while(previous && !previous->isVisible()) - { - previous = previous->previousItem(); - } - if(previous && previous->isVisible()) - { - this->clearFocus(); - previous->setFocus(); - } - } - QGraphicsEllipseItem::keyReleaseEvent(keyEvent); -} - - - - - -UPlotCurve::UPlotCurve(const QString & name, QObject * parent) : - QObject(parent), - _plot(0), - _name(name), - _xIncrement(1), - _xStart(0), - _visible(true), - _valuesShown(false) -{ -} - -UPlotCurve::UPlotCurve(const QString & name, QVector data, QObject * parent) : - QObject(parent), - _plot(0), - _name(name), - _xIncrement(1), - _xStart(0), - _visible(true), - _valuesShown(false) -{ - this->setData(data); -} - -UPlotCurve::UPlotCurve(const QString & name, const QVector & x, const QVector & y, QObject * parent) : - QObject(parent), - _plot(0), - _name(name), - _xIncrement(1), - _xStart(0), - _visible(true), - _valuesShown(false) -{ - this->setData(x, y); -} - -UPlotCurve::~UPlotCurve() -{ - if(_plot) - { - _plot->removeCurve(this); - } -#if PRINT_DEBUG - ULOGGER_DEBUG("%s", this->name().toStdString().c_str()); -#endif - this->clear(); -} - -void UPlotCurve::attach(UPlot * plot) -{ - if(!plot || plot == _plot) - { - return; - } - if(_plot) - { - _plot->removeCurve(this); - } - _plot = plot; - for(int i=0; i<_items.size(); ++i) - { - _plot->addItem(_items.at(i)); - } -} - -void UPlotCurve::detach(UPlot * plot) -{ -#if PRINT_DEBUG - ULOGGER_DEBUG("curve=\"%s\" from plot=\"%s\"", this->objectName().toStdString().c_str(), plot?plot->objectName().toStdString().c_str():""); -#endif - if(plot && _plot == plot) - { - _plot = 0; - for(int i=0; i<_items.size(); ++i) - { - if(_items.at(i)->scene()) - { - _items.at(i)->scene()->removeItem(_items.at(i)); - } - } - } -} - -void UPlotCurve::updateMinMax() -{ - float x,y; - const UPlotItem * item; - if(!_items.size()) - { - _minMax = QVector(); - } - else - { - _minMax = QVector(4); - } - for(int i=0; i<_items.size(); ++i) - { - item = qgraphicsitem_cast(_items.at(i)); - if(item) - { - x = item->data().x(); - y = item->data().y(); - if(i==0) - { - _minMax[0] = x; - _minMax[1] = x; - _minMax[2] = y; - _minMax[3] = y; - } - else - { - if(x<_minMax[0]) _minMax[0] = x; - if(x>_minMax[1]) _minMax[1] = x; - if(y<_minMax[2]) _minMax[2] = y; - if(y>_minMax[3]) _minMax[3] = y; - } - } - } -} - -void UPlotCurve::_addValue(UPlotItem * data) -{ - // add item - if(data) - { - float x = data->data().x(); - float y = data->data().y(); - if(_minMax.size() != 4) - { - _minMax = QVector(4); - } - if(_items.size()) - { - data->setPreviousItem((UPlotItem *)_items.last()); - - QGraphicsLineItem * line = new QGraphicsLineItem(); - line->setPen(_pen); - line->setVisible(false); - _items.append(line); - if(_plot) - { - _plot->addItem(line); - } - - //Update min/max - if(x<_minMax[0]) _minMax[0] = x; - if(x>_minMax[1]) _minMax[1] = x; - if(y<_minMax[2]) _minMax[2] = y; - if(y>_minMax[3]) _minMax[3] = y; - } - else - { - _minMax[0] = x; - _minMax[1] = x; - _minMax[2] = y; - _minMax[3] = y; - } - _items.append(data); - data->setVisible(false); - //data->showDescription(_valuesShown); - if(_plot) - { - _plot->addItem(_items.last()); - } - } - else - { - ULOGGER_ERROR("Data is null ?!?"); - } -} - -void UPlotCurve::addValue(UPlotItem * data) -{ - // add item - if(data) - { - this->_addValue(data); - Q_EMIT dataChanged(this); - } -} - -void UPlotCurve::addValue(float x, float y) -{ - float width = 2; // TODO warn : hard coded value! - this->addValue(new UPlotItem(x,y,width)); -} - -void UPlotCurve::addValue(float y) -{ - float x = 0; - if(_items.size()) - { - UPlotItem * lastItem = (UPlotItem *)_items.last(); - x = lastItem->data().x() + _xIncrement; - } - else - { - x = _xStart; - } - this->addValue(x,y); -} - -void UPlotCurve::addValue(const QString & value) -{ - bool ok; - float v = value.toFloat(&ok); - if(ok) - { - this->addValue(v); - } - else - { - ULOGGER_ERROR("Value not valid, must be a number, received %s", value.toStdString().c_str()); - } -} - -void UPlotCurve::addValues(QVector & data) -{ - for(int i=0; i_addValue(data.at(i)); - } - Q_EMIT dataChanged(this); -} - -void UPlotCurve::addValues(const QVector & xs, const QVector & ys) -{ - float width = 2; // TODO warn : hard coded value! - for(int i=0; i_addValue(new UPlotItem(xs.at(i),ys.at(i),width)); - } - Q_EMIT dataChanged(this); -} - -void UPlotCurve::addValues(const QVector & ys) -{ - float x = 0; - float width = 2; // TODO warn : hard coded value! - for(int i=0; idata().x() + _xIncrement; - } - else - { - x = _xStart; - } - this->_addValue(new UPlotItem(x,ys.at(i),width)); - } - Q_EMIT dataChanged(this); -} - -void UPlotCurve::addValues(const QVector & ys) -{ - float x = 0; - float width = 2; // TODO warn : hard coded value! - for(int i=0; idata().x() + _xIncrement; - } - else - { - x = _xStart; - } - this->_addValue(new UPlotItem(x,ys.at(i),width)); - } - Q_EMIT dataChanged(this); -} - -void UPlotCurve::addValues(const std::vector & ys) -{ - float x = 0; - float width = 2; // TODO warn : hard coded value! - for(unsigned int i=0; idata().x() + _xIncrement; - } - else - { - x = _xStart; - } - this->_addValue(new UPlotItem(x,ys.at(i),width)); - } - Q_EMIT dataChanged(this); -} - -void UPlotCurve::addValues(const std::vector & ys) -{ - float x = 0; - float width = 2; // TODO warn : hard coded value! - for(unsigned int i=0; idata().x() + _xIncrement; - } - else - { - x = _xStart; - } - this->_addValue(new UPlotItem(x,ys.at(i),width)); - } - Q_EMIT dataChanged(this); -} - -int UPlotCurve::removeItem(int index) -{ - if(index >= 0 && index < _items.size()) - { - if(index!=0) - { - index-=1; - delete _items.takeAt(index); // the line - } - else if(_items.size()>1) - { - delete _items.takeAt(index+1); // the line - } - UPlotItem * item = (UPlotItem *)_items.takeAt(index); // the plot item - //Update min/max - if(_minMax.size() == 4) - { - if(item->data().x() == _minMax[0] || item->data().x() == _minMax[1] || - item->data().y() == _minMax[2] || item->data().y() == _minMax[3]) - { - if(_items.size()) - { - UPlotItem * tmp = (UPlotItem *)_items.at(0); - float x = tmp->data().x(); - float y = tmp->data().y(); - _minMax[0]=x; - _minMax[1]=x; - _minMax[2]=y; - _minMax[3]=y; - for(int i = 2; i<_items.size(); i+=2) - { - tmp = (UPlotItem*)_items.at(i); - x = tmp->data().x(); - y = tmp->data().y(); - if(x<_minMax[0]) _minMax[0] = x; - if(x>_minMax[1]) _minMax[1] = x; - if(y<_minMax[2]) _minMax[2] = y; - if(y>_minMax[3]) _minMax[3] = y; - } - } - else - { - _minMax = QVector(); - } - } - } - delete item; - } - - return index; -} - -void UPlotCurve::removeItem(UPlotItem * item) // ownership is transfered to the caller -{ - for(int i=0; i<_items.size(); ++i) - { - if(_items.at(i) == item) - { - if(i!=0) - { - i-=1; - delete _items[i]; - _items.removeAt(i); - } - else if(_items.size()>1) - { - delete _items[i+1]; - _items.removeAt(i+1); - } - item->scene()->removeItem(item); - _items.removeAt(i); - break; - } - } -} - -void UPlotCurve::clear() -{ -#if PRINT_DEBUG - ULOGGER_DEBUG("%s", this->name().toStdString().c_str()); -#endif - qDeleteAll(_items); - _items.clear(); -} - -void UPlotCurve::setPen(const QPen & pen) -{ - _pen = pen; - for(int i=1; i<_items.size(); i+=2) - { - ((QGraphicsLineItem*) _items.at(i))->setPen(_pen); - } -} - -void UPlotCurve::setBrush(const QBrush & brush) -{ - _brush = brush; - ULOGGER_WARN("Not used..."); -} - -void UPlotCurve::update(float scaleX, float scaleY, float offsetX, float offsetY, float xDir, float yDir, bool allDataKept) -{ - //ULOGGER_DEBUG("scaleX=%f, scaleY=%f, offsetX=%f, offsetY=%f, xDir=%d, yDir=%d, _plot->scene()->width()=%f, _plot->scene()->height=%f", scaleX, scaleY, offsetX, offsetY, xDir, yDir,_plot->scene()->width(),_plot->scene()->height()); - //make sure direction values are 1 or -1 - xDir<0?xDir=-1:xDir=1; - yDir<0?yDir=-1:yDir=1; - - bool hide = false; - for(int i=_items.size()-1; i>=0; --i) - { - if(i%2 == 0) - { - UPlotItem * item = (UPlotItem *)_items.at(i); - if(hide) - { - if(allDataKept) - { - // if not visible, stop looping... all other items are normally already hided - if(!item->isVisible()) - { - break; - } - item->setVisible(false); - } - else - { - //remove the item with his line - i = this->removeItem(i); - } - } - else - { - QPointF newPos(((xDir*item->data().x()+offsetX)*scaleX-item->rect().width()/2.0f), - ((yDir*item->data().y()+offsetY)*scaleY-item->rect().width()/2.0f)); - if(!item->isVisible()) - { - item->setVisible(true); - } - item->setPos(newPos); - } - } - else - { - if(hide) - { - _items.at(i)->setVisible(false); - } - else - { - UPlotItem * from = (UPlotItem *)_items.at(i-1); - UPlotItem * to = (UPlotItem *)_items.at(i+1); - QGraphicsLineItem * lineItem = (QGraphicsLineItem *)_items.at(i); - lineItem->setLine((xDir*from->data().x()+offsetX)*scaleX, - (yDir*from->data().y()+offsetY)*scaleY, - (xDir*to->data().x()+offsetX)*scaleX, - (yDir*to->data().y()+offsetY)*scaleY); - if(!lineItem->isVisible()) - { - lineItem->setVisible(true); - } - //Don't update not visible items - // (Detect also if the curve goes forward or backward) - QLineF line = lineItem->line(); - if((line.x1() <= line.x2() && line.x2() < 0-((line.x2() - line.x1()))) || - (line.x1() > line.x2() && line.x2() > lineItem->scene()->sceneRect().width() + ((line.x1() - line.x2())))) - { - hide = true; - } - - } - } - } - -} - -void UPlotCurve::draw(QPainter * painter) -{ - if(painter) - { - for(int i=_items.size()-1; i>=0 && _items.at(i)->isVisible(); i-=2) - { - //plotItem - const UPlotItem * item = (const UPlotItem *)_items.at(i); - int x = (int)item->x(); - if(x<0) - { - break; - } - - // draw line in first - if(i-1>=0) - { - painter->save(); - painter->setPen(this->pen()); - painter->setBrush(this->brush()); - //lineItem - const QGraphicsLineItem * item = (const QGraphicsLineItem *)_items.at(i-1); - QLineF line = item->line(); - int x = (int)line.p1().x(); - if(x<0) - { - line.setP1(QPoint(0, line.p1().y())); - } - painter->drawLine(line); - painter->restore(); - } - - painter->drawEllipse(item->pos()+QPointF(item->rect().width()/2, item->rect().height()/2), (int)item->rect().width()/2, (int)item->rect().height()/2); - } - } -} - -int UPlotCurve::itemsSize() const -{ - return _items.size(); -} - -QPointF UPlotCurve::getItemData(int index) -{ - QPointF data; - //make sure the index point to a PlotItem {PlotItem, line, PlotItem, line...} - if(index>=0 && index < _items.size() && index % 2 == 0 ) - { - data = ((UPlotItem*)_items.at(index))->data(); - } - else - { - ULOGGER_ERROR("Wrong index, not pointing on a PlotItem"); - } - return data; -} - -void UPlotCurve::setVisible(bool visible) -{ - _visible = visible; - for(int i=0; i<_items.size(); ++i) - { - _items.at(i)->setVisible(visible); - } -} - -void UPlotCurve::setXIncrement(float increment) -{ - _xIncrement = increment; -} - -void UPlotCurve::setXStart(float val) -{ - _xStart = val; -} - -void UPlotCurve::setData(QVector & data) -{ - this->clear(); - for(int i = 0; iaddValue(data[i]); - } -} - -void UPlotCurve::setData(const QVector & x, const QVector & y) -{ - if(x.size() == y.size()) - { - //match the size of the current data - int margin = int((_items.size()+1)/2) - x.size(); - while(margin < 0) - { - UPlotItem * newItem = new UPlotItem(0, 0, 2); - this->_addValue(newItem); - ++margin; - } - while(margin > 0) - { - this->removeItem(0); - --margin; - } - - // update values - int index = 0; - QVector::const_iterator i=x.begin(); - QVector::const_iterator j=y.begin(); - for(; i!=x.end() && j!=y.end(); ++i, ++j, index+=2) - { - ((UPlotItem*)_items[index])->setData(QPointF(*i, *j)); - } - - //reset minMax, this will force the plot to update the axes - this->updateMinMax(); - Q_EMIT dataChanged(this); - } - else - { - ULOGGER_ERROR("Data vectors have not the same size."); - } -} - -void UPlotCurve::setData(const std::vector & x, const std::vector & y) -{ - if(x.size() == y.size()) - { - //match the size of the current data - int margin = int((_items.size()+1)/2) - int(x.size()); - while(margin < 0) - { - UPlotItem * newItem = new UPlotItem(0, 0, 2); - this->_addValue(newItem); - ++margin; - } - while(margin > 0) - { - this->removeItem(0); - --margin; - } - - // update values - int index = 0; - std::vector::const_iterator i=x.begin(); - std::vector::const_iterator j=y.begin(); - for(; i!=x.end() && j!=y.end(); ++i, ++j, index+=2) - { - ((UPlotItem*)_items[index])->setData(QPointF(*i, *j)); - } - - //reset minMax, this will force the plot to update the axes - this->updateMinMax(); - Q_EMIT dataChanged(this); - } - else - { - ULOGGER_ERROR("Data vectors have not the same size."); - } -} - -void UPlotCurve::setData(const QVector & y) -{ - this->setData(y.toStdVector()); -} - -void UPlotCurve::setData(const std::vector & y) -{ - //match the size of the current data - int margin = int((_items.size()+1)/2) - int(y.size()); - while(margin < 0) - { - UPlotItem * newItem = new UPlotItem(0, 0, 2); - this->_addValue(newItem); - ++margin; - } - while(margin > 0) - { - this->removeItem(0); - --margin; - } - - // update values - int index = 0; - float x = 0; - std::vector::const_iterator j=y.begin(); - for(; j!=y.end(); ++j, index+=2) - { - ((UPlotItem*)_items[index])->setData(QPointF(x++, *j)); - } - - //reset minMax, this will force the plot to update the axes - this->updateMinMax(); - Q_EMIT dataChanged(this); -} - -void UPlotCurve::getData(QVector & x, QVector & y) const -{ - x.clear(); - y.clear(); - if(_items.size()) - { - x.resize((_items.size()-1)/2+1); - y.resize(x.size()); - int j=0; - for(int i=0; i<_items.size(); i+=2) - { - x[j] = ((UPlotItem*)_items.at(i))->data().x(); - y[j++] = ((UPlotItem*)_items.at(i))->data().y(); - } - } -} - - - - - -UPlotCurveThreshold::UPlotCurveThreshold(const QString & name, float thesholdValue, Qt::Orientation orientation, QObject * parent) : - UPlotCurve(name, parent), - _orientation(orientation) -{ - if(_orientation == Qt::Horizontal) - { - this->addValue(0, thesholdValue); - this->addValue(1, thesholdValue); - } - else - { - this->addValue(thesholdValue, 0); - this->addValue(thesholdValue, 1); - } -} - -UPlotCurveThreshold::~UPlotCurveThreshold() -{ - -} - -void UPlotCurveThreshold::setThreshold(float threshold) -{ -#if PRINT_DEBUG - ULOGGER_DEBUG("%f", threshold); -#endif - if(_items.size() == 3) - { - UPlotItem * item = 0; - if(_orientation == Qt::Horizontal) - { - item = (UPlotItem*)_items.at(0); - item->setData(QPointF(item->data().x(), threshold)); - item = (UPlotItem*)_items.at(2); - item->setData(QPointF(item->data().x(), threshold)); - } - else - { - item = (UPlotItem*)_items.at(0); - item->setData(QPointF(threshold, item->data().y())); - item = (UPlotItem*)_items.at(2); - item->setData(QPointF(threshold, item->data().y())); - } - } - else - { - ULOGGER_ERROR("A threshold must has only 3 items (1 PlotItem + 1 QGraphicsLineItem + 1 PlotItem)"); - } -} - -void UPlotCurveThreshold::setOrientation(Qt::Orientation orientation) -{ - if(_orientation != orientation) - { - _orientation = orientation; - if(_items.size() == 3) - { - UPlotItem * item = 0; - item = (UPlotItem*)_items.at(0); - item->setData(QPointF(item->data().y(), item->data().x())); - item = (UPlotItem*)_items.at(2); - item->setData(QPointF(item->data().y(), item->data().x())); - } - else - { - ULOGGER_ERROR("A threshold must has only 3 items (1 PlotItem + 1 QGraphicsLineItem + 1 PlotItem)"); - } - } -} - -void UPlotCurveThreshold::update(float scaleX, float scaleY, float offsetX, float offsetY, float xDir, float yDir, bool allDataKept) -{ - if(_items.size() == 3) - { - if(_plot) - { - UPlotItem * item = 0; - if(_orientation == Qt::Horizontal) - { - //(xDir*item->data().x()+offsetX)*scaleX - item = (UPlotItem*)_items.at(0); - item->setData(QPointF(-offsetX/xDir, item->data().y())); - item = (UPlotItem*)_items.at(2); - item->setData(QPointF( (_plot->sceneRect().width()/scaleX-offsetX)/xDir, item->data().y())); - } - else - { - item = (UPlotItem*)_items.at(0); - item->setData(QPointF(item->data().x(), -offsetY/yDir)); - item = (UPlotItem*)_items.at(2); - item->setData(QPointF(item->data().x(), (_plot->sceneRect().height()/scaleY-offsetY)/yDir)); - } - this->updateMinMax(); - } - } - else - { - ULOGGER_ERROR("A threshold must has only 3 items (1 PlotItem + 1 QGraphicsLineItem + 1 PlotItem)"); - } - UPlotCurve::update(scaleX, scaleY, offsetX, offsetY, xDir, yDir, allDataKept); -} - - - - - - - -UPlotAxis::UPlotAxis(Qt::Orientation orientation, float min, float max, QWidget * parent) : - QWidget(parent), - _orientation(orientation), - _reversed(false), - _gradMaxDigits(4), - _border(0) -{ - if(_orientation == Qt::Vertical) - { - _reversed = true; // default bottom->up - } -#ifdef WIN32 - this->setMinimumSize(15, 25); -#else - this->setMinimumSize(15, 25); -#endif - this->setAxis(min, max); // this initialize all attributes -} - -UPlotAxis::~UPlotAxis() -{ -#if PRINT_DEBUG - ULOGGER_DEBUG(""); -#endif -} - -// Vertical :bottom->up, horizontal :right->left -void UPlotAxis::setReversed(bool reversed) -{ - if(_reversed != reversed) - { - float min = _min; - _min = _max; - _max = min; - } - _reversed = reversed; -} - -void UPlotAxis::setAxis(float & min, float & max) -{ - int borderMin = 0; - int borderMax = 0; - if(_orientation == Qt::Vertical) - { - borderMin = borderMax = this->fontMetrics().height()/2; - } - else - { - borderMin = this->fontMetrics().width(QString::number(_min,'g',_gradMaxDigits))/2; - borderMax = this->fontMetrics().width(QString::number(_max,'g',_gradMaxDigits))/2; - } - int border = borderMin>borderMax?borderMin:borderMax; - int borderDelta; - int length; - if(_orientation == Qt::Vertical) - { - length = (this->height()-border*2); - } - else - { - length = (this->width()-border*2); - } - - if(length <= 70) - { - _count = 5; - } - else if(length <= 175) - { - _count = 10; - } - else if(length <= 350) - { - _count = 20; - } - else if(length <= 700) - { - _count = 40; - } - else if(length <= 1000) - { - _count = 60; - } - else if(length <= 1300) - { - _count = 80; - } - else - { - _count = 100; - } - - // Rounding min and max - if(min != max) - { - float mul = 1; - float rangef = max - min; - int countStep = _count/5; - float val; - for(int i=0; i<6; ++i) - { - val = (rangef/float(countStep)) * mul; - if( val >= 1.0f && val < 10.0f) - { - break; - } - else if(val<1) - { - mul *= 10.0f; - } - else - { - mul /= 10.0f; - } - } - //ULOGGER_DEBUG("min=%f, max=%f", min, max); - int minR = min*mul-0.9; - int maxR = max*mul+0.9; - min = float(minR)/mul; - max = float(maxR)/mul; - //ULOGGER_DEBUG("mul=%f, minR=%d, maxR=%d,countStep=%d", mul, minR, maxR, countStep); - } - - _min = min; - _max = max; - - if(_reversed) - { - _min = _max; - _max = min; - } - - if(_orientation == Qt::Vertical) - { - _step = length/_count; - borderDelta = length - (_step*_count); - } - else - { - _step = length/_count; - borderDelta = length - (_step*_count); - } - - if(borderDelta%2 != 0) - { - borderDelta+=1; - } - - _border = border + borderDelta/2; - - //Resize estimation - if(_orientation == Qt::Vertical) - { - int minWidth = 0; - for (int i = 0; i <= _count; i+=5) - { - QString n(QString::number(_min + (i/5)*((_max-_min)/(_count/5)),'g',_gradMaxDigits)); - if(this->fontMetrics().width(n) > minWidth) - { - minWidth = this->fontMetrics().width(n); - } - } - this->setMinimumWidth(15+minWidth); - } -} - -void UPlotAxis::paintEvent(QPaintEvent * event) -{ - QPainter painter(this); - if(_orientation == Qt::Vertical) - { - painter.translate(0, _border); - for (int i = 0; i <= _count; ++i) - { - if(i%5 == 0) - { - painter.drawLine(this->width(), 0, this->width()-10, 0); - QLabel n(QString::number(_min + (i/5)*((_max-_min)/(_count/5)),'g',_gradMaxDigits)); - painter.drawText(this->width()-(12+n.sizeHint().width()), n.sizeHint().height()/2-2, n.text()); - } - else - { - painter.drawLine(this->width(), 0, this->width()-5, 0); - } - painter.translate(0, _step); - } - } - else - { - painter.translate(_border, 0); - for (int i = 0; i <= _count; ++i) - { - if(i%5 == 0) - { - painter.drawLine(0, 0, 0, 10); - QLabel n(QString::number(_min + (i/5)*((_max-_min)/(_count/5)),'g',_gradMaxDigits)); - painter.drawText(-(n.sizeHint().width()/2)+1, 22, n.text()); - } - else - { - painter.drawLine(0, 0, 0, 5); - } - painter.translate(_step, 0); - } - } -} - - - - -UPlotLegendItem::UPlotLegendItem(const UPlotCurve * curve, QWidget * parent) : - QPushButton(parent), - _curve(curve) -{ - QString nameSpaced = curve->name(); - nameSpaced.replace('_', ' '); - this->setText(nameSpaced); - - _aChangeText = new QAction(tr("Change text..."), this); - _aResetText = new QAction(tr("Reset text..."), this); - _aRemoveCurve = new QAction(tr("Remove this curve"), this); - _aCopyToClipboard = new QAction(tr("Copy curve data to the clipboard"), this); - _menu = new QMenu(tr("Curve"), this); - _menu->addAction(_aChangeText); - _menu->addAction(_aResetText); - _menu->addAction(_aRemoveCurve); - _menu->addAction(_aCopyToClipboard); -} - -UPlotLegendItem::~UPlotLegendItem() -{ - -} -void UPlotLegendItem::contextMenuEvent(QContextMenuEvent * event) -{ - QAction * action = _menu->exec(event->globalPos()); - if(action == _aChangeText) - { - bool ok; - QString text = QInputDialog::getText(this, _aChangeText->text(), tr("Name :"), QLineEdit::Normal, this->text(), &ok); - if(ok && !text.isEmpty()) - { - this->setText(text); - } - } - else if(action == _aResetText) - { - if(_curve) - { - this->setText(_curve->name()); - } - } - else if(action == _aRemoveCurve) - { - Q_EMIT legendItemRemoved(_curve); - } - else if (action == _aCopyToClipboard) - { - if(_curve) - { - QVector x; - QVector y; - _curve->getData(x, y); - QString textX; - QString textY; - for(int i=0; isetText((textX+"\n")+textY); - } - } -} - - - - - - -UPlotLegend::UPlotLegend(QWidget * parent) : - QWidget(parent), - _flat(true) -{ - //menu - _aUseFlatButtons = new QAction(tr("Use flat buttons"), this); - _aUseFlatButtons->setCheckable(true); - _aUseFlatButtons->setChecked(_flat); - _menu = new QMenu(tr("Legend"), this); - _menu->addAction(_aUseFlatButtons); - - QVBoxLayout * vLayout = new QVBoxLayout(this); - vLayout->setContentsMargins(0,0,0,0); - this->setLayout(vLayout); - vLayout->addStretch(0); - vLayout->setSpacing(0); -} - -UPlotLegend::~UPlotLegend() -{ -#if PRINT_DEBUG - ULOGGER_DEBUG(""); -#endif -} - -void UPlotLegend::setFlat(bool on) -{ - if(_flat != on) - { - _flat = on; - QList items = this->findChildren(); - for(int i=0; isetFlat(_flat); - items.at(i)->setChecked(!items.at(i)->isChecked()); - } - _aUseFlatButtons->setChecked(_flat); - } -} - -void UPlotLegend::addItem(const UPlotCurve * curve) -{ - if(curve) - { - UPlotLegendItem * legendItem = new UPlotLegendItem(curve, this); - legendItem->setAutoDefault(false); - legendItem->setFlat(_flat); - legendItem->setCheckable(true); - legendItem->setChecked(false); - legendItem->setIcon(QIcon(this->createSymbol(curve->pen(), curve->brush()))); - legendItem->setIconSize(QSize(25,20)); - connect(legendItem, SIGNAL(toggled(bool)), this, SLOT(redirectToggled(bool))); - connect(legendItem, SIGNAL(legendItemRemoved(const UPlotCurve *)), this, SLOT(removeLegendItem(const UPlotCurve *))); - - // layout - QHBoxLayout * hLayout = new QHBoxLayout(); - hLayout->addWidget(legendItem); - hLayout->addStretch(0); - hLayout->setMargin(0); - - // add to the legend - ((QVBoxLayout*)this->layout())->insertLayout(this->layout()->count()-1, hLayout); - } -} - -QPixmap UPlotLegend::createSymbol(const QPen & pen, const QBrush & brush) -{ - QPixmap pixmap(50, 50); - pixmap.fill(Qt::transparent); - QPainter painter(&pixmap); - QPen p = pen; - p.setWidthF(4.0); - painter.setPen(p); - painter.drawLine(0.0, 25.0, 50.0, 25.0); - return pixmap; -} - -bool UPlotLegend::remove(const UPlotCurve * curve) -{ - QList items = this->findChildren(); - for(int i=0; icurve() == curve) - { - delete items.at(i); - return true; - } - } - return false; -} - -void UPlotLegend::removeLegendItem(const UPlotCurve * curve) -{ - if(this->remove(curve)) - { - Q_EMIT legendItemRemoved(curve); - } -} - -void UPlotLegend::contextMenuEvent(QContextMenuEvent * event) -{ - QAction * action = _menu->exec(event->globalPos()); - if(action == _aUseFlatButtons) - { - this->setFlat(_aUseFlatButtons->isChecked()); - } -} - -void UPlotLegend::redirectToggled(bool toggled) -{ - if(sender()) - { - UPlotLegendItem * item = qobject_cast(sender()); - if(item) - { - Q_EMIT legendItemToggled(item->curve(), _flat?!toggled:toggled); - } - } -} - - - - - - - -UOrientableLabel::UOrientableLabel(const QString & text, Qt::Orientation orientation, QWidget * parent) : - QLabel(text, parent), - _orientation(orientation) -{ -} - -UOrientableLabel::~UOrientableLabel() -{ -} - -QSize UOrientableLabel::sizeHint() const -{ - QSize size = QLabel::sizeHint(); - if (_orientation == Qt::Vertical) - size.transpose(); - return size; - -} - -QSize UOrientableLabel::minimumSizeHint() const -{ - QSize size = QLabel::minimumSizeHint(); - if (_orientation == Qt::Vertical) - size.transpose(); - return size; -} - -void UOrientableLabel::setOrientation(Qt::Orientation orientation) -{ - _orientation = orientation; - switch(orientation) - { - case Qt::Horizontal: - setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); - break; - - case Qt::Vertical: - setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); - break; - } -} - -void UOrientableLabel::paintEvent(QPaintEvent* event) -{ - QPainter p(this); - QRect r = rect(); - switch (_orientation) - { - case Qt::Horizontal: - break; - case Qt::Vertical: - p.rotate(-90); - p.translate(-height(), 0); - QSize size = r.size(); - size.transpose(); - r.setSize(size); - break; - } - p.drawText(r, this->alignment() | (this->wordWrap()?Qt::TextWordWrap:0), this->text()); -} - - - - - - - - - - - - - -UPlot::UPlot(QWidget *parent) : - QWidget(parent), - _maxVisibleItems(-1), - _autoScreenCaptureFormat("png") -{ - this->setupUi(); - this->createActions(); - this->createMenus(); - - // This will update actions - this->showLegend(true); - this->setGraphicsView(false); - this->setMaxVisibleItems(0); - this->showGrid(false); - this->showRefreshRate(false); - this->keepAllData(false); - - for(int i=0; i<4; ++i) - { - _axisMaximums[i] = 0; - _axisMaximumsSet[i] = false; - if(i<2) - { - _fixedAxis[i] = false; - } - } - - _refreshIntervalTime.start(); - _lowestRefreshRate = 99; - _refreshStartTime.start(); - - _penStyleCount = rand() % 10 + 1; // rand 1->10 - _workingDirectory = QDir::homePath(); -} - -UPlot::~UPlot() -{ - _aAutoScreenCapture->setChecked(false); -#if PRINT_DEBUG - ULOGGER_DEBUG("%s", this->title().toStdString().c_str()); -#endif - this->removeCurves(); -} - -void UPlot::setupUi() -{ - _legend = new UPlotLegend(this); - _view = new QGraphicsView(this); - _view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - _view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - _view->setScene(new QGraphicsScene(0,0,0,0,this)); - _view->setStyleSheet( "QGraphicsView { border-style: none; }" ); - _sceneRoot = _view->scene()->addText(""); - _sceneRoot->setPos(0,0); - _graphicsViewHolder = new QWidget(this); - _graphicsViewHolder->setMinimumSize(100,100); - _verticalAxis = new UPlotAxis(Qt::Vertical, 0, 1, this); - _horizontalAxis = new UPlotAxis(Qt::Horizontal, 0, 1, this); - _title = new QLabel(""); - _xLabel = new QLabel(""); - _refreshRate = new QLabel(""); - _yLabel = new UOrientableLabel(""); - _yLabel->setOrientation(Qt::Vertical); - _title->setAlignment(Qt::AlignCenter); - _xLabel->setAlignment(Qt::AlignCenter); - _yLabel->setAlignment(Qt::AlignCenter); - _refreshRate->setAlignment(Qt::AlignCenter); - _title->setWordWrap(true); - _xLabel->setWordWrap(true); - _yLabel->setWordWrap(true); - _title->setVisible(false); - _xLabel->setVisible(false); - _yLabel->setVisible(false); - _refreshRate->setVisible(false); - - //layouts - QVBoxLayout * vLayout = new QVBoxLayout(_graphicsViewHolder); - vLayout->setContentsMargins(0,0,0,0); - vLayout->addWidget(_view); - - QGridLayout * grid = new QGridLayout(this); - grid->setContentsMargins(0,0,0,0); - grid->addWidget(_title, 0, 2); - grid->addWidget(_yLabel, 1, 0); - grid->addWidget(_verticalAxis, 1, 1); - grid->addWidget(_refreshRate, 2, 1); - grid->addWidget(_graphicsViewHolder, 1, 2); - grid->setColumnStretch(2, 1); - grid->setRowStretch(1, 1); - grid->addWidget(_horizontalAxis, 2, 2); - grid->addWidget(_xLabel, 3, 2); - grid->addWidget(_legend, 1, 3); - - connect(_legend, SIGNAL(legendItemToggled(const UPlotCurve *, bool)), this, SLOT(showCurve(const UPlotCurve *, bool))); - connect(_legend, SIGNAL(legendItemRemoved(const UPlotCurve *)), this, SLOT(removeCurve(const UPlotCurve *))); -} - -void UPlot::createActions() -{ - _aShowLegend = new QAction(tr("Show legend"), this); - _aShowLegend->setCheckable(true); - _aShowGrid = new QAction(tr("Show grid"), this); - _aShowGrid->setCheckable(true); - _aShowRefreshRate = new QAction(tr("Show refresh rate"), this); - _aShowRefreshRate->setCheckable(true); - _aGraphicsView = new QAction(tr("Graphics view"), this); - _aGraphicsView->setCheckable(true); - _aKeepAllData = new QAction(tr("Keep all data"), this); - _aKeepAllData->setCheckable(true); - _aLimit0 = new QAction(tr("No maximum items shown"), this); - _aLimit10 = new QAction(tr("10"), this); - _aLimit50 = new QAction(tr("50"), this); - _aLimit100 = new QAction(tr("100"), this); - _aLimit500 = new QAction(tr("500"), this); - _aLimit1000 = new QAction(tr("1000"), this); - _aLimitCustom = new QAction(tr(""), this); - _aLimit0->setCheckable(true); - _aLimit10->setCheckable(true); - _aLimit50->setCheckable(true); - _aLimit100->setCheckable(true); - _aLimit500->setCheckable(true); - _aLimit1000->setCheckable(true); - _aLimitCustom->setCheckable(true); - _aLimitCustom->setVisible(false); - _aAddVerticalLine = new QAction(tr("Vertical line..."), this); - _aAddHorizontalLine = new QAction(tr("Horizontal line..."), this); - _aChangeTitle = new QAction(tr("Change title"), this); - _aChangeXLabel = new QAction(tr("Change X label..."), this); - _aChangeYLabel = new QAction(tr("Change Y label..."), this); - _aYLabelVertical = new QAction(tr("Vertical orientation"), this); - _aYLabelVertical->setCheckable(true); - _aYLabelVertical->setChecked(true); - _aSaveFigure = new QAction(tr("Save figure..."), this); - _aAutoScreenCapture = new QAction(tr("Auto screen capture..."), this); - _aAutoScreenCapture->setCheckable(true); - _aClearData = new QAction(tr("Clear data"), this); - - QActionGroup * grpLimit = new QActionGroup(this); - grpLimit->addAction(_aLimit0); - grpLimit->addAction(_aLimit10); - grpLimit->addAction(_aLimit50); - grpLimit->addAction(_aLimit100); - grpLimit->addAction(_aLimit500); - grpLimit->addAction(_aLimit1000); - grpLimit->addAction(_aLimitCustom); - _aLimit0->setChecked(true); -} - -void UPlot::createMenus() -{ - _menu = new QMenu(tr("Plot"), this); - _menu->addAction(_aShowLegend); - _menu->addAction(_aShowGrid); - _menu->addAction(_aShowRefreshRate); - _menu->addAction(_aGraphicsView); - _menu->addAction(_aKeepAllData); - _menu->addSeparator()->setStatusTip(tr("Maximum items shown")); - _menu->addAction(_aLimit0); - _menu->addAction(_aLimit10); - _menu->addAction(_aLimit50); - _menu->addAction(_aLimit100); - _menu->addAction(_aLimit500); - _menu->addAction(_aLimit1000); - _menu->addAction(_aLimitCustom); - _menu->addSeparator(); - QMenu * addLineMenu = _menu->addMenu(tr("Add line")); - addLineMenu->addAction(_aAddHorizontalLine); - addLineMenu->addAction(_aAddVerticalLine); - _menu->addSeparator(); - _menu->addAction(_aChangeTitle); - _menu->addAction(_aChangeXLabel); - QMenu * yLabelMenu = _menu->addMenu(tr("Y label")); - yLabelMenu->addAction(_aChangeYLabel); - yLabelMenu->addAction(_aYLabelVertical); - _menu->addAction(_aSaveFigure); - _menu->addAction(_aAutoScreenCapture); - _menu->addSeparator(); - _menu->addAction(_aClearData); - -} - -UPlotCurve * UPlot::addCurve(const QString & curveName, const QColor & color) -{ - // add curve - UPlotCurve * curve = new UPlotCurve(curveName, this); - if(color.isValid()) - { - curve->setPen(color); - } - else - { - curve->setPen(this->getRandomPenColored()); - } - this->addCurve(curve); - return curve; -} - -bool UPlot::addCurve(UPlotCurve * curve, bool ownershipTransferred) -{ - if(curve) - { - // only last curve can trigger an update, so disable previous connections - if(!qobject_cast(curve)) - { - for(int i=_curves.size()-1; i>=0; --i) - { - if(!qobject_cast(_curves.at(i))) - { - disconnect(_curves.at(i), SIGNAL(dataChanged(const UPlotCurve *)), this, SLOT(updateAxis())); - break; - } - } - } - - // add curve - _curves.append(curve); - curve->attach(this); - if(ownershipTransferred) - { - curve->setParent(this); - } - this->updateAxis(curve); - curve->setXStart(_axisMaximums[1]); - - connect(curve, SIGNAL(dataChanged(const UPlotCurve *)), this, SLOT(updateAxis())); - - _legend->addItem(curve); - -#if PRINT_DEBUG - ULOGGER_DEBUG("Curve \"%s\" added to plot \"%s\"", curve->name().toStdString().c_str(), this->title().toStdString().c_str()); -#endif - - return true; - } - else - { - ULOGGER_ERROR("The curve is null!"); - } - return false; -} - -QStringList UPlot::curveNames() -{ - QStringList names; - for(QList::iterator iter = _curves.begin(); iter!=_curves.end(); ++iter) - { - if(*iter) - { - names.append((*iter)->name()); - } - } - return names; -} - -bool UPlot::contains(const QString & curveName) -{ - for(QList::iterator iter = _curves.begin(); iter!=_curves.end(); ++iter) - { - if(*iter && (*iter)->name().compare(curveName) == 0) - { - return true; - } - } - return false; -} - -QPen UPlot::getRandomPenColored() -{ - return QPen((Qt::GlobalColor)(_penStyleCount++ % 12 + 7 )); -} - -void UPlot::replot(QPainter * painter) -{ - if(_maxVisibleItems>0) - { - UPlotCurve * c = 0; - int maxItem = 0; - // find the curve with the most items - for(QList::iterator i=_curves.begin(); i!=_curves.end(); ++i) - { - if((*i)->isVisible() && ((UPlotCurve *)(*i))->itemsSize() > maxItem) - { - c = *i; - maxItem = c->itemsSize(); - } - } - if(c && (maxItem-1)/2+1 > _maxVisibleItems) - { - _axisMaximums[0] = c->getItemData((c->itemsSize()-1) -_maxVisibleItems*2).x(); - } - } - - float axis[4] = {0}; - for(int i=0; i<4; ++i) - { - axis[i] = _axisMaximums[i]; - } - - _verticalAxis->setAxis(axis[2], axis[3]); - _horizontalAxis->setAxis(axis[0], axis[1]); - if(_aGraphicsView->isChecked() && !painter) - { - _verticalAxis->update(); - _horizontalAxis->update(); - } - - //ULOGGER_DEBUG("x1=%f, x2=%f, y1=%f, y2=%f", _axisMaximums[0], _axisMaximums[1], _axisMaximums[2], _axisMaximums[3]); - - QRectF newRect(0,0, _graphicsViewHolder->size().width(), _graphicsViewHolder->size().height()); - _view->scene()->setSceneRect(newRect); - float borderHor = (float)_horizontalAxis->border(); - float borderVer = (float)_verticalAxis->border(); - - //grid - qDeleteAll(hGridLines); - hGridLines.clear(); - qDeleteAll(vGridLines); - vGridLines.clear(); - if(_aShowGrid->isChecked()) - { - // TODO make a PlotGrid class ? - float w = newRect.width()-(borderHor*2); - float h = newRect.height()-(borderVer*2); - float stepH = w / float(_horizontalAxis->count()); - float stepV = h / float(_verticalAxis->count()); - QPen pen(Qt::DashLine); - for(float i=0.0f; i*stepV <= h+stepV; i+=5.0f) - { - //horizontal lines - if(!_aGraphicsView->isChecked()) - { - if(painter) - { - painter->drawLine(0, stepV*i+borderVer+0.5f, borderHor, stepV*i+borderVer+0.5f); - painter->save(); - painter->setPen(pen); - painter->drawLine(borderHor, stepV*i+borderVer+0.5f, w+borderHor, stepV*i+borderVer+0.5f); - painter->restore(); - painter->drawLine(w+borderHor, stepV*i+borderVer+0.5f, w+borderHor*2, stepV*i+borderVer+0.5f); - } - } - else - { - hGridLines.append(new QGraphicsLineItem(0, stepV*i+borderVer, borderHor, stepV*i+borderVer, _sceneRoot)); - hGridLines.append(new QGraphicsLineItem(borderHor, stepV*i+borderVer, w+borderHor, stepV*i+borderVer, _sceneRoot)); - hGridLines.last()->setPen(pen); - hGridLines.append(new QGraphicsLineItem(w+borderHor, stepV*i+borderVer, w+borderHor*2, stepV*i+borderVer, _sceneRoot)); - } - } - for(float i=0; i*stepH < w+stepH; i+=5.0f) - { - //vertical lines - if(!_aGraphicsView->isChecked()) - { - if(painter) - { - painter->drawLine(stepH*i+borderHor+0.5f, 0, stepH*i+borderHor+0.5f, borderVer); - painter->save(); - painter->setPen(pen); - painter->drawLine(stepH*i+borderHor+0.5f, borderVer, stepH*i+borderHor+0.5f, h+borderVer); - painter->restore(); - painter->drawLine(stepH*i+borderHor+0.5f, h+borderVer, stepH*i+borderHor+0.5f, h+borderVer*2); - } - } - else - { - vGridLines.append(new QGraphicsLineItem(stepH*i+borderHor, 0, stepH*i+borderHor, borderVer, _sceneRoot)); - vGridLines.append(new QGraphicsLineItem(stepH*i+borderHor, borderVer, stepH*i+borderHor, h+borderVer, _sceneRoot)); - vGridLines.last()->setPen(pen); - vGridLines.append(new QGraphicsLineItem(stepH*i+borderHor, h+borderVer, stepH*i+borderHor, h+borderVer*2, _sceneRoot)); - } - } - } - - // curves - float scaleX = 1; - float scaleY = 1; - float den = 0; - den = axis[1] - axis[0]; - if(den != 0) - { - scaleX = (newRect.width()-(borderHor*2)) / den; - } - den = axis[3] - axis[2]; - if(den != 0) - { - scaleY = (newRect.height()-(borderVer*2)) / den; - } - for(QList::iterator i=_curves.begin(); i!=_curves.end(); ++i) - { - if((*i)->isVisible()) - { - float xDir = 1.0f; - float yDir = -1.0f; - (*i)->update(scaleX, - scaleY, - xDir<0?axis[1]+borderHor/scaleX:-(axis[0]-borderHor/scaleX), - yDir<0?axis[3]+borderVer/scaleY:-(axis[2]-borderVer/scaleY), - xDir, - yDir, - _aKeepAllData->isChecked()); - if(painter) - { - (*i)->draw(painter); - } - } - } - - // Update refresh rate - if(_aShowRefreshRate->isChecked()) - { - int refreshRate = qRound(1000.0f/float(_refreshIntervalTime.restart())); - if(refreshRate > 0 && refreshRate < _lowestRefreshRate) - { - _lowestRefreshRate = refreshRate; - } - // Refresh the label only after each 1000 ms - if(_refreshStartTime.elapsed() > 1000) - { - _refreshRate->setText(QString::number(_lowestRefreshRate)); - _lowestRefreshRate = 99; - _refreshStartTime.start(); - } - } -} - -void UPlot::setFixedXAxis(float x1, float x2) -{ - _fixedAxis[0] = true; - _axisMaximums[0] = x1; - _axisMaximums[1] = x2; -} - -void UPlot::setFixedYAxis(float y1, float y2) -{ - _fixedAxis[1] = true; - _axisMaximums[2] = y1; - _axisMaximums[3] = y2; -} - -void UPlot::updateAxis(const UPlotCurve * curve) -{ - if(curve && curve->isVisible() && curve->itemsSize() && curve->isMinMaxValid()) - { - const QVector & minMax = curve->getMinMax(); - //ULOGGER_DEBUG("x1=%f, x2=%f, y1=%f, y2=%f", minMax[0], minMax[1], minMax[2], minMax[3]); - if(minMax.size() != 4) - { - ULOGGER_ERROR("minMax size != 4 ?!?"); - return; - } - this->updateAxis(minMax[0], minMax[1], minMax[2], minMax[3]); - _aGraphicsView->isChecked()?this->replot(0):this->update(); - } -} - -bool UPlot::updateAxis(float x1, float x2, float y1, float y2) -{ - bool modified = false; - modified = updateAxis(x1,y1); - if(!modified) - { - modified = updateAxis(x2,y2); - } - else - { - updateAxis(x2,y2); - } - return modified; -} - -bool UPlot::updateAxis(float x, float y) -{ - //ULOGGER_DEBUG("x=%f, y=%f", x,y); - bool modified = false; - if(!_fixedAxis[0] && (!_axisMaximumsSet[0] || x < _axisMaximums[0])) - { - _axisMaximums[0] = x; - _axisMaximumsSet[0] = true; - modified = true; - } - - if(!_fixedAxis[0] && (!_axisMaximumsSet[1] || x > _axisMaximums[1])) - { - _axisMaximums[1] = x; - _axisMaximumsSet[1] = true; - modified = true; - } - - if(!_fixedAxis[1] && (!_axisMaximumsSet[2] || y < _axisMaximums[2])) - { - _axisMaximums[2] = y; - _axisMaximumsSet[2] = true; - modified = true; - } - - if(!_fixedAxis[1] && (!_axisMaximumsSet[3] || y > _axisMaximums[3])) - { - _axisMaximums[3] = y; - _axisMaximumsSet[3] = true; - modified = true; - } - - return modified; -} - -void UPlot::updateAxis() -{ - //Reset the axis - for(int i=0; i<4; ++i) - { - if((!_fixedAxis[0] && i<2) || (!_fixedAxis[1] && i>=2)) - { - _axisMaximums[i] = 0; - _axisMaximumsSet[i] = false; - } - } - - for(int i=0; i<_curves.size(); ++i) - { - if(_curves.at(i)->isVisible() && _curves.at(i)->isMinMaxValid()) - { - const QVector & minMax = _curves.at(i)->getMinMax(); - this->updateAxis(minMax[0], minMax[1], minMax[2], minMax[3]); - } - } - - _aGraphicsView->isChecked()?this->replot(0):this->update(); - - this->captureScreen(); -} - -void UPlot::paintEvent(QPaintEvent * event) -{ -#if PRINT_DEBUG - UDEBUG(""); -#endif - if(!_aGraphicsView->isChecked()) - { - QPainter painter(this); - painter.translate(_graphicsViewHolder->pos()); - painter.save(); - painter.setBrush(Qt::white); - painter.setPen(QPen(Qt::NoPen)); - painter.drawRect(_graphicsViewHolder->rect()); - painter.restore(); - - this->replot(&painter); - } - else - { - QWidget::paintEvent(event); - } -} - -void UPlot::resizeEvent(QResizeEvent * event) -{ - if(_aGraphicsView->isChecked()) - { - this->replot(0); - } - QWidget::resizeEvent(event); -} - -void UPlot::contextMenuEvent(QContextMenuEvent * event) -{ - QAction * action = _menu->exec(event->globalPos()); - - if(!action) - { - return; - } - else if(action == _aShowLegend) - { - this->showLegend(_aShowLegend->isChecked()); - } - else if(action == _aShowGrid) - { - this->showGrid(_aShowGrid->isChecked()); - } - else if(action == _aShowRefreshRate) - { - this->showRefreshRate(_aShowRefreshRate->isChecked()); - } - else if(action == _aGraphicsView) - { - this->setGraphicsView(_aGraphicsView->isChecked()); - } - else if(action == _aKeepAllData) - { - this->keepAllData(_aKeepAllData->isChecked()); - } - else if(action == _aLimit0 || - action == _aLimit10 || - action == _aLimit50 || - action == _aLimit100 || - action == _aLimit500 || - action == _aLimit1000 || - action == _aLimitCustom) - { - this->setMaxVisibleItems(action->text().toInt()); - } - else if(action == _aAddVerticalLine || action == _aAddHorizontalLine) - { - bool ok; - QString text = QInputDialog::getText(this, action->text(), tr("New line name :"), QLineEdit::Normal, "", &ok); - while(ok && text.isEmpty()) - { - QMessageBox::warning(this, action->text(), tr("The name is not valid or it is already used in this plot.")); - text = QInputDialog::getText(this, action->text(), tr("New line name :"), QLineEdit::Normal, "", &ok); - } - if(ok) - { - double min = _axisMaximums[2]; - double max = _axisMaximums[3]; - QString axis = "Y"; - if(action == _aAddVerticalLine) - { - min = _axisMaximums[0]; - max = _axisMaximums[1]; - axis = "X"; - } - double value = QInputDialog::getDouble(this, - action->text(), - tr("%1 value (min=%2, max=%3):").arg(axis).arg(min).arg(max), - (min+max)/2, - -2147483647, - 2147483647, - 4, - &ok); - if(ok) - { - if(action == _aAddHorizontalLine) - { - this->addThreshold(text, value, Qt::Horizontal); - } - else - { - this->addThreshold(text, value, Qt::Vertical); - } - } - } - } - else if(action == _aChangeTitle) - { - bool ok; - QString text = _title->text(); - if(text.isEmpty()) - { - text = this->objectName(); - } - text = QInputDialog::getText(this, _aChangeTitle->text(), tr("Title :"), QLineEdit::Normal, text, &ok); - if(ok) - { - this->setTitle(text); - } - } - else if(action == _aChangeXLabel) - { - bool ok; - QString text = QInputDialog::getText(this, _aChangeXLabel->text(), tr("X axis label :"), QLineEdit::Normal, _xLabel->text(), &ok); - if(ok) - { - this->setXLabel(text); - } - } - else if(action == _aChangeYLabel) - { - bool ok; - QString text = QInputDialog::getText(this, _aChangeYLabel->text(), tr("Y axis label :"), QLineEdit::Normal, _yLabel->text(), &ok); - if(ok) - { - this->setYLabel(text, _yLabel->orientation()); - } - } - else if(action == _aYLabelVertical) - { - this->setYLabel(_yLabel->text(), _aYLabelVertical->isChecked()?Qt::Vertical:Qt::Horizontal); - } - else if(action == _aSaveFigure) - { - - QString text; -#ifdef QT_SVG_LIB - text = QFileDialog::getSaveFileName(this, tr("Save figure to ..."), (QDir::homePath() + "/") + this->title() + ".png", "*.png *.xpm *.jpg *.pdf *.svg"); -#else - text = QFileDialog::getSaveFileName(this, tr("Save figure to ..."), (QDir::homePath() + "/") + this->title() + ".png", "*.png *.xpm *.jpg *.pdf"); -#endif - if(!text.isEmpty()) - { - bool flatModified = false; - if(!_legend->isFlat()) - { - _legend->setFlat(true); - flatModified = true; - } - - QPalette p(palette()); - // Set background color to white - QColor c = p.color(QPalette::Background); - p.setColor(QPalette::Background, Qt::white); - setPalette(p); - -#ifdef QT_SVG_LIB - if(QFileInfo(text).suffix().compare("svg") == 0) - { - QSvgGenerator generator; - generator.setFileName(text); - generator.setSize(this->size()); - QPainter painter; - painter.begin(&generator); - this->render(&painter); - painter.end(); - } - else - { -#endif - if(QFileInfo(text).suffix().compare("pdf") == 0) - { - QPrinter printer; - printer.setOutputFormat(QPrinter::PdfFormat); - printer.setOutputFileName(text); - this->render(&printer); - } - else - { - QPixmap figure = QPixmap::grabWidget(this); - figure.save(text); - } -#ifdef QT_SVG_LIB - } -#endif - // revert background color - p.setColor(QPalette::Background, c); - setPalette(p); - - if(flatModified) - { - _legend->setFlat(false); - } - } - } - else if(action == _aAutoScreenCapture) - { - if(_aAutoScreenCapture->isChecked()) - { - this->selectScreenCaptureFormat(); - } - } - else if(action == _aClearData) - { - this->clearData(); - } - else - { - ULOGGER_WARN("Unknown action"); - } -} - -void UPlot::setWorkingDirectory(const QString & workingDirectory) -{ - if(QDir(_workingDirectory).exists()) - { - _workingDirectory = workingDirectory; - } - else - { - ULOGGER_ERROR("The directory \"%s\" doesn't exist", workingDirectory.toStdString().c_str()); - } -} - -void UPlot::captureScreen() -{ - if(!_aAutoScreenCapture->isChecked()) - { - return; - } - QString targetDir = _workingDirectory + "/ScreensCaptured"; - QDir dir; - if(!dir.exists(targetDir)) - { - dir.mkdir(targetDir); - } - targetDir += "/"; - targetDir += this->title().replace(" ", "_"); - if(!dir.exists(targetDir)) - { - dir.mkdir(targetDir); - } - targetDir += "/"; - QString name = (QDateTime::currentDateTime().toString("yyMMddhhmmsszzz") + ".") + _autoScreenCaptureFormat; - QPixmap figure = QPixmap::grabWidget(this); - figure.save(targetDir + name); -} - -void UPlot::selectScreenCaptureFormat() -{ - QStringList items; - items << QString("png") << QString("jpg"); - bool ok; - QString item = QInputDialog::getItem(this, tr("Select format"), tr("Format:"), items, 0, false, &ok); - if(ok && !item.isEmpty()) - { - _autoScreenCaptureFormat = item; - } - this->captureScreen(); -} - -void UPlot::clearData() -{ - for(int i=0; i<_curves.size(); ++i) - { - // Don't clear threshold curves - if(qobject_cast(_curves.at(i)) == 0) - { - _curves.at(i)->clear(); - } - } - _aGraphicsView->isChecked()?this->replot(0):this->update(); -} - -// for convenience... -UPlotCurveThreshold * UPlot::addThreshold(const QString & name, float value, Qt::Orientation orientation) -{ - UPlotCurveThreshold * curve = new UPlotCurveThreshold(name, value, orientation, this); - QPen pen = curve->pen(); - pen.setStyle((Qt::PenStyle)(_penStyleCount++ % 4 + 2)); - curve->setPen(pen); - if(!this->addCurve(curve)) - { - if(curve) - { - delete curve; - } - } - else - { - _aGraphicsView->isChecked()?this->replot(0):this->update(); - } - return curve; -} - -void UPlot::setTitle(const QString & text) -{ - _title->setText(text); - _title->setVisible(!text.isEmpty()); - this->update(); - if(_aGraphicsView->isChecked()) - { - QTimer::singleShot(10, this, SLOT(updateAxis())); - } -} - -void UPlot::setXLabel(const QString & text) -{ - _xLabel->setText(text); - _xLabel->setVisible(!text.isEmpty()); - this->update(); - if(_aGraphicsView->isChecked()) - { - QTimer::singleShot(10, this, SLOT(updateAxis())); - } -} - -void UPlot::setYLabel(const QString & text, Qt::Orientation orientation) -{ - _yLabel->setText(text); - _yLabel->setOrientation(orientation); - _yLabel->setVisible(!text.isEmpty()); - _aYLabelVertical->setChecked(orientation==Qt::Vertical); - this->update(); - if(_aGraphicsView->isChecked()) - { - QTimer::singleShot(10, this, SLOT(updateAxis())); - } -} - -void UPlot::addItem(QGraphicsItem * item) -{ - item->setParentItem(_sceneRoot); -} - -void UPlot::showLegend(bool shown) -{ - _legend->setVisible(shown); - _aShowLegend->setChecked(shown); - this->update(); - if(_aGraphicsView->isChecked()) - { - QTimer::singleShot(10, this, SLOT(updateAxis())); - } -} - -void UPlot::showGrid(bool shown) -{ - _aShowGrid->setChecked(shown); - _aGraphicsView->isChecked()?this->replot(0):this->update(); -} - -void UPlot::showRefreshRate(bool shown) -{ - _aShowRefreshRate->setChecked(shown); - _refreshRate->setVisible(shown); - this->update(); - if(_aGraphicsView->isChecked()) - { - QTimer::singleShot(10, this, SLOT(updateAxis())); - } -} - -void UPlot::setGraphicsView(bool on) -{ - _aGraphicsView->setChecked(on); - _view->setVisible(on); - _aGraphicsView->isChecked()?this->replot(0):this->update(); -} - -void UPlot::keepAllData(bool kept) -{ - _aKeepAllData->setChecked(kept); -} - -void UPlot::setMaxVisibleItems(int maxVisibleItems) -{ - if(maxVisibleItems <= 0) - { - _aLimit0->setChecked(true); - } - else if(maxVisibleItems == 10) - { - _aLimit10->setChecked(true); - } - else if(maxVisibleItems == 50) - { - _aLimit50->setChecked(true); - } - else if(maxVisibleItems == 100) - { - _aLimit100->setChecked(true); - } - else if(maxVisibleItems == 500) - { - _aLimit500->setChecked(true); - } - else if(maxVisibleItems == 1000) - { - _aLimit1000->setChecked(true); - } - else - { - _aLimitCustom->setVisible(true); - _aLimitCustom->setChecked(true); - _aLimitCustom->setText(QString::number(maxVisibleItems)); - } - _maxVisibleItems = maxVisibleItems; - updateAxis(); -} - -QRectF UPlot::sceneRect() const -{ - return _view->sceneRect(); -} - -void UPlot::removeCurves() -{ - QList tmp = _curves; - for(QList::iterator iter=tmp.begin(); iter!=tmp.end(); ++iter) - { - this->removeCurve(*iter); - } - _curves.clear(); -} - -void UPlot::removeCurve(const UPlotCurve * curve) -{ - QList::iterator iter = qFind(_curves.begin(), _curves.end(), curve); -#if PRINT_DEBUG - ULOGGER_DEBUG("Plot=\"%s\" removing curve=\"%s\"", this->objectName().toStdString().c_str(), curve?curve->name().toStdString().c_str():""); -#endif - if(iter!=_curves.end()) - { - UPlotCurve * c = *iter; - c->detach(this); - _curves.erase(iter); - _legend->remove(c); - if(!qobject_cast(c)) - { - // transfer update connection to next curve - for(int i=_curves.size()-1; i>=0; --i) - { - if(!qobject_cast(_curves.at(i))) - { - connect(_curves.at(i), SIGNAL(dataChanged(const UPlotCurve *)), this, SLOT(updateAxis())); - break; - } - } - } - - if(c->parent() == this) - { - delete c; - } - // Update axis - updateAxis(); - } -} - -void UPlot::showCurve(const UPlotCurve * curve, bool shown) -{ - QList::iterator iter = qFind(_curves.begin(), _curves.end(), curve); - if(iter!=_curves.end()) - { - UPlotCurve * value = *iter; - if(value->isVisible() != shown) - { - value->setVisible(shown); - this->updateAxis(); - } - } -} diff --git a/find-object/src/utilite/UPlot.h b/find-object/src/utilite/UPlot.h deleted file mode 100644 index c5bc444b..00000000 --- a/find-object/src/utilite/UPlot.h +++ /dev/null @@ -1,596 +0,0 @@ -// Taken from UtiLite library r186 [www.utilite.googlecode.com] - -/* -* utilite is a cross-platform library with -* useful utilities for fast and small developing. -* Copyright (C) 2010 Mathieu Labbe -* -* utilite is free library: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* utilite is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this program. If not, see . -*/ - -#ifndef UPLOT_H_ -#define UPLOT_H_ - -//#include "utilite/UtiLiteExp.h" // DLL export/import defines - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class QGraphicsView; -class QGraphicsScene; -class QGraphicsItem; -class QFormLayout; - -/** - * UPlotItem is a QGraphicsEllipseItem and can be inherited to do custom behaviors - * on an hoverEnterEvent() for example. - */ -class UPlotItem : public QGraphicsEllipseItem -{ -public: - /** - * Constructor 1. - */ - UPlotItem(qreal dataX, qreal dataY, qreal width=2); - /** - * Constructor 2. - */ - UPlotItem(const QPointF & data, qreal width=2); - virtual ~UPlotItem(); - -public: - void setNextItem(UPlotItem * nextItem); - void setPreviousItem(UPlotItem * previousItem); - void setData(const QPointF & data); - - UPlotItem * nextItem() const {return _nextItem;} - UPlotItem * previousItem() const {return _previousItem;}; - const QPointF & data() const {return _data;} - -protected: - virtual void hoverEnterEvent(QGraphicsSceneHoverEvent * event); - virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent * event); - virtual void focusInEvent(QFocusEvent * event); - virtual void focusOutEvent(QFocusEvent * event); - virtual void keyReleaseEvent(QKeyEvent * keyEvent); - - virtual void showDescription(bool shown); - -private: - QPointF _data; - QGraphicsTextItem * _text; - UPlotItem * _previousItem; - UPlotItem * _nextItem; -}; - -class UPlot; - -/** - * UPlotCurve is a curve used to hold data shown in a UPlot. - */ -class UPlotCurve : public QObject -{ - Q_OBJECT - -public: - /** - * Constructor 1 - */ - UPlotCurve(const QString & name, QObject * parent = 0); - /** - * Constructor 2 - */ - UPlotCurve(const QString & name, const QVector data, QObject * parent = 0); - /** - * Constructor 3 - */ - UPlotCurve(const QString & name, const QVector & x, const QVector & y, QObject * parent = 0); - virtual ~UPlotCurve(); - - /** - * Get pen. - */ - const QPen & pen() const {return _pen;} - /** - * Get brush. - */ - const QBrush & brush() const {return _brush;} - - /** - * Set pen. - */ - void setPen(const QPen & pen); - /** - * Set brush. - */ - void setBrush(const QBrush & brush); - - /** - * Get name. - */ - QString name() const {return _name;} - /** - * Get the number of items in the curve (dot + line items). - */ - int itemsSize() const; - QPointF getItemData(int index); - bool isVisible() const {return _visible;} - void setData(QVector & data); // take the ownership - void setData(const QVector & x, const QVector & y); - void setData(const std::vector & x, const std::vector & y); - void setData(const QVector & y); - void setData(const std::vector & y); - void getData(QVector & x, QVector & y) const; // only call in Qt MainThread - void draw(QPainter * painter); - -public Q_SLOTS: - /** - * - * Clear curve's values. - */ - virtual void clear(); - /** - * - * Show or hide the curve. - */ - void setVisible(bool visible); - /** - * - * Set increment of the x values (when auto-increment is used). - */ - void setXIncrement(float increment); - /** - * - * Set starting x value (when auto-increment is used). - */ - void setXStart(float val); - /** - * - * Add a single value, using a custom UPlotItem. - */ - void addValue(UPlotItem * data); // take the ownership - /** - * - * Add a single value y, x is auto-incremented by the increment set with setXIncrement(). - * @see setXStart() - */ - void addValue(float y); - /** - * - * Add a single value y at x. - */ - void addValue(float x, float y); - /** - * - * For convenience... - * Add a single value y, x is auto-incremented by the increment set with setXIncrement(). - * @see setXStart() - */ - void addValue(const QString & y); - /** - * - * For convenience... - * Add multiple values, using custom UPlotItem. - */ - void addValues(QVector & data); // take the ownership - /** - * - * Add multiple values y at x. Vectors must have the same size. - */ - void addValues(const QVector & xs, const QVector & ys); - /** - * - * Add multiple values y, x is auto-incremented by the increment set with setXIncrement(). - * @see setXStart() - */ - void addValues(const QVector & ys); - void addValues(const QVector & ys); // for convenience - /** - * - * Add multiple values y, x is auto-incremented by the increment set with setXIncrement(). - * @see setXStart() - */ - void addValues(const std::vector & ys); // for convenience - void addValues(const std::vector & ys); // for convenience - -Q_SIGNALS: - /** - * - * emitted when data is changed. - */ - void dataChanged(const UPlotCurve *); - -protected: - friend class UPlot; - void attach(UPlot * plot); - void detach(UPlot * plot); - void updateMinMax(); - const QVector & getMinMax() const {return _minMax;} - int removeItem(int index); - void _addValue(UPlotItem * data);; - virtual bool isMinMaxValid() const {return _minMax.size();} - virtual void update(float scaleX, float scaleY, float offsetX, float offsetY, float xDir, float yDir, bool allDataKept); - QList _items; - UPlot * _plot; - -private: - void removeItem(UPlotItem * item); - -private: - QString _name; - QPen _pen; - QBrush _brush; - float _xIncrement; - float _xStart; - bool _visible; - bool _valuesShown; - QVector _minMax; // minX, maxX, minY, maxY -}; - - -/** - * A special UPlotCurve that shows as a line at the specified value, spanning all the UPlot. - */ -class UPlotCurveThreshold : public UPlotCurve -{ - Q_OBJECT - -public: - /** - * Constructor. - */ - UPlotCurveThreshold(const QString & name, float thesholdValue, Qt::Orientation orientation = Qt::Horizontal, QObject * parent = 0); - virtual ~UPlotCurveThreshold(); - -public Q_SLOTS: - /** - * Set threshold value. - */ - void setThreshold(float threshold); - /** - * Set orientation (Qt::Horizontal or Qt::Vertical). - */ - void setOrientation(Qt::Orientation orientation); - -protected: - friend class UPlot; - virtual void update(float scaleX, float scaleY, float offsetX, float offsetY, float xDir, float yDir, bool allDataKept); - virtual bool isMinMaxValid() const {return false;} - -private: - Qt::Orientation _orientation; -}; - -/** - * The UPlot axis object. - */ -class UPlotAxis : public QWidget -{ -public: - /** - * Constructor. - */ - UPlotAxis(Qt::Orientation orientation = Qt::Horizontal, float min=0, float max=1, QWidget * parent = 0); - virtual ~UPlotAxis(); - -public: - /** - * Set axis minimum and maximum values, compute the resulting - * intervals depending on the size of the axis. - */ - void setAxis(float & min, float & max); - /** - * Size of the border between the first line and the beginning of the widget. - */ - int border() const {return _border;} - /** - * Interval step value. - */ - int step() const {return _step;} - /** - * Number of intervals. - */ - int count() const {return _count;} - /** - * Reverse the axis (for vertical :bottom->up, for horizontal :right->left) - */ - void setReversed(bool reversed); // Vertical :bottom->up, horizontal :right->left - -protected: - virtual void paintEvent(QPaintEvent * event); - -private: - Qt::Orientation _orientation; - float _min; - float _max; - int _count; - int _step; - bool _reversed; - int _gradMaxDigits; - int _border; -}; - - -/** - * The UPlot legend item. Used internally by UPlot. - */ -class UPlotLegendItem : public QPushButton -{ - Q_OBJECT - -public: - /** - * Constructor. - */ - UPlotLegendItem(const UPlotCurve * curve, QWidget * parent = 0); - virtual ~UPlotLegendItem(); - const UPlotCurve * curve() const {return _curve;} - -Q_SIGNALS: - void legendItemRemoved(const UPlotCurve *); - -protected: - virtual void contextMenuEvent(QContextMenuEvent * event); - -private: - const UPlotCurve * _curve; - QMenu * _menu; - QAction * _aChangeText; - QAction * _aResetText; - QAction * _aRemoveCurve; - QAction * _aCopyToClipboard; -}; - -/** - * The UPlot legend. Used internally by UPlot. - */ -class UPlotLegend : public QWidget -{ - Q_OBJECT - -public: - /** - * Constructor. - */ - UPlotLegend(QWidget * parent = 0); - virtual ~UPlotLegend(); - - void setFlat(bool on); - bool isFlat() const {return _flat;} - void addItem(const UPlotCurve * curve); - QPixmap createSymbol(const QPen & pen, const QBrush & brush); - bool remove(const UPlotCurve * curve); - -public Q_SLOTS: - void removeLegendItem(const UPlotCurve * curve); - -Q_SIGNALS: - void legendItemRemoved(const UPlotCurve * curve); - void legendItemToggled(const UPlotCurve * curve, bool toggled); - -protected: - virtual void contextMenuEvent(QContextMenuEvent * event); - -private Q_SLOTS: - void redirectToggled(bool); - -private: - bool _flat; - QMenu * _menu; - QAction * _aUseFlatButtons; -}; - - -/** - * Orientable QLabel. Inherit QLabel and let you to specify the orientation. - */ -class UOrientableLabel : public QLabel -{ - Q_OBJECT - -public: - /** - * Constructor. - */ - UOrientableLabel(const QString & text, Qt::Orientation orientation = Qt::Horizontal, QWidget * parent = 0); - virtual ~UOrientableLabel(); - /** - * Get orientation. - */ - Qt::Orientation orientation() const {return _orientation;} - /** - * Set orientation (Qt::Vertical or Qt::Horizontal). - */ - void setOrientation(Qt::Orientation orientation); - QSize sizeHint() const; - QSize minimumSizeHint() const; -protected: - virtual void paintEvent(QPaintEvent* event); -private: - Qt::Orientation _orientation; -}; - -/** - * UPlot is a QWidget to create a plot like MATLAB, and - * incrementally add new values like a scope using Qt signals/slots. - * Many customizations can be done at runtime with the right-click menu. - * @image html UPlot.gif - * @image html UPlotMenu.png - * - * Example: - * @code - * #include "utilite/UPlot.h" - * #include - * - * int main(int argc, char * argv[]) - * { - * QApplication app(argc, argv); - * UPlot plot; - * UPlotCurve * curve = plot.addCurve("My curve"); - * float y[10] = {0, 1, 2, 3, -3, -2, -1, 0, 1, 2}; - * curve->addValues(std::vector(y, y+10)); - * plot.showGrid(true); - * plot.setGraphicsView(true); - * plot.show(); - * app.exec(); - * return 0; - * } - * @endcode - * @image html SimplePlot.tiff - * - * - */ -class UPlot : public QWidget -{ - Q_OBJECT - -public: - /** - * Constructor. - */ - UPlot(QWidget * parent = 0); - virtual ~UPlot(); - - /** - * Add a curve. The returned curve doesn't need to be deallocated (UPlot keeps the ownership). - */ - UPlotCurve * addCurve(const QString & curveName, const QColor & color = QColor()); - /** - * Add a curve. Ownership is transferred to UPlot if ownershipTransferred=true. - */ - bool addCurve(UPlotCurve * curve, bool ownershipTransferred = true); - /** - * Get all curve names. - */ - QStringList curveNames(); - bool contains(const QString & curveName); - void removeCurves(); - /** - * Add a threshold to the plot. - */ - UPlotCurveThreshold * addThreshold(const QString & name, float value, Qt::Orientation orientation = Qt::Horizontal); - QString title() const {return this->objectName();} - QPen getRandomPenColored(); - void showLegend(bool shown); - void showGrid(bool shown); - void showRefreshRate(bool shown); - void keepAllData(bool kept); - void showXAxis(bool shown) {_horizontalAxis->setVisible(shown);} - void showYAxis(bool shown) {_verticalAxis->setVisible(shown);} - void setVariableXAxis() {_fixedAxis[0] = false;} - void setVariableYAxis() {_fixedAxis[1] = false;} - void setFixedXAxis(float x1, float x2); - void setFixedYAxis(float y1, float y2); - void setMaxVisibleItems(int maxVisibleItems); - void setTitle(const QString & text); - void setXLabel(const QString & text); - void setYLabel(const QString & text, Qt::Orientation orientation = Qt::Vertical); - void setWorkingDirectory(const QString & workingDirectory); - void setGraphicsView(bool on); - QRectF sceneRect() const; - -public Q_SLOTS: - /** - * - * Remove a curve. If UPlot is the parent of the curve, the curve is deleted. - */ - void removeCurve(const UPlotCurve * curve); - void showCurve(const UPlotCurve * curve, bool shown); - void updateAxis(); //reset axis and recompute it with all curves minMax - /** - * - * Clear all curves' data. - */ - void clearData(); - -private Q_SLOTS: - void captureScreen(); - void updateAxis(const UPlotCurve * curve); - -protected: - virtual void contextMenuEvent(QContextMenuEvent * event); - virtual void paintEvent(QPaintEvent * event); - virtual void resizeEvent(QResizeEvent * event); - -private: - friend class UPlotCurve; - void addItem(QGraphicsItem * item); - -private: - void replot(QPainter * painter); - bool updateAxis(float x, float y); - bool updateAxis(float x1, float x2, float y1, float y2); - void setupUi(); - void createActions(); - void createMenus(); - void selectScreenCaptureFormat(); - -private: - UPlotLegend * _legend; - QGraphicsView * _view; - QGraphicsItem * _sceneRoot; - QWidget * _graphicsViewHolder; - float _axisMaximums[4]; // {x1->x2, y1->y2} - bool _axisMaximumsSet[4]; // {x1->x2, y1->y2} - bool _fixedAxis[2]; - UPlotAxis * _verticalAxis; - UPlotAxis * _horizontalAxis; - int _penStyleCount; - int _maxVisibleItems; - QList hGridLines; - QList vGridLines; - QList _curves; - QLabel * _title; - QLabel * _xLabel; - UOrientableLabel * _yLabel; - QLabel * _refreshRate; - QString _workingDirectory; - QTime _refreshIntervalTime; - int _lowestRefreshRate; - QTime _refreshStartTime; - QString _autoScreenCaptureFormat; - - QMenu * _menu; - QAction * _aShowLegend; - QAction * _aShowGrid; - QAction * _aKeepAllData; - QAction * _aLimit0; - QAction * _aLimit10; - QAction * _aLimit50; - QAction * _aLimit100; - QAction * _aLimit500; - QAction * _aLimit1000; - QAction * _aLimitCustom; - QAction * _aAddVerticalLine; - QAction * _aAddHorizontalLine; - QAction * _aChangeTitle; - QAction * _aChangeXLabel; - QAction * _aChangeYLabel; - QAction * _aYLabelVertical; - QAction * _aShowRefreshRate; - QAction * _aSaveFigure; - QAction * _aAutoScreenCapture; - QAction * _aClearData; - QAction * _aGraphicsView; -}; - -#endif /* UPLOT_H_ */ diff --git a/find-object/src/utilite/UStl.h b/find-object/src/utilite/UStl.h deleted file mode 100644 index ceccb6fc..00000000 --- a/find-object/src/utilite/UStl.h +++ /dev/null @@ -1,593 +0,0 @@ -// Taken from UtiLite library r185 [www.utilite.googlecode.com] - -/* -* utilite is a cross-platform library with -* useful utilities for fast and small developing. -* Copyright (C) 2010 Mathieu Labbe -* -* utilite is free library: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* utilite is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this program. If not, see . -*/ - -#ifndef USTL_H -#define USTL_H - -#include -#include -#include -#include -#include -#include - -/** - * \file UStl.h - * \brief Wrappers of STL for convenient functions. - * - * All functions you will find here are here - * for the use of STL in a more convenient way. - */ - - -/** - * Get unique keys from a std::multimap. - * @param mm the multimap - * @return the list which contains unique keys - */ -template -inline std::list uUniqueKeys(const std::multimap & mm) -{ - std::list l; - typename std::list::reverse_iterator lastValue; - for(typename std::multimap::const_iterator iter = mm.begin(); iter!=mm.end(); ++iter) - { - if(iter == mm.begin() || (iter != mm.begin() && *lastValue != iter->first)) - { - l.push_back(iter->first); - lastValue = l.rbegin(); - } - } - return l; -} - -/** - * Get all keys from a std::multimap. - * @param mm the multimap - * @return the list which contains all keys (may contains duplicated keys) - */ -template -inline std::list uKeys(const std::multimap & mm) -{ - std::list l; - for(typename std::multimap::const_iterator iter = mm.begin(); iter!=mm.end(); ++iter) - { - l.push_back(iter->first); - } - return l; -} - -/** - * Get all values from a std::multimap. - * @param mm the multimap - * @return the list which contains all values (contains values from duplicated keys) - */ -template -inline std::list uValues(const std::multimap & mm) -{ - std::list l; - for(typename std::multimap::const_iterator iter = mm.begin(); iter!=mm.end(); ++iter) - { - l.push_back(iter->second); - } - return l; -} - -/** - * Get values for a specified key from a std::multimap. - * @param mm the multimap - * @param key the key - * @return the list which contains the values of the key - */ -template -inline std::list uValues(const std::multimap & mm, const K & key) -{ - std::list l; - std::pair::const_iterator, typename std::multimap::const_iterator> range; - range = mm.equal_range(key); - for(typename std::multimap::const_iterator iter = range.first; iter!=range.second; ++iter) - { - l.push_back(iter->second); - } - return l; -} - -/** - * Get all keys from a std::map. - * @param m the map - * @return the vector of keys - */ -template -inline std::vector uKeys(const std::map & m) -{ - std::vector v(m.size()); - int i=0; - for(typename std::map::const_iterator iter = m.begin(); iter!=m.end(); ++iter) - { - v[i] = iter->first; - ++i; - } - return v; -} - -/** - * Get all keys from a std::map. - * @param m the map - * @return the list of keys - */ -template -inline std::list uKeysList(const std::map & m) -{ - std::list l; - for(typename std::map::const_iterator iter = m.begin(); iter!=m.end(); ++iter) - { - l.push_back(iter->first); - } - return l; -} - -/** - * Get all keys from a std::map. - * @param m the map - * @return the set of keys - */ -template -inline std::set uKeysSet(const std::map & m) -{ - std::set s; - int i=0; - for(typename std::map::const_iterator iter = m.begin(); iter!=m.end(); ++iter) - { - s.insert(s.end(), iter->first); - ++i; - } - return s; -} - -/** - * Get all values from a std::map. - * @param m the map - * @return the vector of values - */ -template -inline std::vector uValues(const std::map & m) -{ - std::vector v(m.size()); - int i=0; - for(typename std::map::const_iterator iter = m.begin(); iter!=m.end(); ++iter) - { - v[i] = iter->second; - ++i; - } - return v; -} - -/** - * Get all values from a std::map. - * @param m the map - * @return the list of values - */ -template -inline std::list uValuesList(const std::map & m) -{ - std::list l; - for(typename std::map::const_iterator iter = m.begin(); iter!=m.end(); ++iter) - { - l.push_back(iter->second); - } - return l; -} - -/** - * Get the value of a specified key from a std::map. - * @param m the map - * @param key the key - * @param defaultValue the default value used if the key is not found - * @return the value - */ -template -inline V uValue(const std::map & m, const K & key, const V & defaultValue = V()) -{ - V v = defaultValue; - typename std::map::const_iterator i = m.find(key); - if(i != m.end()) - { - v = i->second; - } - return v; -} - -/** - * Get the value of a specified key from a std::map. This will - * remove the value from the map; - * @param m the map - * @param key the key - * @param defaultValue the default value used if the key is not found - * @return the value - */ -template -inline V uTake(std::map & m, const K & key, const V & defaultValue = V()) -{ - V v; - typename std::map::iterator i = m.find(key); - if(i != m.end()) - { - v = i->second; - m.erase(i); - } - else - { - v = defaultValue; - } - return v; -} - -/** - * Get the iterator at a specified position in a std::list. If the position - * is out of range, the result is the end iterator of the list. - * @param list the list - * @param pos the index position in the list - * @return the iterator at the specified index - */ -template -inline typename std::list::iterator uIteratorAt(std::list & list, const unsigned int & pos) -{ - typename std::list::iterator iter = list.begin(); - for(unsigned int i = 0; i -inline typename std::list::const_iterator uIteratorAt(const std::list & list, const unsigned int & pos) -{ - typename std::list::const_iterator iter = list.begin(); - for(unsigned int i = 0; i -inline typename std::vector::iterator uIteratorAt(std::vector & v, const unsigned int & pos) -{ - return v.begin() + pos; -} - -/** - * Get the value at a specified position in a std::list. If the position - * is out of range, the result is undefined. - * @param list the list - * @param pos the index position in the list - * @return the value at the specified index - */ -template -inline V & uValueAt(std::list & list, const unsigned int & pos) -{ - typename std::list::iterator iter = uIteratorAt(list, pos); - return *iter; -} - -/** - * Get the value at a specified position in a std::list. If the position - * is out of range, the result is undefined. - * @param list the list - * @param pos the index position in the list - * @return the value at the specified index - */ -template -inline const V & uValueAt(const std::list & list, const unsigned int & pos) -{ - typename std::list::const_iterator iter = uIteratorAt(list, pos); - return *iter; -} - -/** - * Check if the list contains the specified value. - * @param list the list - * @param value the value - * @return true if the value is found in the list, otherwise false - */ -template -inline bool uContains(const std::list & list, const V & value) -{ - return std::find(list.begin(), list.end(), value) != list.end(); -} - -/** - * Check if the map contains the specified key. - * @param map the map - * @param key the key - * @return true if the value is found in the map, otherwise false - */ -template -inline bool uContains(const std::map & map, const K & key) -{ - return map.find(key) != map.end(); -} - -/** - * Check if the multimap contains the specified key. - * @param map the map - * @param key the key - * @return true if the value is found in the map, otherwise false - */ -template -inline bool uContains(const std::multimap & map, const K & key) -{ - return map.find(key) != map.end(); -} - -/** - * Insert an item in the map. Contrary to the insert in the STL, - * if the key already exists, the value will be replaced by the new one. - */ -template -inline void uInsert(std::map & map, const std::pair & pair) -{ - std::pair::iterator, bool> inserted = map.insert(pair); - if(inserted.second == false) - { - inserted.first->second = pair.second; - } -} - -/** - * Convert a std::list to a std::vector. - * @param list the list - * @return the vector - */ -template -inline std::vector uListToVector(const std::list & list) -{ - return std::vector(list.begin(), list.end()); -} - -/** - * Convert a std::vector to a std::list. - * @param v the vector - * @return the list - */ -template -inline std::list uVectorToList(const std::vector & v) -{ - return std::list(v.begin(), v.end()); -} - -/** - * Append a list to another list. - * @param list the list on which the other list will be appended - * @param newItems the list of items to be appended - */ -template -inline void uAppend(std::list & list, const std::list & newItems) -{ - list.insert(list.end(), newItems.begin(), newItems.end()); -} - -/** - * Get the index in the list of the specified value. S negative index is returned - * if the value is not found. - * @param list the list - * @param value the value - * @return the index of the value in the list - */ -template -inline int uIndexOf(const std::vector & list, const V & value) -{ - int index=-1; - int i=0; - for(typename std::vector::const_iterator iter = list.begin(); iter!=list.end(); ++iter) - { - if(*iter == value) - { - index = i; - break; - } - ++i; - } - return index; -} - -/** - * Split a string into multiple string around the specified separator. - * Example: - * @code - * std::list v = split("Hello the world!", ' '); - * @endcode - * The list v will contain {"Hello", "the", "world!"} - * @param str the string - * @param separator the separator character - * @return the list of strings - */ -inline std::list uSplit(const std::string & str, char separator = ' ') -{ - std::list v; - std::string buf; - for(unsigned int i=0; i= '0' && c <= '9') - */ -inline bool uIsDigit(const char c) -{ - return c >= '0' && c <= '9'; -} - -/** - * Split a string into number and character strings. - * Example: - * @code - * std::list v = uSplit("Hello 03 my 65 world!"); - * @endcode - * The list v will contain {"Hello ", "03", " my ", "65", " world!"} - * @param str the string - * @return the list of strings - */ -inline std::list uSplitNumChar(const std::string & str) -{ - std::list list; - std::string buf; - bool num = false; - for(unsigned int i=0; ib - */ -inline int uStrNumCmp(const std::string & a, const std::string & b) -{ - std::vector listA; - std::vector listB; - - listA = uListToVector(uSplitNumChar(a)); - listB = uListToVector(uSplitNumChar(b)); - - unsigned int i; - int result = 0; - for(i=0; i listA[i].size()) - { - result = -1; - } - else - { - result = listA[i].compare(listB[i]); - } - } - else if(uIsDigit(listA[i].at(0))) - { - result = -1; - } - else if(uIsDigit(listB[i].at(0))) - { - result = 1; - } - else - { - result = listA[i].compare(listB[i]); - } - - if(result != 0) - { - break; - } - } - - return result; -} - -#endif /* USTL_H */ diff --git a/find-object/tools/CMakeLists.txt b/find-object/tools/CMakeLists.txt deleted file mode 100644 index ebdc846d..00000000 --- a/find-object/tools/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -ADD_SUBDIRECTORY( tcpClient ) -ADD_SUBDIRECTORY( tcpImagesServer ) -ADD_SUBDIRECTORY( tcpRequest ) -ADD_SUBDIRECTORY( tcpService ) -IF(NONFREE) -ADD_SUBDIRECTORY( similarity ) -ENDIF(NONFREE) diff --git a/find-object/tools/similarity/CMakeLists.txt b/find-object/tools/similarity/CMakeLists.txt deleted file mode 100644 index 2c493835..00000000 --- a/find-object/tools/similarity/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ - - -SET(SRC_FILES - main.cpp -) - -SET(INCLUDE_DIRS - ${OpenCV_INCLUDE_DIRS} -) - -SET(LIBRARIES - ${OpenCV_LIBS} -) - -# Make sure the compiler can find include files from our library. -INCLUDE_DIRECTORIES(${INCLUDE_DIRS}) - -# Add binary called "similarity" that is built from the source file "main.cpp". -# The extension is automatically found. -ADD_EXECUTABLE(similarity ${SRC_FILES}) -TARGET_LINK_LIBRARIES(similarity ${LIBRARIES}) - -SET_TARGET_PROPERTIES( similarity - PROPERTIES OUTPUT_NAME ${PROJECT_PREFIX}-similarity) - -INSTALL(TARGETS similarity - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime - BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime) diff --git a/find-object/tools/similarity/main.cpp b/find-object/tools/similarity/main.cpp deleted file mode 100644 index aa307182..00000000 --- a/find-object/tools/similarity/main.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include -#include - -// OpenCV stuff -#include -#include -#include -#include // for homography -#include - -#ifdef HAVE_OPENCV_NONFREE - #if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >=4 - #include - #include - #endif -#endif -#ifdef HAVE_OPENCV_XFEATURES2D - #include - #include -#endif - -void showUsage() -{ - printf( - "\n" - "Return similarity between two images (the number of similar features between the images).\n" - "Usage :\n" - " ./find_object-similarity [option] object.png scene.png\n" - "Options: \n" - " -inliers return inliers percentage : inliers / (inliers + outliers)\n" - " -quiet don't show messages\n"); - - exit(-1); -} - -enum {mTotal, mInliers}; - -int main(int argc, char * argv[]) -{ - bool quiet = false; - int method = mTotal; //total matches - if(argc<3) - { - printf("Two images required!\n"); - showUsage(); - } - else if(argc>3) - { - for(int i=1; i objectKeypoints; - std::vector sceneKeypoints; - cv::Mat objectDescriptors; - cv::Mat sceneDescriptors; - -#if CV_MAJOR_VERSION < 3 - //////////////////////////// - // EXTRACT KEYPOINTS - //////////////////////////// - cv::SIFT sift; - sift.detect(objectImg, objectKeypoints); - sift.detect(sceneImg, sceneKeypoints); - - //////////////////////////// - // EXTRACT DESCRIPTORS - //////////////////////////// - sift.compute(objectImg, objectKeypoints, objectDescriptors); - sift.compute(sceneImg, sceneKeypoints, sceneDescriptors); -#else - //////////////////////////// - // EXTRACT KEYPOINTS - //////////////////////////// -#if (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11))) - cv::Ptr sift = cv::xfeatures2d::SIFT::create(); -#else - cv::Ptr sift = cv::SIFT::create(); -#endif - sift->detect(objectImg, objectKeypoints); - sift->detect(sceneImg, sceneKeypoints); - - //////////////////////////// - // EXTRACT DESCRIPTORS - //////////////////////////// - sift->compute(objectImg, objectKeypoints, objectDescriptors); - sift->compute(sceneImg, sceneKeypoints, sceneDescriptors); -#endif - //////////////////////////// - // NEAREST NEIGHBOR MATCHING USING FLANN LIBRARY (included in OpenCV) - //////////////////////////// - cv::Mat results; - cv::Mat dists; - std::vector > matches; - int k=2; // find the 2 nearest neighbors - - // Create Flann KDTree index - cv::flann::Index flannIndex(sceneDescriptors, cv::flann::KDTreeIndexParams(), cvflann::FLANN_DIST_EUCLIDEAN); - results = cv::Mat(objectDescriptors.rows, k, CV_32SC1); // Results index - dists = cv::Mat(objectDescriptors.rows, k, CV_32FC1); // Distance results are CV_32FC1 - - // search (nearest neighbor) - flannIndex.knnSearch(objectDescriptors, results, dists, k, cv::flann::SearchParams() ); - - //////////////////////////// - // PROCESS NEAREST NEIGHBOR RESULTS - //////////////////////////// - - // Find correspondences by NNDR (Nearest Neighbor Distance Ratio) - float nndrRatio = 0.6f; - std::vector mpts_1, mpts_2; // Used for homography - std::vector indexes_1, indexes_2; // Used for homography - std::vector outlier_mask; // Used for homography - // Check if this descriptor matches with those of the objects - - for(int i=0; i(i,0) <= nndrRatio * dists.at(i,1)) - { - mpts_1.push_back(objectKeypoints.at(i).pt); - indexes_1.push_back(i); - - mpts_2.push_back(sceneKeypoints.at(results.at(i,0)).pt); - indexes_2.push_back(results.at(i,0)); - } - } - - if(method == mInliers) - { - // FIND HOMOGRAPHY - unsigned int minInliers = 8; - if(mpts_1.size() >= minInliers) - { - cv::Mat H = findHomography(mpts_1, - mpts_2, - cv::RANSAC, - 1.0, - outlier_mask); - int inliers=0, outliers=0; - for(unsigned int k=0; k -#include -#include -#include - -TcpClient::TcpClient(QObject *parent) : - QTcpSocket(parent), - blockSize_(0) -{ - connect(this, SIGNAL(readyRead()), this, SLOT(readReceivedData())); - connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError))); - connect(this, SIGNAL(disconnected()), this, SLOT(connectionLost())); -} - -void TcpClient::readReceivedData() -{ - QDataStream in(this); - in.setVersion(QDataStream::Qt_4_0); - - if (blockSize_ == 0) - { - if (this->bytesAvailable() < (int)sizeof(quint16)) - { - return; - } - - in >> blockSize_; - } - - if (this->bytesAvailable() < blockSize_) - { - return; - } - - blockSize_ = 0; - - find_object::DetectionInfo info; - in >> info; - - printf("---\n"); - if(info.objDetected_.size() == 0) - { - printf("(%s) No objects detected.\n", - QTime::currentTime().toString("HH:mm:ss.zzz").toStdString().c_str()); - } - else - { - QMultiMap::const_iterator iterSizes = info.objDetectedSizes_.constBegin(); - for(QMultiMap::const_iterator iter=info.objDetected_.constBegin(); - iter!=info.objDetected_.constEnd(); - ++iter) - { - // get data - int id = (int)iter.key(); - float objectWidth = iterSizes.value().width(); - float objectHeight = iterSizes.value().height(); - - // Find corners Qt - QTransform qtHomography = iter.value(); - - QPointF qtTopLeft = qtHomography.map(QPointF(0,0)); - QPointF qtTopRight = qtHomography.map(QPointF(objectWidth,0)); - QPointF qtBottomLeft = qtHomography.map(QPointF(0,objectHeight)); - QPointF qtBottomRight = qtHomography.map(QPointF(objectWidth,objectHeight)); - - printf("(%s) Object %d detected, Qt corners at (%f,%f) (%f,%f) (%f,%f) (%f,%f)\n", - QTime::currentTime().toString("HH:mm:ss.zzz").toStdString().c_str(), - id, - qtTopLeft.x(), qtTopLeft.y(), - qtTopRight.x(), qtTopRight.y(), - qtBottomLeft.x(), qtBottomLeft.y(), - qtBottomRight.x(), qtBottomRight.y()); - - // Example with OpenCV - if(0) - { - // Find corners OpenCV - cv::Mat cvHomography(3, 3, CV_32F); - cvHomography.at(0,0) = qtHomography.m11(); - cvHomography.at(1,0) = qtHomography.m12(); - cvHomography.at(2,0) = qtHomography.m13(); - cvHomography.at(0,1) = qtHomography.m21(); - cvHomography.at(1,1) = qtHomography.m22(); - cvHomography.at(2,1) = qtHomography.m23(); - cvHomography.at(0,2) = qtHomography.m31(); - cvHomography.at(1,2) = qtHomography.m32(); - cvHomography.at(2,2) = qtHomography.m33(); - std::vector inPts, outPts; - inPts.push_back(cv::Point2f(0,0)); - inPts.push_back(cv::Point2f(objectWidth,0)); - inPts.push_back(cv::Point2f(0,objectHeight)); - inPts.push_back(cv::Point2f(objectWidth,objectHeight)); - cv::perspectiveTransform(inPts, outPts, cvHomography); - - printf("(%s) Object %d detected, CV corners at (%f,%f) (%f,%f) (%f,%f) (%f,%f)\n", - QTime::currentTime().toString("HH:mm:ss.zzz").toStdString().c_str(), - id, - outPts.at(0).x, outPts.at(0).y, - outPts.at(1).x, outPts.at(1).y, - outPts.at(2).x, outPts.at(2).y, - outPts.at(3).x, outPts.at(3).y); - } - - ++iterSizes; - } - } -} - -void TcpClient::displayError(QAbstractSocket::SocketError socketError) -{ - switch (socketError) - { - case QAbstractSocket::RemoteHostClosedError: - break; - case QAbstractSocket::HostNotFoundError: - printf("Tcp error: The host was not found. Please " - "check the host name and port settings.\n"); - break; - case QAbstractSocket::ConnectionRefusedError: - printf("The connection was refused by the peer. " - "Make sure Find-Object is running, " - "and check that the host name and port " - "settings are correct.\n"); - break; - default: - printf("The following error occurred: %s.\n", this->errorString().toStdString().c_str()); - break; - } -} - -void TcpClient::connectionLost() -{ - printf("Connection lost!\n"); -} - diff --git a/find-object/tools/tcpClient/TcpClient.h b/find-object/tools/tcpClient/TcpClient.h deleted file mode 100644 index 25871033..00000000 --- a/find-object/tools/tcpClient/TcpClient.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef TCPCLIENT_H_ -#define TCPCLIENT_H_ - -#include - -class TcpClient : public QTcpSocket -{ - Q_OBJECT; -public: - TcpClient(QObject * parent = 0); - -private Q_SLOTS: - void readReceivedData(); - void displayError(QAbstractSocket::SocketError socketError); - void connectionLost(); - -private: - quint16 blockSize_; -}; - -#endif /* TCPCLIENT_H_ */ diff --git a/find-object/tools/tcpClient/main.cpp b/find-object/tools/tcpClient/main.cpp deleted file mode 100644 index 736d4b6b..00000000 --- a/find-object/tools/tcpClient/main.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include -#include -#include "TcpClient.h" - -void showUsage() -{ - printf("\ntcpObjectsClient [hostname] port\n"); - exit(-1); -} - -int main(int argc, char * argv[]) -{ - if(argc < 2 || argc > 3) - { - showUsage(); - } - - QString ipAddress; - quint16 port = 0; - - if(argc == 2) - { - port = atoi(argv[1]); - } - else if(argc == 3) - { - ipAddress = argv[1]; - port = atoi(argv[2]); - } - - if(ipAddress.isEmpty()) - { - ipAddress = QHostAddress(QHostAddress::LocalHost).toString(); - } - - QCoreApplication app(argc, argv); - - printf("Connecting to \"%s:%d\"...\n", ipAddress.toStdString().c_str(), port); - - TcpClient client; - - client.connectToHost(ipAddress, port); - - if(client.waitForConnected()) - { - printf("Connecting to \"%s:%d\"... connected!\n", ipAddress.toStdString().c_str(), port); - app.exec(); - } - else - { - printf("Connecting to \"%s:%d\"... connection failed!\n", ipAddress.toStdString().c_str(), port); - } - - return 0; -} - diff --git a/find-object/tools/tcpImagesServer/CMakeLists.txt b/find-object/tools/tcpImagesServer/CMakeLists.txt deleted file mode 100644 index 043c7a0d..00000000 --- a/find-object/tools/tcpImagesServer/CMakeLists.txt +++ /dev/null @@ -1,50 +0,0 @@ - -SET(headers_ui - ImagesTcpServer.h -) - -IF(QT4_FOUND) - QT4_WRAP_CPP(moc_srcs ${headers_ui}) -ELSE() - QT5_WRAP_CPP(moc_srcs ${headers_ui}) -ENDIF() - -SET(SRC_FILES - ImagesTcpServer.cpp - main.cpp - ${moc_srcs} -) - -SET(INCLUDE_DIRS - ${CMAKE_CURRENT_SOURCE_DIR}/../../include - ${CMAKE_CURRENT_SOURCE_DIR} - ${OpenCV_INCLUDE_DIRS} -) - -IF(QT4_FOUND) - INCLUDE(${QT_USE_FILE}) -ENDIF(QT4_FOUND) - -SET(LIBRARIES - ${OpenCV_LIBS} - ${QT_LIBRARIES} -) - -# Make sure the compiler can find include files from our library. -INCLUDE_DIRECTORIES(${INCLUDE_DIRS}) - -# Add binary called "example" that is built from the source file "main.cpp". -# The extension is automatically found. -ADD_EXECUTABLE(tcpImagesServer ${SRC_FILES}) -TARGET_LINK_LIBRARIES(tcpImagesServer find_object ${LIBRARIES}) -IF(Qt5_FOUND) - QT5_USE_MODULES(tcpImagesServer Widgets Core Gui Network PrintSupport) -ENDIF(Qt5_FOUND) - -SET_TARGET_PROPERTIES( tcpImagesServer - PROPERTIES OUTPUT_NAME ${PROJECT_PREFIX}-tcpImagesServer) - -INSTALL(TARGETS tcpImagesServer - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime - BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime) - diff --git a/find-object/tools/tcpImagesServer/ImagesTcpServer.cpp b/find-object/tools/tcpImagesServer/ImagesTcpServer.cpp deleted file mode 100644 index 023eb87a..00000000 --- a/find-object/tools/tcpImagesServer/ImagesTcpServer.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#include "find_object/Settings.h" -#include "find_object/QtOpenCV.h" - -#include "ImagesTcpServer.h" - -#include -#include -#include - -ImagesTcpServer::ImagesTcpServer(float hz, const QString & path, QObject * parent) : - QTcpSocket(parent) -{ - // Set camera parameters - find_object::Settings::setCamera_4imageRate(hz); - find_object::Settings::setCamera_5mediaPath(path); - - connect(&camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(publishImage(const cv::Mat &))); - connect(this, SIGNAL(connected()), this, SLOT(startCamera())); -} - -QHostAddress ImagesTcpServer::getHostAddress() -{ - QHostAddress hostAddress; - - QList ipAddressesList = QNetworkInterface::allAddresses(); - // use the first non-localhost IPv4 address - for (int i = 0; i < ipAddressesList.size(); ++i) - { - if (ipAddressesList.at(i) != QHostAddress::LocalHost && ipAddressesList.at(i).toIPv4Address()) - { - hostAddress = ipAddressesList.at(i).toString(); - break; - } - } - - // if we did not find one, use IPv4 localhost - if (hostAddress.isNull()) - { - hostAddress = QHostAddress(QHostAddress::LocalHost); - } - - return hostAddress; -} - -void ImagesTcpServer::publishImage(const cv::Mat & image) -{ - if(image.empty()) - { - printf("No more images...\n"); - camera_.pause(); - Q_EMIT connectionLost(); - } - else - { - if(this->waitForConnected()) - { - std::vector buf; - cv::imencode(".png", image, buf); - - QByteArray block; - QDataStream out(&block, QIODevice::WriteOnly); - out.setVersion(QDataStream::Qt_4_0); - out << (quint64)0; - out.writeRawData((char*)buf.data(), (int)buf.size()); - out.device()->seek(0); - out << (quint64)(block.size() - sizeof(quint64)); - this->write(block); - - } - else - { - printf("Lost connection...\n"); - camera_.pause(); - Q_EMIT connectionLost(); - } - } -} - -void ImagesTcpServer::startCamera() -{ - if(!camera_.isRunning()) - { - printf("Start...\n"); - camera_.start(); - } -} diff --git a/find-object/tools/tcpImagesServer/ImagesTcpServer.h b/find-object/tools/tcpImagesServer/ImagesTcpServer.h deleted file mode 100644 index 6cc3f1e6..00000000 --- a/find-object/tools/tcpImagesServer/ImagesTcpServer.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef IMAGESTCPSERVER_H_ -#define IMAGESTCPSERVER_H_ - -#include "find_object/Camera.h" -#include - -class ImagesTcpServer : public QTcpSocket -{ - Q_OBJECT - -public: - static QHostAddress getHostAddress(); - -public: - ImagesTcpServer(float hz = 10.0f, const QString & path = "", QObject * parent = 0); - -private Q_SLOTS: - void startCamera(); - void publishImage(const cv::Mat & image); - -Q_SIGNALS: - void connectionLost(); - -private: - find_object::Camera camera_; -}; - -#endif /* TCPCLIENT_H_ */ diff --git a/find-object/tools/tcpImagesServer/main.cpp b/find-object/tools/tcpImagesServer/main.cpp deleted file mode 100644 index cf36c980..00000000 --- a/find-object/tools/tcpImagesServer/main.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include -#include -#include "ImagesTcpServer.h" - -void showUsage() -{ - printf("\ntcpImagesServer [options] port\n" - " Options:\n" - " --hz #.# Image rate (default 10 Hz).\n" - " --host #.#.#.# Set host address.\n" - " --path \"\" Set a path of a directory of images or a video file.\n"); - exit(-1); -} - -int main(int argc, char * argv[]) -{ - QString ipAddress; - float hz = 10.0f; - QString path; - - if(argc < 2) - { - showUsage(); - } - - for(int i=1; i -#include -#include -#include - -TcpResponse::TcpResponse(QObject *parent) : - QTcpSocket(parent), - blockSize_(0), - dataReceived_(false) -{ - connect(this, SIGNAL(readyRead()), this, SLOT(readReceivedData())); - connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError))); - connect(this, SIGNAL(disconnected()), this, SLOT(connectionLost())); -} - -void TcpResponse::readReceivedData() -{ - QDataStream in(this); - in.setVersion(QDataStream::Qt_4_0); - - if (blockSize_ == 0) - { - if (this->bytesAvailable() < (int)sizeof(quint16)) - { - return; - } - - in >> blockSize_; - } - - if (this->bytesAvailable() < blockSize_) - { - return; - } - - blockSize_ = 0; - - in >> info_; - - dataReceived_ = true; - Q_EMIT detectionReceived(); -} - -void TcpResponse::displayError(QAbstractSocket::SocketError socketError) -{ - switch (socketError) - { - case QAbstractSocket::RemoteHostClosedError: - break; - case QAbstractSocket::HostNotFoundError: - printf("Tcp error: The host was not found. Please " - "check the host name and port settings.\n"); - break; - case QAbstractSocket::ConnectionRefusedError: - printf("The connection was refused by the peer. " - "Make sure Find-Object is running, " - "and check that the host name and port " - "settings are correct.\n"); - break; - default: - printf("The following error occurred: %s.\n", this->errorString().toStdString().c_str()); - break; - } -} - -void TcpResponse::connectionLost() -{ - printf("Connection lost!\n"); -} - diff --git a/find-object/tools/tcpRequest/TcpResponse.h b/find-object/tools/tcpRequest/TcpResponse.h deleted file mode 100644 index 1db54363..00000000 --- a/find-object/tools/tcpRequest/TcpResponse.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef TCPRESPONSE_H_ -#define TCPRESPONSE_H_ - -#include "find_object/DetectionInfo.h" - -#include -#include -#include -#include - -class TcpResponse : public QTcpSocket -{ - Q_OBJECT; -public: - TcpResponse(QObject * parent = 0); - const find_object::DetectionInfo & info() const {return info_;} - bool dataReceived() const {return dataReceived_;} - -private Q_SLOTS: - void readReceivedData(); - void displayError(QAbstractSocket::SocketError socketError); - void connectionLost(); - -Q_SIGNALS: - void detectionReceived(); - -private: - quint16 blockSize_; - find_object::DetectionInfo info_; - bool dataReceived_; -}; - -#endif /* TCPCLIENT_H_ */ diff --git a/find-object/tools/tcpRequest/main.cpp b/find-object/tools/tcpRequest/main.cpp deleted file mode 100644 index 820f187c..00000000 --- a/find-object/tools/tcpRequest/main.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/* -Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Universite de Sherbrooke nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include -#include -#include -#include -#include -#include -#include "TcpResponse.h" -#include "find_object/JsonWriter.h" - -void showUsage() -{ - printf("\ntcpRequest [options] --scene image.png --out # --in #\n" - "\ntcpRequest [options] --scene image.png --port #\n" - " \"out\" is the port to which the image is sent.\n" - " \"in\" is the port from which the detection is received.\n" - " \"port\" is the bidirectional port from which the image is sent AND the detection is received.\n" - " Options:\n" - " --host #.#.#.# Set host address.\n" - " --json \"path\" Path to an output JSON file.\n" - " --help Show this help.\n"); - exit(-1); -} - -int main(int argc, char * argv[]) -{ - QString ipAddress; - QString scenePath; - QString jsonPath; - quint16 portOut = 0; - quint16 portIn = 0; - quint16 bidrectionalPort = 0; - - for(int i=1; i buf; - cv::imencode(".png", image, buf); - - QByteArray block; - QDataStream out(&block, QIODevice::WriteOnly); - out.setVersion(QDataStream::Qt_4_0); - out << (quint64)0; - if(bidrectionalPort) - { - out << (quint32)find_object::TcpServer::kDetectObject; - } - out.writeRawData((char*)buf.data(), (int)buf.size()); - out.device()->seek(0); - out << (quint64)(block.size() - sizeof(quint64)); - - qint64 bytes = requestPtr->write(block); - printf("Image published (%d bytes), waiting for response...\n", (int)bytes); - - QTime time; - time.start(); - - // wait for response - if(bidrectionalPort) - { - requestPtr->waitForBytesWritten(); - response.waitForReadyRead(); - } - else - { - app.exec(); - } - - if(response.dataReceived()) - { - printf("Response received! (%d ms)\n", time.elapsed()); - // print detected objects - if(response.info().objDetected_.size()) - { - QList ids = response.info().objDetected_.uniqueKeys(); - for(int i=0; i -#include -#include -#include -#include -#include -#include -#include - -void showUsage() -{ - printf("\ntcpService [options] port\n" - " Options:\n" - " --add \"image.png\" # Add object (file name + id). Set id=0\n" - " will make the server generating an id.\n" - " --remove # Remove object by ID.\n" - " --host #.#.#.# Set host address.\n" - " --help Show this help.\n" - " Examples:\n" - " Add: $ tcpService --add image.png 1 --host 127.0.0.1 4000\n" - " Remove: $ tcpService --remove 1 --host 127.0.0.1 4000\n"); - exit(-1); -} - -int main(int argc, char * argv[]) -{ - QString ipAddress; - QString fileName; - int addId = 0; - int removeId = -1; - quint16 port = 0; - - for(int i=1; i buf; - cv::imencode(".png", image, buf); - - out << (quint32)find_object::TcpServer::kAddObject; - out << addId; - out << fileName; - quint64 imageSize = buf.size(); - out << imageSize; - out.writeRawData((char*)buf.data(), (int)buf.size()); - printf("Add object %d \"%s\"\n", addId, fileName.toStdString().c_str()); - } - else if(removeId) - { - out << (quint32)find_object::TcpServer::kRemoveObject; - out << removeId; - printf("Remove object %d\n", removeId); - } - - out.device()->seek(0); - out << (quint64)(block.size() - sizeof(quint64)); - - qint64 bytes = request.write(block); - printf("Service published (%d bytes)!\n", (int)bytes); - request.waitForBytesWritten(); - request.waitForReadyRead(); - - return 0; -} - diff --git a/flann_based/.DS_Store b/flann_based/.DS_Store index ca95d332..fcf030f8 100644 Binary files a/flann_based/.DS_Store and b/flann_based/.DS_Store differ diff --git a/flann_based/stereo_image782.jpeg b/flann_based/stereo_image782.jpeg deleted file mode 100644 index b0c20f71..00000000 Binary files a/flann_based/stereo_image782.jpeg and /dev/null differ