From 13c51ae2a299219c1c38c720574b7259fc42ed4c Mon Sep 17 00:00:00 2001 From: apoorva Date: Fri, 3 Mar 2023 18:56:16 +0530 Subject: [PATCH] deleting find0object files --- find-object/.appveyor.yml | 55 - find-object/.cproject | 221 - find-object/.github/workflows/cmake.yml | 36 - find-object/.github/workflows/ros1.yml | 59 - find-object/.github/workflows/ros2.yml | 58 - find-object/.project | 79 - find-object/.travis.yml | 22 - find-object/CMakeLists.txt | 472 -- find-object/FindObjectConfig.cmake.in | 10 - find-object/FindObjectConfigVersion.cmake.in | 11 - find-object/LICENSE | 27 - find-object/README.md | 92 - find-object/Version.h.in | 44 - find-object/app/CMakeLists.txt | 164 - find-object/app/Find-Object.icns | Bin 278666 -> 0 bytes find-object/app/Find-Object.ico | Bin 72078 -> 0 bytes find-object/app/Find-Object.ifx | Bin 74719 -> 0 bytes find-object/app/Find-Object.rc | 1 - find-object/app/TcpServerPool.h | 127 - find-object/app/main.cpp | 685 --- find-object/bin/.gitignore | 8 - find-object/bin/box.png | Bin 50728 -> 0 bytes find-object/bin/box_in_scene.png | Bin 122490 -> 0 bytes find-object/bin/multi-objs/38.bmp | Bin 152694 -> 0 bytes find-object/bin/multi-objs/39.bmp | Bin 137954 -> 0 bytes find-object/bin/multi-scene.jpg | Bin 55822 -> 0 bytes find-object/build/.empty | 0 find-object/build/.gitignore | 4 - find-object/cmake_modules/FindTcmalloc.cmake | 34 - find-object/cmake_uninstall.cmake.in | 27 - find-object/example/CMakeLists.txt | 38 - find-object/example/main.cpp | 346 -- find-object/include/find_object/.gitignore | 1 - find-object/include/find_object/Camera.h | 81 - .../include/find_object/DetectionInfo.h | 164 - find-object/include/find_object/FindObject.h | 116 - .../include/find_object/FindObjectExp.h | 41 - find-object/include/find_object/Header.h | 56 - find-object/include/find_object/JsonWriter.h | 46 - find-object/include/find_object/MainWindow.h | 152 - find-object/include/find_object/ObjWidget.h | 151 - find-object/include/find_object/QtOpenCV.h | 54 - find-object/include/find_object/Settings.h | 404 -- find-object/include/find_object/TcpServer.h | 79 - .../include/find_object/utilite/UDestroyer.h | 77 - .../include/find_object/utilite/ULogger.h | 536 --- .../include/find_object/utilite/UMutex.h | 179 - .../include/find_object/utilite/UWin32.h | 62 - find-object/launch/ros1/find_object_2d.launch | 14 - find-object/launch/ros1/find_object_3d.launch | 35 - .../launch/ros1/find_object_3d_kinect2.launch | 24 - .../launch/ros1/find_object_3d_zed.launch | 23 - .../launch/ros2/find_object_2d.launch.py | 30 - .../launch/ros2/find_object_3d.launch.py | 42 - find-object/msg/DetectionInfo.msg | 12 - find-object/msg/ObjectsStamped.msg | 5 - find-object/package.xml | 53 - find-object/snap/snapcraft.yaml.in | 67 - find-object/src/AboutDialog.cpp | 58 - find-object/src/AboutDialog.h | 53 - find-object/src/AddObjectDialog.cpp | 461 -- find-object/src/AddObjectDialog.h | 91 - find-object/src/CMakeLists.txt | 281 -- find-object/src/Camera.cpp | 296 -- find-object/src/CameraTcpServer.cpp | 190 - find-object/src/CameraTcpServer.h | 68 - find-object/src/Compression.cpp | 79 - find-object/src/Compression.h | 20 - find-object/src/FindObject.cpp | 1829 ------- find-object/src/ImageDropWidget.cpp | 66 - find-object/src/ImageDropWidget.h | 34 - find-object/src/JsonWriter.cpp | 122 - find-object/src/KeypointItem.cpp | 137 - find-object/src/KeypointItem.h | 69 - find-object/src/MainWindow.cpp | 1709 ------- find-object/src/ObjSignature.h | 202 - find-object/src/ObjWidget.cpp | 830 ---- find-object/src/ParametersToolBox.cpp | 823 ---- find-object/src/ParametersToolBox.h | 78 - find-object/src/QtOpenCV.cpp | 159 - find-object/src/RectItem.cpp | 155 - find-object/src/RectItem.h | 69 - find-object/src/Settings.cpp | 1782 ------- find-object/src/TcpServer.cpp | 209 - find-object/src/Vocabulary.cpp | 534 --- find-object/src/Vocabulary.h | 67 - find-object/src/json/json-forwards.h | 249 - find-object/src/json/json.h | 1855 -------- find-object/src/json/jsoncpp.cpp | 4230 ----------------- find-object/src/resources.qrc | 8 - find-object/src/resources/Find-Object.png | Bin 33709 -> 0 bytes .../resources/TheWorkingGroup_video_pause.ico | Bin 32038 -> 0 bytes .../resources/TheWorkingGroup_video_play.ico | Bin 32038 -> 0 bytes .../resources/TheWorkingGroup_video_stop.ico | Bin 32038 -> 0 bytes find-object/src/ros1/CameraROS.cpp | 194 - find-object/src/ros1/CameraROS.h | 91 - find-object/src/ros1/FindObjectROS.cpp | 350 -- find-object/src/ros1/FindObjectROS.h | 71 - find-object/src/ros1/find_object_2d_node.cpp | 191 - .../src/ros1/print_objects_detected_node.cpp | 166 - find-object/src/ros1/tf_example_node.cpp | 114 - find-object/src/ros2/CameraROS.cpp | 188 - find-object/src/ros2/CameraROS.h | 93 - find-object/src/ros2/FindObjectROS.cpp | 366 -- find-object/src/ros2/FindObjectROS.h | 75 - find-object/src/ros2/find_object_2d_node.cpp | 217 - .../src/ros2/print_objects_detected_node.cpp | 183 - find-object/src/ros2/tf_example_node.cpp | 122 - find-object/src/rtabmap/PdfPlot.cpp | 161 - find-object/src/rtabmap/PdfPlot.h | 69 - .../src/superpoint_torch/SuperPoint.cc | 355 -- find-object/src/superpoint_torch/SuperPoint.h | 75 - find-object/src/ui/aboutDialog.ui | 265 -- find-object/src/ui/addObjectDialog.ui | 109 - find-object/src/ui/mainWindow.ui | 941 ---- find-object/src/utilite/UConversion.cpp | 326 -- find-object/src/utilite/UConversion.h | 253 - find-object/src/utilite/UDirectory.cpp | 372 -- find-object/src/utilite/UDirectory.h | 139 - find-object/src/utilite/UFile.cpp | 97 - find-object/src/utilite/UFile.h | 137 - find-object/src/utilite/ULogger.cpp | 591 --- find-object/src/utilite/UPlot.cpp | 2562 ---------- find-object/src/utilite/UPlot.h | 596 --- find-object/src/utilite/UStl.h | 593 --- find-object/tools/CMakeLists.txt | 7 - find-object/tools/similarity/CMakeLists.txt | 28 - find-object/tools/similarity/main.cpp | 219 - find-object/tools/tcpClient/CMakeLists.txt | 49 - find-object/tools/tcpClient/TcpClient.cpp | 164 - find-object/tools/tcpClient/TcpClient.h | 48 - find-object/tools/tcpClient/main.cpp | 83 - .../tools/tcpImagesServer/CMakeLists.txt | 50 - .../tools/tcpImagesServer/ImagesTcpServer.cpp | 112 - .../tools/tcpImagesServer/ImagesTcpServer.h | 55 - find-object/tools/tcpImagesServer/main.cpp | 129 - find-object/tools/tcpRequest/CMakeLists.txt | 51 - find-object/tools/tcpRequest/TcpResponse.cpp | 99 - find-object/tools/tcpRequest/TcpResponse.h | 60 - find-object/tools/tcpRequest/main.cpp | 300 -- find-object/tools/tcpService/CMakeLists.txt | 38 - find-object/tools/tcpService/main.cpp | 208 - flann_based/.DS_Store | Bin 6148 -> 8196 bytes flann_based/stereo_image782.jpeg | Bin 481791 -> 0 bytes 144 files changed, 33699 deletions(-) delete mode 100644 find-object/.appveyor.yml delete mode 100644 find-object/.cproject delete mode 100644 find-object/.github/workflows/cmake.yml delete mode 100644 find-object/.github/workflows/ros1.yml delete mode 100644 find-object/.github/workflows/ros2.yml delete mode 100644 find-object/.project delete mode 100644 find-object/.travis.yml delete mode 100644 find-object/CMakeLists.txt delete mode 100644 find-object/FindObjectConfig.cmake.in delete mode 100644 find-object/FindObjectConfigVersion.cmake.in delete mode 100644 find-object/LICENSE delete mode 100644 find-object/README.md delete mode 100644 find-object/Version.h.in delete mode 100644 find-object/app/CMakeLists.txt delete mode 100644 find-object/app/Find-Object.icns delete mode 100644 find-object/app/Find-Object.ico delete mode 100644 find-object/app/Find-Object.ifx delete mode 100644 find-object/app/Find-Object.rc delete mode 100644 find-object/app/TcpServerPool.h delete mode 100644 find-object/app/main.cpp delete mode 100644 find-object/bin/.gitignore delete mode 100644 find-object/bin/box.png delete mode 100644 find-object/bin/box_in_scene.png delete mode 100644 find-object/bin/multi-objs/38.bmp delete mode 100644 find-object/bin/multi-objs/39.bmp delete mode 100644 find-object/bin/multi-scene.jpg delete mode 100644 find-object/build/.empty delete mode 100644 find-object/build/.gitignore delete mode 100644 find-object/cmake_modules/FindTcmalloc.cmake delete mode 100644 find-object/cmake_uninstall.cmake.in delete mode 100644 find-object/example/CMakeLists.txt delete mode 100644 find-object/example/main.cpp delete mode 100644 find-object/include/find_object/.gitignore delete mode 100644 find-object/include/find_object/Camera.h delete mode 100644 find-object/include/find_object/DetectionInfo.h delete mode 100644 find-object/include/find_object/FindObject.h delete mode 100644 find-object/include/find_object/FindObjectExp.h delete mode 100644 find-object/include/find_object/Header.h delete mode 100644 find-object/include/find_object/JsonWriter.h delete mode 100644 find-object/include/find_object/MainWindow.h delete mode 100644 find-object/include/find_object/ObjWidget.h delete mode 100644 find-object/include/find_object/QtOpenCV.h delete mode 100644 find-object/include/find_object/Settings.h delete mode 100644 find-object/include/find_object/TcpServer.h delete mode 100644 find-object/include/find_object/utilite/UDestroyer.h delete mode 100644 find-object/include/find_object/utilite/ULogger.h delete mode 100644 find-object/include/find_object/utilite/UMutex.h delete mode 100644 find-object/include/find_object/utilite/UWin32.h delete mode 100644 find-object/launch/ros1/find_object_2d.launch delete mode 100644 find-object/launch/ros1/find_object_3d.launch delete mode 100644 find-object/launch/ros1/find_object_3d_kinect2.launch delete mode 100644 find-object/launch/ros1/find_object_3d_zed.launch delete mode 100644 find-object/launch/ros2/find_object_2d.launch.py delete mode 100644 find-object/launch/ros2/find_object_3d.launch.py delete mode 100644 find-object/msg/DetectionInfo.msg delete mode 100644 find-object/msg/ObjectsStamped.msg delete mode 100644 find-object/package.xml delete mode 100644 find-object/snap/snapcraft.yaml.in delete mode 100644 find-object/src/AboutDialog.cpp delete mode 100644 find-object/src/AboutDialog.h delete mode 100644 find-object/src/AddObjectDialog.cpp delete mode 100644 find-object/src/AddObjectDialog.h delete mode 100644 find-object/src/CMakeLists.txt delete mode 100644 find-object/src/Camera.cpp delete mode 100644 find-object/src/CameraTcpServer.cpp delete mode 100644 find-object/src/CameraTcpServer.h delete mode 100644 find-object/src/Compression.cpp delete mode 100644 find-object/src/Compression.h delete mode 100644 find-object/src/FindObject.cpp delete mode 100644 find-object/src/ImageDropWidget.cpp delete mode 100644 find-object/src/ImageDropWidget.h delete mode 100644 find-object/src/JsonWriter.cpp delete mode 100644 find-object/src/KeypointItem.cpp delete mode 100644 find-object/src/KeypointItem.h delete mode 100644 find-object/src/MainWindow.cpp delete mode 100644 find-object/src/ObjSignature.h delete mode 100644 find-object/src/ObjWidget.cpp delete mode 100644 find-object/src/ParametersToolBox.cpp delete mode 100644 find-object/src/ParametersToolBox.h delete mode 100644 find-object/src/QtOpenCV.cpp delete mode 100644 find-object/src/RectItem.cpp delete mode 100644 find-object/src/RectItem.h delete mode 100644 find-object/src/Settings.cpp delete mode 100644 find-object/src/TcpServer.cpp delete mode 100644 find-object/src/Vocabulary.cpp delete mode 100644 find-object/src/Vocabulary.h delete mode 100644 find-object/src/json/json-forwards.h delete mode 100644 find-object/src/json/json.h delete mode 100644 find-object/src/json/jsoncpp.cpp delete mode 100644 find-object/src/resources.qrc delete mode 100644 find-object/src/resources/Find-Object.png delete mode 100644 find-object/src/resources/TheWorkingGroup_video_pause.ico delete mode 100644 find-object/src/resources/TheWorkingGroup_video_play.ico delete mode 100644 find-object/src/resources/TheWorkingGroup_video_stop.ico delete mode 100644 find-object/src/ros1/CameraROS.cpp delete mode 100644 find-object/src/ros1/CameraROS.h delete mode 100644 find-object/src/ros1/FindObjectROS.cpp delete mode 100644 find-object/src/ros1/FindObjectROS.h delete mode 100644 find-object/src/ros1/find_object_2d_node.cpp delete mode 100644 find-object/src/ros1/print_objects_detected_node.cpp delete mode 100644 find-object/src/ros1/tf_example_node.cpp delete mode 100644 find-object/src/ros2/CameraROS.cpp delete mode 100644 find-object/src/ros2/CameraROS.h delete mode 100644 find-object/src/ros2/FindObjectROS.cpp delete mode 100644 find-object/src/ros2/FindObjectROS.h delete mode 100644 find-object/src/ros2/find_object_2d_node.cpp delete mode 100644 find-object/src/ros2/print_objects_detected_node.cpp delete mode 100644 find-object/src/ros2/tf_example_node.cpp delete mode 100644 find-object/src/rtabmap/PdfPlot.cpp delete mode 100644 find-object/src/rtabmap/PdfPlot.h delete mode 100644 find-object/src/superpoint_torch/SuperPoint.cc delete mode 100644 find-object/src/superpoint_torch/SuperPoint.h delete mode 100644 find-object/src/ui/aboutDialog.ui delete mode 100644 find-object/src/ui/addObjectDialog.ui delete mode 100644 find-object/src/ui/mainWindow.ui delete mode 100644 find-object/src/utilite/UConversion.cpp delete mode 100644 find-object/src/utilite/UConversion.h delete mode 100644 find-object/src/utilite/UDirectory.cpp delete mode 100644 find-object/src/utilite/UDirectory.h delete mode 100644 find-object/src/utilite/UFile.cpp delete mode 100644 find-object/src/utilite/UFile.h delete mode 100644 find-object/src/utilite/ULogger.cpp delete mode 100644 find-object/src/utilite/UPlot.cpp delete mode 100644 find-object/src/utilite/UPlot.h delete mode 100644 find-object/src/utilite/UStl.h delete mode 100644 find-object/tools/CMakeLists.txt delete mode 100644 find-object/tools/similarity/CMakeLists.txt delete mode 100644 find-object/tools/similarity/main.cpp delete mode 100644 find-object/tools/tcpClient/CMakeLists.txt delete mode 100644 find-object/tools/tcpClient/TcpClient.cpp delete mode 100644 find-object/tools/tcpClient/TcpClient.h delete mode 100644 find-object/tools/tcpClient/main.cpp delete mode 100644 find-object/tools/tcpImagesServer/CMakeLists.txt delete mode 100644 find-object/tools/tcpImagesServer/ImagesTcpServer.cpp delete mode 100644 find-object/tools/tcpImagesServer/ImagesTcpServer.h delete mode 100644 find-object/tools/tcpImagesServer/main.cpp delete mode 100644 find-object/tools/tcpRequest/CMakeLists.txt delete mode 100644 find-object/tools/tcpRequest/TcpResponse.cpp delete mode 100644 find-object/tools/tcpRequest/TcpResponse.h delete mode 100644 find-object/tools/tcpRequest/main.cpp delete mode 100644 find-object/tools/tcpService/CMakeLists.txt delete mode 100644 find-object/tools/tcpService/main.cpp delete mode 100644 flann_based/stereo_image782.jpeg 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 a0d1e74198338be6f9e4f1581a43bf6ff4929788..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 278666 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 z z@GW0k>-lA-0y3GD+hhF=Z9+?EM@+r8@UNVoWIrG4?Y<-sF;7fc5eB&?UB3@FnODao z4SRRH*ZuMhpjuNt-`8iFyhfJS~+ z)@K8uo!zZ&4@-!(Rk&khjY%`QQ;kDC?1m$+XJiX(|2tNQAkRPV16C?u+Nzg-boGZ6 zv2Uz1*u2U({3KXUuDYcItabpE-~mOqKlJ?wDu*l)V%uQ~pDmw9Sjtj6bpEZ?vas(X zdvl~p3@O>ONYL;QyP1dWYmb?tut44@8yWgZR2_{~_=O1b3Pun~G{HFC+av=gv-pW$ zq-AoiG%6&U`9?>=b;J{svT1T7WKhBoOmmoz^~=KXg6@}}NEexsGwy}b1}!*loQ153 zZkv7YITF&z{K#~ZQSNy{Q!vx?a6|~pQf67eIVv!YlL~*@f$QV5A>u&16Rb3bB($W_ zG+zuCY+KSrQVW%oX__yC4`H&%!6;mw+dP`S(3H)SCd($bjh{*dl&B2%c9E2WmcMsL zp@z_=P6!l*9Bu*Uj$Z)EI;#65kG-VTU#d2p_O!kob5&5?pIobdaYs=nQC^iVsNxe- z?gWPukrQ}=a}m9n*M{AxLm1CXgqx~DlpYY;;u}lE;X31V4~>)umD4ADeRL7h>fGT{g;Lt=vT9E~rCQ619(l%(@eeDccVcKm9_Hm0t zTF3$whyS)Aot7K%M-lqzcBRDA^9E~Y zt2FSa)NLq&qPOYMUh<^-bQv+~9ELL4hhQa;?Lp_FjkG$d#%K?x#bd)2h=k&jv1v)T zsWtx&0g%+LVfhupQbO-h=Z=i%t;{=*WG^_1@5eRoVt_SNl$+4J;1cAjMzhMA9;#TA zOlu)KI*^W>c9nameWSn}{-Vi7*W|ZwZgM?e=t!~+TUj4+*U~83oPi&tV^4WRb&f&i zyB*VD2QCzGt=+q8QD6VHoGIOsf3Mh^n(b*1UnUeyeEkr64!&knu^Xn;8l=6|2Nv)7 z_i$8oC!k|Qh!q^SiJ8MK9bI`BPp$B!n!&+1KDt^;$$P}E^T7|=36#nY6~ID%{|0lR zaUgD>q^%q1(CNkYk*&ui7$_V#Go+v#J)qTxyIK|kMI1htrQxw1MsY;^bMeIO7fl|8 zJkmMU6PHn?vIbggkOjq3BX+d37Wb@`v7{eJeDx$ShtA;M7VPeUi9f-w7n3I8OW;mO z3FZ=Jy#zC&@*e7Q-lX9hl{Cr*TnFRDD3Vvl3nB%M4{kaJvgtTtVM^Tnv`&6r9GP4m zEbYY!{ybG-^C)Bu*A?3_t@rDKi^y zA=%N5grN1P3Ak0tGt+KiM$VV8_o%^OE}jd`KyZyU@@`*E3!M_;_X#plOo&q|I8ntL zaESkxM@e#3kVo{JUpoQ?i$O`SZfs!R&y3R&v4K_nFt)2H56yvHLMX0?{N?x`082o$ zzoECr9qeGzrxG|Cz+&bov#&zTWZ*R(M#DM#0snvhZ5p8ZkJl2xMYjJn=0GtAx41^B zBJIQNB<6J!ii*UCIge!a{ejpxt<5S>!>XIuwFlXs|9YbNv9ijv)uVqY1JV8^`1-B} zJ{+QkWH9fCHH*K8O{W zVDT~#jfQ72EN?Bu&>vR5Kt3}{?4 zGbGVv+jE8MpGjyi-Yw|ZY7)_CuDkp$1;~U5@qfS_8pUa5buB0vD@H{|OdnD_Zp@%@ zVXPXH^~!0y4mbLin%aH{i`jfpFgk6ZH{5vXkZXOkd>~XVRGkkGt$)S!a52-qh5r|r zO$O&R_=l2zDci9<`F(Dd;Ow2^Fi%U&xr)i&T9)=HZj@C&0v!7GO-NFSK)^d8`lU$L zi`>8WZa?6X+x0d1$d10d_(?=N%k%450xtJKt!S$xF7;UU-WDK5p(RQc`X7OH?bbHW zDUE?HG)XQXSio+)g#R#YnsztjHbR#*_H-CAcDXN5aIqB--~lBGVEw_M16b3it9b7@ zwqhyvqj_f>?2kX9!Vj}U6w`U=_>NzJeehldJPo~~l-qf^iz=V3fR|fTL*F2bT63yJ z1(7Z5h5`whz|V*P#g+RjqA|O_4Eobuw|5d`hZx9@)nzDEf|C*0Di8kiB<~VdDg}#o zR;ji(@>lUe90MC12$SqcKXo%5ZLJG7(c|p8AtV)v{^wws`FIQ~k z8z%G;<@W??_B!IE%?MmxqaoDK04nRIyEvpBkcKUbA<+JXMtK)aCb>)626l4&6`nY7 zQ~O4YjOYi*va&TJ%qWX|iq50_){=i%r!HExks9DULupxPwv);#pY7&{qG)tCD@^RW zD^<%(>~2*KK!V*Q!8b(Dgz|8P@J|QskUp9;>SxnQZC@3iPI}MEq>pStaJ6jl?!}-K zSt{_@eLn7bwzxI>^9Iak=Lg4v4Bfhyz`S$i8(bmK4Du$pTl%*df{m4JBQU*?6F^pj<)9RzIh}*oV%{~Yg)q9Qc2#z| zc*zI_3*2D<4F3R5fTiF4l=WO6bXYF1)EY4*06PwO1W$r2ONk>Cj!N=^wdB$n2eWLV zyN$HU@%3PL&N5i)4RN@(iA9<0T! zm}_Z0O?Mr}J}gE3>0uhx;_I6_evR&T*)K;bS%e%dDczxp8P^(zHb_t&JbrhkS#INC z)Q858AFc8EP*<=erc6{&i*`H+tIM71ssPqTw%e2pi?9D~wo2P~!x|wST4;wM_2S;V z_8}8y@qnD@<0uTpQ-E+P=+Qzy_;Q{@A_NB%YSDwNB{D|uX{+BOm>osoT+Y&wbc|)P zED|cLBFiykBZ{XbE3g-)(?gVM8t?=8fdz}}2*=^KrkA)Vu1DpIFPD$KLdMNHSLYJeGWB_Svm0g=wn|Hij1aw-CYc zojM4b9_1{JXP*L8*~!~tohUlEqS#TvhVN5oA3}^x3}kUUKU!U{4l~HMIw=I5bFZGc zBCg72*e-X;5QN30-!!~A>rK{-LwLXVL>QO)pWWE5)sk`eT(8cCMJpEU^^iR)m6C%nN~8lWQ#6u{1H)n3d3x+i}9ONM@BfP8WjwFln zuEdJ1(#Er!R7x5M?m2A%hmkLw^7hhwkb=si9lU!)aC8+o z6g?(6gn1y4A`AE4mEn}JXJP_bZUWLrr4fibuId)t7b?L1vF}X*x;n2{m*}h`(i#~T zH((~e-wCe}Ep0%hRBq(#E3UhR=$WICbXlMxuthxrp?^JcRke7QR&s$jf}JHXN^%uB zlL0S-q|RpvF#uUUH3z4es_Z(d8)ilHvXNik$JP!WOU_Y8=WDCJ z6py^OupTp$H%C(cK$I#EYzFYwU{0j)z@?a&M2hEzlWu#Y9Jr08$J8791bRHkoS7Og z%oEM+d^Z_5Fb-cIcH<|DG(i; z4k7raXJ*tuKgVsq&Nu0hNSgO0D!@J2B*F1e7J5yM(%-)$0o5%Gxr-(sZNE-4fItvz3P^aGo)W?!y6o!@73`7kQK+*fKxLD^Rjy%5#V9x8Gwd z-jJ;tf%0Sp(fL5e9@)2gv}wzuE3uSX%ckFj!bRo@LPG0zbj8x04k+Gq35a{gjE{1xkPmU}!z&9!0 z;TMT9a3AKUJ~q&N=)4|1Y~!WFav0>GX9f3k1ati1Lx53ZOqSR&SRO~gSB=+;YI*8* z;|O+2>8>_2Ar!Cjn-Runk?XwM>VH(y_@_*{_~rY5&B7@Kx*;Av7p9vY7TwP73cqDbHj^gH z?R+7zSiYB-!Sj4)QhhnfO$#7z>6)qCXM&uXw0+5;T+`XkPrPGLuK{#=D{j~Ah3Ub` zBEe*$1X4Dy&30d##JbfUA`NSuCbcO}`YXBC*h28!)taqd^u*<7c%egJsP7b<8w%GxAp%P+J$YU-maEc{04S`>3{=BzE1xth!5zVMGa()11c)q4@ zcFdY6T`uC~_=vdQ10!zObYZ*Sl(Ym6H zAm|juDhR~d!>bq?ihOF!;hG(T<-`iQ={PXhm#vl0vb9KcmPU!>%$}5t%`FI7tSwj@ z8VRIk@sL*@e(8_l{moH#osRt(r}ZXQn~0RdJ_C4nvP!?zH6w~c+5KkJID;3pF&sJN zn)yNc5y!|(1bI41K3g7S56m|W&q9f*%9{enJu?u7v(8Q^3O%!_pA~cfBuv|dC&3%6 zH#a20M#tDS(1vV0Grwdn+K}j~-<&NO;?P|y&jr}^IRmjqGlc-$?S&)(+YX6G?_e8! z-X+?tUMxLBaupo0L|B}AP;XXbVa77(It)^zhOjq z)pc>^-JnO$0s^Z|!a=(o+j=c9a8{v#yk4KR|1{C%r^nzBM6_$(KTP~WkigPPtI^GD z25Lt8Gs7On$FQRns$k)Q+s%kVBr(8rx<*fvvPn2zynI}UHR)~dg*cHVsTM46&;ewT z){-$mC&_+{%~zyda*LKDU>G%GmiWJC-|O$`Q~7jHejNz^A4?kiI!(U*gnySsU(2N& ze*Tfae?q^%p-aT|z7|k5Uaq-8oBKxPN1+pSKDkX;ExX+`H`Er** z%DF?Rzfj_cz1V?L^5v%~au>>C69fd$(UjldSk-%kb9gw!%ENz_aMn7LNUB9yozUaj zU{139jY+;kYw}m8oUu@$BcF@pnOw{~7mJ#hJn}Ni<7;PT!Ot)iT53K~qlY6ce)o^Y zXK2`8>T#t{GRTA=oO&kwKjw1D{}4|+vbV?4*;kc|=Ol{+Uh`a1=Novn zKF2(Y&i17LB#b!|v^M}F(fVI#*k(ylw3|`Cu{fe`s8>bpJO5U31!M)9Hh!PK0n`B5 zg%GQo7RYRe29LUGv_a6}1<`rt^)trHq1k4s-Nna_i>ZLbEcJG-%NEf0YnX<{`{$r^twpWY{B+2MyQZY zeJ+QOK83?AO1cVsZ!dJYLm5K{?Ex{T;5|987l>EEcsQj2lMS6L9seIT7q6(!Hvd%* zIOE&iyEmDV=v7|ux3o|Bb9UM#N<&bw4$Em!RqdbD;`St9>d77=Z~5T1^wCQqs{BA;|7S{gV|j* zUMVUxRLHRHRTm+{G&+*-Ad3U8*<8rczJz)o^=XCuY16(iG>vkZn7$&N4!osT{{?bZ zXS2*V002C+c8QLhc?`$MhK{<9C&tE?BpfS$(K8QhX)AkFb(QyyWw?@uM|ZV${}N)U zh^^t}&dJybt!FA+_qr~BMp8c}*fCBzQFY1`SKNXA>qoY{0(7qklb38iY3ItNO|h3M zxJwVY3_s>Uf}qAtAi2-MTDOTme#$7??W+tP$_A30pDPs(%y7`;7ug2>^90`F{clu| zO8v3kCb#LPo?}>M%N!=@u&c~)iJ`!u$w>=<`Mg_-D=~-FF2jkAIs!o;#r>AiVlYKx zmeaF>g*h~_Ui-jC-}z7bnIVDot}b07*v0vd_Esd2s}SUw^2pTpAK_!XL@x%`5k`+c zmw0WHH)?`Nm%I-K;VG((>SX;>09yq%%Y!Zi4H{7JBCl#SlH@HK&i8P^Q@)2nBigU( z6pUg_rF2Nz(Iu#$e?xqcxdaEp4)9^l?rne(4;$!=tKj^BjFF)zJb%IC$N0pXZGPKk z6zRpp7l}+Nv3UY%tWt~i$N_iOl!gM#e2A=>vm518(QUY_MmJ7z=MeIr)*aXrV=agO zE7uCm{Gue*+u02f)hRV@p}*L;sB54WKg@_0p*!h};(Dcdx3ZO-b2AFs!hc!bAR037 zl(QFMt!$z{`R~sfqi=#dZnz~YH%uc?AsKP3xJDyYirw+9T=Sqsh+hZ4m!9F_E&-5C zMl&YY8mws!#1_7rqrr4RJ}Co)JqELUy%ofNgaQ7%d*AF*OalJ*Ug_;RA8`I$y#1e+E@MElrX}Uho|x$Hnfw_(j}qH%}_q;WuCo8ePjepu33{&YGeboix% zXZw(yhA3aQUGp{BQfMO0^@uEVRteJy#`dMq?J zW(>m#<>ruo$Ir1)RnQ>Xp(cA~QuxT?2q6v=M0+%ykYlYM>D}nXZj!~`;1^OQe7RR_ z1s28i^fkcV9|IL|8&WRP;sn}uaL8ibAt=A}GIk!>l`tV$BT%ORY>qIbadd3D=T~dP z7CV;(D$F0AL*xr_aOP2Q0Zc%tHD$9E$ss+vbVb_q&5y{q>28r+#R35yeUB61gg~>0 zaWOG@)1qy+<Zhi}G9 zZ?JCOXLQ1Pv0R6k(RhYii-VsEIn7P)yuRME8zMeS#2+Ak!OKcnbfDKMz#?|liyrjS ze^S#rAfZ55+*+rvP@82BNSXlQ@qs8~<;7Hb$g@ug@29K>vHH$hO`8QVr;SD@7^+4|AV3w%;kA2UD6U{Z~ZK0KF1EsF=;G zZ8Vx7DSN{=&aj6jN%x7kwe2YF5V>H`tAc`0m+DaUHi|b+OHAndE~51_1XlWzo7Zgl1yjg%xz{9S?r8fn4Ts1psMeJ1#@ z5mW?@X{CW{q(S2TE`)P*9*XfYn>eU5sC3_4LbG(+GzV{o1JQ2{``O5z$I)2RhIk=^ z-DNA09|nX!R2!t9=9t(VLG?(Fv&RKQkz02U zSqbC9`t?pYDN@HtHh+S8_d1_PI9mfsL{F|1^s$ygW7kZM8wLK_N$I0=4bwIro>NKT z&Cq4WpCTX&5XvSX*>F^0AO}NVK$3$!LvUg% zW)3%oh}AJRlP8wrhVVjuhOZ}HBj3f|Wksm-YYBnRn*T*kxeTlQDo^wKKe_`F$muvv z7@A01IzY-bt^L;VQBya|r4emN2Lh?S4irEew`Vb!)Nst3jwC;tj+viyB~v)Q-VT@cHmR&GPPmTE|_kNC1zmzDnG#; zlfFvoTZTQT$;ufYX{i-6Oxt0QJ`Bo{8r{%c)h5@ssa+TVH z_mOj!WrHzhB0RaIPk5>#a4>Rm68>5K$UGc#SY`rKxBN);Blc0Hph!s`%@?0*x*N(< zZt1zQ;U{d<@)B<+-eY2XZRuHf3Wh`Y5~X)!*Fg$R5zM^+dRk&bgj-QQi05GSJh%cK zgx+>6I=}}@G8f{0Oa&3C(tg1x5-r=sArua5Z*OBA|ZaRFgcW0lm zYKAecz8c08kZH7lC?$XqZ3W^IZ~IFHki*{yd)QXfs3}||P<`zFbg|&f8)z4@ zLVE<~Pw?^gKtn+h4d*@HApVa}Kxr%pu zNGNqQ|8A++63)g5uN5ctYQZT|n4Dk~j{dE~iBW5j&6_bT5i_ZGHrOM-dhN}-=0`9( zB{uxm^^6);NwH~{1>bGUeziD|kxI}eH@J2{_c939P}M?vDuZP!ZAv7GZ;gcT*xsQ6 zvd&Am+R$kVfB1t9M2cqjmZHnjZ45nWv{cz*o!Gd*v9!)((@o#BIJvyK8i%JmcSt09 zl;xqs5qsnuuLwqiAYqI@IX56|EqSX_RbB?Js=<_%4u`ik7q0&YlxOl;RE>&z9;k42 zQk?yyP#t~2DKTcv4M^aGKT9y(cF2IH_Hsp5)F6ikn?A2t&G{B?_26Gj&D$CVk|E?J zdPZC9{qP`YLFkTL%EDG3hUE_0=J&fqa~9bA5U0Um8!FuYoxE*EXzQUZHuTqja zM?kP94g7!*I6p%fak}1zXa0Sw+%tyVhz$f6255-oC6fX4{W1%lwB;m_a_Rj~nU-z- zlN4Q2Dj0rdgQ8x>=4*&s!syta=Ix=tl_3yod@6f6!w}Z=QW9zxVC?^Fha%S|C#epF zU;Ui3>0(^pLGzUM=3@ljr8 zWK^cT3+DF#WCB28KK&&NZcDewlfrM2z6dPz#m#V!Tm+XZihkqf85$ z!Dw-$!xB}5=Z6`eNVDH>@Xrxy??g4a1qie!}!FBb9$JJ5!T1O5_&#(mG2RQmU}> z&y={dr*v*D<6U6(NHf7K@ewgl!cwHj?vdcTt?q+J;5jFZ@+$sEeg@zk42Z!Gl8v#J zlccmlvrq1jSIv2p+(3`FvYSTAQ@a{wAq!48aa_P)X!d`*6cBAVh^xPvrmYoiCRV(W zyjO8K5mhURJM70lJ#W2H8rK$QR!%5#fg&z!!17h88+z&snBor7(J~3sERem9v&s;@ zI9B#)PpVFk;RL%h{PmU4V639Mw9FL@tBu-(Lrp3%b+8rTG{#Z0)UAu(0KGKy138H6 zKyEYl_tVM7IV`a=bC+tXI%Wr|GcyYUy%QA7r=~ETz|hN~pflIXOn>WCeolWV@?5G2 z?TW>XLJ3AOAzmCC&L~RQer|bSlFoHna?JRdvpb8Wzq_luvSCZ`y{d~k8JVMe$}uJP znQYb4lrLt`px3!$X>b1}_%_DyEk)8ZqBag!vyosKI0bUr5rKZ_IXV6az_-wRZmZDv zpaiUO0+lI|aIfD8oj=VoK>iFlD)s#?fYs7!m`5nU+$(iOF(Z?|$%0eV!f6z@p)Y21 zdu{Xwr;pBvA&oDUl3Ai{(klE-9=*8^*mY3i=o#qtrk5p~hV7!untW~My20u@rNOPG zAcx;m2CuirF`NR+{DOGGvZbAwUhM4OA~K@QBUS%#ZcCLEH$%QWgl8ZP@6Kh6jWKxg z`9?WLeE9gbid7wjv=wLsixI^OQMEYLH zQbpn!cHO?Rr*F&{aCJU*6Wae7b`*$kw0*4MgYc&jGs6k+Ti$o~-7>Q)zVsu(RpDse z6B`tM==bYdt7WoQ(awyyJsU6R%&B{xJ*ugHNR$I-CM6q#7Yf@yQ0ml0lI~x(Q zJ?DmZH`Q>b4ap#kdb7XI8m5XlDsafi-}PYd=0mseP?_=6ePJPRC(H*#eX(An@m+$O`l<A7m#ALv8JdS}OOPd^bxewgR zfABSaoSrs2w9nx=;`sxCx^Atm3j;NIu?3##LhTL4ng*rL*O``L{H`avP8EXj$;WEE57I~TIiwr7d~3W$Z@(x(NeI>n${ zjiB*?+z8Usks=RMu`mEfhuvh50|ytc$+z5iTm>OUFGheyca(WEi>C-(ZKXceQGYvX zT<1x}he3mp6BPn4X+w9f1&E@hE7HDkj`DRbpjZSKtwq>i@e(osa&}zG@U(WA$k?Qdual)G zL$Fh5e>-px*xl7Y{zo+3e>gEW3R5LI3a5E}HVeF80hmj*tmT(23b%QE&M}lvvSdAy z8}A|EaAt2 z>495rPI!zntW7n@0K_Whl+;}?a-$K9j_9M5!q|MI&&G>Jz>$J}t6A@oVtq`*HVwp>RsIR8jRL%{MDIKL2^T-FE^% zkpNqS5dsaq<%`F_zgt4!soCy~_re(>kmd{WiBH-MqKGbZ8UbS^$`AH)scMLC{c5n} zc3aRV>~@BxSn;OFA?@Oi51W9|2C)7Uo*DF1FB@L{4Th{nQ}7I24%r8Rb~i)P>##Sw zg1>U6ee_J^LD8mw#eBU2MhW8Rc8t)+FPnP^h_A)Jp^F#j%ClFv z1)5bfMZ4tDwKz=yxSS0FpOJ{Vr#QX=H9IV};aKhh7XH83a`aEW&w!Mdl<89p2)2(v zqr?!96wkRh=TD~sQOtpVanuoiE4t;gQhlBCQ4bgc4_vLegY7}R=m;E=Lcrat>v(pn2~x{RfGRkE9;KlA)LdHx*^|6$U{@aQA=?BDRU zKZfl7{mlPEZ2v;T@3&F^KVrX!K%c{>|8L)4;nWvD!>GUE()av2tNtAfe+{4h7gzA; z5BP1@{5Ko;T7CBFhw#`B;n8>S>&N(XFZ?>E=lS$qej9(^he03DbnnAX@4~^q4UPVK zv)_iO--Sufw?Z$&N`Ic`Ux!6^;j@3wqHyR=f1y~*B24IO#VD~=2n`&+Sj>bi0PAu` z{j9&HB3AH;TgEY>6SjMJ6^@9X*4F2Pjz$+6qRJh;7Fcsc0f)?oH4{&mT}rj}JnLE3 z)$q;2r60QvplnmX@E+RF^TAc;rYxTw!#>3lOAcMXR-{@06ko>!woA7p5}*;YsDQhz zdVM4h03v6yC_j~)ruN&GO0}Nr?($p<1EqfLB**vgZV64&ljv)G zO5M49>wRJ!*9tv}<-%wIT4j?I#lgO$L51Tj(b{VF61c*gf`Sp%7enG8Oy1_vD;#4U z@v3OSfOtv@Ej1Z))#Ps?QxbEl_}G*esHE*Y%v%O^)DbX|6SFNWR3k~~B~S{sN58KAY<8$9mT8B0vPHcSFS zEsC56&j~}WI>O8S+VNvdrhvE^9&kyG=(3G%&8afB7UN`p6{(5B?wD_q$^ zob=mV;scFY-XDIh4*k;-9NWtra*fTfr!l(8>jREBoPDV{MlrP`{LZif)Y>-_DhYxV z%ZDTHMS0-YghgLzD29vUbc;#!B;mccSg${hl4aA<2@9>NUnXFsvE3#c+!1-+h4H7M ztgvFxW;-uiqmfv0Hg!e2IV`Ypc0k1=%=pT{pk~RQn1WOEzo20)fgr>74~=uhmyD;{ z_Wt)$I@j^igg?q7Gf&!$coh_DjOh50Zb?r?wnYXVfteGBexS8%nVhD}MzrzrsZ+r~ zL@k7jkgZ@Tz#+m2jRjOD^@QmrB0H^QMhOJTGYK|4)1d+L+zfSJH9AZ>w;3dQJbrSS?gK*o&~3QmurR8@`3ad?4HLSBf+JRw zaCsDI@%Q!5-viNLaTvHE=5B{-uX9-}d#hez1P%fmTzL01mpaAhT=Q&G-^eLdbcsU234hI~H2UUFTg>@&UB*q@k%(0SKYT0|1>P+$MmZei6 zWC{Hxc#QXmTFHC?`BQK7thlGC99~==;#z-1R<^OyNdnQGk#bz6v0};%IB<4Cm2vSK z87~Eg|8)_uBuGmb?7-8R9ijk1J5>wqZX z{+y6-#b||+>ZYftEnxnDfysFyR%O`tciHRNu0In?alAKsiL6O9aULopg=a%IZUAg= zB>gD8$XQXP#VT9%k=o7v0FZocn3U;tMbKNb8X#}UDLf{9uq+3jW*(HWL4P-B&>C7F z_LOWd@BR`TIt{@0;`HfEd5)n|#8sMW^I?6cKiiPnazG-cJ2zUEjC&CCStp4ny{B=f zk&})~EqL7*$+jC%c}9^h^wzQ3_e0^ci`2)pXk>J*)&qMd4%txed-;;bfFC*9w(em} zzSDVnX{9afxqNrse@|_HtLxZIZ&+ZrbA?n7PQ0xmWJ0|gFx^rc|p=7U<>)?CRy!n*rNr55kq$dYg`}a8Fj{&pT6o95v zIMB+sF1ejvGqlb9iTMrud9W2Yh0;U=6M}|;SF5Q$JxmlkEnGc^X5cZ1{|PCUkcxjH z<%@=Owh@M(Y;%mel0!agQ2z@cZ;AsyE#ld3Ev-ujKM*;R{0hA`5nk2VCu<2?9tx8h z5&h!XD`wPX9YqnrGtD*%w8QHEPaIVV}l!cHG!QuS1$xzepm zd^yA&^omPvO-)II$0Mye2xjOhRc2UC<>oEb4Hq@!--@+g$iHtJ(tb zl-?=nXw)OyN(?#F2c6gx7qzLh%#(2p%mCHmG`v`P>M=IZBh(n1&J0LHFCCpRq84n& zQ`GW2TyhcRK-ktxKTGx+plk#sk<3NWYy%|fGG5>x=K>lcD1-7aJoCZ>`_va4aZdU5 zJ4FI%x&H$-7pvhHD3}d?;i>RPL)qf}TolNc&x8F+Ulwu($J+&tDY`1zrlilW6!%>o zl@P#t?C^BH%5tdvy=0@rSM?_Hsi+IK8>S8+Ws(P_zP>khMUb8tJr*-W(B>PY`5K9- z$H09o%Am=yY57fQ&Bwnv>&7q6{=y-n)@LL-CcQ5J09 zdD22p@O9m|Os%2yN^|$Ff%}|Dsar5Qq6)a$LrDK(sP&fWkl9h0GSh@#nU3I-Rwx zfl{rC1dZFON9AS&mGNr%45F3{0q8!t{Mo=p4CjU%U6585myJBwqGXt8{h*-*;gCdh zk~syXwhmt*9IiXiakazt@jmeY39`I!lp9DAw!a?n!s6+b31}g)f*) znI<8oQ$4%4n`VXx^z*f5b8;)LObo zF~C5{aaG3|PgkfR3@Z;iDSHBHy!XQEpP|`75C1YicNUx5n9h^}!nOj;F+!L`9O1mDq914Oi zoB9w9FE-Q|TB?|b5iSIsHwcZ6$->m3^_h%+I(}csiA+ix`#WuPDkLs{ z*%gB!60PZg00>u^1?Jbrbuyl`5vx@n!<-`$L0tm&d}Z@I6D*_&J)dFs1$6e<611?}iPkE;crg(=Rb%Hm{o zv7NpLsb>mNtI1XQv{UiIaZhYLj+1~*2vG1(v>d{G#`_UO<{|X_IuJ7OEfyVd29(J@ z72Q_worJ>xF5-O+)-33H+8QW`?fb1^j$GMBPl{{E@efbQ8z-arl94sj%u}^X|7F;k zw1Dl&wF+FX6MXOdy#Y3%L}_ROkmb`q?{Q!KdFUWjA^Z`!MHU@kmu@Wz5&W7Y z&s?JN2V!(SRV{mm@7IuaovsE2$elwO)})aj zQin(CHIe9Pb<{$mf1#cI3}d#dRZ6R)SGWzN;Ta3}y6Z1md?_t!EQ^ zG3KS1Nyw7(fOpVqgA|IJDmzP$^lPgwjVJs#yAHJMfHVJp$XZQib`Ty&j}lSb^gPgX zIVp_JVGY(`t|YeGTgt`0r+Gb|jiGqNdnQZc^hBEaGdW3dQWPA7q6ai?NBo^@T||UaHFW7I0tjCa}8qL_rRi*{FDCe?O!MnDKLJZ>@4KZ zj+zaR7aof|qrwwAHtJ|<_1o2eT}(JNmAsS|Qu@i=@u!x;IAm_lni*8Q#U8i)BlE~q z2Djm%jcqq)-PPu5c!R(7S`2Ub&mEQ-y_H)38t=7zR=6_}n-LoI^ zrCBIL9buq=2a|{5Sp?r;`jPMYUvg4|q#Q~;ni6w%fm!_oO8OjT#}$LEzXhxfSUM%f zLa4tT_F3L2`1G(zmyQiqFzq$vCSS3VFdSPK#cOZE-Dd+;@ER+WWpC zlW=Ebw-i?#u@}R*aW5eYh2RV6*1tWIjLzxx`d9x}6UcEQJj^_oC^C`5`Lk30zj52? z$twA?q%2UU)e(RLr*zrjw^Wvstd2*hXa6@Don`g3Sul`!+wQcm(jo((WvXh`a+aQ; z)-Y({gA=%2N!Qd>7P&?~6Rqu#N@dXut4<58qbu;KifDzV&b;J2#ogi9TgJ>C%khdj zz5ZH?y4Re2=Metu$KprWz%?8aOla+g{}%=o#IxJPoj{Fp*BNh>rb3@R9L(E@9?Y4k zstB>5(@Q?CmPVo03zdORt1Q2UAUD2hf0l()i2Tlbt6T&#v6a`}4I^8WxbpL{=qmx} zzM>&={X<@US-8Y*J$FGr^&)s)TnP2&*qhyJo&OEwGVr@7qqzosLWXzw&lXSv)lClq zd`JgvTRd&-euOo;BlA8+b3CW4PK&-k4dpBsek4eT6|G@@VXxbb>*U8dWaD4x&{93o zG*HaN87hKATP%DIKGj#2Vlu{%Z3G5V-7DPUfyOh4NOSLb5%be7SdzoI>Dwu3|0VM! z=D^VEzzx0}HIrmIQJ;zCNH7EGNlnY3@7f01RsqBn4tpk_h1lg;lrF;P?`wN7IKCbnim*7&9qhXa{{*A~h%lsHpRQMp1=TNN%stf}Ni*YL9ME0Z(9u)=4cta3# zp>qcGMfm*@xIaFhdcc1_=8snuFUz=n?L1D$f4vqj3`ULvAsHr$W3te67fuO=*yvJ2FbNqJUiHmu*+ z2xSC+;P>!Bi+;m|WA9ZY%7v;lWr6ya=XRhf^GT@}Z8M+@f+n%(nk70)#9Qwv%iiyF zRGdre$vM0DkCDqXAz}?q4V^vAmE^RAzKB$F(l-xFhbr=i z;$k(Lmx~~I3Jq}%A3R{52@}IKg9iaa$Bje*{1>Y~FS)qU z<3$rdSscfnIm;y=CR8{k^##neWNP=W)Dk zKYj_;Lw6*?DCts%lNW2>A66Gk>uj0CLh_J8$m;G{p_)c|isJnU;8W}mm;J2>1$Bq{ z^~A~fryf5_l&MminIVx*j2nX-27MJB0Uel2REzV`;3>2Q zDckU~W=Tlt1izNtWPf+Rq5!#H)rIqVb??`005?F$zv2iFle&A)_VckFwMR%%iYpPN z(7ICh7kN<0MkE@gTvYxi&OLx9Bq zNzN6`0O^h^`J=VsKGNhb}fHQN3AO76Qv66=R+HtZUYV5+8NkxtSQHMmG&tSU7l3&W8^(IZ-P$8;X5QEmdcKTmUHZ zzScT{YMXVQ~qB`QHmCdWKa``dFFnnDb{X}z@@9QG72Q{=<&Qn6+_S|Cla9xT$I?~MltEY%6&=s)EzV>3NA%^xX_ zx1)PNH&ffeZSn1E&?YysxvwjQcz85y=A-Gu@w_I{&o%iWP=aU+f=5xC?BT;cib(z4 z03ne1S-8xu37gru)-Z?5jYIal(2boafq5Q>gF3?e7ea@N-EcL|PL^Bk{ISPS!tbv% zP0SSq~7iOSK(c5xk2zPhhj+XAU}0v1_sjSv(qrHvgbu{X-ipc4pZa!OuLgk$yM@#2pjeDsLC4A)lZ*HpEJEek_EN67t136l$oh zM(3Jh=i~&y-$bILf^JH|G7lL7Z%M@V`hlk8AsEbL%1b&9m0_mIB3^&Hd5haP7BA>p zUw}L{C}`s+7`66*39t6+0pxZ?a((XIUc8sg!wfgqw2R%pDwyQoIc~(;g<;+nrj(nJL@b!@|!KV&W@ZgcD2AC#2MAp#fPG|8lXBN$8 zxRM+eE-OGwUHBFXNFwm|s<*_9b0v3DX0CyFkEf$BLws)}k|x3O9!RG_6hvZX1jJgk z@`8b^&J4VyH_)1tSJN50@Rdr#D$Ov`Fm<`Rc2vSNt86GT`7_;M*of2q<%OPHHebzT z`o)O@Wi`{5R!M(EzD7;0GsT8EpQ7<(aoF7T-`KVjM zz9xMjCIB2FN*qp#ER zGMrn($Lv!U&@NPu9vv3#hF{HB0m!3|AlRON65`@x-Dx*Kl=N_mEe;*9wH2;jFtZNr z+H*Icwl6IJ#w70+2#Q@2*f-3EW9O+E)=quI4+UZFFWzrtVu2G$Sx8Sm^89uBHC}mW ze*&I^tXWgt3j5u$NE!)bfL5sYnP+7u%RT}*hEc#XjJjl6zBkkiyusqX>EJdWkW>qj znDGuSqZYqoG|%dv%-U#*BR72`uV5n?l{;IpACrz7*_&6{c|pn^SNiry(L^)hu}EC@zaspaGv<*=(zGwK$P?E`T-4Ibm$Cux9Xx19i_)l6sliGP=F|ilj4TO5^Vv7zagT~K&;dXoHD!EI z%)c`@1MWcoWDA~WJ6!66bHSQ-e2QeL-1D@vGDLRlpsqJj&x$=rQc}+p_!vti*jYg=mt6z?Xd&4Mqpm4!S z(FvH)^K_<2?w_oH^)8pB8cyeTE!96x0e^6tqIQ86MYaZ(;$(6s0K1MFO_04${j6=o z5bNOREbuHn?}q3``ym^y2W89fD-MXjS*LV#dLH&^U7lj%IXP^-^RCK-S3RJ?__eEf zefAL}l9x>etV>aA%$Z!`NJ2s)(!kj60tAY>{Wc3ngYqM3uniIO1rLm*LH+n(r$HXy z$|8yZ2`h0jki8K&{NkrM-jlKO0ccpM!kwC@Y2wZ&ns5|$haX%WD!1v^C*(c2NT{Ze z5A~iP-7nO)tq(prav1!=;BLB`p)%5{d*CrFcb*g=tcuF4%b5WEtcMzzuz(EzQsqyZ zM3udpMuTQxAC#*?3|uPmgsA((NpX%80$L|xHTucb3Ms*RQAQC5d2noBP=kMC`bazP z;3^`0OF{TEkYQTt$F~V3jjc){%yjZm)J2sfGx%V^X^8Nkn-fY9zL(bU@~9}t!aVL8 z*@A+Sc5oOp1|8f_3yndZ_oHAEUUt#y($+fU$B>cil9dD6wf#*|csN76HbQSfm5;aM zFlHe=32C4rQi)gQ0(l}}DE(v$TPlx6)pnhme3Ud^Q2S6~a&p?4pvc^#2LEd)hWmu^ zz(kZmf&lrs?iR$YK#hX*%XgsuaSCpqUVNiM9IVH$g{L_W@~p5t6Ek=kx18Vi5Uu|P>^QYQ z;xs(VQnx^uTv|xnZ;2`q$k5?i7Sg2@OblA%-_2V!o9Wzmmx0_=XB=GaW=rYsN7YQ0`<56 zoM_ls!n1-@MbmN}Pl4uyY*20Ho-j*ifdq|ma4~(5B_6WO9hR*`sKbha2-d51h)H*Rf!P3V0i1z589zfEL8yQv-D zQJ#>*CZZJ13FXS;#+?VaACdP%f0MywB-g}u&J5;gpb)RB{xfQ2<%nucwd>@Jp2KS+ z^^y7`p~z5X{&*m8En6`zR-36vhJjP*w0O^9tsu*)E3FFC1QkrU z;`4<}Rf>zRRiokfkqJcmA`;7at0Y;4a~7u)SA?8AgwpQjU~lPHiadeMpj4w@;X6NC z1J>H78SkH4dtUp@nFmo$tE*)4CUcb4)N4s6W$o*%9WMtLvhc~KJ)Dz4%VlW##;N9z zTOZJYuX^8Zf+_bH&9KPE>yEG0rmchKT#A{U&h9 z*F9Mj9Raxnh$rD;73p&VNeU^+?iK&H=|3n12RxHjq4WGy4Prm&Z;l5lUck+lj8{^;R zdgq|k;KtlN!piSWQWry<=DT8@+yRP;m*ujsZDv)X^Fi5cY7X)LSw$<}K@Ifj#nRa7 zY92J*XlOkoHl34@Oq{ldcI&)#8v8Yr=jId}+3%cy*en7rVg?+$&dNWdLWedZYko$N zh@Zwd$+=c7>DEY-H#vY*s$9RWZ?r%v`-)uN%6SZh|8m=;paI6#(fm5#tD&)riw42t z55$2gSu>mGZ|TuCJ6$AVA%z%!#-z|!)Wo04^lYi{Og&?ILb{s*a**A{Q2e*V;7}nP z1j}k0xp2w9DEj(#*8e^Z9-&jq_sFIrk$QKss3$gh`+28E z4zR8fzWv#@@=}vSJxaMLqrAh?T2`Z{374R*-136r(hxqe>( zL61XqMy_UqB`3*NimiC8T-St6(wP4%GobMfYy5~t7-?Wv9tbFjTlX2A3+NnP7)7sO0rXsX$6sRM|6s8lZnN~b6tF1uegeHn(XUeR3FO8 z=TH&QanuLk)n!r4pDUsRy*`z&{}|UNe(dg1gX#gJR`ioGPW?2ieCM*41ZkmC;(`sw z%jvGx6niT#q}I~V_thRlbj%k#(E6BPnMOu3&Y)36;ZXs&NFV75poZ4oX|PM(K3x>f2%O|8@pX{gvC8;?CrIeN+durWJJmH}#|?innp>i=O5rYRHs4 zNy`8^jfZ(~SaLiqWKGs`+IDUXN-7{4wsGL8acV9-BSedv>NuP-&)&6+l2F+Vr0dFr zuu8Vz0~Y)_ryBrbTvRa4(vY1P**K;}-2nE5Spm_~rQ1}D4{Bp0V_&~7#Jv&t&ogxb zj2r!dQt5mStQ-_Ulw{gHUod=C7h(Q&oQ&8^Sp`YlL$6kKYPMyBKVPb)TrNaZqgoOg zfJKU|%Pm}T-N2tLldvRJm5ZT!iS*C?NBy-%(?mJiey^$;h{rFBeY97KEWj!w%x=+S zSqP5hWa*QlY!8@V(1QpUBxm5x!{_q9HFLjqlOZ|9BJ#C+y!ifAG*k^Vyn!Xx0haJK z3$R2!kfCu~iuM_<)*Ix%_Z7$1MHtU~&ab=FGhJvF!5F<45#R1uW# z5&&~?myMGO5{{rSJzJB%({;1)9|edacn*RNpuVY0Da~Vilcq@<`+sDxm7`pOfPF%* zA(rtgEdMDl*7UtQZE;2yto|u&lH6a@>J%@&WIiFa+n$9A$||ih`3$8Ax5^Z zq-Vd7wvSWNBxYGM8~#wTm|-*QJv9rLfstVa z5&nn@s^_10wuub!OkzXqt4()B(z)mCWkI*jU` z!8LW`q%L;D<%3{tZf{c^LL9cRG4Q=4R;E3E#>R?Xss)Xyr+4E;t>W}YE~XCeHz$6J zrhpgT`C_=Z!9c+Wt>jI32EC&B#H7|w(#R@^IhZG!#S=Dt_ws0kLH*b0I6gOCb_&ud z`|CSWhJhv3gliADiL5+)Q-`QI0-A& zGNe7yhkcWsvXhk-i&b5NkcO~1<^U9dX7|Wsrc7!SAw4Tgk2blHR8gk$x3b;%iOMof z?0v@}R8)8#C6d=910m11I6JNYI}-_{etxwY@R+Kuo^MEexmU?AlHZ~o?wpAq9ABt$!H2e3+BEIX)BT$ zUAwwqn5yZ#=hQnj?r%xEhvu0ec*~NxOFOHDFZ*KwWE5>!aO<=1ZiqNf+K+w_co;`i zk(->vsBwio7`3S7x^DTOX!uH ziHb{J4P!d9GX{Le?1xgSaa_*O5J!-8fPzpd)fNS`3CR)LE#WaYRiV&YL%TotLyPom zoqMf7VLzEMC*PT^ww`2(y`l#6c0L>QdNKT~( zuS6OKrD61yb*R;KLA_A~)KZb$)+z9>TJMKFf-NJ>@$Cv^lkYDCa6Gu|uRQ>*2wHd? z3mF~geb>bSR59FAqAGJYGYg7Lu+m^Rq2=m-LEq7oGpxjg%s!DN@i9pL_Bb2NqMHhC zKTw62ykQ}*eUWdZmJ`$A%%AjyJ_Lf!KSgB8pf)fx_k&|0TC(l6T#2fP>L9n_AN1t1 zTy?q#>G%3wO^6_=A_{FQYpk-4^&^K@I@w0bIj$hi63)Hd2AuQDykx5codU3XOB@pc z$3yF2q~J6w8m|5L=Y0%$&CP>AxW} zt<O>GJU`fYP9pDRSfOu>Q69bqTUY94C=I{APger zT9zw|j3RTwZSjX=SkZO&F>_z#V0Pb^n8P)KMw3Cj!6AMLvADzoH=ps6t%#KC!|FeM zjM!Fkm5+JSRTNRwHaqF_0jSrD*=Q(b6^N=~NP*Z!8N;g|4WOqlNLRGoYvlKWtD;U7 zM4&necD(B__05#aPuHgIQWB_2!2-1iI%<#e1) zTY{5W$_K<$=)X2oo=1Y2I>d=VPIg0rezNDl4CbM8Kydz^pCb*aaY-(l0F=I)z?l(B z@FP>+I`tmrOnRsydfJoxkuh+1R$4sR`AF2&Xp=nQq7~nI5l~Z@?!2Y^2CjFy8bDem zR;vbv!TeI04g|GXQo7gY^a}49rzj_rtRs`BS^>_G7!cRD6d*c%pE_B(G^!FVLsT;@ z&miDm-YAahRdR%0TKNry3B@NWzUJNLzX6z}iaMiZ&gPtoNQ10|*e)e^66^gkTS8Ey^v?76 zh{J)-`Do3@XyFhgInxi%PbDVh-iThLAUc$4PKu6&$!dG`WzxAhUFY2Lb+z|sfTlKmiHQqH#Zq?Skq9NZhwN`PKZ(MCR!B;}q zG)#Z6BgS|RQ9i5&m5Ix6nE}F9b*wu!Db?@HH36;Q_PvO9f zS*J@4KjVEKnAR3EsgM#Dok4()@7a(PKA%)Efa?>!hhDMNziIl7al~8sj#?_FFl5g$ z6vWUJX_I5_Dv3q2zXX|saR^ghX=G5ff5k=;@k;P)yiUsh0*URh+=qZ`p|nfw9H3Q; zTXo>t7&yZ2Zej^ZF!@v9r30?3KW;a0s5Hgeo_m(9x|Tds+>h+t<)DG>i(O?d`Zf$2 zdT92>$=zMIiX~mtmF=MjLk@t|=wHTOfzHK~rjiY*a^;3~6V#ZYGW!YWXL-v!ssO;# zECFX?pUmtyrYngHUa?1BLn(Rdx%Q5dGU`O^lSP)to1*iBCVj?E9w-qf`HOoQ9=?-r z>^CL=4`-Jc6qpPHm0k%_{M&-2!XLPG{@7N~dL#s^1`ons+zWeyekI3tO;MM`e3akw z?g6mxHRkCO3;*zpVI3@ zQ@jn-tofQ?!v|w2Naf-Ma!ZWO5CI>-F>rC}H8kGbqAiJ)3fD?xN{Fmd8ZC*aQ3YVa zK5We?Rs_8kf_`Pu(eHE@etiHA>jtxbR)=8v#q zlfd^FWKVDA2V0^(KVJi5rFdl)eA36Ka_VhF3NxL(Z~Cmf_xh*uPo8npq_i#BNKeW~ z0*}!_vfBRl7vlM&!ny7;LWXwe+sF?qyPl4FRGI zUmn0f)Gx@;8@Sa$K(q`&geHDgDtRi0BSdi|!}xDvwqMilUTCt8aGOn`Z(|s(gY$f% zgw-g5o!H_i!W1Nui#w5M-CFElDw$T+P;3h>w89AyyBgoW+(5yyfd$`%$5*}}i6UOb z=3Ka9%($C$S5vXuk@Q*LdaUzrc2z})p-cxu={Fb~C!eTT)*8V|hec6!?DoyIYk_u^ z&m~1>XnWr?N+4U-g5L}V?a14+BL{^m`B?>mcxpF<@ZhtVKV%ErZmtOZR}qZj|20W? zvnKr#E5nMa$+SvH@E1zHQcZUBtpRT=bADiSWjqzxkb!-ET_hd@WHWw%-dGR-6f^*6 zec*c20JOH1;V~6dG*omb|23YF#Jo5r`_CJw=}&mN6V^?9=ZFAIC4v+4A((_lb4~-t zQ?M;lX(*+V$DGa4-A7*3jPIf>w=m5a`E-E6o%7Zza-_ueLxI$_9e_ROt)+YL%5O{X{Xu){56zFzBlOXW zyTt%&>T%2iCjq`#v&M@L1*6{Wl80lLJ{pROHX&QYJ1)xT2H6|53zo8GQZ7QgEnPo* z6sfw$9F}*#+Xsk|HTk}^kZVh48P8u*xx#)1sW47Yed2Z6M(9=NOtVTz2r5F74apNx z^|BO+S?o(aVPJPaY-brmmu!B461xq>hqiEO2gxaJCzloJvr9BTs1(aISuGv>6&mZJ zE7kg^MEZT&ip~Ozl_0@vncdyh!``eLVu6+Vv-?RQ6ki>< z{2`xa3RZZxqJ!~Wal5YPts4{fUVAq82BVnWVa9p@=^AjUA|_NvNEHhf+XZiGbq~Q9 zun!oZ;eK9r*TdukPVEv~ySMXYKafi~wTjBKEmy8HluU7fkBO=0HaP{u@3Hyw$`)-@ zu4EdzzjYXMXVgRtdN!<{453}zS9KVvK5^so_wXCgJ$@elJD2WPujmj<8CLSOvbm|# zF|AoR@BllpTkj)t*|0Ll{ebhP%0^{0{aH^uUrW%L(;nII4}$7Ju+Rpz8@334*!NUG zvvq7JC7%ouORunH&mU1oH+ROC!*a&g*_Y&p&L-=YDWo!Rsnn~4!^ESp|6DBA^aXs$ z(JBCTsP>n>-HlPTpEq67lP&X;!02wx&(!T~I!>Bu%mFEPYh(UK`n|FrHxA(fcn4%c zAl?5svem+_EUn!M;Wty@RyZx5B#F8i;}WkKqzQEQCS!_rN^eqRW2&+lfBT{h>*_|Yn2F@{BbA?@n)?VsaREC~0lM9DwDc)bH)-Jf z{vc@SpaXHPcM0+33k2sH$k>>U zC{kr11D-eh?oBB$;pkD!t^A?LO~J<^j#TF`skW2-jPIC)Kl5GxTo_k|DnAfAgO~XR z;xOXXwH?~ocN_<6d#0Z#5oOvyDxqw?p`RZ)ZiqyBKOp{vo<;NxiM@E=;eSwT)tI=u z;iVZHdZ)JUCCxyzExe>`xI=sIwV%fs9Q~M97XA-_h2UNe+mQb*Z>MU-g`91yQQD%f zNCO{-LxRVCMs8f6Ew|!n+p-|(CIP1DT<7z6D{ROapq~kZtPlmX8Nqd)(CR9SA&+aK zQwQ#Rb}W_3Ia?xt=wCg*w^!1Y@zYgo(|W)w9ZD$n1^*D;brL%FI!8w#Lu@h(@F##~ zFr7#eem_7-dqO_{d`S#b^BxVw3MW`M+75rnb#>bRW>cd()6IzBI_9*4|1#KfI}Awx zm%pH-mdTQ~I`jB+nj-=CCP*GOe;>ZB{@tY|Ge#QHMu*iQ{i}_8im&ZdW^wVlQSY`Y z@4I6Ccr0?OGh$T5ny_~jVNUr8oypP;Dd@TU{Is@O<{qW9k*DVR26@n_{Ew7{$t*p z^}&Dg;~ata-(!FyLLa$_zBYW#hUcbX7)`b&KINw8(i3U$Y7)M(e@qn^pfBXV2^rsi|@_2aYVr-^Cp99@AYHeY8RU4|e zBhlEn1uR25DGf?0WJTzoB1(fxn=tpGTc25Noa6S&En2mOB)}&)t=)wkmu6hKm!N7^ zc@k)w+t>*U9J619egqjPAhM~dVu%)eNw4;=!3w-)K-q9BFPkrTju3*)UU^gNZL|EL zIh*pK7)v(aiz&S~3(s!<5$!tKrVa)+I>$e0?p~KSbC-A%!IMYT{PQO>|kI zJF9ZC39(3P9{5&ug+*m|@#(&3&vYeWUA5MJs*Q(ugh^B~FmbYHtHu^}JDnBj6QN7F zWT^*7Aanv~%b1f0ZZ=os4R}tsXvGu?xu)kDg8`yMk9B+d(sskD(v$FYU=|axSh_Gq zT44)mek$1g)2F?M??OD9Pu`Dvp%{Vn0bl2u=%5H>?+r{r)|V-ejnS?n(Qf{IwN^Pz zdyU?*CT69TPR;mQRdemilodKVa`OBir|H$Zyc<>auV8h*`2-K9ZAXO1_N1p?k-$Ln z#J7X~M-}toMG`BvPB5#0=fcVMn*cb7u9f3a#}YuE&oIlKK+xv-E*FBFOorFF&?A`3 ze=0zBc63%3=ILv<(w52JBp0F-u5$W>+*ILu_?IEN(lTDF*i-N0aAo~cDn{Yk)%pR*&cL*vq8xnjRx^arU%)Jwr6Qv<^b1mbTUlW%8&>+u@lC)ooL3Cq$DNBr`A=L=QG}RYr zwR_HQc?6uuns2Jt`o61GOOVBS?27jLr^ zUv1?kuF8=aRYCbAbO&Knrp&6)`jiD(vSSZ35D$5(eTo5(4BmZTA#~X(;%|u@KnKLVS<3pAmGO7 zXW@@gs*{vYZ+=_Z!p}0xDgQXOHEcbKl{BsghV$;Jf2Ql;C5snwwk!T*LS~zS@mBLw zB@^gHhKJ1j&mE+P{BNgTzcpT~*2$NFbJWg^le{|Xy|Vl2$Tn8VU6{_$;vk&95Fg17 ztxXLxD4h`ILTMNZw2i}&2ewNR&1iML{;9UqyVPnZR7QH5P9<87Al^wz6s()Up&^hX zU9YDQKYRJ#O8({rdj7BfdxKcbz%vc$5FhRBlJxLa;m%x&VME>0!R8sT&eNft8?0tt z)A;%FV4YF1`dWz?WMGzY+K|u6mDk~04T4EJVu?q8-=4(q7XnTlhEc8a-0g8J;?%yD zo{p@Ps-Dony6OXlp?iOzF-kGeZTn9aUxo=~8cf@epAu9oC8SGYd}{RYw)_Y|V7Ib2 zg_b~yT4G=yN~`N$L^$`hlJuPM0BR z={xDI$v=Y*o})?l+gLfFO`w8YZgGDe>>l{f%vg%Ef#e|m{T!+k_ohV5S7i4t?oJN| z5hJZ{n`L^9HNA3lLl$H9q+_pOVQ^8C{|$+kN?Swuzj*pl zPS4x?pO(0|&x-pcygbmpiXf55<+c^%y=}*H3|x+k)YC@b;mf9EH8&Z8FVRm%qCzv? z_%p*B=4}m~oZs-U@(Q^DW=+=!~=7)fs+JV!O=0=M^%3UH` zsyBwDu5^K-S;+-RFSu)S3UQPMs&i@r==D&xV#7WE6aRb3sC{`qSAC(L{+gH`_+m4W zKC9K06N}uf%Q&23{LefE1CDS|SI%;BLn2G8&$z6kq)?ThNI^3#dZPaJIv2<`->L~tIqbh=H&+a!`wkM0M33A--_Q-_S zRrck<*F;TtuaW;NH~}M+VW_y#&sb@wzw%Q3lJZQx+Ta_PoxkD}$Q3EO;W$5VJ4!6L z^}%XGrmE>F5~O;tsSQm5uzn(;w8n&;pGGoO&X|iZ|4wGA#_&i=Ixf-SkFpc#AsHz2 zM@IEOMRSgJ6a3k5z<$W16ZlNpDRUx}MM{?+i&){Ku13^1N9cDXbNr-Ps%}=4#1omxd;rZak>4WGS1)mJ76YcFl-Ovy7crW- z?~+o3JVueSQS}x={~fSgS^i_j3u*brTzJe|!@Rd+We8AzoSfIp7t5`H$xO=0SgM_R z7f!&8xp~RYWHdzPr65?nN09~X1~H3B`-o?((avYvka3IuHAmUW8h~B>!32y?FSWxC zD1sK*>gpQr5LoaHLHKm%?X*b-5KCwPBKgmkW}`+02mIYKYzr3^dX=I7e50ENjsTP}5bVZJ`( z1AB-!u8XP0n2*@@IKT#PL?7fkBJY};Y8KH4DGT;@U%pOWAAmC_V9kBC6s6`t{+x9< z94rVuS$|e&Wb-W2h2kU1Z&76b|H@>M;KDBDR?v6YIi32=Gj56-bt<(dVA)IKN8B*w;O> zBbQl16s3V4Jr$~TA$ps%S!8}hmZX>GqosDSlPIa`#I6_DN=$UUrVI+bg9a&JKID}_iXQ9zydOV5XSN-NOgX; zBuVhQVFi;0xA3)XI_=paVYu<1nUdW$-L4_v!$2&Q@CctE2OzMx3vm*0NL#`8fV$>i z{&zh&&t0XoK)oS9*`L$^WIjigwP+#)Wh1^Ea-$AHn?XQdi$%KHF}#_9dfQ$5@5+YR zoO2XSbVgqCIBKI1I4jHx)w4pBetRw;+%(c+Pz3pZWk|ac;?%0PS<>RV7@$ly3JgJB z=yKZ(4E1C$*t5&GQxQZA9kA6|gK-HFq}F%-6N{~`q63GVHnhYmjYyrb*Kq7#bKzjP zo)ZhK@X`1&hKir0TABW%1AJPoYPpzFE#jluTw(R95h_oG=kI~og~=z~(pFp$$FU|` z;G#UwFrE_OkMky3XKTz?6T$~=4yf?iU>MkN5~`=SmMLb;4hUtN4F1U4A4DU_cJUplGeVm_iakyorT0*ZyhZT8{a|yd(v;OK7?vPp*Z#`4h-llM z@*@;*P1BXA+XV;aX&!g+4}pw`goTh)!Dq3j@Ie}P=YB<`pjNJhJ# z$j^mQ@hsUFUYmWWS^G}EnWory$efw?8W~$w@!cyMuN7dE$JtGdfo+R&wLJK_Z)c4oc9A3e({u1J0GHNisA*F@9 zm-T;J@U6109e_#QbK#hsi-ZUW`m57EN5FW(Rq!PrbZK4u*{3I5lbR*}BrVN;F9t6C zb(+!&`&OUHPk)EMR~Y|%ZbfBR-O81a3ePZp`)qIf(CzYeOLM6-N@A=s+;~*jKlQ9;we{_r$$SO*CMT7QXhQUGy+Jo zshg3lI?xuB35HGjDDAu?v^Lj!BIO|`DqnROrRS7W+82)J=+NbDsZ?SmCgchGSjVNo z`{;r%UPpb4(3EMO?4mq(@vPzjs-RX%$`5N>3S3H_!KrU0vMQNGt^!`*kHiw{`OJdsi{BFY%|bsnk*e|aO-G!gA7n*SUQPClDt2|= z>+RVbe4a#}v&45oEu{z+p_EKw3DMjy9qD>!*;(~1cSQguuDrs=tU-4azoQ=bD97pr zXCQ{60hA%l%Gpo>^29M4N z^uyu|tR0R6YjF3qPzYHz1m{?OYc-QAPN-H@e{od+gV1OOHvGkb(B*{5W~POy1qL^@ z1%{coHp2^naH}7is&ZGQG6bt1Eb}tO`H>s*PZg%0vsg#psIBjuT2&lQlAwgMrGIuj z2!-pRk#h?|kER+M!}|D~9X7%wHl7!cT#)4gT+H1+5Z8O2K!qsn-t5tMv`mSWAeCXc zyjF*k;#kERb>Rdj8#g}@X#_!Z%U`L$Z*MTMMxMlAVpUL~VXqCvYzA8a5!jG}zk`ML z5t{9*yk@#un->pg<#>+t)1M};zlww{9$#EmV_uc_zZqc2O8YouI)`v1 zf770rsSaxG^AV9G^<8#eX-&vd*hwy_EMnv=h0#H}-ZHkPst31%k3DaR^OkA0f_wuf zCcUNzSscx3EEOw{5r0X3O+|nv`aY<*IgcB-#=b7Z;nf2NpUU z;LwiRRF|S#cyYZY7PC|k|9`5Uq=ROGs_y}3=J5K|Jt-LF-d&{+B89zoX+p6u2W>)- zZAs-ekt?`0q?@q*gaN=Z6?&_Cvig0%fv`U(IOl4wL{kJ#sAeVg$KMIG9nMVoQS#4- zSGOM{5sdd+-bNYV!^>9uwcQv`SI}^DyQgUAO5YC2Yz@~<^8L7pB79nKty0Th5-37x z87zKO>~PmfGvlm08IW8ZhlMj0H8V=Lsyy_bQ!=#02y|Y_%)gTQ z{pBT*->>W#8xCWJtIW}A5129Awia-G3U830Px}0OYM{BgCrAM@^e{OG=W?Fo)#Zjf z8MqE;d5U@#uaHG&WSF!z(0Gf9DnBVY?g4Q(qZKQpZ0f2J7yDIOBzW9|la) z%&P?y99z%&oEAxlY}An5kV;U^?Ce$LY*dx-$8h!YrMrU;Oyo{5r|vU^~}p4$pTo7lD+h0(B(ly1%V!Twp7; ze4VkUJrkkn`^&$3epMT+Z8H<+i@4`Yc;FB{Q5JWGFW-w;l3kYmVqmP}K(%_c49>(vd~h2x%a?y?5tE zUb4Uv5GL3W{bvdS`9enHnagdkFA=_og#r6T-RGMZ%hp9$gEpvl&fkeAgkt}4CAaUz zKe~1?-kAGnZFc?8r-VUiVY8ne4|61qFT3|SW^(+H&&5B`t zg;F?z+|rD3qW>W=FD_mh30wn4K=sZ0ZCh}ZWc|S9n%cr=mQtZ_TkjqYi6m9#kRsIA z8+bUKKYl@lNTSgig zhh+Md&mTAr(L_>rFVrf3z?U*bqs&;TQ|RR-Z%UfLL}R!fm#_Bs_E}~@k@$*q7mqs< z)7jW|tg86x?^m0xFhBP}P94yJKwd0TQ!>-V^k1w;VCb@fCcv@%2W5S=A{1`^HXoJ4>MO{7 zNZ4(W4W(T?{N^*IjkAx`Y+_s8p8kkM2iX!h2+vg(I@V$p~N z*_;4GfJmvn_);a7g);S_R4@0txl;qSCPn=Vx7ifo8E)ygXNftp2Wvo9v$EEHMg(u% z&9QxpX*(nl!1>mwsa~$1yoFpJbs%yb)>ZH#D7=oW6{v%=b!p0iVT85s!*gc4&|jcz z$o47oIDMeQB2`}AT`A7oh>7tP0?H6}R*{9H86{{l&bBrFpwr}S>Rzb)XNI7m^6^}ExaHd`50&zQylt4w6Zo>;i$*#tuyqdpk-SNzr7Ne_9oey-Kc}Qu9 zJN8CJ+Wxxy9$TyMd24}pL>s*b=6>mwF_k{;J?YH!1R?p$QLSPYOsQqcFd_eQv_6%!VK4b^IT!|sm|y>Y zFUUE#UXVD85L}LX8>EwePAiA$@;&MAdz;**l=;rSGKmB>hP?1GNV*#bnn7`B|AE5y zd>7%Y5v`shH>>zau36-aztDvecq&y~xrMogeK-L3Nv2VGi6_iO=)vIuxc%9xsB705 z7lT074tGgGV;sao?$4Z7U`y|)Rsm*OdsX!eCsTiJ!jH0W{KiFbL+^B)PH&GbvYi1@k z3UOGH*!Xw1q+Bll3=r440xwLW_c?6b;)!wb?ypb1P}^xx1$-a}dY zoWrTck>))F&KJF8TBuQ5$c>x}8LcXG+d?H~Wk8UXpxngV`P8ZXgqS*PJ z(E9UbJ96w=8+S{lg)G6bby~O7MYMDa{kz_hGE8%ro^1CZ)3}PxE|uY1boC5U`o}33 znw?;7D{Iy7B0MeE%#kkMm{KQ-dRdmItER0Wov5jWzb`)tDF%NJ_%OBKf#pY;XE%2h z@k!Y^Q;@^`gs8I4MbZLePKE7MtgX|7EdY4VJrAK6s*4Ph;PDlh{j2eX0 zPqo2%TQFt9T0gVE`+-C$i;#HjnkgFfA1aXBuq-4JUK**|FFET1VC*4cqw`xMx?dNd_=GC| zGDPcsr^ZN+1`{AH*8rB-pk6DIL(uqF(VpzyZ}O8h}#wN^^{(6s)OL9jRV<>zX|NXL2Ez=$=RQO_g_ zAOg0Hb72~-kLLQoO6YzDb%UclsVLAl^-dQZhT{EeMP|x8$QEIq#3}Z2&6AQ}mlYVi z^=PKdNXklVQ~C>gb6q>d&C6CiRFD5@{o0<_StN+vOaSFGAVApQ`L=CN z+qP}nw#{kVw(ag|+qP}nHg=MGH`!dWcYBvh_T9btUP*neRMqqQTO=G2yR9mfF8Q;- z)htFO-V9MhWGt@lLwywT)*I7-WSg5X+P#G@3OJJVb5^q&i(if%4sfWr$AH204MRnu z9TPiSCNY={N=rd1)1P;{Ts^HO#*Hc~EgiFh<}TGyn1a+^2TJ42;*GN1Edg|pgD4PL z40Hu=Bzd{!{kjp6{QH6D$M^prS`mK?mR|mYXkF3Un-9I&oO!j$y;=PJaKU@I{A;ix zzq%xUyy(5UfX>{W)4e*+{D2$a4dln}HT)RV;0=__?6v6KZrbgYbv>Ws{fE(dY4&RO zcXe*=$(+lp&5RE&iZ9PX4=h&?ELach_J1{6Fa8>>cK>0tin;C8_WUzi{~4|Svy9f~ zrsWPXtj1zL=JSOzm`9s$hA?SE-`b&^gD0-d0JAkv@IHeGB&g(X^O)+ixFpHDG>Osc$amXE#_diz5s0~ zIIXv;&O>rMXzCR@Gq$VZEsB0e%{u{l$YLQ`<6Igd?Wn&_c)F@!RnM;Z7dbb(L8?B4 zwDGS}UBQ2`rmnh25CWx0&>V2qlA=o&R9!t2b1l?fn5*iDW5VzIXLv5FfFcDU#6FuA zz@noQ;|^0uyCF9bE|)=6&1ylR?~h!rmbU2El{~8QTUkv$gYEU{NAaUX~v2cQ+&{k2FGG$|GCSo^OG5krSW3&@84OtkFo82#zAZOP*P;qLj;_ z4SIQ(i%HpgARKGqp;Looi!N!#%ih)dtPP@r)jB(uj;bnPpCP!>E#(gJJxAoZf)((o zxvf`HacAHIpl$=M1kUs3CPQ~+a^wT~nV;r=M4qShITpI+e_xw(oGsQ4wL>uQ zX2^Hs198GQq3}kCO`fS7p|ZX1FdG8tx|Jy)j9#rR?UAje+H=L#7fMAaw_Ff4Wqtw@ z1U2grAT5(bK1$%lCtB=jdM_GfuHz0a%NJaDT z=1#_5BMG|<|4fhJ;c_2jzC_EsfQs_@OTWKsR{mD>ekEdfH(WQid|j_d)i1%k^*N{o z)tgvGiHeKn9%=x3cnC&d#c+N!R8^W3oir2?rx0Uq0a{9{f!PN60(%b5e)|@a#qf!1 ztzlgz`r%q+FBo~oO1Fvfu8>+C73s1xn^1Zsf7RHNbB#h1IXyRki99EdyQgif7S$sZ zLuf7Rvd_Hdx%w59`^b=(RyEt5*t;VZFKaT{PVsFpekv8B+90?7J3zHNJ6yYw5|ABH zN^LK|@hn+ZD63d^{*!15zWkHx&Er~{8qtJo+QdTEgj=~OM=YrEG&hs|)^HKrq7-5> zb@Z5LTH&UFH2oGLt24KU@0T4zD^W<04K6Jx*XabBUZA0&mjLQ#mJJhY3AP{d`*A|?Bl_A8i225r3HV!Fo z7xp7QS`4O4TGT?As!ekS3ufDfI|cLBI~#pPPkAnp-wkeXB3{7lZ}ZAL4Y-@L<-LAu zRxIXB5c=xOtWbKbPl$m|q%rLKMo*2Hpy+nDJJHG>xJ zwNHzNHhE%Y3~X5#QDtczp<9~jjikkYw&*tGufwK1ckh!aHg)7B#-jeA{I?q`sdMW+{m#YEx-Do{<5gRzPQ zsv=xcEE}!nvSsCRmKct3vfM%&>iDEME!ZbZs)9i0LKrTWw-4e`;AVb-PJ*aqle6_) zD1SW&hQ)L;p>>c#L1oMcl&=xv_HO+|&tvgpa|D=nLt&y#UV@CW(@N@C`Q%89_WtiO`LC_IQ zKzIH5#}2z^3qJLpmSuBsyMat?AN(>De$Zbfn5!BT03+g7KwPd0ty|k}M#W`f+!%Jadx@AJSS96kD)uM=DkH736oVDNL{D>?-^*x9X>2R@UyWX-^KQ3W& zTw?g1MLC)#q0F&9SRr$uO4;6=pyZyOnY|3*ISfkb852~vPzLEbs=v;AF}r_DB{6e` zSxB|7>J!Ly&=PR8e4cIVJ~@^qc!rhIl|woKrM-NZ@!}a zI3^Dc7+Zthgw$~W)i5exhdfXExU#PrW1g!dSEN@w!}|R~&BVcRo&GUwWXoP|gBPTC zS7=g;{>_H)oDf-yV`yzHRF8>2^yMl!v-vt!JJ_I7JNbmB%~6>?JviO$EPhH3L8f+8 z3grOz%GQbL5k!)YtleKgV>E74K(kgv7|(l_R_ zoosdjx}$BBOLQITC}!h}e3unHmdfiUXuG^Fo)y)cARXtv-~83B&MOm}M-qdAaV+&N zX#OE1U!FsAho5eobdRLB`UK*R2h=g{0=L`wUIiGP{I~sjnE{sD?4l;^V{pV*n2!e! z_xyjEN6~OdoFM8?t+hsNlFlm#=Wgd9*Q%zo`O1P+GXLhkvrn`y=K8A2n08auMnJMK z$t4?B;KvoPOl#zsjcs1lshEO&08z!AA%1Afcw7)ipRxc$2+jt(02d?woZNp-?ms8@ zf0~nf{mV@(U`n0e{ zFD^0o76NHLoYYC~&E33Jb0RD$Q5FONQ)!>!zd`d31fs`J^+t>#)jHQ&ZwgR#$3dTv zMspo(@ijWiV~q$`8+D~o(VI1-jJOQaj6C_OHCk%9V-#&1BH7Mljr1oDhXJOv0aO`o z(MN>6?kFK0F3|AL@-UG4oNgj&1B)1!k}tDCXdgP0)Dv$ooAN~uSPloj6#3q!+$tPE zf9imCBHQj_eG-qb*d{R5i9iGS#0KzXy!ht#Z0XujYhAs6wUsvmev^C2S5yNq2|r%} z`8yyowqwT(MnbxA3cDJ4%yZmws^~2H%&m%q3 zhU#)SbAN{@#mY1?Rh}C$^(TP-=A}1;eMHY8OP#+hfnV6Fu#kO-x=BUv2xZ`KU{g8{ z+d`ahEQ3g)JXk?2er=G*6-mY`8_|l!l6jvkC=O3x0uZ9J5^qyO7Mpspz~p+s{<0Vp zITAIkPs3=ae%k{1CDde#(jcKU~sxhHxRMD&zF^xOlZ(GI_8{UZ@ zznE+tQr*}=8-_kRH2ti{TkSp1;qwK@xCkrUwSr|HIp^RZsv@KkUx(1UN@F*C`R73n!Q7{%1u83(z^mJIs%kZ->T*Sx^4W6zC~dP4td0O25Dy_)5_-|eJ6Al4`Tf{FKK0;)Ipo0t+EiD>wSjt?IJHu4lC9@_FNZRqKuU90+ zK1=(#psEeVAjXf~4Fln$G)TNvna$%3k=qFHYjjlK! zcasf-nlqXzu^_Y}E;bUbp>NCbFWGHen&9N4S+qvB zwkO&X=yoU+2QJh;EzmT3%Z;mmKQ$ZU5sGpfa3XUQ6pO-NiqEdxb~jfcF?%?_B@)%S zgTeVFR^)+EF6*0D`0knuX4MdH5@@P*ZoTTX{Vxrh7&_|*obm%ceCHIA6Qm$`^vHtx z^PeCl=HSQ^r966G=6rJ(LTv67qt*-|rp!CU_7m66?^pPbqGRO8T{9tY!AaEfeGYAiJ+#8Hy`>-0qYy+_NbO0li z*5$%AJ&EAGp7=US|Mmsk`P9XJxVQLYIT$EC^vYh~^Gzlvsvq*YEkP_3c*yPYV;A1m z*$+#?wNVv!0YNDq*8}5hl(Y_rbC=f-_+j&vkz1t&YbdznpjVVUzN+K}f|Gsy*&Z+! zk@}#)TW83>CgaRK#KIBMAKu0a&sah_E}#4euCyrKhX`aX(A2(lD}(1RKmN>P?8S+6 zZ_yG;X;du|1Rd3&{KKc8kjryj&g8)ha`UW8SCb#R4MI^x(%lmSGe~AXJi1VPG1xo} zOwUp;!nNC#eb6MZKJnvi*h=td?xdyEJ+G$=)C)#uPuNUq9)2t0<}{NUhY(_yT&%vQ zE=D*Pt+z3W9ftwZb6g=FTS#8#=wyHtHwmB{>&KtQJ9=K)$5AOYv+HIy^AGs_2mJm6 ze*Xc#|A62BC&2H!mhq>Flmph3UkuiQH-KE7=IDzkz7@TDQUu^A`QNFWI+#-ypR|%f z>Q41b@~#RZmZ7k9REZpAwLJFd?*}|*0M#RKV_-g)aLSB(GvGcf<3;%LTQ7aduK8OB zPdbfmw1ca7HQUul8YFN3vkQoCB&0v9 z4cR9~!1u}=s9CsBmCwiW@%U_BNbckDJ1U#Lv3m-Q8OH7q^k+Kf_8kpO&TI35#$`>p z&?L?tr&Lfm1faq3D@oet348a-y0eE`An%bsj`}lPznpjkacKbAEyk6e6FYP=o@ zT0-7Bh*?9*RJP}`oPa|* zS<$;31;^drA8Xi$0YfgY!I-j{9;<5v&keC2g=b->j)J_{4bVff1IT*-fB&EYPCcyQ z%=F@!?ne|fn{qCJg&xM>K_9HvHU|(?fSQjI=|8N(>LN^*z*w)Z9ns}lgIF_nE0rnG zXcGmyfgolGl8x@H8=!E{j$vH-W|7EEo;7bzzBg%bOuueoVLqJPh87x`=hTrdoAFfW z2Y}0Ct5_b%_cv}V>UkPI1!Q2&Yx}EZ_kbD5Ap(_C;#j}eG-WDp-f|4JW_tl}ps>g| zLSoxZ$JLQr{-s+XegDU#-;0|IZgu(mz9r{@WEq%VZfPznfgciP6CzssOQ8KLR?jX) zEKBIs#Wa*!Wn*OK6Sm=G$KhbZ$%`R=D;RzMM~xGC&;eiCS_6}W^^2hn6TNj8CKNM6_7IVRNh4uW8LM(PN_8ejgioJ zx{J&!1gP%)RJQt}l{Jhn0Fuj5u-@h+1R%nTrr^JaWf-eAL|}(^`kn4gW^d7;q7*aN z+zr%}wGL4XvaG8Xjy@5Ll`a~>hQ41uLgw$Ke7@-Z3rA0;Z(tDd;z`9HxxJoDW>FWb z!-}N6(?!)o-u{}hXR{~}Vt|b6A=lcBcH_L=c`u=e(`)b63=DD^T3$3#IT)ML_s^m; zlU-pR*z!5D9p2(*?d?IBsQ}+X5Dlh10?PW;`DW=?KA@la5*m=9zJY0^S$%0SS{)6S zHk`-{Yw9`H$gBl8h!Apn3AP2RUBCqc|BVxzbzi{|`&zjQ=s^94ujR!O-IOdp&YQdl zxH_u0Qa^rwIw;fDcq6Rj#yYRIKAJR#aBT<<)z%pAg>Cu@vqQNQNxwN9PQDytj64~jW(sP-}AJa3@LJo@{ z;Frq;^i!VW9u8+t$&0h@>UlX`D?daYr8k{!8PKPjyM6#zRTZ4E`*usthSO%e6P)RN z0q|NWNHa2+KGro=kp+(sW2aQUums=IwLl(}k!G-(lz_ckzp5D#Yrxm=o46;ol=PI< z9DeJ(xsp%J8iWNF1SQ88FEd7b0dua85gCn0t&f<~E?neR^r>Ia*x0OZ=XWIiI^g$Z zfHdG80NhOI^0qdEk5%pP|BWrolO8MphI{=3Zrgf#!r{#@hbKMERov=1Po}`eft?v` z*davQ#-heYw_)hE{f`m;#|Zypg#VXggqI+}_I!5J)dnws(IQcxR406ELqa#R=@-vK zif^0DYvSuk5!Ixv1bNz!pU5R{R2EvPpweR)etd`{Fx%254FO5Y+mUR)k-Z;!E^$rVse8 znC8e7TFRt4d!k!6H~(<;(t?1l?|GYDg5?$pNqpGq=Wsb?4PMC5BeA!fTr>uOSxyU-vFQaVtg}#Z1WIB1 zS?tgs7*L0U0j8sYT!%RqHa@(IAeFqujoC5y3)Pf3vTuY7n~n9dH$67L~sYq70$!8$Pp9>9Lb z3LE^LnUy0U)>;Z-Y6WMdaAqZyp*PV3{1l_=-G<9Aj(iK{MF@^NifXy+_+CvV24lk)dgfoTIPshDFX%^p5m5ku5foyl+<} zURprEO(N2|k@vG0RIH|b7bySg>MA4trU7xld>av0vLI%rw=_jqIoY=On}}@h%}nvd ztvxQfST68F&4cwz)N?q+i^h;Cn`DBLi=|}|ZD81CDOmrFEah=ba~(k9(mXi_vXAno z*B02i_mcq_K;|o@dz!!h%I;>OL3qm-pvp&!lDgf*?!8UzE|~F%0mZoJlD-&7iCe?F z>~iX~5AGYLKlyy%jft%e%;1vc;2Qcpo36oe z-g@J=2;$y=VvB6kUE`4=m&97`Z=iZ+J^9d!Y)gpYK&8o@u|3jp<|-AM)HV`zb18^d z(7Z0M!9DoJXlPaW9=rs|uh$I5`xEe@8uH+~_#!W!`@wBwS16(Z1;LXY=iyAUOy|^i zU&~fX0YAuC+hC#wHv{T+oZR8w^tGtnj}pumnb5Swp!W?; zp8|7YHBcsOs*F53*lI@`Mjbht(w!Nubw=2+u65T<61Q!lkJGSBs}9OvXG!~h^x$QmlB3!tt~ zUzngCKM_RXw~=tMB-)D6$WTX#@J2aAv|iiNC25x7@mez_jZp^9 z6Ew)qW}XGPVrr09-r8Q@Wt@wCU0GjoQT(nob?@WI7*3IqwAKFp5>7UK(%^}@(l1*s ziCT&geM%#g6}Zld%OW(a@a2uNYG8f^2cnco*uL!~$@jokUK`>>sY{ULh@U5i_z z8F41lKy-O2b%zraar3Ht%$v87Q=b|kp3aRtfEd~Y<0^ZpT&@_|i?;*89)nm_KFkx)s}?9kr7`Qz(Nc+we^M;7f?2 zP$8LAclmwhPmkHC7fK$@cd+Qhpq6gY*W!1cI~{2(ilO~RkTBko#L?XeLa9#- zL_IptK>)?VXp=0z2KpT{xevGXP$Dp|*NNcocVv1eI=l@2hTQmdL5#|TnNpVl7eyxe z%gEP9w@}}uR{`L?0IezCpe;dk)ccY#_$tp@=3@8<^b1|ZfNAFIG0Qy-n8-Sn$Wv{? z!^P+QoE~j8zz*(tFGu{{=T5O#x9@;_PkgV(yc3{9IiOe1?^p!rhO(*rMyGETIKlX& zoZMy&!8s9N!MWP$trNA`7-m*3sImq_HySTyZ%WoI-r;;^QTv^Zd);6zz*1GOU%$8z zOI2(ujWmb@3FYcW*0ir8T6(X@Ik*%^wJ|5iQ_7mk%K;n;U;g*pF`Yr2nZGnJU(nf8 zRG4x?V)jR>7&=X9HPS~)f)mo!CnUGxK>J$L4;37f43Mn+(ubri4Gpgtz|&x84N2E9 zIIKpzPKDgZ>UigMBkY;F8mVO7H(gY}7ore85@>ZDWiiqOp2l>Q3A7>!y{E87kB5@B z=lWnF%bm~JcB?TV0$xBr0-x6-LgdEP+8|B_{c-{`Z#g2;cC__j;n+@f)5q6{+Ex`- z!CIPDL9Z`lv5<%2-gFn}ipWD5$R($e0jcMG}?)=JOkM2NC$!_y(%@ShSKT%j@hf}-wdWg=O6aWu$?a&|9#%%fRLi&z-W z=u=nEvzJy%#07U zD!tdTOE$Xt0lug7yuMy?Lq6sL;(?YziQqNQdhC8etHx`VM|^#R*z#{h;bC11bepef zR{E3Q0g#5#dIh&;ioE5XG&HCf_qhGYr9pLNHEo^SD@a|&YUUL6Eqgm`K_a5GVSZ}wAKyU10 z-IN&w2I-D)9txe&2!Je}3aB$Xt}2J#sAXDf(`m!^Hk;?&uNGokUmVoBFl`?lC@QqO zpe7B)QHM#5-=#&4Nh~7GZNcoys$+9(H#O;|3`WXia$Jqv$ZaSDV;e>lREjb?^FiDg z6dwT>hlwtkx$|b>`@+C{vr5k=U`1Px?T3CaL@U6*3HoEi%AcS=9VV@BM{}RCn0SSe zeUtd|aCg;1!oZYn3j>s0uX(en7+)>Kzkn7nOCE;{6Sl@F&kQe>$3WPP(BE99^D)>8 zHOi-RPbbJL*=pt=*8C4^{)aXH!5=611PnXLB&>O7h>yN@L zQjT*N%DOev22(??B)`YD+$30;}?jv-b(+QD}EjtD?QYj`58z&qBASWh+(uCw87W)p5c zhy>wGhykJhWvP~{)RNeRk`)NyZ3`rom@{i`g!xW*M0=}y*mLb=P zRP%7r0E>5@d!GZ^FNzsZ_bO#`g)*^zZb}nRJvP4o4%1BJQot*ZRfZfoPVyjwhs6v5 z!l*o_Mt~yG#amK}>E(!nf^NWCPG08^+0tA47If#>1a1hnqU7hXY??1g~hr^t(o$*+9vcEZ|@-wd2{h*U!{e zc&~Glzdy56fq9`Q1qw@zassrFe*mLocam*W0yOcyb;1m^K}l#m3r})r2Gg|$ES|yG zDJ^!q5A)_wmS)v+3DRIwiQ;N^r}W^*TA~S7_)7i3?jUo^z4}&Ih?cPjoy0zZcCph% ziTXpnMzY(AVUM+|^mJLx^L1P%m?BbW1V)aW=zzws=7w0uh>-f~X^Y8)cHkh2c5fL= z=hF9W!jT2*_m(AN0=OB2+CzsLEq>gEoaEi5zVvVS<`7jzQNRv_i(a@$j@GHgTvd** zz`~FoLd^A{3)SK8&ml?#z8_z0q9Aql!>BJ^obLXxc0MVVXtan&_ z`g*PQ=i&!(k7T2Ay98NH{baGCLvBY`qbO=s%^%;XV8m*43uIusK-&+L9)(id=orb5 zT)FePzTx(X7ms89BR1_#`)`0=sppr=DJ92*@*WLq?FgAR!R z7*JE@PV4zgN5|lJre1nt2dAN8sI&%OD}}yNz*nb(*#1LJI`@^aGQ}O))6-ii%Yeg zFU{F@9g+yF;U+?!;DV!ZcDzn#V_i2=G8>S;;AJqx^rPLjbY+yC+aLC+aD*(WJt zF;_GV{n0=ow_>gkeh-*bt?nf-6z{la)xeuqqXe8nk+G=waH%UDBUzG!&5u)E^X;mk zzu47_h#u+fqE{D}{@xPeT`|V00|$om@uoI_zdu?@^F+LJjxK}IP;zfGvt;S?R6C?N zQjO**A@QIyAa~e&#&*$3TeMcI8xtt;qcm8BzAH(wG!~}C@NSX1nA{s{Fy)5`w@HqE z_I*Ll2VdSFhnlLEX%hh)1I}Mf&fspn<9kA29}+=%41#d_)dYRZ8M}Z9y1GXnJ(){c zKBSKw;J+k@ab_NFw$OaP>#jmLvCw%CNr`Fs6?Uzn`=v@a<46$j%{bXZe+GG4vX|(1 z!&l2p_otMx1);p7VJneTqwWudZkZn$PeSx}iAsHT*@&hEuWZ0er+ne|+Tr?$u)xHqXBRtbaP zFt`w4xK8g{k}uBAMYNO^8cCB-Ib-$|VD~xe8-HxJn;1}sVilbPi#@V1&{&)e>{gqWdY+@I)?H93+oz6v`vx;(KW}?0a zz1uJzz#(LxhpR&d6q{wA-6Xi3?m8XQj~2ZQ6%7xcNj#Wk9KOAyjeAtZI{8t)HR3Y2 zDrMHq?QB8bNOzR%Lc~|EKGHz|dl}*+D4JDGv7$jG5LC3JoF8^=1Y zyvv?KrFVbq^+oFRA1?h5m;PS_m)_%`F1RIxX|)0ojFJEw*4uHB-A*MOaYtxx{3Q5} zuY~nji3`Q3(*vSi%!&vj-by;&nH~*M#FSwHAP$5vQnxpDZkUj*68DF5)|Gsg=a1?6 zO-K*S4J5N{#SM(I-7(ZK-p_{L_`+VVBS0e30iTNJ!)jCooziWck#hP0w$YhIvHyM0 z5LN$>SMCCh_M_<%bSQ;w&2`Pt{J3;z-_8@!1HLJv)X7An6F<{wouoUh)2(i%NL>oU zO%2X>4gG)x3aDx05VYn@Eg*LfB6e&GUJ8P!zb%%$KwDu@iWAnHsi5|!UMhh@;77I0 z$`$!#D?;tyM-VB?FuK(f&|V3+JZn_22-Cn=~6b+W)N4&4o0pr_u>!q{<8gcxHjNKyDmOYirh7%Oh1dHWDfLj(P$?_1L zCQhROqH~jMGIpP~W<+K*(~`aUS_wXFj)EMp?gRCn9)V5eJ$If2_i1Oefa8D)5o5TY zboh^#+RRV<(Acv2W=`pim8J z%ajBeKQ83K@bD7+Kd$;8SN;D_u6pwp7G-BHQp&`F zYrQ5{GNU!65%LGV0Au!P^@P_73gUrB`-TbD>ZP9N^JvG!n!=XlCUo*n zii)~8j4X!_^wJ`~1)C=Yhxp+{yPbx7w3oz>f#&r<%|K%-i@|{nY9Ux0D zgL=Qd0E?CT}C2KvEPw*D3msMO_zCSuU(T7_l2~w<u7J+|}qE&@B-r3Oz|e*0laJS*i7mC^X>s-3^y zi2ji&T}ndIhAlj#2_%J$iqL*hmGNfy+z+E9G{!LzVGQM9F+{?qtZE#kXr>66Ch&Tm z%*+bQ8AH`WseU-=b1GhXQBgFgu+3O45B;?GtL{i9z)jcm@cHCPl$&Z%VLtWed_H*R ziq?NaTFacP{`lUU1bmg>nTbRbcDP3YAv+L@QoF6aD5D_AZEAN~l)%uuJ_D-Z(wW<~ zTJRprX@C|PZ%fOR-BQbY4-e9w>OP$lslR!#jpG4E^QuO}A$a?2?1^v=NoSjqwkmV^gWF{~ zGT8St#H2MICu7ZwGd-VdpWyR5%u{G${(f*nt;rjL0KF4r@;Ku-XpCkPNik{o+{bX_ zp^uu6mP>kG1$FMl*vR6#hCVL@q*pwr-fZ3(T3IaxPX_0{Xw-EFfFK@yW1eZcR9_}( z+|wJircQAUJWaGxV351z+TGB4WHl-o$I79Ckt#Q8EgpdGh&a=WrL4&dk_+0_-Te-q z(K5WPIJL2#DyT8tRp13EO!0&GZetWriyioqi4>V^ugGA&lV@48bxmyUizwY;G%Mtp{>Y+Ou!~mlR+_ ze;dP?EeW1^SiEC<2T4x>0|fy4PF69FJ3Eoi*un|Uwn1>_)_$4nmzwg#&=@?^GEsO2+dCzVtle7*edbfl4Dm@&!)T(bsRiD z@4|Mqwhp}a%LkE`H{B-1*q+kz3FB1Qgn>S6u~&%}@GM99Df=6;9-Gg??2l#(`P0rC zp4IFb7$w=Yr5%5sEb78mbGXtQMlh2gMWIYNt5#B>U=4-)9At(0=rrBjM?OP&Bh&Bl z;ue|FhoBVwzkxj-@(HF(&n)|H_iR7LDi0=S@FD%VxOVckC$Js-Gq;ukrD=>Z`i$e< z#%+;(Y~A0^&{$9fO5K#N3T{$t@GbJV;|8P_ZJV z?KR0kcJuEmvILcXE`h?cERK=l)iFfe$w2ZgBIMk9ICMupX^pyr9ifs7~;qyqTWhj125+{t&Ot_CChD{G^KC!}(}3#`%y z@aruyM@2t@C=`B_=_hVAp(5sAIxZQfL{PM*^-&p-Oz}_>2dNY^r28Cv`_%-at#a=! z|B4-v7i&~9;KJ7D?x)>_`=`9Qraa}2bB3+Wy~raD&yi_}5icNY!}IMOV?zPTcp^v! zwtBo?RggW9(L~ej%^>px>K(F{al>h zllB8d4K0$xzrs#v?lyZ3XUFN*wZjq};{CqrHKor_Dbe?c_#%qBVg zh#_Rt(HHtXTW-izT8SFlt|*#rwDBxkXXdve=9{^CHk(li>adg3E&t-H(v# z82OX{e8W;{D`0d&qPrTN143|(X`EamKRk_V(rQ6IetR-&h*4t3LaSu%WY=zIT_W)X74Ua!I#MVdu^(MrOV_`Z9K(nm#!uN+gMo0WM|$5xkL%HY?Z z5tj)27(@(>XZyz@y0_FJyMU!=p-kr=Fj&3qPb3^r5u@GNzJinCfs~S~%ariit|8m6>pYzR)-!W~?_>CFe!xUr`C%cwDp3>BrZstzqqxN~ z{>~C1o@UTK&OX;jb8rU*iUu4-)V1CkaFBn5(t*|eh1y&y&QqVYaDpQp(FJ#zwB5Hj zTs!jJ0pm2|4_;fUp*=VF?DhIhkoWu~VOC~WBNP_&H7N=sAc3syn`=FBm6gwbMCO(n zw1Ga2FfZh++CI*qfTqeL#5tIv64KD8e;@=E&x|wkf8wHXISXd<2puYdn>8#g81Htp zh5fQKG8E8enXX(#@xh#O9fSEIBAkP!sfv&t?e#mwj%+I6eGbad(rf|4!~#@T+~A0y zjldClKfWs78GuPpC3oF~)CwT&;#IWkQ&R*G!#(^b*SsN+@gz}xCp4<*G^+5d<%00( zaTfTUZl4vUU}vuycD-?O#e_0h{~`g{`E@E-Jc)<{clzBLHW~8(^)1DPDi<|yVDSRu zoZw#-kPM=MnyywMLexlZ?-3`ZPo(Fd?7aqdHC$_tXZ+|U6R{jX^$LJ$%;=A2TC$^yo(fn7Alld|%I9pn-EXzosyIj%3Idyaa8m3VP4}YMEH1Fw5j> z4k1*WTBjqjf)?3O;a2%b7m^Rkez&Ar3sM)n67?$3py;wf*MYV#IfPYUC;E1mIPZ+rjxgaoO=4tmOyDPc&2dnI}}-AKmH;uwKw(s zaJ%}u%D0)6qK9n*aZ37hu!{+C*(kzhbeoG7{_EZdnLc6Zogs*=m9t51vVK?3isawS z`e#bui@atycG)z+=TP6Ky9;#uHRFx@dLq#oBfRYyNnyr9n1xSkWcZSCjz*E(g*7Bi zFyy`N;5oLt3XZ$yV9>{h%)ap9mD6SdrAnC8b>C)S8aemm{13(nE5LaTYNb+YhdHd& zNvr9uYDTY%qlnr1nBNT0`}069M^;?~f8YnlvGYS5RRTcq8jOBdB1QqZps8?FD`9a? z=S!Vqb?Izj>cQ_R&?Eq3E`waQ`jfy4f+0=St=!-)7x$}|sg)o4dU z1jZeq46+Cqbl`4`3XMYm$f{+tSXrqC)W&!G6`ofJ7Q@1@+BB35;?yUNqItZ zl4%t^J%{Ud{x>0?@9^k=?g#Q}XXq-H6D-~Qx|(LOXs zas`STOnK-TedRe?d1ih9T}`MuVa6d0fAy0{66-g~JD$gtkafg;-^?5J?+uC_3cIVh z*-&9Q7>PWv84J2-2JKkuY+ITaL!f}RQ%Jdt_R~|+Mq*;A8NDbpIVFh2^-yK|NppGZ zJ#f{%tYUeHPG`k0pk@4lJrp}?8q0xE;wWkhCi_n(J|_|bpTHM~)AID4JsaZsoYK(M znV_zj`V%#%zM@zi^B#4-wTF8Wul{;`4d>Z6#T#%=@!;}Axh>>Q26~M?S5TU6ElCC_ z$RDefW5Fjn(ag6Yvv~YYjNqTT4Ig{YrmB+_G$%SN+A;TA@0s5bOi_2`EGO>;9T-JS zf?!{eeHWTWt@H!+Fdd5~{e_vPYUms$b6LknWnCnRC!YJ<|BiV6l&Wc*<-id=9xjtopnK`~_iQy(J;2eECR9sDEyOc!Mb?~LdigxB%w#`O9 z(;{p}C2dM9RhN@mEot3Vk>)`NDm&G$Qd7we-Uk22C#9EAlMb`qFg;Tduu7`E;vi32 zR?mC=IhNvibw1amYlh>j>LWk_2ixg!V`*;PtLdmA6HV$txkJEvd=Y#70Qq226H3vo zBb;-zhIhACG&l|;+%cy^kvpFa^g%B9z2gvE=wq{w?#ZQ(aHAQNY_xy(CHu?2=O(ggg_gyxVLpt<&K zRgA847L2sttVs|km+$|Ud^X#)lCxalE-dPaEso=J{8*F+qtf=pNnfP+T@TeD7BsoQ zYRZTkP-wa0x9BvjdQ6Yh60*U&4ta=`6SJWxQ5$JZgrX?zlc%6SHN-BMM^zpQR^O5k zFs`S;)y*Q$i`R#sCkOaW6?Y~90s3O}e!|&gnUvz@d93rG-||_n^J^i2k^PO8cm>mw zTsvhFZ&`5Z*zC5gw7?hZ$Ny8&U>MC+_c8Vcb<(sVL4H5m(A4;bhZ1(-??Aom7aP;R@CKJoX3 zxEXmU>t3RbaJRb!u~G#CH~w6D(4gBS45cs0liNTb-&=Qk-BPcMj8eR4G~u}zZjFFU z2Tw1Nu!nevVM@c0TV*OjZIW~_+rR)^Y}OOuUK2%25~maD1!JRwduTbkE+nuN;h(`@ zLe>yDrfA!wUx4WRCsJ(NQ<^SDh2%fltAxjd*M5Q2ganvz)p!Gj!(&sIW$>1mgC9iy zSD7ighm*JA@+a#n9l3^8dzlJz-G6Ak9l zHj;NFxu*c~t?pK1syZ=o_z$A2!}w!EAmlG}T_|{MCoah}74wn!d_9aOQJ@?fq0kQ~ z2IkqxTe$;PK3j)`9yM7R8`=v7zh&Hj1j(i4v?|>y(E33Vnp05Eg>zK`*@?j2xAbX0 zSApDxZ5KNIDgF9P@5Cy)&QEW4t_3fG-2d;~W?ziQ&N*J&H4H`AliX<~3{{_>kaPW(cGS`rBK+sX zXc#ubfb_1sPGXtC*0W};=@V|A&&kQfE^oZMYlmj999B^nO3%k%PshgQm+rRPhbO>q zJlCn1VJc@UcyF4+Fv)1KQB557!+y@D(rae=25s|6Nk$~B)Y+jJ7Yg1bomHq8oE~Li zAL4)#75haobzX3JhNI+!lZG)t)QtgxDL$ShF;XQ2G#2$?4WFiKyoExx-^YuS9O z0Cn{56|NUI#FZh`gt%hVQ&;f!osHJ5Sm7y_1PJqZV2;+9w!NkE#NhTmnJyWa5$3tHM5%ygr&Wb7Oa>p z8#E;5_5sbzflR61bV$^n`<9?BD7O6L~{F5Xsl6+n>= zl}%TgK~ol~Fqqn%9+J3G!NIKrYrWinB+}$U)6o1pil^Y%Mcl(qt;k_px#HF(O(`G_ zF@?&}4yuZ0{OnGs$mE!;2(O29-AsW#Y4;n;X4oj$!>dB$Nt>92*!apXc4<`5HC{iG zrzkDPwx?M-o@f^pDb)W$-97dQ!vNu8UYpO_wr$(CZQHhO+qP}nw(Z@%r%l>4ZNHr~ z?f3ZsGn0F+xdyo+FFFiz4V1UiEMN1X@g?iaWjMC(d+eSd*E3_KGm0#6nes(rG_@hB z$H5gduu->9*$~#L#SS;ExaD9 zgKM>rHADd?iG^BXHeY(O=Fag5q=qvQTyJo_i&5!u+}4N zm5dm&IfNLD6~WX9&xf8C!JxIvOH>&(t_MV4pr`=~q?4$+H{atX2pJMa`Bb=H%8WQq z?pjfLfm%|%dGdd|A8C0(89QLcin+u+MvQ9_)zZ{GtACF4W4~g`wQ#pN^cbIbX049L zR5=T%;77P_`vj?1plFJv)=}knkxXu>+dPolNc_HDm{eRWYCdX88f$4}KUs>{)%}9( zPR<2`J#ODLJ)(eY{KzoV)3^W0tW_f?QiS%=ool#tV5T7Q>whn&!bB`{m5bThdA{u2 zW<~WJW?YONkg7+f9{+?R_q?nV_RAvYI9q(AsAMr~z1ar~mpFRit!@d#@Xxpz2y$%) zRtl^7*EnMWog}1Y07$1NC~sSVC(k-@Jo*kQr4BDgLb8o-Ceq-`<@+WpD5I8chpV65 z06l2cK_&K$aBUz5YS~1_u=8=U?Z5wFkAm^uccqciMWHlly@M-p^LiZMxV~@s;sYA> zLq(?4j#f^aS`z*M!Jx3~T4-M>;E^gJ#TtdrADR7JjRAu6hsmNG+BeLzuP>F7_f9}m z()lFB5PJ7$l0}b^M3Nhfg|4I3Y*S^q#@STpxT6s-wFzzzb+T)sm5Kp@PIMMtdA%^)>`Z zFnT9|F1cp*R z^{UT-64#*H+Z~o8v-4}*s5Sg;+i{{t^T=RuxgOZK5AT@nRZ{URpTc%H7V!LzLs+?& zv+kj-yPbF1sT_gt6=ticm{G^AUeqlP1QJK;46?P~RgG)IA%B0pHVu}yh1h_a zO!dEI18EWZSB@rXk42aZn3>JZ#sr`Gj*J{@0bFg%O7?ye8l?X75CE6P)_e|!rW?(S zrzDiyUUQGRZWj}g^Zuq6V0wi#DM^av-1jdg=y(EEjCa&&lZ=(>MerH+(^%=Hw>3Fi~ z2BZ?Oej+sx9*~*ZV!qaY4sRC@1nr)#KpcHud_(sJS(byd=yeRqU>jiPFSK~1pjYzWb*nY#i7Vh{ z-1hAKaO9nVMGLab9z7tu!ml0O^(qGOn=|b_HrwJ0HW3FD{-UT^rG?Y%8e)yo5m9d7 z^_atjj75}809+$maBsBDqT7&!$(1Zg_Z}1_;wOYIp_1v3j?n*n_GtgCRMPR-F^7?k z)?)t?mvX+Sh;Eo0r&;}U(wSIg+at6J?g%)Ovp{2-pzyYNfbdeda7r}H9%jBwm(W7r%0Hm&|kU^|Ip&rZNJ zgH#+E2V&C`+-6-;w@MF3Rm_MVnhx>*dU)a((h4wNqc!Mup_ss2W!THmO1|RSqcqus zbcLEG*%#zIRyisIOWZu+T7&bosKf!z9Do`F@}^$Yd^nXmmF#3DYA=LTjmec8o$X)^ zxtdCl`g{0Ab^wf*G-T5v+A$9(6Uqc0`gspZbF@vY7S)(thWp*r>rxE7ZtuAv3|qk& z8%$ERU}W#VHx%y-V2K#~5(G?S)gci!eNJ}$P)|Wqb$we3D`?h^1YTe}M=XJ#`}KCh zKH`BD6S>N+k-J$rJ>h)^K=aGw<~02aus}GH=(2eUA8iECiQZtRmXZdfcIWlkC!`$$ zMq!WxG-joKv#9F@yxWbh0T1phc9H!|DHD|e_12=Z2Dzq1u`x|CQM z1p0pA%WgUE&&OfiZ`0)$HyV}~9~mIa(AG3wN8h^csgY{~=4}dSV`+`GnyB?$BXP0Z zieGTEF(`v=W)2tnP$2x%rt{Xwu*8q9his;fJA%Yw{%a!g`s%E5P@=GVMkey+IWsVS z{$M$l3$kLqCY&9eoGX`DfLBT}9qRx>Aw#{-DX+u^(zAN=OP4omF^2q8S~6~mA)yh+ zH0MH#I*7jjElk$T5|j^@qP~osol1SVLY(gOz=(Cyl|@~|#sKd%Kyxk%eoT|_K_B5L zHKtTu-JzJg_f$Am$!%aRrcE*hlTT3*OCqufPwx~Cs-YgM^asBX^-ZjAQgXu@62;X6 zgBt(I4e9u?R}k;y->krUp911VV(YCaf$WH<|HA^QnAv`j5-!tByNPhT``S6H5G|T< zUl#c{r1MoM7|<2<+1>UqT~NoWDws=UZ7p(9rpPi@Mlfff38Zloogge+4NAnuyP7@j4UTxjXa3{`J1 zpYNq-g$cpGC;ghIf{C|+Y=1hL7DLsdm@5|xlD7=dZf??Xu z4M|9RIZha2!c6&7S(8wF0)^qBE6eVuDhdw8zl0;Zbyq}tF4O{;Zx^Y%z*wz335T25 zx662+Sj`4Pc$;of8}7zSxU-UAopW8ckk)^`L(>PE**cjB&+&Gw?;-fz_6tU258`== zsF@BUuGn6D<2%&Rk;dqI&#Y1-!7ENIDv8KMeuT$>G0)PM5Wp~=k(UAkuLgCG|9z`L zG&u}by7^g3#eiYK@WGm?ChsRN-8Z=$P%MfL#xYR>=g;+!VG-( z&(|Tw2GNRm3ZyF$P^^QUSHlR0raDS$dyXW7nq^G$}(C@ACDxjADvDpYJJh*6=h0-lcdHRR7UVOz}l-7@> z(rM&Xswky=0?^kJ!>@Mt2wV^z+VI$?Axu*Xn+A`>l(0Ekt!F)@xbmn2*o<$)SMGOYwe@L+ zv#>SHV02^R3QuuhpAqrNUdxKonB{$85g3(aWA(q%zMpArjh;WM7fkKi6gxZ1M)1_wRLH2 zlIu<6D;=8BgDA|N#AHYf&1d=5!mMj*IA_}bo9D~W0ZuKEX)|AL@ri2F-&f*nziZ&& zLjkm+7fHU{Iq}F&==Cr#*;*ItDDQ*#d_U3bEMs8yiDdJPgeJ?Pj>fNsCT+{DmVkem z4m-h`*D+Ex;Y#cSZ6%4qxy5RDQ9(&UCspBnla(+eDgPva=*^{TGEmPHMzq zjXe}$Vu|N@(C6@#34EK)v%cloSb7JDO{&VUmy#7tAqRswHfX7_0gaMyBtD;D$sB)T z{ih_sQ%1u_fJ1@YgIO}}B{wv{bw@g(P|%K|Wg?niBO+WIhm34SQXCm2>Tk%rZ*VMPvrQOZ+u3Y-1QVPtw2pMkc07Q?Q2!4R3(_XTG5 zKD2wAuY2S)2G#o17kQCX(|R>g+bNcRvd7%sMvO7i6LqVFn@pL|I@jZ9JwPR_moS z1e86%CrU6RhG1ZwFv-x(lf=|5@I^NO3t{GC6_u~gnabIW{B#W1a?Zl$g((e`jol>M z1wx>zvfWN{bU~^>jIeK_JY@mVr~m~qAP*c9Z`w}{p)=K}UmJE7GI>4um1A8; zD-NPx!;pS4G%1npD=UWj!D&T86Q#=l0ye#&&wVM9eoX)Z5g1U$M_@Ky&RJn;2zQ^r zLR))ZQhqy18iwo-%I{4W)mBstXO}-`{n*^Y#F<&i^gVWJ+M7I5KtfcoW@QQq=#jWu zu;=@b_u>3^d))!<0D$$_T%FP_=bOn(i*K;5(hBCFuvNEiN1E|*n&SDV_TZ3nR5qZ& zocoD{-+jyZ3L$-tGzJ>x3}Ad|(NI6Z@drN!)Lp*#I^DwcOXiImx{E`f|8#uN|Du<> zXpOWuuLvUQVXT+KXJc_SrdWvQ-sKP=?(Tr55#D`;_jGlM|fz$fzbnG%#P*n8#t$}`v~ zZcf!Nh*o3=e$@f;mmP}d&+pIOS^T*paKdzrki#cn@9r;vZfHrQJ9K4pX~MAsYYgz( zMi=r{_FD~fD;D<0cg<8>W2mC(^CneP`>nm(0II;SLg^?j2d#FBnNCH4tp*wMh-@)z zw+F;4!B&_H9%fLiTSLdPU%+S7I`l@y&pjYtFnfL1f%xVLtY9~E?O2HWdKWYl)S)gu z!1jX=+-0)jgnC8m{H3hl>1KGj$p)ujZr>e+Bbz|P9JRnW|8*k)!AuQ#AeB`|sacrQ0cu93!Su5ua-zt$nmfgq{3> zBDa~eJs>K1;)Jnk{C3(%=$m$WJ0*J4fRlM4*~24?_-4ht@_W{_wAGw}w>?LQv9GAJ zt@h%UlTmoBB|z2es?@Ufrlxr=)qtO)x0$5q!eu-RVv*bQmySkMblBqPOR8i@XEKgo zmDD$u%GC_ng``z#EqYuwQ-Q`UNt=9Wqbj|hb5u#$Z>F>D9+X|ToZxz;9m+w}|5TJ0 zrcp=$s|mG*gzdm_0k&aKN*%kWNj0m&%zkbn&X29OcxVp-I~WG)oJQ2Z;g}V+8j5kV z;_f(Oxhuu*CL9`P8?caTbKDzFp`^TpKyp#E8^-|ebla_=77L#4pX0uKRsd>@sWgX( zwl9#Tt-6cznD>Zp@c!1h?I0z@J8Peqw#^?;j@X~?DNnKj7@c*^^JO>vt+y!Ce&T;5 zZ{bSy-W5Vs_n46`*^E^~~X z_|Ex#+8$z(lk`ElMnglbU#V0zSka=0bC9#kHICl$-ShEUK;Qr8OoJ8c(xxhW~W$Fif- zbJnH1DhPUzy?Q0#VHmhRu;ZA4DFY%ZPc1s|IA*EixZ>8iOIY9re%6tv zmx<9qb7Df(&=Q~i1>+Zk^54_w40lS$YKtfYIR-uqrYOsQZGU7BD-~K)cdtV@at>7!|8*QAXT1^_XMAYV5dp0xeHS zhLE||+mbaJ2(MP>0a#$k_yXNh#B|XyLx zWb^c0Pt8ddj7Sb-N#aQMrz*+?sXHeZbo7f@?L(!e{(|$bB+hql~7I=^Bp2zgl-AId{n0kc}wjJNju{FTY|McQ)tfIi!DO;5sISla#XYMv2 zIhZb0aA9Hkt^+&ZD6=#wS+Ys|CD;H;;u#*81+DY0o6W&xGqE zZ%N%#Ap&%%q_+5+6^Tw9CH*@`EY@W-OLIf`c_8+Y>ipw5z)IF5(@J~>EtUlI;=e-y z1;PuA8gdMfxCEIO^A#O{F;-c@K0JY-=hK22HK$)|; z8#AK;h`KPZ$#|7n$Ac1zOdLcHv8t%k*ks~95Mprpc?$=Kwj>b(*Lu!H;JiPStCYXw zsPM6`zAW01MQJL63wmJ<*qUp~spUcM=zkqwcaGA0L->jx`W_ie#BZ&Q)qsv#s+$cp z>IB$RM5w{tLy882*Mi`6VSLRaFx2xlqqEROQw=e>VlzGm2YofyY7 z2PwV`h(J&Hl)FU!+$gZ($JfN(9i)=BZWNM((^mC!(r?HO2V|uwZ;Ui-z3k}*EgcpN&a>}1=xrfGj}}v@jW%6})>%pIF+zL$ z^4Bs@r$_aNA>~~91kW=qtsQ&1JkVtL43)cSW$MM<8Clka!Xk1y3}*k>J6%)w%Ppuf zkVR;5%l=?4T9uwJQg(7Kv{Z3Fa#t}|@2rJemJa2Zm`-Y)^8@I1Fu@L@%FfWdRCICfVg~>4hwqXq>nd|Co?iqQI%z`#iYIL4roEE zKIOz>XfFXMpbs+*r1e5^@H$hvx2R1^Brh=D(5?j7&#*WB>qHUrl5^mgLp4w>vL(sc z9cm{`$KcH((h&d68SXWp;GD-MH%~cQH(2XKOqiFLdRQy1i=nW7ekkKQX+s9z#m1AV7Ml$}n49Aed?q6)Z zW&ZD=e}=vBob$jSNT8!)%Zy!4vKLk5jsC!?%1_B6fjMx%i^^u(xVP2!2PB1dO0$#X zrW3l3s!aW_wZ*eZ2ecuvJQcV#ViZJ>R|V>JU^>seu`Qcw)JcPS>dpC-ZcG~nb-H|TPUFC?(okEh9DDByNEC&BC%DHm?_<5-+rQkf}q*`Z%nrl)gwee^2>wAMEW&*R>yiwBe zKV!;>s8~K~i0L^LSU%R%4mlt}>z*s7y_erEMjAwe26}SXEfV&Ti3-0G1l(@->9oBy zE{l-{BU?7TX>jU2kkFjvANQl@2fGRjeG36%IW&8<401~%%j;2&+6a4ux1YES$${dA zS@560w(%v*b48YMVV#WDC1V56R(ee!CP)|<=fM-AG#2wdOOm4(cWoW$D2SH}ScIfuEPXX$0`Sw}Gxebu5=WX$OP73m&a_U=45v z2)x8@r(o4M>yF#Ds6^!PkA}UE$u>wvLEoPc=3FkMXO$q;UPfu|AC+=r!3}*Ha3y-( zwQ$+JvYglr&;&gh(mPoTj3^x-VOYhr><9aKYi?dA5G$llBr-9cODN4sL~6Pw1p-yQ zay}vF^K*&nEPDbteBPhmuSIs%U?_-Re{*{ThC`I~ZRYbrOoU|Pll&m_vz%BjfuDlG zp$4N@#!-NATREH6nA6Q%Bm@O$>*Yl5n!TlD%&-!ns{G%-QS&I^Ku2;3I22Bx5=Z6asBY)mPM zz#8n!t5nrg&qBI@focY8z=)}2+eYuJfAdQ8aZNYcU@UAoG`DVuCujrrvLnm%Oz+$yf+%w>J zV(Jf4s{c6ibx{$`N8B?+2yvfn9Ce4PYUUkh`Qk}IaBe#i6%e#nhjShPHFxI3KbD2- zIy14$!yM94;CI&oO11tz=x#4ohDHT-fH{odKa94I6b76>QZosC<=5;PR2G$db1C?g z)M7(s!ZDf5yZRo1scEUS-&P!JRJjLVV%b{W4RQ35RZM(XotjA|Sb!WPWRxEnIAXma z;FAP!33^yI$uqvJ0WDMh8IX6$=06!iOoLCOT_;$#d~?HWy=X58rOjhi3qmC5s`*j; z&3+O&qWKug;S4ImpoZMZ(B0!CbBT~hJWigGYetxRN`G_v9A0gutDe#!0e7kkCYY|{ z`E9)i>NDIP`XkVa%=Agj z3t7rcp5GPZ;wy7Ek9cQixT?}a{YAqxqT?9EzoGrK3{B(o ztB3~|MB3Z4s!2Za$~xySYKcQ^$y}3_DOq&2FFk^u^CrDLQK##g5DQR~5eFugdJ#s8 zmJO)6mo*}z)a4#7bg)sFz0 z7KP(y|HGm!RBe->e9RgncAn+S=dF2d9MDX1x`1qcXXPOT!?5z|&=Fu$(qrG|eTQ6) zsK?g|@ob)@gPO#mxtv{YFr@l(5{E5{tZ~CO7K{KPzkE?U_f9#yb9Nm;Kz@o0V%*_C)91=+ZhoW!$TKiW@*a?Fn5Fx1@05ztALX9ROO&!|0=~ zxHHmNn?W&2Ji7Ev72D@^;yF+{QzYV?9KiYi*z3C6rRBhvj^A!E49DQ(;V(RNF7gq2 z5UPOeObtA0p|gx0hx0|da6hxCQu^TFv`#&l1WiUuWC1n9}A7^DJ63%|GENI}I$q96E6X&X&WzKm;Omd3>CpA$0# zZeMw%K#bCUVMdo>LG2U|+$x60ZM<>-Iig!1iorF@sRRT=hJpDP^##VNZG{Cqn$=#O zoe;@)lnx;Z4}_kk+czU~l&#B6eF4YKvW`i!%0UfUw-(E_rJPd$+AAHtgj%=9h)GUy z^rFs*c6ZB2PRD%BhTKjME4ZUN3&I3~RswkkLGdPx8Idzn#W`-dqDBdYdoCsGTeo|z zH{_UZI>5%beNytLLoj!>AC`3KqbFQ)nDU%$| za&5{Ze9`noSR|#nBo!Pnd;3Z3Ws;nLTzm=$ec70u*?7FTb0p6LWfH|_cx$~7+QWaB z5WAdJx3WkVLYrU+w=_gMLYOoc9)rOPa!9%iD%Bw7PJCHtDHM5@I2mPTa`|;ra9Lp1Q*aIP|yuIDs5_+0y`tC)e zDw9@vo}R)HYPB4Pi;F*6w^EDwq#$ib20r``jTJW#eq!Hlv zNYB(pzm|ZZ&U5P=GnB~al{79%BgN#HfjRY&CG>0ab6y|o=5}G%tAr)eG5`4fQsQ)O^Eyt|K zenGnlar^9s!1)hJ|NQn7&ZpAcyovXcZJk9s465F*SZ&wlV3$CSW%`gz>edtu!aB8^o%MuWes*T`EZ!;#Txd zmu^sz&67%5)nDTK8}S#ed^ zIV6q7yKJ9k*72a^qFy&ayeo?;Y~qq}$o{1&vX0k#{~~Ni zVj|E;l^0Vz0_)94ux@hxi;h25@r}b@(~gh4w?&K&Rb^R1xmTaSYBPMQ@mAL;!n7~V z^bUTWBgVrb7=k_2A}0{KYT(!}&*Kp{qK(Q^)OE#7cjNcJ!|MaiS)>jYOs}n2e+o0@ z$v-i;hp-K3&Dho-bSHbQJt8ehsk+!-UQz(tmk=b6=>VBbAEx14hzh?C3?9ii6Yl!W zE}}7#+R$LFiR{vv@pPR4v7}}g?sI|J_Q6sGvk@z5%*FZAoLW+q&G7#2C?OrRV^Ivr zwT3@v!%3#5UY3-|)&fTl$}jw1W69n*Zng^s8%OE<8omqxY!8N}$H|p4iniR}yu> zWnHEH2fO+;?v#}Biat3VIKvAzJ4e)t7{-J(RSnfsPwThUUEiT)A%sB@b~zY~seA!Z zt7JKeolb&{ga6aKJRAL@4KW1!WdEb)ncR#p32`zJ){P=1pkIkqErC!gci{_1cgC!N z*a3VfHvdtW7exj|z0CF9Fx20a4=zNg8B-xhzCV9h9voQ{tPY~wab)1zI7VF1Yzeq4 zN;C3C<~+;$bE;i&e_A4SCYy}LO2 zy!iu=&4~P**e?(5-B%qdxYYieINf7QW%Z^Lm=Gj+9Sc0mHvjaOK|Bs!<cDcph#! zI|FbLhV_j~9&;8i{gHWmkQ7?TC5$o27)rAzk8 z*}FC2!7@u)sSdRD!=(=~!^>cM7DYh@x%GrI24#PV6vKEO){R4yT3X5@qccGR?9*3f zZM(yVXTVx)dJQk>9WX|~bVW?aFBW0nI^nem+j%y}*nG6?ARPI>LaZ1jQ4kf6ztt$G zTrt~JJqXGT95+>Yv>_tGS0U^wRaXREtUCx@)P& z?0G%F0NUiRK59WjR+C4O*|e#Zb$&vd#5RUuGBvg&Fcs1Sh%toCV=wLJJzG3A_F4{~ zSb%ql;_ot|avbF*Xm*cRs;7akLbDLHsg@x~0mkuF)MEx_MwtHQAHS7;wkWQ>A%>B% zWQXMDKFLDVyX=4FWosaw?U=GeK#^-hl`TObXh6zTk)xX2N(eTr-Lmxs0%6!q!=QmR zY`D;WQXnb*3iK}0fEjCnfn|hfnyQl39q2Na&$^B3!IoV`$=-Y|Xph(-9}kUJZrS(A zzP(&?*zpsfi5{>Bcx3mkZ(D1+P0r+{)!JV~=)ScJi?F+FM!rgdL>YL7PcrM8g%$X) zSI3l;SfQEi-E{ear_BK>)E*W%U?2H_ zwlT(^eV};!O&~#l?y7t+1=b*bJ$>^gIZ1YR;4a+t=SB8GY7M7H9vZ49vzG(Yoclj$*%G3-yX?2NZq3CopC9h2!Z@hj>76SmlzaS*>V@C0hgYM>3&} zhKF;UbRpgWXJ?+Dy9J{9VPe4FoXi;r{^)jGh*FjkB^;o+iL&S?2DwyflcR!;9OV>aqvek$J;jnRO_P~ z$DuAJh^~P3aOG^wU+sz-2N|2FBoGT`y*UZ@Dx|!br20Yg@zcw76`SFQ4zednp=s9P z?|uJ&0ar!ZQUpbUB7O)AhgO)vb^-c6uL~b|A=tbJi7q-pMVzx+AC!4d#d&ll!_tk8 zM~Zs{X*j2$mt5t&K~>=Il4JmshZ>c#RB}#i@YU0d!rp`f7?o*>9Dy~> z5-6L=;$)~a-|bCYSt{0W(%x9;gSvaDWVSl-Q?I|R{HVqO4Q{fl`-@;V}hR8 zX)57lWTBDk!m&$nNR3bXX+KNr+=Bya8S)4$a!NgIs93jkSWlR+O?7%X<~AK@&hJ^$ zSP`_Pay&x-7KlIRwXLJdAt|xf`Kf6V$QoVjEtn2cnGnNySZJ+(D6>kD%?{GVPiyLH zF6%ggNt*pN(n(6Nq={gh!yM6E3*i*o5S~bhT;=PB`%~&8799WSUsV|^*J%$?=llwX zZDhpph&rFJKCPN_cPaJ%x-VNTFapoZV|E_$>yKc%qXF5a4Na1v)7lX)8X4$1+%lUV z9Ropxrb6AL)c309RvoO7aecEfc<@Z$x8da87*zL@CDVIs6qzbM5`hx!<`K1rG({#B z7grogAJQfPnUyam6fJ9G;t}tT2J=t1Dd^?dQKcMV6}Yuq?Is%H^FSszTY<4nVRM*P zlgFufZ(_k8EeMGcFa{RaC6MDAOY0$SKaT%NoElkn12jXZZbAP`_md7EZQXey%;2u`V;6?E?$WLxzXr7X0%&=C89FH=>S#i{D2c zCXTivIn)6I7%Hx_m*}@qJn{E583VWeTZANg z*D24b$>zr+3VS}|Tc*MjbL#=IH@$2_t8SJB{S5s{wA+8v*w_Is89_74m6YtCvaq^j zwD|q+rL2Dw-@0yN2EAWRlV`<8!Ldz$P`9jc89~mDP{12-(gsJ?S9HSGgQE?+yqYw@ zgAey~3CX6_bx@J?hF)TF3*iX_l@*e?JlTn|uRoy0RurRLQ-P7@r8dOV-v17#;vc)y zFAEdSu~m!Vid~Jns`Y0J-XY{(u9oXTlS1|APp&VGB6(uKZjQ_xhXTlwEcE@hQW$%gok0eY}pdl_;79irp755>L0 z9VRk>k&f(-$~kO|YIw{mcSc%{(>-`a?L_Z}QM1uxia|$Jq>l`av}x@zf5p){P{X=C z3SDdk=&=Yw;+tW7g?qE+puhlqCy^q3BojG}3Rucy{zx`;YmDuNx${W;t6X4;gN3~^~Zs%65wkoq&~()<42vcXNSX8shfsShZKgg-vE0P>@UF~*6J?I9LdHHz9 z(o}0|yxZz(=IjEQR%$u3NNB-n_gsB^Aqh+Vb!fPzVKW8?h}~FsEE)e?_5t?Hb|D8< zBaCg052!^f1^WH|ya9vaI@(hWQovq;kq5t^Wcu$;NacI6POx2U1i8JiMw5*@`fRFf z=WSu1(b@+lbLrG-JP7ZCM}cWqtkgp0TZ;&kcDjZM@z7>n3U1_ zXo9!>f6pooa;tGng)Wf8-bBf?Zvds!H)8q;3%2+jq<~M!U^&3Sqi_-G_myq{sGO#{ z%C{_%93BXCy?k>09BX@)504WP||-UMWE<^%shmU1zS z)N(Tq$W`~CIA|B%J+@21uPiP{p%`3^a4GVI6COmQI2aS9GH-w5_bw&Hmv#jb%ux8c z%poUmLmCoxrX@#?A)*QX>V+GcHl#K@jB=%Ky7O#A1CYw0F-aRo{wU=r&B^c1cO{wL zm^K-`3UB&*vptGr6ka?jneb}3B9aS)hm=guE4IVuxZeF)_+72Pu+jdOGAb25d6qDC ztzEiy5!ZqbSbcCv*v_^)VZM4;M}VrTnin#s!1Tn!1@(KOb$s6lHBGcjalsdgYC~G# z(e9f{VU(VW|2-hD}ejUiD#H93;eH>s!~&5mpGbR?FVhu!`Pl4F`?Z4*Nb zX%881Ezlc-VsqCn2v0}L6JRRevbvnaHK2_7T%KT!F~#V9-F0>@GEs8K@5J~{qSw~D z!sm+KOFrpl_UCjz!#;*l2mk4P35f_44s9haBLjVBMQ!iC-sE0oHCrBieoQ1ue!??_ z4ruQUq8O`ViHXGM9O8PN-yy-aoSeU72R<-R`uUwnNo}R$jwJeRKER6A-$0zmMFJvj zqX(72Mf5!Jy%7I+`fKmvP!EZKiGy9Nhe`;EKV^3iFY#*YPgTy4!60T$^OSNXi!lC- z($qQ0yl~F!BXEW2Jon?3NE|Yfk7cMxtc)Ok7~2@^>&TCWo=(E z@K)MA-8voP*GQUe{$Ud)<{QHcV062?cja?_@GOe(Y& zCl)KhI~TF@W0+a9HdM82P)`t4{lcqo3UZ8GPZ?X81o=h{qL$HEU` zOb}79KMLFT5neo;fvIl)j6dRJbpUd)#nDKhkBRW38(3KsvS|VT!x6{s1xXBmD3a|c z>VlK9*u9M9VG{rd`>J9DoI;CL74K=z&9HuOpBPEVRSRLw2kBP5N6EajD4GLMYZGSAP=WpLB6sPals`l2k5@c!({0*le8f?SGASJ|FUh(LQt|xaE_k2fB!TofV-` zpTQ0}S!_0L+8;6p{xoC;o_okPTt>B_T-ea8+dC6f)bEZ$@_Gr}0*afouj!hQ_yPcI z;wF5gnpTy&c+T7EA?yc`&^`hIc&E)o#un1EK6KO)JkjzaaHmxb*}ndlVh5x9jXG|^ zdDxo=w*_A@<_3!~50F56HBcI^uVT#yb=JzQ=g zEXg58g9j_aL1DmKgOT!QKZB(7kv*Mi+DTeD(>z0>po8Zs%9?ux+SW7=d1-t?JO1i* zpaqRy+q)YD3PGTyNDW&#?>oU*mwtBEVMmHN&5mbJ9>U-VkJBCS(&W!O ztc+>MwpdPgUdc+Q2X#rCEY&&g9yl}Me8`9R+S4W)ecnA!Uf914{NKzdk0QjjqUuw6 zNbf6++8C_N-2mYBEyz#aCB;hN_y*#(h#-y1^T9RlhOr6hnI<+m(IVYOjMD7zf4Xa)7V8{XgtDb$LHWSSw9pi#Jq2Thap2Gd3f3*BW} z)9~o`F8cU}Je;jJZ(glk@90l%NalJ%P}R$Scy&nIG&$v&pY7&WG;|bjtn{cRKhVIQ z1Mk7;)OdBuff`<>EKD_xpBRwNY=%*Qnv`68_)2?GiHgu3Jl7fd)MjBPc7v{a5bjx$ z^Y*k74{C8?x4$jI`iFd|DlP2hR(%~YwSho&8mtQ^Hm;a~VIGocb>p<+?Qp_xtg1Ij zh!G%SlW9pXPm1A2D-zI4lhjO) z-5HtVQ&(Qo4m|7BO6o)&Z7_&q75@%M8=SV(F!ruJ~+Xw502Xs`DVZ7*NzUFY%_t?hnM?!ej)TI$_8PjASm&u692 z=jNN)?rr1juG!;NwesgB>~S&bZeDILe{aZ${r5-z=SA%6%5JZaueX-ZN8=Baxvw|n z=acH|YHm;K_eb|wT`v)MJVp=LLYTu8cvR2}$z(pj1hHG23dwKKRU5Fm9bB)OAr?_@ zYa^bchJ5x9B(SkYHxdQxHcdq~b#9nW%vgaZI6n~4+9P-m7#0L(A_L^UR%imF^&WL% zSf}}S(yr8GwkhP&%5*{@rPRi9Q@Q>)xYD*R#;s~IKABgNomcManZXdEl>*Z&IFrUU zi+$0}SZ;b3NQLq?8aHao*(A#Ibpmka-qCXgA?bX2jRe|`(8*x=MxWr%t#9TE-v(~k zm8o6TstfP267_xbJ1ZBaV5}%r-CgP6|}ngmUMjUf2E9N14?- z0m@p;EE`9{uc33xsBN?Tn+X7(FIWx*P~8&sF2+dtp8zxoK+pcygqda1`2a)6efTUR ziU$OmBfd|#)~j)0De@iEDFkn$HiB>Zls62m&<>u+auOB=#eP?$NAr_ZARIy76*?kH zEC4<7_}1B~*$ZIU?HD2nX0)NDe>DrV+h{{YG_%#(qUO_Umbx6O)M!7tAF^f`PYRNa zD{~xl@Q8mshQlDbX+98WpKJpYFM&P+v|yTsRn=r6Uv)F}pLBtQE?#10#C|_9A$=Fe z8j1YbScr~k-wLp(o=GuP=VP|<^o6Yn>{@oKrr0SSG$atj5?U~b!;p`=pJ(>T0gjM( za`EYF!{#+`zc=L_Tk$t|%x}P_w<1)_0n48c9mq(DQqfmP0&1AOYBAq>mz8ZG@Tx>o zJ#ftJiOoE}=Xk_E;OLuU>p4D;-resxmTP24%s1f##TPm^(|<{Qe8z%u90xx^T%~BN zJvV#JA#qB2HlHd4YCZ5*6tVZZr{Kr8!>mxs?(1<(?e?&%3 zXL@I4Ac>*Y5G0-Yua~+$1S{6@>&?<7)>7$}FQWKw3N!Rdw+=qC?`5%(1Bf(xRznB; zu~jhO<$?D-Hp+@a7RneU~86!p4mD2r{3<5#Y(i5qa58^O= z6%aH4iXv86-jZeQNhZkD@*@d=0qzE^9vRa6{eCcEX4T!vE{^u9Zqk^b)A4iB#0CJ} z0O#9Su2sup%MN5VUi1A+^aum+HEMfdS`JoJe*t}%>wP@W8C&W*qaw}Ph>^$s?PV<` zDb28a)Sd zrPHg{%6dZRys8cdEm}lMsC=XrkkH-i$Cw@&+gNYmT$fI9pxn@Xvi$K`1IgH*h zj6%&LXCs@CK`IGVo4uS};_;CsxOYR&=-lTtu*_$_)YDGrvuXGkQ4+%^9I)mQ82%Iw z)o_SBo&n?pbjGPRex72L>f$}a_H8sf0qn#vIeWEiC{j-5yWCYnANK%Rr667DGXnV% zwn0N*{Xh~*W69BP^0j->m_(oh-0Q`wj^vS^?zd4{zCb15yQ+<#S8csuh!#yMY_?6` z(ftieh_$ZJ0cBbP`>}YS$(f1PSt%wPEWZa#J4SRtqNj8>|Fa@hB|NmDLh>6s!sDy1qogG9EPf&eTVb5bQiJ1zh~V2n>mrkJ5#+K0$h*x}NZ3 zD1$I=>4sOc_$}pYYHnpU92hr>RD{HtT}UjU5_83R5+bB0cVK(bx4a%ZD5A{DR^6U; zum^N0p1Uk+Mi}4wG2d%Z@YmtU19@2@SJ$1*pxrY!?n*kbdN08A&bxC(;?kvQ^-Sio z$p6_{jbvOJ0#u=T*SG2at{B3FXfDhxkSXwMqyT?AFA5%qe4QH^#2Y<<`@EizHeA}>wR5`+tk`pZqC>W zzI`vLZfsd5KwdU8(z~X0vry9ZzO&xs@;k;t+W>!Bw5}@c7II11KEn|%w$qT2C2oZb zy8@JaZ{j#1+r@i2j9ah7$;rWiOum{L9Dda>AUG|-(zMpCemYsNsDKN}D{G}SsQ0Gi zXLuZjbbQd|ur|POu;hS57=EjUT8yh|{&CP}D7JstIR5#G5o_fTy!%pLFV5l%11#Bb#J zRlb8*h|5XiX_qUHqWMX)k_MENr@EZSp$5*6Gpm}Lb_+ffm|qLv_4=+WKft?EE0&_F zitgN8a>f0Yez-`w-oz>T_s+eT{pMRc%>!pgTZWY4!h)%1)?r1(W}mq;!1ZqXfqF}5 z&FAs@+()wXix6DaVe)LTLo$#C2qR)i@Jhcpp_5%Dm0-6t>4tdw0H;JqB3aWjHDqk9 zH4(eFQ-^V}0pRDZx3FXS8tL1re5}0nl%t|V(=GItSP35jqLsW(i_e)zlMl*ogQ`a{ z5I{d+Ei-3=ohyY?uc+A!Fa;;0z*0?%!bY{-n@PBY^8jmc$toEaS@nCc>~FWt<}RCj zqTgL!=hAV*sbX60on6cwZUe74wnFPa5HdOe2v=mK1Mjib+$D9XY5tR=7&Eaqd%T!o z2}CKt<6chQlY7%ODU0F;V5+p6n+xb8@}VFJwCePh4v_b5mp*dRLreKew}gu<8`5gO zf^H3RC2XzRTB6r?QD&ruHwBFW?c(ENr+w!?;kWO3zp` z<#&k3l%ryisv9ctd|4>wR#d_NM^xjsem~2Kg-~g*rz#2=6f9;Q1o-_;2T1)y0o{i5 zVWzAVx@00g@C2bak1$4vRghxGv*lrG*kR*+2_AX-EHw{V2?|Pvit$?UapesR^qXe4 zv_4ycPN`pxf`MB~-*?G#>{d$327ypogZpZcG<4)G$yT)6>joyG{znlV=VjHg86oEa z3Zw!?R5XO5(d89EAfH`5)p!4lfazKIaW&2L5w+uN!pm&hfRey8A;&esa@A|Ju~gkDgObku{QYWIpF z(OrH@Hct6Am37R-A#(I|JGpoZzZs`&Kq<5ab-8~EZOLzu{%$_MF|v*W2SNbjKIn}| z=g6f^t%7!+Gscy1xVs^0N6o^Ycoy~NW_E-NnI(t3(T7F54(s{tX=y|qd6Hf#b>P-{3x7Q0!F4)^HQCO znEy-~+h=M6_|!s(rOvg7&JZBz?;R?aStEpOfNh zQ9!Wly}`m!gpwh%U<46U+Nr(8Uo?WF*ls^P_k1oi0Mo_Q)T7 z)hr`E-#N1_XjU8L%UAMDSujE-9P#rP?nzW?qbTDr$`E*fUw(HH3cT^AeLP+^&O2>B z2?Xg*1pr;={0g=h8eqIsXWRTwFEnnRT=4T5ntA*CW3}sQ%|4&L*HX ze2N#rnV%)8`8bO|;RVOuC^z(k=wJN0 zSwU~}-+w3tXJBCVK6|FwfM7q?dYIi#6HFCQ3XY-qfC>Zx53@I&}7^GOJnjE2Ek zyL{;&V$xJ{?#xr6u7K_y@&4$p-MU%vFpa`?MH93}fPIJus2@5X6PLFaH5gGe(!ei8 zuaDFOAy%_7E@0sQa0T!G~5qMj!~tkf=f3QF?GkBQE~X)??0G$;V?as5;Zg1A3IViJulnmywaB_A+LVJrAU^ zv99Y?UNahZk4QqJ^1{<6Sm`L6S3(*Mg>;DE%GZTQ*GH6)BU7`b|dRHIuPHV?mappN!u_;BVA~p7ybIacLn?4 zCyNQZ3K66pW=3$A2KL|8jquQzHP%g8x3Btiy8)sA?#hWH%Vq+JL0?$|a_+-vD_~Ai z1`)X{P+p4(vON#^U8YKD%yW~fDS<>s-Xb!K2GO?r4I-u8$oq^CukWx190Pd?RUK%6 zh_-OF2@hvhtw>=VDQ-z(KP14<8b?Rymu~@q*S7%Y=O`Lx9k?TS+>xn0m$lL1{;ZMU zZF|1YJJgSCQDV%x_1=EGx-1kLwS)Vl+_SJ%mJaIL`o5vcxsA;{0|_5D(%+aj9_OUi z;<6yCsZMT6X$91}B-#~zz(9_0Ro2qL`mxEzFg!)P#+}aBcep`dt558nA&4d5J~yaW zHwX!esr?F8Sl4NK9$C9JJv72!JA;Iv={uufT81%ZhTJsuo@OoCvU3&vMjKJ4r@Ei4 z$@V9RSJbT5A`lcnCzQ ztW8pfCt~&jEoEgBYCp!BUQlxSoJS)gN&!qH>#`)4Jk}}lDr|yAsp5p$Nh_bI`fffy zX_hHNdYc%uKFydk9QCpp@#->`<5*vZ9F}SHTG4MJzl2N?dG?r9Hr(l?p7&wyY!WV_ z$fBI*)iuRZeZ}F2SqD}6MDNwTeK&JNE)TpUP-4lb+^1NrZ-4Ug(e++f^s4e&WqK?< z-X04r04_HZX2V{OVFhZ|hAl8;&h60PJXxLpU(I@Q%kXbXR-t)g=?$bYD_e(+UtAOF zLqhJEZ+%ncf~-y>Uzv2JVe~$Ap`ps%sXgUWr8Utj9I6NcRE^}mS+|EiPUc0Rqr%p8`F z3@R!U6Q@23aTta=P!qC5e&rE~VhRO?KU!y^ixgOUWie^{7-0KG zy+|gj~FWIsH2DGCa4~u4{{Pt*!j6(}d9T zCFR^==$bNc+5%OTs-BGnux zN6zTI^I>fC|K%OKxsugx=42z6k?lpP>4TDe*+qh%D{32!x?a+-EkEaoujHJuf^w$6 z%dn6B!&IoXjpe%mPMVG6fWa)1{_gisZ}C$4hdIbr73Fg(pLNoB>Tr%t4bLcdg)sBo zfoNp#_tEQl^DO<*$ycZnKTZ$nM5C8g2iU)N&y1eu@l~;(@U#YMN$klTBR@^XMd>hE z`ykC5N}3S3A2Vr$Z49M)h+4~6;OU75rxDKWnVvXH-3k&voAsVJ*K}L^u?Zhr4LWu9 zjgMdB$+q24izDe7S%|EfnUt1nsy^69s=W!)_TnvB??01A-><1fhDsE=WeutzE}C;9 z+plga40B9vIhh^FC@!b=4~MxJe$#tm(5-2f^LmnLmBet?z?uSxo9&5Bx*LwJ5Y|Tv z^}estiWQgfG?fSp%NA#;ywSB%hS(Lji3D?) z5r2j+?_ovyd}_aOEXS$j8M{QisNRg8I(bj~@{6nUXSwzBdq7BrH@Ujlx8{n;jr28g zrl?g{D!CHHPDUtM3Q{>Y#$VvSd`mudTxQ^m^q!)%Er@GguYu4CtxjBLu%{~Uxv*~V zmx`a_Wv~VL=3yaLKMcq-Q7{5l$J0&KQ>gqVi@O|eEO4}qBcRh+6B5+)kz=el=;9xO zyWm7Gk`z1G;1PUDa)%ZRDl~LsjcGNs9?56NF{)j%J;EHfV{}r78Fr-diRHgd#j<)( z;`06>QrQ>Mn=qI0{ig;c(5m7;HN6RQ<8F5$;#=g?^P9`#%c(DRDxMR+EmH)47)4m` zVD3=2&lW4(?}ypU&br{imDbUfyQ+TS$lxISa>@=yQd0#_>ltHxuN%k`%5q6M3=L)Y zla@AXMgVh{^KO|$&PTQ~B{NcttJxQ0nQ zVu4u*?af704ZF=%bvBaX($LjQX#F782z_eK0ZGTnqBp733|{0OhT0Ypz1<{}Y(!uQ z$T3dNc62UKc(3Z}J|3BZ&a)yivRJ&9|9U4Jrv^_H<l9d+pn1OSW0lO&b{ioG=5O^HAh!-QbOy8lF-NU5NU)*iNdx zaF{$Xq#Iy*4hazV&^C(&R|b|+`I~qF8G-#SAn(^Av&X=`&k?=8K9v9Qr)_Xe=D08A z9;j|)^$P`ugoRt=<*o<{rm73FD&9%Kx$!GQwQ~3gi9MSmp<-lw5Df99OpHk+P|Hds zyMeSydplj<%h=K9nD;ZM25mKl<(?py-~-jC3$=V-#zac3fT{XY?uP@%51^|?RLvB3 z=$#l2JH_LV`-p8Z8)LOIi3E+@fxvEseMkMv?2yYI3raQFuhopD)s_aDToIUrQ-o^I zc{k$DVh6tn*D9eS5IwHI1&qBDPJ)~Dtd7(2LO{`+wiffR*a^Th%CA3c1r)rOE}OwC z--n7Z>;jG2XoqXH!K~+tvNuEYj!~A=_gURvGG-2)p#E9J_}1?4%lA~Fy(HA^w|7kG z{Xk+}U<;Om_udSbWSKpUF!-w_8YOh*eHf`jxO?K0MhmfZPfQ{)orUB7HE_Y#RtrPk z=(jw>6>0kUgCzV8A0(W*eu+x>G{F0`}FDEDcw{wXlh|5Pz5^DRn3&(~hRGP<4(Hg|Fnc1IuF z#h}(@`32`eK7tMjj3|GPH1}pB&-WkclAwFp*$RaQ(#GC%b{bxHbHu%V4jFZzW-U?y zNY4gGj#?8H{X?^7+Oo#aWoUoswY_;tNAdPlb~!P(^ZWq5;~H4a*rRoM&la7s&!o=y zArTYMm@Df^Lly3X&-l%!!9BSn3tr!71I5Sqh`t27B`EKHxKcN-$~RqBI3oWeI(>vk ztJrBK5hcsiHZVLbz!PWZ5<$I~n!ta83O7;sD^1ct#l)w?K@(*`5FIL!ciB;>ii*y; z5p1uBSruv5*@LR5T5$6qKWWB^TT@2xq-i5pnjf$oaRP7*E1%!yOjx6CUFf-J-gr%| z!+y(!!^4WL;kuZPIm3gWHgD`7*~QYe&i$gCS#pUWP!A27I^N7KVL(ftzuk-ogt&ywXgWQu1vRv*dZAmzWS{Xd`F|P5ZQsQLP6k( ze8~M?jMJcz2V-~d#E=0UyPYBy`aaz}LdFG@j9AO)gb7L1`=E}G`^(#B z8-_XXsXJyp=g2n=q?A%9fm-IX!^51j`qFkP!vPePa#GBB3p6$=$}xy2(HW!|c%7&} zEm20zdyyudVR^xBE9!2|QbQ=FP^>%FxRVCMP=^*2c1YlNj$j`wZt`JPAXeJ<@CcAJ z9L|2ge^w9qe__O}&r#P!kn zFb75Y-*pZ}S#zKjZJS%LzA?P_{)c4Em)43e!iyomu)HH~*v2e@F?uj9>h-^++e`9f zjEx4I2Cvms_vCjmhgU9z0+TBWLk?4T)qI+M8!gQ7iOh4~ajWvDx!D z!zKiOROTKy|67Lj*G{CX+#d}>CKOQUB26%r@Ew>>r}oxkemt%lN9>HCVB4EOTjJkQFnCK|Deww%D`$)y08w7L?D zdeJWr?&^m6Z4O(BP03V{<*(vmrx280JRoAc>m7Q1m92f;)6oUc0fQhOR%rx1`1I!a zKqutKNVlDdhGJyv!4dcj7BI^Wj>rd@vzg^~vC8`p#XV7BwVxBL=hT-_{bI_Z@I6`D zt{T}+hiMGgkaI0+RMY4Z0xZHL2-WlZ%2Y*RaTW54WjGy0aFAf zRmnsjsUmB7`WZ<+W(s=daOL6TC072Z$e#gFP|t!`L^NOi5$q)$(mG}4InO+txobU}3Dl=Gv$4*Ldjgzx|6nM- zE&Qo&j>yw%X5;>|G07FC*p3g%!bx%(mX{OUOmg#PSZmf4hOAT0hoq?P>@U?@DPHe_ zIz5()G+CBG8rv#ecFiL!2$}ROs=t}isY2QcNBPlTyo7_r2_f2>4Qa2$K zv}!oO&v%p7IWxJ`Y{)3}VRk5O&E2AiAA}BJG(BAJ3eokiT|uwY>UOz^$G1Oyx=^1; zioF_Q0uy;UDAI7N8Y9{tSM4thB*fU|JY(@w7U|LOAk+L|nXytCf}iBZiwyrSE`S() zY-DJy=~xz8Xw6-@_>A%J(3D&wX))!`&|D@oF(}f5$dL)Eb(YiB^d|k*PG)?C8}UTg zYP$<4z9tA?fXPnTvW{SmirKTN7H$qC|4l>!r?~__ghNv}Iu%%DJP5AUZ3I!ymROCx zQyv?LFX>eMf=P)5SUG3g7u?!mex_zPLoZ5)!gr+@^p;zQ4W8#?PxjUb)>?Pq2T8pE zb!Lb8Po&JViN?*m=7V=Wou}UHQ|U5kLX(8;IpUsQ=a7e;fQ?WH3lz;QzS+e}Lfr+XNg8 z3ryBFt+3mKnVyM80i1S>Hwhu|DWI=0LcFafc#$pp#K{H z`hNnFc0Co5U+W}YQf+`qr6wSfI<{(&IiwE4e=Aw?KU$yR!-TKKk6tW?IK__R`(0up zI$^wkLZw+c{N3!Rk&BuNgeZMdyeCo9Io7=z^4s;4M1k}6lwZ9=N!BA!dFEZ$TGL8b zSQ-JthbbEs;mzm3zrQTXiv}AoOtVz}atcfu;BhAL>i^A?tod+#PCL7CK^uV`zZSUO ze!c67gaXs?JY0In>wnp8k#`qo_50MtGRyIy#_hTKHNa8%?7-YPbrjdwU+$Bh5^0E0 z`u;3U5T28r%}vFNKQ5FSZ|vuVgpfTHGH5A3Bz_0_=*ZoN`UY^NxRdl1fQ=Y@#T#O1 z&Nvnx&4`8Ae4#TE0xXR}SajqsV?heH3aGM}A^!fQk(A?JKCA+T zMZ8cOLkkk!GJ_@go)aaCgC^WHC=1#8HZ^iW+WF4gwwC5$rl~XLbhg5 zP{H5N4Q|u!mhM}Q@?HVMYHt87bUBwWe;HT?)HiX9!Vq;`Ws5)ShyUYM<)1vbouZKr zsh#a6@HtI*De}kop{iq4*age#DI!N+Zcr`56(VNJ%@p_iA|Z6Wzd#UuCX0Tc>;pF+ zU)d=|rv_K&B+1P#HG~OBiNi3s%2#Gh6R!y*?!$b0*Tcmy3`uopfet*-`D6$!$(~93KzIWCNR};YFYt z8VZsE=zd9zjNKwqRj=S|*SpWj{7V54>EAoAGW&WyDoGd$erfyVv3Q~=tWWuqR%2T2~VRX^FtYrnf&(m0a;_+MaX`4 zQ&uiAXlqqrwrj`d_~Bj+Kar16_Rir`;`1(`Z~VtP{PS!q*~rVo&$B8yZKSE3tOPcvpa@Mx)ZiBZ#T0Hey4%4miDw_=t7z!itHTf*q0iFPhWinO+} zO_!-dA;YOsmzr_74#saaV*mRWDgEj!ag3m3`;#O}kX~7}a@-)~l#DMHkPfD(mso19 zKbYU?DGZ;uk=;v%+}?s%7-j&cYTpEE&sp5a>fHhTv$TXaQs&Mk>^pUmF_pK8G*~xH-DN&+^r6PzjB8%o~P9i#P`XtBcuo zXAEG@&uIq_D=I)O0YS)0tUoi9MyVthYvK$7?iJN5lnq&+aFf2{r1MsZ9V7N>A=H&~ zh;jH@BNWulOv$F_m^SM+J9A{Tob%5mrs$7GCu;l4U9Pv?gJ@5>JSxz*^ryL?Pu|Uo zwn^y_&k0s0y<&E>sDxDZjMrmqu@U0)n4K{>Rsq9Lj)1|I+Yo3v-3qqRVOL|jTu2T! z*mTTlyVJ?IGB*Dg4Y(kEG$a=mn%59<8?X|-%*z&!+DP`p40K~G00vWH`cLFIcq@a# zK(@QrSIMbP1X*=rNkTw4e6OxoJ<)uVl*8`SUUrXP35hqZBr)d&eVxpAwkP&-La{k+ zI4=B?$XN(|;+Fb4r+oE8Df>XV_#B}HTPDH+mEUbrou0s08k_O1)(vowO4Vp0W1DIB zyuzBym}QTzj58j3=ib4}+&c)og=hD%ITX<7O$$lpnsoal4OsP2C8#c)GV^LU5mkj9 z*+#j+Vw5lR#d%2*B~F!Z`C;FgNhCY1K?X;WHOVRcd^X$7dG4m$u`F;dAMm(jB=W#n zbl+zWn1I;u4R-)xLv8}MwJY@9lbNxx+%3;dI2wfWJGRC}h#-H2p^8KTR}V?<`}P<9 zqz6gB)(X>*KoeF5BPm?5#hYm6zJVbNe2Okk5g{*0rPjMIArAk;ZH%wGiXz&si z?>F&wef$b+5Bc1i=xF{>H7*~o z5C56pE4e=Hgg#>dmS%I#iQz2|KU zL!d5QjX~)o>8Y`ml;LP+hsNxi$s59b;@x9nZ;WDsWDf_^o`WP~U7RCHQc2IXlcH$w z`sGr`>@-*GX0G=qZFFkS2JgfZ`#_c|%Z1)wL9l4;+gb?G&#@hwB6TsNXKMrMf#sX@6A!SV!ejWBYGcmpdxf?|7ev;iRb_YN78yM+rV}*e_MYVSzRWn245lw zb|?ay6_SHqd$;qJA)gHU($#d!JM>fxC3)R=>d{ok z_gI^4&X%DIx09R}MfL_m^v=fyf1EGBu~O{-ho(MxyLo+wRNOFi^X4p(I-s<2V@D#V z7<-rR${q0-X7`DL6%p%QDO`QB4x%};XQ2u$M8UY#z6wCEq=_rj^e2S2F3#ay=9+36 zPqJ|9h8a9Y^PBCh!hUsWCiK(n3;e)WNk<9#CYHNjjUEI`U=b2rT-?jU3GNL|F4Z^= z40me?=GrHmcRJay+H}0Yga)%V3?VaW+UgSRW?2XwAM_>7?zA80(iN_A07YIoK#Upm z{D5n*QNN|Hoip)djeb*vn~1Th7apK!gFm4xRkpnz84^ICMv-CEQ02k|XY=NJqs9Oe zI@0aWCT8Q{jJ&;qq8vPR_p(wSX#-$lBhW=8e;VRL`)j_GVTF^!TEHHQROB?QYTHt5 zwbrKi_74z6_JHKD4u|<17RK4PnS2ev7vrFIOsHK<6%lx3RYR=NMKUTa!O10*8lcep z21*jN!l*SiAr8waE+C2o^A~a|GYGyU8o)x%T4Zv&>?P=@>(j0r_oW!K)0e;w3fQ&E zX(P!{y^0qP@_Z^EN6?er_p0~_Mq6=ujkFaJ@uH#tho-2D9<2GYrXMi8!TNhB3Nk}= z*5GwOo1}4qCqhMZB;=eJguVP^$tdegk{LyLJab(8}#2YkO=3yW?GX zvP>3fJhFhWKkbr4FRG_f)d1%TCT)>KA5O9 z5J&UwS+JS1IXnn{6s7O@@DzMYi~B=%*l~S^;E?G1s&-;G%T}|n?2fG=KRcLDif#Rf zH-QDv8=2B!L#daPGT>9ky2P`!ID^R8S3MwrGG^W94*2*b#yVka-KrS^JO zlC`V0VhJ!m=Xu`{@>G9$CO;=19qNnFnoHq{HE{v3LBm|U=vqA<-vQ_N*-x}p@rq?X zVLWq)wN@aG%z@^Np=MY4Suj;n-Z4T(mssDET`N-0>D4%!9YF|+cx!SON|mwA_@y&` z*3@mc2dW=WKsH$}%|L+E(S6L~w%jsROSYzWASQ#Nf~_O@;3cp%e{h& zoF1RLg`r6VshaJUtx2^f+WwXT8Oaz&y%!%aB%B!$@!%=gNyvpQJx<(DQ8Ju(N8o3v zABo)y63>D+AD6L#B*@!-`SW}2=sK{(jmMR_ZB0ZEFq1U6=Z2yEnpv(xi~y;&O+ytOTO4a$v%kb%SpvYTCT1AY?L{>S{1W1%#`ft6~Qu-1I+XAC8 zY^YR4txPfW{uQO3q1L6msQ&5Hv22&vE;|Qgcs#$Is{O8MPvep|L1E)%z(j#e12Tx7 zC1TTDMeFH48IL&Gi4PyTu@DKAVeAZ-xlyP**War2L`?R@bx_teJWd5e!LP2wk@q$* zD4G&GC7F z4bsg8t~9P&tR51XuOnL-4O9Fc>BJDzT$P#+!uVHVeinIX50g;BYSgKChvFV}%dtHW z@kD7)EVM{)xvi*s3n&yEnqoG_m1Re35P8$3FyIuERsW8!f-qZ1tEJv$o+ zj5n@!=2dxjN^r%u6u{<{1bc)D<>-TF|317Fk$-<8A(&^&r#l~G|fl0m(sKY5W7?`mA?rm^x1&(<@0jY%QgBsgfKm=gjyK3F)1^Qb;aRKE^*;3k%hPf==%v zvw!f_u*VyPRDeucTn|z2t`DSIpTZSz2LCZDI|pBbq8P=IZZG{EGX|0N5ht)?o!ZA~?iy?!aZfzau@U z_@AXa=N+4-ugT_Dv(On*y_PaB5bGf(reWYzowGGkT#cTh4GnuKYpvY8V5$Su1|B8O z<_Gw`c)AkPMN38w`S1A$>i~KB*NhF=67e)&aE+v2Uou42F8np}HZh|r@D&B9~ zdMPW=?-h3cgCFmx&?=wzJum%m40{G^Xqk*jK(hh78wilEn;49 zwzvB1)#ZlJPf!0px<}e$SFT~SWTl|`s~27F1YvP)H>`@<3oo10S>m6@;xIT1$fp@K z)IkDJY%TZqnQtFB+cm$0X?&qkNk4NwZjUssUo9ikOLs-dJZ;)C$lk3v zYh)9(8@vq;%=brKf%Iss8B-M#uK;4j{4(D>qnhhKj6@0_jY&iMaJOw(QK$2JziD-^ zD76bE)t`%@7nPoPZWFxc-{!0M9~WeqRRb^{JIS03j9U&fPUQEtURr?!VrNgngzGMt zwE8?IU#3`ecsF*~Af12zfox^6&#>ljmpke(+YI1JQv6flQPky5JP2@|aBMWqpyo&b zKgB}xMI=qly%=oIcb(fj&r>{_{|ld14Pzb1V=oZB@EsVzvygP{5v&UQnke8!OZh;0 zpcfFGs~}!^#j?#nbq_kSs~8N@e(b(7M;2L5$}c*a%Wp!jy7EOKrBcQ6{tLR_sN$jK zEm2-Tzr_>Z8vCqQ%1|riD+c$RUlQ`EIpXVv%I4ssSaH*onz^= zM{+z~c2x6Ib+<8+25u$CI;0PGP-HgacFDoiWuz*vrK;q=v|%F3==Lr&Mg`?(?s+MD zXZ0(Rh_d%GuFM-b@7v-G(7_tpPTAT9VTqNd(&hBk zoK$743(xl0gjG;TIEMsLZkgi#(;`;_v1xR?wN`dm=DTN&i1Rji}J+J}0{WB zElS%Fv1NgG9yfngQUDa1g4s0#$TDzxqYX5vuPa)tP8{E4QA9>`88i`l!=t}iqtx4( zMi~;g#<`z6fG%zE5Cj|Hy?PlB-F6g|1+F%2%S6T6SVevrckrWM!_(gH$A;kE#RX#G zbDR=|T>>Qx{5|mark^?bn5iObgpH(4Dn2#vrAu_IN2PX=h>UWq!99Mh1~15*`G6Tq zs?w<7Oxv;={)q8j2}r%fmC%34YP7M(NlFX2odv}PP2H3$Rv{GD_YsuV*5q<-Cz)&& z;HxP)YqA~DX6})EVd5IOm>F^L%n9yy5VyuC z75c;p@NoH*qjFY<*k!#t4fgCtErotLOnH}^M7&r8UEiEq=#(i--*Uy?HDmRqsyYKd z1a{s|!hIRxI=}5<6`)3(@5ABE=uufxT`g()A0?%VdKoz?4gSssuKu!Or4L1A zM&Xj_?Tyw@IPfnZc#dSiJ`vA!Kf%b*1~Lv@=W-ZRgKGnznk7NtQ`Ea;;E|~{WC@?S zpT^ZAa59(%?P)fMvLc}`528VshNP}pXldKgwUVf2vEKh>adGR7kna@759SNf4YO6p zQ6S2a!mJ>AiBFl6w*$0WjzAK_KFiQmHjD2+I(rV4iApVTvxhKmP*Sjv)Ai>vd@kvi z>f+5+V=iN_z>pZQ%W5rhbIZ)AMLbD>^eG4JTB&|uZ|Vb3y7$)bKfSdYx3L?He40S@ z+F*_QW(K_MJauiiPs;pI9_g&?!AC)+x!H0{!3PcWquy!|X4lyDTSs?aP}OZq@ZgG? z@sz(fQu{ry{PL8%YKK3pteh<` z1g#4E8dH{}ARx(Zu5T^g`66z8)L`w;3PKV1&(p_Nuf%RgHF z3c72KmWrY64F`oxDs}^hSS33R6yns5o}O}-xJ|m~jzTx? zvu_P4Zz6K+E}6%aI_S1BPcC-mq2@X=MD`GjA2UL||EaBd_<^nut#SnVyu^a}$ z_Ut)ZcTBpL&dGI^L3N<8V(sJGXU=XQ6daG@5`H6iv>#f?J1&_#uq+k2kFf10dXL=W z!XRAgr4JNHv8J;+t-+F8PE=I}HtI02$q@9an=%er_Yt84NT$SE!!bW-O`9{bWKZKd z9Eu4zQ?+gY$Zn{l01O5id$mOO?wThqfXSz7FqL3~bduBC0U~CD-B6cACHx}uU&80T`{T+ij`grLm zHbzi*-!Lg#jL0x0i`4X-Z{PoFuN@;kp%cpP%95r!ITjexPT_Fe_U(oamH+80En;y% z7z*Y?sIES}ri(XT9z2G5G$gh%uGegQ#oWhvCjVNlzh-)w#Q1Id3ao-f=mtW~doH`a zM(Nt(1}mxW%0+*;0Ln_J-C9yWP^2O{+goAr^5jA2r>-C68xd@2=iuR%_v5u>!9BE8 zA(n}DKRr`#N_vocq{30oW>3O!#p|Y?I3>-IkmyLcW+0@Fiu0(qO?vLnXFb9TYZjG4Qkr(3KYjcxxuIs&x8a*0|x8*x%z z!i?9ELshB9m;Pi0&2}JV1~4&x$e49C|Fo(5y3!Ul67-#GU!`eBn<~iRFn=zYeSvK$ zM}NW)I1dzVnr8;)&pz`hF9?jJKJWvIyi1DC;@{w) zo75kQGV}efT^bgK$O=EQxK=*r7-~uo7df`tlOe^NU%NaiQ-5hVatQtymuJo}bge5J z{QYNsc8yCy?P~zDKcc;h)t(9M+@_WFuIla%_x~_m7ALEcg^3};_EUDtdj31{uVEEb3{ z0j(a*oG43Qh9a^_?GaThl_1j-9fR!qa~C3T`N|(TKh`KOd7PIx3+XDnQE>^SM-#0e zugG&ly{Xk&Tp*Sp2#en3aPrOFa5*!s=nUb`L-JRma_xc3 z{9Kg?U0yxR&b!& zrXLizwyC$!6l>Se5f1#bcspV?cGZ_F=Zqepb2!N@63JH+YDs-}POWF4!F7fc*{f<3 zgx}&QZ9dyi0bFM-W=Bxef@eJ&J0Dc2d(sF&En(~swsdKR| zJmsR|&vi@6=rp1K*HAFNQd5hjm2Fq6qRvxq1oLU_+ObR=|3}XI06yoLY_g<#FOLf0 z2H42Ie)*Sm!n7N@nB;s5d#YZqza3>FbZc9Y(6*De6?!mSS8w-;Q{y{yFH$>8<}DbS z`j}qgH!tTgD!4S8N26)hSy;6O!TXW}l3IM^WQ^&FhohfNkP>O#dKHDXVBcWj!*>r0_SuMlBi)MZnINxnbz8!?@4| z$i~Tn);Ff;=;ud6g+)-olZriF#`CN&V-aB{xK*yG(+j%H6buos`x_ld(%w-doYOV+ zF+Cb!_7>o9(B#+r$J=W)r6(9HJbr%6VlZ6*Eyt)7+Xe9Xrcz6F9=WO%bdSltr!*9q zY5vinUo`0s21aAdw>zCjnf7e?H-EydC9q|8mjb{lsZ&31vSv;GlfSN}+leqL*<}o;21OTzE4GH0A(?NmJP;d)yV41HFwd{5|RH-*{uQzu*5oHP(>=f(BpmL@qD|1 zOsNQE5nZqRQ|{jwchQr*u3__u92}LXpj_=L@xq~qjVGY-J+GN@3;rk}2;>m8L(FW* z!We4qLvjVw`a;BnlkiPEG&w*ALyLYTQq^pzbOe0QljGXWXh~`LE>6@!ikarydnkHc zmJUS~z%1xYc;)Ghp&mEVr0_aB6&hcm4Q~5xobEa$HO=T_Dd{YjYt5ij=$USly5xz$I z_fj|}IO61mAxntVfBf#FC#K<5KJ>)5dmW5Z4<{wZy%roM8R2j=O#%IhxHykpxC@DU z;7Bfs7Zioz6=8^ z!Qob+tIfI*V-jQ{EkmmCNWZqSWuf;&Aj>t2V}vGg4u}y!8lS^XM(@Ue8+nrDy)7_f z!i!TP1NVd?42x#DW(0sKN7#a)an10_+AsiwA}-VPT@c+$9*2K zT_g%xWR}l=I&+%vPH>+XcV-Weq>EG;Cx1)6VE5eWWMe29VhO2eOSXiXvq~pA0^oe0 zt@*5&a6=Ep0q~W;KcXKXu8hn2PL2*@KjRmN#p0*FX70i(MK*qfe!p{KC+0J?r$Nki zJKEK$oM^zgX1(9g>j>uqLF}{?VgAo#7c`nL0x_w)uC~$@0%{M%SI5?2q~o1wNcZf7X11ThBBC15j_-r@Q48=xasqrl zMbbe>qj0&yxP!lvo1y-iWqx#>7RwQR=R8zqnJ)TL{D;bC;Ed!dMbV{~&-G1nkwPXP zYY6$yrH8Xxm|Bg+cSex5BPg^_4trK4P~lk2E~qS0ZOu)v=&yeLh6bu@oQs0u=qSql z5u&cO*w4*!X)QAEdP zztF(~89O;eax3?;6p)|XJ!Q;?8D(&0p)kFe5dfWSBfN>9WFXBzOdZ(FCI)c+nCD04 z8?xh;N1G(D=p-c>TGRtIjlhFfMAxCA!hN6LG#OR+9D<{=M$dsM(x{mdIck|TKBy!; zyda+&v0If|c+MRBb{5=?q2(^{&RPPKscN9UZbX100H*|g#fXwAo?6<+?CCvlTA~3~ zDj#D`)xF=@&d7#mR*OSwfQ?ecS>l3VHd8?S_ER+QpsuJLp-8;Ssi2p?0K2zD9E0t5 zk@@Hxzs-MC_^!o|8>^?dV9JaDe=2A-Vh-v&98tZJ(7=>1)wudS?NT?BAMk3?j^dxk zM2Fp?frO@pzlHaK8dneeDI6?PyW4YDd#*!~Ns5#&MqI_$%7j5#5Nu)$oj3x-(XX=s zKP2_Uv7GPU+V9%VACzqUkQ-m81MwKd+2&o!&xasB`(a9mBt+#(tFUG7F=M_^1%k|4 zqiL!(nOF=Jd<`3mx|^z^DEAeajbli3G}o$z?J~3O_^8rjtsm5+hYXgdODv{hNo8a7 z4_=bC8JJEBa1fZX`sqOr`sL<^wl{t8ZkeB6zoyxW1u|4`y(^6F_1p-cq)ocOeB!R( zxIYYGZMw>J5FC~6z{+1m)DIbne5~~C!%jd-ImHIGZE>a=M;7@Xncv`Ynul7~Z~}v2 zOyk24Gu->4+C88{0$GPKmxUiHEO7MRCI;8=Q0I$68bGh5v6mD04NmqQ>DxQ5V#Bbo zbQ9%p@l%9s*mBHag?rSk+%1N~_%lqt&hA|)U4%Oij@rAW7qw5ijuY>N%Lbv?!?E<^ zK9wTgk)jKHT%VZ4F(ft9!#g+Zu^mDvGbu~V1%i4QTs_su&Me#pgf(apx;_ccx3n3j zM%5x|0*8xhxjXgwfaKG9b%S8ej^Gv8SX59nAOKN&;x#VUW zReA|26Mgo{_`Tt{b3a!j9g7L@m~W|!8?2T6#t{RyMC3zVScv1KydK>6yxlsxvQG8rPspS94R1c&4{C`{C!>q zTp5XdG_dkIHvJQbBIQBm$uYHULRB6BSW!igHALedp<7fFTm-rj?{*-?A428)c|yo#|{RLh#2t6p6H2tfsJSBC#N$>kRDCfvrI| zmhQGBc}JCcGOTkoPa}$Sg@HrKfcj%1>%0Cu=6@9J+El6W^Cq>WP{K10@5pm^#6hnIUU=6koxg(p z#g)WyvW6~<)VwHaSuqbbxyEM2GAy|FRpYrQA(pq+%j#DWeYp3UZ(*X#P4W!UsYS7R zmrS-uJP4z8ikLTO$>pO)!80@?*4|KV$ zy;z*es*zs=Tl|v;qDypq;Fen?;V%nSC29K2-k~XDGEXpgw{H`}iOfN7Es8MJg0_y% zl8a@1jINFhMnKwK&t?XI?}$KvOx=HJ#JsKZcS9^6w#Hie#ydRW94s2us&Y`KR`B6! z|0D!Dv^*)K{BqL;pTY7~UBVR*t<$1+tc2oVWPpR*8`IxHFGnIJ>uGNg-n&g;GU}D|^_{F7DNUMUDcvoZ6 zOw348Rr%bB8)0KQ5f_({Lsfqao8<+Nt6eBVo5;IFG+;}iKZAl)JDgC&)i3Df>vm0s zj46_u&KB*6E`T2%V?;p;hKFV&frQ}@3yy}B$ZUT;eOG<`8jMN9$vO~fx;Yytws(Mb zz7SZq%((iENuZ+p;m(FaiEGsO1d_s~HG@=2Hrqp~(iA=ieXhKBr|-{8p%E@SK5o0y z_v$Av|D$gf{d9`0@s!VmbdX?9bSBZ-5szB*;zrK+o`6GN#(v^f?2+y{-=sW#*z6vg zW~RJAo&HUwG7=Xf)P5OgFKDZG|A zMiTkAet1U}yYh&9kU(Zpe9TYJbMvWsvIu|U{@>5N$H`y0G9KVjn0g9LIyl+JzbWqf21| zvZ;Gto})K1_+Q`rStqkZf%oAb(0i2o4&K$QSn<0esp$09Dco~WTvC8o&4pKcgIF7+ zsxz3-InAAgFr-LY+i@Re&4p{c*RUHy_)2?7PW4gpVK<&;DCLLo$l2Sec1OBs5{A}y z>Or#VT3O&)Y9MmZK;X-ZLfftC(CW02t8d!}UpDf|4P`Bd2io6xf%NUlp&_$F;(bK; zJ7IZU@5UJwx3hYy7v6@STfj*~;nJx0=1l}5xZb8xL)1)1)cg8mAn)evMeEEkc9x}e=xC5qY8F~=|K3K<{n)G z_iw`x+Q`E+_!S9Z2Ujuky;WU0*eb!aH*wpir_8iO&7m&1E>vccz>vz$ zykwJ8Fi(usC6Y3EgVOH&FV&6pqtETr*`-OCiCA6AY8FY8xkV@t+m*a6L)wMqJ120$ zn`scng`?$`W(V_dvDS6}nI?Psi^i|gD4}%1!&O36!hs+2;a_%fhr$^8tQ0?Xts_>q z;kVuV(jtOy>SWrM7@u^M69$zk{QGNgoq(ue{J!aLiR|k86>7%7B_M3$at$VmG+yU2 zhjSVJBqo@<5dudF?phXJ1iKv*-%m^WTO@R`ToCJwW%XME+TL?B2cg{?S1MfXfA<s20O&;^NfW*T1 z0uwYNxA;RpH$IZKrDS8X?xF68@8`W&LH?;98lc(kIpGPBK1+&#B~l+_Na!qkMFGE+ zC;S)zG!eRT=eLOoxcL+c!2iLo!7XCgmJp#I+YC@z3ylL$8N$+xssd8`a}dNKlTJ1# zSEjStU&2cv*ge>)3$YMum?R6Tz0dKn{Ckn2k2U$JRGWGUT3W{{KzR_P&{WwunaqG} z@L&5QawIY(5-LMYs?FM4db?l~g{wp4-f3Om^i7zu%w=olA9-C}-IDJUtV@*rM~d00 zGHMv;?)LGsV7%KnY~!4!B4S*gW`jI5=_AF0na4uoLx~ z*Pg<1zsi01Z;8B^Uuj_85}j#R+T+q04qj~GWqB>Ga_``imF$~k6n4p%G^OFraQNrT zbOrTR5R!8_7srdGd06&)M`5f}h2%)VNZAdhzcM{xF%eP1D$9?%UlW8ajIf-wb2JR6@w~7~0KH*+iE7!bunW@ODPdh;nZ~KYS6ORM`E;?C45Xg9(L9F_jjI~ZkXU&lLRz-S_Z_H*E zdmJxd=l$_0r*&Ml;m^)rmT5uGqpZVtfnqp>6Hyy)oT^WDb9!TN>A*@(gqIW6s=y}#oj&5Lsl}JD_Xm5CrT_hbFIJvNN3e^RKTw}X_s*$rs zGzq>P&b}Mx%TEt@4cO8wyS&}yXRV?H8X}L?th&>@K?9o9lBG|V(63Y?z&E&7`spN8T3Y6 zJ#R{Ke7RsAnXnj`JX(+yFffCYzx4F2NpZ9uIYIEphMCqbs~FWc6%nvDncby%GjP%A zX<+!KhHM#SD6mjyYS5Lul3viuu%Y>h)1K?ASI}53+Cr*2U`xk!c)d%tT>K4035^3V zYl?*LRX(c>dmH@Ai1g;st3+R2xE2|JIA$c#(;SrnV0U9n0&gNIDY^UD1i?jMJJ@t63`7IH<&OKzn&^2f=KIatV_4Y1L6TK7Up>5a{Co7reH z0ouwuC$FdXP>~~|Mx9%1;SY1K5bqvHSLN~yf|YwT(di3qwBJ5d6kvOfNTtW|K)g$G z#3G?@@}m;6$w&qcEbOs73cmfTSvWm7fFg85kix&|DMCDXq9%zd%VeZKGqZjB(JF3$ zj#z+9T2F?~O0lW(uaouL(Mg~=0mMC1blUsmcyDk;NIF(KV%CSr>C2-IK({?sl(Rsc z(Rx~EHJTd=QMMymM>M3-D6q8XJXE8i9A}dQQ!NBAwi>9r5A6Igc&c-K@G)AZtHo2# z&CoKv=wjOJ?D;RBo`b@AbH)zE`k=rSx&Gb4s4Dnh*!KkIA?m0GS|0E#P70aVgEkrZ zsMr!#=?(r%f^>e7z7J>6}*A56<0){`%9Jul3!;Bvf8qKmVFjhn{(ZlXdd`sGE zd9SnHJ0z#%DL^1qe^`hC`Qj@-rng}8G&{;f!9k9n@nA@X6s<2z&YTx=dOgEb#o}XN zdSkFZt-T=$qWLyCLaQ<_v>L||&C|t}*9mSjSXr+q=4Osf{=Z89}d;iNi^q0T9ZJ|9s{;Z(hEKmvbGZytU;Z?eflRmJjH*(&+-7W+P zqKpb{x)wn7S_q$jmV+R;0P3lGOg1bx3^IuXYydCK^zGuvruI^V2lQ!*&}ny3R^a-g zZ@0*dPJN@p|6Q8mV`Za_lJcX7FklJL1EFukn=X)$jCIfZ^8LmomlX~12`G%K8E7`Q zhjw`Gs;0pS?jrm>Ss=2$m=ShBxJ@MWFUsZeAfRwtm z-m+CHoac$ad}ub{J|~sV2?{H4Xm_FIIHuSKL(w!X6wPteyPVdzz5WN}orb|ek9S`Y z(sX*%=$15X!~aR#4es3e!T$`{9n8TRR7j$?HTl4}$I(p`z#)Aw2y8!j?6#AbV)vi8 zhWZ?nbCv^@r{?}@ak3-Gg7mCgSp|nVy-Pr2vT-%N(xIn(ulRu$Gl|`#2<{L3 z4&Fcc*2R5#9kruln7l_26zpk$NYQUeKsziAuDbYCE3s-k*yP%9hV~j2WS_H{$xc;{ z{{m@d8oX)(D&v7^+{4NTve+h@w#((6>+GjC54%q^Q7MCEV{2kS5}1Yi9wW52Si^)_ zBUm-!JXhLX$4d-nlUt2Pz!n@-y-U^q>NbXK#Zn?oYi$?d2<1vWGb*f!i`H`xcZ_JDT!s-M~T$!Gki&Y+~fNpk|S7knX_6HAUkT5<7LbwU1VW+~}lKKTvpBW$EnX zTyD6dGL~{vAg7-#e^H=3HM)3%q+!nr)j>0=J3zyTMPctmn$vqSNWV}v)8q>SeSFVk zBPV#-eFo{tch^cL6wmbY3*cOsXr}_HF_DcX*l>ZJ%+sft6Vj@rck;zwE0I4 zYL)3iptzQLjCmfuDb`$2Ym}kCRI81Ti3T*Sdbh(FJve6_3;k^SFhpFcM7kzNotC{| z)OWT%SjGvumXH0aQz&@9C839$k>T^0My0uuTZXe~rF(?zQ$-E)Hn>aJS>Gnf!l z)lknGpw$aC~0rNMmwj74gk(6pjW=2?7kOZ{m}P5 zm7JGilcT1RzlG<4?v=z=v;f=hb-Oj>Lh4-JQNP~`w!$B?gXBQ)WlplpTlR8-bGo?Gz6UB{|DK4_|+FBR0}jXCa>#iU2+xmG=# z3wEGNMjd?Vpsc{4XiJ-j=IWrjX~Ls{r~`x4Zk98kGLsvB#vuOh^%89MMc&57_Nz;a zlKC2F9-52Je9D&6TI$A5dm$J6s4fYRK8NB5L0K!?_TR zf38L;yzKYNBw}HegXQ`IZ%Yk3#x8S>5r-!e260j}75pB}AxkaCx*_udyX&(hm#-v_ z*-{t(I0YtOuc@L2s(hOGW_PXoB6CkQ`cp>S>ZB8fC82F=9NOQO7&Pe z5GR0zj#Ez+md%5vLZSag8h2I=*cP8;#}Vo-O^p5{!ZvpTzCmL!e@f4k*VsUbUj`i4 z&dPFQU2m~Bj(--H)-=`3STA#VeOq%JuC?z+!~Tcgiksv2pRXO4H*^S4k4hrL6c`xd zUk^6kF8@2VjiU2SMzwi-Ta^k!Qsmk9NGf#hwr9^R@Ma@J*D5NgajVp$MXDuab{|@- z>Xf-I$Q#{e6_KW2pmMvx9d5Dby&g0?t_SV#q2Yn95*w!|{C5~yuI(!$qZ6$=Q@hBg zgYM|g)=JP$9`eu6Lx(#Jw-k))lIUDM>ZnLtbG}hCLM`lpO;$t#bBk2taXJ&F27ogq znL2z6w>j6C?o*$fg`^MA*03EHXo{Y|pU|%+|U9l!^( zOkoB71eFcZ&vG7g$%>B}VSbZ>6Nh|Z^0uJG}d z3?+MZ!pw>UGp{RwyDcvA*?PNv0oq8pBQhHxdv&Iw}TxZmB2?+MZajD zPPb+!B#r;Q+dxh$c~#Y9fOLnw?HQ~Ts<}sHHmzq%cy;iIMAZy*=nj=lhP`P{dBxH{ zH0IU)xaT*_Shhk@u0r@N&)nN%M*+0i!>3E$K(v^W0yp9;te1FF|o3y zss$hg8cBd4mLT6hJrnoX2pXqXTu)>4-E@SljmI+j-Dm&}{piipUV2dR=7-mE z%I(j0^JAOvD#)NPx66OGF(IZl5~xrDB|)nPi-w3RlE8j2V_fw2pUyvnyZb6w`gl}n z*&Q>)pk4vxznXohy?qbGrsHHE3N_!J50*GMLU&Z$DzZQre!xZB5e1G#sAh|%kbd+H(=Av2( zI^4-l#Eo-M&cK!oB1e>MK61qXBU`Puuwd&$FsNa$2KhTjRSScrapgsoNPdO{Jw40S;}QjM{8^L)5tP zi00c&_f5`_14P8vJAq*5R_v4V;ObH(y8OZ_;0Jn1BBu^G&h-a-HJOEB!pVxgh;IdZ z*)LL;xud1TsS_2(#XlgV;*+CAfzDw}v2fMXRp*GTe+z1rPXRu`7f_2|o1a~O1K zM_2PEh;5Uj$3Q>t6$=7$k$J+t9D=TG5xUj;`h5$?5XHwC9W=y=qTBg4jOF^7uXVag zR^q|fv_FSj+_Cw;lH&IiT_vuk$T}0!!|?D#@Z>)pPW+epFwwfQV*wBOdru|pJ`pDm z#te#j0-dPF)GxkgKkDCv^i(H&t6oO?t!fDq6ea*2Km?)S3kZmpB_Y2-`swq0dG+I*d%$vLD&=MJi3 ze)9leB;bP#Bbe5buF6af9lZAp-P`bv*8;GPQ2@>@=Wyh0z-+VH$;}XCOR0&N3 zK9MSYW{su>HdG@T@h4@1ti?>o)Cln6zL35TwT{P-cNU?fv&jAsO7xekeDe3ZQ|%(U zNpn-utNIpef(dv7>+cDv|2oz$>1-H7_b;R8dU|;UTg>l?S#Xc^PaPN|Enz~e*2*fHz}$nl@Qyv1u#qv4}r zQTf4x2lRLnV1YLWl4*ccRFHp&EuiTXU}D>b>mfu3vh&(O*P{x3SpH46Vv=Saw;wB0 z=k=Ebg4%O0FnU4rBaBlI;h(h|4xw299gQ)wUDo|OGq{qK**R)lAjdMfW1r3+3MU94 z?c9u&cQ{a7r0Dr<|8?DkfQDXboXxZi9Vy~R@SVnNSQSvSIm^%V-*yfyM&Ph~u9C7J zsA111beD-8AKt%HxCvKth4nnGlEI$5DBGt_<*Ki$y& z=3jx?z(6chdxd!)V*tkvr=0DN2Z4{9_6ZXhZL2uqgf-{omr5zk5Pl}k4qA_CWR>?e z$E#Zr)NlPq#Z{%aK^SyK8WDvY|l#5e)2dRO*37Yn?p#T$k?7F3>@Dv`$QS&=hn7LnJTL(WPDrPGKi!lYKC<5yq za=p#dE|c|eroNQx(yqYE>RE*-_hHOTNDv#FIR5(%nhb_Zp(OdIvcIaIzcZJ12*61|Ib*cRY>m4nHo zLq+>i4vsfd(~#WPw)|*^D$$|5p^`gP-@(b8e4A-b$GYx<+hU1npdV6`0ELUroR?7l zO>icEuXeeu2qv#?sw6FkM$SSz5|#X=HB=)cB5mU&laEIz#_Sifk?+=UYwNwgR zWvyLokp|^ZaDafL62vT)&Yq>u`~)vqE$4wV=ylc`C%^hZ7_0vAI1=K;n1iVxP9Lxq zh@@=q+ZC3j%F~~vmf)Io!RE+PmG3pg^10Hh|Cy22G%D*DV1)41v}xtPtz&jb(u(nc zCe(MMicAG1Nvs~<~uWo-8 zWlguFfh6?k-wYC#u;ruGOTIWQZuDWes}^*%z5sno`wtVPVhfry5oA1cY()GAuc_pFuVopw zAnt2|x>x$?KFwR>MT(n~BDYgh$>e89y*ohT$7E5c|0A6q zK`Sd=R6YfdmSlnMqvdaL3!5l4m#5I<@yhU4>$J%=p|y9 z_S=MLO|IT!e-p!5Z(Rl1xyCiilr{!6PUVtF2N#IK+xn!6Z5ie~^*Hy3`=!{o_lc_k zJT;fe45l~)_}m?P46UC&z_`2bZMse#DO;e{&WyMHxImk&QD<|B+pjnn@$B5Wm}`{9 z+Q`@<2U`1zM60itRUm&dL;GXcl>j=rb(UlNs6IHJ$}KH|8x(i86v!!C^HFSqm~-ce zFS}ex-R1REi@8OiBHju72&(r8iN9qQ!731#Qw8ob_U9lWm{lL;5im~VPCRX&Sgn1M zF{Ub;AkZSUZy8-Ql^|+<2)_TZHT6|fn~gTPK#M11l3LF?snxD_zLt8uK9@k(pRceX z3vG8LER2=-3qCGD_ICz5HtD0AU^9j$^*i7wC=8a^ZU=_6jL>Lzzvi{?69Yo)HImVn z=(tSsC@r~pum62~!IBkG?d;f(o<%#()k8MebLp7dnLi*Rpmxfkqu13||GVyyMsp|r zT|A)-YGjJ-V662SzxdC!vOfLM+zhN&Gg#qrJN4*xr<)eB+;nL83{Yf#Vp_`K5L@SN z5F6}KZoA3G|0({(ErE8T2@bGW6}xaM!AFegS}AF))6k=lPmIz1m+|m4#i72WHY48Ga9Gt*djc0@moL0iP*-X|6(!6B`JnaQz9~iG^$dfd<;+H<bDrLL3S3xHBmsagljDt*)MSv)_OS?~%k9&~b0qqDV+ z{XqV%E17(w_9f2jt`Kv!n1yP0XSwpwzq9d!7h=y6>7V;-u?mt$bdK&l{Kr)sUW!c$?YicYi>D#t=huZ*UtuTX*Z zIGdR4RpfauahUFW1EdD3F6S{k&u;U=FggCR#;h;Nj)daeSVFi&b9>k2v($rdZt?HH zee%u}GTCIH4>kIAy{FS|fKm@>_RZHjuKiG&FKyW%T)GMrpk^~D-d~qILWt`Zmo*RN zDBA=ag9IX$+Fyt1BOofI(0#ioCh3o^-dypT9nUoM_1KW7q}6P&G7~Msd$Q(>K{P&|uZsblb65bm*gT-tL3@1t&5QKjk{PASzwx9NI!i{|UzC-FnEwzb2o zIAdKPah;}yOPa-7HJGX6_TfgM8oH&RkLVq$;snn>$XMFcTj2Q3G0~% zdy&>lmWPDM@2RX$AS}F{c@0XPGGp&;Qu|8?I!PVn&czb(j z9czHEgq!r+RO8AgCz*GHfSw&h;X50`a&oD_?n+>5W@deywdYtq+1gP0z-s zua+8jw+)Bu8_X`ZV)`uhe<`{$@^vTk_f-R6bjpi&+A*2L6NPJgAiLU$!nS>SacpWR6*c87zEZ ziN=B9ph2nD>&K9YjZEr!F+70{Y=MFJ%T~-PKL6d0e=zVWAAq*clON{JzPMykBmsQEWUg<#qWM(AyBa%1U z5>9421#&P-?~~dvXK`Gd3uEZNs{alUQ`u=rmovU?Qsmur6R6-GTL@pGpmJ4$?eaAr zR5Y3mw+tym_mD>Km81Gajwq)$fG?h{j*eJ{T^?TS%pxP~_f%fj}&U zJuU3))Tx1EQV1v~GI9{c?=!Ci`!1%j(E(rMh)pC2r1*q}HD$D;CbVd}r@lsT6ETxZ ziW^yXZ3dXDVr7p?-;Jf;fRZcMd_D7IL{qU*F|NrC9g6msBpC>}@QbudX@Ohd3uEK_ zZa{K~C9@>#71g1|%@k%|6L(QSX5j8@EL-M>ncN4A*D*#I`AMTJjIL=EO5x;TF>-p? z>jDE!?d~ngUXK)qEn2_z)l}AaO_>&&CS!*jNP`2rvahEKIyI7I)kn{Sm+3=?2d|u+ zS!-YZofN8!)>N~;9P>a@E%YQ?6oXH5Z3yepmBoqK+wMBz$}o2=3L52D9rt01PSLsA z5S#kjx_4BtN%jfE=aiFqd7}K0eZpf`G%PBbQx8`*0x+Nx|Hs!^Y(L}29Tvd>%{cTX zj&E%W-Rw&FytAB^p{7_q!$=HHq;24u*h=B3+>Gnp5fTOnE!~1mbzm^1sTR(&#ukmC zc&PTK13{k${*z_8LVv9=Z&dmU>)=QS0w4n91q&`hVNLKYj~p3@EnCv5F>B?ZQjO3+ zbn#9II`2xAbC!~05b+s=<`J@ZSgZTw2-Bt^xFYhTEW&_!I7zYqC7rS!kQ)Bit>kN; zCZeJ7#`{>$Sj-~$DcJ<|ltwzfQ0*S}g7(g?Z$!fd5cSZJu{*2uVRFe_^hdnSkX?#r z$Xw=Uds04c0JnR%u9p$7ADLjUdb&cRSld{fTjzzW#hi_w7jYS)ODRJ$fEfHon5zJ4 zxM~+?fNFg?e^9M*d8MhJ*_?YEXWqhN*qwu=h;7vq+3qxrq+^(E%?aT_;gppTX|ACT zI1wT31zJ+vySuMP89D=d{7roBl_}zQtEHcXaw95(L~nHj=sW~P;R*hgzdGbDRv*At zdRW6BENv|FB;-Q6VJ!}K@`?!69mi6Vh#Dg!r#|wFZc7hW8P&IdwM)CS5JX!@8p@Qo z2sjD!f$Lr+9siiSy=@j9WG!`7=u>7Hw%kS2ptn}3ZP`=*QS0%D$DWZJmoG1d^%soK z1pSX~qb>{Sphht8vv^;F$s^iE-ZTqIsMtt1Z#ye6qkJ|-KY*$7KBP$Y-VK)INA%G1 zwacuGS+e#Wg@ZSE68KsBs;Fv5zxLPpP{fe(=XgOHKLVFPmaL@Jb8XFZEH&dMOgSE(Hjfa@!(T#`{I?g|F82t7 z|Au4utZ6KiP}J+RMd#)CN@l~uUmG?PrTMmpCPcWrEi_|35bSlPL6)Ckc?<$Vm%IGt?D515`CNtd zR8GGpayDg>&GS}CZ(vWy=wtGq^_&}CCVlyp*KBxQDuS%Xbfj5TUE}EaKh7@Lf@fO; zPN2ury;hGwgz?W>ctWsaGS_nK(U~+L?RrbWV7)?rv78V| z5I$@TkJfvXS7vjA+6Y9%v~KPzvS4s;r)rS0(GR`b&#BY?Z}Mf1ZE}p~S_Cp*AHlFU z+U3<9`Jl~9ZQAsXe~oloq^13o&?j`l0sNNyP;{?$GsVCG0fj-f(?r%H#Cm|NaV(|2 zzyWLQC`t~rEnas87aM0x|7k~R_!Rd2#Fq)G-I$xEF?qE@G#TGgYh$C$mN@+vNgnR> zQGDlQ;Hh28q@!#+yeO>>fX<{%GF)R#4gzI=_7862n9M(SeqX$oXqLA&v_L1VX8JfWJ1|_9GG# zBj&u{3WY_B;gXF~2b6KCIF;ZLkVVoSCO=^D63_g8!D-d1 zZd6b1nhCcw=PE0jCt-A;>+!A5EZzm@Ii!JL$d0+2hF{CWm&8wCGO%M3>UY{M9`WH{ zOUD_rP^;@ZmXiT7H8W#5FZhXV6FWzyO&>V$@AW`tZKsZ1S9ZL|`W>PHlTh!IDPK9T zTA}>SfnC4=YEsgjaBnKlTZc5P`%SBd4iydvIDs~>>xB6PJ6gDfYUQiPGlABE4P9VL zv~{|*5fEJI#UhKKa9dcQJf4PDWJRXG#=HxP@&6qKdtG>7P*Ge^zh9snCUJLo!*!0# zz|t#uWcq1RhG{R)=-&7};3s{xB-1?!G2b?H7_MS!LLDMP^g&8|Y zz^TfJb9Rw|B| zuiDqH@5u|U2@EdFpi;!xqk8<=Mb5?9eza++XlRfcP?XZ2Rr5bXE zJf~Ppg%j{Sx74{@a@hjE0o`)ro%ASSBT=xHZ-PdzzqGAwXKC-XP<*XSw2eb4jSovC zy%=kcsb*PwB{$?x=d`hU^$w#U`s@6sLZ-tt-#BhwxDg5D_YpC-LL7i_!3eR6)@>}jAfCGMOZsC7U^LmsK)RBvwlFSkjI!J5o z&uCos_MM2=2T6 zIUj*0P6=0;jYsyGrjtu}(4Si5`U%L=LkO0*j+q55DHWls?#xBPNAj>e{$qbxK-mqI z?flU=JE&UoMak`VP-f)CDFN4ZQ-Ve8FgS^=P8ZO6OW}N>G$P=L%k0~{i7};WF~ZG* z|6*@yUnlMQO)UT&%0TkB#(>1kG8s7+eQ}ox4%O88Dd;b}hVwMK9bB1?P5nMNSxUH) z0^s1HuSpjpO3poh_ntO)Dk1#~UDwqux*M!Ud^}+hRyHb13jn|gS{!uA0N>wq2WlX` z$z0)m@uFXyeS`9BoiYcKjiQiMJi5V@3SCS5$6&LVjUza2ent>ad>$c(FOgNiifits zsPO9Ns*O3KA&JSq?yBTrHiNB1K-RCu^bHP%?oQ+>)=@r81KyN&C~~(kJkjO7|0}(` zH7%Qt2F_>t2M+Ie#~e&z)sj5QV6BH`E!N`BS{bmOfZnm5){BbL3jC|__fQQ!5)u}G z_kDc;qp*;74I!LfSo=b5m3A?{4lAV>ExniEZ+LnT9HR5gh5_}J@bHgCi+G8&iZ&hu zP=@S5H|;<5+KT=frBP%GrV5uxi(iN5*;HZEvF72kvb;4zn9XSLO*yi=-YyYlf)ot- z{2VCmwggsF%a8&Sx@n7#=6AkFOv{`Fkq+7JdkxM{NAE4HO-*J>GV(3veB`@dzdOTr z&xtdluP^tw8Tg?fX?sF@g{$7|l=Zb%#k$iHD^hKI%L}B%hV5q@-da+eq`+8(gvL#c zI{r}l62J1*uOI6(W(8Fb@-#d8W}c5r4bpH0azAg-fI-22d0xz=&Q)~eQ$V;FpvTeJ zH*?DU@#k7(`X7=^fj$WvM7d};U}{CnnGC=35!I-ME^j@79Wt)^+e6du4K!78mREM& zIeEi{C5K$Jww$BP$}>|wlB4+J{(T2LU=JMDbA07E!*=n2x#y)M`yrID{KaPEb z_B`_zjhSbXeS&9icFJuOrR3{vail)v@>x;febG`x6hthy4P5?U@}#drDz2?HH6_k! zd8a<3+^cL1@oN7@mB*hlz=iVjAs1j*rA)ilby5HK8+kr_4pY zA}9B;adi}AN4wqU>utpzxuldl(b&%${599(J&)t*%&07E^-j*p7)=VAb2JM$y-Z|g z3=spE;Gq5xj`CBLzzBuR@k&G;=(f;JD}b&kMy+;0n3mED&iM%Ss`MC~@-#uM`l>I3 zvxp&+C)ldoUnBu%+nl@psQBTHV9j8e3l$2g=dMXuoeF73afDoehT17p0JRp~2wt5N?7s(usd2?YWTvBSg zD?!5Y*3+|ag)2VslJHG6MbH}|^$*tbIJFhv1bl0&*E8q-@8qI7H>C;)UF!7s6|Hg` zE|Q{!g~NUHLU{$K(NOl}`wXIPHtd1b-FSys1G5Mb0rl|?q%@tbnBvUI!fuEkx6f5%i9A^H83KP}qrWi};ew$6U{Nbp zwz6e;UW#v=8ux^lQ8|VkFXQm8_*y3sqlc2eD76XkKsQ=BF{RFVSlj#Ujo2{sgx{C{ zCXfZOZRN)GPuuW&SH=MpQ8|Y+_V1mEwFx;KzxkKvW%(ynZkk0*9E7_R^j%{)0X6V4 z2cJQ$Jy3^>lJA4{L;<0hs}Qy*{LwrLN;8KI{%t@wXyO*?@)j`G}50bMc7 zSSBgN&T6CrhijuWl>-#?o3O8C0U}Kt`Qfl@s2BTbP85Vjgs!@YHXCYaLWD`6Y$98g za#v2zYJphEpU8+V>AuEYT!UkfFyOWZEJ|$aJ3bM>wY^JGzj>TnMn<*duNKx(1TVmY zWrdVfH1-~*z@(2el?$;FMKq*Woq_pZIIcbUCYn4*DFGIQ86OD;W7SM`~Y>46!%RmI5ob za_mjI9WlA=DoY!uoaURX$3y~~0$O*iP0*srdVV<2P#<^l_<6J@Nb_x34J!P4_b>ePFVwwAHEi_+MoKW!Xp z;na^^l4~I#zM`YcCzj#GMm)iK%`tYUG`!fAn>+SUb&-2|P78UiB3x%dpswKAg$QfE zsBH+$`RNyep7#|pBXDBQw2qrou%jsvHG6`y{pv5_EZ`ScG&hr%E!1`fDq>=gky#B? zvc%W#Ut3-Trn)x7KIzBcNh>5;5@&P!klk$W&P8`v?$wlG|4pw*v2$4&1TMqXY-JB>qW$yRDgMLGd~T9BYSd622%XA9dgvrzl2 zk)kZ*ZUnLU`o*YXuha zCn_X6PTS0>w7l5ufnu~om`%TR-KS1{^nvT@rC8LV2_RXL^8r~VAL4WQN8Bsl_TM2* z#K40kA_|`@F?z3^e~K{mWWD7AvR&*50D|UN*gd9Bq-WVVo07PO^bw-}U^RwEt7Nkf zl^qK_<{ic@eV&BZ*j_VQhH^uifDyR2EKnlnk2UKqE5@ZwU&$RmJUSA@6|4OV@vBpU zNHp>WY@+EDhXu}ZFr=yT2o?D^RY5u05gai}3Vd#)YSI2(&t-s<3A6GW&kt!YX+9FC zF0}58#sYwA-4_0Nv%)maBd|RdU#OELsnJE|X~b!XydbFfgoBP`BRh`Ts%!+GKxvC9cFBHto+S^ zHi&mS`UvJ1cl&f^u49Q6OgfdMOaYhrYZjs?fr2X+q~2<|-zpl!IHy%tqX26KRX?>VFY*f@whMzHU=uk6{r|Yh(NVJ7b))7Xk>5}~SrXXT% zcs-JkQgUv(c+Mk{UAEq}1&2{M7`2Zi3PjMEhAox)dB1v@co26g|6;`f{6ZU-tx&a0 znVoOHciEr1??k0^wo7$73(d>sCIfoj5iIk$hJGV&4Mv=*nhSNN_M6)${NeR0_V`ZZfv*uT4%k;U(o$QJw@{alh0l zkSU4V!LHaDIVPBBtP=uxM=5HPccR~&YpOdIO<+vVOty-HqNikA5 z=4_(b3tsL*%;-)Z|Z_nM(b)ba_@ZD}wI7Tol-QP6v^f-+%l7rZ>|3JCiG&wJeJ?(v-eY@RSYH zn)>@Hp@Uo62AklfgFv6{|UFi!1wGn4P>d0A0T^TLAVc~9thRyXcTwzo5d9`!E^ z6UkqfwMz9HTsMm{XsCqOx3bz^AmiaFPx4P#T>o19K$ZkO(r zfiJXC^}!b4Ayn=24ccKnRQUuY!ygLKh5e%Rh0xl)8tNCRCw*RB?s$1u*d z9F;OG%<8WF$l=3x3#cC_JvnV2AOAX^5FQ19?fh@7I`*+E@HWX(yx$7|;P2B$wvgk9Ge+sBUSMJlGz{>aE% zjG13RsfM(tlOzC%2yaLqY9jkfoPF-eyax7yTvvd|{L-KeWq+@RnIcVff?O)PABdUT zk&OR+B*$~9ZIF>Ph&4LV&f9>pKsaQ#n|cD-48+)3_%}*Y$LUwixk=S#a?+Dve0MFh zxmTqRcitm{GeEBzXQZO%<73IM^wGbs!QH2o=i(4BuEv(~b)ZF(y&eGT?Ru(}`V_io z?V-?*QzjcfvJpCAQ9NDE7Wq6&vuT~Dqfy#=ub0Dbo_y6E*^nhoLbPb8Uy*&bZy#gpWDP$z^}m2jOi{}r{T2ZL7B?gE?I#(k}$7T(j) zfdOHSM%5Y@KsXBR@Mi)frNqD!bE4~N{nbX87SEVedfu9A^Ve(ws00&3)5k4!y_Gl@ zH0+Zu2LO%EMAR*UwB)VHLXYB(>V%zl#2^1TiU^3_v*Pb#S-6#FNc@PMaD6WT%xnPI z#;QgnVXsP35&)Jd!hpfIm4Wrk4tQ!GzJ%c^a02U_sS@V%W=x0<>ZE?%==UAtkdOr$ zc{9=t;zk{fCs6Kc7c~^f^0y|uDZ{6p$i5baKg?BM@hk-X1Up^?0GXg4RYyf}2QB>C zPbn-F%m5JNyX}Z}5z?>wNh3!b&WXGVXn?F|_8_f#kHl0mFBGN_QG0G026&}QE3dwqtWz=ygrjr zu3A zCY4w09E%T#iV&YC|q1kQvZ20+@RukmQ&O%IjabW5B-KAHqTMv9sgz;OafaNmlL58Eo(kjX!3XHO0LFqyX})pLhisqH)|ZiJ%=g zaB%u7A&=Kj{a^NHV6G~8UslkpMcyu!fEb7YhJ zIs#L5%{@;W+~$5Vnh(`__y#BjMDT+1D%?U!nSaah{4t8pw+~>*_tNE7Fu_R@fC6D7 zG$b?SIPhs=!aKmj)Re~VSzDWM`F>RNI_EuQcxTA%(*j&>BEJp&dnMEL4 zlj<-tDLaPATz>UL;RJzeHdsr(neurb3l`)8|<8cXyLR1kIp5GN%i7 z5-O%A8dj+QalE9g7TiREh1gg}}$|jgJ6+ zG2uK@dfoNKZ219T2;Y>*U(uA6d?fH&cooG(Il5XHaA*!HbIWN6@U_N*zun;~th0n= z`%bIE40o1g{S+kZNu=3-5oL8o@mn!h8C1gwa8{OWL7gck&NcP?8r;*n=K}f2)R=Ti z505OffRDs;BSgFfN}=YtxLCM{Bos<~ki;Q;)IjB_tV}NUj{Z4!2x|p<YGPejE*0OwrnSlf)DcCru$)M`JwO+~FoC?&oV zj=!2r_I*HOEs;dErL0u-u_mo2J3_wBjS371G17mHw!&!YOETx;(I116Y*~@dCTnVwr`pjrv<9*&>SEEaM=$?Y^ z3oCJT`X_&GgD&lmVXl5|8%6V`SP+gx1O)reh2L*hSDDsg+cvn|O;PhD1w zx=?#&ZoriKeV}&mNwi_PGN{K-MUFb(86_mHF$-fbtF9zUeI1DSys7C?ls8f#N-vum zOq*c|fZ454P1GC=Wz~o-E~R<{k6Wd&kp4uLR%E zxGny58%!kO&r@Te`*-ltzVh~et3oNp-MWf(d)ySx5_sv_r(9(L$AvvPb>UPv`wN9p zzYY?G!6^&$ssj;jCo!}F#Q#UkNlXd;ry*vXnY3z zmYw(ghRAsKZU?^)OG86SCi*C)MIjBKOi<=+r=q`8VhUrCmDj9%V3#x)(ga(7VuYNuwf6yyDhJ>jp zo63qj-VU1h*)!#hc#4f=rgJfJT0Op*H4eXSz?4pAL{b8CE;*9tFgwBxmWbrU(?K#5 zW(T>_sV5??f!d%r3#gQ{`bgU|?+Ro)0(9GW#zlssU-4QL?C4|Zy%OOQTg%1u@Zvm1 zMq{CkM5AmKW$MKt-Jg8r;fFXtV$Mi{QtDl$UUhYot|^;|SGXmsK1|W%-ug&d?6fbX zVAJ>TARvQ!SNwyu_8bgC#=bb8M+OtV1gby76+@W7@Str?In<#EdvW+3Tsd9{z)-x(gsl$pyLPHs5XOHQ0*?G33MO{AQPzF=L|>g3QUY7= zm!gCkRY-$>W-$B9r@4$#+%PV(s+D%}0ksnlF$5N`G966ydSHDdWF0u?U5U2MoeyIy zEb_BD$M?k{Ss4kG2+r`;W;EvlVSB`8;`kK5ZF@c3l~;6N-r1pQq79iF{>dYYFw)uSi_z#`6db<^bk zMy=c&0KgeNDkb6ZTYusVG4!&|dHIfNYswk47Z_$z%&+VoSKcz=)+@H11(CUya?T_$FqEUe|~2okWc=LdlK#zM_21R zLaP)wG9H=|>cD9c+m`AP$O}D$!HBmhgYmVv0-N>?EZM(3R?t+-cGZ|Fe#0F#zBoM*!+dYO;?g%y`-NozU zza;8d&X|0!maN{s?p%y^yGpV=DqL!?emsG?`8GG3==mnVhmcri zN@o8bE#(HKKu|=eHB>{&UntYK!_Y;+`^S$?%a@^D=}gYNzn}6LaRE|)wsfTS%+Nq% z_??O$-E{;VK#e;%b!md+NMf<>W2dBi@7$Ome^Baw2wu#L?g2yBkLJvRBSK1LaJi<% z=mEt`^^T~1tTVex`E;gWqlRQN^LyJi7U6U4P{S^vZ6&sSvYKs4H z3nQ)4{{RFgw_v;5!-U+cvY(s9w%A1HAcP- za1S_=q2n0%-DtR7ViW;WQ?)3CX4M*QC zzfS9ln`uXAzmBhdYarcuNA9OVZPh@{Wfdv}dhgRCN4KfgauNl}!R{WD?9cM(=OrfT z+J1Npp;#9Jg;I-tjS8gdZ~ok>nJ9gk_llbeV0pOfI8mVpIl4rTq8Rm9m`v6_JWgpC zS%-{zJk3bkxK~n#Py#5VQXi;}8EHo@yF^%Ld@Zi3h>u6&S5U8cg;;yYB75Y2kkFC5=%z znp921F}iEvp)juotKzPlicOO31egrl3VzvgOZ!oz3Uo70e8J*fM3xSe(mS5Cm6^U? z2$=vNRmLA0LPdQ0Cx#gWW1e)m%5Kc8zaTSALQ};Mdbsw?hp&P5ve<>=X|WH2pWvvk zlj%Z~p3TM6+yzfThb7_*+q?*OdC+}UlB+iOwh9${;)lF=cuqBQpz$k+m}7Q=$Ghd4 z4F)YgzxSqHGE@M9P2l*&5b;Hu)`5|28+^u;X*~PPReLEBd*His0|L+s8@7@rA(6u% z%a|G<-eDATyl5&RI}>Gu-j(%%m)>`?jql7hQMg!8HfpjeIDCrj)*qP!GV9yakcCrh zVcBd3vp6`ndPgjO^6)q0N#na6VV@n!m&B$-MdA%VNnC()dPjSgY`5;*vB$HGi{ zWrds$3Vf4y8Z*I4G4NOBSDe)u6qeyZ`rT)%Zod%RM)7nyNpOlX18fhdjDHRPAZpk@ zn>DNXjA%42y(a-vlKC1neSYE*fw1jPG8TpLZu$}LLC`~?x=o2W=7Kh?8Mnul!q;L3 z3f>860aK3%LaeXySpp`kzoJK!%!srn?_kPYseZHw1n9W$mNM zMgT+|S1Wv0A&AG~O%UN^zR`6g{2=To3%Y;hX#s8ppt{`)4lzU&%_PsB_4sKW7^fy! z0?Xq&6U<;kKn?D#N{|d!N1Y@!V9+#itC_2J0$R(0L)gnN2F=v#8OL;LKRO^uJ<40U zMQ3wVCck0b3^lM3`B;hkaqU&&#@Gfeu*Q)+b5>7RqiV~Fm3#*|?f#(NtXVB&;ny-` zC#P-Z2ro@aEekr)*28WhsZ!_o)tODm#zkG}oV#b}Me3@C8X!m#?~P{sPN0Lt+em@P z(6mA~-~ueM`5^fA)F;bjln~gt&2T*<0XP)s_A;gr-qXWH@j1!3*%dB43bT;Dc9Q*+W^c6lP0@**;XmPEyMR-#7S^9 z4cf_L(3c2Ik-jaxj=JGUS3U>Z$76~~P+eBs=iORYqKQjm?Z^(x$VGB2K62pHILGv?jGv}pu#i?|D} zQN2Spf^PzJRwYhUTkA`X*NCt253{oydS8#Pfuo3};h1l#dpd}m?bGJpU!|tNk}rfG z(`nYy_f#EQ{wMZt=c_s}1+MK69~mZlXgl+nM7%3Yk|Z5|+6TAlX}fF-Nn|$@ub#rV zZqD`(xLWl-u6cRH7Wy=jmvaQ!zq#iCqMovb&8f1ozO5doA)1a#Y|tq(D)?Y zj>r{OU3#SK3Yld$ke^s+WHss3XNWt1W)FdN-&?crV@JE-E;}v;SkZurR2oLO13fpQ zHp8P^iV)g9ZzJhhLVfKZIf&T#J9Vx64VT;MPj^A;w*;Q+z&v6?e{0OAL z_8V5gZ~ehriA|JspfVYQri^x`|8IWpH%E2-U6n&Nc>jJ((}=!)f=4;{ak`E--7c7U z0%2~kI$Ob!!}y}_D_QCB!h_3>V%!MDymTcx8e7bfFQ0>H!KxgbeuLVo%@wi2!eZ6K z;&y;>or=8s8GXQJz~dWUm*=VC>W8BBs9iBP9dc`X0Gnq4rcJ@?s6zRJMnx7;_to)+ zW)kfTjLVCJ(dri;K0d$f!CX9Yw9HivTlZ;2nTHczUT|%{QANeQazu{X2(SvkSd{gZJjS*%v6+;rHPq$sLEQYmE7y zpz+5hf5)UL{}9_qd+i{Fxas!Fu$M~TOWaTfMC+`S4>U>E14(DTb~8W?BaE1CBiI*J zcqQ!7HBzdl2zI>!UDLd89=7p$bC9a`Y>=5WU6o7OY*}=+5cw=Dh6pi`*}Mm*HfeS2 zd(X}|XKA{4y=jpJzOBF?t-vF(+VJHHX#`sx|I9h zbohm`n%g1n<#tXIj`Y$GqJS&)j$*dV)r;Ky2bM!pGc73cJCIzf>Z*!{Gytk|wiZGqZ!7#R)h2X_(J+(lBc@ph^zOXMmuF4UL$cXR^0 zvno)UE4_0tyihy!Hr-7qrPVc2Iod5^kx< zg{WkYL&Wpw=IfbJE_u3KBsw)i&m0_*TQ|y8e_+m85G3=%-Z1Yyc6Y?F4=wX}OfUa3 zvdAgV1Zlc_)2}R|aHsnG%bn<58{0YPkmHSu43TR^INpQTR}Zq~IK4@xCD`F272%f8z?26`-S!-dhd$iZz}+3_}YJfYqc=E-rO8WFiyNbFFgs%6{yU zVcYfk4*w&@9o#WZCjN`AbenCw;7S(ARnpDUv}Fk7XTjSr3Vd)k%a$x&=id`xzp7H} zzTOfpNImxGE>e=HZwO)`T&Cm)5Ws8qg4;+mAO(}(kV`3%D-FxRU@Sd?%^hPcN;BrL znnhIF=LgHX?Ola(@`_#`OLCK5{~@|3;z_wy=a~*Sw8z;TFh4j6i`ZkdUh%qA~gKZz^Mmah{Hke{6|cBkFwFld0Z|5_s77_vBHW>o@J z1ANh3LgAbFELiJXLp{#PxWPl7-YluO@x(oQ(AlnL^`c0u!x=^J56ooJiDDa+s?3l`1OC6Dq77M$drA(o{Kg z8oizHkZxVi*sDpC&Aif!x-^AhVac_r<12L0O5-}wD$(GY>^@i5ReKkAx|dW^#6+SN z9!!C^T)3?K536ulsz-e9fRGPW+Iu(Z8LHs|-Kgu=SQ+`(xII#k!kzWAddE)N{V;`( zyEl*_<_&>S{!l7mCBs!AuuAst`rZm>eF%N@+Re9Dste{19x&gdkad zbH8n;HzVbvO1{_Z&xnU-sq#p*!@GG5mGc*YNEsh6XAiJpB6>U+$qvh)^>j|m6b&){ z(HCYji|TCvBy5WV5s;9+>Oh-A*C%tQJyAt;IBSB8j2@L5Rg2|6DzTuy#9z!H^k^Wa zrq;V+mUy_iYHJh%h;BNT4WJY8}}G@(y^v2`t7HPihX=F;oi<` zy=4RM?+xRmg09qO`V}nvi3-0uG zG=YyVzu#lq0Y!PB4VKW-zi)b6HkjY2OANgmDoU$@or?4y>#~g!s{~-Zw#5sETR`zy z{Y7S{7wIrZ{ZR~P-t0q|#9wzaEFVXIDFJOxlxAARa11O=fDAHgwVS5K&*n;lrqhF@ zUJ@+k8o!lggNL*1%{^Nb>JWO)&YBcEzEz9yD8?0qYqNzPa4g)wrRXS1c|~uzdJx8p z0A!VuR*a?g;3Y?Y00|P3%wV*dE4utG71nXy!v59Z&~Pmlo^Nx!%lH?{$a`$<$e~4j z+IDCU=i?VG*WPCV-o;}L8WLPmaJ%h1(jCq~y82H*RVnwrYb0)kUQ47ZZ%1l5eF5T6 z2T)E5$$G87vaPi9R+`|j5?#;-p?+J8UzE?Xthz*cs$8=AQl1M^mdICOk&ZU0iq*@Q z{9n(RV<$K2JjGb15#4Y&(b_)xS2D9mus@KHj+Q{vo9sRRAN->>DN4ItQnsa4C-+0YVaP7gv>)BBVLz;uyu&nLqHt{6zE*2WxIy@w zM*B{`T)ZsZl4lKIQk*Zz=36w!>F`v7cmmu%6;B)Df? zdzG0O2|D8V^Zr~d0nDvX9ZWh3oH+;=F`TWNN&FRBlcI7Q=`r!!Nc|4B2Ser`aH`hn zF>STX_FqjmO`d_~X>WFnEiR1}F|U3&+_sjd0(#uYb2fmIK9@B;^IBJeN?y?qYx3~+ zk+Les_Hj5=#ux z$Nw`v36bG6G>)O#si#(EXJbyAGfCt&a}P-Z##s% zPAppQsF*>k#m^s$XYour=+}=Ohw`kk+y=3#v>O)%fj<4`ibP%^gDiO@ucK0*u+vOl z$0du-YWcxNvC@e2<1!gF%6InE`wJ~^1Q$C{L2qvFwzsfL*K=7|{fWJgPSFL)a-BJY z*L}DoFt1EDf8GP0$(NmAn*@(1D{HZhP2zL}->-+9Wo&t{`IM4eQcmm%> zpnJaRI?S@Xzx-de80x&_&a-NYUiKd0i^#v}!tUN{{hD|r@X9R2PAmT4dG{^GlvvR~ z7GBB$vG5q-(beZavOMJ-+%YGr*Io(PLq=^f;MYXT8z!iA%lWza^1nMB6{(YLp8gnx}?+q=&uyY=s>vRk0vn zqO$3eiQZmH4!vA`o?~G;{f2~+g3o~8Vy)xUz!s%sAXCl*JjMO`DZjQ*iVi20J0XeH2e56KjOF#2~2!^&0=TD(;fd@ zD;1o9&+%sBjqp(&d+G|atYbO%hN!O)vh!zZfKT$xLv%iYmwN?h zL=H4>Q5$+`*Kj&8A`4RZZ?f{;@UAD+M2kW6j;l?{=t!TIkQGo6F>6}pBR>EkqM~ag zG)0>v&dWu5RqL<4bo>V#+SJO*kmxgsiMSlHi8KDuxG$nOk79(z>w;2jB%Ek-K}`C_ z^+2wDi-i?UFEAqxXo;S&$#1PHq#O<4)oFrxH4PilQ6f~LPYS?G9DFZ-WYoIHkMZw! zBxK~9;W;5K2!3nPFE*~P-2P77yGgE2L?zy$S z9xz4)W}5Ry0(-buhecrJ_=k(g*}}R`fLWh;GCmUghGyDk&=lQ3f=_*ro6V;dEPfVB zl2w|Nkg5uVoR9J9;Y9nR9wWx&kkLXKd2 z2W3@Q|AN{jef+R3sc6jK!ToM%E(x>I4vg84u;?&a$g;MhGAOD7_-QsE2<&oq%1^4K z5y`R}w1(`tg+MU_a@Xbp0Jm=88%RTqX*=F87q@syLFXX1iNgMJLVmo=Q#uR~mkA-pv%uYhyY~ z!1wiaygT@(C5~3Tz+>7cjzF?Z4l`Y`1~r+Nm4WIcia6hk-3_15HBdL=v3kOr$sB1> zzy50FibTwEW3@ByTJQw9Z+A&SZ24VTb=M7hzcYhKW4WJ52Fq(D!qoMK{|t2k;Pl9G z+p6jC~nbU#St;yn%gZA%vaT4K;S17ltJ8l^0aZ~703pmSo z@#;CfD|nl2khaf2nAU%#Nq>>&_|APGlb!81Z@X?>6_7GQsm<1*8G}hnno%|g&=16| z&yfS?8}T&Pq^2;p59D*#OZV^Dibgn$aL28W-i~4Uoyc#4q$8l3IIjr}Y1mRLuxZ`= zJ6=LyFB2=jM&%F{ZOU3~hqU)|G>WkpR2Jm(}*o6i>z^@K$Sm4>fR+Z9)!QyytGcdBDpAjXMr0I7Rd{t6vJ(t+ zq#`aPwc>p8adjp6Ly&gq32KO!>!_q6@ZsLqBVXP-_=p%zy_La@x^zwZvUwgEHuF#@zmwGV@(`lqBj9T_WsS;L) z`AOa&vwvpy$B0#DGS2@nsPeH(cJ>-H3QentxgD7m8`mPw^Lx;5CX}Z;e?oq@yDw!n zL1k-}9c4|^X8YR6VPU7VUfZ^9+qUi7wr$(C zZQHhOci*;cBezmhm8#?^nR%G}h;yp;{?__-G@~k|yE=1QVGKul{Nub}JvXwCvK6_J zJ0jFg2hwt34VFiS5{I=ZfIJ(xDkra9HjfL?!LE4@d_9CE#&F6*!aF#&R{C31L4XrJiQgz6Vx@q4_#fJ+vk4+%Qn(!@K4c?#nAC56RnQCba_4KzVh8&1Tusyqy`l}oQlM1o~@u%=Eb6|@PoMXLyp&Na@GhmBSbE>s!K6dFYeto|W7{M=! zQYtf529Pi^fYCNGi43drWB!2agx{U2HgBhFw;r?LiaRmy6c1q}<0|llWi>eX~5HNhwLFOtGj4 z5ks`MQyz&qeJa+~^j!cHVH7!$&|LNj=|fh`mRDj|6~SvDh>Z!UPQbJ{YG?ihhS?m5d?RE^hwh+{%$#vy;#4Iyz!b;CX1PO9->2jR)kiX%Bt+t4HJyf9W!q>msc05&p|cF^0ro6X_{b#Z|2OHu$GW!3$MLy2D1UQvszxU)E%>r=CfgJc{5xG`NN^x)_ zbF;hsCI9B`dFzLjkV*_@2D{QsR?x_JK;&@hlo7Th1F({9a6VV(i}_bVdYqPvT2Yqd zp@Jvf7($vmg)emI&PP zag{=^@X|Nv3F$$(9c(c;($AH!;ozzBc;R%=rrZ)Se`q7YgKksVI6dHHY2ad zVL!7muO5KJ=qx^6dXb-nV}(*F#8Jieo<#fArIpZH{58CpR8TcojpR6~zl{wX&NgTn ztNWtV0|lk!bVKPgLl=OFB{PPpu z;V{Yn3xFgms2Bm_x{HVcwn%2vjj_}9=4RUBmx!;ONjr^p(Sc;%J?==Q8$Eo|MMiNi z)E*ey`7CS1(p22y8zw%#yZ58tjgg2{S0KE2b z+19cp?ItVh8hkce;y{@6AOV~>#x;lTT}ltSVsVo_v`jxjZr{GbnpQ#k*TRhokbA`o z49$d-8L%q#>D?3f4_@N0!5Q}#cj?^zS=bjZdtcbUQ1-S7f2cig{|x+#yYdG&72v;& zb=J!|%Os92jM1$AWuzpLD5Jm#eLo@4oY+faTfTdfwNa4^UnU3fhm7-PRLI_(oALUt zxodSh=w|;Cj-b4Jiv+gFs}-vkhG3+hsYMji(J3cN?@Ofz&r!uSgE z{c-s`N}Y0FdP)Rtf8v}jC6rZKZxF>5gO;DKjKDvx?zP(a<4(nksR3}pp4LD`&6|qRz`5y#v?R(*FX=4 zdvh%oo@H}$P|5O(HYx=6HVnL+LnikEHIQPl7zuxM7d?8O_LvZ&gV}I|!e+hLggQwf zw#p7)bfXb7AACXQ5Pm`FbJQb3r~zFSA}Q+cNNvRlE#O~&K0OE0_QwNUE1xXQ#0+fz z8y%X>UMs(8&`#A!2%TTAMVieCent|sp-43bBy;nm+vrKwUZB8e?WlfhuSJ+VJi@3O z#4*Z|+T2?Mwqi?q180^>l)LZ@NzRhIf3x$@T@+?MAyW9H(awjBeoG&nsD}@w_l+E_n6*U3&J}rs88UCb zCg#(}JSJ{9I4Y3V(&lx6N6RpIo*67ZjtZb|SRyGw0zs=%#&x3Ks*G*gC=0ClE8&$w z2(;^SP7*6M&$J)vcZ*cUR&vayU+JZtTPvK=6XR$1{7PR&{P1wlYI1k&!#azSJ+Ta{ zDHwnx0mH%r$)3={>{6*RdvulpiGyzPQ~4xz1wsk>OiZb4eQ>|^YP*D`goQ|iTtF8; zkUVb9lx!HgX^R$BJwdh)DYinzm0;!1so0`Y&}xY|h%bPCdQ!fwxK}MMsjaqXIi=%* z^Etx{C3T7WCsFk3xyYhX}PnbS3Z z{%Igb$qhsjaqD4jt*i`IKm1qLkKkX9S|rl1=1=0qJPaRA9pVi>0RB~>-Q407hg&e* ztBn?CS1Mi2w9!BfqH#L!nvp$Sp}__HoUsudKwyQ41T+ME6yK&&%?aA~AZDq->x!Qj zRH+ode9!63#JME3&w;U_(?5^b$AO8s`N_@=Dmv27=u+DV?#U$25G$x>Om%Ct?y8t#Exu~q6f|MrVIxkj|2(7`oHU7DCma2hhhR-&_DQc7K z<7DrwpkGa%+$r#M3CS00J2F?{l%!v!UrX=0d_CCFEB zEm_JA;Dbraa%295X>g93x!TWL2{j=;Lm>JVR^@zgg6!clmMj_fRp(0|YBZWS(}3!a`o-ywsk>%3rgMD$eDh17L~lQoS`K{Hss%#40Sbycc|x&T~!ya z8mCMFaK%4)FrmXAAkpc=@bkS`BH;K@b`+-P`VnFve!cgjWY}$^-LwegvbB|7zhDmT zz|)}M9voV4H6+MsCC;C$ak%hj`)(;o>P1-BFkr?Iug%Kle}0tlTYnMB!}ntnWaj}2R5DC3e379H{R(w)ZNg3fxApTqAlq7y9=P8eu!V+YJ< zPhLFINgU5|@qqu{n?LW2g4tY4n*}=}n9b1gHSPVB%ZikQoGS7&W)&Eyk5U1+$gBOa zkH&`Y$}eS%9{t142$%sJ0m9(jI%kml83-Hx>frfyJHeI8TnokWYPEhb61^^y@W4mL z%j3Kn3kjt9+DZfHftWEH5pQsdZ%^b(dw3N1N3YhK$b-860RN z7YRHFhh1pI_b+@xIjzROul0(VV%!}3^Ymz)R6pJK8~H<%0R;kmSXXCo^&QT4 zhQG5Ld5ewLT|p|96gYAXWFGQUE<@&nM{XES>SfBuUV=%QS)1pkOLmt;@-dmJ+O%JZ zF_{lYPGR6R+;|p|VqcNT_sfUZPZe}C9y^!mu6iZq2%hFK+ zx1vnIK=8_*--*f$K&{YbNO}E$=0(3%=aNO@v~#x)FxYNL2mT>2Q)ccyo5adI1rxq# z*USJ3(6uA`DO|KsMUe8wNgheq-Z+SDztpi#EE<^?xWW+qV5zjMvqOJiUh&a6;C$n` zaN1pTGL9niwuiTixE+EpE)^dmu_mM-`N#y(>#JActv<0aU8=wKf7y))0ZV+m6vE6J z^7Iou(?*Y&{79};ONuRG{|VmI6q)7C9LlY5uOoZc7mDEm5&M4T_VIb)CL;%fg{{1Y z)E}G=F82*X^*lvms%Szje(XXXDApb6$k-Z9+KNFti`Mak z(b&3Q2;rO3;zvrfWnc-9a&VZKLHC^?40qL(7t|pEolvI{3b-2lDUmQ$GsMFCygP{) zqQv;?-j`jzJD?UTaF<&(BxIlqt2Uy;iIPRS3CV!jiZZUfu|(4E_`0}RK6Eh55j1c* z4^EXWi%I;K4h({+#mC-TaA@TgX21;dg~H%|6_`R)PLl;mO{dRHfwU`B_-s_){G~f9 z7l)px!n9{@*Pm9t3LjRm4gx~hkA_-?j>VLY>l(Hp5B(TV2<2}ek{7Vq50!(OF1s-%?go;#h6fBPdj<$eM1C*+K!o|0hfwO=h%mwj33R(HF9RzA7dmuRLN7=yWuDnWb2IP&~*H>YZ{j zUfdMlK{N>Rt>SN+V9HF(ES`u~w7<@k+gX6B9X&RitN_;^P|b}26dp3@P;D-LfP>wD ze_cS4$V$<#y`=Hi<72T9@rpIIC@ouPL)Nti?8Kn+p|00*kV0N87%==Af6nCAK%3V& z8@g|g8t3$^kCnzJf8_Rzwc115$=4i4qTMM-jLhg1nn{CZI4nz*vpco8TWYH(`rmD; z49doRy1@(reu)~XaQ5^kJz3=;A|@^rx&n%Hc6iCbo2X~q*sdP#2-u5UZ?n`HkaoH~ zIj=vdP~%s5+0~hs3J^E^Xd%SG9sA+!qL(OYyO07OaTuueoltte7*quYjyfm=x2Hd*E zS0B+pFD>lhxB8N$H=}2x<%CB;0l>F zks5)kTaalRj+lgO>MPvjA~BMcz9jpk6$dp(d!tyGSKK@L1lPRNm&)B0%j6P4GA_ii z2ST?Mx`t*$iYMrED{*oD*_b)1-1yKdMByW7JI7xjEHACKjWZf2Dp5?xL( zX63X*#d)l*1h7M?`ZP`Tr_AmVu@&f}OHPT@G)ZpOudRa`hie}b$Uv&M=p$3;52H0m z1V63)F8wvH!^)-E+mnkd+8IHG1*RN(h-kf_(OsSgid}u=cO$?``O|_=+5A3CX?Hm| zNMP;%wP2IlAL8vK*#C0INz3kDS6(h&X{=^%6{H{71GnZ)o990WIKjn2uu04rl!eDU zjrwbGkQ{(nVb6nlGaRaAx?#L-FqF@*@*=uVd*_mJ>vbNuovs5Ih2&RE_z% z5)G4^KU7q5ylMdk-1lEbh0Cfghw$K*^SSIpiFqrh6^3RB_dSVLu4%pSOCw^^LN4X) zzhJ?0yl&gJ$I3XkC3cLp<2K~F#rGWS<9aDnJ!ij7@(l{+`$s8a&_tq5JNHkj1XR-( zKu9eM^-lfhAB#qqhnttZhB4&)&FO?37p{60gu4A@2ttFF0Q3&;#a?0v7uv=Nsc)T zZ#lbIeZev{+* z8F^Gow%iaxfe*kdRf&Kcz^S;s3L=QO^J#WSEG+!o-V*qLS*^WGWxU0$7%_pg1EhoL zzoF|qckzRc@9=v&7*o}+J=jcY3VTYbv*jc%QV*IayvvRXMuJFv|q5X*pMC` zK-8Uy-T1(f?5utXkj`SYIWRw})bw4Ux{_JQae))M+l(dA9#?~hy4uEhOk-woVo73< zFErX583WyXB%c*J^RSXiZDKeK>_i%fUs)&$DeaCDS$dBmrKR@bPu*HV{T{;s9ODbq zkwEAwfU4)@9wQ5FdhX!h3#VC!2g+_vvWyG|5%XmmwiVvgJ{Wd6pz?Q%>rKfE=o&Cg zH`s;8grr=GK`r6#tJKdK^^qEya0&}N|LNBhS)q7c(o_|ES=nWw2oYCkqA@D;5m)6( zfxWJ1DSCZDJmj6(CX?x4Dexri3Q8BvSoE{~mZHlZ-y?QjP`g-t5V_;Bud+M6v!LN) zd0ikTpN5a00bDei`#wV}aM1;6O5_yu*h&V<D81p*heSbx&W4W&Eq|7 z(g>OCU?)eOszW3=I^gPwZY@m+)wWBsC+Iv2u{)BA0bXr@1oyPJ>)b!C*p?> z6a*E@V2_Ptp~&Q2A2+0tj?SlOY20Fq+@+t2Jzu;;ghHk|W2QA*%2oipoSKDgyP#-q>vlsm-K6&m(wVaY1c1n^ zIk8#n^A;qU(z1f^tCW&#os&|4de{2>^UcS(4%;XrI2PAQb1f<7+?h8pPtLDahnbl0 z4jU;Alp;`PJnSyiBpb_?y**`w$>O#Xses12S0{{}=A~XZg1$#W>py7K zUp#^U*s1@MkM54GG-K@p5MMQ&%cV;U^^l`gy=8L>q|hoRcmFny`IPh!NbY-#r7mjeT!~&+Y_|=iVCdXZNI3-6yT`5Ezuh3``5K2OAeo zAqC0A+5}KLOw7HVa}TTrMNsi1JGJW2_g)bWtP7>w0LEcjUJY++Gn3yFY_UM4HuFs4 zIH7vQ8%yz$rf!{5&GigyfA8$dZ~@^4_ki!0A54zY{JNF@X%3iMC;BW$;q2F?eucCR zx`uP#RJL$bwwo{ghW%mjt7{N4t%MmlxnT58=@*I=;sjet`Hp(YLG)yz91qsDK5FsT zX4c^}CbFkC=g4n$m*Sr3Iq|FK{WzX?RCi!_Ys>k?bis$N!-{f6?Do#pIu>5VSUxe%UR1_R;h8wDut+60Qca!DoZL_);dd-Dsz(8Oz=fbC| zJIIr~fNb1n7%lob$pPf*)!i=68)*ByP{ew|m@95gKPD?E7d`8_Y~jBflbgz=Qv|VU z7j}#N*h9R~18Tfe!d$4oICEubj2S+giW*~m$^e(1(S@smrS4}w`|QlH=_k8lqxGFY zILFbILzx&LXCJI#BK~!ybqF=Y*5b2tbQ_7mQa3B_OSnHI;W*KmhZbZ@TFJf_%p|?t<`I(4A=2 zLuu#?Rp_N6!hY#R%@-0TC#lc|oA9__#)k07t80yHTTaGVt24`9NslW7tl)Y%ln#tl zpx5y7E5&IyT2;;UsGlaKl}F#q+U}==hOThw6a4^c} zd8XTYja?Qv=wH!h?FKA!Yz5P_@cWPaG+tT(_vlCDv*r}QAc<`i3o%Nef+ML7TkMq~ zd=GbJ$F^71L5t6NOB9c+QEe^utSqK-Y5!)IRIxo(nRfHVgS%V4h$RBzH;Bm$l3{1| zzcp+Kje(@2C_je;1Oxsn>adV7&c~Aob5*yHexIR!{(>57+5z`p0B7KH!wFE;%gvI)FzC-EPR1neukpM@uxFv$ddaK}@gwJCfOJef z_HaASCs4ohO1|32GMH5?DWbl_c_Rp&8U2M!XF@&s?ZSRHo&B!sYb+^4C6W<3`nuPQ zx9+b`wZ>)F-}--h?|SRK9HU=Cw}y8n+E-(cr3#I7ru}>gGP8In#r+JM5;Sb<_U?=h zrI9&^`(mzkAnH4+Yl?|nOCU+bAx}PJmmG-Vq{Ng+Eb7LL(2$2y!aFb@3L{Dw4$>-? zbAV3$C6zN5f8eOOHCM;*=y833oM1>noNz>bX+s^5+>XB4UrvOcG%@*ivc5=8flsp7 z*Jdv}8;U?E!2M!R1?wpjV?Uo>wskzXJS(r-B80ZhkE?(3&PiELUHtT?P3Y!9g4M5b z$XY>MU<2Pz7eu5d_E5b6cyUsKKLwi=oc`3v$^tf$9m z3o&UMFa=e3NOzE_6-tqfzehdSH3|!MM(L17<3&bZ>bae9kI4AQ%s*1XH&Y|JLR?Y# zJ7aG*ghN|oS@<~AaQyb-k4KK(;pxY;O{QeghacWO)GDIQHXQ^@6ksVjZN3WlaA2k( zq$rZ&>c1*xzArL#EhZ(4uby%_7^VV+lL&ErzJ#oS&{mNvfm_H%$3lK;M*f=DMkJT& z4mUf)k#CStNyNkS{|`)kpEJBAju&-8FJf0^R_CuH3t@Ww+0z=KeZ7uA5lxCFL7jw< zOVP_XrYG>>AbLH1C#t&%DPK{+)@Z{lhTumNal73H@WvA_zsjr!zwV&18;_ zMCZVX5`rWk;g%6F-&H5j&T514Pn5%awxPfolml@0VYauei~Xb{vK#agE9IUCgyBQ3 zrvbmDC%@$|nwj0%ki2ON`=7&u+1-s+I}k5gq^FJHhqnkQd2qoB)-q+ZGpBd?T`bGu zKYel+GerRWY&CYyL%pzQ#|D`mP0B4fyY;PFXQu!PgK~jPAQl?&{ZD-IObP84N1{56 z{rgNqFbh9gJcaXDILEi`d^vZcUqfFbT&`E4I>Rc7OadV=bQ29&?2p@p4(Kf1|LVBc z@GvcT)LVE;#qAlkzI`tEhB{;NVc!`k190F0h!Uqj{b6?O{`LLtH_w+VFk`Bj%i;9Kl*kWE)eV?WF~uHxzkFO8$w7xI!7 zrV>CaRn=N(Zk9bSUdk2lJl6Q;={-rT^6gim-zeS>(Edn}-fdTEO-S>0-WS<=4l9=k zAa36{hlSmMi4w@roK|J`T-q2xNVX`aSV|cVqXbZ&ICl2f8bzKNz4Tv9CoSz;0Gt2k z0BOA{D3er~W9NZCgT8fu0Vx(JvE62?PibP;Rf~N#q-`l4SOyvzGQc=7E)J z=&*jObDUUsR`V0kc0g(aj(&}oW}{KOmj5aexjjGsdN%%ggMa->dIMpZ$wS4ojbqg| zstWWxF@`TkyuK>Tg$Z0MJLtjCX6MKRpqcT!MoKhfnb`N;g+;o+p*;|^{9J!xU-#o0 z2?G_~-aIS}9S}ohptUYPP-l=~{Dg)g2tz__4*e2ty9Z&K$ioMi*Gcubyq3oKAEqHI zm*`-Pf<&B^<6;f{ve-hO(JB#kD6Gy87ioHy$tpoS=l!>Z>N7GGqR#NCU~6$t_3zCZ z;$)SFS+G*81z@n1#TLF|?G?O>TOn*UON)ud3DQVrBjlMvpkt_nyP{p^^B2B5XmPRT z*f#<#xjQyi6I5-+-mn_xRtU7>^07y^q;{3DWpw$$)Vo1*ohh}Ku?7B40H(ch)^=+U zB{b+fEs>|m-=OSk6hi)eB6@Eu5NwYyV3d|QxFtY^TooJyE*MRGdPoGxz_Zax6_xqQ zcoQrzHrfk__2tux9qr(d3-;4@jM=IVazac;=a zHb{nva^%Dq9KCJmBxLB%EnH!gcxoB6(G+#J4@DSCW~II?W!Xiw^66M9IN%*z#DROKOK-oeR?j+I;5Rp9t}eh$7@y!2bex8V zOE$eYQ4bNAxPnxEK+n;~^%oPuroGnqh&Af0>Pp{~VW^c!LcXFq3;n9NC%cN0=SOE( z#8|uikmV2IN?XE*_;}VHc!0e!N@>^K0@|U+q(B6?U)41v#<#E^9iV8`u;zXW8 zYN>m<7Zt+xn#yu>03OM;lQg?MvY|>0OFNB*QWMl;fXYIghuE&&(Gxd{5+V3RG8$*4 zlp&ch`7e>fH?o=~;5C}+({fv_q$g`~f+lz&M$sDvxyvM?{R{1!k- z4IX4LEpvr~0!@w>e(14n>2wfShF+i>43;58tsl|OmMY;}cU`SMEEGIqjc zn%?QIZ7X{_@m~z|HDVsUOt+qgd{q-shKvx^fXr*6|LTdMm zPJV7SIE5}tcI=d}47=`StkbcPaRfVb$MBA^s=m;-OzOXo&n(mqP0f4OM|2d+s!EKF37fBNv2Eq%GK>qKFQh|0!h!9O)%0PspV1Dy3&mA#Fbk(c#% znYlU!e!Xhm5F#^pA3Ih{jVi-veX5Rq35Jn! z1Adj7?*qo?KrztBF+@#tW+^v!JYnV)4Pv&8dw|^i5Wh7I_p&_!T$!y4Q`hIaG4Ry4 z3tP+iWB#!DB8l*Pz_R0$pHG;1j+vCbMCT)O!Cw0zDp87du-*M_YlEXOph`^*`^E_P zIfWuO=1S47AcxX*lomY!OoqOd0!eCC|Uy- z->-juMP*!=pE=p}4m3rz<{}iu@3t7VsMwc$ffrKao_?hg|5*P;i;$@g^Q!t|pL4R3 zoII}qq;G|ab=gAYfsic@qxXECgYrEIKreka-^5m9^E_QE=m>98AxniJ==hNVfZ~6m zcHpHn{sg~r<2GiOyd~8joZ;Vq`kz$-*spJPON==MPZ%wARvBxVNUJYxlig^*plkyS zQEtIuGbdp*;B%?IZ@zS;>C{N8A;XXv$(!%-bTd+CdIaK;jUn)N<3o2T}f%st6cns7?$^+bLL)g`}X) zgmR=dx3b-+0`T(HGCf7`pSkz@pETXw|ZdBSkp;>d_1~ z7ql#n)xz)ZBVt2ke67LCPvc z(ndCm{6n`tqD3}>mIPE=YhDm!G|^|=i58mEGh_5It;+_K`m*Wk_%CLdLC*jT!Zr%H zNtvmR@DW{fKNs!;VbAe~)j5zj9(!2bcaMDY^uaF6Pp4V~f3?1M`HjGk4ah{5UDV0# z)9LA(SclCAYD!+jkymlS{ndm+14#7o@H?&?&~~^hBl1ZchF#VGk)meR1=_nxnXYCO z<F$!8s!6dxRBUtnB zSUl$8mD?r7!HH+m##(Ys*HJu!veg#gAVX*@f=z^8zD@7nt}ke~`9~ic3?KxIw7Py; zpLbAhH(!zx_E zVT}N(M6x~ycz7BTL`x+J^P|?>NP<+%-rR1CCI#GT)|eiUh)N;5q?m=fq>BBj=ufb^ zK^m60tNom=EAmJ~3{&vg4Ph8{8)M~3!eigqD?-!*<-}#bvQ&~>j~g_Gy|LiJ9tv$T zVXRV|UsIF2DvA_$yQXG|)#OpwmTx#$w>Q}EFJvv(8o+2?5~oRw97bX5 z_6zK7eziQ&1KrfMcJ}`Vq5-w#c%V*6M3?K@u8L7chuR8^)%=PiWOiJ+@=C=0sPX!o zcJ(MxO)J!uaPEWaoyF8)e1aXlym8f&Erp600GfktdSv${)PE=izW^{J=~s*ccXcri zT)Wl3&U&lVH`U4C@zip;NY4Nxpud9m)*tnry}-#F3VUXxMDQ<&ELQ<_1v7jX~M^8xySQCzuCD;Uk8rT46kCmtGA@pGf zqqx4u`-S6MxM;Gwz@No<*rf}*0D{!Idkq71jn@P}L%R;4OhHdwXX{<&Om?ocL;aJe zLRNbi+ixq5Ktn4PZ46_;YA(1rF+eyU z1kjt(uuTr-9jr4ZRQD8fLqDqa(VP)6H?=zbyjJ(csyWgar_2Tf>KZy1Uo?ukDlDma z9<*~vgEjvk$H(5WA{E7hL--ppP#*3dyVXeKzsWLF=7e2ldvi6K_awdsCY^ZPDT`To zi2#eqhi$Li$cQmE+@oC;Xp&Op>D$LBhoC4aJ9A-1yLlnWP31OC}l`X zU<+TDZC_7nL}ZLTqF^?@XU@%n@?w<1A?b)f#z$E&n$40O6-0GveAVb0o})#1o4#EC z3D$JHQ^puOfU?P6uX@n4aP_X?5#6E^Ma1MJhS2($BLC^#t?-*CogdtBUzo-F7x(24 zUIPA5H~;>2Du0*-|4=vm{`&3RrSU(HfHrc@808r}acQ6#EXO_`o#>ztP1adZq8!O@ z?m!XRCF@C-9*Y|`hEb@8lRU0<5UY}9<%yJGC|R$&=n#(dJU|pE7DDcn##&KK%~g39 z$FkH7cOv{Ei#L)i@};6fRaQK~S~Gth?a+aNOg)92=$oKZ^r%~c+4}p?XrNkIH5r-2 z`E3JqO3;>3zNQ5kYmdnpzKhZS?ewL3G;$0T)s%4iO4Kr^Te@85^u5?*TuwuYtR7Wq zMGRGLuX@2BK_xOs4xqysJnf|OiRHZ6sLd-NFb7{o`;bjGCDy?_6 zEKzQ;Q0@5VukkcytFU{-Hr3>0q4d4Q`ZDZeFq=uT8l!P_6^eIulT4i^zuzo;F7w4A zC>7X~UB(ef!WQ_ZW)Yfc|{v0cb?Z9;2lVccwKGCceSnPDr^G|sij%t+g z`0L#Bt0IW~Gg_7^D<8Q)bq$t?(AP-gehTQ!$y@HW}Y*#^0Vo%)NTd(y^luz0S zt>*!hI#yn4`R`5;L>yHN#0cJoi)kr|Rem%To$!x~z-1K9myrVcPZLQO#O`pANt>(nRFR*vx)t?}&NjQ2NwdY(6d< z^cviYN#5EYd0CNw#e#}J4gaKgTB`$h;Dzi5czeGIBFF@jq>8V$!IL#b=n=Opy$_fk zTBEcgZga6r52)RJk&0k%$z{waAhr}B+>t=+^P(CX-iYy-g>{7Ds! zhMrcTW&0vG4v@k%fS$1h>d7bQaBhYj@+=9%fh}u=oZA ziGEWpCO7|at*>8S=gvbFdu`nLAxA0c6gSLAD{U6Cx;WqF75tMoN_{Vy=xLj@GVz~! zBt`MUd_|gr@!S6p0-DQ6MR+d|ojS~rS)FQ74p$&xiF_!W&O-&_7Ua0jEfJil#WtY* z($u0UJRe|i8*G*9muVDHV&-3D?5}liiNWNFahi{aS#$D;-M96w{lNmtzt(SQxKSad zp#!nw^CQPYHKP!8`usZL&KOFLlC?e|`*UBzF;W#H8v=N)qdS}r!Ep*Y+)2|#QNHqs z$_r=m8X4!o{89~wl|W%m%pvc2iAs>vz62f9@gugrjR`++FInJUpKt=S-)HNRM3!$J zt6`2;7thujDsL)ck3?5WuPXj+p|~n%^LqjR9!R^|0UbQk?$p{c?-G!jh&;B%YLlz0 zrePfY_)h2S_U)EUe|sj{o3F}z4M-r)&$nJ;*}^m^DHOK?(nz#cWY4#qJDKl9JGa1} zhwW1*ZmjD-Ma@SMCwA3jfiV$17@LK``wPucbr9vj%RIB#ZmdR%w92zxS;_5 z5M#5UL~nw-a|qVn(1u!Dd0#}({F*VTFBK%CEJ)Ck{54{$`hjb%%N{E&5h{`3*5 zo!^L+T$_Hj6&8+CZx^sSBVOJ8h$^)Fb-ZM#xpQf{qDn*TGn-$~EYFg|kl9f~w|D#I zx~xE~a5R#vk^1ahAhRF%pzZbN_TqZ}^F-Ta4TOk%?kM4HXNJV0m+yVpBFD;U4*%W! z0$BL=?O0H{sCns-#cJu_bnLz#D-$6GJ}7B{x!jUqi0}b?1hMye+d$2y62>heelU%a+ z{BD%dp3A;yw<1aF8G#2s{g#xQO>Olv(rF1T zGYzYSJUL3x_T8YkCG6G|*I&elF$ULKNZVS8)f!~%3(0xO{UhtC99Tf$e4;D;h7Hk8 zHoJ}EkNyRP^}PPl>Aja9SIV9Z#-rN{Opgp)V?~rvJQfD%PdP`4+adbdullVlxb1~* z38fTFZs^u~q9>Q_L^Yh*sr?9$zLU1qY7MT#&?WtzJkey2-Ca7GVOBg>rT&*-@(7z! zliGPN$XmkBb=$}^PK}9>fxnPvxMn4}8@Uv;W)_^0MU&cOxXiTW(6raZf|tyd;|i=Y zIhtz${PN5j32_g;dg?S!dOiB*ERwML0pH1o2=`$E+JCbv<;$sQt)*WDY%q0&WcoKz z^xsD9Uq9LR4JfST?2p9zmqR~C_d!Jm?S-?BNHh$5Xjb=KW^A` z)4d`%9P!adPX43n@9s*@iq9B=m+wOWs|*%$CE~O+amAcW{(VdzeHs$v?E;?Q-rRGW z<5srwG?uIm6Deg*E$Gb^2#em*tV=3s4eOakNB9J_qkpSvi^LI5nM44G##;p65;=R6CY#m#e!&pHj zz@A?TmEixDabzt49tWGADcOo^0ZTPyVU(Y0C<6vlO@mTN=@+8?NlYrGGO>^|umH(F z$ew(g>@7bYE(P_z_A`QR-9R~z6X|CD{cbM-_{d+5I>l*ChYe>>1w&m*s*P;H4@ zsiwN&BLY<8)`s9Mg`I4s#)KwiT1mV|hpAH55}wfE+lCJdp*oaqG*03<6$VJJk4Ih> z_+tL1Hm@J38Q+fi$+1utqX6h;>Ku@*ZaJ{rIz>yU+_9%Z*MTFQ`07%ns<8;C?0}HL z|37eg6lWc<^@10)ZO@zPD}d^PYoeb#^k2tHktKMk=~r9q0dDBm4t4laC;{Iwtg-H3I3&7F?K*$4x|8#k=s!$6Pqgpk2P z!6M7p!@C?%Mh8wKc3;#E&CeY~eqpAceQ=+F%4{OEc<}ggN62Y8N9s1NGzOO7~Q&R|>g6n>HsW zunj*?sI=%Z)`r6Xh)w;%L4nWBi%nO3Yx;HjAb||It2beYgf+7i(59$A-1*OzU=!aW zxOLlcIz1<(*ZHazV#pXo|2_N5Rx*4xv{`*Ii`!_FqSZZcw2Nxp8HDH3;0#GP!0EtgY0TC;ZsYWqT{O^Fk`bU?$ zWjp4QI0Skwl$zQ0*H3a4UbVPgsJHCbX3a`(rz+(x*sK}bbWR(>Kb=}i=|Xm||1E>0 zR+G-ae)ihb&#G4QZ3lB_&ZUPYhr>d%=|<4E4_at z7E>hc2Zp%Jjy~a3;(v?Y246 z>_y+bsZ##0D0R&LAnPrlqKvw>;hAA*1VlQdr8}j&ySuwnX_%qAJ0&DVL`p$A6i^V9 z1`!aDR&s`z@5bl(-|u_Z&tlD*nSEV*@3ZS>SZB^{goz*>j$0|Wm^m%8E1npAXhcVC z`u@j$Hy7Pb$g5QI5<2E&CkMOldxZW9{DU6_<}2s+k~Pg3kDwjItR^Q9KTfw2MTC(w zUztloI^CF3C&?%>|D;E_gbW#qO)QPrJha1ow>4tGxkHF-y|sf#Xauq?+k6~VCHWWy zE_)x8L~;2``lO$44gLuF0uBEW9BYg{|NriLM>irnw|oR~hq}GTTt(zz56(ST*Wr*U z-K8D1ab34ZY!8vr>Sg53;QR$86o{7 z;Iu4*{!!*z26TRtQHD6LTz;j08imeS1em+IST9z_|C8oyCSFqKl4xK9-E)7%-W zRIsrN5&Tef*$R#;ZMXeurx%%gFaS2K+nsN$PGP;>c}I-jB>Q6hZ3SDHYuicTqWE3r z!VSYNbOlQ8dtuu(dBa+O>+=blx4B>)d8Q-830hjB z;OL|!f3hWRMIxJzPj{WqG;pb57ZI|QxcjFe-n-wl#KZ3s2Nj*thdwL&Lr+hCX`Sn5 zXY9{}8m#w$iAO!=g;Q?%7Q4UEn+rwyhbUY1_bL!{u$Wiw} z3U$O(`xI@PfR=EBP>i-opZ<)m-^LYA|Jh(FT3}5|yNk@3sVK#vNYv^*eL{aQLM57l2uEt92y!&W}Z&Yq}vfsjZRj*!GvY=&Yw}m|V z&KG0yXjk#T#J;f`bLgy_<*wgR1fAuvhtEuvCsXjz)Ku<)R?!~1+CwaK?U0B5tcDY~ zxnjM|Q#%r3bIXi@%z~}meTlPM99LJ^uglFhOPA|rup_7)WlyGl{M(-nUxI5?FiP$B zb)&T^-x?IoJy}HCLGdmfdL?mj`Mq$ya#rP8eQxK@pG{796NY8u#ALW$SCaT5)a+Z| z*xaiT_>e)k<#}Mvi56+>W{`OTbW2S!i;u+lvo+G04VT#GYwI*v@yASgBpzB}n6hLd zZSL>!X|fK%iKmpcrB(ssp$m&OLZ1kjraY1orxN59V*dQ(Ry-`5!t7jaM|)zY<4}w{+i5&-zGm4k^q8LD2f-LoPn-=~-aJs_GZ%j#)jU8~d7Ju& z5DiP%i;yZrL&EL59)0(th#{d56@3^1FP)#~eK$elS|?O{FGZZ+A7Sgk6Yo`>f711d z8gJ^r{jmmQ7DxQav8&Pw7GnNaSW)U8E5U{?M=F#PZJs+DxW#7f`a3iio}AC&9e;o2 z;t(-gj!HUh`b-W732``Oi))=93tCa9c=q=53xcVILw19(q@ah~=x;X}$wy~`Mm&av2X;Gu z-_69kozEpLk{RbiN|{(BQ>9>eALB#re`4b6U9 z@YB#WH3~1tVE8@lXNQ!`B^tpVj^W)T{12T>Rs#n+r8Xlue(#sr+Z*kIf6Z)=#H`!m zbattm`Eh)U&p0{$!=X4?yJYU*x)f+EY3r80&il4=?a4Hzx^EYqQR%T5&GX)O(LW}! z3ijqdsE(G2as?g#ZbC+Rl&*(o@K00^H}~b4K%E-TKBh0gN3@RqE=PCVxda*}DRjlv z#44oDi|Qhy3h!(JmtN+rF)Q6Ns?V0}8P!0nO#`>lM1MZsJ^@wj26;L>-?fFlNH9_? z?)b*_HR#SEx;f&T&M@=-rb%s+FE$pYxWOy-k`6lBi-Yy;-zvPu#9~g3q?!C!KB2`| z@5--+lFGRx^qVGzy)6zyGn0eiv%ZysGcgnzVOsg$%~l+sF{oJhson>8a&A4N0ZK z`5Y{+J>LE4J1O2zYU0Ve9?pfh4sdr+5w;aMl<0+~V*FB#FJVt8AGN0AgI?DH2@ejl zTVu!U#v7b?T#+CAM0Q$;-+3Qxx1(w-?0d3l2s&oxix2*k@fx^1h(e)-v8VZAFX@;X zeT_W!F<6Dt`BgWQXut7#T@&Eny?JGkfn)7#I86R1dUHteC?%x#Zpdgz#@S`HU2kv2 zaLJ4ATxR}ENdU!ozmxn!rq-l};5^9bj*-)5B)LR^y{BG24*O4zkyUrY!G_ETysL0b zj#3qdF25#7P%{ywWT4gVvWAuqy992|tOvE!Pk%jE=pI~u^2U2w$EFSsO>OfE3xq4r zk5Sn!+tSnab$vFx`)hfbV@Y=^iB%3_`du=PSawx8p4xmsf2>3J^baEw;i61X(=Jqw zH23ZsI3!f=@f-ek(KG=s{c?|TnhR|*NPDI&f6=B~zKSM5V@15?C(r!U%7oJyv|;P; zgk=B6#$dz5Y6=ggN!q)Hf@8t*7!Qky!+oK=jcGU;4s#TK-^1Mln*4}w8eFuyPigy9 zd(e7U=;Ce9)_ZC)cyD^22DsoKXxt^->a^wL7|(wrpkS()PkDO7V=*H?T5fhu5F+GpwL6iaU%1wW}fYif!Z8IeszG@FiAxHibAz3Fp++*LzlNv(0ZT`2sMtGon?NYyX( zJ-sjWG8NQ)82hvJfn3y~jF8cB{s6frMIeK~H!zMAA+f1!xJNxA1x1USRc_-@P;9SqZ3V8P7pC{Tmqi8?f7AV$g z;&l^CzY2xdXrxeMP^OJZdZrU0=7{$@DR-}l1j@UK+{YE3;!SlD(*L%Bui^{E7Ovaz za|M39tFI_iuv;Psfgi1$*lB*GE_8mB+m6>NALkfmY@%P4>R%$7z5mXdVLUZvcP>P^ zZ+ynrgdjsYn8)gonfh;|owZXRipaJUH_G&L7cgvUnro4flPNDS@<`*$hHOrQ*tp*O zfXiE39;3u!Nz4v7&o6(J!?vwE(LC3|=;e`WK+!EPO_kx)9aj-Z?B!_;X6-UFjOV*` zNI|#k))UTPtSYG`v22s&W8&{Z4w#T_AMN#@Y`w|A_dcp6jYzVOqdqIOo4H+2dhl7% zE>GN1m6{)bSTN`9>o;PyHvo}1|5~KbW z^IP!2WrSt))47Vdh}Y7gG7WH^aqeLU8eDCuPTJz=LFFDdeI!ld^S%KopH~Jo-y%`? zTm`Gdmh)d#V(!YuK&@~N_9=3P0|BZ(lzX9X75}3DGYFMT%fcuCP)5DjPXplk$(65v!9iu&}CA!UzOaKv!{5%twWVsB6*`bhUMj}2gwP_esT53PYm;^8I|>2%OoudJ8B9( zw|XfZ#kcDPrkpD^+<|p7+^ksCg{+#~+Dp#@9dQ#|*{SLR)Gld1INhCov3&`*$9(*? zFeGF}U$WGMutOh%Oi(4O!;P+jV{~Cf_Z?js-C_4?k#!RtVUS_)pj+8IrU2+G_12;$ za37dQ&2kS;F|X?QNkf7MHXd;hZID_&#@A>bwnCbpHB2W84lS(v6xznQqRB0H2P3~0 z*LijrZ?nyIItYM+-qm1~r%TA6e`J}Hj98ZK^pMAcE3^!&mIRD{`j}E9%|AD!x>i)E z{Z3ayTSS$28bZF(%;ZAv<-MpUiIbv|)We*6jxv>nNlvE-LurO|`&D88m`6FizOTuKpMjwC2nEEVnqtTl- ze{uCi`EPW77@m5z8nn)}krP*A zG!Bw^9K5+0>?)5pyT@^uatdS6F{m|Mi`#=v{Bum>vztZxx(KyhAH7>J_ zORfCv0!~e--_*(+T*b8B!F`3>i_q9mG!xhA^?4ckIcVcN;DE4;%h+3ra1jco18un} zu2o7rtW$!%Q;g=$rm)H>dX=}Arv51!4+ks8gXIGAeuwo2!w+DG^{Bm<`RUU8z3zc7 zAxHlG-6q4LFFVy&Hk2guLmCYNb66QhYd#Z;UypRy?%uvG`%>|_DuNbz!;MTxQYxoHMWO;06z1wJ6Jl&Qn4(ktIDBLAWOZJ9Nn1BD zz1Y=#`-{8o`(n0!@0(hu@=wwPB;izd)?D$|lotBrcCQ&0!pWxUC*{Up%ub>B8xtr z(=tb)o%^&etkRH!_bSEk%ZjnVwCoc?C|)*H0=Iq8B~qdNvGCt)^2hcACS9Lv=8Sh6 z8;)&dG#Qiz2C=jEpB%trbRy63TsDXCA4~=45j?>cdF&PTYw{0{S^5ffr*pz$c1u-5 zXqdKN+sDY}R?V?xiJ|NibU)FXtmDf+CR9J~?pElH*4gZ(o=r;c<{cKw9lGr3)E(x# zbjyA^i%Q@3ECE!A*|yI8MCOnc+%yajW`b5>&1H!U7|Ab3Yi~pPmqa zV7OK`c-XVpPqj<+)N~9OPjh~`C6hnDHQb^}vaun$%bz&a4$SGIU)q-0Nbs|{V8F>M z&ZaNVn6}H!+J6SxQ7i3Z{2bCAWM`1(Br0E2EKP4r>igcrn@-{GQ*l4uU6RFjoI-sn zd%UCzd%E8Nm4$5|u339@Rb91)-nQCK@6+Ye=W}9Ix8I`d&lEIKj}+eP`mx>8`49{B zWeX(;ca8-3B~moKXW@TsqI(LRA+VT#38I{ zBhq>cx`q9x?4eh^N`q<=udG}HH*L~~^mop0kpk3v9xQLwHif@kAvz`Wv0*D6pj3)B zze0}CLNb;7jm|{mV?O50*>UXWhfd`RVjd5&VIf`FGY>J%`{LaPx3YK?#9C^x=g9Q( zrJq=6S14g*Ghx@(ZnX+!*iqO|iVtgQsv52AlliNDsDFw1(^qbJevY_h6trl%E2dn} z^2LZKvQo%)i1a0i&6s!hHNO$l=hfzgFKhB*uRH@AXb9O2xKEWy^}S}^XoxZTif**r z^^t!C-Qqm`x^5D~8aqFXKCdTkDy0=&!&-hTr4w0SJoXpFtshP2O{^Hf7mhPCtF8pqggN!webLp2zkC~t#j#Rs3`fHko=*8@k)`ETe1Ffd6^xEJ z*X*4~C+vuya8z<)%{!3CUnWX8|18304UwFWqW#M7o=t_&8oZZdlUF3d9y?2NNqT7R zpFObD;&(yb<`VqwxnNtF0mBDJKixf5oTVX$0LCKgcU?FKEO4PDq7lR^!U~Y<^kVd1 z_xVG){ApTn^g6ulMbY0no9A~5j(WL)$FX_3>*kD%JtrR*TzeB)bImgyi>qF`DR)wE z)SJprsTjCmuy(7O!_m5GBtAA9CtlEC`0aAYp4p!@x+Z#i*7zj51}3A~=sQIVPd;%V zs=VvS_;EQ8*facKVVV`?#rHLqzyoluFd3Ba!R9 z+?ZJ7Zvy^j7c5Z;N$=Ykt>uy)?|17S&GDXr@(^E%{9!U$lOVlb9_+p zm|EX?Of9AhMwa(TR)YJJulQJiq+L<;qMP1K&b18I+I#(|9rkP3s|kE-dlc)Pidue9qI zqg$mJTHOQK#h|?>Gx4Ajd7ffUZ+#Zk<=_RfB`2ltaCMPIW1@eEeG-npaV4%~r}$h+S!!O2TBXLr zO)1~V{y2W`W8qt{nbN3~*;mw$S$IY@@+wSGVlP#E=SKM^^2T#J@NMAe;i)dxHIYW& zF0*h=CS9NX{^cRxppMV}XN8VkP45cGRQHmePfe`xu#?4E7$)@xsua1DbMM|Pziaw zDgJ(lFQ&-1>Dld)Q$bW_w{Ms+QwQCOFnoG?by;XCJM!D@uZV7!H7IVqF5UPOu5Wpn2ejjS-@7Epz{Oq|Q!7&#V`;F>SiY=juImK6bT_-$hIbJ?>?yzzK6ogz zRk#XT8G&H7>)6-bJkK9&C3Tv-wPCBhI4wguQT~X8)fS~i`j6?xG6#bLlx;>=sUX-Om*;wtmgDQ}y-tqn<|Wgq1%~cUjg5tj&Bm@8A_x`;Bjiv6F{%XO$rs5v_$#?G4`QMF{lhF#J;s4k*4M~w|$g$J~} zUkWJXD&isjntG`Im)4A`{2l&VLn}R>HLk~dt{J7Ptq$86f6De{uU&aNeudvi&j>`y(o`Ivhd9sJ^S|~&Cdmf z{r*_`cjALbO(mE6oQ83#31wT6AO@~e-)Al9ho8p`&WeKUTZ&aCWi;)dRv>xjzW=r% z*>!3@BT)Pj#>~Ob-#<*^VyIRx&NUYja4-~HXVIw8vVcLgLcL^Ji2fkeAov?KL_@CT z!(U=Q9}UjQ^!>m;vs%R0$XnAr8JhW{If0Z|2_)f~hWSgKCIo`BzpX)v4_DWo{wMT-h+n1IxhkT>gN>MH{th*V%7f z2Q~Zb#sjkITE=KZ8QK`c3?`nu7XCe~% z##Q-6nVen;ak(5F&Lf{Bovc{lx>V7=vE#P6M6(&K_ab|dRa%sz)n<#~nMborg9MA@ zHEwOVaS@@gUaZ48qZL<{)Ynn&|C}4{5WtuIn>qGI{R;V;vrap1IrTfUOHL78K?rY} zH9?hRJ;57BQ z>y^)w;pb54p9Up`zvWj_i7l&N)nZtb%w)TW7tK^##EUt1wxtl6y*1`hb31$SI zP-RNM->+TM-vtb8=P&yT?09%H5Z_=OJ^yQtU5{wm<6}+SlfI_nHF>?pOSg{! zmc*?hHBF`u85CjHn5?6WwI(x)ly6CXi61-93 zG~RpZXA~W$xjw4GGR^(?h_?%C`RZ}Gsvc-_DWxCDl2PT{(@QoLglTnT#e#&iGPsjS`*WCC> z;viftqAf1J(tX=fvAe5&t|wLD!W`v&qc>k13K#OSDjm71mpQjG>PI!beKE#LTYN1N zx3Zl6eRVB)yAG>=MFp=T_~V;r#_oPf&TOeKpLIO0oZ4Ti&cW5Vit4q|S{+*JoHsAA zv&Jy}nbWCzF@7F3K*!lyCh64VqU~M3c3G{OXeOel@Q5)B#O9S$i9`Hm-AKkAtE4K9 zhPEng6h4ltUhj7nD|dF%o3@rN?!YPZ2*+C5sQTua9s-R2NT}>k0I7C6@p|L2*0gek zLof~vE&dnp=0D9$pD700N6s9Uy~m2Etjltn0(jZ}Kyf~p)byqhYYaS#ztKv&yXNm= z_}DQ`b16UOKy5Z~zH=pRbW|{7PIO)WC`!w7ps9(wiZ@(-TeGJb^`!jq07b=#Am=9i z22^IH?a*5F;Pzy#cZfTlfK3W7-LwoHCADUFv-m^m>K%JGR$nG>boL#lM96#lP3$`P ziQFoSw&a8t-~ zWN%r-c}i=GN8(c`+PGWeC;zxK=+-UJh4!=XD;|0;-p%Vykq)o?JcYFcJl9I8&{c#1 z?&1gNdJ6A@ruDn=X8vXu`R|kzANIb?E=4xCy?Ng=X&kf*`7 zFY%d^a7F14L$j=21CHQW_0f9zi)R8!4e#o3W+#y=_K~3<9Di65tcv5l#C)g~l(p5! zecMqrbS&W-iDRiU*?u%mrOu#E1ZG_^~r>Z$?B^>GpR@PZ%JbpCEr)Pg06$`O@Hvgj1Zhe6NN_KL|%$a zl38Cym~R}rXAy@`sK-hy54_Xr*n9oPVcvHr?{Lu62jg2&1sL&}>qfdWl&JCaikIQ~ zn$+EMc|{_8MoXK)uk=&k8Ieh(^>=o(8_-awO1?xiogl}zdCf!BIp9dsQO}538V+Fr zE*8Or(H6r`uZ@r+Y7GN~pTOEbog$UP5YYcb59 zH(h^-`%QIom($w1*Gxe2x`Ha(ZWs%}q|z$c+cYpuRt=^jN^6q$7w<9ip0()(&uFqr zq)Jn@68<_`p@&m9@dV4*_y*eN#n+~hx-nC6upuSeOy6oD-)B6+tfjAa!i?QAAM?n; zd2<^uKlRr&hv42GJ~=r&tlxjG(9=zUqgwTXGwkcvM{Vv*WWZMr4fH`7gyA7Mg@w9d z>#x7Uf5f@ddd`jNyfgFvr60N!;{5a%8%;Q4CZyL+1p0n;)`;^e-cuMW0Az zSz4%sBCo3CQ{WB|%6X?ua*B_vf0icm*Hp2-4<~5+eK5By>0jKF7wuSMN3q+)Z?#*X z(@?&()^})uKL?u#aCy3$OI9rEPy3+g8{>z&r6ksuxt_KZ8cK{wj}aoO8<&rQ;<8`1 zt3=g~or?anu%msu`>x21FkGm1uf$zAaAqL9VktXQe0T^IlSmvRKK^h`B1wPgeO24i z^6R*ozm(7&8tQ0CddiE?FBMR}b*^}f@oAA`Mtn@nkRQPeeu1e0r{{Bqv~YXFj6kYJ zPn|tnRz`lN*>A0_U)Xe@vp(C?koVS60toFoS3!G5&(KqdV zW_^DX$na8M{>zm~$c`9g-zRs zll5jQ>rqKh?!z#8(-v7ikdy06`oLzinnk>vqftBjC9l{FJFJ!8M$$;dEw7`IM4I3M z@u@nDog93B>Lh6UuH%cSVgB9sPkf#lSUf*F0si+L1@2Z`@sw2)imj%dYqDO+jOS=e zv0ISmP5f{qOU~G-`(rjn?{{TueH7hW4N-J@(k^F*0_9;#?#t#9WFH-y2ejME&M$uRN${oNl?`mce-9H3HzR-7%5GSoNV67P6ZY2sF z3GM)U<7zADZN??K?`t~hM~54@4~VkG8fOFBkh7WU+fv+L%O3dh8<70IW@d>isfuAF zBt^+kJgk(I-QVs(<4qH>>@9K?DfXK4bCT<9xJq{;@!S<2&Zs|Ck^AKTKG(Z=Ch%8; z??cKz#VFkAht=!xGtQUM;CEa0ji2ofP0ThDKWBl*2T;1W%xBIY<^`)MaSnXm;c=`u zB%b)xZYLJ9AKiqR?+%0(=!{6+3?2`S>mIz~iV5(hdE)U-cSpqPL*}7~Lg!q-wLlNa zD?#fLlzbG|3^~cp9m$SvF_{pkflUaKCiBynyCDs`A8zO4tzd0xC!R+zxuz|q-MJyA zo=>(_P-BBowZ}Q)X=_R#^~d?;R3>SH-fv349A3Rzk7@AGIG9NOG4afhJmrf{Ii(1e z{>SC76O_+bI*7XKBE+i+bup{+eubH5EyAj=@a_I&;OwXHr*sPh#iN}@Dj7na%iASd zE%cnJ4Z&F3J~TflOSO7fehDW4_Vnyo-G%6&jHfYpVJvOo{Xf!LKQAt5TmLLxF@Ncl zo~nTHQ*0SoGFVUb5iNRNt4{|Vr`FW@Q1lD*8BXNla@`gLSsebib520(c>iy|fRl7| zI>s>B0h9MJ?d60J)I~2C1BK>$M1|LA-p@HrKg}FbCBpXPE&kxn+O9-R1v&bI!k|1G zCT*pxE21g}Nulx6V!@U2bjlfbOl!Omg1QyO2y>BD$q(7$%&Z#;1CZ*1A55G)-)hp|BW*i*g@E-N@0^J>Rn-c6jsGn$OCR3HOBO@Nzw@ zmF1R7y`IkPj{6yT(|+wk8gYta8{WawbqF2U4yq=z;&eE%D$iJ&aVp=g>23^){_azR zSgWKv+2DV_ExHq-COI zzwovyeal?*^-4$jtQBfZux%)5FITAWM9i%&tI%W7I`d1p^19wSm-4ez`i`M3ZgGmy-KAT zV5~F4@p5L+Bi*9)TM>MKPqwGpudg1RHpM5f;`jCZ!v6))4k9qXiPa?xTn|J66 zYn!L%r{-S7o-I;bj)h-8S_x(ae{)q!jlpO5s5?$LI?iwTCWJ@pNDgx0P-cKi0rLyDkc=47jJc`T!nR-Y^lbfpW zxOcpn`$U^@P3Q0HF{09qj?$db$c?F@dnjK5&9;hjL{dZC+L;XJSK@wAgv38S*0fUL z>V>h$i#k@ksYf*HoMAb9@?+BA8+Fw`_dYtx%_}l~iYOGPrWu<@f3hR8qk#LHi%q0` zbZpWO%J`lnpp?N>o&21rcZFg9WSkxLRJn=yH@)ho^<>C?o^8pN&i-4oJmJAl_G&E_hAwWE zon-8WI0Xt1v%fOY7$ucApv^68&yF0yg1KE`-=8VL{|XO$Kcg-e;vXdp6jsD0+J4UV zDQ~Jp^REa!w?gVU?bHw^qiG0=YTK{j=6$PtX@S`4N?J$l088EEas=7HE@5-m4ZTj1 zCKUl>?tn-k2Iu@S`6LZN*MAzWh8ICY( zPHgyq57S2%e{fTsc7ch34!7Yw7Yp4#BGNN;s7Um6i+=DT-${I$$1dq&cDF;4jd(FC zHC&^9I2i-7t&3kpZ7lgJ=9pEAuaD=9W4X+Dk85sq5f^nM+RP#ck2r? zyG<7Yk-KJZC=B=hE^9}jOh(vYJppJIxlKW&7`BTEOohufz%kH*4x80OwBYKU2U-qo za+lDk?$J8hS!^w?3o|<@JK2XWhtbT<%IDY&1yubJOZ1V%>ne$#d3r>>F8T3io^NkLu9Iwp@vv~?Ibte%L-gQxtuG-$w8~-UV;`JX=(Y#tRdHf zaJcX)FOy!&bX zvWzC#JNK8vQMG2>pJ=L8J7e6>uwmYj7JX5)1$0fk0^2rKKbdJFzV9yxmu15GfLp0; z4Ze`*n_V=1IkwG$ls6bBi=@!TFn@N&f)$zk8nx&eAixg-X|jQUpEM9wVRodiosFi2 zRlXUSxs|IjhGk`;X=CRdnq61|!bFwFx|!)|s^_cW zY3P~SIR=G3%Snjr>x%~Aq52{VbHYMBo$XC^H1gFj)ircY9V2s4`5<&ul8=p^TD~fl zy0(d}dt_cEDjS4_s?2!q?O>{-p0A3orfcCIiOK;%tD-D5Rr6FZ)O0MoBh%_jK^XOU zaDN+JwLBH5s)lJ$W+n)V%J9-w$x}vGH*$N)Us9%p?#b(?vU12?`umkbsH>VWX;20^N*tG*y*Tm9Ujn zwe+o=eBv`vaez@D6Aic$x{7V#^uZ+@iF0+bTq@-!tTTw{x%`NN>9R=!$v{id64^_8} znZJPp@SAibbX;HFq9zKk;Hs1&2X_7ug#_J3-$7CFZd&r~a%l3}IX5wPpxZPg&Uv!D zN;nDx$}yHpmPJ==Mj(;5F?Wz3W(r-hXo}7EF8~ixkytbOvPNkjP>5QJESkYG@;c@Y z?e=EFEKU|fPD$IuNL9XG7TtUuiM$330gMzR)>*i$ia)5(S}sKf;&FTvdxwTZ{`HNK z!BKR~ANaQU<71VtTCEH?;Q|JD2e@;Sg2ZT%mvtJA(M^>B2VC5H2rTm~04@WSHLlye zf+L}b;{i{(Y8kNno9O?Lu9J}%-?U`(^FozVq#^Qg*U^9?7!thi2$M#W^_jhjM?$ue z6sn}bN~1AI(EYNnlaLs{%%oLf0|PX}k&yFr=_o0% z!DI>&yz2#%!jgqAog>fJ66Ii0n5I2PS64?prcqMpO5XYLCih6gjky21m4HM)^Ourx zFi4WbmNJe5vVVJb2lxd+3~NP6LZpkYQjy?(+Zk)-VEwBtQ&nORCl% zBQ6)cq$DK`H{y}t`!w7u^plj-(~gtCkW@1E@+w3DHF0-#3h4aPV*--^>o2Dv(N6*- zB;>nekm%j=5)v`z(Mae;s$}#T42eFaB_W}`lmM(4i0W-TuwpL>2_vIe31UU~$F0BT zfPW}ZkjL|`rH!Tc5lV0gaPVmiGT|E9Wo6;D8FLNY^s=xXjJ<{o+7H67(a&NnbmWH< z?<*IG_-z~#ebZP%LQf|~99^aE4-yHKFIKayl(>wRzLre1I9Q?#$k=tl9Tah}e*|O> zdULdYfQY?=APx{fHUHUfl&MMjk8?M%Nc0IMadAzJXmJdgs`L9g1ezgVK1m!b(-#B8 zwbJY;1>K2 zdJFV{d-79oE&|Ya?-;a8>Z#FM%6~Z5K+XRNgFOYS-E*V|frbP)H%R1}H^A{Z{VxZ7 z6D}j3dIlH*k^@B|5#93l996g|nppLHDE~Fju~V`rSZ(^h9E{r|_)~?qi2rzpc7t3r zg^Pk!Rii~A&rX490=fk{=ZkWRC^+T}@ciC2%vAdz=^(tYMedD=fX#RBZ2+8$*K%nh5I`%i z)_<9~y)1niB?3{cJOoI9C*VT;dy)!V7$O-2OhNQ(Bx3i4a)vO5e)ky=MZh!2-&bmI zVKfP!-jf7iYTw-5fk6H;aAB|tz``|10HN;gehdwi*@$NeqsvE6o!*ncA7o;M(PeyI zEgoM)Au+E0uD_2>2D$>AX>iX}f(hN*ivmH*&BeuqbA_P7$^o@!0I&UNywC$tRr{d4 z{QP7$ZE+#3Bw!kQO2dS}N{TQ+uv*gnxb>GP76cpa-Qz{G1tDUt_o~bF0lA_=lmJB3 z@&0vSPHR#1rI2g~1&d2jI&{(l(Ae!g5bKUmxucoVJ| z#gCz&z|SvW&;f8#jRcDMArcW`g|u3i5n>;=TYYNT!$% zO}lgFHVXy0L+rqQfw#|qtlaFueu0i)z!XRRw#?=OOFn~vuwBLZ_~ZeiYR0`!)`CTR zQ2Bnu^<5@l;rg2~OdX<8hlE{&cU@rW;DpPlYha{b1ZVR>1T7k(K-jU$09}rk-*WOk zqUy!GP`^_kSNH6zmqKt}u=^p9d_=DV40!q%sIW8N9A2>cizwi4AQOIGIXPYtcfjKS z34ob%pXE#xYcG!5|P)Bv7D2n>W7D9$S<%Oe|k@2@$3F%LBS z;vWy(E)mOvE@T$!qsR;A!Q%B;xk4g-`0(ZMK=^F?qCl7#@;tJ#JR0?YrwPg>JW%!d z|M2SgGI=og3^VJpjrsC;z{;6XAdC(pURfDFW5Bg=$r5fTkJtPq;2OA&H=7&6!^cy= z4VDOofzaIrWMo9W0F=EzDK{FATH4t^&>L-E#SV7cjY43a<#DsKbEcia5Rj{0i2`=8IuK(tXHAo6z~^$UayB%T-oLk*C}3hB z(7T0sd4=2I2=paYUS6g7XaxALM*$mHF%_WXS{fzXr$oGr4Jy!fg#_XZx{JC+KO7kv z8a;;JqF;R;8k#~x-GY!&2v7zm^c!Prw5AT^8mCJcJ6BKS2{K*|@Dkq1_ZIa~3@T^EmipX3EISoQb+7W~sE@PY}f@?QZHn8zLfC*8XdBly1r ze4a26B;?<)vEq2a2v+__@h@Qn3%~%0%YT;6`@bZddiRSCwz&^mve*j-u+l%0UkL+P z(EC1MzWV-Oud)8WyegK_Lm3TQe_a1ZN)HzI1*B>E3J&+h zB12zF2h~^rLU|vK0x^a{ItabiHvnOwBzIr07EC3y==9lF03rv-GB762KO55((1IED zftquX6VU}gR;&Q%$$JC<%Dpe2`wK?&zbBa2cPP{~Vt@x=Jh2A;cGh|-sQNF593_v@ z8A|W<0@ZUHb&WpY?&cPK2)_m+Dx%ylqmQnE%gL5v!DBGH6VO~J4MBeS`_4-dDSZr8 zz4tg1g$)$=RTk~z$C7Js1o+e`>M>Ys5rzP-NCGtBnEReo;^z|t!UyS-eq2HWrPb@$ zxCXij;Qcm@qJglqTmkTT$tW63#_UrB;;ewFfCelB%oFq&5k5W^pcTQE3}pb&WdELa z^*fFUMuVw3eu21J_o9W-pmWC#k0kH_BsvXXeE4wk@zNOpBxm+=YOw4s5Uzz>GbT7S z290<`MVb~}G&R~|c6QoAYA~B441}Re&&x|K4VVL`i2auUenA&c4W^~3p$78@12eEt zhK84$iVNru2uhx&j0!9RXa!e1ZlQwEsPqAV5J4(#E=nd-z^V~r8RdWE2Z!$`sO_nC?mC?rJ_Dp~-_0x}{;)CyuZF#&;bB; zb~p)G_&@4tV@c2`si{a)Ngx!O_m_oI@+J}pmD0UinKGm>5->X(oES`N1Oq+H08T6- zCS}nGN@(b6O%2juAx$C%i|yQ#$Qp?uBqH~-#)$!dvjH3k2`?}kFm0I0pT>RyK2sym zFAqMYDUm1qzZ^Q#{}>{!NB@jKdQ_?EA3;bZ z{>8zXF8UFel{MxOra&MFghC-MQxIqupR|c%AAzOr3lzDXNL~F1kC;_AC}j-ztN==q zAik$Oi6KHGH)ufJeL2l{>A?+s-4-kCG!Og}U8pEGNNRq@VB?*qaB~U7l9S^V;ob z2PgBMRN@6cf(k*)gcWX$N<0Kb@ZAFpP@05&F9s-;QQTNSb|1dY{U1uo?NJz0&?>>Y zU4>#yXi)H!b)Coy#i1|Ws#Ju1&9%uF;#{9p@Pa-y8euL@T8&?aH7f845QFl42a;)z zBKRmo;kNNI$_Bp0b%%nC`N0VDdD3kBAqLThH^}kp&O$ORumUr!HwrGymdm4FyU5bJ z?2wazpCVRh(D^#FQI1cDHOL6XIv9D_jKRv?$lvNBlLy~+0gCoR*oOayj8N@D(ydw} z{+wH*43C^(kl{WD3?Kx`0+#MZ{wD!4*SrTVK@@XGtLE>(GW>nLjk1`G#$T$MWOz)t zL5fEmZ*WLiYvi|STy8sMgmgh#dLMUtLdsKwPh~7x8{Z1CI(4p1QamIHq7|KmXpl#c zw8qHqD$PB`78uIHkLiy}UA+nyuc}T=o{Jik&0;oQ`gW;jvy{jvQ0OK2l#7isJQJZgBoeO3cQ8hiU}T6PG&IAxPWsGR)LnV!Cjr+X zj6#dmW`%~lFhQ|SOuCiTPkxYy`D#V@)L(Q)>P@vs zqP+}SB0T;ps2r$HqB=pbUc~cX{Ct*JC&D9sXn|rudmc?jVOxxJ?!US^-YXGn zMSR6A-(Ki=GfOKHgzoJ&8hZ~FJR;&tT2N{cn}cEU^&(1~ydEoa(Ft+&!PQ&|LHRZq z>5tVy@q|hFYLQ;ZlSGx}`{;%IfV=nXZJ8*3L`b>sLroEwSU1Qv2q|SXhSf&_6Y++% zP_-yAFgbf%`mm4`$ra+wLNfH25fJZuF_ zS?bGOv;u;@>B2fxuxPKz+#uT{prq=wyBV&Tf}jul)(Z&bl%24bRv#yX2p+rp)s8 ze2P{@PP>KCW2B8SLx#w{leb9L^YOsiMi5l%q2&{Ts-IyLGFcE?29$ICl!-w~dOM#l zko%?0Tn>AT!p50PcYb&L;6v%6^?bs0=1$mzd>})nr3mp&KiqF5x-ZyZ7jtL*%nW}w z5&uz&FI0Lbmf!XmY+^nzC0xdr22Su4ZlDO)47B%IKS`>kNI}s@m)9Ao%U{$c&3K>* zqxUbJl^q-4BBnP|G%Zo6!;_|6zaQnPGb$xc;SCx>M#jb~Bz;|9Ka?iY@hD0Pr@}u2l)MlI_guVq!c5a4Jzb!3RCF0?mFbU2V zt3xzdwM7lp+hGG)!fc;kS6-W&5TcR^h)tLPCxxz&rFA=D$AA6xg>f++e%_C|dwBbY z$7JTuE}M2|{eutI-#xuzeqLg1xIY95y!}+sQQ5QBZ}=as@IPDuTJ!&Kh5rawXwIW@ zGSkwtbH@)W+S>dV-<~eg~}3kb(I&;26u5}wDxKJhF^9Y~h@xdUmE+mSr=aa(tcdgqQ>Z_@~Ztij814JH3 z<|oAmN=bs!@_FKr`s3DrFubm>A4y4S7(Y0&DM=VNA!O2Z6?bj_-t_eEK}dMjrvdJU zJ;N)5BwHBD^v#~P&)6DZRrmAve^0&wV6qYN@$M@>!VV$7_x=e|m&sqk)47(!06(AD zv0xNlT*02UzI6=s+k979)@KF=f7=U9^JiStF?8>}Qm9zMJ#Gwyg&(P;+f#&nkh3n+8ymARaU}c?{q#TyqZ`4R@ivP_yFm zQ4kn9T*ykUytp2q6@3du#Z<@MAV~Bv6u~vz_u@5 zh?B120LMi7h+riOPl9kaioi*Eh%-2b3XNa6>j&#vM$nPVCov57)QDB#n_M-KXSJuq@2m_x}5D#OryKYWw@|ZxCyF7_P-Il@ox54j|ds;_Yh~{MT$9Um(68 z?cv-g(DA9npBUx?H!U9{*w{|c8#NBGfxxhaD=ofa)-O5+{~%n;=es=&%IxQfFscz4 zM)*3xcIZHg6)xSe7Ha4CLk)X6^`OW8IX|P~sU9ut`fu^z^C2=6_Hf*X4pHJL*V(^5 z%8-5Mx^1BLj9WC2ePz%H7)TJL6iD1FKd?OsP}z@fPY(zg0S56Vq&@%P#b^GXgM-Mx z?C-75I>m#w2U1>QQA$hadWL5^cl2a$BkTcR>a#Vn)K2grfj6oS81kU~_C1>y7&pH9`uFQBpMR}kc;5xUIISh9xW%{JGDiUeH8mL!rrC0Wz%kOxDZ(W1M0pn8*aOi|gz-_w z!(;$2dGVm9;%@Nd&4WFB9*R8zXxipWxeJBS%TKRm=*tUf)Z+=2))$8jK49tvV3S&k zL-M3*Ct%YyU!K}0?Q7F|M(}N+n8XOV8h|Rb2OmZY(nSrBleb(Tka>>=IcbG|I)=P>Y_)oH^huzCv5Vq+y#XV{SJlDpGS4wEC|Zt&BR+qzc{RgF zQ#cY=jDKU}G9_^1qa;N`^W>YF zlzfusGCDv7J60+ep)j=OeNZ9P#b=flxvIv2Q;}|oU-WKd2+NlLJCQ1w2U@V6X+r2SKETT0LP@2;=?$mWGW=iCpi*$zcu*^?3$2vGD8U!b=!E+D z&L8z)@p#ZHTESK;U$F<`oh^ZQglt?OmYjg*01C4a;@LhZRFWdam9Z=d!m{L?qNX2Q z3my4P{Zm)Qv&4XB$pvhW2>1f#apS?X#0b-p@(79!cnpRne9QQ7Eg|4qGO6D^4}M|N zL-P8}28L()@`)*u9pgZ_Xh67RVs-OztDd1wt*cu62IvdHrKSK83F>G(fS0gMBc*Yi zj(f?fWt68%g|J}XVqt7MTu=|i_}j+^fXTW_MQs0u%>u@@UZ~^qqJCg5PJ$^6n#_rQ zFCfNeRg>b4-rft9dOlC~YVWZSsC%Siguf3FBQ92eUJ&2}FMaCNa!)_&;toO`IG^^H;oGoquXLc0+31w^dgE6g+e9y`yH!Z9|wlad! zvZ*x#b~W=VCvToamsZRiW>-@)rF8QoYVy=si#fZRzsBUm{(qV`xtgL_sp$WU#u;} ziuA=~NsZmEW=8SDMO1OwV7r<*H%_amnp~!vCN7&it)}vZS$D4(u&cSQxT#2-n-Ur9 z>E<37mY7|rEh4JyW;GR$6!FUI2AkDPxo%SN`XXWRr1EKV2AS2A>5Hhsj8G+?(BmS4 zk_ILh6cv@vXU%Hvt$4VQ2WCJ0W;L@bCl_rl6ckOKTH`RQSy4NwurN1FOsvKQ0{`^F z!t3l-HPsIl@`|c&=d5a)m(80}yd6wr%4gkVx2jn-EyJB$hYJX)Ccm(fwW?WL`%nQ{ zI&< zGksk?kryS@;SFFXRX>07D?l};;f4mF;<*64%UaOX6|Kv|6Gb{4cu~zaUzh)C9+_WJ zL^NOp;F%n0GYs|*gjO3uto7O#OMwE)HyotZg(dSeDZ zHB>?KD45&`SIml1iD|K0XsSK~54Yo1wX-W(+^TYRtsmf4elz@7+-mleH05dlqYPLx zPSFV&8Ph5n(urhmo)*~C|CpbZo|c%9nAVVfWz1@4md{$qUK38qQ_|CsO$(9gLm)l` zURnSKDyidwtFpsL#HJCa)M@GIWu=BRzyx(H7q65xX?V)GVXCZn(K_G+mBfqGB4ZX{ z6~HElgbn10h}Z8zsIpRhp{?r?LziU45G-AQg%)H0LtftGAoPK-)r$r15J35(*p&MTzWCRAP!ojv^A$h-4IRk|7ySRk6~@!1c*^ zyi*t|Avrl#L9B&%cz!m-n1rIuiqU~Mf>6b;PbQLvK~Pc-g7QvEPELyRqSiul#+O&2 zsKxpuBJ-Z-y5`4Ic|96i{_Ky17koy{fO6$-D2 zga?xNiSR>G!{MiglM@XP5+9-x@(6&5Nm>~?bGjBRNvaSRu(BaC{{koZ$n8}L@tYHc znjz>@YICAAK@%SA^IO!;8i)`r<8{hi1a#i_;q_#B4>Xy z%t*%>{xoGfL>R?j=l^N^DcTACq%Xzn@Kfm!_$gtq!Ouj_;HPv;-0y&&O8d=z@-)fl zSoG}~TQsyM4D3VTr*MOY9|Q0cAr8@N@JJSZig;LqXCUjJJJL0Ixv{zRs6uALB@x5n zrz?0JpP9ORK))Ps6PXMLe>L!#1FAYLUoRBM)pW6;)j?W#rE4H=@R}i*y;$`91!>2 z1OqD$_DF+Gi{k$ZAvZ7I408}8J zHrODkV0!@NIT`?U$JPKmoik9%UxY>sWS}JQ8V>-qB>*qy443kd`PG~W|HGgDhd)6Z zMn+Gg;7?PBSU#zT<4-<-KlyOhPbr*XQxI$Y6!y61aQsQ?@q(w_1}YRxo1#2CyzDkm zo{xDr!Jp*2JqS;`EtI#1M--Si;SsDYR1nZR!=F3|f7T@GHVv|KiqyJ;VHR{=Fp2Vb z)ZH#&DE{P*$KH*)&@8nUnKFSrQz~Z}oF%6n{a8 zs}fFyH()%RCseqO!$ykSnJFgVf)hfhY(@rBW57;$!e3zI5a8@DHlotTA6^ocw(@D)G|GW;Ts@DQst;nlTwTW5v&X5 z4;V_tkq?6;sa81(%p@hi_5ly+H<7tmMl1}U@fH@6@&1-|k)= z=m60sz?x8#fIYXUL6%Z_AsCT@cOx5w5n2F+oM1y>@U8 zM8+{3ij*2`7KQO20Rl)r|7CvujVPqanT->9Z-NN6bO?e+4YqNDGmj*GKa6wIM&}kz0%YMtfmPD|L+qOf z9to-A;dJ!4t(!<>-K67T1oT9LO(aPYkWCUNNb)~2YBB&K-vE`_awTJ?&HoP> zF)h9sU6khPg>2kzoLyNl#ZV!iS~ctXTkmRYX=z+>%k{O@QwUcMRTjJGfd)@PQGsXLQo3VSC%vs2bNaPy9KUYn^9F! zHf2g#MOE$G#r5^qPn}#`arfU}-@STnzGwbFR>+%If zJ1$$T7iJY}^Ra^U`Mi?Xz>*U#JNkCs!fAQBTv_EYtIhJu?A%GqpJ_Er$y<}lulU+z zv02SJ6WODyo~+Lao^{@4HMLEj{Ooy?sb_z6PT3td=I7M>WoAxsY3|%#;XWXiTJdCQ zK~`4Iv>X1~d$G6Up}fCR5*ryxjD8zgTSM4Z3t* z-iL5I(0Ycjw!EY_$t*UD>6iJr*=e_R1L;$`G+z1+uvcEskha&C{irudt+u|WvT`z0 zs?OLfophqf?5=qY*8yNBBjWtW!F08KEVY>X6#)*QW z`ht{E}cm(9;Fon9EbIvU&Bz=-xFMMrBUMn_M~&@@H!V+*F2PRG($!=}gcz_fE$dg_+e z;^b{#u8C`kqSCS2`E`jc5kzF;c?h-j?Ag;}+V?`Yxviinf=a5p>CU>imM|i6mjw#i z_-=Aj7!_ByqP{MEbtqo>B^1ERxy_-JX7;*!>f+W+z#d!AU=OrRpkimQTUHmnCK!7Z zJnnA^ref;;GQU20br7ES7E2NYJ_{{7?D}O@0FZ#Oc`+r(^{-s|nwUFF^1wYeV98yjtKpZFNSI zS`e5vePUQfaqwy%?BNE6dOEC?sC5<{}fG)lm8!hNNk4%JHL%ecC9l0@{&wpzOZ)TZ&0hpGifPU66Gyw2 z&norSig_Nv;_zc&1&m0wM#sd!bMwq|u+$Q`|rcgs$&__rHAfG+!~X-d|YVp*Qm3(y9w75_+uws8k_6R!jF9 zu}(k>1M0ARSDB$pZxou&pQ{e_QNl9DKuP!lq1-znXKB&W2bXy0C_X|w~3X1BO`h-A#g@81G8Ws5@!2}^8%3VSW4YXV&R|O?co?|e~DNYV@mx~NEC8Q

DT+9+;a5S@~A3c3_ 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

T*aBp%&TN@ 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 X%)Tmu;l0qY00000NkvXXu0mjfuJWKO diff --git a/find-object/bin/multi-objs/38.bmp b/find-object/bin/multi-objs/38.bmp deleted file mode 100644 index 8f0345162332e13c2021b7097936b0dc024985fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 152694 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

(M9XAwwqNKEafvv&|6R z37MgGC=-2xY%TTx45KoTqb;B{Z zJBMcx&@qu{=Q-P}`y1kzSlWJ&>gz-Sq^*NzMf+rHIfO5>e(~voXJBq`x>k$y9*gZ2 znG0KU%vH;?^JmYq3+FFfx}cc1YMcxc>cx@(5JkdgE}eODra;yItsq3f4vgEtLarL$S+vQXzPcgBS#M%trqLHjW~An*vVtHH-rYDntmiSAvn;~w^{+&sjYImEk{w5 za&xTurOM97#3!w1w_2~=3qa#*3v_Q@kXjlsDWe74unYb80V9fJZ%JO(tmYVTF14Bk9HL=U*RGp{DuE&fb%1nO1XKcxfaP`$7c_aj)<*d};XcaHVB-Ki>WA z?waTs7$=}XH;B-MX+x(dJ2zX{w^zc!Zen$dNi8)w{q^a?rw<=Le0=nH)$<=eas1}- zn@4XRWrl>heLV;+-@SbHa#fy;T(4nr^61F}Cl9b=2Ra+6jGY~OGFEJ<3F)yL$Ce$d zHAJuxiVmKsMsfVjQ#bc*mK&VZHK}V!*OJ$k6rPpXu~0PE51#QeL)MbrO!R}m{&5m^ zE(2+*!>86q@79A`|NGYe-u1tC&Dd3X!y(emeOo`LR=g_Ex0NsfF>ih0Rz2tDRW+dY z_SV7#=0X{veo#A`!#c&oo9B|X6~tuqc;M=fD)c_g;ow? z!S&I2#j3{jQeK zCivWD5=$IUF!76=KroXUd6uzo;dy0+^!2sh{Mpf3Ic|cme#y!!t9s8}sXhQ6v+K{f zv$_J*x^kv-pFLTwe0{|R1UW1S$CBQaN|l@AM#J&t$BW7;<@RzH9_3|1W}LN6Q#b9| zwCB}5uWo#G3>DHgd+TNcbi7c7PWy z^?->#vcUyMuEkq0pZ{SP?pqEQgJzgF7*d}r zM8h-vyz|ozo=wD-2xi*|T*`1V^pe!Bw35R{42gIEaH~Q?(JjK=1b&Be7)TQjjGEzq z?Y(55kb1c1LC;u^rZNS6ITr??_?cDEty!-f{|;yq#0aiEmh1^mFHAQ{J?Ah{zs^`{ z)_1#Mn0cQGfajdf7-+IHkvHLa3frme0Q9j%8xP++yy9?`KoFXOTw-EEtZB|~Db$Ad z1-XYN4V8Y@h~y8eD&MVlPiq2qK%51zkr}}=NLxSn!;k;+!@qPShtCVoJkbAjo4`bD;4+5`n%)pYF!rjGS*aL1ekEMesqycU235)~sBI3q!(>c)V z6+Ej|5gyNT1Ab?MW&3C#?Ug<1I)mq|87yzG+25^#AaB)5s{lGN5PEyg^f^oCEbU#| zd%Cw;lq-NHJxNfjl>iU0L(O&V<=!YQ)4Jm4wnizC1{$etl*$#Z zX^`I&O@y2du}vExPLAtFgt$`P|KRJ2Kt^~I-zr)T-aNSSU^NQn3CbX#W$qa#Ew+Bz z`u*$oPuf4}i%I1M|6z53xpIU}zheB%Ffzs5#_MQ~fV}wmNA1lD&*IM#p!5b0lzu+& zp9f|iu=uI)todUMA=AoW%y?(a1p|9By9rs<|I~x(psZxEwuNNj#4&yxBa>PaooJaE z1G@p(;KvHwAGlg70*u>x+zaP)1F)gRpq)!7yhfT-e65M0If3J66x8!yR*i;8|BkLP za#8JD9np|SIfUu5>(&1FUM=mm%vj*4-I6=3?qu&H1H>Pj^Fi$g)U&K-v}g4CXyKW| z*1CjkysiW5mwLE`chU6A4S)jR5HbLVpW!*QjF~BLy4<*c=fTT^_Xq2q?t9&Ly6Z1G zL^Lc>#PFfl&}pga=7_)!;N20+L*fFbpPycRx|Ri@FrZQw$|_T`rmhIQ#*!A48O;6R zE_-WgC~3t#+q-t}qrH!=Ke~SC`k|3S#C3fqM{XZkex&wCW5ILbqp9RH6R)4Te&70i zllM(tJGsi7URzgs1DMm;T+)R5*Vc=Ibn=4`&gkcVDaFyjvk>&d7Y|ij|9s`=;h%@+ z40oC{+x|x^gG&h9&G_YVOKyS zA~+DGLjpv~?(C@Pz~4$; zpYx3Y;{vd~0%08s$>;vcAigx`a0L&4XHoC+9m}O$DtHy#2DDY&ysBEPIN&&7EZ-ks*!M6%dRMxK^U`WMTMJL1KOY(+zYH9m5bLJAc@ej7R>Q9ku`=F&h|7< zW-b(h7S?A}%SS^9t$SL`!(PhaG)yj~hd*J7fw=SsK(nwbJO{cHS=7lzsqYkfCvZn* zS5V{a4zV{wsuG2cj0nhPjn=48UP?Ifhsf-J*()kZGH=SK(9fegN3V@me^DW#Gpoj=MX?cNEDx$<3HSlyPC0wEW-dZ~`Vq%8)m3FU%rbvSzp{dmTY6 z5VO*bE9(kK!!PVAP{?(sk(C~1F67mWg57IGTtO|xNo^+E%~uq%V+uhlQ9Zwc%oMXcbz6Pm z1d-^9+BAn;qth5!#aswYvOFsM=VTcrCb+E%N}%tpxz+y`7XvUrwi>wb{cbU5pdJ7N ze9U-=nK(e&qv7hn-gC?a%=e4*Md2`SN=92|t})Xnjr<9(!02cEEZ^O`q@$m+l~q=G ziyB|MdF|r0i&rmR?Yr8yt#8|gZPmu1YjxM{uG@!iAHH+=&b2!=1h|mkhh+EO**kA< z{oK~IS&Poo*gtRogZ%~O9AR>LWB29V_jljFb^lh+t)4qQ#n0h+<07ceykHD?Vhl64 z8Yb8Az7PadyE*)@@C=cqEk3KHWV=qe@Y*02s@;pF0XjI(O*pS)!-{&k&dZOwA02&k zbp27g9NX)7*fvHr1{`DRnMDH=(&C zR&pnxzy90Ko_at2KH<88v?zx(p&pewGX3S!Uk?1`z~Tedl^33|Cl1BHcrxUPf89<> z#mvFeQ_`uUi(;fNKkGC_S@C6+!s;WL?ys88sk>tfx)y9(u#IWYA)jr-Uxytl(nK+- zSlKZdS-C^&W+fe&1fo>9k|)O1^nFRvyuYLrh1yN?e&Tge+O$fP2AL6y{D6F-0*oEZ zX$;A;@U4>t?7-KnQ9ERLV#|3QfjgG9T82-Cfk6~J(=$qH=#8FFJNlVJWk)ut2!^E@ zRI}lm!zYJN&N(?}%bZI2-R&zL1vwf50%MfK_B-3BZ=b$$ddJJ2wqn}gw9?6eaa}aZ z1fF+Z-g$p##~*}gAy-z={I-aiZmCyq4u2>*gk)*05d5GtOxPRfhwl%sAFgaTen!NB zv<7Z~oAiNHLUIaKN!DzR8zVPH zmX4?suX+i3Bm4|e=6AMf+NQ&s4!?HzwNGEGvWGXeyz$B#1!D?XSOW_)5`<~W!7cQF zLc7GGf1Lc|4}Y#6edP`Q*ja-{kHPc)zwBSIznU4!bX!J*9h5*bf7h}R8E~AeIWyW- z$!y|b#-rsnOu;w6S#dpY!@RBYs$yBufONJMR_QE?a^;2;Dmy3UQN9NUz^nK+>U(*4 z_yWCR^(S3ijqI32j9j?%;d}Et(|rkx_p4ADUB~+aVD}^h4RCINZ%fPQH_Y6D`-J=p zVu#OGNMQBI@}Rd}8!K>UR$v`izf=2X@zUvy?oYc%yGO5#Ub%gxmU!FgYUKRL@QCfW zYYSb+!2<`sI%rqqT6!sZFQBhNk{Q>1+xzzQ?K``#b_LpYZ`3PP8b{JWhL=*1_)U)JU+a7c=h(x z)wpTxrs8O@W)T>Eg6N7=MJ7#FKTKnOKfj_PCq$+Z|HF+{BWh=GCJ=q?`n8kSPOdmv zEmkZVWMXI3vsqtbWHE%UX#kx^5e!g%{r9Ck&@w2CMHjwb z9%1YsCjS7>`c9^PTZ&Lk_{H&yf4%tEy?@=iaIcB3GRyO(*StVR&=XVz_0HfM%Bcdi z_!a|NyxopjC5V)PPn&b~=W9LHgR4!} zgr(87GlOa}K1R?7+i=|K5G8Qto3`!9wj)!HOqoAre((I=*Lo}2 zjgTk3S`iH58L(O6&*B@(IFuq`YIptl_kaF#6MxPMUwFRvU8i1j|4+nPg;RXhrUbbC zazT~N>#=N6(LFBB<>ufDhwhu6Z-X(I<+Z4YAM}mo?>XYr!_L2PZ-~@^$??WAYWlErMqq6wvla} z*c5&qx;`{-$V^pg*%HcjQHF8NDKOp*@AwF+87$4iYg$3w`1D54jh;_>Iz^0W>9BSF z)_Yr{M_{vI=Lh50$5C>n1=+6qyRPlB1f=L0T~iyaizjTy*9!@Ia;vMsELsHb1HIri zOZUYp&bV3Gz|J1GH#+Tc{w^|ObR@j&6=L<~nyjdxp@&3U{9%wbd~8{G@_L7#+o*5w zj5%4)^qwOMJw2uQ>+x4(x6YIYce36!m_xwW^*XqT;gg5CD!r z6(0=|x8|ON=@MRWGm&Q;8>>=`m&>L+mit?UAYDzFKs;yf&FKY9SP!cwW9TMU7sq3y zvLk8kiGdFHu*B{X43r<_7jK(ic)m8$;pd^NzJS{5tF3j1T6Iu=NGE24Yop9 zwf(h~h_+`=PgRL?s?~0x^eywY+}qND3Q~=c7cHK_+SB}mkO|GfJZ&tRku(iO9jLd_ zk3#T+LNxvDvEbRwiQvo-iedp!jm*R%(`!@;T#QEITaxACsglQnIG8`9!@S_HGjG73 zX0jXjdFiQI9EU1l*kNv};KGbrGtxh`|7icw*N^HjY5{BioBeN2ezWkbWv<9`%IYT4 zvO8HCCH?rykN@)HKeHeIx%9IQWl~@Fx2u2a`din$uF~p^j3z3!F0F+F_RrAwL`A5E zS(b&Y_+*96Fm`RJl8pYr{uqGn9N4*iXBFI%P>SldtSi^AcYE*d-rXuX9I88dcNzyh zn|n5|+q`bcx+Nbk>C`YoQVe2wZmeeg#ybO>ma$!NZ-fMB7C;;E?71Oue9QY|Ns%LA z)Eu&f&kvdd*)qvK<#Y9LvqUA@IJcuz#iaf?(wh653Epi6RZa5oA+<-zPWpBcf|umH(LD+&&+Aj62TRCVQdzz24YYy z4s8nOS}Bs7Q6q*1^D0g*q}~}D85_AYQf=t^cJ~eS4Gj(r?jNk4q8CRB&l1eAYxpo1 zZurv<*TCBP6#TsWq`sBqk->1IF6)09T9jk&G>ybcZ_J)jcz(D4-O2BE@LZ(aEEuec zy5<1y9AWGqe)q$_{`lvZNc7VmYkkU;_YHG4l)7^eb<5^g?{O>sC<%d! zXoE;-<@&t46qksprL4}kALWNzm{40S%4(W%`RyDmrF!&aM3j$1X-KRDrQ*wC)+m|< zy6^*V464K1=-NG00WK9UwlfMSyAH_|1?(YYXD|?SUd+QR10;`z$&-kQBqlHt*)|wd zora~|nb(XD=+&Hzr4tXKfr4i)@TskZXWk(FyzlD1ul7|5y|2znU9Ph4!PmtC=|~O* zXX?c*Vp8zj^+nf}t}8pQ?3}%`gXg01h4v`eFt(u>5iM2GoH#LPx2s@W^vLy(B_Y9O#}k#$3|l8myy|w&9q%|rkF46 z0c|vM#U+~qs#%;kaQr(O*Z9aji7`)RP=}5I8tQ;DL=B(8eBr+F6UFPu53;!A#rpu; zc@}PWrjg)wmD4o^b!|AKUialDS)Ss4OfKw0qR|^Cx1GFtvQi|D{a5#I+FxGM7n`ib zDSj4dY#Bhoq#NQjD#*nIEE-`vtSg(Y?7FgR_O8Nn`Ok}sFqE1H&ymg;82ws@qT9yB z<2v4r4v!As8WxA{;5m8&y6__yhcMe}Qso*9xMR3f06GJ~6RkkN+SoXLTwKVO#>F3% zro@~Ub29J~I?OxFID+9)?GI~AIXJ6QP0L3s{tV9yN|MD0V2*!u{OIwcZybGN#v9cu z37-G(PW3Bbf*K@rxqrWLSqFTJKSMKf@#Al?b0xbS)_1Ec)F0{VJ752gum8u||FL%N z+Cnp*P;et|_(TDZPAd!896-zBz7^(P)_m4oP1Y|kGo3Ib%;NF6BA}fvqf&3<|;{T%G&#^uV5aU?KL9vp=0uRU-x3 zYg9Bx{mI5W5&A>j@N57QOe7k;0nb-XRvkNk>cI5_8xB-BT_;HrI@?-V2FZkhtb*W8 zf4-uYP}NBrYIUh#!KF<#p?|XblSQ9o>MK6S&(;>I@9BV}VQH8?fA9Rz`Js`an(^;k z?3^%>7z<&IMG2&qqpefQ6}51P8uF7mbm0bA2G{^x$^RiKOE~>YF5zo{HJkuW|Gpd3bKTn@Beb4kgf7*Z*Wc-U`g| z{*-G(bs%LykA$E-gsTyE)jv0AmK+3T1J;g*XYQQ&pJ)E(hW}a76J#A)z^Pn)yTC3Et=R zwJWsy>=&)ltZw~lTdy*zsP=H*1oy^&5duYFes4| zeL}%FpTT<6%(c4}e_nZVlaCO=4jP$6WquN{@x%STlx--cx^wpbIlhlKX1KnX`(mvY$>sZteL_J*L& zMd}i!YX=C3N2{P?25)aoEsrnP-HtmJUIj|xfVn@21>?Xz!T?Z{=>xpbGWeqF@VTdu z%TXOTmqn-;6bzm@jOv~}Yv*{s>dDJN8BCXVl4D6s0~Y z+_GRe2y_yZPrNe%z&%B*jiPS3TA>m-qML2-tkw>sqeBAej0@~q75U$e_l@^m>#L}s znZOl1rV>^-@+<|dV8o?>gdYR!n1s;87+QOq8uV- zXJ^;uUvD2R@z>uRQ{JC4X-Wm30XUK)5*k0J!oRTIZ1CNzAFSp`mUtVX*13CQXKtPO zk2C+#{U6=)x{IB&mWp6*2^NguTVe%D^%WK0@Do_nx@x1C`eLI=OZOjZ7kZ4 zn$|J;L2==`HdMbO!FQ`Z=X_bUd?9M1wZQ$-H-u5Z1I~CX zFu5mzp_5%FFP*HV9MWNjt{vKTsIvKz_vf41B4p{-T{)>1E#j>97sYWS~?zQcXpecfxi*KAs| z>CUE(uC8SN?W)BR$G&=#V{vlTNxfUDX+ZEyg=T7&DLgax%!xB6rkt2Eb;{JfsnwEk z%Cy2W3|BebZ#te}dWt6Bo%&~_Ena6mtZ3cyf39T;S)4L@bM)uYpAY_gaPGmPWq8(% z$Lw7Zp@h;0MtTx z({vFy8C4t&T>Sge8FWAFim?Fno6`!tR0!BJoeLBuC8n3>W)$STA)T*ge|7S!lb27{ zCV-6I=sVcAwXfPkDM8Vwg45^gB9a*#(-<+lpr4eKRqw{$Z+gEO{AO_Npf6ANtdiMw z(deGvJ=WdfXFx=-4wfsyaNzA80=P1B;{ksCA4?psL_ib$z`D+Hws;3~!Cb&`css+v z^H)DyJ#BU6F8Q<8v8v7ys4>z6(=`Z6l%V=(%&$P)r!zji{%KLP)C?HwO=){kxfx%| z@yo|o9$z_YWmN=K^<;BU(kM)2^0|5EPMj+|zc+=}pg2Bw4x$;dxq_Hk zLWQ|Vpaa6;S^o_M{Yp3#BWX~X^v%DW{I`*R8<{gA7hRB+BhbUJv~Qz+sSYs>_)F(H zsMc@Cas#Tv$IEhWc(!9^KCD`}WDOFgt599DU{qk29zhc9-<;?iAhQJ>eE=xP~7+3re&*ZUxc-d|dxg4tNb=2HDdT3Gt0chPjtN16|9ymVL6UmTy=*u6}8JOX=ar3Gs;5;=WCU zGz7NRg4vzmi=Zpr^0Jv8NVCZ7!hLg)Ac-Cu1tI@s_i7O(k|R}EV14z5t=@{#SBew#j|?RSASc;hUct`h3EK#R5S@a_FTK2Ye%jf`RT|{ zXMQ>}?@R$ta6|kVp5w>GzeA+FL~2-KKtC=zunJZ_D;0rxa_E`E1zNIc$%ZAB={8Ym zgkoPSKbx7gP4~M(k@%GbvP!-ztg2T$=5Wn^*mii&4ui%B)0Qq~J|IUu%W_)V$xL53 zecAM78tv|*CSu++T~Ze@bv}jmMj>pUHq5} z%lVn@FC9!rqf6InRrS@cuZ~ z4hrpn4e5DpRkd$Y|B9JWG}jn8`|zSLD@Rs-ys`?A%*WLwtvM*k6(6lQzryBVhyQr^ zkJJ7*t!J97kybVs+qY}WB)%}_raaTm8=c> zAARAx;~9^~9*@I#Y~vir*<_GNA_)WnAqgSLfB=!k7@K5~gMmQ=d(N7*&ik{ztNMP_ z*7EyRuO)SUx_95Z_Fc7W*Ot8Q(7B2mpFA=7>0}{U^TAt3{YB7dV1{iodM^KZ`TFHD z$5c)~qg!?P_3W%^%9Bq9N=1>%)hH%`2FDjgXRTk>X=m9y!bdGJ>60l`C{HFeW)~&0 zrJ&z{U+s|kPxOoWK&iQ#`opADPe3|K*!*n@x!S_{oB^fb<&};xrD;gGH52un1;sjm zGTIn4VGDZzgmx!V#iUW@lq~2FdY|xSnu9ubZ>($T~KSX^qP)ifC&| z<~S?6sF4Jbc39@jKN^kc#95Kp30G;RBX${pCmf=Ty{qNbC2f`iSOwtO0?d)Pe_Lh( zqS$s&?OzymfDO9oC2SpZp44;d<6iPZkp!wu$tvGAG(CQRbPomCPFncU!tWM#Y)041 z%Ms;#>g=f_r;bP~_QA?Bk;)L78L7wqU-|yZv6W-}WBsr8zxwX0?{0s0`<(4_UYqmU zE3dusf4xE@s!Kbb7@j5Nnt2gF$^ z%kX3Kc~&bU>F0)Jg*h6y!epD-jhmjpCe7c%LYf3eMxvqG4x3HhA{Z|*csKy0X#)Hb zRs(*TtyK9icCA2shS~z6NwA6b)qHLp_i%-vZLZCD%S|lhaM>7L9no?0sua_MdMs2+XziG|aeY9?9ot}+jlgB2{ zO?Fr`Kqjz9{BvomhEjI&u*~|$!5jPp-G!td<0PmZphj1=)*N0yW(Y$4CqZ?&CvHQx ztfZ3g~jwoavW4{N+#eJJ)<)xLMtgO!@$y=00VS3hp3tWUk@j)S; z3yXf%eWE#0Lyf&T|HJuH=c_;Q=&7SCj#m5+Uu~>=Uy)^KThgn+d4mTA54?VWH>+}g zec1is>mR=Uzg{mb{D=RiD2Kk41dc*94Aa$)Wxc_3hd=8alquD)*1_hyGz6Mu_9G zqDHj=8UUcIzWiCe`DqTo)zYr(NCMi~es89uVOg#h+!lJE(T^a&%(=D$Jw82YB_aOx z_d57w0ETr?(FBHDhe>Yd4t(9A*Wt-QzRLi*JTFcDglKp_E!W?QkBsf8i2dW^$4?$V zdG=)Sib&W6l0jO^QHPtQC`dy>awzMwFAO0u&;=#sEQ=tw7TJe*Bq-}h%Yj=J-R^f4 z)P}3HAg92i^Mi18M$Ks#Mt=&^-WMVL_}?RCCUtQZLS=F@K`znQ!_dGpH6 z>SvLrKpp16JbCWq;gg3~9$xw3%EGfw2b#xsA}|e4riWx7{dGYFK*}$}?}2ap;V-aU z%WQkFRC5zJs&6Io^Z$}6SK!8zdr!oQJ~ScM*!i)ZF;n5~IlAZQXGbd}lr9c*Jv`)r zI2D=hZwxTZJ-Zh`yi^Tip^S!~2m z7L>)^Qy_o~(9x?fM*xq|xg;HmUe8O$-9aVlC?r)J?-eC(-EpmsEsQo2O5l72$Z`Ld zkE(x!7@ZO?hkva@n_6xwg%l^|6Q$3Q6ZZ#c3wWm@*r>~zz@)gc%}2Z7g9W=5>>Aot zaR{SF4COEK{B5(y93;ioz~Kr)G^n5WS0nt73=KDnh(wF%|KTxH3LidnxUvk1|F;m^ z(sMZ~cu!ATs6zUeDd%Y7*l}Ub@SPwHjGEKUx|2Yc#0}!AVl6Y7ZR~|=wAq~_sEA$@ z1HlC3i;;SF-MjPOt-)>@%4E!_FVysjC|H5%w0BrEU%}*8ladv1FH+7#)05E+1E&U7 z4Xk=^ReiP6%Z+A^HuJaq(Q|56U$XG+h3_vcJPWZaR?!4(_!r48>)8+MKmP%oOKv~D z{qXj~(+^J%o*wKTtb};`dn#&|)u(kgh6oE~*a9$TMEn)_zp1(KjF^AyHyCAl@tq2# z+rG6Dv@Y1bVB>;vuF9%pNR@!+WH^^wP$Yw3X-OuL41%RovZxe665xqq+A2+ps_S3wSwFi*2 z2j8wM-=)i|7LaIl7lSbY^>n^?wv4*s%*w3IUX^H`xZb>Snyn00G6EvZzd8#SB@=Te zK)Reh^E-v3ebC_;T)(xbKWZWvZ2k5psnQfRoPD)@> zdyYMk-#Pu%yzK|J9~e4N^-D5>t%tYH+gd5U#Rq<| zg5kL2$0aW9c*U8MP>r_eG#x%Syn1-`TdOOaAo{tZt==mqv|Uk998CGR{Lgac5}u9p z3AT9d=;h`gJU{xwqsRX$zH$FaWzmt}srPj6y54m?>uOGxFS;uJSrY)y%&0FG)I(MP z==z$c*f^OOSryAWztcZhh;RA-F`!AQp^a;ylDyi=`&Jbt`3IepJ6@$vS6_ zwva5zq9MC>*E;!t%8>3yc*I8z{EG20Oa|8_2Ck!RmK}X`l?G z{f*d`@=~A_B)duz*oIQi_Efj1_6+XJB#fVxePd#CTB)tt zC)boQ&@67`XtnE2%kH0oTmQxSzV%XW2plWhuvNAJEiK%#j#|52*`brB0MMhTQENOT znjGvw+O=8ffP1FD#wKz?Xl=d%N$O5aoY;C|>*B48&n!Ok^vqKM$9Epzd2#2(qZf}B zKa$aH{lxl-D-*>rS~ec%iCvhqUX}6h$JdTa8&jXP)luahZ5E%9iiopFq5Ho22VeQ~ zD}Q{Y6J-a|twQFkYxOfw8$ZZj2hTXi{m1uD-aonJ_eK`1*H?Ht&t zsnj*JdC}&|pCD3{?_$%E&S2H_6zJiSX~7&ArV}=efyqRTi`(5(9;ZFK_UznKJ`lSo zan3Yn(A&g$9BaDAXnYC{FZprEnW!f{E3<_@1@-K-PO(CC@Ek{k@*(Y2 zIUh157YI8EkE*^)8}#DuP1NnD~tW zuW;EY+bC-Iv=C_4GeYQOXiuj}j@m^a+nGT-#9K=bjcct$Q9~!<0gaR2PYzBF&K;b4 ze(w3{^V9dH?>)LF!&WUT9#yC3Pb)iB%wwd=xQ|})n4H2pj(vY@!?6t?Z0OW0zO2s+7`+5)b9yolU z7~p|s8Jx*tH!@f`CrKrZnn@dlVTN1oJG`%FUkwgj(zE3KCDqn@+tSGIm-@A6j0io3 zVih5Hr+^2{EnJ;LTHRZR-|nDJeUC&H+h4@x?={35e<;*80eeuIOBAyC4&QjcQ^+~$ z4z>wKP0|*CK5*0Fo>nC^2!H>l`*-i(y?OWM;mwspqi3*&5seRz9~?jU$-z%{d{WcR z>t$KkSDh5ybG!F<@87$BZ_i$Dzi*&fM)r*ijTE1jjeJ*cC9g1Y!)%=fSM+?@GtncL zv)R8(`GrCU(lPOZ$RMiF+|0uQSAd%nqKBOZ;na0d9YyW5R-A9AIzvC>HUx+8!z(6M zoL|A-szi=LGsR4hT|XPx(LL2&_jYHJpKE{7eMII-^4NX4`-|>s{dEiGYch*`BzmNj zPNS?ewM3g}408AeM$z^XT9=~nl|OZ|fx$C*{0byjI6wWY)fl}qx@@$@xN+nf=c6^$ zI#Mq4J}q7}xTK6121)1H%mxHLe! zkLS^m_w}b=4}M+242EwU++Tp)&}*o)Av-(Q?v$vtid07`+gL!-S1Z06{;KBeK7Fhr zv@&Bzs zSTr?EbL3Il_{NjQ9`sCi9^DzaGqPZ$ii^9P%Z2c0h}{?BB~o|u!p-|O?;G7Wx@UCH zyge1c=p4AGFVO240*nFeCDSGyqg=@$(x6{7`l~YiW{VmT!NoNPMC8+RYR7`6b;Cd;2CI>*gTN7m*hUqcML?~ zQ>m&a;x`g38b}As@o(7U)Zjl_ea_o+=FXYBeD3nW<%8pcl_9+UWdC^o_=$1EbK=58 zMVHMxHt*EDQ(I4M?c3Vd-B+{loS1iF@Wf!-a`B1qjEDm!)(1xidk1@mdxr;x2Nn<1 zIC?Q)@O=Jwr9^YE zN1xn@CH(Y@mH71gs@VRoOCN18w^sedyoIiZZ78DZ3L&9z-2jKSDV{>53x`YQ{n znF1hY6iW)tiW6^k=LkHro+qclt~3BK4Hm4|-dW>WAiEUqtn3+}h;pbB z#3EXU9aCq_NPA}4Z%s6Q_T)l0 zCGM=hvhB)je~7k)`Npg)m!GPnUa4JlG~vpKa66}eQ{O+QpY~?-%xKSO&#Io91jl?} z`nrpyy;A^=eu(=>dHS@}iZnjKGu$RxBN&!aCfzGcLNlxw2442ylg=!P@H{d#GJm8j zLCqmaAGd!s+2L2!X+np}AWj#RiH($MRD%-XrlUT8CRw|C+@f_B+EV zIJS?CMEOQgWl)ZbgXV=T;>GKXX8GIu9nd<48(89qu!*3c+H^Icc_U5$ddLeP3zUu0 zb`%>1+#I#jnSRdQRg9FgOM+*;fy7Osz?FIGiyspRy6EfmF;(`h;nLI=Mt5}mJ+T`?^8o^CYoy3N0)lvP&w&gL` z>X73nj+0}}QfrOaH0Yafy>r30ZB5@`Ur%4phMo;eHZ1vgNhedT@9W!<*{UYJ0|ImZ z>oqf6m6t>3V3c#Kr5TDQScyD&m3FRKp7nVD^z%=nKaI{GEt}db)I7rII@Cd1Wl#I6 z6t#uR2!ILSbcAmmsetX-z=qO@Yg+3*AP%0Z4m7pEPq6yoGlrgjBti=EDJdP4H7 z6T8wysEVmLAHH1)9CQiC;apDV8A%4TY+2_BTEDhtL9%e)W6=>2DiJ{{|ED-LG5;c4 z#8MyVu6YnFjBZ^ov*pO}k&z>kF&`z#$vk|dx@*`!jB+Lo!)9=xdUGO&2dj(6-u{DS z=@4tAN#<042_s0J3DS3fKcMU&3rP+Nc_@tX&VKERaoQp zlu!wH)=wabO7w;^mc&jEf3t(GuFPL`%JkuaKzjNOv-oy9s z*q^;`%w;DgoD_3>kG&{Y+go@FDS60-kM5@f2^T!#QX3=8kXE zVQVIGlkfxu0gQ+>_=zPh-3cTyym?FjE@n8_69n3BfoBuKY}@NtBs=k>x?OWa=LCw* zanpz&%C)Y~QJZ`E${*Xev+qz}RRN+FcoWN|sE-n6oad z0B^7XgtGZTo?d;;V zDRdDZ8ax63b8r9*u}vT*fb@@do^be(oD3(W*A8@$P_UZ;o||Nb8o;3Pa<{s2Mo?~( zc@Pl@&dIMJ<$f{hQ7zCTz-cH23b&Fek4dUeDxELryJ|vG?|fM`Gg6Jp%=Cqt5?#Y` zELa5nlIjPY8NneFsc1AydDR!$>cpb+wzJBN@Af&p{Bhc_{yw$Dyw}x+3VqSyi;hAvQQPIF0RjgMpLr9<+ zq!)iuF>-4cR?``g+KX~0QBYp>nR1eFpoBj|Y~UIj zP?UujZvv*lr+>QMG#N1ul>jKhA;7hw7Su$x|0wDkFqZ~z77AARSP0CkEkq%*1l#@* z*SM)NB>s`$-zB9lW`^8mJ%D$PQ$KpEGqUFMe+bzY!CI^XlMvk+K{9;uRjbWiS*0{v zaAOhVZF82PvYbQ_&Z4w#`d2iBx?Re`X+r4zv-7J3mElAySwRUi6M2YJOpJX+C4Sur zS=5?VnDR_EJnbt{{=O^GX{)u>q084KWS>}P)R*D(X<7ZT_Cqp%w~lRUzP0H&8+0O} zrT{bB!ipJ1NBNGkTidjQJ{CR0o>8nm4|t0*HzJ6B=6r_T7=zX`U4o%2QPKYW>kt2W z@}zop;Q99b$~(PasF;IbP*4u<^(bF`)Oj^3+JmJB7F|fZ=-Oo!qQ7WeRRm0f7{I)- zSyar_(8k=Uda6UwComSv=#>f&Z30AvCMd+%k6MI?_l+f37GN_BTx&tlErp!Qz%=ltifuqCcI_}sN<>rRPhP9xC$aU4lr(0eYuJOhT#%ew zRDEc~^=gf~sS)r0wZ4omq`tM^%kyUr0@bZJVl&}#YHNF%%G`!ydGYouhjFE^At$@7 z(swqge;*Zof*k(>Ips(oHdtkr=Y()YnA5PvDH`DUo6S;QpSWM=o=&s0(!w&x^o=~H zh2*0YEE*?OyQfNFW@x_$1{!BjP}Fh0Y?M;Uh00Rkvu?KRj2JgvZI3)39>cvG|H@ z{Hgl2Y35g6tqwtZF%O0!@$bnWpFI6nbyiB4D;Z<@Q_y13fFO%MC%QoEqv=sDBriyr zI!U;v=={xV3y>DUb3NOtqffMku_{D=Sl8CBwOy4K+ngE_)#?1RSBIceT>#;Lji<@A zV%`}(ZsDUzG@SxbK5!h!LPCl~$+V~rLegCrYyc`dG3Hw#yKzKA4!!LvAW2PeH@8Jr z!bajrhH|2K<&dEl9Akmv+ayQ^Yr2}=fM&fc8R$*7>vU;;svI4`w!65w+a}^#lMs7{ zl6Tvd&$R7}7KeCvj|%a>ds7V(S7ub4!}W;G;vI6Pa1am;)}tGpOaPRs^(k$NampEh zieot7u${nHb!H|(5XhzQjfc{}IFQTyfKL;A%AKL&9bJ{wdrHkq|3GO;am`ze!OWLI}OY8RGsD)E>}H< zyd0Qz0&H~FWcW$=9$&2$!H}BB{GxB6lv1AUcgcsyroW0ek`H0iO3E4jTEh@>RQuX) z<`VMhTMr(-0n9-@jSW;zYFCsk6^zDF)J}^38J?LXjBU3qo-xDELu1->3cgg`u3RJ%>01o*%SEcF!YCsO>!EKF*ZpK8Xi1OCnyh29) zUce*Kwkf5QPk}WhE}M}QW+3hI%whxo(dYU;MB&pgEuIy9S_(G^6{IhS z3rR9x@mW=I&os4doy}VZ$w+b{($fx7AOM}1UjK9v(!+#iw!~|PFk{uM!au!M%9&I= zQp2C&`S#DZ58pn#=b#)7puMW}YNX-H2v`wwKfQ(vm&U{Y1*JDkPtSF9o0-(Bz6&$Z4+)gp9JlA^^GDJNHf!q zO$g5+8`QPXJCZJyr?1k^CHmj-jYD@1Ek3mP%f*FW>;kpG$q3egJcBX?9Tu&jGNC4& zyJ{iIT<-mC-9MW*v-=yla%Ie|h43bcDNT64PIN(is~4As zHyT{ll)7@AOuC3kEu2cS>spCt>5I)mvx|hI=_FjmBrfkSDut%Fs^H!(I^8zSK7~E6ZWVajk3|5zyM#Q1Gvw#OgmeGg+}-N;W@bI(hN=ql_v-D2DgxkZ(t^~m8A25mQ*A6Mn}CXd7(05 z`kjeSlkhsl4t@~|q_8zZ2wh^sZxR1|3rqX!!fw()!4+vM@;Rp0GsY++!5vD`h3Zu)}O@Lkw4ufARk znS&!;D$t8#*cBMZ5e@Kxm`9)

_6eNC*Tc(-+FY`VPBB5!|S~D#QlZqKo`i`vuh$M}yV+`B~C}Kl}2WU{OAf#>)Xh zsRiEDn%4wqQc!5>PFoAwyV8{+*1U60^FRdJvrxiq?Xbt)oZsHoB^m=Kum{6|oljIH zLgz-nUJDXDx4)Z}x??jo(AnyPr}QCG@=CuInk6kA{eWO#&ZRG2uNl&r-w_;4UT;({ zIvLHtHeUN<;n@;h?H>Vdcz*nZZtm#k{}a!w3nJA996~aa7QRV5@J6sulJHDuU>ydA z5E5N1NumRUlyPn!uj5qO{`|u*Mih9IkEE>J3Sf>&bLKx}S6&uiaQZht@GI;vca;aRT@lQQ5=g_~+#c!^8OJfi+6ivxPG& zjh2Tv<_wi8)JtJRyV|Ah#3pjI6;&x-3snN{^S-KyvQ^X(Ybp})uckItk66bmFo5?)5G1D?Ae+(D2MZNvF`y!Zoz@aimku@!i?$Y&5qOUAbnn zqKK($N*L4VSzP!gMinyOV!P=mj1y0?4n6w9J1BGs4vhOYagO{QxC;ptQM>#)FylGV zatgM-S<~?OG%3KSo#@6qXEh`Y-bAV?u3^Pmdbx?Sh3wfv_4oijB}GJ2 ziy{ye!*dkt8`C4|0`bquzLX>&%RjC>lN*;58Xp91*em?a z45Nl8&#YdjUc@OE#41KB@Jaluji&ii<^TboFzoW^TmRgL+2SbB#?#JDRwi@asanvA zn}~D?@2Y=|n>3a+O)*>Ojp84FedF(MRQ^ENEd;+(3fYqNq9Bbs8k6R)jV0iSOW+EJUc&SIi*rwuLna?#7OF%aul#uZ$2A{Z!Xem= z+ zbS5B0c}5S~a7^t}AKf9HAZ@*NX5FG$;0#(KAP%%dCyQ(SlIKVdxKG91uc$L_$hTzY zbIx)B_=qHXs4_yMMfheJQNkcf(JZVm1?Mw@@*P=0#xM|$0@Dim0QP8-d@aI)lDMJ1 z%Djq&&=cVff1mf8X0CE?7T!88e#|+JyYff>Mc-@(&xPs6vjM|}-I;hK_>SI2s-L_j ze52wwGG2y$UeZ@efEW)ebidSMlQP#E#e-*sC>=>5JU0=F5r#|+X+w1dno@yt*bt1g zp8U(De;W-fv&XJxp{F?bunG)A^2C;?@XB@XEUg8o3s#j~DL;Y~d4?#)c_(6wsyFX- zarb%4HZ7|T^etVL%|=VGpjoVOv*?V}Mw`7zl1C{cgp_RCSWZRhMQ|97!OW;t&0aGx zT!;tOK^?OSN73O zU8D738>{LjiB3CZC+E9bNdq&Yx!Uzb`RHl{UBMNvj*|o?2~L6ubzC!m&JjG#WEE0Q zDGu~T%ev@m)9^0;W_fWQ$Cxv#*YbweEKU~fL81|~h(6Z56?N78Pv@_kU!w-}e|@#2 zl3U^lDnitk*HD#YNM5z5NkmfE@4#+VBt6#9ebI3F3;>7SQFh)L^*nDMT%<5EP}gc`JRK6`NKx-uZR@3)k(0>?SMbr`tc> z_G$f`8ZMZi?%OPN$1OEbk&=Y$O{**LfaJHdUR+fkTU$m2A?=@beY)Y(4Rbflm3iLW zsT)7r_~}N|omDo8jFd^4^I!QMWX@v5YSU+%K3n!#&8AVvSXgsvsEV4ZNLuaGO894N zX!TN(AWa|}f~9SZVc41~_8a0IYJo*}ILE66cqUD#bzIPe=jjgL;D7GD+q<;4BJBzN zT)O7t8t6?YN8wcC^jYx`VHR3dEP|d<4%&6ff|&W(UQu=w2&9SGK&LZF8TF)|w6Es0 zR>DT8qffr7Hcq)=2-Fqul2R#aNW6J*^eHKlmffNB$g6=`6djscMD@|#I1aSM znHxH;kJvcKM2p_AXqcpCDQA=tI<529@i@HsaiJGsR@Mqob4bwW)+&sOhJXDCJ}tno z6WDj)O6bQ3@6R`DN|92(KDXvLq$oy522!q@0?&^t#VI;uc2z*7;?q(wwNE~g4%{3}@G!6zVVo5ivR?ub#4}XINXM1LAZecKZ5PRg$F$W(HgY z+gd$Etu+K=8ry6iz6DRIrm^)o)5TCtQ)@DH9a@Nn^T}VHOix#`0{#u-yZ7ALvusZV z1rZK9I1YvOSZPhlZPa+}j4M!X3qCKevd^QOlg~=?CzzYa^So+pwV~N`*oRR6Nql@`0v?)3qUMWBFx7O3 zD-;pHL)i(qgcI78{m_iNFmMR+LkrL$z8&%Tv~KDSLW8B?yK0%*gfh~w;lTb;#Bw8l zww|Ay%54$T5k^#wEb`-uea~ev+k`WJt!$=8Y zm_&`)Xa@B-+bD^MaYSh#i&bx}b)v0B(2WFGu(s1pBLYPEZ(Z2&>1oqZHD?nP2fU5v zH)+%ttIA~!KYFSd zg>?7{JabY22Mw%|;-Oprd3klzSyEVO3{|xkdCtTEH~?Mh3|XNNt!Q=HK<6uxZJG(H zgMQHzanepd%J|yz5ONz456zOxaW*grq6Xmrc%ochX$ep1l72wIMZ~n$Nto`-X z4iy1uGX2_gCWkfO#MIAIy;Hr5d#ee9=a6TH0O8*d)34PCm!`NCv3e*9$P6iATyZaZ zNuMK1m13oY(>SX2{CCQ^3Vl;qC`1^N(!ezl5`vOZ(X1P#>=WpnX%mRKxo&k|0%?iE zL=#JyV9_8>*Jw`(iyIZ8hDsSVb6%^JLQt3<&>V(L|3;uW?oiIAh*B#bbmN6qhKNUe zQ1G1buvMUq1kaGH$)r;hI{i$i>w7S7$m)58Ok89e?h`Z@}}8sU1sp)J!OZb3@xkG;*>e5IBMC z^mJ>^v}%U>7+!@{Xg|O!R3E2>u;g~u{AGreP~}2ivxG=*nkVw8j@W09dJT=p#G3i# zlwgLVCO(g`NL@=SwOvfYHn$r~Uz4ev=|SQjm4{YFLND1rjCUD}NXs;=#H){5%oh6z zRMQCDNkkt3rugQZ0qo0KzwYG5Y(dtBi<_2|<0BsnP*O6z`%*Aa38j8sf* zzn520(xOJ0v!Y&6S`xdXDMN!b&9@BO>P0uEe;`%x3KU`lcbVtPb7*Tw@ z?jH|NJU$f=?y_j}6@?LxMPj7a*1!-pD6KE;n zTxB3n-gxrlIqqEk=j%V$ymCwS6rL$Mejl%|)bI^HRZAr0;AsgwgHt-ZQco!h7>__cjogOq{6;m)tw{m-W9jE2$IU`T{|?NyBld?s z3rj|-TRaD}0dvdxgqj07(Qc{<`l%5Yy&JmZd|z(o0EU6qnq$6i5K=(=q+qGpi@>p3 z&0)%ON2@Z-AwUi18$~;?Wxivg>0!C07O?jS0*ut+sI90-Dm!tWo3II;L0J?3;!0x9 z#8h{a7%;7Cf`axfd`&z!6p(X|9=4a=vU*{8NPIpn8?lr*jf>ULXw$T%J9t}Hb?nLhtMG5?=7z^K!xT;3D6M{$Yk9SI+uVn%}e|P*F=JWZv1jN&8g~u!-=S&Sf<~c ze*BC%C~LvPsfWckmh@Hw$7Dz|5hb7(K-zTc(G039ccpS(H@6x@UPZ5r?*bb*?cG%a z-;;#Fhc@dI)D?N)!lOA{a#OJP=XiSlui;l+QYSh0W+Q zz<<0gVr1K1tcGY|i5kWI%@AXg(9aP?$~%`nZZ;t0tEW!~3ERMqA*~_I zmmYt;pia~QQpf&UgW#UO_59KE@^8@3;`w*o-nC>`r$0rqToToxz4&ZyXEO~Ge8W6L z##73`pMXygich2b3u{Wl04NSXdvH`1DOu%zxr(s@WwCjU)TG7roLpwoit=wLb|lbx zEGD;z=J6c~{iX4s>nvf*9)nOp#6O}Y63jWy8O`YXpMY~&f3Rx7HWD^tqqKIjv|i|< z8qFd_cf7$D4EW10%Cf`ho7gJ*%y(}jMn2S^5!Zj<;i@A>wx!i?dQs-%IM1#<%@G6-(N)OrL0ne=wxow zxG7kmv_X9JXbj>?xu^6v^~w+O)o<*`7sU*;9o%>JTTzH9Nqe|c1QPRv@}jV^#brT8L@bKLH=w<^R72{w94I4A;5Cj&DMfo7z56>(g4 z0PL6zJTIZWTzih%bpEr~pFN)CuiJ5F$KoA8TChn9J8uQk;^@TEkl2GblEa8vumnOp z^;#36L1__d1)f{d7-Y8XqeDe`XO^6%7Uz;|LcSKzJ()3VN%h4y_3iBRkRA&q!V48L zS{YB5GFA9|(I(Ostiy`|t;9bP<_yNd9J%J0dj!-8h_e~nGh6b^rG`HPE|UG49YvZ`8PhF`sl=m;x>yX` z10Y^U_~6K6m=lUcua>)n$9h?BlK2W7(H%%RcN+Jgf2P2J-6LXziyQ5{>v$DA#tiI&!vaykDh?oBkqYy{W*{fnCT zm5%~|gJ+XU7z9X1w`9Y9qX*mG0oe8d;JJDNn#uC&d%RIir0RfqJb(T9lP10{`nl(} z=%IQ5==H)eQBgoaFu}8zWf;Wzpk5F*e3xR;K4M7vm^F3P1ol)H74<|(2?+&9!)DVF zrqQZnO@Ep538stqMvRqRwY7RwwOjFxKriDNqtLvXW0jcPg&PQ4`)GaVW97r;Bhm>` zs{S(PqLG0!s4l!V;@g*wey1>CiRyMvwwHV=$TFVAS^LiXQEUDMlc zs1`AkTHA`I!*$bqqy_PDW3sUp^NH1AO|oVQ9?IvtNPX?}xv0x=IB4uRgt21An4Q!w zf5kVe9ISQJiWg5C&&3xFpe@u`QUQvQ(Du|g>I+z{!_BdfoG&(2&VLp-)z4J~aQd}T zLxOKauon#p3hi5j4wT>XU>i}<+s6La85WVG|ccN-;qBn_7vxyVf?;5ZnJQs zxgu*K>5vMVg6pk##vdzg--2&|HD?^K(!Xe)4d!8K;aN+toue+8{>$`}=f$7->+p@8 zw|6esSw@7O5-O$o?3-o5#|u7PP&L}uVYm`57q6qp0XdGc_$2)UO#tQA0U^{j{?7tv z15y9Bt}j|kZ$t`w4gA>JvoO(?hno>}iwUr-yR&y|EL~Urj(!0Uw zq)7QJ^!jB0V33?(IW*dVmL4O}&OCsyGjEFrq2qs-`bg`xtZ-3tLF-_B!4r{x`ZvW6HNi7va(*{RpgY zFHfrZSyYXeGuLQ5qgtQxh+=d zWJ?QXSHN?0vU4z#pxsU3Ipechos2Cbel~%*RnD$q4}LYLT$E<);NAUfwb+MRVHvgE zrf4xyTR&U-S@&mU60(TvjMe4&v=INqVu3Ve&2Uhf<*is)bwo)iOiSDP`y2`N7YIgL15Gs$Pc zre)buwuGxKTAGSRDpqgT!%!rubvGehDNLnb)w@|r?>GJ{KWayc&OaOZMpOXmnJU&A zB!P7FGlr=gLpa*m$u>(0}yyX|*If>(G#Wm4$Wd!L6TfEiK`meDuu+ z>8Mug`R>^n=eDm86V8j|9F8+z%IDAd*m6J;MP1PnO}vDYAUT2MRBLI>zjtmGHWJ)M z591*8j7vz>geEaB&CHEVtwTFb0@?8FQ~H8FYm7>!dZD>lAbYmJIWi65e%CX*X`5{T zK4y=$3&Sa#HA~&Pk+y1t{kyq)hMWhn5TA(pT$uA|$U@t!S(sa+6|Ov~O`p770WFdN z)E?L2fEl3kMy<;A^6G3wgwG^vO{-)(G|c^powCsA8`m5S@s3BsK|@!#e--^s{Fm4bQiJzSVQ9V-M1V zC{enTKw4)Z!YcKm9_rA2y!VR@ML$-4U7fiswS#*qWAK4yIef4dviBgcZ(XxhZ*9>P z_k?FWDoq%iMN>stQN^S+%z@bnAVFX*=ll-jHUn%ffI79o50rvYlx+|KqLygmXfy}{ zStGUt-a&sWQFj4$k^=|>Hs>q#0;2BH0ZpT(;(x9(Z6r`B{?V9+6kV&D?8(<}+Ju7d zY_aXmAlpiNtpg;8O&gJu-5Qq4<=sr-mk~7ZLseQRv@ESd#+`lmR$$93#eoJYPA2*} z;zjo`QKvcIh^O>`0G1ymPH?RY-QOZt6v9FC2X*kt-H=1YZvR|Rq`u(|o@rs|E%n-D zob!)Zuf5HnS3u29L>ji=`ExxCQ61dh;!U7e^pQK;Og*yK4?KGVn4dj;_Vnkch39Rz zwk_FK{^#I1jUYVpZ=m`}8%Q(C1VqZA37;H5CQlK88)==!<(FwZGwgAfxfo^PT*4Mw zE&;f(h$j@LXWHMuHGJ4Q^rueYJgvqKfHmaN+kv!NP}_~RceiNiR`*h9L_6N%m~Ie`XW-Bzc*Zv(9yj8#RoZYBWTPIpX%VQGXKy|uEuJ^u+Prvk*>s#2u?3J- zB1WBMLeOQF2J4Jpo-iv|aS81xuj|+4jRf*mY!GT0Aj5dAwKOJVGJr%LjP3v|qvO&? z9P6)W%8X?i?d|-i?qVKu0J)x!xC4u((Ag;SK$?p=gx0UC9Ude61oA2KoY``iy6;E7 zRWaH-=>n+xBrlCZ_St-0nhL;tNI}(~?-vZ~0-qbR%SFSk;iYsh^n55Ihr%#lZy+!83$| ztH+~V!P-OH1C%Xt&{M5^i+s<69!H-CV8sTSep2T}oL_fu7C#5U>B5dFmktqZc{ajB zo^u*lM`P2@TpYSvlxHg*F24@s){tr^r2JLPXYW9B*@K2$-FkGZ`&M;}@IS|&z+@&M z4PXpj*u^l?y;Lxrnf=F}^c~RH5qko7J_=Xv^4uG|FsE+={+gl_%p@DOLwoZ;T_p8;W z($rt~Z0n1oo|Qmd>EDJPAk0yowYO1sK&O|@l_3}fou)G8Xq2sMKqq?~HZGWQ)a0uP zmFI{WJ`K#t?+nAz5hPbReJyXGCno-B3!~BS$IiC&i zhUZN;Yn%c+^F9ZtL1dBI4-4C|!h+HODc~s5*;sZUWd&$~8MF#aGabhOTv%@wSmoa2 zUx+5O9sv&D+bIEXjv901=Ls$BXmk;E+FDO(sbSP_$Hb#;LqHKq?NB7&5w3zv4;JL7 zHTTyw&R0OeUe5G0BsYxK4Pbzf)Pb4oTb_(y+9`iO3`Kq`rI4zj!g%apFCW5b`9;6( z)Cd3*n9Q#$5pSKH(e|Fr*DT)LWLJpxj_RhI?QK|g{q+QSpO#S+0-6?_uC@fX{^m)% zU7kOM<}e5WZomwk(abT&g6&j<)PmeItw7ERsg52l5H}L~0q|{BXSx`sO(`LZC^2o7 z8B^$UzB!NUkx(MDLwXVno=jrsbrw^XWz47zSpF4Qg@tH_$kS?Ox zP|dJ~YU~@&aL^k_7x-pOuy_)H3Yr~tz~?4#NbRP%&&j~~@q2YQ5~iBd0!x~+Q0Ijtz+4ng^r~McsS9bg z)t&MEwuYf+0EU2#9;V~+TRuOaMyy4g=SFaXg#_yEs9g`9qkf@uwnq+_K|R3EijDM5 z)5F<=hfu{RG5TW2Uu`t3L)Qu5O5-(KOWUx^0kKKejj#%0J(xsxmXwUr@d^a*N=5eW zt$voUfWL0ztqK(3YYr2}pRo;iE~?RVd_ztogf@_as0eJ?16zp%vjNsLrd_^rU||iq zU?4d6FQ@<}elfQ)qFlUO7N!94vHkVBxRI9sD+H376$+s)@IR<27Hb8;280;}7Q@Z=f=hT# zRf0NewcRYC@h&5&WjTn{v@ z_ndhQyhlMP88}Yew5|XV9`fw3&z}CPoX-TF*WHp9qO$jJy`dbj2g97>4G85(FCO=S z{Io3w0;)jTrz~%8({Bs000W35>#lJ^VR~kk4REL%&1hq{`W-B7rUp6FQHyOZ5gu)A ziLe;Lt4OpXYE#sv-*sACaDLH}pQw9%RCj3_pE3}5+BwqAHNdqlX;La(ZZf;xX-J6P zAi)sga8z=2uWaKcfg=u{@7G1mNj4sG#PYP)e{_;2BQBtC45P zYG(%)hI@ogm)35U(#}m%P>~g!67U-ImL6~V{!k3IBGALMW6nS=Do^Mu<%sr=Ms}bT z8}KamKB4QmRMb=AAMu7NWGi_`f29U{_QtcP&pY{%Za=)e?snlhS#6`7DLS9K)a9&& z3nS?`+W2jFi=AkNHjdt@x)8eC6A zYzt}4py{5CH9%EntF#3L-=?m4qdd9x#&DM%pX@lZUhSmLp`-Dp3(dO}8PqgnXl=tE+-ce*E{E-AVY z>;Pc)-@?I+;%zZpJf`W|@B`bw*xtXre{cU@(}t1^vq~DJ8sgpzATnrB)QCxj3=EV8 zp=V1)k{C!R4$@4i=4&^st8Z`Lr+t-+X8XGBz1w?xdOO3YH*T-^C^6F&q`RY&peX~0 z1X2o~Bm!84v5L(d*fOwUpfUo{!l{Gd#+0e3A$6K&7FT(0@wo@*9^8I#`|fRFFWR@V zLB=19e?DFj^1w<$FR~JFw(XG;Az}5PP69lv#yPF{QN8l%b_ZZrQ4wvJ5cN%JS7W3E z&mbC&U1sOZ^b=9Y6k3jk0u^hS@rnoV4uc2i05{Cg(e0E3Fb_@?Bi$X*0h5XYMG?L~ zaLq!mTEUhBc(KhzJ{m`KlyIrz#wi__T{cyo;JMx8=!=i8dDwa|fVL}4!xIGL!8rvk z9w~S>KkTgszwwRP?qwK;>I7ZoU7ejigwGs@i8daTIroTN zI?gKqec9rzi?{Y}Em&H%^=@0$EY?hYYF1Pe_ZpWd$A?UI+txc?$vZN4Djb{oSA5i= zu0x+6`h45xHPYWm#eLiBLNiAX92n>y=-=1>|1*hdCR43!AkC7TA=1&9xK@QtixVmy z!ZUZy+@85T$9j%kJ9h2iwQ>qYq~aOAGyK_b^$w*X1WTYr;5!oVS+^1a-$X0<2g#~X zKx+fs(?RJDfo|uT=ASbe21I#MDa6Hfi)K-m(iXJ(S;dHl%E>wN&G(C5gp1PBHi8^2 z1c-($qZ5!_Fq*L_Lt-6;C>}q8RoB_g0@zRuloTr{lX#^6_}AhUNCuJ|nE`$&?E-O= z`zR?0TEGh))z#>!pjL&CmC@o^?E>yRo4+=-Zu$rLH}t2NlOCSe-V&fud_(NAF2Y!a z=}EDHEYeO<-Ly3c!G>q}3{ZhJ8ao340)tjvLp*^K%+np*OF(=7%Ko+eHSmF6HK=uO z4^>@Lq95+Bpe8e;5B8f!U9g@B)rYqZ*Qi?vb`F>d-gA-}*@4^i(4X)Be9z~5y7yFA zd++ALyosdEr@sGSO(6~2dkz$EO+~zIXH|-!-l0Q7hjty>)xWF%X#df@M=N@2?bfwl zuC15#l%AC!>Yi4HH_?aZd(Qvs{J&oQ>*ceT9arZM4}a+Wp?7X?P1>l|W6=NuvT2q4 zBL&kropCEb7%ylQMB~g)Yn7?c=wT(;ssihdCXO`amY!3k?e`?#R)X(;_5SDYm%4CU zzoH#!dIRdNeiHwqZUoOS{<~O)&2u-;)qm;{<5Qxmsaa4c#n(6(K|GSpSdQ(GRegD8 zro+6QtqP=-=MCWlDRZ&$>^X;^%S4SJ_CR>7MMx%8x3d$T1kA+YkZ_tk<{@BA^kxcA;>5z9n`w)br45CemGXj<`n8NOo8 zV4huDcOBk!c>M7A{_*|W_SXsG;SG-=Mtsj-K7Ygf4LdgM=-yET19w4UOm$7mZ|OC8 zcnts{hF8d4L;N#Z3B&fgZnUC%#V0E&(S!jAk))~N@marc{m}ZMOGB3)Tzc^G!AtV= z<+kE|-Cr4{hW8BbAKu@+zr&h7+5zt$ul;!Kp0yR$ zsK)L-w0raJ&AT@5I=JiLnuBXTSo6V>50)HSa_ECYWtOk}XyuNTr34P_J+S1!l6RH} z7_6nts-~wKfE!z|X7c0n|j=yRDLqzpnHQ z`gi@o^|jYaKgYizBT7431o%kEGb)l8j-(NWPeB?6O$ee(#C`|~t_j@O3GvUhF3TZG z-X+eK;1!}auc*;NsPO!4l}gCycL9FYLVR6=EQnEa#`a{arC6y9@?r#9XFqz{c*_NC z+mwveSbl@K1fsC}0Ao{E4L&mJUpfmlln%w8@(${w72;K4*lUP3QQ2yk(7YOEk{qTC z%&~Q2cgOBNzx({z^JkBqRj$7qcWxZLadhR;%5WtBk#5xbfElkk9ZUPoeShxQ+_8gW z2X`Ob-M71MxNrE_@Uf9*89z2YJU%=zJn{8Jz2@M&!DEBRCXY>?nmk1&PE8!0I6884 zWO!tFa9Hcqzq7w`2wVDgR*N&|P_=lybBZpF^ww!dhmZCht^8@Dy`y_Z_k6JDgH0c7 zn%Fe)*~Dk_KbyaOer1YKAj6A?R}8OsYsFh%y!FMqUsR-)XC)ygVbP!iF;RU{+WwMO zMbo#SJDZ%~BrqNQ48wsYG~1JUVlCVQZjt1uZhHdkr0~jR;UV}lL9m@nxk~{Z699T6 z!7v<0f^)SC-+0=@*Xbg}2-jXK{hWbs2`GYI!_b211IglJ$~87v`|jz%rOyEO6}zbSKvL!jZ-erIs8 z5w4GN{JmY2!v+C$lAQ2v2hZTz8j_{K|J3nX^Gipc^FND3QR5H`Fjm*-Xg{IK5$k?k z<+96Z&)$1R;fUvdF#X`#gKKN98MoRQq()&;9Y(GRZ{ELR|LFeFlcOguoV+l3q14Ff zQ>PD~KK#vLdHz-(Uw!=i@$*~GZ<)8H(qDk})+Jk~woVOB4K5vAI<|D|=Ge^}H*eg& zar@5gJLK-2yBF?W7`!mpJJ`Fvcm1{X*Cww`c1=>NmFoZ?`_}ed@4HTxTo;bLZDQNR zg9#7V@x$DIc>kCCzuf!fUiZE3AG?3N@#Br58$)Y`BvmQ|8qs`y{rTzh(-)^NuDe*t zE{xyv4)T)iUb%aE_w?lS>b@ZdUf>b=1-HE{5(7VTNO=h&WO6f%-@;qZm;E_`?K zyNi<-C&!!R^U2E5dUV0jT}O9q+f@#hku4+VN6vSjM=nr|($9T^eWQJ&^F}Mp-Qc#t zfx&^#2Fg0w`0>V(jU)XdWk*&lN9{7Pmw#2`a+J^gRMfA-?pi(g*+LcaUu zyZztoU%Q_XdF$q_n+IATZ+f4uwSu^+h^dan0ee|G)Z=(Eu^qn(`Ur+ZF6KV7WAGW2|C%g~nPTOBXlPyD!S;T7wIWkVG|%(AS#C(9-oyS8rD}+2=>kUp;^I_SM_>Zr^)w z&yUyQb@rUyvtdtV?qv&P$U~yAN*&KcTLscAG0Fahz8cy)wDn zuHS8z@2-Eh;kylYH{2ydcZcQ;Y1M1$gppMvk47F{dvtB(wUxJ4-nxIQjLkDsXHK3u zdHm$@$>Wo^CU3pC_2Q=&KkfQy*MnUJm(7nhf4%wZHD4FgxZZtz`ugC>xD7YJV- zczN&Tz4Q0ZPn@3^oEY3OxMN_)z}Udp?y=pscHeq_>-pI8v97VMgIx#D9t675ZiD>v`n zG%Wbxdw!1uHJ#`^8@Dx)(%vvB8`W%sx&!&2Mrld4u_tR2yKsK?c35|RGX|74KEb}QKiy37i=m5>S;@9TR2GRm^d%uWpcYHas=DI)8ziN6`r_>}Maf4(Gr$n{U(G)Fm2FP;UIy;2nB^A!H9&lGetgqiJg0 zC?xth-f1e`p+sn?DiQiW3`FgUe%2%qoA69w($BgCe)#!^wLh$#x3&la9JATzXzLr6 zY}mM=vRCnfvB9~wE+4vlu34^JzOwns=Bdq7kER}-dvtE#9J0B2@8-SV?)~=hw~uc> zt`5g5>#jVx^5n*o8<%cenz%G^a^mFqle_{&M}K_u4Jc_FXKO^4Ni~ zTVsXNlh03XJh^drAk1-cHEOlb?U~{jfgdJ zed_wv>sK#dy?o~KnXxmf%RuiyZ+9;;UN8e2!~c0|GS&u$xo)7A@TPt6X%t@ZjSk8i zKU*wfJf>{pW{v|ska+3SS>GC@&LId-%oc7S!zT=f4-ry@h*1v#GD&fT+iS?NI)JDI;odoP z#eD+c01tWQHwIiR-8>FjLHRIs_kg|B59QGOe9jwlifjO|kR+XhvdJJMue??>bnE6$ ze@d)EhuE70h7eRyjluy+o^3gw%vGk1AJ~>xpn3K6-=}2CPvfL zld0}zc|PS=YR`)&FP^`6{^0q8yAQC2qPY7m?t8Sa@QkGX`|-cYlYc+C`=mSxXP%$w zKGQwkJ^peyy_vgM>pC0}C=+~)Vr-r76 zt`A-R<@zsUzl@R1V_aFgdw2Jq>pl1M+|yf6Z}r{kyWDqq-{pOM`#2tIRu@@T)@`ml z-VznDevNPs>7wFT5ul}Z6OI%tg=Q{CMze5-K{E>Nd&kdQn3%~_0NflMpT6Hoc@bZb zl5K|@yIr(>+(9r2_x#3wBZq9FGyv>8?oA#^DH#Q<#HHhWkj9xjA>}J0hm;*85$vYG zk(60yKdYG6NCFhG1hlsYpzRqH!UE7RhPt#fE{c3`zvXcBoz{; z5RRsIo27Sg^>(e@SC;I^hB7vnjx61^bl1eLi6aw7RyND_Bh{y1n!1A@ADnxTlU~p5 z_Q~y&`zH5o*;hI6kL)_~!I2N%{6GyTYq8Kg6SiR!qy^-~Pa1<@txy4Z|=PL^5)AcFR$FWf~4QOaqq_I8>NS@j$Qrb>M!5^!i#Wh$FUu^ zcig^q``YDeC{?8yxpDW#)f=cp{SaPp|L6NR?%%j_}bfu4jL zemwn2>CQ->NTA#PrP-nbX-NE;XR!P8?!DdB5zmuG4)*H*>5!a(@qu*%^0Ug;+1=NT z*bW^S;vOzAIsC=&q2WXO4(%J-H#9O-t~riBJx53OA31o${ZQr#0H`!c zTPusy)W+h>Qg?l{{-Z-59XfjG=#gd_Jv!Pyin;e3?m0Yhc;fiP@v-A$hsF-|9I7O) z97dYmBh7O7(BVCYt51rLNKRN4-m@JaDwfEOy?*ifw(Hy8+Vo<|%JpNYb=lC}mTKLAAAIgzs&@0H{5)7lm5Q3>xOsj9qS!CHg@c%V?RClsYr;O_%m~K;%Q-tUyIY@WbesGCp+W6 zM!H9yj68YvX(zhoc#9Ww}-wxG;(NUVgy>RJiJmy<>{ZH{>H?OB0uWJ)LHEQ{)780zk7G@-Tm(F zcRRk@v0_K1vjR!V-E;Kd=jw?Q9cJDNtYg7T79VkCWB`UE?ASj3->5W^1{yz=9fpRW9L>!+fxFud``#tR!SJimZG z+?~2Rb$RMC!Mdr_={wUGrY~&0u=U>7dt~Y!_5b7bAFtoO{+nB`>u%RT*TB7jGVbob z3f9U?&;x$Wk!H-EkG>xJ=V zxphG>?9b1BE@l-$i7*@^&Bmt3wvTN;xBc7?=YF{R!`;VsOJh5G;?~642}x?p?1~@> zTKxialffR{h=dPY&p5<5pW#^&o&$3$9|^xR{kHS?&as_b&WiBl_b0y}_+DJeflm)q z09D_*zH@yZfoo?;-;%y>`>GCZJG4zO%FyRSSB9>fxN_puiRxw4B*SjRv= zapc62@gw6W#_Nk*IwR2UB3XU0^6^TXH}Iu2Kh-)c>*Kv1Jv(}K%~`JZp2?ociAgXl z8=+@_hCVcUr~rI;`0$a#b;IN1T(FhUwP$@XF^-pmoAe8f9T_VXuKv6``0mDcH=f>D z%9)bibEu=wrPf@!W9bJ=KUny|!VL>I?B1|@-|mW{S-8J6Bs$c!pzA=_f!zmoZ`@tE zrbUCD-hBG+r*)VVe`fmWTOnZFMtT@OXo4Gv1>g$NXq<%LjWZJ*o(@U8O6%V_}@#~BKdGSBL{Le3azw~YHqctb~XX1Ze z{?E%7%_6YjKhOU2{6A&Ttvb1CY*krdzdrr-*{{!jdG^b%zx?|0*E)}bW9ZhJFdPCtD1@Y%ncgY`tJ12 z?VG!MZV~LX3&;<)fA{I#Q+EqL2m#fcfN+3j6VlQG?TCM^^O=4Q&A^!v4+ms9?4Q@a zzkmPW{=w0~^4^b}tmIL9j_f(J=ggrq)k*!y?oU>Kvii{KL#Ga%+J9>Q*ZaTT_cd}+ zF((@iZuoM;mpi}Qd3opM@yp|V^S|+u?6deXF*em}nMjXHT6y zclO-zbJZ)`gCD)`QFcecmBfp3ui8z89h@@QPD6HJrnOtR0I?}>k8+x6Jwfg zm)0Jf^Vi>|+l!(OnBf_e0h*f5o)_==u+OKT7o5I-`2Cviq%fK)U$b)ZI z`Jh!4{1y4F{?4=qOuk)p&fdLy_ul91uUD^LYjwBv#aQRqxkPM;J<^(LQ~$i9Tn?;r zz)?rU?D@-{t$WIaY=Uv!K>Z-z#GNnhJhJo1=_9A7PFJ_ong#xo?f=-me0y2d_*x+L z1SSQ6DFMY}XtQYFh|R=7c_!F*KV9x=_j6aQdv|{c(j$L60_d^#@ZP0+YoVVl>$beH zr5t=qUS2Y`WNi0X^-|YvU;E@*3yQw5^@VaWQc%i*e7LAc*V69qKPs%FHpK!vHJ2jJ ztUgg|DlOZvY|}CkE)|94+5>M49q0t{p@WBl1BVX0cAz4@RJt8|DopE*tvrq6+s3y& zy{#M&B4Z7Z)&_5SwL)dGKG9<<*)0~VSg>N-iftRW)p7#b13qF)O^CDo!{enVGm0%< zSr&4soVy_4O!qP#;mi=r?C5Vd!Pdje9{%~mW$qx9iDr66z(g&DzVXN}i?kIPGctUS z2_~U3)aHn5CX~Ui@VWF2^7;7Z$JZUN6$F3=)@J=ILhCZ~BX3-_ar4H~^8?PT{6N#& z+BUR}ZU;heO#KR`z2!bMjl2jP;JHh1j>%UuDK1%R7Dop<)F7hX&rXj!VM4mtelvb* z`@AIk()HNcTJ_0+imTT~Ljn)#aXq@OoPZBj8t~+L?%+z9)m4xRa+K-z*;Z+vsr;<8 zn^tc+y6NbJqZcMFOiWHxJ927pYVWDN%lFnF!p(%H^kPeN z1l4w~ss}C$McZ_86e6c=x~!g$aY`7jhpZUECw$jg=90i()yXF+#p%>gMo7r$jIud4 ztK(>(tl!3x6NFbSSLMu4E@%J9fK6>x5NmuslcIwWiAw$DI&8j|VP{ad2DO=oB|Bj? zXX3(#ipt7N4<$Epzc4ux+ky1KqYP++bA!^KkDWcX`dC?Mz^g?M8V|jv>>bY(XGlOM z8^(FOV%A5h0JTsK8=qfaGi+P`R1ii-$<6s`+lw@fX3i?HBZY@-ee6ju;ej0&dLYP? zd8>eGQTV%MhIIyXX@3ft{Wh0}%nov`$Iu_%y{@czXHT9zfA;*j^JSd>@XHVPeYkJ! zKI5^5GYQB1>oeSbfYRhMqZ_s(66*9wm@p|65)?&_=S5=+V{xq6UYU0X5k6i$gf`)W z%b<*UZD^+})g$Eu_8hY%GLM5VhzitNk5c(#X=Gp&nH~GBewH3qtk9u{PsgJwD=!8Y zNnnq~d2~QJaxyOidm0tjl_@QS$O*ZZFP*peK@#}Ev7##oTqP+fuHzf*`B9x9NlE0DxK42h0ol#vp8 z+o@}wEtilArG%8MibAp#-P;!ClWcyhrS4yUN$d$r_Jwm7hLf*a%Gkg%;VH?*A8ORb6gjx~fMZqS_QH^OY<5|2KeM$3~>b867G(!R>{7mNX*_A|P z92rHLHb~sHdPbf0kz&R;{TP838(-D!!q`%VFlIyzN9qyY7Ps zMMA0}?dJKD#OmudQWfvphH9a-a@-a1Mk__yh+4dJRkg9W=w_)-(E+5$1HD+B_ncG_ zDWNW|rf@d^l~6FKn`^uij2d-Cb8e1nJ_P}yQ*TXOn!5DWrRqrPsGgZRbNI~RR}Nci zt^%33F@WsV%KNVYlgZ@zqubQ$s2gEe|8;YYk4oc68yO5p?9|0rUOHqYfA|jg3ve9| ztD$Xjn|P`&Xq$6b!|lolz2f)63IsAR3L+bm`1r4DlN1ZBh&tmIQ4V^b8bdC=bt&3~ ztp^}WN!ucH+v2T8T@b@Bnhp;WN*5W+Sj>%`{fKebB?``Aw(|D1h--C$8wHI65lTO6 zn@A=ww>ew1sh1W#R8Clpps*F;o>s;1awAu>V}D88CRb7t>wPh1z5n_9>)xl&R_~aq z=^6wWMJVJGynV13nQTE9fZljFzrHk?qsyu@jSMf`_F&~eyf0QxAl6DMvAAVAu**z!s zus#v{s%@mYow7|oS>ABk1^CL;d1>phG_4`UF`z{tC`sE9_hNJg1h$Pva>f(w8l;WH zb2_83LilL5p}o6AGAAsf4j!oh4Hu;3GzTGSR}7+HMB1w(WO4|PfqCD|K0|M&L7&qj#!?1(`Ht-aF@EN58x-yM9`Y>(~X9&>cc4`NzkmuPS z)jbf{m2?-iL;3@FZh2`nbQo8<9^rysL3(XUrKo(Z?w~B-ZQXTb5lPt`(~Fd=`v-cC z5M{|{ZlREnd{__Lm!h2p!r34e3k_KAWa}$iU)}oZu2;n`?}Z(EYm6pIkcmRa-yBnn0(&sP&F{otW#jxV-+rIsl=KHyGd&0^nj0PKIwGA;vg_kfe%e z=!^=N9-v>{Z-j)daNm^U3r6=-LK59YPVnUxm2dv;4%s_|yxRPhkXy-ll02S7)Cbi- z{bf^P#n!!LmkBaT%O6s66l?LhOhO|Fi#HD;cHQTZlb`b{$oOOvX;| zs)}=M8%pp-*Kn24Mp=4qz0vu2Cs(-`h+Od1Q72mGs7|y>fsm-IlwMzQ-@12${Dk%c zss*Ww>(O3Ht(h0vqmmZiNMMpViL_!=mQ``87-ma}jvW<+&JFTQhf=}Y7GWO!+^0ur zH>`>WmaEgt@XTs^bqia^kgPUT4TuuU2eKx?;Hkm67B8CcA%5abuhqCV>!w-9mMP6k zWwj_T#oDqRLX2kkLDgoGqn|j}k*qlkC6v-pw#czEMY7$o@RfOPeVw!nlNi2@Z5tb_ za6T|@kY(EjS*=M4Adc`%knCEH1c{!}@Y z!|a!Baa}zv_{t@&Vo&tLLA$1T7;Vl%bv!rKaK#ukb6Io}NnQr>6Y1nmURJCep_vp2 z?Y+*hI+`T;uX;pMsWquA4>ZI*?k+hiQ-dltit0zTt(!rr^0b+AibJi&d7eCssu(3o z4h~W1k~10P0~If-5vAR8r;u1?T&_Dors{Z5(sbdqbG^Z3D_j0tS^M*k9<0y; zBQ@fcsDRP^!(x^2`kSwVQ5(R6oE0xhKbVIg)LpxU`P61Fp+Ta9Dtcxoui$nt=G4;6 zA`QT3@PMPC&vGF2#8@xhTS-Rrd76Fue{|4@JNeVD8Ukio4})Hqd#E0x{nrzlD5ruSTix06Z2Bt11ZW5+ z7EgRxA)EtFWGZwZfFTgdU}-`S4iwmvB=q6)vlW*1?=uy8A%-U~9w|t=Q$l%keMVQ zRayHRoq?<){U{hsc9xdWMQBOJ`2c1)aq-5*D;BR!Hf9FYz&>Guv`lseVQA1H(VV2fyAwevpjd$Tnr zf3n{21E(BH6@)R$FR@{M>h#r7 zT)TP=X4+=wYTHJ4`o28ZXRgES_1U@Exf^pg;QEbW%IpYk%+{$uzMFG5VfN4*ziHhwp#*9&UVpWBSJQ=hGFYc<`SGw;ZfENei@F zX_a&qklZ_rGz^+wY;HIQn&xg^a3J<31D2y?B1tf+a~97Uun^KmLrY3HEL}JZqZ)g9 z?47Z92JZ|$8PsBYzujzFg_^HJ1rZxhvt>+RM*v^3_aa{S7~0A%=TxHIGJPTw zF-tMT<-ttcJ=FH4GEeB)CC-!O+InGprerRI6z8}#gYlVM)}$e`PPfJpG@x5{iD}xr zeshhX;3Q4;Pkf`#Sf1mbdLS_>+~9XeT>OlbH}Y;FO>un7%wDXMHu6B4e02eQkPXy6AW9IzARh!556u67ld25OkD;sOT83 z&DOOuS23|N+`LiD3>@Uzy1wDo+%5R}*4G`kzrGE(ZdW?Y-I}{TSN#9i^@=#1`E2Iy z%-uV8(fQuD_rCq++i&3ZH@By6Pk%c7=|`V_H2%@}&T)ay<=Qr@p1x;>L1ny2By*xZ zjQC(i16n3vW4Jx)jEfY+3Q{kKZ!Sag$^_7i0D50w*!J?rN)(HTGx}`u*yOFrdj6|( zS9e_9@z{=115Cij)(oP6SSJMkn4vBZ6oie)nox>_BBN-?EV#nVi6*4WC~RlL>Nr7= zyrwDth4RYUrXVnA&^;LP9$ip#WRcPaml4srXOs*UB=fj|7#qqTeNPCoXlxU@SsJ+q hPUytZozg=|CoaYc{dc_;oqU~iU3zwj!OFqpe*umXa>)Py diff --git a/find-object/bin/multi-objs/39.bmp b/find-object/bin/multi-objs/39.bmp deleted file mode 100644 index 38e1ffbcbd0e7113a3262a14956e966df93842b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 137954 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 diff --git a/find-object/bin/multi-scene.jpg b/find-object/bin/multi-scene.jpg deleted file mode 100644 index 45a411a5e3df5e59d118121e2384d67b5437db4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55822 zcmeFYbyOT((=R$O1Wk|t2@o6t!QDN;;O_1+_%JxZLrBQr5;DL5!QCAa2r@VX4;I`B z5Zuq?`M&QxvhKO-o_qhh>)o@uSI^#6)%#an)m>e+`(gHB89=BEQUU?c&;S55)DQ5m z0??KB1KR@tN=mE%Y{1`ca1_ShApiwx``ds3Ks*)z19imB%f}7K{?B6`Zf=acNB>aD z{X_Sc_dm9W6+A{qFE0;KE-p7HrF8yDOKUl?N9OCpQ;BT*}YG%EsBwi`LrC z0qiD0f7tqso)&B?L2n?S#;xWdYv%}74Dhtm2~gLy32?R%v89)i#1;1w^>g)bwezx~ z^>cM`gNph|(ElS`6m|T!n~R?I9}+KT33>$`FHbuwS36I76r-oDy{NVv=s(#||0L-D zbAGzZUvm zn*A@C9**u_?odbf{|))ShW{t&N*-P|{3s2}x_jFF>oj0g=RZiHUbbBSBgH?g|A74$ z=>Hm)_w)L{=SLB6@p5wub8z!=@QVD4U)9~l$_wo7CWpF~U>E5Bk&OR^m+QYSyPO@= z#uEhsC6@ND8CY4nd!uIeci7fO)ZX3G)yhi}>}us;$K~W<=OE7Y-+OVzx&Cte4-!yJ z|8${j>F?pc>`@Yz_Wxu1w*Xq&f9v4iI{52G|F(mF>)_vZ@E;G9fBVA!KYZc8N4$1! zs4&+T70*7*17rb@fEXAUz(=UvqeqW0u^wY%p&9`m9?oMTf~QZ32#AP?pHV(1CZQlD zA|j(BqoAUqp`jsuPR~eB%}7a2L;Y6>8j2MQ6AK?38=snlh=lt8xIJ_Lh_KO?(L;e~ z^Z;}sG$0Y$LpOj170f?E`=|Y9d=EfF2V$URiH(Dcha#va1fZh3C!?iM6b-=piJ$VF@|d46my@Nwt3*G4fe^hU4Hqdrn49@sf%86$>lBfS{1D zh^VZbJV-%NNm)l%Pv5}M$k@i#&fdWh>;(1l_VM-e4~Tdh`7Y}Hhv>wl>mF)IXyeS zxV*aliwg|^{0~^D{eK|)UvLqjaG|3v3kKF-TxjUNe}NNWJfh>ld@7@bWd$Lo=MBRq zd7Y3`-HF4%r+q|f?fC=u86*G7%j3V${z3Nt3|RR8D`fuy_TO>M0UiU=D7DuTt|pYaEaB{mH0?9du!x8ef_gF9(?i9O7H}TD zxTl7e8bgwX4lG_&2b!e*UG_OVbvVR-Piu{8H<0dTDd^R+jSdz~Uy@~BmJaW1!e~}$ zUa8*r#}VTh*(bw*=`Tg-8SRc*aZq(&)6Q!`v>gqtu*27tA|xAU*@W4UNeUh$e-lm2 z<2EAc3V(;*4?b%45jSNa`Tn-eBJ0-eQft~ofsTRxE>gxP%nHl^J&tE@+XrG`)B*bb zjJ4452DhA8JZ4`@JF7_ZwWVq^!z9F=V`5E{DM^OS^*AOSk?!Va zxQ*5#*%`j1FRQyNE1Z}Zz4$+O_HbA4W!(Iz3QbCaI|eH_VU9TJ287#U!=mWfic{!BbDhXlpvxxD`vtR{l3u` zTA*ttY}7vBHorbcFy2bV#?YxPxRT)YTykFH62AI%KLZ~+-Et>kbc@Fu`_0K>!?@l% zXPC{Xfb*kMBlqyD6fI3lhvtF>lNXwHfo~x*8;3@HpR`!BPv{jS`~lOUH8;A}#9Wfi zd!}>6=GWxqz8uDlX|Xm}u|r{3dQ`^iU5-kOJUhn5k|{-od@3}b=o4aM6@^D10LIM^ z0Mfoc>O`NM9a5+s3HJ--v_BeH$db9IY)RShNtkye2TJVz&Km#)*q3hW_ljBYQPwLI zH}Ak*3;9|yjI-w@@Kz$8|MTFZU8*Wug(6wmmZOIvu^MvJ7MCu z;{Cqgo$`1qUfQIW$grUuMhK4{Q^(hjo9hw!COIMpy5kL@b!c${y-`ijdKIjH@S|z*v?%Tkow3@a+~> zITQZxc1OGm24Sil0`+f^T(Z&X1>vBxJ)K#Ys_1EvhV~;3Yl6&63ZV6$(~d%$OE3eL zw=nP$4$uYok{pMr0V_$?v$0~MNH)lOSt6+G&Q=t64y7w3Km`2DETub38B!GJ-!BUB zGr`Xb+h1)v0^eR1=cxs`Kk3%`^rurN3{k(q3vR@tyPIGV-B1gn?IZV4Ak7TS*||`D zGjH4f8%w}o{JTo=N%uKg*g{^Gwln9Uh6l9HVbY-0DHy#ziNoc_q)K4W>FeWfjTl#A zGgF?96GhD$bg4fgJXzbSY9e}_e{k^&kw3w~`i3Qt0{Ie_8NocB9?iH4(mn0W5V8dR5f=F%d?b)A0aE`5yr z7_NE@PoTjn5`Z(ktkKxf=h!0e4WTg3NgXO9VAOs0M{(vwENkAr<_RKbhjIh^{L5;y z_@|e#8j`2krF3%v)4>6-lh;apbMoAr)odBZ2WDGuHLfWry(-0?D`OLkpe#j_YKCK3 zizF|5KTtampV^NQ!+SIQEXz6YNyj2d*vZaZIVMKn1AsL>#q)I+SOT1Wc}mi8*-tg9 zEWP0Igs!41E#@Z`OY@+^xA7#26Q!)+6zM1)k^TeI!jHcN)t+u`SWQTrm`Or2EN7_J zI`B+Vgm*)XAwQxO#b1Vq?J~^_TW3E-6PTCtr&%+HE>F)_h9OFv$8yCCU>O&M96ir- zeqB=jt_d+E(pg;p#*i6Bs?nip-rtV|mA?oFa#8LJmz#fAh&7$7xr}|303tsbHa`B4 zs*>`a1n-3@PVS5vE6P28=S^OcQPmhJEPW0a>dEwR(Cv2`cBGuW_wFf-;QY=RD zU;k(o@bNTL{H@Er;34n*mCBo%ASDeG&#x`uw!Y8w>p8oha7FF+aXE1+4?A)#KW?dI zrecefv}s6dwTZzrV~Yk0A?vwjz4_cu4ofQ2YmaQ2EhQf3(wvQgAM;BQB>F?6B145= zl1z6%q70eC?IQ)F+9v6$2_FmqCriy1B*^qm&JY;Ebf)_o)fJLQRL2_A%5`EV8D2$^ zk_N$B_T##zPGEiCZ9suUeF>3EWe~Rz8sQC3di-OWb@HZ|FRy$OZ zJsL|(^ht#x8EM|rO<#dxqd&sAjh7na7WlBO^l*iBw%Sw|KKbqD3Y!kX^dR&p>?y5&!(<++w{YOEwCL0BfHe*2jjTH?k^ zFeigWn~Nz|v#TH*LIrEniRU4#9Lo?5lj!xFrsWAGV7aG$%f{V#!<@_0?p7UtF}|=2 z>$(btNh?_2On=8N-2-56ynR4m(6`{Zxd+G@fBP4*uzhCUC_KkQ5I=2Ld(4}qf+1BY z&tWe6Y+H>p%oRToB!O1J*Lx)jKN+VpbK&)W56wc>L%s^TI2k?w3akq?6~r?0ma_`W z72-99a87&B-ra{7+YfnSyIX1Ac8inTlU^ze0C}w8D1bq@hnsS^l z^xY~P8_2(JNeqMAKw>4fNyA10y$dR^n35B_wJmK!!SB`2BtBhFXxhLLeZd!qNgOvv zTur|`a^RJAC`5X8S?s(pHicsSo@6=5kBSH^q=+*8BMD2G1^#0SDwVfLX4s^e#5!)P9_1RnrrJLO~ya1Yw?b)sl%KKHsn zybihPJ|q=n7#a{4#*sg0qS~h+y%2q%5FA`rGs41IW6t9W7bCVzK*$+VWpmjLg~5QrNV5okX31`Ym!&%fK4NXN zvjnCP3++8gyc#;hl1EgPC6Bqxv9tR9$OM(KBY7i1GcEHU5)Lo9**~N=vm+Y$%tN0? z6jqEWC_r=FuP#|lp1@D>GKn=(2^PP{Adlb}pEvgSY{>hNr2M`r8_B^~?#4R;Tm!xD59@jwT%Wo<;i=gr5!Wt! z3V>>HVwvAkgFB97q$-t5vu#4xV+-3om-y>b9TV0RESs5u`QAiXpQv^VvVY{)MOKFv zw)5}nG7RlQ%n74qD;UGn0V0(kd0^Zie6x)Tw@ha+uALdPMNe3w`QB@xq7Sm+BNhiZ zc8JrQ%I7g#yPJp}J|d#A7uhd2u90nzaQKpNH67=wr~>7DsSt4>CLL5r+T|C{BhjIV z97%MLT-+N={bko2MZ1=7yRe-;NW@wZu;R>uOq2=|Flm$SR$$bcK#Rm&D;afJ@~VA{$-q2ea2 zc#G;rS9IO|1^dAKN&hgP9<^K;pesCtI<4fBL1MpKnWt2gMCoUy#UF6+Q=^d@Wipse zxdnnLqa<9>eZ%k^P-=TUeb9D8Pfp`yBj8P%8fA~GqzgV{?-w&RN-UFQjWiEpd-h$a zoFk|0=n?iZauCDH#v_7%UKuvYOtmhI>w9yZE^&R&; zB_ya+{+T2NhQ^}L2pyekF@3}ty=}C*HZZC7)F?tK@5CeuznIKE>@dkXS3JZ~UHR_%K(F)9-*Gc#J zjkY$I%ghKp)E2o4*1DQNV_>Xg9?#haYCsQEpCkrh8EdQG2k7wiUxiRGRMGu3S9uHv zGYIb_$#kCg2&BUZMq==c`F18U7btkb_N04-sTUm|YfvwOV^_B}Hsggz#((yWJQ5PO zq~?<@lXz!9G7%OJ7GWkI0rRyM>P&~e4hJyBd+;f!Mo4#%5LabPeUv);7HNRQEUaF& z_#XPrMz$~@M0kCIB;)LkMcwgKm$Mg;f;}-+NMGjwAF%rrgm?Xv%u6}ht<}bgi z_9IVQwMR;BzOCSFkm&Q9?@HU!(&&2tL~>tVbU8uJ_wPt%!t#VTn`4&<6k-|HkoQl*aAXurtz=2_!G9PF>r)0`};|j zd|_;xc*w>TtIS#)LCENBNLXb$GOZBfY0#^?ZSi-;<|E&mPZKYHb%loXDf3)SAYs5o-Lzrw1{od6ED*RkZZyReAYr!>aaTC9if>$3rfB|pe4Wz|V?vq3?8&0U$YJ-rz%gb8IpdVJaNJQ|y3B3q+pj90KQQS+ z_cr5>OJWZYb&IiGF}K&m(e=d?r$p?VvKiS@XJa8TuG=l|avTO!%f2o0#vPaOCgyC* zT*Czil=>Ntzf5CJESx%w*ZkQf?NDG8&eiZ9WI`>z&#h5}a`S;VL<)O=yZS6Wy8k+H@ z%ZO&QseipJ#(?@LJOI8rS!6M1?I;?(pKrQn%3{DvDATry_mn8<`SJ~(#nP+bWX&HD zs&uXWE{Vzm?D_Re>vn*7CggcyL_jQ0e`&wC-^!M&Q$S3jBW55mC`hbr^5@@+PsYILnWe$0#AxgNyk z9XdbVgtD4M@s@y83B7MA-pho5J@`~NmuK_(1OST>Hkk(<&t;e=#lhe3F-;UM8nC3u z4Bd5N5e252y*w6Yfl?dHAz4a76btRZkzj zv`^P)rai^v1yl&PvT?-F=h~#!M^VO0Q`eV+N!ZKC;zr6%w?%vL2XQY^s2TY$1F~H*e z(OVfBzRVOGzy38xbkb=`0hhfgybjQlVY+!=!)*kGH!SZ>WUyI@>N; zc*~Y}MA2_kxwN44A|;KgRX6FP_KvOeqjTGdYv z&FHJf9zV6e%4N>u&!pe;wZA*Pa zljfV=3|pT5&f8KDwj1Xgy+Wm6*O#&+<#=*wSfNnU=TU9$Oi2au_WXNF-TqxoVzEjB z{8@zVj8oa)Zur^O8Q3AG7U`ABjis!21WI5G4I7MeL^ebf z*0%-tJ$+3++|j#cu9NMTXvX<_b5(d+LxLQenXG@ugUzgs zgm8ZCZ?#jg4|Rh=$4`>uT-}Vy^L=nbbBV@orXpP3pli=h=|^a z#a%phK}dIeCnK25jYR0p+FY@tXhUwHn%C;oZyN*yIa(D~PL6`~WSsxoWzVVihrVF`c$Yq_5zKxjzN<@;6s~Cd+nD z^J2~#D8CFIRe(~J_a-?r1dVM3+lxppE!B@+D)fk^WVSUNy1D6#ALt9SDhi|*I?WYi zmdg8jCiXwgNR~~y#HDnbWp;M*zNa1M$IDAy5;HMj!U#UoOyu?_1Kw_yc2zijC7nQU za4xB&r&9LWu;N@Nn3_ERK6vj4klWY6&zFQe`>EGLC3y5*Zo!o%%Jl6xUQL6HML6{3 z@~`r`;frbJbkkh*Cdihygr(PhRH3K9dMn9gq(q>7ySqxuQC74}eRJKr?`KVqgtul- z%LvGCCECZQDqMk!#<8AQLsGbEyU+GL7&b*l*v8&S742~ERIx1@=I(3CeMr^j%UY4} zJDgu?!g_@BWD;T?_T}gHH>-N*qH=Q(tdSFq*7bt&kA`Fl=X5Qlld!o;HiD`BN8vbhS?)n zI}%PFUr5yIbMTu{>u_a~;7|*GmwQV*x^#U;^=cecZ(u{FB{2j3e1dGdFR`XrY7551*QTmbL6)v@qoc5 zTNo@LRA~*t`Zd8hPpNR0JawTurfqfJ*KL&g6#hG`VBT<1%`JBw72&T0HSenF3c_i9 z-^y?D`+TvtONM25N{Kq*nxN`lg(dgj@-N{&4c9LeKS*R|hj9G-B+;yRwTp9#p$=$D>W+6 zaaXZMIr{4KZY?B+t~D+Eoe^Z_(Fn_U6zkN2TWJVx4dMmM(? z2a9&{JkLMWp?F6#@oQ*Ywj{o?iH0WR$F~%p!3zb6(zlmf!|_{}8h;S4W6yQFz^y2iHIQ{AlktZ1FDEq`SEiT>AwTyi|v#jy1*vbfCB zU`m&lxH;@>QI|bG!!+GC<+}|tW;)cj`Fm}|s1v`mU0bTgc@-O{SA(F|n-=&-mjPZ| zAIUQ<83PZ)#22JhAiiJG{mrsen;IZ;8Z9HWL5NQM$msXa_d^&66^d$)A&1W*R|@6& zM-?G8sJOb$$vG9>IXocYYQ~l6O2>i!G^wik)zj|oxD+R_1G>EV@Ys~@1HiQHhz_}? z`l$LT!Y4-{hw)tcqo%~L{jTgCgsS?sRJ;3kgEolQnNNpY2{NhY61u+c{z<(t_1Nmf zm`uoJgfB6-T)z0Sv+YKgSDv(fQq|X2XQJHV2S;wpJHPiYY#U~Sn@D>*k1h;bvurEq z!!%xeINPGs{;1)hbS5OuT=L?OU>AoEE0KA5t4Q3w?)1qw+m@%qaUvl!so8Z$b=1`3 z732>7j0xx&2rkQK^Hm&8Pemltx!Fqi^6&=_Zj=!&ApEN3i{Jtu8~s z$9}1ndK53ehvM`?O|OX7(OPMY(UDEdi9CDSJCffwLEAG!I?Bg#__stEkg(|IJXc$g0@@8yGA!i!OqrmnIjQQ#e_i1O&GKg-eLGE;6!CiPcqF3O<)T$m&!dCtYm|iZ z5Yr0}D6&x5;d9dD%{aszB*5n4WzI8snyG$s5MY+{^ZBM6BjMkyNaxaE289*7AA0QP z(rBjjaD4_5{_2JP#s@&9W;}0IgReUnCj7O;7lPa<|<_ z?|iGIgjwx1jL_iZA7c$XqsrQ5QNdk|FJ&0`VG4{o8SCpnt*08)QE-GAZnHoF{h=SoPK*alE$Lu^><9X?e(#cUsN8LQjM1)+gsQMEz-Fmhtt1W%TP}K6!kmc&U0i$5K=m z^HPG{=`rszQFLyR!k?&J-N`t|!Hbtx2U>%VW2h(SB%5=7mXei|Px)D*<#S04TR7^a zCCV(YNqtuhsm^7tP;<0fmtq27kqi7(3oIJQHL!l+g^|z;64lWs!5{?bS|hY|9snF6 zbgC>&A=6c*^$GDMt(d=*^P%=NsW0Cz9_YgbrT$FS1gDro8zb0=$4eM$d2`3;K3ph> zA8*}MMyKD<1umLql@;DPt@6x~NviXr6)MrO=8M98n=U{ub1&OU^p)Hw1IU#~Zp=8B z76lbjfLRvCO>~S@Bi(Q-eOQK|^jUu38CLyUT+-KDVSDD#HJU4YQ{aTJ!1kR#R=IyA zj4U%?Kcqn_zR1NH`efc6>o^Z1WiJj{PKR{Dd(%dQte1UF0Yx;O70{9~7Z*}1jY1W1 zE6J&EPt<(yPAR%YBPQnHvaU!53GmM?;7JdEhOMtevC%0D-_CfjIf43Vw1!A0KNosD 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� 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 L+xpZk%@P0Ei-O3c 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 72ff182eeb74285c03d07311bd5e060304f66311..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33709 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 E0sYA&y#N3J 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 17accbfa0822682f9da0f99a7c48d1fe8bfd82d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32038 zcmeI4J#rLD5QR$-8~_Y_$=C=??6ssd_6XSE?JWjQz%|xdTe7&>_Exp#V~d>5&Sd7H zR)=aLn%DJ{@5?G>mxe*2l&kWpynbEk>$?2)s+2$5-SuPp@7n)Q?R)?J*#51Q4{uAk zy?t!I`=gY9e=p@-Z8nSRdR@(b);TrKzNTrqdU$yFRIhL5`r5{h<6q5KoBOF7Kh*YQ zu5aCVn{USt-S~(<-Jh|4|JUEBpVRv2pP#dz-%_UOlB=CF*Y&!s7w639`RuA4-HT_v zX*~vzx3 z`o8MP&j0>BTz{Wfo11@ITOxjKZ&J@Mj6U!Fo^eOr{Hw>4=I`XUwm+kO*54n!g!(z0 zSvPZCwHlwC^S_Pt&(Rt8nf+hQKfzqh|B}6_u@~nLe`OuNEdR>P!mhed>K^Kc{tDug~@3=d?=womTs@U$@cz{=2&K_r3aT$TYjRN+w=eHuH#6D&CPQ znRrD^J5HQZEyHUonRt0Dub()jdMw+oWa4ERQJXlWMoh+)OuX>UDsf8P1DhO`>&6T3 zNSUwHh-t@_Y`iSPYcpS|9?R=jvhng*wx9V*wT!5(WaAYv8E3vy@y@D}jn^L7->be&#FHGNQJUjaS5EocT({JF7}I zUVC7ZBRMM-??{zQydtI@Cr+uB;kA`aygZiIPn=RcmhD$E@v@AlO`K9ACgVybUU+Af zIHm4^O^(WSyta~wm&fw@iBqb_vi(XXUX~HHiBoFCWL(L_ z3-7EFr_?>L$x*p(yzq{c`AUtLc3jEE%QCz+^OfqcynZDcFOOyWnXgpKh}udvUJ;XV z<|`HNtSZ@f?SV~>pI!aZ2@AwqMD_%QB)iaY~Jt zj4PRV;hk0Dl)48tIV#tU7v7OFU#St(jw{)CS%%kUzEVAw*RN#b<*{r(^Ob5DQCrEz pD`GOve5K-@RV5p*J+R4v|rW^{0EeY%>DoX 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 1bdf4b6a35dcc4038b9b38ecb2b40e755b8d0588..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32038 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 NXZrsDc>lQ=_zwXpb=d#_ 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 ca95d33254e5e3a62cb09facf244d1307da7214d..fcf030f8c6b33e2020d64f0adee8d0d08588f214 100644 GIT binary patch delta 329 zcmZoMXmOBWU|?W$DortDU;r^WfEYvza8E20o2aMAD7-OXH}hr%jz7$c**Q2SHn6Y@ z1EpCRj3!TD5t|&uB0Tvqi-rg*LlQ$NLncEGLrPjoadJ|Aeh%Yi4%TcYRyKxWhC-lP zbxsZtiy^bG<9X&V0|4l0OwRxS delta 173 zcmZp1XfcprU|?W$DortDU=RQ@Ie-{Mvv5r;6q~50$SANeU^g>6NQjleaPog)^~wAK zI*i7X>xIQ8`->M0|%s{O`AixbITtPN&Ed0(qnP0{eWEle!#4RA_F>H?KnZpbKDc>L^ diff --git a/flann_based/stereo_image782.jpeg b/flann_based/stereo_image782.jpeg deleted file mode 100644 index b0c20f71814e67cefd8d448f53c134cded5fffdc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 481791 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 z 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

ZJsO$! z_31)o{`U{w`9qU)6_M)A5-UnCnND@sY^M*Lw%NKjB+qlEFX$K{;5vM-7i`T8|8%rK z<6LbBk|N}Cuk>e4EsVkHBL(q8R)zCS3M&(oxTJn ze_b}lwl1)FK>hIigo3|Vw2Z{MIcnjVwwZ+od!C8&8mxnOaDm0&;FzPNw~{BRDC84~ zHGa5akREDL6W(`qK^|-`#>#xW#X=9YO6ECK6FmeaXnkDk0|&;3s3Ov>_yCk2-l4yL zh%(}N2*`p9S}-73s&E;mka+H5KBcOrf4MS$X4Mo!IaP68|8k|QvBVYbSRTGyDK(Vvic8Au%a!7W zqQJ@1&~jyNH7r*uD$2?o%aut*`H8_ke$m-e?8}uxQ9;oZcDYhkQq)u^EGeA^%avKV zK9m-x3296@ELW-ub@{^VFz=w4`UO*q3)bcH;8tNZtR5*r%=Ef>MY=peu0Mfcg3=;w z9+ta44=)VR!qEqwEO*|NT)3q+T?%(5(#h}xQ+_@X8EbQh3>j=3z#$ega$1Q#+qX~% zi*`{;hMLt$DcR|<@mbl)G0EAP>Dh?_E!qsy;|jk?`I#`?Pb;G+f(p#At0YilbZoMW zQ%UiZ4iW2c7w>|+^t2!mg=b9+jY&&$8>W#&H-Sc4D1_rg7@QIi2Igg_X#}t-5)8|b z6sHPF>#oOTu;GF8V{@`n!_hvAmoAl;0w*azdkt4e;c&D^3R_rS$=Mmn2{i03gzA&& z=mCX9fkKL!KL@xkc0xdOY^Yor(HJX8n>!^v8!d5S$Pl|aifxF2%g35x1QW~V=T4fQ7qdDF+k({5 zb{zn_QBjfM%~AZAg6Wgc8Yhwrcc>#pSeUCKB-~Z#5z!P$rD8MKWzK)2j_yH=p7E-q zXtV%|S`&nAW*0y~RCL{6X2Sv~kWeFSBpRfRS_08ps0`LZ{ybl&%E*6UL3H(%5zVfP zqUxi)o4xwAk#3`x&>Pl9fxfUdQa5?<+y|>84|aXzt7g|n?mU&KUmYnoxGRETjihGR zNZu}TsZ`;rbt49;BbNbnrX%b;P*u0@!?W-ah#K7Jt?1D;R zqZkgn(G6E zj(X}aG0t}%wDu7VTKgF6OCK`HOH68UEup#^E1$);qKz?88V|#6shO(3PCRwSyv57c zty^9m}KwM zvrDwO?)UXsf1XwQ)Pc=Ya!ZPGi;Hvf@?S6`g0!Ox^0SI-AG>hj&8h=NQ}6S0-g$P` z-o4AV%|W+G!&TBhFU%=<Qz{R*XcOr{ULrhF;j3#ZOK8A|RFR4n4ZivFC!PHFf z!IV;6?#&P9>7#hjsg*Y+HG~r}&zm8@dia~Z&wlQ?)euf5+*Y5|5K2U>?QH@pp%>B( zp=5kheL~{|yx`|12DjYNFoBF~njhN`L6vo( z(_eh@V1irP&v09Z?LnVLSEVYhBHPPT<#H3cg0FY~#I;6<@~nNL}0_ zkHbz0T+z30Lrc*!iyQVQ=|$q{zZu{3autc(0#z?+jbaPj)F+p~K7h$-{6- zppd3T0XeQka3?Btt_e;igY~wL0Ja5!R_@peR*C}Gbj;s1@5z51To zb)=tCD4=;fzA_AUE+ReM{Jp`bN32k5rmR>|8K-s;^R*Pk7kPvMc5zj^me*)qD?hK< zS4(nuI@ky&cFf!IYrtg%= zyf=GDUz1IYdkF4!dH=?DABf%lWOU%5&L)eM$Nb1JN6QnVy);o$f4!r#HN^0fUqCBy zy*>tuG7NMyY0l?XhWW8LG|W3Pz&&iBr^&)xQ{kqX4}PrH3s1cpF&45{$e(tvl^ESbUK-@cvc_7JRkqWLs`#l3i2J) z>tyN)yC6BQ`1^U&{ytKl!QC$58^mp?x3`zKkN2Q%M|(=EE-=iik)ADHZiD-sO0^P- z=|H@y+1+hu$BX$2mfD@un_NAH^}ASU0hsCiD?mQH}k<)(nx>O#*_fV4bhe+UERy{>uMpRV8QCy;C zN{OyGbTZOrQ_B0bSy4tzRPrRyX4e%K6lABDESOh5si?3}Ti{h#G^xC%B2+}+e02f* z_()z}x|={)RFs$73_mXtgTqpRBmyf-v^jDOnA<0(_^E=@bF#8?va+-}qz}86NRwpe zWu>QRD4r_0zt4GkPV`T8MT-qEBuL3l_TWq7qmwj4`dmYZ7WYL{oz#pN3KPVorfP=v zxoEx?cY%8%($f=ZIQ^fToaoK#?{gtRLI5@;iRr1iiBWO7MDK}-gZo@oLQHUARDKT9 zZ}EnS(xH7$H<2F?8ZPrX&~UOCuG3wY5bYHkDfNR+moz=IC{NQ6%}-)GolYN(!6hM- z25GmbhDd3)qtkgs_^U$ok-R8Qz5T9Ecjv^$U_6`cbhkGIBPAEz7>LIY>2!fe)5UI|YU57dykL`3?d!O?MRp&{2aD6Vqqs3Dg8XpL{&Kqz7or>bRT#L%hI~J+B zXb;c@LZz#{$2GgsF5dA-(YeB$PDsfI`Wp?`6}f_}pLxp?1f&t2Mq|t?6K%iL@FS>4}t>bQG<&_%1YYBnkKFWs^(Gt7lZh z|MEF2SJagh+`hdQxDS zV{+5N!@}a;VVHBjoLUzV7M_+oAvienNgWg0T^k%cA$cO)bsq5+V|{P$_62@^{u9If zyuAbWz_lzBV6^r24fig&?WXAG;9aK@hor0h_w`=d`Zi-)s#Qd|Kl+SE{86*%@IUsv za*tFTzPY(T5%zpf&zrtV7gt(5<;@gY5tO^~mS9(%C*>+u(h`5Cxu2d_pe6?mL}XA@RCE@q`w&O&$?&vY%M)^+=IN>R z5<%sANo6ifH-}UJ%c4r>!&4wGzjxZg}A2=`8 z2mH-;)-&Li7x=Lpd-x2q#jLN<)YRxXX2v1B`%LD3juta)y@Q(>OChJJK@s{m?lqbi zco~rHNCiqE$&#Z8kN}Qb4S10t*@-j9*vTP+j$sf*E2s;2(_1Vp#}+MW1rOwj{-b{= z%JEEblRgWjYAdOe6isk5-;M}ikwZangR zOH0X-l9r<-EpQ(q>yVflo!Qb_qoGJfUjwN*3f#d3^{In{)8c*MLmixE0z%N!Y@8ai zxs{Dy(~4XkN=|UF8kecnf*y5{x<{t!F%G0(qaQ>M3A@Ek--Gq^z+fwYj~-d>Kn7}C z5k0C6JrqQ1Ys>e+!M?$2*ih_uJ?bMZdNG?AUX0!X^hSoP<&pytijSy=ki#uJi&|Ut zwXqtFhGdMuA1;$JvWe$DW}-ycT@M^^#Cql;(H1BTsA=F26KIqahf6~=&{0%^o*tBG zf%o@R1frIBGpmRXWEzeCGwLS^AzdcxeI3 zmZL}E$;$piv?x*bS1XE_L$m3@`p^p^2 z+*#hlR$*>+36skJ-D53-hpO9fxJS=C{r}aec;KqO|A`MX^68MC|ha!b1 zemEWh5~ZX+pLcK&Hz7$v%w?!k7!XFVqds8t+`zL@0rVy03()| zWeCl|(h7ApC_zxaY<^WoT5RADHTqy5AUV2L3oQLi4lkQ^$q}x6+;ZDkLXMV=hIa9x zS+ife4F@jR6da(=O9#C#=Ko8$D*&(TFwbj->1Jx1KR9YJ=l#RsF@1BVg z4)iu%|M+gOoyb+O8I}bfXT>?_t+g5+sk0&aZUZ+q!kDD7E(s3i+H=|~4pR1eHyW{a zv-CD@d_VWXT}<-K|I`)q;=3 zY}?J!qclZOwIxS#XXFOwrX2|`vDr?Z0hpMv?XHc8Wf=XlkfD=ic-6r0Zg;gOj-9Zf zzvCr8*t+508ThM(K%Uul5?){l-FmXhK}}Hx5P7DXO9`+(dFEvINh=z^H9*eTPD14x zyA3d0M^Iu&5zl1p1{&rJbF%vkqz3q-J_RAQHVEjpp$=fS&5wYh0Va@2#%Qs2pXo;A z-SFFQXiR39Rka342>7!77a|xS0}yYI>(!pIeC)lKFOf=%sOb$(13OW zORK}n9)hI91_*K|?Y)tEGqZyjbdXjHJ1B9!plo5385nxNck#koVIIU|=Rw>gXkY?l zpZ;*YoZ)5*I(7_Y`nazdI*T4AF6da=P0_%Lq(E_%>UY`8!G%@R)D%jQL}y1CYD*7G#6NO8g( zq+cWVs9TV-k0s4!n7cu2HBFrga}UlJf>}L+s{Te5ghS$cU^0-4Jb(nm_YeD)%V@yioI}^3 zCV(iBYvBeANCQB!oELPPf$$QJ51>uU_&BOMr$x80NXb zww2`%2i+iu`-6^v^Z+-&T92vN`0S8uABdqFz_hB>3ImYUcAPE$MbOFF5fHpu(G1GM z%&gUDYIobLD1V?2xKRK;TW6vflWiv36k$kY%P+5gJTz!{GtszdA4X~ysX=%4EbNbN zK*LIFD>sZ$RMHZaKrK@pY2yf1!~KyUv{lE2M^KvM$6JqWTy*r6Gbdrpd6uGLEby&k ztVvu`t>K2JlW+pc#FcX8?wvRJFWI?6R%|aG0ybHzw9L52iW36MZZ31f$=&HKt zSW3g_%(0qzC5u|1@1edKqmPAYJM@@%m0Kbtu*MXlZ*9qy^?;kJ*Tk66Y!Q^aU{3m6 z=nIfekO`BJo`o%~&^DpsQ9IAUdt|csMG(R@qnS`aJv}Y#J4$jIOq+7&a_{Kpn1CO= zKmnT>-3)`lIv4BV)U{F93Zr>#u0Vj^t+lc2%0;tiVcHKi&?7awEevRfSc`S{Nvmb1 zrWMMSshMXVAz{p9$HPPb2kEY^6X(vI=mK}5tqpyD(b;*ntIN6{JUZTfx69hu$$oTp z9_o5Y>9gO~c}fX>$i1UfD)+Q?zNBnR*oWRb;N7?F+y$T02??jO6Ly_~cb`t>XZzs& z{pf`EzlL|ePWTV+k^`S(pTYaS4&^?0&xEEbNq9-AY&&88t+O-p0K8*gbgn)0#UWc~ zS7$3Gx$gbXGrBsvY==5+U7ZOS_STLU(z`mX)~?P@8-!zRot-bhBV?e{W;=^XN_U=l z!3J^B`2_29~vZ3e>SrNfmBo1ps?+~G@>z)30_O%Pe&;K0J zv+Qk|m?UGzPT+6rI@AT95dRo_fwRJNfnk6?2fn+QcH23d33?s|!axsqwYPOzU-H=l z>Fs3TY?$d#Clspkt*0OyS~qjb*Y+E{`#}1j{2AsYAKMuyB;`~8{2(2|cU^eP){fqH zoZgwvbeWW2Y_~D+>I1dAhhaLD`%1Y6@8QTeoI02dK>av|U zrF>hG!*uLBrF7l9$N16?r}_&rjX$dDak>+S>iOZ&|y{*IqoZd7Z@ z1?_!U9QmI4Ja#+()%oYKEOGBj3`?nB*{)r;^4+etwG7jHuKj@da(lf=TfgtJb-#B0 z5vHpbvoW)euRPF+rXB}cdXJxYU5i1jz>P!o9Y>a780VqJkM%OWU5vK=`0{`HskW0i!<>hl!SsfC5uRVPo)^?xddwEN2`aXC9})t8pnq`Yq=3=N(a$WM z_qWK;=k(>AXBfGq9-BcHw; z^l2IYr$3_a+m1ema2qV^7Zmyn_lX`yIxgL|`g#;(&lh?=WXpl6mfXUX09P7Z$xJS& zfOdq_m-qDSIlg~Y$6J>f>g?+?$(wEP({n3#;s>qo;6)Y;|FDlV>{)=Hu%3K-|Ge|< zubIEJGVLdqEwjFOgn9Qoan5{zJi$Pa3>wjJW2KW4zeE5p>IINSSdNG6gE{Tj*vo7C0u(>EIz z>RSQ_RYV+nD`#$>a_!tq|55M`^#@n;uqUy07 z?m2DCw-?yy7?;!$pVsaZZ*RPPQk1`(rUBbVjz`mS|ES_c8{a-YcGL^sZkgr@sKaOu z_pCbz1Jvm5@`>Gd76yso=#Mi;i2btf+-`NemRwYPWlg6n8+KlaXx&Cn*@>utO6sW!pU zO>pm3?W4r$oY$YsXaE46x!yf#_9l@;G(XYbxJ>0jZ;KGAP{ z_InO~I2;1G!|R+4x;FUXb8z1#1l<4Y;3&WExpViwSvK$kq0Z{S@;4{|r`flQH}<{z zne(KNHysW}&J*yt7lu_iQ5NXeW|14E+{P=MrR(SAq!C=M#;7eLx%EeJR%j#1ui)b- z0%xsom(b_i5z!suoz~e1>MMJUk$@9Hg~L0x^_#O?;s19PKO|Z3v#_iiQ3XAv_YNy# z>)WXZSlX*79!5m2L5-*a+sds&63W=#3B?y)7$Kjsy&0 z+}=L;720XvH~FrQaC?A*L$1cNmFomU%65o+E`^7mzBb}v0mvp`NZT4L-#$*5NA%LG zk$IMfJpqGicd&debXWtqYO)a{dkzQHz##ct^`KuOzjn^XjY9(^JRpB$+O9=1hG%j> zzPcML1%<{ftV@5nLS zWB!+8#=Ba9mcO7?g^VizPJUkMxs7@O696l%{c zyX;}*Tkb*Gcl+=^;`Sdz;<9@STAH)+Peq~vsc^mw{15nFDGE&c!G#=m$ls1OLxj7o z6z%GTzXV3G7`4g9<^OUON>0MhSC9XdICZ2WiD>GN%KwNTyb#(yr1Ntrv#mj0Q1vM% ze+$~=Krers`!>kJR0+SzHM)ROAHTgLzjVnKoSna)(=L%)ZV@kZNf$UfrB5HxekO*H?fui{AI~AABk;g? zCGdp}N1?9rSnrIT7Rk-}^7tb3UGax20Amf3TXXc!oqsp}`RkA4Xe;1PTz_#Z(LZ_t zz^y;C&O6rM$sNwx=(Y3Xa=pk5`w#3&)a?)2dv)Z9-G89Aq5ThT`|Hoxe*x?t|%KY>h;Z)-tQfIoKst-s7cKJzKs3;IJhz-*fwTaHNnrE*jO>3?7kIM2>~9Q&^f zy8$YF$i(neCB0zB=-*jpt#x}g1<2r z*e>Yt?p4U$6U&$f>6TYwVYAT1681hp#;XZti-27N5M`aptmL zKGU93fFSs5yb+7g|6gy4JLV|h0r|G~zkx90wLJmBoqjm|et#|pQPCjgGMf_AC<5`M{NsC#b2&c`)LfawvWbV<#}L!~pem4JZ{ zbM{_h9MVpQ(frO=i>do%SmwKoIM~@!8gya=FMA1$X16ec{)!%`TVGx$7%3jGe`m)| z90?fKR<9_>If1=T{g68%_YA`RxpPQEqdF3BHCmyASMSM@rZ|1q!y$x`2jKe;YL4ix zLz6jWEei|a3mHjItCMRcp$={Cr84K z|M7X;zK?2Nu;<=c7U2q67!+XESLb~5(NS?mQ_l~M>C&L|UFp&EF<1c2gQN7LmSNxR zDErVY_t=~=>#u_s!|TSdrgIv%@8F%@Fwcae^rN;R+Z!INcnnMGpNZAo zTkLr(zvz%R?7Op$D}9s*!IG|Fq5ZG6?z~g-q6E-}Q4?T#t$e^ zAY;Gj(G4J(3on=VmnRVOy%ML~_Z%1~pFEGuFME5te+2X5=d?2uy%40}aAQelI`0}P z9;#sOF=v_L5`5vE#S_qu)qvv*y#fL=k@@MQNd+MRUc$kmVNmlM%lgySUN^Y#Ij%&~ z9_Ql#n*`JGO@r(z2h!o}3G6i2d^=jb1Gm06k_VdJAO_01!_LPkHU(f;*-~&t18$55 zMxtZdXTjHXvpO0xI+V`zC)M@59Mxj;{53(TCUeeSc4p|fkQ^*BClJtuZA@Eb!q%S;$l zdf#)%xOfbA^veT#AKSEyGrwQ3VA-b4yAFJLbc_hdMESYQ`+iS$E>oXa71qC0wlzPpSUvGoPN|eA~X-yFAL#!#(w<>|?9#-0Qc-DM*|W%H{C0 z7NjC>=^LH)Qna4ba`hebvZHW1wq;8Qm&AE%o`37$!MC1UbA6(ckmPLn%^t(_Vjv{O z<7GSZ%P;28bfV$lSx0ona`q#ABF)d<=MeF-C&ts-gKZy$@w1-#byywRe%+Df^NM3a zXEsn#C%I~|nJz!O(V2;-?YDpS^zR1z7<&(w8qi2)bcLQ%2MW_ZW3%4No~W{Y^sV!m zhdug0gx6RTc%eeQ;KXHxw_*q5bC`Rrh zMV?DmJo7j5`Y{IMp>ZrXkSk~4>xO!c^|lVLN~Ly+9u~9#ul(!ptFQZ>Q6!%m#%0vkvq|!& zKhcc8y?yKwd+>+F<8RMR(4O006DNtyw=u!E=%~-xH^n&2c3Dgt=;yxAbVVg z%zw)iY_+wuGrwgi-Ws(?1_kVrW&ei86WiVmR=?=RR&qp#{aq?Xhip(QZ_5|9s%mwoD1(nta3h)^`sc z+}FC{h9nn4oUzp*)4Z3(M=?*sX}bv9*;j9ll@mB6lF7tymAgD<@!qrcOj%DiumBTC zpfvZrcDRjm#}DpUF*PyJ*EcX>>WU{nI&Swq{Mvo7?9BdFb{@ood61;?xv$#V+uJ_f zc2jzQn_ECy-L_BB`&Z9ZBIw5BainssCz_M}5@z1Bdi6au34X~<$5F~IJ??>tA4lb8 z`g=^&y&rb4J1*vq5AThd$eyn-Z;@1@*tXs${`y0I@gQ#7;3uLWpu74x#K#C17Q**n zXEm_|yP#d2x%FEo6=-7#(7fQ{^FIuZ>39YLcE8{1sANZg=-6w}g*RG)A3pmNVqn7Og+gemr*bDB-pTV~)dlq&JU_BEb6nTh{hAm?1jd%VRF1 zp{pI*r_JPypyRerq17JV1;T+~gb3@U&1fI4b$T}hbm6~IrYuiLG0&}t1M{;X(Jy(<%Ju74&4G@pJBGM*KY@^U$@E=^ z+rjSVlgDpJ_H}htCtd&8$0xw!aO(^(3%rXR2XI<`?-xf~Z>_4XuDZ4L*cbQ8@9ks0 zFuZ@JxA)BZ8-8N?R({d_tRJUw`q|A@3h7sT$JE zJF2RO%*=bI4}Tv{zhoG{U26x87?!oWjfXp;e0i11FBA$N&HU diff --git a/find-object/app/Find-Object.ico b/find-object/app/Find-Object.ico deleted file mode 100644 index a4d848551f57a0ebedece69ed6871d0ddd6fb986..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72078 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%0D-4p@7XJ|YacJ>asTJgSA0r+c&;lsRM#&4_# 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%0AR<@u192)f?^epmX1&2w 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 JPDHLkV1j{6^HKl+ 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 6f01082f7962d447504017b227a24792f8109868..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50728 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ⅇt){yu(o6CH9MS9ibiHP8H7dXK$@_P;>R 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