diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..ac43a74a543e365510111bb13b7f24a46bf97a27 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +openpose/.github/media/pose_hands.gif filter=lfs diff=lfs merge=lfs -text +*.exe filter=lfs diff=lfs merge=lfs -text +*.gif filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +openpose/3rdparty/windows/wget/wget.exe.debug filter=lfs diff=lfs merge=lfs -text diff --git a/openpose/.github/CI_deprecated/.travis.yml b/openpose/.github/CI_deprecated/.travis.yml new file mode 100644 index 0000000000000000000000000000000000000000..0c2e3202fc6b08c227eb45f1aee6fe922c9db09a --- /dev/null +++ b/openpose/.github/CI_deprecated/.travis.yml @@ -0,0 +1,162 @@ +# # This will run on Travis' 'new' container-based infrastructure + +# # Blacklist +# branches: +# only: +# - master + +# # Environment variables + OS + other parameters +# global: +# - GH_REPO_NAME: openpose +# - DOXYFILE: $CI_BUILD_DIR/.doc_autogeneration.doxygen +# # Set this in Environment Variables on travis-ci.org +# # - GH_REPO_REF: github.com//openpose.git +# matrix: +# # Use a build matrix to test many builds in parallel +# # envvar defaults: +# # WITH_CMAKE: true +# # WITH_PYTHON: false +# # WITH_CUDA: true +# # WITH_CUDNN: true +# # WITH_OPEN_CL: false +# # WITH_MKL: false +# include: +# # Ubuntu 16.04 +# # Ubuntu 16.04 - Default - CMake - CUDA +# - os: linux +# dist: xenial +# env: NAME="U16-default-cmake-cuda8" +# sudo: required +# # Ubuntu 16.04 - Python - CMake - CUDA +# - os: linux +# dist: xenial +# env: NAME="U16-python-cmake-cuda8" WITH_PYTHON=true +# sudo: required +# # Generate and deploy documentation +# after_success: +# - cd $CI_BUILD_DIR +# - chmod +x scripts/generate_gh_pages.sh +# - ./scripts/generate_gh_pages.sh +# # Ubuntu 16.04 - Python - CMake - CPU +# - os: linux +# dist: xenial +# env: NAME="U16-python-cmake-cpu" WITH_PYTHON=true WITH_CUDA=false +# sudo: required +# # Ubuntu 16.04 - Python - CMake - OpenCL +# - os: linux +# dist: xenial +# env: NAME="U16-python-cmake-opencl" WITH_PYTHON=true WITH_CUDA=false WITH_OPEN_CL=true +# sudo: required +# # Ubuntu 16.04 - Python - CMake - CPU - Debug +# - os: linux +# dist: xenial +# env: NAME="U16-python-cmake-cpu-debug" WITH_PYTHON=true WITH_CUDA=false WITH_DEBUG=true +# sudo: required +# # Ubuntu 16.04 - Python - CMake - CPU - Unity +# - os: linux +# dist: xenial +# env: NAME="U16-python-cmake-cpu-unity" WITH_PYTHON=true WITH_UNITY=true WITH_CUDA=false +# sudo: required + +# # Mac OSX +# # Mac OSX - Python - CMake - CPU +# - os: osx +# osx_image: xcode9.4 # xcode10.1 does not work with Python # Versions: https://docs.travis-ci.com/user/languages/objective-c#supported-xcode-versions +# env: NAME="OSX-python-cmake-cpu" WITH_CUDA=false WITH_PYTHON=true +# sudo: required +# # Mac OSX - Python - CMake - OpenCL +# - os: osx +# osx_image: xcode10.1 # Versions: https://docs.travis-ci.com/user/languages/objective-c#supported-xcode-versions +# env: NAME="OSX-default-cmake-opencl" WITH_CUDA=false WITH_OPEN_CL=true +# sudo: required +# # Mac OSX - Python - CMake - CPU - Debug +# - os: osx +# osx_image: xcode9.4 # xcode10.1 does not work with Python # Versions: https://docs.travis-ci.com/user/languages/objective-c#supported-xcode-versions +# env: NAME="OSX-python-cmake-cpu-debug" WITH_CUDA=false WITH_PYTHON=true WITH_DEBUG=true +# sudo: required +# # Mac OSX - Python - CMake - CPU - Unity +# - os: osx +# osx_image: xcode9.4 # xcode10.1 does not work with Python # Versions: https://docs.travis-ci.com/user/languages/objective-c#supported-xcode-versions +# env: NAME="OSX-python-cmake-cpu-unity" WITH_CUDA=false WITH_PYTHON=true WITH_UNITY=true +# sudo: required +# # Mac OSX - Default - CMake - CPU +# - os: osx +# osx_image: xcode10.1 # Versions: https://docs.travis-ci.com/user/languages/objective-c#supported-xcode-versions +# env: NAME="OSX-default-cmake-cpu" WITH_CUDA=false +# sudo: required + +# # # TO-DO: To be implemented +# # # Windows +# # # Windows - Default - CMake - CUDA +# # - os: windows +# # env: NAME="W10-default-cmake-cuda8" + +# # Ubuntu (others) +# # Ubuntu 16.04 - Default - CMake - CPU +# - os: linux +# dist: xenial +# env: NAME="U16-default-cmake-cpu" WITH_CUDA=false +# sudo: required +# # Ubuntu 16.04 - Default - Make - CUDA +# - os: linux +# dist: xenial +# env: NAME="U16-default-make-cuda8" WITH_CMAKE=false +# sudo: required +# # # TO-DO: To be implemented +# # # Ubuntu 16.04 - Default - CMake - CPU MKL +# # - os: linux +# # dist: xenial +# # env: NAME="U16-default-cmake-cpu-mkl" WITH_CUDA=false WITH_MKL=true +# # sudo: required +# # # Ubuntu 16.04 - Python - CMake - OpenCL +# # - os: linux +# # dist: xenial +# # env: NAME="U16-python-cmake-opencl" WITH_PYTHON=true WITH_CUDA=false WITH_OPEN_CL=true +# # sudo: required +# # # Unnecessary/redundant ones +# # # Ubuntu 16.04 - Default - CMake - CUDA - no cuDNN +# # - os: linux +# # dist: xenial +# # env: NAME="U16-default-cmake-cuda8-nocudnn" WITH_CUDNN=false +# # sudo: required +# # Ubuntu 14.04 - Default - CMake - CPU +# - os: linux +# dist: trusty +# env: NAME="U14-default-cmake-cpu" WITH_CUDA=false +# sudo: required +# # Ubuntu 14.04 - Default - Make - CUDA +# - os: linux +# dist: trusty +# env: NAME="U14-default-make-cuda8" WITH_CMAKE=false +# sudo: required +# # # Unnecessary/redundant ones +# # # Ubuntu 14.04 - Default - CMake - CUDA +# # - os: linux +# # dist: trusty +# # env: NAME="U14-default-cmake-cuda8" +# # sudo: required + +# # Install apt dependencies +# addons: +# apt: +# packages: +# - doxygen +# - doxygen-doc +# - doxygen-latex +# - doxygen-gui +# - graphviz + +# # Install Caffe and OP dependencies +# install: +# - if [[ "$CI_OS_NAME" == "linux" ]]; then sudo bash scripts/CI/install_deps_ubuntu.sh ; fi +# - if [[ "$CI_OS_NAME" == "osx" ]]; then bash scripts/CI/install_deps_osx.sh ; fi +# - if [[ "$CI_OS_NAME" == "windows" ]]; then exit 99 ; fi + +# # Running CMake +# before_script: +# - bash scripts/CI/configure.sh + +# # Build your code e.g., by calling make +# script: +# - bash scripts/CI/run_make.sh +# - bash scripts/CI/run_tests.sh diff --git a/openpose/.github/CI_deprecated/Readme_Travis_badges_table_and_backup_instructions.md b/openpose/.github/CI_deprecated/Readme_Travis_badges_table_and_backup_instructions.md new file mode 100644 index 0000000000000000000000000000000000000000..3e9def3b5d38f0f03e7472f6ccb8359e787ef8f0 --- /dev/null +++ b/openpose/.github/CI_deprecated/Readme_Travis_badges_table_and_backup_instructions.md @@ -0,0 +1,13 @@ +In order to recover Travis: +1. Uncomment all the lines of code in ".travis.yml" and move it back to the main folder (e.g., at the same level than the global README.md and CMakeLists.txt files). +2. Move `generate_gh_pages.sh` back to `scripts/generate_gh_pages.sh`. +3. Re-add the table of badges in the README.md: + +| |`Default Config` |`CUDA (+Python)` |`CPU (+Python)` |`OpenCL (+Python)`| `Debug` | `Unity` | +| :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| **`Linux`** | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/1)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/2)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/3)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/4)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/5)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/6)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | +| **`MacOS`** | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/7)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/7)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/8)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/9)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/10)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/11)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | +| **`Windows`** | [![Status](https://ci.appveyor.com/api/projects/status/5leescxxdwen77kg/branch/master?svg=true)](https://ci.appveyor.com/project/gineshidalgo99/openpose/branch/master) | | | | | + diff --git a/openpose/.github/CI_deprecated/generate_gh_pages.sh b/openpose/.github/CI_deprecated/generate_gh_pages.sh new file mode 100644 index 0000000000000000000000000000000000000000..ed0b4b48acd4d47dc94d3256deded29860d8901e --- /dev/null +++ b/openpose/.github/CI_deprecated/generate_gh_pages.sh @@ -0,0 +1,104 @@ +#!/bin/sh +################################################################################ +# Title : generate_gh_pages.sh +# Date created : 2016/02/22 +# Notes : +__AUTHOR__="openpose" +# Preconditions: +# - Packages doxygen doxygen-doc doxygen-latex doxygen-gui graphviz +# must be installed. +# - Doxygen configuration file must have the destination directory empty and +# source code directory with a $(CI_BUILD_DIR) prefix. +# - An gh-pages branch should already exist. See below for more info on how to +# create a gh-pages branch. +# +# Required global variables: +# - CI_BUILD_NUMBER : The number of the current build. +# - CI_COMMIT : The commit that the current build is testing. +# - DOXYFILE : The Doxygen configuration file. +# - GH_REPO_NAME : The name of the repository. +# - GH_REPO_REF : The GitHub reference to the repository. +# - GH_REPO_TOKEN : Secure token to the github repository. +# +# For information on how to encrypt variables for Travis CI please go to +# https://docs.travis-ci.com/user/environment-variables/#Encrypted-Variables +# or https://gist.github.com/vidavidorra/7ed6166a46c537d3cbd2 +# For information on how to create a clean gh-pages branch from the master +# branch, please go to https://gist.github.com/vidavidorra/846a2fc7dd51f4fe56a0 +# +# This script will generate Doxygen documentation and push the documentation to +# the gh-pages branch of a repository specified by GH_REPO_REF. +# Before this script is used there should already be a gh-pages branch in the +# repository. +# +################################################################################ + +################################################################################ +##### Setup this script and get the current gh-pages branch. ##### +echo 'Setting up the script...' +# Exit with nonzero exit code if anything fails +set -e + +# Create a clean working directory for this script. +mkdir code_docs +cd code_docs + +# Get the current gh-pages branch +git clone -b gh-pages https://git@$GH_REPO_REF +cd $GH_REPO_NAME + +##### Configure git. +# Set the push default to simple i.e. push only the current branch. +git config --global push.default simple +# Pretend to be an user called Travis CI. +git config user.name "Travis CI" +git config user.email "travis@travis-ci.org" + +# Remove everything currently in the gh-pages branch. +# GitHub is smart enough to know which files have changed and which files have +# stayed the same and will only update the changed files. So the gh-pages branch +# can be safely cleaned, and it is sure that everything pushed later is the new +# documentation. +rm -rf * + +# Need to create a .nojekyll file to allow filenames starting with an underscore +# to be seen on the gh-pages site. Therefore creating an empty .nojekyll file. +# Presumably this is only needed when the SHORT_NAMES option in Doxygen is set +# to NO, which it is by default. So creating the file just in case. +echo "" > .nojekyll + +################################################################################ +##### Generate the Doxygen code documentation and log the output. ##### +echo 'Generating Doxygen code documentation...' +# Redirect both stderr and stdout to the log file AND the console. +echo "OUTPUT_DIRECTORY = " >> $DOXYFILE +doxygen $DOXYFILE 2>&1 | tee doxygen.log + +################################################################################ +##### Upload the documentation to the gh-pages branch of the repository. ##### +# Only upload if Doxygen successfully created the documentation. +# Check this by verifying that the html directory and the file html/index.html +# both exist. This is a good indication that Doxygen did it's work. +if [ -d "html" ] && [ -f "html/index.html" ]; then + + echo 'Uploading documentation to the gh-pages branch...' + # Add everything in this directory (the Doxygen code documentation) to the + # gh-pages branch. + # GitHub is smart enough to know which files have changed and which files have + # stayed the same and will only update the changed files. + git add --all + + # Commit the added files with a title and description containing the Travis CI + # build number and the GitHub commit reference that issued this build. + git commit -m "Deploy code docs to GitHub Pages Travis build: ${CI_BUILD_NUMBER}" -m "Commit: ${CI_COMMIT}" + + # Force push to the remote gh-pages branch. + # The output is redirected to /dev/null to hide any sensitive credential data + # that might otherwise be exposed. + git push --force "https://${GH_REPO_TOKEN}@${GH_REPO_REF}" > /dev/null 2>&1 +else + echo '' >&2 + echo 'Warning: No documentation (html) files have been found!' >&2 + echo 'Warning: Not going to push the documentation to GitHub!' >&2 + exit 1 +fi diff --git a/openpose/.github/Logo_doxygen_black.png b/openpose/.github/Logo_doxygen_black.png new file mode 100644 index 0000000000000000000000000000000000000000..342df5af45d6c482b5c93ac715224ecac636f3e9 --- /dev/null +++ b/openpose/.github/Logo_doxygen_black.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:836f2250b34d07c8b094801bb0e57652eaea8c0ea1b9b1360f5ee936ed09be96 +size 8782 diff --git a/openpose/.github/Logo_main_black.png b/openpose/.github/Logo_main_black.png new file mode 100644 index 0000000000000000000000000000000000000000..baafab007271a2804c2df4cba2efb2389c8fa027 --- /dev/null +++ b/openpose/.github/Logo_main_black.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89dd7c908e68931619aa2a1ed5b48bc15e1d0fa9caeac53a960076c4bd6d2a08 +size 293509 diff --git a/openpose/.github/issue_template.md b/openpose/.github/issue_template.md new file mode 100644 index 0000000000000000000000000000000000000000..c9e836c7b0deab0839ca08711e0f159836adeb1e --- /dev/null +++ b/openpose/.github/issue_template.md @@ -0,0 +1,85 @@ +### Posting rules +1. **No duplicated posts, only 1 new post opened a day, and up to 2 opened a week**. Otherwise, extrict user bans will occur. + - Check the [FAQ](https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/05_faq.md) section, other GitHub issues, and general documentation before posting. E.g., **low-speed, out-of-memory, output format, 0-people detected, installation issues, ...**). + - Keep posting all your issues in the same post. + - No bans if you are unsure whether the post is duplicated! +2. **Fill all** the **Your System Configuration section** if you are facing an error or unexpected behavior. Some posts (e.g., feature requests) might not require it. +3. **No questions about training or 3rd party libraries**: + - OpenPose only implements testing. For training, check [OpenPose train](https://github.com/CMU-Perceptual-Computing-Lab/openpose_train). + - Caffe errors/issues: Check [Caffe](http://caffe.berkeleyvision.org) documentation. + - CUDA/cuDNN check failed errors: They are usually fixed by re-installing CUDA, then re-installing the proper cuDNN version, then rebooting, and then re-installing OpenPose. Otherwise, check Nvidia/CUDA/cuDNN forums. + - OpenCV errors: Install the default/pre-compiled OpenCV or check for OpenCV online help. +4. Set a **proper issue title**: Add the OS (Ubuntu, Windows) and be specific (e.g., do not call it: `Error`). +5. Only English comments. +6. Remove these posting rules from your post but follow them! +Posts which do not follow these rules will be **ignored/deleted** and those **users banned** with no further clarification. + + + +### Issue Summary + + + +### Executed Command (if any) +Note: add `--logging_level 0 --disable_multi_thread` to get higher debug information. + + + +### OpenPose Output (if any) + + + +### Errors (if any) + + + +### Type of Issue +Select the topic(s) on your post, delete the rest: +- Compilation/installation error +- Execution error +- Help wanted +- Question +- Enhancement / offering possible extensions / pull request / etc +- Other (type your own type) + + + +### Your System Configuration +1. **Whole console output** (if errors appeared), paste the error to [PasteBin](https://pastebin.com/) and then paste the link here: LINK + +2. **OpenPose version**: Latest GitHub code? Or specific commit (e.g., d52878f)? Or specific version from `Release` section (e.g., 1.2.0)? + +3. **General configuration**: + - **Installation mode**: CMake, sh script, manual Makefile installation, ... (Ubuntu); CMake, ... (Windows); ...? + - **Operating system** (`lsb_release -a` in Ubuntu): + - **Operating system version** (e.g., Ubuntu 16, Windows 10, ...): + - **Release or Debug mode**? (by default: release): + - Compiler (`gcc --version` in Ubuntu or VS version in Windows): 5.4.0, ... (Ubuntu); VS2015 Enterprise Update 3, VS2017 community, ... (Windows); ...? + +4. **Non-default settings**: + - **3-D Reconstruction module added**? (by default: no): + - Any other custom CMake configuration with respect to the default version? (by default: no): + +5. **3rd-party software**: + - **Caffe version**: Default from OpenPose, custom version, ...? + - **CMake version** (`cmake --version` in Ubuntu): + - **OpenCV version**: pre-compiled `apt-get install libopencv-dev` (only Ubuntu); OpenPose default (only Windows); compiled from source? If so, 2.4.9, 2.4.12, 3.1, 3.2?; ...? + +6. If **GPU mode** issue: + - **CUDA version** (`cat /usr/local/cuda/version.txt` in most cases): + - **cuDNN version**: + - **GPU model** (`nvidia-smi` in Ubuntu): + +7. If **CPU-only mode** issue: + - **CPU brand & model**: + - Total **RAM memory** available: + +8. If **Python** API: + - **Python version**: 2.7, 3.7, ...? + - **Numpy version** (`python -c "import numpy; print numpy.version.version"` in Ubuntu): + +9. If **Windows** system: + - Portable demo or compiled library? + +10. If **speed performance** issue: + - Report OpenPose timing speed based on the [profiling documentation](https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/06_maximizing_openpose_speed.md#profiling-speed). diff --git a/openpose/.github/media/body_heat_maps.png b/openpose/.github/media/body_heat_maps.png new file mode 100644 index 0000000000000000000000000000000000000000..40039b665e5ba5211afaffbbc1f9a5b09abebca5 --- /dev/null +++ b/openpose/.github/media/body_heat_maps.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11eed582d06c69f409e56c0ded335fd2fbd3d06228e7f5b3d2b1e8b3b105adba +size 2431310 diff --git a/openpose/.github/media/dance_foot.gif b/openpose/.github/media/dance_foot.gif new file mode 100644 index 0000000000000000000000000000000000000000..11a7c58fdb277af8bbd4be131c9f75eeb408096a --- /dev/null +++ b/openpose/.github/media/dance_foot.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:84db361692ac5835e695a6c971a61a119c3d426ff698db90dff2432546481fbb +size 4406638 diff --git a/openpose/.github/media/installation/cmake_im_1.png b/openpose/.github/media/installation/cmake_im_1.png new file mode 100644 index 0000000000000000000000000000000000000000..fd814974c7c97fd2278a90ccc36d10be14b6c192 --- /dev/null +++ b/openpose/.github/media/installation/cmake_im_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1c4f8bf6946469234119982165b32c40181f77ebf21ec7ae1f103549041dad1c +size 60058 diff --git a/openpose/.github/media/installation/cmake_im_1_windows.png b/openpose/.github/media/installation/cmake_im_1_windows.png new file mode 100644 index 0000000000000000000000000000000000000000..a9dc26fb28ef10091803ba34afab1abde743e346 --- /dev/null +++ b/openpose/.github/media/installation/cmake_im_1_windows.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:faffd27db861260d9444ad86d224d0c5fbd6baa9cd87f25de2208375a997197b +size 14297 diff --git a/openpose/.github/media/installation/cmake_im_2.png b/openpose/.github/media/installation/cmake_im_2.png new file mode 100644 index 0000000000000000000000000000000000000000..07988100b7647982aa81cc8cfdba58c575000dde --- /dev/null +++ b/openpose/.github/media/installation/cmake_im_2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f3bb1794aa08a0ecccfa9bbd1bd6e20a4f4b9414b1ed721b11c30db5681149f7 +size 39714 diff --git a/openpose/.github/media/installation/cmake_im_2_windows.png b/openpose/.github/media/installation/cmake_im_2_windows.png new file mode 100644 index 0000000000000000000000000000000000000000..cca71a0619ac37bc4e4099e59d37152f6e5e6fcf --- /dev/null +++ b/openpose/.github/media/installation/cmake_im_2_windows.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0b2914dfe7015c68b36bab9e1c5b80c9a30ae5fb88b783c41b3c1bd437a3b6d1 +size 10979 diff --git a/openpose/.github/media/installation/cmake_im_2_windows_new.png b/openpose/.github/media/installation/cmake_im_2_windows_new.png new file mode 100644 index 0000000000000000000000000000000000000000..c7982c62fe415aab4ea0dca574710bd7abd381fa --- /dev/null +++ b/openpose/.github/media/installation/cmake_im_2_windows_new.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:28779d4a920d34a74ed62dd5f5bfbc4b7926daf84cc410495f10566771adcede +size 13833 diff --git a/openpose/.github/media/installation/cmake_im_3.png b/openpose/.github/media/installation/cmake_im_3.png new file mode 100644 index 0000000000000000000000000000000000000000..315fae90029b104b6e025533f3e40422930324ee --- /dev/null +++ b/openpose/.github/media/installation/cmake_im_3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:225659a6dc93e078d9a3813ba2c9c07c9c2093751a3a70e4923776efe78caedd +size 132802 diff --git a/openpose/.github/media/installation/cmake_im_3_windows.png b/openpose/.github/media/installation/cmake_im_3_windows.png new file mode 100644 index 0000000000000000000000000000000000000000..df9ca1b564ce6215d81b5c9e325ecac84e9cdd54 --- /dev/null +++ b/openpose/.github/media/installation/cmake_im_3_windows.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b6627e3fd08376daa50e16ed3772394997589f77a775d98df919255b48e961c +size 36462 diff --git a/openpose/.github/media/installation/cmake_im_5.png b/openpose/.github/media/installation/cmake_im_5.png new file mode 100644 index 0000000000000000000000000000000000000000..b4468655d6191746bdf464e1687d27a2169d6578 --- /dev/null +++ b/openpose/.github/media/installation/cmake_im_5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fac231f89e02ae6181aa60d8f31425e57f0d41ea14a7ac3f7a6d8254332b18c5 +size 112509 diff --git a/openpose/.github/media/keypoints_face.png b/openpose/.github/media/keypoints_face.png new file mode 100644 index 0000000000000000000000000000000000000000..11bf1469f9c4349b07c425d427f6b8967f343098 --- /dev/null +++ b/openpose/.github/media/keypoints_face.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1239ebee72f12b55453cfa1997b2a5f53d806f2518f7b723d0bdd996d569bb72 +size 35159 diff --git a/openpose/.github/media/keypoints_hand.odt b/openpose/.github/media/keypoints_hand.odt new file mode 100644 index 0000000000000000000000000000000000000000..362910e41c00c25899ab82bf80fd84154dbb1c35 Binary files /dev/null and b/openpose/.github/media/keypoints_hand.odt differ diff --git a/openpose/.github/media/keypoints_hand.png b/openpose/.github/media/keypoints_hand.png new file mode 100644 index 0000000000000000000000000000000000000000..8342ef8602356778b1f3f9b7ef9fd7b4765c959d --- /dev/null +++ b/openpose/.github/media/keypoints_hand.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b43d9c9f7a85c4cbc342909ebd65d465143ee28bec669b0fe84ab159d41f4f35 +size 185529 diff --git a/openpose/.github/media/keypoints_pose_18.png b/openpose/.github/media/keypoints_pose_18.png new file mode 100644 index 0000000000000000000000000000000000000000..12c4d6db02e57047aa9b202a65e66a6454c9c5c5 --- /dev/null +++ b/openpose/.github/media/keypoints_pose_18.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:82c3a3855af28f6507193123f0a8bc6ceda54f583af195db197530ea17a589c4 +size 11153 diff --git a/openpose/.github/media/keypoints_pose_25.png b/openpose/.github/media/keypoints_pose_25.png new file mode 100644 index 0000000000000000000000000000000000000000..eaeaa16890906500c40db6ede5c2763b159df703 --- /dev/null +++ b/openpose/.github/media/keypoints_pose_25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5380ae2b1d9ca5566ce34b1ee43ccdc3f19e464e9f735f7c188bab46b441ab6c +size 71796 diff --git a/openpose/.github/media/openpose3d.gif b/openpose/.github/media/openpose3d.gif new file mode 100644 index 0000000000000000000000000000000000000000..476ec8610321ebd380a5cac6279ade67d0167373 --- /dev/null +++ b/openpose/.github/media/openpose3d.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e4c16b230bb23b25a6cfd375086e7faac10bc6bb945e96e9f4d7f32fcc66e8b7 +size 184051 diff --git a/openpose/.github/media/openpose_vs_competition.png b/openpose/.github/media/openpose_vs_competition.png new file mode 100644 index 0000000000000000000000000000000000000000..719af5e8d53ad9b1223527742910f877f7c6d749 --- /dev/null +++ b/openpose/.github/media/openpose_vs_competition.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ccfbea42ee908eeae5629981547d0af837edd18db28baa8bcfada049161703d6 +size 31674 diff --git a/openpose/.github/media/paf_heat_maps.png b/openpose/.github/media/paf_heat_maps.png new file mode 100644 index 0000000000000000000000000000000000000000..6ea94ec8c38dfe0d3484848a46567d7e911ab7c8 --- /dev/null +++ b/openpose/.github/media/paf_heat_maps.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:976e86944144d90c6b18f4d61a05be0cacd8d71e9b1f002ff732761a96395788 +size 1894279 diff --git a/openpose/.github/media/pose_face.gif b/openpose/.github/media/pose_face.gif new file mode 100644 index 0000000000000000000000000000000000000000..2e63bfa612c365382b5d667e3b9567a90f5046bc --- /dev/null +++ b/openpose/.github/media/pose_face.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f2030331f4caae4a5c928227e01fb5c65183bba181c33867e87f942bc2b003b2 +size 9638181 diff --git a/openpose/.github/media/pose_face_hands.gif b/openpose/.github/media/pose_face_hands.gif new file mode 100644 index 0000000000000000000000000000000000000000..4b5badc3ea1437edabf3282cae647434fc16bc25 --- /dev/null +++ b/openpose/.github/media/pose_face_hands.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5d2a3509ef791f7b08e751c6aea0287f4efab5ffbb0e6af7e335b5c50432b9a9 +size 8391444 diff --git a/openpose/.github/media/pose_hands.gif b/openpose/.github/media/pose_hands.gif new file mode 100644 index 0000000000000000000000000000000000000000..58497ed209bbac72aca585de9d543c1993b6ca28 --- /dev/null +++ b/openpose/.github/media/pose_hands.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e369475240b3cbfe10436ebf7a4a5f1da1d10756ce95782891f839b0d2ff946c +size 10723711 diff --git a/openpose/.github/media/shake.gif b/openpose/.github/media/shake.gif new file mode 100644 index 0000000000000000000000000000000000000000..0b996cb144fc496740c25b0c09da4705fdef7f20 --- /dev/null +++ b/openpose/.github/media/shake.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6971f3331bf676f48174bb3358d43355a760bc53852b22ff67b2b7b0da6e7a43 +size 2040076 diff --git a/openpose/.github/media/unity_body_foot.png b/openpose/.github/media/unity_body_foot.png new file mode 100644 index 0000000000000000000000000000000000000000..2eb468210f25539cae8d1781d11a7fa5576d757e --- /dev/null +++ b/openpose/.github/media/unity_body_foot.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fdebe1ed182cc8f5ac2e729bcd9f280ab4806d45929ad4050e6ebba37dc98123 +size 22363 diff --git a/openpose/.github/media/unity_hand_face.png b/openpose/.github/media/unity_hand_face.png new file mode 100644 index 0000000000000000000000000000000000000000..d2ed6772bb6ef533987203f30d21431db2dcdbaa --- /dev/null +++ b/openpose/.github/media/unity_hand_face.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cd94f84ddd32809693493dc40b4a73d7f0df9aa85850b166c95f527a1504fd05 +size 32471 diff --git a/openpose/.github/media/unity_main.png b/openpose/.github/media/unity_main.png new file mode 100644 index 0000000000000000000000000000000000000000..d655d5732d5de3fbe63ed7bf22d2f90169818e84 --- /dev/null +++ b/openpose/.github/media/unity_main.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c09e900fa60ea56f8323b6ac5c66f5bca8f0af726247dfcb4a79c4287347c662 +size 962101 diff --git a/openpose/.github/root_index.html b/openpose/.github/root_index.html new file mode 100644 index 0000000000000000000000000000000000000000..34d72f1ba2700ce3cd1eed07355ed572ffa73446 --- /dev/null +++ b/openpose/.github/root_index.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/openpose/.github/stale.yml b/openpose/.github/stale.yml new file mode 100644 index 0000000000000000000000000000000000000000..eb36d22906afb82206046f04236b6958f0c7f8b0 --- /dev/null +++ b/openpose/.github/stale.yml @@ -0,0 +1,17 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 60 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 7 +# Issues with these labels will never be considered stale +exemptLabels: + - bug/typo + - enhancement +# Label to use when marking an issue as stale +staleLabel: stale/old +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false diff --git a/openpose/.github/workflows/main.yml b/openpose/.github/workflows/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..da639bcefcb3ad02ddf023fd80bbe60704e1d829 --- /dev/null +++ b/openpose/.github/workflows/main.yml @@ -0,0 +1,291 @@ +name: CI + +on: [push, pull_request] + +env: + GH_REPO_NAME: ${{ github.event.repository.name }} + DOXYFILE: ${{ github.workspace }}/.doc_autogeneration.doxygen + GH_REPO_REF: ${{ github.repositoryUrl }} + PYTHON3_VERSION: python3.8 + +jobs: + build: + name: ${{ matrix.env.NAME }} + runs-on: ${{ matrix.os }} + env: ${{ matrix.env }} + strategy: + fail-fast: false + matrix: + include: + # Ubuntu + # Ubuntu 20.04 - Default - CMake - CUDA + - os: ubuntu-20.04 + os_name: linux + env: + NAME: U20-default-cmake-cuda + WITH_CUDNN: false + CI_OS_NAME: linux + # Ubuntu 18.04 - Default - CMake - CUDA + - os: ubuntu-18.04 + os_name: linux + env: + NAME: U18-default-cmake-cuda + WITH_CUDNN: false + CI_OS_NAME: linux + # Ubuntu 20.04 - Python - CMake - CUDA + - os: ubuntu-20.04 + os_name: linux + env: + NAME: U20-python-cmake-cuda + WITH_CUDNN: false + WITH_PYTHON: true + CI_OS_NAME: linux + CI_BUILD_NUMBER: ${{ github.run_number }} + CI_COMMIT: ${{ github.sha }} + DOCS: true + # Ubuntu 18.04 - Python - CMake - CUDA + - os: ubuntu-18.04 + os_name: linux + env: + NAME: U18-python-cmake-cuda + WITH_CUDNN: false + WITH_PYTHON: true + CI_OS_NAME: linux + # Ubuntu 20.04 - Python - CMake - CPU + - os: ubuntu-20.04 + os_name: linux + env: + NAME: U20-python-cmake-cpu + WITH_PYTHON: true + WITH_CUDA: false + WITH_CUDNN: false + CI_OS_NAME: linux + # Ubuntu 18.04 - Python - CMake - CPU + - os: ubuntu-18.04 + os_name: linux + env: + NAME: U18-python-cmake-cpu + WITH_PYTHON: true + WITH_CUDA: false + WITH_CUDNN: false + CI_OS_NAME: linux + # TO-DO (not passing) + # # Ubuntu 20.04 - Python - CMake - OpenCL + # - os: ubuntu-20.04 + # os_name: linux + # env: + # NAME: U20-python-cmake-opencl + # WITH_PYTHON: true + # WITH_CUDA: false + # WITH_CUDNN: false + # WITH_OPEN_CL: true + # CI_OS_NAME: linux + # Ubuntu 18.04 - Python - CMake - OpenCL + - os: ubuntu-18.04 + os_name: linux + env: + NAME: U18-python-cmake-opencl + WITH_PYTHON: true + WITH_CUDA: false + WITH_CUDNN: false + WITH_OPEN_CL: true + CI_OS_NAME: linux + # Ubuntu 20.04 - Python - CMake - CPU - Debug + - os: ubuntu-20.04 + os_name: linux + env: + NAME: U20-python-cmake-cpu-debug + WITH_PYTHON: true + WITH_CUDA: false + WITH_CUDNN: false + WITH_DEBUG: true + CI_OS_NAME: linux + # Ubuntu 18.04 - Python - CMake - CPU - Debug + - os: ubuntu-18.04 + os_name: linux + env: + NAME: U18-python-cmake-cpu-debug + WITH_PYTHON: true + WITH_CUDA: false + WITH_CUDNN: false + WITH_DEBUG: true + CI_OS_NAME: linux + # Ubuntu 20.04 - Python - CMake - CPU - Unity + - os: ubuntu-20.04 + os_name: linux + env: + NAME: U20-python-cmake-cpu-unity + WITH_PYTHON: true + WITH_UNITY: true + WITH_CUDA: false + WITH_CUDNN: false + CI_OS_NAME: linux + # Ubuntu 20.04 - Default - CMake - CPU + - os: ubuntu-20.04 + os_name: linux + env: + NAME: U20-default-cmake-cpu + WITH_CUDA: false + WITH_CUDNN: false + CI_OS_NAME: linux + + # Mac OSX + # Mac OSX - Python - CMake - CPU + - os: macos-10.15 + os_name: osx + env: + NAME: OSX-python-cmake-cpu + WITH_CUDA: false + WITH_CUDNN: false + WITH_PYTHON: true + CI_OS_NAME: osx + # Mac OSX - Python - CMake - OpenCL + - os: macos-10.15 + os_name: osx + env: + NAME: OSX-default-cmake-opencl + WITH_CUDA: false + WITH_CUDNN: false + WITH_OPEN_CL: true + CI_OS_NAME: osx + # Mac OSX - Python - CMake - CPU - Debug + - os: macos-10.15 + os_name: osx + env: + NAME: OSX-python-cmake-cpu-debug + WITH_CUDA: false + WITH_CUDNN: false + WITH_PYTHON: true + WITH_DEBUG: true + CI_OS_NAME: osx + # Mac OSX - Python - CMake - CPU - Unity + - os: macos-10.15 + os_name: osx + env: + NAME: OSX-python-cmake-cpu-unity + WITH_CUDA: false + WITH_CUDNN: false + WITH_PYTHON: true + WITH_UNITY: true + CI_OS_NAME: osx + # Mac OSX - Default - CMake - CPU + - os: macos-10.15 + os_name: osx + env: + NAME: OSX-default-cmake-cpu + WITH_CUDA: false + WITH_CUDNN: false + CI_OS_NAME: osx + + # TO-DO (not passing) + # Note: CUDA jobs fail in U16 because of an issue with GCC 5.5 (https://github.com/NVIDIA/apex/issues/529). GH Actions doesn't support + # GCC 5.4 and CUDA does not support newer than GCC 5.X. Thus, cuDNN (sh file only for Ubuntu 16) is no longer tested. + # # Ubuntu 16.04 + # # Ubuntu 16.04 - Default - CMake - CUDA + # - os: ubuntu-16.04 + # os_name: linux + # env: + # NAME: U16-default-cmake-cuda8 + # CI_OS_NAME: linux + + # # Deprecated (not working for the above issue between CUDA and the Ubuntu16 from GitHub Actions) + # # Ubuntu 16.04 - Default - Make - CUDA + # - os: ubuntu-16.04 + # os_name: linux + # env: + # NAME: U16-default-make-cuda + # WITH_CUDNN: false + # WITH_CMAKE: false + # CI_OS_NAME: linux + + # Ubuntu 16 no longer works +# # Ubuntu 16.04 - Python - CMake - CPU +# - os: ubuntu-16.04 +# os_name: linux +# env: +# NAME: U16-python-cmake-cpu +# WITH_PYTHON: true +# WITH_CUDA: false +# WITH_CUDNN: false +# CI_OS_NAME: linux +# # Ubuntu 16.04 - Python - CMake - OpenCL +# - os: ubuntu-16.04 +# os_name: linux +# env: +# NAME: U16-python-cmake-opencl +# WITH_PYTHON: true +# WITH_CUDA: false +# WITH_CUDNN: false +# WITH_OPEN_CL: true +# CI_OS_NAME: linux +# # Ubuntu 16.04 - Python - CMake - CPU - Debug +# - os: ubuntu-16.04 +# os_name: linux +# env: +# NAME: U16-python-cmake-cpu-debug +# WITH_PYTHON: true +# WITH_CUDA: false +# WITH_CUDNN: false +# WITH_DEBUG: true +# CI_OS_NAME: linux + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + submodules: recursive + - uses: actions/setup-python@v5 + with: + python-version: 3.8 + if: ${{ matrix.env.WITH_PYTHON }} + - name: Install (Linux) + run: scripts/CI/install_deps_ubuntu.sh + if: ${{ matrix.os_name == 'linux' }} + - name: Install (Mac OS) + run: scripts/CI/install_deps_osx.sh + if: ${{ matrix.os_name == 'osx' }} + + - name: Configure + run: scripts/CI/configure.sh + - name: Make + run: scripts/CI/run_make.sh + - name: Tests + run: scripts/CI/run_tests.sh + + - name: Docs APT packages + run: | + # The Doxygen apt-get version for Ubuntu 20 is 1.8.17, which has some bugs fixed in 1.9.1 + # run: sudo apt-get -yq install doxygen doxygen-doc doxygen-latex doxygen-gui graphviz + git clone https://github.com/doxygen/doxygen.git && cd doxygen && git checkout Release_1_9_1 + mkdir build && cd build + cmake -G "Unix Makefiles" .. + make -j`nproc` + sudo make install + if: ${{ matrix.DOCS }} + - name: Generate docs + run: | + cd ${{ github.workspace }} + echo 'Generating Doxygen code documentation...' + doxygen $DOXYFILE 2>&1 | tee doxygen.log + # Required so Doxygen links/finds the license file + cp LICENSE doxygen/html/LICENSE + # Required in order to link .github/media/ images with doc without modifying doc links. Remove if using `publish_dir: doxygen/html/` + mkdir -p doxygen_final/web/html/ && mv doxygen/html doxygen_final/web/html/doc + mkdir -p doxygen_final/web/.github/media/ && cp -rf .github/media/ doxygen_final/web/.github/ + mkdir -p doxygen_final/web/html/.github/media/ && cp -rf .github/media/ doxygen_final/web/html/.github/ + mkdir -p doxygen_final/web/html/doc/.github/media/ && cp -rf .github/media/ doxygen_final/web/html/doc/.github/ + echo 'Copying log...' + cp doxygen.log doxygen_final/doxygen.log + echo 'Copying index.html to root pointing to actual docs' + cp .github/root_index.html doxygen_final/index.html + if: ${{ matrix.DOCS }} + - name: Deploy Docs + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: doxygen_final/ + # publish_dir: doxygen/html/ # Original one, it would turn [...].github.io/openpose/web/html/doc/ into [...].github.io/openpose/, but images would not work + destination_dir: . + enable_jekyll: false + force_orphan: true + if: ${{ matrix.DOCS && github.event_name == 'push' && github.ref == 'refs/heads/master' }} diff --git a/openpose/.gitignore b/openpose/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..06a27c272c022ef7fc53b15063f5e60a9025828b --- /dev/null +++ b/openpose/.gitignore @@ -0,0 +1,139 @@ +######################### Binary Files ######################### +# Compiled Object files +*.slo +*.lo +*.o +*.cuo + +# Compiled Dynamic libraries +*.so* +*.dylib + +# Compiled Static libraries +*.lai +*.la +*.a + +# Compiled protocol buffers +*.pb.h +*.pb.cc +*_pb2.py + +# Compiled python +*.pyc + +# Compiled MATLAB +*.mex* + +# IPython notebook checkpoints +.ipynb_checkpoints + +# LevelDB files +*.sst +*.ldb +LOCK +CURRENT +MANIFEST-* + +######################### IDEs Files ######################### +# Editor temporaries +*.swp +*~ + +# Sublime Text settings +*.sublime-workspace +*.sublime-project + +# Eclipse Project settings +*.*project +.settings + +# QtCreator files +*.user + +# PyCharm files +.idea + +# OSX dir files +.DS_Store +._.DS_Store + +# Vim files +cscope.* +tags +.clang_complete +.vim + +######################### Windows (Visual Studio) Files ######################### +*.db +*.deps +*.obj +*.opendb +*.pdb + +######################### Windows (Visual Studio) Folders and Compressed files ######################### +*.vs/ +*x64/ +# Allowing this file (removed *.user for Qt) +!*.vcxproj.user + +######################### Caffe Files / Folders ######################### +# User's build configuration +Makefile +Makefile.config + +# Data and models are either + # 1. reference, and not casually committed + # 2. custom, and live on their own unless they're deliberated contributed +distribute/ +*.caffemodel +*.caffemodel.h5 +*.solverstate +*.solverstate.h5 +*.binaryproto +*leveldb +*lmdb + +# Camera parameters +*.xml + +######################### 3rd-party Folders and Zip Files ######################### +3rdparty/caffe/.git +3rdparty/caffe/.github +3rdparty/asio/ +3rdparty/eigen/ +3rdparty/windows/caffe/ +3rdparty/windows/caffe_cpu/ +3rdparty/windows/caffe_opencl/ +3rdparty/windows/caffe3rdparty/ +3rdparty/windows/opencv/ +3rdparty/windows/freeglut/ +3rdparty/windows/spinnaker/ +3rdparty/*zip +3rdparty/windows/*zip + +######################### Compilation (build, distribute & bins) Files / Folders ######################### +*.bin +*.testbin +build +build* +.build* +*cmake_build +distribute/* +python/caffe/proto/ + +######################### Generated Documentation ######################### +_site +docs/_site +docs/dev +docs/gathered +doxygen +html/ + +######################### Video Files ######################### +# Testing videos +*.mp4 +*.mov + +######################### Validation Scripts & Testing ######################### +output*/ diff --git a/openpose/.gitmodules b/openpose/.gitmodules new file mode 100644 index 0000000000000000000000000000000000000000..4e1c0d5f1b93f83eb2431a36075916bbf6dddad6 --- /dev/null +++ b/openpose/.gitmodules @@ -0,0 +1,6 @@ +[submodule "3rdparty/caffe"] + path = 3rdparty/caffe + url = https://github.com/CMU-Perceptual-Computing-Lab/caffe.git +[submodule "3rdparty/pybind11"] + path = 3rdparty/pybind11 + url = https://github.com/pybind/pybind11.git diff --git a/openpose/3rdparty/Versions.txt b/openpose/3rdparty/Versions.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b3503db1a3dfe9f3605d7f74b676bc0f9a4eea3 --- /dev/null +++ b/openpose/3rdparty/Versions.txt @@ -0,0 +1,38 @@ +Asio: + - Version 1.12.1. + - Link: https://think-async.com/Asio/Download + +Eigen: + - Version 3.3.8 + - Link: http://eigen.tuxfamily.org/index.php + +Unix: + - Caffe: + - Version 1.0.0, extracted from GitHub from its master branch. + - Link: https://github.com/BVLC/caffe + - GitHub SHA: 864520713a4c5ffae7382ced5d34e4cadc608473 + + - Spinnaker: + - Tested on Spinnaker 1.13.0.31 SDK - Linux Ubuntu 16.04 (64-bit) - 05/25/2018 - 41.580MB. + - Prerequisites: https://www.ptgrey.com/tan/10685 + +Windows: + - Caffe & Caffe dependencies (caffe3rdparty): + - Version 1.0.0, extracted from GitHub from its master branch. + - Link: https://github.com/BVLC/caffe/tree/windows + + - FreeGLUT (only for the 3-D reconstruction demo): + - Version 3.0.0-2 (MSVC), extracted from their oficial website. + - Link: https://www.transmissionzero.co.uk/software/freeglut-devel/ + + - OpenCV: + - Version 4.5.0, extracted from their oficial website: section `Releases`, subsection `OpenCV - 4.5.0`, `Windows` version. + - Link: https://opencv.org/releases/ + + - Unzip: + - Version 5.52. + - Link: http://stahlworks.com/dev/?tool=zipunzip + + - Wget: + - Version wget-1.20.3-win64. + - Link: https://eternallybored.org/misc/wget/ diff --git a/openpose/3rdparty/windows/getCaffe.bat b/openpose/3rdparty/windows/getCaffe.bat new file mode 100644 index 0000000000000000000000000000000000000000..63a289f693fce97a70950071c34d643f2be24e13 --- /dev/null +++ b/openpose/3rdparty/windows/getCaffe.bat @@ -0,0 +1,22 @@ +:: Avoid printing all the comments in the Windows cmd +@echo off + +SET UNZIP_EXE=unzip\unzip.exe +SET WGET_EXE=wget\wget.exe + +:: Download temporary zip +echo ----- Downloading Caffe ----- +SET CAFEE_FOLDER=caffe\ +SET ZIP_NAME=caffe_16_2020_11_14.zip +SET ZIP_FULL_PATH=%CAFEE_FOLDER%%ZIP_NAME% +%WGET_EXE% -c http://vcl.snu.ac.kr/OpenPose/3rdparty/windows/%ZIP_NAME% -P %CAFEE_FOLDER% +echo: + +echo ----- Unzipping Caffe ----- +%UNZIP_EXE% %ZIP_FULL_PATH% +echo: + +echo ----- Deleting Temporary Zip File %ZIP_FULL_PATH% ----- +del "%ZIP_FULL_PATH%" + +echo ----- Caffe Downloaded and Unzipped ----- diff --git a/openpose/3rdparty/windows/getCaffe3rdparty.bat b/openpose/3rdparty/windows/getCaffe3rdparty.bat new file mode 100644 index 0000000000000000000000000000000000000000..ac4b5f97f08ae6b2bf6761bdc0d91e2abef8dd05 --- /dev/null +++ b/openpose/3rdparty/windows/getCaffe3rdparty.bat @@ -0,0 +1,22 @@ +:: Avoid printing all the comments in the Windows cmd +@echo off + +SET UNZIP_EXE=unzip\unzip.exe +SET WGET_EXE=wget\wget.exe + +:: Download temporary zip +echo ----- Downloading Caffe ----- +SET CAFEE_FOLDER=caffe3rdparty\ +SET ZIP_NAME=caffe3rdparty_16_2020_11_14.zip +SET ZIP_FULL_PATH=%CAFEE_FOLDER%%ZIP_NAME% +%WGET_EXE% -c http://vcl.snu.ac.kr/OpenPose/3rdparty/windows/%ZIP_NAME% -P %CAFEE_FOLDER% +echo: + +echo ----- Unzipping Caffe ----- +%UNZIP_EXE% %ZIP_FULL_PATH% +echo: + +echo ----- Deleting Temporary Zip File %ZIP_FULL_PATH% ----- +del "%ZIP_FULL_PATH%" + +echo ----- Caffe Downloaded and Unzipped ----- diff --git a/openpose/3rdparty/windows/getFreeglut.bat b/openpose/3rdparty/windows/getFreeglut.bat new file mode 100644 index 0000000000000000000000000000000000000000..16ddef4af9ce4b55150aae2c5974f1b324e55907 --- /dev/null +++ b/openpose/3rdparty/windows/getFreeglut.bat @@ -0,0 +1,22 @@ +:: Avoid printing all the comments in the Windows cmd +@echo off + +SET UNZIP_EXE=unzip\unzip.exe +SET WGET_EXE=wget\wget.exe + +:: Download temporary zip +echo ----- Downloading Caffe ----- +SET FREEGLUT_FOLDER=freeglut\ +SET ZIP_NAME=freeglut_2018_01_14.zip +SET ZIP_FULL_PATH=%FREEGLUT_FOLDER%%ZIP_NAME% +%WGET_EXE% -c http://vcl.snu.ac.kr/OpenPose/3rdparty/windows/%ZIP_NAME% -P %FREEGLUT_FOLDER% +echo: + +echo ----- Unzipping Caffe ----- +%UNZIP_EXE% %ZIP_FULL_PATH% +echo: + +echo ----- Deleting Temporary Zip File %ZIP_FULL_PATH% ----- +del "%ZIP_FULL_PATH%" + +echo ----- Caffe Downloaded and Unzipped ----- diff --git a/openpose/3rdparty/windows/getOpenCV.bat b/openpose/3rdparty/windows/getOpenCV.bat new file mode 100644 index 0000000000000000000000000000000000000000..73661c86c4162c8b8213d6647ffee68abd6778b5 --- /dev/null +++ b/openpose/3rdparty/windows/getOpenCV.bat @@ -0,0 +1,22 @@ +:: Avoid printing all the comments in the Windows cmd +@echo off + +SET UNZIP_EXE=unzip\unzip.exe +SET WGET_EXE=wget\wget.exe + +:: Download temporary zip +echo ----- Downloading OpenCV ----- +SET OPENCV_FOLDER=opencv\ +SET ZIP_NAME=opencv_450_v15_2020_11_18.zip +SET ZIP_FULL_PATH=%OPENCV_FOLDER%%ZIP_NAME% +%WGET_EXE% -c http://vcl.snu.ac.kr/OpenPose/3rdparty/windows/%ZIP_NAME% -P %OPENCV_FOLDER% +echo: + +echo ----- Unzipping OpenCV ----- +%UNZIP_EXE% %ZIP_FULL_PATH% +echo: + +echo ----- Deleting Temporary Zip File %ZIP_FULL_PATH% ----- +del "%ZIP_FULL_PATH%" + +echo ----- OpenCV Downloaded and Unzipped ----- diff --git a/openpose/3rdparty/windows/getSpinnaker.bat b/openpose/3rdparty/windows/getSpinnaker.bat new file mode 100644 index 0000000000000000000000000000000000000000..6bdc42c3c246e546c86a20730268f6f34d0081ac --- /dev/null +++ b/openpose/3rdparty/windows/getSpinnaker.bat @@ -0,0 +1,22 @@ +:: Avoid printing all the comments in the Windows cmd +@echo off + +SET UNZIP_EXE=unzip\unzip.exe +SET WGET_EXE=wget\wget.exe + +:: Download temporary zip +echo ----- Downloading Caffe ----- +SET SPINNAKER_FOLDER=spinnaker\ +SET ZIP_NAME=spinnaker_2018_01_24.zip +SET ZIP_FULL_PATH=%SPINNAKER_FOLDER%%ZIP_NAME% +%WGET_EXE% -c http://vcl.snu.ac.kr/OpenPose/3rdparty/windows/%ZIP_NAME% -P %SPINNAKER_FOLDER% +echo: + +echo ----- Unzipping Caffe ----- +%UNZIP_EXE% %ZIP_FULL_PATH% +echo: + +:: echo ----- Deleting Temporary Zip File %ZIP_FULL_PATH% ----- +:: del "%ZIP_FULL_PATH%" + +echo ----- Caffe Downloaded and Unzipped ----- diff --git a/openpose/3rdparty/windows/wget/COPYING b/openpose/3rdparty/windows/wget/COPYING new file mode 100644 index 0000000000000000000000000000000000000000..e60008693e017bec1b4eb49c84be3898e26fcf2a --- /dev/null +++ b/openpose/3rdparty/windows/wget/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program 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. + + This program 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 this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/openpose/3rdparty/windows/wget/Version_wget-1.20.3-win64.txt b/openpose/3rdparty/windows/wget/Version_wget-1.20.3-win64.txt new file mode 100644 index 0000000000000000000000000000000000000000..c7a8ff0903518f68daccf3736e9ab25ae2e27a61 --- /dev/null +++ b/openpose/3rdparty/windows/wget/Version_wget-1.20.3-win64.txt @@ -0,0 +1,2 @@ +Version wget-1.20.3-win64 from: +- https://eternallybored.org/misc/wget/ diff --git a/openpose/3rdparty/windows/wget/wget.exe b/openpose/3rdparty/windows/wget/wget.exe new file mode 100644 index 0000000000000000000000000000000000000000..339772d9f2d2cc7d560273c2e6013b538a1a7a42 --- /dev/null +++ b/openpose/3rdparty/windows/wget/wget.exe @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c0e27b7f6698327ff63b03fccc0e45eff1dc69a571c1c3f6c934ef7273b1562f +size 4923280 diff --git a/openpose/3rdparty/windows/wget/wget.exe.debug b/openpose/3rdparty/windows/wget/wget.exe.debug new file mode 100644 index 0000000000000000000000000000000000000000..d9fc259077ac1e36d02410b5af91b12471b18f2d --- /dev/null +++ b/openpose/3rdparty/windows/wget/wget.exe.debug @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:19b30f747d8823cc77c36c8199e7cefc0a507a6fade4dcd5856d3afb3644aeb6 +size 9726237 diff --git a/openpose/3rdparty/windows/wget/wget.html b/openpose/3rdparty/windows/wget/wget.html new file mode 100644 index 0000000000000000000000000000000000000000..71a9c02fe4406ef942ef05c8b1f8d62753562016 --- /dev/null +++ b/openpose/3rdparty/windows/wget/wget.html @@ -0,0 +1,3704 @@ + + + + + + + + + +WGET + + + + +

WGET

+ +NAME
+SYNOPSIS
+DESCRIPTION
+OPTIONS
+ENVIRONMENT
+EXIT STATUS
+FILES
+BUGS
+SEE ALSO
+AUTHOR
+COPYRIGHT
+ +
+ + +

NAME + +

+ + +

Wget - +The non-interactive network downloader.

+ +

SYNOPSIS + +

+ + +

wget +[option]... [ URL ]...

+ +

DESCRIPTION + +

+ + + +

GNU +Wget is a free utility for non-interactive download of files +from the Web. It supports HTTP, HTTPS, and +FTP protocols, as well as retrieval through +HTTP proxies.

+ +

Wget is +non-interactive, meaning that it can work in the background, +while the user is not logged on. This allows you to start a +retrieval and disconnect from the system, letting Wget +finish the work. By contrast, most of the Web browsers +require constant user’s presence, which can be a great +hindrance when transferring a lot of data.

+ +

Wget can follow +links in HTML, XHTML, and CSS +pages, to create local versions of remote web sites, fully +recreating the directory structure of the original site. +This is sometimes referred to as "recursive +downloading." While doing that, Wget respects the Robot +Exclusion Standard (/robots.txt). Wget can be +instructed to convert the links in downloaded files to point +at the local files, for offline viewing.

+ +

Wget has been +designed for robustness over slow or unstable network +connections; if a download fails due to a network problem, +it will keep retrying until the whole file has been +retrieved. If the server supports regetting, it will +instruct the server to continue the download from where it +left off.

+ +

OPTIONS + +

+ + +

Option +Syntax
+Since Wget uses GNU getopt to process +command-line arguments, every option has a long form along +with the short one. Long options are more convenient to +remember, but take time to type. You may freely mix +different option styles, or specify options after the +command-line arguments. Thus you may write:

+ +
        wget -r --tries=10 http://fly.srk.fer.hr/ -o log
+ + +

The space +between the option accepting an argument and the argument +may be omitted. Instead of -o log you can write +-olog.

+ +

You may put +several options that do not require arguments together, +like:

+ +
        wget -drc <URL>
+ + +

This is +completely equivalent to:

+ +
        wget -d -r -c <URL>
+ + +

Since the +options can be specified after the arguments, you may +terminate them with --. So the following +will try to download URL -x, +reporting failure to log:

+ +
        wget -o log -- -x
+ + +

The options +that accept comma-separated lists all respect the convention +that specifying an empty list clears its value. This can be +useful to clear the .wgetrc settings. For instance, +if your .wgetrc sets +"exclude_directories" to +/cgi-bin, the following example will first +reset it, and then set it to exclude /~nobody and +/~somebody. You can also clear the lists in +.wgetrc.

+ +
        wget -X " -X /~nobody,/~somebody
+ + +

Most options +that do not accept arguments are boolean options, so +named because their state can be captured with a yes-or-no +("boolean") variable. For example, +--follow-ftp tells Wget to follow +FTP links from HTML files and, +on the other hand, --no-glob tells +it not to perform file globbing on FTP URLs. +A boolean option is either affirmative or +negative (beginning with --no). +All such options share several properties.

+ +

Unless stated +otherwise, it is assumed that the default behavior is the +opposite of what the option accomplishes. For example, the +documented existence of +--follow-ftp assumes that the +default is to not follow FTP links +from HTML pages.

+ +

Affirmative +options can be negated by prepending the +--no- to the option name; negative +options can be negated by omitting the +--no- prefix. This might seem +superfluous---if the default for an +affirmative option is to not do something, then why provide +a way to explicitly turn it off? But the startup file may in +fact change the default. For instance, using +"follow_ftp = on" in .wgetrc makes +Wget follow FTP links by default, and +using --no-follow-ftp is the +only way to restore the factory default from the command +line.

+ +

Basic +Startup Options

+ + + + + + +
+ + +

-V

+
+ + +

--version

+ +

Display the version of +Wget.

+ + + + + + +
+ + +

-h

+
+ +

--help

+ +

Print a help message describing +all of Wget’s command-line options.

+ + + + + + +
+ + +

-b

+
+ + +

--background

+ +

Go to background immediately +after startup. If no output file is specified via the +-o, output is redirected to +wget-log.

+ +

-e command +
+--execute
command

+ +

Execute command as if it +were a part of .wgetrc. A command thus invoked will +be executed after the commands in .wgetrc, +thus taking precedence over them. If you need to specify +more than one wgetrc command, use multiple instances of +-e.

+ +

Logging and +Input File Options
+-o
logfile
+--output-file=
logfile

+ +

Log all messages to +logfile. The messages are normally reported to +standard error.

+ +

-a logfile +
+--append-output=
logfile

+ +

Append to logfile. This +is the same as -o, only it appends to +logfile instead of overwriting the old log file. If +logfile does not exist, a new file is created.

+ + + + + + +
+ + +

-d

+
+ +

--debug

+ +

Turn on debug output, meaning +various information important to the developers of Wget if +it does not work properly. Your system administrator may +have chosen to compile Wget without debug support, in which +case -d will not work. Please note that +compiling with debug support is always +safe---Wget compiled with the debug +support will not print any debug info unless +requested with -d.

+ + + + + + +
+ + +

-q

+
+ +

--quiet

+ +

Turn off Wget’s +output.

+ + + + + + +
+ + +

-v

+
+ + +

--verbose

+ +

Turn on verbose output, with +all the available data. The default output is verbose.

+ + + + + + +
+ + +

-nv

+
+ + +

--no-verbose

+ +

Turn off verbose without being +completely quiet (use -q for that), which means +that error messages and basic information still get +printed.

+ + +

--report-speed=type

+ +

Output bandwidth as +type. The only accepted value is bits.

+ +

-i file +
+--input-file=
file

+ +

Read URLs from a local or +external file. If - is specified as +file, URLs are read from the standard input. (Use +./- to read from a file literally named +-.)

+ +

If this +function is used, no URLs need be present on the command +line. If there are URLs both on the command line and in an +input file, those on the command lines will be the first +ones to be retrieved. If +--force-html is not specified, then +file should consist of a series of URLs, one per +line.

+ +

However, if you +specify --force-html, the document +will be regarded as html. In that case you may have +problems with relative links, which you can solve either by +adding "<base +href="url">" to the +documents or by specifying +--base=url on the command +line.

+ +

If the +file is an external one, the document will be +automatically treated as html if the Content-Type +matches text/html. Furthermore, the +file’s location will be implicitly used as base +href if none was specified.

+ + +

--input-metalink=file

+ +

Downloads files covered in +local Metalink file. Metalink version 3 and 4 are +supported.

+ + +

--keep-badhash

+ +

Keeps downloaded +Metalink’s files with a bad hash. It appends .badhash +to the name of Metalink’s files which have a checksum +mismatch, except without overwriting existing files.

+ + +

--metalink-over-http

+ +

Issues HTTP HEAD +request instead of GET and extracts Metalink +metadata from response headers. Then it switches to Metalink +download. If no valid Metalink metadata is found, it falls +back to ordinary HTTP download. Enables +Content-Type: application/metalink4+xml files +download/processing.

+ + +

--metalink-index=number

+ +

Set the Metalink +application/metalink4+xml metaurl ordinal +NUMBER. From 1 to the total number of +"application/metalink4+xml" available. Specify 0 +or inf to choose the first good one. Metaurls, such +as those from a +--metalink-over-http, may +have been sorted by priority key’s value; keep this in +mind to choose the right NUMBER.

+ + +

--preferred-location

+ +

Set preferred location for +Metalink resources. This has effect if multiple resources +with same priority are available.

+ +

--xattr

+ +

Enable use of file +system’s extended attributes to save the original +URL and the Referer HTTP +header value if used.

+ +

Be aware that +the URL might contain private information +like access tokens or credentials.

+ + + + + + +
+ + +

-F

+
+ + +

--force-html

+ +

When input is read from a file, +force it to be treated as an HTML file. This +enables you to retrieve relative links from existing +HTML files on your local disk, by adding +"<base +href="url">" to +HTML, or using the --base +command-line option.

+ +

-B +URL
+--base=
URL

+ +

Resolves relative links using +URL as the point of reference, when +reading links from an HTML file specified via +the -i/--input-file +option (together with --force-html, +or when the input file was fetched remotely from a server +describing it as HTML ). This is equivalent +to the presence of a "BASE" tag in the +HTML input file, with +URL as the value for the +"href" attribute.

+ +

For instance, +if you specify http://foo/bar/a.html for +URL , and Wget reads +../baz/b.html from the input file, it would be +resolved to http://foo/baz/b.html.

+ +

--config= +FILE

+ +

Specify the location of a +startup file you wish to use instead of the default one(s). +Use --no-config to disable reading of +config files. If both --config and +--no-config are given, +--no-config is ignored.

+ + +

--rejected-log=logfile

+ +

Logs all URL +rejections to logfile as comma separated values. The +values include the reason of rejection, the +URL and the parent URL it was +found in.

+ +

Download +Options
+--bind-address=
+ADDRESS

+ +

When making client +TCP/IP connections, bind to +ADDRESS on the local machine. +ADDRESS may be specified as a hostname +or IP address. This option can be useful if +your machine is bound to multiple IPs.

+ + +

--bind-dns-address= +ADDRESS

+ +

[libcares only] This address +overrides the route for DNS requests. If you +ever need to circumvent the standard settings from +/etc/resolv.conf, this option together with +--dns-servers is your friend. +ADDRESS must be specified either as +IPv4 or IPv6 address. Wget needs to be built with libcares +for this option to be available.

+ + +

--dns-servers= +ADDRESSES

+ +

[libcares only] The given +address(es) override the standard nameserver addresses, e.g. +as configured in /etc/resolv.conf. +ADDRESSES may be specified either as +IPv4 or IPv6 addresses, comma-separated. Wget needs to be +built with libcares for this option to be available.

+ +

-t number +
+--tries=
number

+ +

Set number of tries to +number. Specify 0 or inf for infinite +retrying. The default is to retry 20 times, with the +exception of fatal errors like "connection +refused" or "not found" (404), which are not +retried.

+ +

-O file +
+--output-document=
file

+ +

The documents will not be +written to the appropriate files, but all will be +concatenated together and written to file. If +- is used as file, documents will be +printed to standard output, disabling link conversion. (Use +./- to print to a file literally named +-.)

+ +

Use of +-O is not intended to mean simply +"use the name file instead of the one in the +URL ;" rather, it is analogous to shell +redirection: wget -O file http://foo is +intended to work like wget -O - http://foo +> file; file will be truncated immediately, +and all downloaded content will be written there.

+ +

For this +reason, -N (for timestamp-checking) is not +supported in combination with -O: since +file is always newly created, it will always have a +very new timestamp. A warning will be issued if this +combination is used.

+ +

Similarly, +using -r or -p with +-O may not work as you expect: Wget won’t +just download the first file to file and then +download the rest to their normal names: all +downloaded content will be placed in file. This was +disabled in version 1.11, but has been reinstated (with a +warning) in 1.11.2, as there are some cases where this +behavior can actually have some use.

+ +

A combination +with -nc is only accepted if the given output +file does not exist.

+ +

Note that a +combination with -k is only permitted when +downloading a single document, as in that case it will just +convert all relative URIs to external ones; -k +makes no sense for multiple URIs when they’re all +being downloaded to a single file; -k can be +used only when the output is a regular file.

+ + + + + + +
+ + +

-nc

+
+ + +

--no-clobber

+ +

If a file is downloaded more +than once in the same directory, Wget’s behavior +depends on a few options, including -nc. In +certain cases, the local file will be clobbered, or +overwritten, upon repeated download. In other cases it will +be preserved.

+ +

When running +Wget without -N, -nc, +-r, or -p, downloading the same +file in the same directory will result in the original copy +of file being preserved and the second copy being +named file.1. If that file is downloaded yet +again, the third copy will be named file.2, +and so on. (This is also the behavior with -nd, +even if -r or -p are in effect.) +When -nc is specified, this behavior is +suppressed, and Wget will refuse to download newer copies of +file. Therefore, +""no-clobber"" is +actually a misnomer in this +mode---it’s not clobbering +that’s prevented (as the numeric suffixes were already +preventing clobbering), but rather the multiple version +saving that’s prevented.

+ +

When running +Wget with -r or -p, but without +-N, -nd, or -nc, +re-downloading a file will result in the new copy simply +overwriting the old. Adding -nc will prevent +this behavior, instead causing the original version to be +preserved and any newer copies on the server to be +ignored.

+ +

When running +Wget with -N, with or without -r +or -p, the decision as to whether or not to +download a newer copy of a file depends on the local and +remote timestamp and size of the file. -nc may +not be specified at the same time as -N.

+ +

A combination +with +-O/--output-document +is only accepted if the given output file does not +exist.

+ +

Note that when +-nc is specified, files with the suffixes +.html or .htm will be loaded from the local +disk and parsed as if they had been retrieved from the +Web.

+ + +

--backups=backups

+ +

Before (over)writing a file, +back up an existing file by adding a .1 suffix +(_1 on VMS ) to the file name. Such +backup files are rotated to .2, .3, and so on, +up to backups (and lost beyond that).

+ + +

--no-netrc

+ +

Do not try to obtain +credentials from .netrc file. By default +.netrc file is searched for credentials in case none +have been passed on command line and authentication is +required.

+ + + + + + +
+ + +

-c

+
+ + +

--continue

+ +

Continue getting a +partially-downloaded file. This is useful when you want to +finish up a download started by a previous instance of Wget, +or by another program. For instance:

+ +
        wget -c ftp://sunsite.doc.ic.ac.uk/ls-lR.Z
+ + +

If there is a +file named ls-lR.Z in the current directory, +Wget will assume that it is the first portion of the remote +file, and will ask the server to continue the retrieval from +an offset equal to the length of the local file.

+ +

Note that you +don’t need to specify this option if you just want the +current invocation of Wget to retry downloading a file +should the connection be lost midway through. This is the +default behavior. -c only affects resumption of +downloads started prior to this invocation of Wget, +and whose local files are still sitting around.

+ +

Without +-c, the previous example would just download +the remote file to ls-lR.Z.1, leaving the +truncated ls-lR.Z file alone.

+ +

If you use +-c on a non-empty file, and the server does not +support continued downloading, Wget will restart the +download from scratch and overwrite the existing file +entirely.

+ +

Beginning with +Wget 1.7, if you use -c on a file which is of +equal size as the one on the server, Wget will refuse to +download the file and print an explanatory message. The same +happens when the file is smaller on the server than locally +(presumably because it was changed on the server since your +last download attempt)---because +"continuing" is not meaningful, no download +occurs.

+ +

On the other +side of the coin, while using -c, any file +that’s bigger on the server than locally will be +considered an incomplete download and only +"(length(remote) - length(local))" +bytes will be downloaded and tacked onto the end of the +local file. This behavior can be desirable in certain +cases---for instance, you can use wget +-c to download just the new portion that’s +been appended to a data collection or log file.

+ +

However, if the +file is bigger on the server because it’s been +changed, as opposed to just appended to, +you’ll end up with a garbled file. Wget has no way of +verifying that the local file is really a valid prefix of +the remote file. You need to be especially careful of this +when using -c in conjunction with +-r, since every file will be considered as an +"incomplete download" candidate.

+ +

Another +instance where you’ll get a garbled file if you try to +use -c is if you have a lame +HTTP proxy that inserts a "transfer +interrupted" string into the local file. In the future +a "rollback" option may be added to deal with this +case.

+ +

Note that +-c only works with FTP servers +and with HTTP servers that support the +"Range" header.

+ + +

--start-pos= +OFFSET

+ +

Start downloading at zero-based +position OFFSET . Offset may be +expressed in bytes, kilobytes with the ‘k’ +suffix, or megabytes with the ‘m’ suffix, +etc.

+ + +

--start-pos +has higher precedence over --continue. +When --start-pos and +--continue are both specified, wget will +emit a warning then proceed as if +--continue was absent.

+ +

Server support +for continued download is required, otherwise +--start-pos cannot help. See +-c for details.

+ + +

--progress=type

+ +

Select the type of the progress +indicator you wish to use. Legal indicators are +"dot" and "bar".

+ +

The +"bar" indicator is used by default. It draws an +ASCII progress bar graphics (a.k.a +"thermometer" display) indicating the status of +retrieval. If the output is not a TTY, the +"dot" bar will be used by default.

+ +

Use +--progress=dot to switch to the +"dot" display. It traces the retrieval by printing +dots on the screen, each dot representing a fixed amount of +downloaded data.

+ +

The progress +type can also take one or more parameters. The +parameters vary based on the type selected. +Parameters to type are passed by appending them to +the type sperated by a colon (:) like this: +--progress=type:parameter1:parameter2.

+ +

When using the +dotted retrieval, you may set the style by specifying +the type as dot:style. Different styles assign +different meaning to one dot. With the +"default" style each dot represents 1K, +there are ten dots in a cluster and 50 dots in a line. The +"binary" style has a more +"computer"-like +orientation---8K dots, 16-dots +clusters and 48 dots per line (which makes for 384K lines). +The "mega" style is suitable for +downloading large files---each dot +represents 64K retrieved, there are eight dots in a cluster, +and 48 dots on each line (so each line contains 3M). If +"mega" is not enough then you can use the +"giga" style---each dot +represents 1M retrieved, there are eight dots in a cluster, +and 32 dots on each line (so each line contains 32M).

+ +

With +--progress=bar, there are currently two +possible parameters, force and noscroll.

+ +

When the output +is not a TTY, the progress bar always falls +back to "dot", even if +--progress=bar was passed to Wget during +invocation. This behaviour can be overridden and the +"bar" output forced by using the "force" +parameter as --progress=bar:force.

+ +

By default, the +bar style progress bar scroll the name of the file +from left to right for the file being downloaded if the +filename exceeds the maximum length allotted for its +display. In certain cases, such as with +--progress=bar:force, one may not want +the scrolling filename in the progress bar. By passing the +"noscroll" parameter, Wget can be forced to +display as much of the filename as possible without +scrolling through it.

+ +

Note that you +can set the default style using the +"progress" command in .wgetrc. +That setting may be overridden from the command line. For +example, to force the bar output without scrolling, use +--progress=bar:force:noscroll.

+ + +

--show-progress

+ +

Force wget to display the +progress bar in any verbosity.

+ +

By default, +wget only displays the progress bar in verbose mode. One may +however, want wget to display the progress bar on screen in +conjunction with any other verbosity modes like +--no-verbose or +--quiet. This is often a desired a +property when invoking wget to download several small/large +files. In such a case, wget could simply be invoked with +this parameter to get a much cleaner output on the +screen.

+ +

This option +will also force the progress bar to be printed to +stderr when used alongside the +--output-file option.

+ + + + + + +
+ + +

-N

+
+ + +

--timestamping

+ +

Turn on time-stamping.

+ + +

--no-if-modified-since

+ +

Do not send If-Modified-Since +header in -N mode. Send preliminary +HEAD request instead. This has only effect in +-N mode.

+ + +

--no-use-server-timestamps

+ +

Don’t set the local +file’s timestamp by the one on the server.

+ +

By default, +when a file is downloaded, its timestamps are set to match +those from the remote file. This allows the use of +--timestamping on subsequent invocations +of wget. However, it is sometimes useful to base the local +file’s timestamp on when it was actually downloaded; +for that purpose, the +--no-use-server-timestamps +option has been provided.

+ + + + + + +
+ + +

-S

+
+ + +

--server-response

+ +

Print the headers sent by +HTTP servers and responses sent by +FTP servers.

+ + +

--spider

+ +

When invoked with this option, +Wget will behave as a Web spider, which means that it +will not download the pages, just check that they are there. +For example, you can use Wget to check your bookmarks:

+ +
        wget --spider --force-html -i bookmarks.html
+ + +

This feature +needs much more work for Wget to get close to the +functionality of real web spiders.

+ +

-T seconds
+--timeout=
seconds

+ +

Set the network timeout to +seconds seconds. This is equivalent to specifying +--dns-timeout, +--connect-timeout, and +--read-timeout, all at the same +time.

+ +

When +interacting with the network, Wget can check for timeout and +abort the operation if it takes too long. This prevents +anomalies like hanging reads and infinite connects. The only +timeout enabled by default is a 900-second read +timeout. Setting a timeout to 0 disables it altogether. +Unless you know what you are doing, it is best not to change +the default timeout settings.

+ +

All +timeout-related options accept decimal values, as well as +subsecond values. For example, 0.1 seconds is a legal +(though unwise) choice of timeout. Subsecond timeouts are +useful for checking server response times or for testing +network latency.

+ + +

--dns-timeout=seconds

+ +

Set the DNS +lookup timeout to seconds seconds. DNS +lookups that don’t complete within the specified time +will fail. By default, there is no timeout on +DNS lookups, other than that implemented by +system libraries.

+ + +

--connect-timeout=seconds

+ +

Set the connect timeout to +seconds seconds. TCP connections that +take longer to establish will be aborted. By default, there +is no connect timeout, other than that implemented by system +libraries.

+ + +

--read-timeout=seconds

+ +

Set the read (and write) +timeout to seconds seconds. The "time" of +this timeout refers to idle time: if, at any point in +the download, no data is received for more than the +specified number of seconds, reading fails and the download +is restarted. This option does not directly affect the +duration of the entire download.

+ +

Of course, the +remote server may choose to terminate the connection sooner +than this option requires. The default read timeout is 900 +seconds.

+ + +

--limit-rate=amount

+ +

Limit the download speed to +amount bytes per second. Amount may be expressed in +bytes, kilobytes with the k suffix, or megabytes with +the m suffix. For example, +--limit-rate=20k will limit the +retrieval rate to 20KB/s. This is useful when, for whatever +reason, you don’t want Wget to consume the entire +available bandwidth.

+ +

This option +allows the use of decimal numbers, usually in conjunction +with power suffixes; for example, +--limit-rate=2.5k is a legal +value.

+ +

Note that Wget +implements the limiting by sleeping the appropriate amount +of time after a network read that took less time than +specified by the rate. Eventually this strategy causes the +TCP transfer to slow down to approximately +the specified rate. However, it may take some time for this +balance to be achieved, so don’t be surprised if +limiting the rate doesn’t work well with very small +files.

+ +

-w seconds +
+--wait=
seconds

+ +

Wait the specified number of +seconds between the retrievals. Use of this option is +recommended, as it lightens the server load by making the +requests less frequent. Instead of in seconds, the time can +be specified in minutes using the "m" +suffix, in hours using "h" suffix, or in +days using "d" suffix.

+ +

Specifying a +large value for this option is useful if the network or the +destination host is down, so that Wget can wait long enough +to reasonably expect the network error to be fixed before +the retry. The waiting interval specified by this function +is influenced by +"--random-wait", which +see.

+ + +

--waitretry=seconds

+ +

If you don’t want Wget to +wait between every retrieval, but only between +retries of failed downloads, you can use this option. Wget +will use linear backoff, waiting 1 second after the +first failure on a given file, then waiting 2 seconds after +the second failure on that file, up to the maximum number of +seconds you specify.

+ +

By default, +Wget will assume a value of 10 seconds.

+ + +

--random-wait

+ +

Some web sites may perform log +analysis to identify retrieval programs such as Wget by +looking for statistically significant similarities in the +time between requests. This option causes the time between +requests to vary between 0.5 and 1.5 * wait seconds, +where wait was specified using the +--wait option, in order to mask +Wget’s presence from such analysis.

+ +

A 2001 article +in a publication devoted to development on a popular +consumer platform provided code to perform this analysis on +the fly. Its author suggested blocking at the class C +address level to ensure automated retrieval programs were +blocked despite changing DHCP-supplied addresses.

+ +

The +--random-wait option was inspired +by this ill-advised recommendation to block many unrelated +users from a web site due to the actions of one.

+ + +

--no-proxy

+ +

Don’t use proxies, even +if the appropriate *_proxy environment variable is +defined.

+ +

-Q quota +
+--quota=
quota

+ +

Specify download quota for +automatic retrievals. The value can be specified in bytes +(default), kilobytes (with k suffix), or megabytes +(with m suffix).

+ +

Note that quota +will never affect downloading a single file. So if you +specify wget -Q10k +https://example.com/ls-lR.gz, all of the +ls-lR.gz will be downloaded. The same goes even +when several URLs are specified on the command-line. +However, quota is respected when retrieving either +recursively, or from an input file. Thus you may safely type +wget -Q2m -i +sites---download will be aborted when +the quota is exceeded.

+ +

Setting quota +to 0 or to inf unlimits the download quota.

+ + +

--no-dns-cache

+ +

Turn off caching of +DNS lookups. Normally, Wget remembers the +IP addresses it looked up from +DNS so it doesn’t have to repeatedly +contact the DNS server for the same +(typically small) set of hosts it retrieves from. This cache +exists in memory only; a new Wget run will contact +DNS again.

+ +

However, it has +been reported that in some situations it is not desirable to +cache host names, even for the duration of a short-running +application like Wget. With this option Wget issues a new +DNS lookup (more precisely, a new call to +"gethostbyname" or +"getaddrinfo") each time it makes a new +connection. Please note that this option will not +affect caching that might be performed by the resolving +library or by an external caching layer, such as +NSCD.

+ +

If you +don’t understand exactly what this option does, you +probably won’t need it.

+ + +

--restrict-file-names=modes

+ +

Change which characters found +in remote URLs must be escaped during generation of local +filenames. Characters that are restricted by this +option are escaped, i.e. replaced with %HH, where +HH is the hexadecimal number that +corresponds to the restricted character. This option may +also be used to force all alphabetical cases to be either +lower- or uppercase.

+ +

By default, +Wget escapes the characters that are not valid or safe as +part of file names on your operating system, as well as +control characters that are typically unprintable. This +option is useful for changing these defaults, perhaps +because you are downloading to a non-native partition, or +because you want to disable escaping of the control +characters, or you want to further restrict characters to +only those in the ASCII range of values.

+ +

The +modes are a comma-separated set of text values. The +acceptable values are unix, windows, +nocontrol, ascii, lowercase, and +uppercase. The values unix and windows +are mutually exclusive (one will override the other), as are +lowercase and uppercase. Those last are +special cases, as they do not change the set of characters +that would be escaped, but rather force local file paths to +be converted either to lower- or uppercase.

+ +

When +"unix" is specified, Wget escapes the character +/ and the control characters in the ranges +0--31 and 128--159. This is the +default on Unix-like operating systems.

+ +

When +"windows" is given, Wget escapes the characters +\, |, /, :, ?, +", *, <, >, and the +control characters in the ranges 0--31 and +128--159. In addition to this, Wget in Windows +mode uses + instead of : to separate host and +port in local file names, and uses @ instead of +? to separate the query portion of the file name from +the rest. Therefore, a URL that would be +saved as www.xemacs.org:4300/search.pl?input=blah in +Unix mode would be saved as +www.xemacs.org+4300/search.pl@input=blah in Windows +mode. This mode is the default on Windows.

+ +

If you specify +nocontrol, then the escaping of the control +characters is also switched off. This option may make sense +when you are downloading URLs whose names contain +UTF-8 characters, on a system which can +save and display filenames in UTF-8 +(some possible byte values used in +UTF-8 byte sequences fall in the range +of values designated by Wget as "controls").

+ +

The +ascii mode is used to specify that any bytes whose +values are outside the range of ASCII +characters (that is, greater than 127) shall be escaped. +This can be useful when saving filenames whose encoding does +not match the one used locally.

+ + + + + + +
+ + +

-4

+
+ + +

--inet4-only

+ + + + + + +
+ + +

-6

+
+ + +

--inet6-only

+ +

Force connecting to IPv4 or +IPv6 addresses. With --inet4-only +or -4, Wget will only connect to IPv4 hosts, +ignoring AAAA records in DNS, +and refusing to connect to IPv6 addresses specified in URLs. +Conversely, with --inet6-only or +-6, Wget will only connect to IPv6 hosts and +ignore A records and IPv4 addresses.

+ +

Neither options +should be needed normally. By default, an IPv6-aware +Wget will use the address family specified by the +host’s DNS record. If the +DNS responds with both IPv4 and IPv6 +addresses, Wget will try them in sequence until it finds one +it can connect to. (Also see +"--prefer-family" +option described below.)

+ +

These options +can be used to deliberately force the use of IPv4 or IPv6 +address families on dual family systems, usually to aid +debugging or to deal with broken network configuration. Only +one of --inet6-only and +--inet4-only may be specified at +the same time. Neither option is available in Wget compiled +without IPv6 support.

+ + +

--prefer-family=none/IPv4/IPv6

+ +

When given a choice of several +addresses, connect to the addresses with specified address +family first. The address order returned by +DNS is used without change by default.

+ +

This avoids +spurious errors and connect attempts when accessing hosts +that resolve to both IPv6 and IPv4 addresses from IPv4 +networks. For example, www.kame.net resolves to +2001:200:0:8002:203:47ff:fea5:3085 and to +203.178.141.194. When the preferred family is +"IPv4", the IPv4 address is used first; +when the preferred family is "IPv6", the +IPv6 address is used first; if the specified value is +"none", the address order returned by +DNS is used without change.

+ +

Unlike +-4 and -6, this option +doesn’t inhibit access to any address family, it only +changes the order in which the addresses are +accessed. Also note that the reordering performed by this +option is stable---it doesn’t +affect order of addresses of the same family. That is, the +relative order of all IPv4 addresses and of all IPv6 +addresses remains intact in all cases.

+ + +

--retry-connrefused

+ +

Consider "connection +refused" a transient error and try again. Normally Wget +gives up on a URL when it is unable to +connect to the site because failure to connect is taken as a +sign that the server is not running at all and that retries +would not help. This option is for mirroring unreliable +sites whose servers tend to disappear for short periods of +time.

+ + +

--user=user +
+--password=
password

+ +

Specify the username +user and password password for both +FTP and HTTP file retrieval. +These parameters can be overridden using the +--ftp-user and +--ftp-password options for +FTP connections and the +--http-user and +--http-password options for +HTTP connections.

+ + +

--ask-password

+ +

Prompt for a password for each +connection established. Cannot be specified when +--password is being used, because they +are mutually exclusive.

+ + +

--use-askpass=command

+ +

Prompt for a user and password +using the specified command. If no command is specified then +the command in the environment variable +WGET_ASKPASS is used. If +WGET_ASKPASS is not set then the command in +the environment variable SSH_ASKPASS is +used.

+ +

You can set the +default command for use-askpass in the .wgetrc. That +setting may be overridden from the command line.

+ + +

--no-iri

+ +

Turn off internationalized +URI ( IRI ) support. Use +--iri to turn it on. IRI +support is activated by default.

+ +

You can set the +default state of IRI support using the +"iri" command in .wgetrc. That +setting may be overridden from the command line.

+ + +

--local-encoding=encoding

+ +

Force Wget to use +encoding as the default system encoding. That affects +how Wget converts URLs specified as arguments from locale to +UTF-8 for IRI +support.

+ +

Wget use the +function "nl_langinfo()" and then the +"CHARSET" environment variable to get the +locale. If it fails, ASCII is used.

+ +

You can set the +default local encoding using the +"local_encoding" command in +.wgetrc. That setting may be overridden from the +command line.

+ + +

--remote-encoding=encoding

+ +

Force Wget to use +encoding as the default remote server encoding. That +affects how Wget converts URIs found in files from remote +encoding to UTF-8 during a recursive +fetch. This options is only useful for IRI +support, for the interpretation of non-ASCII characters.

+ +

For +HTTP, remote encoding can be found in +HTTP "Content-Type" +header and in HTML +"Content-Type http-equiv" +meta tag.

+ +

You can set the +default encoding using the +"remoteencoding" command in +.wgetrc. That setting may be overridden from the +command line.

+ + +

--unlink

+ +

Force Wget to unlink file +instead of clobbering existing file. This option is useful +for downloading to the directory with hardlinks.

+ +

Directory +Options

+ + + + + + +
+ + +

-nd

+
+ + +

--no-directories

+ +

Do not create a hierarchy of +directories when retrieving recursively. With this option +turned on, all files will get saved to the current +directory, without clobbering (if a name shows up more than +once, the filenames will get extensions .n).

+ + + + + + +
+ + +

-x

+
+ + +

--force-directories

+ +

The opposite of +-nd---create a hierarchy of +directories, even if one would not have been created +otherwise. E.g. wget -x +http://fly.srk.fer.hr/robots.txt will save the +downloaded file to fly.srk.fer.hr/robots.txt.

+ + + + + + +
+ + +

-nH

+
+ + +

--no-host-directories

+ +

Disable generation of +host-prefixed directories. By default, invoking Wget with +-r http://fly.srk.fer.hr/ will create a +structure of directories beginning with +fly.srk.fer.hr/. This option disables such +behavior.

+ + +

--protocol-directories

+ +

Use the protocol name as a +directory component of local file names. For example, with +this option, wget -r http://host will +save to http/host/... rather than just +to host/....

+ + +

--cut-dirs=number

+ +

Ignore number directory +components. This is useful for getting a fine-grained +control over the directory where recursive retrieval will be +saved.

+ +

Take, for +example, the directory at +ftp://ftp.xemacs.org/pub/xemacs/. If you retrieve it +with -r, it will be saved locally under +ftp.xemacs.org/pub/xemacs/. While the +-nH option can remove the +ftp.xemacs.org/ part, you are still stuck with +pub/xemacs. This is where +--cut-dirs comes in handy; it makes +Wget not "see" number remote directory +components. Here are several examples of how +--cut-dirs option works.

+ +
        No options        -> ftp.xemacs.org/pub/xemacs/
+        -nH               -> pub/xemacs/
+        -nH --cut-dirs=1  -> xemacs/
+        -nH --cut-dirs=2  -> .
+        --cut-dirs=1      -> ftp.xemacs.org/xemacs/
+        ...
+ + +

If you just +want to get rid of the directory structure, this option is +similar to a combination of -nd and +-P. However, unlike -nd, +--cut-dirs does not lose with +subdirectories---for instance, with +-nH --cut-dirs=1, a +beta/ subdirectory will be placed to +xemacs/beta, as one would expect.

+ +

-P prefix +
+--directory-prefix=
prefix

+ +

Set directory prefix to +prefix. The directory prefix is the directory +where all other files and subdirectories will be saved to, +i.e. the top of the retrieval tree. The default is . +(the current directory).

+ + +

HTTP +Options
+--default-page=
name

+ +

Use name as the default +file name when it isn’t known (i.e., for URLs that end +in a slash), instead of index.html.

+ + + + + + +
+ + +

-E

+
+ + +

--adjust-extension

+ +

If a file of type +application/xhtml+xml or text/html is +downloaded and the URL does not end with the +regexp \.[Hh][Tt][Mm][Ll]?, this option will cause +the suffix .html to be appended to the local +filename. This is useful, for instance, when you’re +mirroring a remote site that uses .asp pages, but you +want the mirrored pages to be viewable on your stock Apache +server. Another good use for this is when you’re +downloading CGI-generated materials. A URL +like http://site.com/article.cgi?25 will be saved as +article.cgi?25.html.

+ +

Note that +filenames changed in this way will be re-downloaded every +time you re-mirror a site, because Wget can’t tell +that the local X.html file corresponds to remote +URL X (since it doesn’t yet know +that the URL produces output of type +text/html or application/xhtml+xml.

+ +

As of version +1.12, Wget will also ensure that any downloaded files of +type text/css end in the suffix .css, and the +option was renamed from +--html-extension, to better reflect +its new behavior. The old option name is still acceptable, +but should now be considered deprecated.

+ +

As of version +1.19.2, Wget will also ensure that any downloaded files with +a "Content-Encoding" of br, +compress, deflate or gzip end in the +suffix .br, .Z, .zlib and .gz +respectively.

+ +

At some point +in the future, this option may well be expanded to include +suffixes for other types of content, including content types +that are not parsed by Wget.

+ + +

--http-user=user +
+--http-password=
password

+ +

Specify the username +user and password password on an +HTTP server. According to the type of the +challenge, Wget will encode them using either the +"basic" (insecure), the +"digest", or the Windows +"NTLM" authentication scheme.

+ +

Another way to +specify username and password is in the URL +itself. Either method reveals your password to anyone who +bothers to run "ps". To prevent the +passwords from being seen, use the +--use-askpass or store them in +.wgetrc or .netrc, and make sure to protect +those files from other users with +"chmod". If the passwords are really +important, do not leave them lying in those files +either---edit the files and delete them +after Wget has started the download.

+ + +

--no-http-keep-alive

+ +

Turn off the +"keep-alive" feature for HTTP +downloads. Normally, Wget asks the server to keep the +connection open so that, when you download more than one +document from the same server, they get transferred over the +same TCP connection. This saves time and at +the same time reduces the load on the server.

+ +

This option is +useful when, for some reason, persistent (keep-alive) +connections don’t work for you, for example due to a +server bug or due to the inability of server-side scripts to +cope with the connections.

+ + +

--no-cache

+ +

Disable server-side cache. In +this case, Wget will send the remote server appropriate +directives (Cache-Control: no-cache and Pragma: +no-cache) to get the file from the remote service, +rather than returning the cached version. This is especially +useful for retrieving and flushing out-of-date documents on +proxy servers.

+ +

Caching is +allowed by default.

+ + +

--no-cookies

+ +

Disable the use of cookies. +Cookies are a mechanism for maintaining server-side state. +The server sends the client a cookie using the +"Set-Cookie" header, and the client +responds with the same cookie upon further requests. Since +cookies allow the server owners to keep track of visitors +and for sites to exchange this information, some consider +them a breach of privacy. The default is to use cookies; +however, storing cookies is not on by default.

+ + +

--load-cookies +file

+ +

Load cookies from file +before the first HTTP retrieval. file +is a textual file in the format originally used by +Netscape’s cookies.txt file.

+ +

You will +typically use this option when mirroring sites that require +that you be logged in to access some or all of their +content. The login process typically works by the web server +issuing an HTTP cookie upon receiving and +verifying your credentials. The cookie is then resent by the +browser when accessing that part of the site, and so proves +your identity.

+ +

Mirroring such +a site requires Wget to send the same cookies your browser +sends when communicating with the site. This is achieved by +--load-cookies---simply +point Wget to the location of the cookies.txt file, +and it will send the same cookies your browser would send in +the same situation. Different browsers keep textual cookie +files in different locations:
+"Netscape 4.x."

+ +

The cookies are in +~/.netscape/cookies.txt.

+ +

"Mozilla and Netscape +6.x."

+ +

Mozilla’s cookie file is +also named cookies.txt, located somewhere under +~/.mozilla, in the directory of your profile. The +full path usually ends up looking somewhat like +~/.mozilla/default/some-weird-string/cookies.txt.

+ +

"Internet +Explorer."

+ +

You can produce a cookie file +Wget can use by using the File menu, Import and Export, +Export Cookies. This has been tested with Internet Explorer +5; it is not guaranteed to work with earlier versions.

+ +

"Other browsers."

+ +

If you are using a different +browser to create your cookies, +--load-cookies will only work if +you can locate or produce a cookie file in the Netscape +format that Wget expects.

+ +

If you cannot +use --load-cookies, there might +still be an alternative. If your browser supports a +"cookie manager", you can use it to view the +cookies used when accessing the site you’re mirroring. +Write down the name and value of the cookie, and manually +instruct Wget to send those cookies, bypassing the +"official" cookie support:

+ +
        wget --no-cookies --header "Cookie: <name>=<value>"
+ + + +

--save-cookies +file

+ +

Save cookies to file +before exiting. This will not save cookies that have expired +or that have no expiry time (so-called "session +cookies"), but also see +--keep-session-cookies.

+ + +

--keep-session-cookies

+ +

When specified, causes +--save-cookies to also save session +cookies. Session cookies are normally not saved because they +are meant to be kept in memory and forgotten when you exit +the browser. Saving them is useful on sites that require you +to log in or to visit the home page before you can access +some pages. With this option, multiple Wget runs are +considered a single browser session as far as the site is +concerned.

+ +

Since the +cookie file format does not normally carry session cookies, +Wget marks them with an expiry timestamp of 0. Wget’s +--load-cookies recognizes those as +session cookies, but it might confuse other browsers. Also +note that cookies so loaded will be treated as other session +cookies, which means that if you want +--save-cookies to preserve them +again, you must use +--keep-session-cookies +again.

+ + +

--ignore-length

+ +

Unfortunately, some +HTTP servers ( CGI programs, +to be more precise) send out bogus +"Content-Length" headers, which +makes Wget go wild, as it thinks not all the document was +retrieved. You can spot this syndrome if Wget retries +getting the same document again and again, each time +claiming that the (otherwise normal) connection has closed +on the very same byte.

+ +

With this +option, Wget will ignore the +"Content-Length" +header---as if it never existed.

+ + +

--header=header-line

+ +

Send header-line along +with the rest of the headers in each HTTP +request. The supplied header is sent as-is, which means it +must contain name and value separated by colon, and must not +contain newlines.

+ +

You may define +more than one additional header by specifying +--header more than once.

+ +
        wget --header='Accept-Charset: iso-8859-2' \
+             --header='Accept-Language: hr'        \
+               http://fly.srk.fer.hr/
+ + +

Specification +of an empty string as the header value will clear all +previous user-defined headers.

+ +

As of Wget +1.10, this option can be used to override headers otherwise +generated automatically. This example instructs Wget to +connect to localhost, but to specify foo.bar in the +"Host" header:

+ +
        wget --header="Host: foo.bar" http://localhost/
+ + +

In versions of +Wget prior to 1.10 such use of --header +caused sending of duplicate headers.

+ + +

--compression=type

+ +

Choose the type of compression +to be used. Legal values are auto, gzip and +none.

+ +

If auto +or gzip are specified, Wget asks the server to +compress the file using the gzip compression format. If the +server compresses the file and responds with the +"Content-Encoding" header field set +appropriately, the file will be decompressed +automatically.

+ +

If none +is specified, wget will not ask the server to compress the +file and will not decompress any server responses. This is +the default.

+ +

Compression +support is currently experimental. In case it is turned on, +please report any bugs to +"bug-wget@gnu.org".

+ + +

--max-redirect=number

+ +

Specifies the maximum number of +redirections to follow for a resource. The default is 20, +which is usually far more than necessary. However, on those +occasions where you want to allow more (or fewer), this is +the option to use.

+ + +

--proxy-user=user +
+--proxy-password=
password

+ +

Specify the username +user and password password for authentication +on a proxy server. Wget will encode them using the +"basic" authentication scheme.

+ +

Security +considerations similar to those with +--http-password pertain here as +well.

+ + +

--referer=url

+ +

Include ‘Referer: +url’ header in HTTP request. +Useful for retrieving documents with server-side processing +that assume they are always being retrieved by interactive +web browsers and only come out properly when Referer is set +to one of the pages that point to them.

+ + +

--save-headers

+ +

Save the headers sent by the +HTTP server to the file, preceding the actual +contents, with an empty line as the separator.

+ +

-U +agent-string
+--user-agent=
agent-string

+ +

Identify as agent-string +to the HTTP server.

+ +

The +HTTP protocol allows the clients to identify +themselves using a "User-Agent" +header field. This enables distinguishing the +WWW software, usually for statistical +purposes or for tracing of protocol violations. Wget +normally identifies as Wget/version, +version being the current version number of Wget.

+ +

However, some +sites have been known to impose the policy of tailoring the +output according to the +"User-Agent"-supplied +information. While this is not such a bad idea in theory, it +has been abused by servers denying information to clients +other than (historically) Netscape or, more frequently, +Microsoft Internet Explorer. This option allows you to +change the "User-Agent" line issued +by Wget. Use of this option is discouraged, unless you +really know what you are doing.

+ +

Specifying +empty user agent with +--user-agent="" instructs +Wget not to send the "User-Agent" +header in HTTP requests.

+ + +

--post-data=string +
+--post-file=
file

+ +

Use POST as the +method for all HTTP requests and send the +specified data in the request body. +--post-data sends string as +data, whereas --post-file sends the +contents of file. Other than that, they work in +exactly the same way. In particular, they both expect +content of the form +"key1=value1&key2=value2", with +percent-encoding for special characters; the only difference +is that one expects its content as a command-line parameter +and the other accepts its content from a file. In +particular, --post-file is +not for transmitting files as form attachments: those +must appear as "key=value" data (with +appropriate percent-coding) just like everything else. Wget +does not currently support +"multipart/form-data" for +transmitting POST data; only +"application/x-www-form-urlencoded". +Only one of --post-data and +--post-file should be +specified.

+ +

Please note +that wget does not require the content to be of the form +"key1=value1&key2=value2", and +neither does it test for it. Wget will simply transmit +whatever data is provided to it. Most servers however expect +the POST data to be in the above format when +processing HTML Forms.

+ +

When sending a +POST request using the +--post-file option, Wget treats the +file as a binary file and will send every character in the +POST request without stripping trailing +newline or formfeed characters. Any other control characters +in the text will also be sent as-is in the +POST request.

+ +

Please be aware +that Wget needs to know the size of the POST +data in advance. Therefore the argument to +"--post-file" must be a +regular file; specifying a FIFO or something +like /dev/stdin won’t work. It’s not +quite clear how to work around this limitation inherent in +HTTP/1.0. Although HTTP/1.1 +introduces chunked transfer that doesn’t +require knowing the request length in advance, a client +can’t use chunked unless it knows it’s talking +to an HTTP/1.1 server. And it can’t +know that until it receives a response, which in turn +requires the request to have been completed -- a +chicken-and-egg problem.

+ +

Note: As of +version 1.15 if Wget is redirected after the +POST request is completed, its behaviour will +depend on the response code returned by the server. In case +of a 301 Moved Permanently, 302 Moved Temporarily or 307 +Temporary Redirect, Wget will, in accordance with +RFC2616, continue to send a +POST request. In case a server wants the +client to change the Request method upon redirection, it +should send a 303 See Other response code.

+ +

This example +shows how to log in to a server using POST +and then proceed to download the desired pages, presumably +only accessible to authorized users:

+ +
        # Log in to the server.  This can be done only once.
+        wget --save-cookies cookies.txt \
+             --post-data 'user=foo&password=bar' \
+             http://example.com/auth.php
+        # Now grab the page or pages we care about.
+        wget --load-cookies cookies.txt \
+             -p http://example.com/interesting/article.php
+ + +

If the server +is using session cookies to track user authentication, the +above will not work because +--save-cookies will not save them +(and neither will browsers) and the cookies.txt file +will be empty. In that case use +--keep-session-cookies along +with --save-cookies to force saving +of session cookies.

+ + +

--method=HTTP-Method

+ +

For the purpose of RESTful +scripting, Wget allows sending of other HTTP +Methods without the need to explicitly set them using +--header=Header-Line. Wget will use +whatever string is passed to it after +--method as the HTTP +Method to the server.

+ + +

--body-data=Data-String +
+--body-file=
Data-File

+ +

Must be set when additional +data needs to be sent to the server along with the Method +specified using --method. +--body-data sends string as +data, whereas --body-file sends the +contents of file. Other than that, they work in +exactly the same way.

+ +

Currently, +--body-file is not for +transmitting files as a whole. Wget does not currently +support "multipart/form-data" for +transmitting data; only +"application/x-www-form-urlencoded". +In the future, this may be changed so that wget sends the +--body-file as a complete file +instead of sending its contents to the server. Please be +aware that Wget needs to know the contents of +BODY Data in advance, and hence the argument +to --body-file should be a regular +file. See --post-file for a more +detailed explanation. Only one of +--body-data and +--body-file should be +specified.

+ +

If Wget is +redirected after the request is completed, Wget will suspend +the current method and send a GET request +till the redirection is completed. This is true for all +redirection response codes except 307 Temporary Redirect +which is used to explicitly specify that the request method +should not change. Another exception is when the +method is set to "POST", in which case +the redirection rules specified under +--post-data are followed.

+ + +

--content-disposition

+ +

If this is set to on, +experimental (not fully-functional) support for +"Content-Disposition" headers is +enabled. This can currently result in extra round-trips to +the server for a "HEAD" request, and is +known to suffer from a few bugs, which is why it is not +currently enabled by default.

+ +

This option is +useful for some file-downloading CGI programs +that use "Content-Disposition" +headers to describe what the name of a downloaded file +should be.

+ +

When combined +with --metalink-over-http and +--trust-server-names, a +Content-Type: application/metalink4+xml file is named +using the "Content-Disposition" +filename field, if available.

+ + +

--content-on-error

+ +

If this is set to on, wget will +not skip the content when the server responds with a http +status code that indicates error.

+ + +

--trust-server-names

+ +

If this is set, on a redirect, +the local file name will be based on the redirection +URL. By default the local file name is based +on the original URL. When doing recursive +retrieving this can be helpful because in many web sites +redirected URLs correspond to an underlying file structure, +while link URLs do not.

+ + +

--auth-no-challenge

+ +

If this option is given, Wget +will send Basic HTTP authentication +information (plaintext username and password) for all +requests, just like Wget 1.10.2 and prior did by +default.

+ +

Use of this +option is not recommended, and is intended only to support +some few obscure servers, which never send +HTTP authentication challenges, but accept +unsolicited auth info, say, in addition to form-based +authentication.

+ + +

--retry-on-host-error

+ +

Consider host errors, such as +"Temporary failure in name resolution", as +non-fatal, transient errors.

+ + +

--retry-on-http-error=code[,code,...]

+ +

Consider given +HTTP response codes as non-fatal, transient +errors. Supply a comma-separated list of 3-digit +HTTP response codes as argument. Useful to +work around special circumstances where retries are +required, but the server responds with an error code +normally not retried by Wget. Such errors might be 503 +(Service Unavailable) and 429 (Too Many Requests). Retries +enabled by this option are performed subject to the normal +retry timing and retry count limitations of Wget.

+ +

Using this +option is intended to support special use cases only and is +generally not recommended, as it can force retries even in +cases where the server is actually trying to decrease its +load. Please use wisely and only if you know what you are +doing.

+ + +

HTTPS +( SSL/TLS ) Options
+To support encrypted HTTP ( +HTTPS ) downloads, Wget must be compiled with +an external SSL library. The current default +is GnuTLS. In addition, Wget also supports +HSTS ( HTTP Strict Transport +Security). If Wget is compiled without SSL +support, none of these options are available.
+--secure-protocol=
protocol

+ +

Choose the secure protocol to +be used. Legal values are auto, SSLv2, +SSLv3, TLSv1, TLSv1_1, TLSv1_2, +TLSv1_3 and PFS . If +auto is used, the SSL library is given +the liberty of choosing the appropriate protocol +automatically, which is achieved by sending a TLSv1 +greeting. This is the default.

+ +

Specifying +SSLv2, SSLv3, TLSv1, TLSv1_1, +TLSv1_2 or TLSv1_3 forces the use of the +corresponding protocol. This is useful when talking to old +and buggy SSL server implementations that +make it hard for the underlying SSL library +to choose the correct protocol version. Fortunately, such +servers are quite rare.

+ +

Specifying +PFS enforces the use of the so-called +Perfect Forward Security cipher suites. In short, +PFS adds security by creating a one-time key +for each SSL connection. It has a bit more +CPU impact on client and server. We use known +to be secure ciphers (e.g. no MD4 ) and the +TLS protocol. This mode also explicitly +excludes non-PFS key exchange methods, such as +RSA.

+ + +

--https-only

+ +

When in recursive mode, only +HTTPS links are followed.

+ + +

--ciphers

+ +

Set the cipher list string. +Typically this string sets the cipher suites and other +SSL/TLS options that the user wish should be +used, in a set order of preference (GnuTLS calls it +’priority string’). This string will be fed +verbatim to the SSL/TLS engine (OpenSSL or +GnuTLS) and hence its format and syntax is dependent on +that. Wget will not process or manipulate it in any way. +Refer to the OpenSSL or GnuTLS documentation for more +information.

+ + +

--no-check-certificate

+ +

Don’t check the server +certificate against the available certificate authorities. +Also don’t require the URL host name to +match the common name presented by the certificate.

+ +

As of Wget +1.10, the default is to verify the server’s +certificate against the recognized certificate authorities, +breaking the SSL handshake and aborting the +download if the verification fails. Although this provides +more secure downloads, it does break interoperability with +some sites that worked with previous Wget versions, +particularly those using self-signed, expired, or otherwise +invalid certificates. This option forces an +"insecure" mode of operation that turns the +certificate verification errors into warnings and allows you +to proceed.

+ +

If you +encounter "certificate verification" errors or +ones saying that "common name doesn’t match +requested host name", you can use this option to bypass +the verification and proceed with the download. Only use +this option if you are otherwise convinced of the +site’s authenticity, or if you really don’t care +about the validity of its certificate. It is almost +always a bad idea not to check the certificates when +transmitting confidential or important data. For +self-signed/internal certificates, you should download +the certificate and verify against that instead of forcing +this insecure mode. If you are really sure of not desiring +any certificate verification, you can specify +--check-certificate=quiet to tell wget to +not print any warning about invalid certificates, albeit in +most cases this is the wrong thing to do.

+ + +

--certificate=file

+ +

Use the client certificate +stored in file. This is needed for servers that are +configured to require certificates from the clients that +connect to them. Normally a certificate is not required and +this switch is optional.

+ + +

--certificate-type=type

+ +

Specify the type of the client +certificate. Legal values are PEM +(assumed by default) and DER , also +known as ASN1 .

+ + +

--private-key=file

+ +

Read the private key from +file. This allows you to provide the private key in a +file separate from the certificate.

+ + +

--private-key-type=type

+ +

Specify the type of the private +key. Accepted values are PEM (the +default) and DER .

+ + +

--ca-certificate=file

+ +

Use file as the file +with the bundle of certificate authorities (" +CA" ) to verify the peers. The +certificates must be in PEM format.

+ +

Without this +option Wget looks for CA certificates at the +system-specified locations, chosen at OpenSSL installation +time.

+ + +

--ca-directory=directory

+ +

Specifies directory containing +CA certificates in PEM format. +Each file contains one CA certificate, and +the file name is based on a hash value derived from the +certificate. This is achieved by processing a certificate +directory with the "c_rehash" utility +supplied with OpenSSL. Using +--ca-directory is more efficient +than --ca-certificate when many +certificates are installed because it allows Wget to fetch +certificates on demand.

+ +

Without this +option Wget looks for CA certificates at the +system-specified locations, chosen at OpenSSL installation +time.

+ + +

--crl-file=file

+ +

Specifies a CRL +file in file. This is needed for certificates that +have been revocated by the CAs.

+ + +

--pinnedpubkey=file/hashes

+ +

Tells wget to use the specified +public key file (or hashes) to verify the peer. This can be +a path to a file which contains a single public key in +PEM or DER format, or any +number of base64 encoded sha256 hashes preceded by +"sha256//" and separated by ";"

+ +

When +negotiating a TLS or SSL +connection, the server sends a certificate indicating its +identity. A public key is extracted from this certificate +and if it does not exactly match the public key(s) provided +to this option, wget will abort the connection before +sending or receiving any data.

+ + +

--random-file=file

+ +

[OpenSSL and LibreSSL only] Use +file as the source of random data for seeding the +pseudo-random number generator on systems without +/dev/urandom.

+ +

On such systems +the SSL library needs an external source of +randomness to initialize. Randomness may be provided by +EGD (see --egd-file +below) or read from an external source specified by the +user. If this option is not specified, Wget looks for random +data in $RANDFILE or, if that is unset, in +$HOME/.rnd.

+ +

If you’re +getting the "Could not seed OpenSSL PRNG +; disabling SSL." error, you should +provide random data using some of the methods described +above.

+ + +

--egd-file=file

+ +

[OpenSSL only] Use file +as the EGD socket. EGD stands +for Entropy Gathering Daemon, a user-space program +that collects data from various unpredictable system sources +and makes it available to other programs that might need it. +Encryption software, such as the SSL library, +needs sources of non-repeating randomness to seed the random +number generator used to produce cryptographically strong +keys.

+ +

OpenSSL allows +the user to specify his own source of entropy using the +"RAND_FILE" environment variable. If this +variable is unset, or if the specified file does not produce +enough randomness, OpenSSL will read random data from +EGD socket specified using this option.

+ +

If this option +is not specified (and the equivalent startup command is not +used), EGD is never contacted. +EGD is not needed on modern Unix systems that +support /dev/urandom.

+ + +

--no-hsts

+ +

Wget supports +HSTS ( HTTP Strict Transport +Security, RFC 6797 ) by default. Use +--no-hsts to make Wget act as a +non-HSTS-compliant UA. As a consequence, Wget +would ignore all the +"Strict-Transport-Security" +headers, and would not enforce any existing +HSTS policy.

+ + +

--hsts-file=file

+ +

By default, Wget stores its +HSTS database in ~/.wget-hsts. +You can use --hsts-file to override +this. Wget will use the supplied file as the +HSTS database. Such file must conform to the +correct HSTS database format used by Wget. If +Wget cannot parse the provided file, the behaviour is +unspecified.

+ +

The +Wget’s HSTS database is a plain text +file. Each line contains an HSTS entry (ie. a +site that has issued a +"Strict-Transport-Security" +header and that therefore has specified a concrete +HSTS policy to be applied). Lines starting +with a dash ("#") are ignored by Wget. +Please note that in spite of this convenient +human-readability hand-hacking the HSTS +database is generally not a good idea.

+ +

An +HSTS entry line consists of several fields +separated by one or more whitespace:

+ + +

"<hostname> +SP [<port>] SP <include subdomains> SP +<created> SP <max-age>"

+ +

The +hostname and port fields indicate the hostname +and port to which the given HSTS policy +applies. The port field may be zero, and it will, in +most of the cases. That means that the port number will not +be taken into account when deciding whether such +HSTS policy should be applied on a given +request (only the hostname will be evaluated). When +port is different to zero, both the target hostname +and the port will be evaluated and the HSTS +policy will only be applied if both of them match. This +feature has been included for testing/development purposes +only. The Wget testsuite (in testenv/) creates +HSTS databases with explicit ports with the +purpose of ensuring Wget’s correct behaviour. Applying +HSTS policies to ports other than the default +ones is discouraged by RFC 6797 (see Appendix +B "Differences between HSTS Policy and +Same-Origin Policy"). Thus, this functionality should +not be used in production environments and port will +typically be zero. The last three fields do what they are +expected to. The field include_subdomains can either +be 1 or 0 and it signals whether the +subdomains of the target domain should be part of the given +HSTS policy as well. The created and +max-age fields hold the timestamp values of when such +entry was created (first seen by Wget) and the HSTS-defined +value ’max-age’, which states how long +should that HSTS policy remain active, +measured in seconds elapsed since the timestamp stored in +created. Once that time has passed, that +HSTS policy will no longer be valid and will +eventually be removed from the database.

+ +

If you supply +your own HSTS database via +--hsts-file, be aware that Wget may +modify the provided file if any change occurs between the +HSTS policies requested by the remote servers +and those in the file. When Wget exists, it effectively +updates the HSTS database by rewriting the +database file with the new entries.

+ +

If the supplied +file does not exist, Wget will create one. This file will +contain the new HSTS entries. If no +HSTS entries were generated (no +"Strict-Transport-Security" +headers were sent by any of the servers) then no file will +be created, not even an empty one. This behaviour applies to +the default database file (~/.wget-hsts) as +well: it will not be created until some server enforces an +HSTS policy.

+ +

Care is taken +not to override possible changes made by other Wget +processes at the same time over the HSTS +database. Before dumping the updated HSTS +entries on the file, Wget will re-read it and merge the +changes.

+ +

Using a custom +HSTS database and/or modifying an existing +one is discouraged. For more information about the potential +security threats arose from such practice, see section 14 +"Security Considerations" of RFC +6797, specially section 14.9 "Creative +Manipulation of HSTS Policy Store".

+ + +

--warc-file=file

+ +

Use file as the +destination WARC file.

+ + +

--warc-header=string

+ +

Use string into as the +warcinfo record.

+ + +

--warc-max-size=size

+ +

Set the maximum size of the +WARC files to size.

+ + +

--warc-cdx

+ +

Write CDX index +files.

+ + +

--warc-dedup=file

+ +

Do not store records listed in +this CDX file.

+ + +

--no-warc-compression

+ +

Do not compress +WARC files with GZIP.

+ + +

--no-warc-digests

+ +

Do not calculate +SHA1 digests.

+ + +

--no-warc-keep-log

+ +

Do not store the log file in a +WARC record.

+ + +

--warc-tempdir=dir

+ +

Specify the location for +temporary files created by the WARC +writer.

+ + +

FTP +Options
+--ftp-user=
user
+--ftp-password=
password

+ +

Specify the username +user and password password on an +FTP server. Without this, or the +corresponding startup option, the password defaults to +-wget@, normally used for anonymous +FTP.

+ +

Another way to +specify username and password is in the URL +itself. Either method reveals your password to anyone who +bothers to run "ps". To prevent the +passwords from being seen, store them in .wgetrc or +.netrc, and make sure to protect those files from +other users with "chmod". If the +passwords are really important, do not leave them lying in +those files either---edit the files and +delete them after Wget has started the download.

+ + +

--no-remove-listing

+ +

Don’t remove the +temporary .listing files generated by +FTP retrievals. Normally, these files contain +the raw directory listings received from FTP +servers. Not removing them can be useful for debugging +purposes, or when you want to be able to easily check on the +contents of remote server directories (e.g. to verify that a +mirror you’re running is complete).

+ +

Note that even +though Wget writes to a known filename for this file, this +is not a security hole in the scenario of a user making +.listing a symbolic link to /etc/passwd or +something and asking "root" to run Wget +in his or her directory. Depending on the options used, +either Wget will refuse to write to .listing, making +the globbing/recursion/time-stamping operation fail, +or the symbolic link will be deleted and replaced with the +actual .listing file, or the listing will be written +to a .listing.number file.

+ +

Even though +this situation isn’t a problem, though, +"root" should never run Wget in a +non-trusted user’s directory. A user could do +something as simple as linking index.html to +/etc/passwd and asking "root" to +run Wget with -N or -r so the file +will be overwritten.

+ + +

--no-glob

+ +

Turn off FTP +globbing. Globbing refers to the use of shell-like special +characters (wildcards), like *, ?, +[ and ] to retrieve more than one file from +the same directory at once, like:

+ +
        wget ftp://gnjilux.srk.fer.hr/*.msg
+ + +

By default, +globbing will be turned on if the URL +contains a globbing character. This option may be used to +turn globbing on or off permanently.

+ +

You may have to +quote the URL to protect it from being +expanded by your shell. Globbing makes Wget look for a +directory listing, which is system-specific. This is why it +currently works only with Unix FTP servers +(and the ones emulating Unix "ls" +output).

+ + +

--no-passive-ftp

+ +

Disable the use of the +passive FTP transfer mode. Passive +FTP mandates that the client connect to the +server to establish the data connection rather than the +other way around.

+ +

If the machine +is connected to the Internet directly, both passive and +active FTP should work equally well. Behind +most firewall and NAT configurations passive +FTP has a better chance of working. However, +in some rare firewall configurations, active +FTP actually works when passive +FTP doesn’t. If you suspect this to be +the case, use this option, or set +"passive_ftp=off" in your init file.

+ + +

--preserve-permissions

+ +

Preserve remote file +permissions instead of permissions set by umask.

+ + +

--retr-symlinks

+ +

By default, when retrieving +FTP directories recursively and a symbolic +link is encountered, the symbolic link is traversed and the +pointed-to files are retrieved. Currently, Wget does not +traverse symbolic links to directories to download them +recursively, though this feature may be added in the +future.

+ +

When +--retr-symlinks=no is specified, +the linked-to file is not downloaded. Instead, a matching +symbolic link is created on the local filesystem. The +pointed-to file will not be retrieved unless this recursive +retrieval would have encountered it separately and +downloaded it anyway. This option poses a security risk +where a malicious FTP Server may cause Wget +to write to files outside of the intended directories +through a specially crafted .LISTING file.

+ +

Note that when +retrieving a file (not a directory) because it was specified +on the command-line, rather than because it was recursed to, +this option has no effect. Symbolic links are always +traversed in this case.

+ + +

FTPS +Options
+--ftps-implicit

+ +

This option tells Wget to use +FTPS implicitly. Implicit FTPS +consists of initializing SSL/TLS from the +very beginning of the control connection. This option does +not send an "AUTH TLS" command: it +assumes the server speaks FTPS and directly +starts an SSL/TLS connection. If the attempt +is successful, the session continues just like regular +FTPS ("PBSZ" and +"PROT" are sent, etc.). Implicit +FTPS is no longer a requirement for +FTPS implementations, and thus many servers +may not support it. If +--ftps-implicit is passed and no +explicit port number specified, the default port for +implicit FTPS, 990, will be used, instead of +the default port for the "normal" (explicit) +FTPS which is the same as that of FTP, +21.

+ + +

--no-ftps-resume-ssl

+ +

Do not resume the +SSL/TLS session in the data channel. When +starting a data connection, Wget tries to resume the +SSL/TLS session previously started in the +control connection. SSL/TLS session +resumption avoids performing an entirely new handshake by +reusing the SSL/TLS parameters of a previous +session. Typically, the FTPS servers want it +that way, so Wget does this by default. Under rare +circumstances however, one might want to start an entirely +new SSL/TLS session in every data connection. +This is what +--no-ftps-resume-ssl is +for.

+ + +

--ftps-clear-data-connection

+ +

All the data connections will +be in plain text. Only the control connection will be under +SSL/TLS. Wget will send a "PROT +C" command to achieve this, which must be approved +by the server.

+ + +

--ftps-fallback-to-ftp

+ +

Fall back to FTP +if FTPS is not supported by the target +server. For security reasons, this option is not asserted by +default. The default behaviour is to exit with an error. If +a server does not successfully reply to the initial +"AUTH TLS" command, or in the case of +implicit FTPS, if the initial +SSL/TLS connection attempt is rejected, it is +considered that such server does not support +FTPS.

+ +

Recursive +Retrieval Options

+ + + + + + +
+ + +

-r

+
+ + +

--recursive

+ +

Turn on recursive retrieving. +The default maximum depth is 5.

+ +

-l depth +
+--level=
depth

+ +

Specify recursion maximum depth +level depth.

+ + +

--delete-after

+ +

This option tells Wget to +delete every single file it downloads, after having +done so. It is useful for pre-fetching popular pages through +a proxy, e.g.:

+ +
        wget -r -nd --delete-after http://whatever.com/~popular/page/
+ + +

The +-r option is to retrieve recursively, and +-nd to not create directories.

+ +

Note that +--delete-after deletes files on the +local machine. It does not issue the +DELE command to remote +FTP sites, for instance. Also note that when +--delete-after is specified, +--convert-links is ignored, so +.orig files are simply not created in the first +place.

+ + + + + + +
+ + +

-k

+
+ + +

--convert-links

+ +

After the download is complete, +convert the links in the document to make them suitable for +local viewing. This affects not only the visible hyperlinks, +but any part of the document that links to external content, +such as embedded images, links to style sheets, hyperlinks +to non-HTML content, etc.

+ +

Each link will +be changed in one of the two ways:

+ + + + + + + +
+ + +

+ + +

The links to files that have been downloaded by Wget +will be changed to refer to the file they point to as a +relative link.

+ +

Example: if the +downloaded file /foo/doc.html links to +/bar/img.gif, also downloaded, then the link in +doc.html will be modified to point to +../bar/img.gif. This kind of transformation works +reliably for arbitrary combinations of directories.

+ + + + + + + +
+ + +

+ + +

The links to files that have not +been downloaded by Wget will be changed to include host name +and absolute path of the location they point to.

+ +

Example: if the +downloaded file /foo/doc.html links to +/bar/img.gif (or to ../bar/img.gif), then the +link in doc.html will be modified to point to +http://hostname/bar/img.gif.

+ +

Because of +this, local browsing works reliably: if a linked file was +downloaded, the link will refer to its local name; if it was +not downloaded, the link will refer to its full Internet +address rather than presenting a broken link. The fact that +the former links are converted to relative links ensures +that you can move the downloaded hierarchy to another +directory.

+ +

Note that only +at the end of the download can Wget know which links have +been downloaded. Because of that, the work done by +-k will be performed at the end of all the +downloads.

+ + +

--convert-file-only

+ +

This option converts only the +filename part of the URLs, leaving the rest of the URLs +untouched. This filename part is sometimes referred to as +the "basename", although we avoid that term here +in order not to cause confusion.

+ +

It works +particularly well in conjunction with +--adjust-extension, although this +coupling is not enforced. It proves useful to populate +Internet caches with files downloaded from different +hosts.

+ +

Example: if +some link points to //foo.com/bar.cgi?xyz with +--adjust-extension asserted and its +local destination is intended to be +./foo.com/bar.cgi?xyz.css, then the link would be +converted to //foo.com/bar.cgi?xyz.css. Note that +only the filename part has been modified. The rest of the +URL has been left untouched, including the +net path ("//") which would otherwise be +processed by Wget and converted to the effective scheme (ie. +"http://").

+ + + + + + +
+ + +

-K

+
+ + +

--backup-converted

+ +

When converting a file, back up +the original version with a .orig suffix. Affects the +behavior of -N.

+ + + + + + +
+ + +

-m

+
+ + +

--mirror

+ +

Turn on options suitable for +mirroring. This option turns on recursion and time-stamping, +sets infinite recursion depth and keeps FTP +directory listings. It is currently equivalent to +-r -N -l inf +--no-remove-listing.

+ + + + + + +
+ + +

-p

+
+ + +

--page-requisites

+ +

This option causes Wget to +download all the files that are necessary to properly +display a given HTML page. This includes such +things as inlined images, sounds, and referenced +stylesheets.

+ +

Ordinarily, +when downloading a single HTML page, any +requisite documents that may be needed to display it +properly are not downloaded. Using -r together +with -l can help, but since Wget does not +ordinarily distinguish between external and inlined +documents, one is generally left with "leaf +documents" that are missing their requisites.

+ +

For instance, +say document 1.html contains an +"<IMG>" tag referencing +1.gif and an "<A>" tag +pointing to external document 2.html. Say that +2.html is similar but that its image is 2.gif +and it links to 3.html. Say this continues up to some +arbitrarily high number.

+ +

If one executes +the command:

+ +
        wget -r -l 2 http://<site>/1.html
+ + +

then +1.html, 1.gif, 2.html, 2.gif, +and 3.html will be downloaded. As you can see, +3.html is without its requisite 3.gif because +Wget is simply counting the number of hops (up to 2) away +from 1.html in order to determine where to stop the +recursion. However, with this command:

+ +
        wget -r -l 2 -p http://<site>/1.html
+ + +

all the above +files and 3.html’s requisite 3.gif will +be downloaded. Similarly,

+ +
        wget -r -l 1 -p http://<site>/1.html
+ + +

will cause +1.html, 1.gif, 2.html, and 2.gif +to be downloaded. One might think that:

+ +
        wget -r -l 0 -p http://<site>/1.html
+ + +

would download +just 1.html and 1.gif, but unfortunately this +is not the case, because -l 0 is equivalent to +-l inf---that is, infinite +recursion. To download a single HTML page (or +a handful of them, all specified on the command-line or in a +-i URL input file) and its (or +their) requisites, simply leave off -r and +-l:

+ +
        wget -p http://<site>/1.html
+ + +

Note that Wget +will behave as if -r had been specified, but +only that single page and its requisites will be downloaded. +Links from that page to external documents will not be +followed. Actually, to download a single page and all its +requisites (even if they exist on separate websites), and +make sure the lot displays properly locally, this author +likes to use a few options in addition to +-p:

+ +
        wget -E -H -k -K -p http://<site>/<document>
+ + +

To finish off +this topic, it’s worth knowing that Wget’s idea +of an external document link is any URL +specified in an "<A>" tag, an +"<AREA>" tag, or a +"<LINK>" tag other than +"<LINK +REL="stylesheet">".

+ + +

--strict-comments

+ +

Turn on strict parsing of +HTML comments. The default is to terminate +comments at the first occurrence of +-->.

+ +

According to +specifications, HTML comments are expressed +as SGML declarations. Declaration is +special markup that begins with <! and ends with +>, such as <!DOCTYPE ...>, that may +contain comments between a pair of -- +delimiters. HTML comments are "empty +declarations", SGML declarations without +any non-comment text. Therefore, +<!--foo--> is a valid +comment, and so is <!--one-- +--two-->, but +<!--1--2--> +is not.

+ +

On the other +hand, most HTML writers don’t perceive +comments as anything other than text delimited with +<!-- and -->, +which is not quite the same. For example, something like +<!------------> +works as a valid comment as long as the number of dashes is +a multiple of four (!). If not, the comment technically +lasts until the next --, which may be at +the other end of the document. Because of this, many popular +browsers completely ignore the specification and implement +what users have come to expect: comments delimited with +<!-- and +-->.

+ +

Until version +1.9, Wget interpreted comments strictly, which resulted in +missing links in many web pages that displayed fine in +browsers, but had the misfortune of containing non-compliant +comments. Beginning with version 1.9, Wget has joined the +ranks of clients that implements "naive" comments, +terminating each comment at the first occurrence of +-->.

+ +

If, for +whatever reason, you want strict comment parsing, use this +option to turn it on.

+ +

Recursive +Accept/Reject Options
+-A
acclist --accept +acclist
+-R
rejlist --reject +rejlist

+ +

Specify comma-separated lists +of file name suffixes or patterns to accept or reject. Note +that if any of the wildcard characters, *, ?, +[ or ], appear in an element of acclist +or rejlist, it will be treated as a pattern, rather +than a suffix. In this case, you have to enclose the pattern +into quotes to prevent your shell from expanding it, like in +-A "*.mp3" or -A +’*.mp3’.

+ + +

--accept-regex +urlregex
+--reject-regex
urlregex

+ +

Specify a regular expression to +accept or reject the complete URL.

+ + +

--regex-type +regextype

+ +

Specify the regular expression +type. Possible types are posix or pcre. Note +that to be able to use pcre type, wget has to be +compiled with libpcre support.

+ +

-D +domain-list
+--domains=
domain-list

+ +

Set domains to be followed. +domain-list is a comma-separated list of domains. +Note that it does not turn on -H.

+ + +

--exclude-domains +domain-list

+ +

Specify the domains that are +not to be followed.

+ + +

--follow-ftp

+ +

Follow FTP links +from HTML documents. Without this option, +Wget will ignore all the FTP links.

+ + +

--follow-tags=list

+ +

Wget has an internal table of +HTML tag / attribute pairs that it considers +when looking for linked documents during a recursive +retrieval. If a user wants only a subset of those tags to be +considered, however, he or she should be specify such tags +in a comma-separated list with this option.

+ + +

--ignore-tags=list

+ +

This is the opposite of the +--follow-tags option. To skip +certain HTML tags when recursively looking +for documents to download, specify them in a comma-separated +list.

+ +

In the past, +this option was the best bet for downloading a single page +and its requisites, using a command-line like:

+ +
        wget --ignore-tags=a,area -H -k -K -r http://<site>/<document>
+ + +

However, the +author of this option came across a page with tags like +"<LINK REL="home" +HREF="/">" and came to the +realization that specifying tags to ignore was not enough. +One can’t just tell Wget to ignore +"<LINK>", because then stylesheets +will not be downloaded. Now the best bet for downloading a +single page and its requisites is the dedicated +--page-requisites option.

+ + +

--ignore-case

+ +

Ignore case when matching files +and directories. This influences the behavior of -R, +-A, -I, and -X options, as well as +globbing implemented when downloading from +FTP sites. For example, with this option, +-A "*.txt" will match +file1.txt, but also file2.TXT, +file3.TxT, and so on. The quotes in the example are +to prevent the shell from expanding the pattern.

+ + + + + + +
+ + +

-H

+
+ + +

--span-hosts

+ +

Enable spanning across hosts +when doing recursive retrieving.

+ + + + + + +
+ + +

-L

+
+ + +

--relative

+ +

Follow relative links only. +Useful for retrieving a specific home page without any +distractions, not even those from the same hosts.

+ +

-I list +
+--include-directories=
list

+ +

Specify a comma-separated list +of directories you wish to follow when downloading. Elements +of list may contain wildcards.

+ +

-X list +
+--exclude-directories=
list

+ +

Specify a comma-separated list +of directories you wish to exclude from download. Elements +of list may contain wildcards.

+ + + + + + +
+ + +

-np

+
+ + +

--no-parent

+ +

Do not ever ascend to the +parent directory when retrieving recursively. This is a +useful option, since it guarantees that only the files +below a certain hierarchy will be downloaded.

+ +

ENVIRONMENT + +

+ + +

Wget supports +proxies for both HTTP and FTP +retrievals. The standard way to specify proxy location, +which Wget recognizes, is using the following environment +variables:
+http_proxy
+https_proxy

+ +

If set, the http_proxy +and https_proxy variables should contain the URLs of +the proxies for HTTP and HTTPS +connections respectively.

+ +

ftp_proxy

+ +

This variable should contain +the URL of the proxy for FTP +connections. It is quite common that http_proxy and +ftp_proxy are set to the same URL.

+ +

no_proxy

+ +

This variable should contain a +comma-separated list of domain extensions proxy should +not be used for. For instance, if the value of +no_proxy is .mit.edu, proxy will not be used +to retrieve documents from MIT.

+ +

EXIT STATUS + +

+ + +

Wget may return +one of several error codes if it encounters problems.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +

0

+ + +

No problems occurred.

+ + +

1

+ + +

Generic error code.

+ + +

2

+ + +

Parse error---for instance, when +parsing command-line options, the .wgetrc or +.netrc...

+ + +

3

+ + +

File I/O error.

+ + +

4

+ + +

Network failure.

+ + +

5

+ + +

SSL verification failure.

+ + +

6

+ + +

Username/password authentication failure.

+ + +

7

+ + +

Protocol errors.

+ + +

8

+ + +

Server issued an error response.

+ +

With the +exceptions of 0 and 1, the lower-numbered exit codes take +precedence over higher-numbered ones, when multiple types of +errors are encountered.

+ +

In versions of +Wget prior to 1.12, Wget’s exit status tended to be +unhelpful and inconsistent. Recursive downloads would +virtually always return 0 (success), regardless of any +issues encountered, and non-recursive fetches only returned +the status corresponding to the most recently-attempted +download.

+ +

FILES + +

+ + + +

/usr/local/etc/wgetrc

+ +

Default location of the +global startup file.

+ +

.wgetrc

+ +

User startup file.

+ +

BUGS + +

+ + +

You are welcome +to submit bug reports via the GNU Wget bug +tracker (see +<https://savannah.gnu.org/bugs/?func=additem&group=wget>) +or to our mailing list +<bug-wget@gnu.org>.

+ +

Visit +<https://lists.gnu.org/mailman/listinfo/bug-wget> +to get more info (how to subscribe, list archives, ...).

+ +

Before actually +submitting a bug report, please try to follow a few simple +guidelines.

+ + + + + + + + + + + + +
+ + +

1.

+ + +

Please try to ascertain that the behavior you see really +is a bug. If Wget crashes, it’s a bug. If Wget does +not behave as documented, it’s a bug. If things work +strange, but you are not sure about the way they are +supposed to work, it might well be a bug, but you might want +to double-check the documentation and the mailing lists.

+ + +

2.

+ + +

Try to repeat the bug in as simple circumstances as +possible. E.g. if Wget crashes while downloading wget +-rl0 -kKE -t5 --no-proxy +http://example.com -o /tmp/log, you should try to +see if the crash is repeatable, and if will occur with a +simpler set of options. You might even try to start the +download at the page where the crash occurred to see if that +page somehow triggered the crash.

+ +

Also, while I +will probably be interested to know the contents of your +.wgetrc file, just dumping it into the debug message +is probably a bad idea. Instead, you should first try to see +if the bug repeats with .wgetrc moved out of the way. +Only if it turns out that .wgetrc settings affect the +bug, mail me the relevant parts of the file.

+ + + + + + + +
+ + +

3.

+ + +

Please start Wget with +-d option and send us the resulting output (or +relevant parts thereof). If Wget was compiled without debug +support, recompile it---it is much +easier to trace bugs with debug support on.

+ +

Note: please +make sure to remove any potentially sensitive information +from the debug log before sending it to the bug address. The +"-d" won’t go out of its way +to collect sensitive information, but the log will +contain a fairly complete transcript of Wget’s +communication with the server, which may include passwords +and pieces of downloaded data. Since the bug address is +publicly archived, you may assume that all bug reports are +visible to the public.

+ + + + + + + +
+ + +

4.

+ + +

If Wget has crashed, try to run +it in a debugger, e.g. "gdb `which wget` +core" and type "where" to get +the backtrace. This may not work if the system administrator +has disabled core files, but it is safe to try.

+ +

SEE ALSO + +

+ + +

This is +not the complete manual for GNU Wget. +For more complete information, including more detailed +explanations of some of the options, and a number of +commands available for use with .wgetrc files and the +-e option, see the GNU Info +entry for wget.

+ +

AUTHOR + +

+ + +

Originally +written by Hrvoje NikÅ¡iÄ +<hniksic@xemacs.org>.

+ +

COPYRIGHT + +

+ + +

Copyright (c) +1996-2011, 2015, 2018-2019 Free Software +Foundation, Inc.

+ +

Permission is +granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation +License, Version 1.3 or any later version published by the +Free Software Foundation; with no Invariant Sections, with +no Front-Cover Texts, and with no Back-Cover Texts. A copy +of the license is included in the section entitled " +GNU Free Documentation License".

+
+ + diff --git a/openpose/CMakeLists.txt b/openpose/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f48e942e9f379eb96739705d549c215faa664850 --- /dev/null +++ b/openpose/CMakeLists.txt @@ -0,0 +1,1069 @@ +### VERSION INFO +set(OpenPose_VERSION_MAJOR 1) +set(OpenPose_VERSION_MINOR 7) +set(OpenPose_VERSION_PATCH 0) +set(OpenPose_VERSION ${OpenPose_VERSION_MAJOR}.${OpenPose_VERSION_MINOR}.${OpenPose_VERSION_PATCH}) + + +### OS-DEPENDENT FLAGS +set(CMAKE_MACOSX_RPATH 1) + + +### CMAKE HEADERS +# Ubuntu 18 default. After 3.8, no need for find_CUDA +# https://cmake.org/cmake/help/v3.10/module/FindCUDA.html +# https://cmake.org/cmake/help/v3.10/command/project.html +# https://devblogs.nvidia.com/building-cuda-applications-cmake/ +if (${CMAKE_VERSION} VERSION_GREATER 3.9.0) + cmake_policy(SET CMP0048 NEW) + project(OpenPose VERSION ${OpenPose_VERSION}) + # # Not tested + # cmake_policy(SET CMP0048 NEW) + # set(CUDACXX /usr/local/cuda/bin/nvcc) + # project(OpenPose VERSION ${OpenPose_VERSION} LANGUAGES CXX CUDA) + # set(AUTO_FOUND_CUDA TRUE) + # # else + # set(AUTO_FOUND_CUDA FALSE) +# Ubuntu 16 default +elseif (${CMAKE_VERSION} VERSION_GREATER 3.0.0) + cmake_policy(SET CMP0048 NEW) + project(OpenPose VERSION ${OpenPose_VERSION}) +else (${CMAKE_VERSION} VERSION_GREATER 3.9.0) + project(OpenPose) +endif (${CMAKE_VERSION} VERSION_GREATER 3.9.0) +cmake_minimum_required(VERSION 3.0 FATAL_ERROR) # required by cmake eigen finder to find locally installed versions (e.g., CUDA 9.2 support was added in eigen 3.3.5) +# cmake_minimum_required(VERSION 2.8.7 FATAL_ERROR) # min. cmake version recommended by Caffe + + +### Extra functionality +include(cmake/Utils.cmake) +if (NOT WIN32 AND NOT UNIX AND NOT APPLE) + message(FATAL_ERROR "Unsupported operating system. Only Windows, Mac and Unix systems supported.") +endif (NOT WIN32 AND NOT UNIX AND NOT APPLE) + + +### CMAKE_BUILD_TYPE +# Default: Release +# Bug fixed: By default, it uses something different to Release, that provokes OpenPose to be about 15% slower than +# it should be. +# Is CMAKE_BUILD_TYPE "Debug" or "MinSizeRel" or "RelWithDebInfo"? +set(CMAKE_BUILD_TYPE_KNOWN FALSE) +if (${CMAKE_BUILD_TYPE} MATCHES "Debug") + set(CMAKE_BUILD_TYPE_KNOWN TRUE) +endif (${CMAKE_BUILD_TYPE} MATCHES "Debug") +if (${CMAKE_BUILD_TYPE} MATCHES "MinSizeRel") + set(CMAKE_BUILD_TYPE_KNOWN TRUE) +endif (${CMAKE_BUILD_TYPE} MATCHES "MinSizeRel") +if (${CMAKE_BUILD_TYPE} MATCHES "RelWithDebInfo") + set(CMAKE_BUILD_TYPE_KNOWN TRUE) +endif (${CMAKE_BUILD_TYPE} MATCHES "RelWithDebInfo") +# Assign proper CMAKE_BUILD_TYPE +if (${CMAKE_BUILD_TYPE_KNOWN}) + set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build.") +else (${CMAKE_BUILD_TYPE_KNOWN}) + set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE) +endif (${CMAKE_BUILD_TYPE_KNOWN}) +set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Release" "Debug" "MinSizeRel" "RelWithDebInfo") + + +### FLAGS +if (WIN32) + # TODO -- Makeshift solution -- This prevents rerunning build again + # https://gitlab.kitware.com/cmake/cmake/issues/16783 + set(CMAKE_SUPPRESS_REGENERATION ON) + + string (REPLACE "/D_WINDOWS" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + string (REPLACE "/DWIN32" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + + # /GL option causes the code to crash -- fix this + # sdl flags causes error -- error : unknown attribute \"guard\" + + # https://stackoverflow.com/questions/43697154/detect-current-cmake-version-using-cmake + message(STATUS "CMAKE_VERSION = ${CMAKE_VERSION}") + # Remove "minSizeRel" and "relWithDebInfo" + if (${CMAKE_VERSION} VERSION_LESS "3.14.0") + set(CMAKE_CONFIGURATION_TYPES Release Debug CACHE TYPE INTERNAL FORCE) + else (${CMAKE_VERSION} VERSION_LESS "3.14.0") + # But the above line gives warning on CMake >= 3.14, alternative + set(CMAKE_CONFIGURATION_TYPES Release Debug CACHE STRING "" FORCE) + endif (${CMAKE_VERSION} VERSION_LESS "3.14.0") + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") + string(REPLACE "/W3" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + string(REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + + string(REPLACE "/O2" "/Ox" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + string(REPLACE "/Ob2" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ot /Oi /Gy /Z7") + + set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG:incremental /OPT:REF /OPT:ICF") +elseif (UNIX) + # Turn on C++11 + add_definitions(-std=c++11) + set(CMAKE_CXX_FLAGS_RELEASE "-O3") +elseif (APPLE) + # Turn on C++11 + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(CMAKE_CXX_FLAGS_RELEASE "-O3") +endif (WIN32) + +# C++ additional flags +if (CMAKE_COMPILER_IS_GNUCXX) + message(STATUS "GCC detected, adding compile flags") + # set(OP_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp -Wpedantic -Wall -Wextra -Wfatal-errors") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp") + set(OP_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic -Wall -Wextra -Wfatal-errors") + # set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -Wpedantic -Wall -Wextra -Wfatal-errors") +endif (CMAKE_COMPILER_IS_GNUCXX) + +# Select the Enhanced Instruction Set +set(INSTRUCTION_SET NONE CACHE STRING "Enable Enhanced Instruction Set") +set_property(CACHE INSTRUCTION_SET PROPERTY STRINGS NONE AVX2) +if (${INSTRUCTION_SET} MATCHES "AVX2") + add_definitions("-DWITH_AVX") +endif (${INSTRUCTION_SET} MATCHES "AVX2") +# Windows +if (WIN32) + # Suboptions for Enhanced Instruction Set + if (${INSTRUCTION_SET} MATCHES "AVX2") + add_definitions("/arch:AVX2") + endif (${INSTRUCTION_SET} MATCHES "AVX2") +# Ubuntu +else (WIN32) # if (CMAKE_COMPILER_IS_GNUCXX) + if (${INSTRUCTION_SET} MATCHES "AVX2") + set(SIMD_FLAGS "${SIMD_FLAGS} -mavx -march=native") + endif (${INSTRUCTION_SET} MATCHES "AVX2") + message(STATUS "GCC detected, adding compile flags") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SIMD_FLAGS}") +endif (WIN32) +# if (CMAKE_COMPILER_IS_GNUCXX) +# set_property(CACHE INSTRUCTION_SET PROPERTY STRINGS NONE SSE4 AVX) +# if (${INSTRUCTION_SET} MATCHES "SSE4") +# add_definitions("-DWITH_SSE4") +# set(SIMD_FLAGS "${SIMD_FLAGS} -msse4.1") +# endif (${INSTRUCTION_SET} MATCHES "SSE4") +# if (${INSTRUCTION_SET} MATCHES "AVX2") +# add_definitions("-DWITH_AVX") +# set(SIMD_FLAGS "${SIMD_FLAGS} -mavx -march=native") +# endif (${INSTRUCTION_SET} MATCHES "AVX2") +# message(STATUS "GCC detected, adding compile flags") +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SIMD_FLAGS}") +# endif (CMAKE_COMPILER_IS_GNUCXX) +# if (WIN32) +# # set_property(CACHE INSTRUCTION_SET PROPERTY STRINGS NONE SSE SSE2 AVX AVX2 IA32) +# # Suboptions for Enhanced Instruction Set +# if (${INSTRUCTION_SET} MATCHES "SSE") +# add_definitions("/arch:SSE") +# elseif (${INSTRUCTION_SET} MATCHES "SSE2") +# add_definitions("/arch:SSE2") +# elseif (${INSTRUCTION_SET} MATCHES "AVX") +# add_definitions("/arch:AVX") +# elseif (${INSTRUCTION_SET} MATCHES "AVX2") +# add_definitions("/arch:AVX2") +# elseif (${INSTRUCTION_SET} MATCHES "IA32") +# add_definitions("/arch:IA32") +# endif (${INSTRUCTION_SET} MATCHES "SSE") +# endif (WIN32) + + +### PROJECT OPTIONS +# Select the DL Framework +set(DL_FRAMEWORK CAFFE CACHE STRING "Select Deep Learning Framework.") +if (WIN32) + set_property(CACHE DL_FRAMEWORK PROPERTY STRINGS CAFFE) +else (WIN32) + set_property(CACHE DL_FRAMEWORK PROPERTY STRINGS CAFFE NV_CAFFE) + # set_property(CACHE DL_FRAMEWORK PROPERTY STRINGS CAFFE NV_CAFFE PYTORCH TENSORFLOW) +endif (WIN32) + +# Suboptions for Caffe DL Framework +include(CMakeDependentOption) +if (${DL_FRAMEWORK} MATCHES "CAFFE" OR ${DL_FRAMEWORK} MATCHES "NV_CAFFE") + CMAKE_DEPENDENT_OPTION(BUILD_CAFFE "Build Caffe as part of OpenPose." ON + "DL_FRAMEWORK" ON) + # OpenPose flags + add_definitions(-DUSE_CAFFE) + # Nvidia NVCaffe + if (${DL_FRAMEWORK} MATCHES "NV_CAFFE") + MESSAGE(STATUS "Using NVIDIA NVCaffe") + add_definitions(-DNV_CAFFE) + endif (${DL_FRAMEWORK} MATCHES "NV_CAFFE") +endif (${DL_FRAMEWORK} MATCHES "CAFFE" OR ${DL_FRAMEWORK} MATCHES "NV_CAFFE") + +# Set the acceleration library +if (APPLE) + set(GPU_MODE CPU_ONLY CACHE STRING "Select the acceleration GPU library or CPU otherwise.") +else (APPLE) + set(GPU_MODE CUDA CACHE STRING "Select the acceleration GPU library or CPU otherwise.") +endif (APPLE) +# Display proper options to user +# if (CUDA_FOUND AND OpenCL_FOUND) +# set_property(CACHE GPU_MODE PROPERTY STRINGS CUDA OPENCL CPU_ONLY) +# elseif (CUDA_FOUND) +# set_property(CACHE GPU_MODE PROPERTY STRINGS CUDA CPU_ONLY) +# elseif (OpenCL_FOUND) +# set_property(CACHE GPU_MODE PROPERTY STRINGS OPENCL CPU_ONLY) +# else () +# set_property(CACHE GPU_MODE PROPERTY STRINGS CPU_ONLY) +# endif (CUDA_FOUND AND OpenCL_FOUND) +set_property(CACHE GPU_MODE PROPERTY STRINGS CUDA OPENCL CPU_ONLY) + +# Look for CUDA +set(CUDA_FOUND FALSE) +if (${GPU_MODE} MATCHES "CUDA") + find_package(CUDA) +endif (${GPU_MODE} MATCHES "CUDA") +# Look for OpenCL +set(OpenCL_FOUND FALSE) +set(CUDA_VERSION_MAJOR 0) +if (${GPU_MODE} MATCHES "OPENCL") + find_package(OpenCL) +endif (${GPU_MODE} MATCHES "OPENCL") + +# Code to avoid crash at compiling time if OpenCL is not found +if (NOT OpenCL_FOUND) + set(OpenCL_LIBRARIES "") +endif (NOT OpenCL_FOUND) +# Required for OpenCL in Nvidia graphic cards +if (CUDA_FOUND AND OpenCL_FOUND AND ${CUDA_VERSION_MAJOR} LESS 9) + add_definitions(-DLOWER_CL_VERSION) +endif (CUDA_FOUND AND OpenCL_FOUND AND ${CUDA_VERSION_MAJOR} LESS 9) +# Handle desired GPU mode option +if (${GPU_MODE} MATCHES "CUDA") + # OpenPose flags + add_definitions(-DUSE_CUDA) + message(STATUS "Building with CUDA.") +elseif (${GPU_MODE} MATCHES "CPU_ONLY") + add_definitions(-DUSE_CPU_ONLY) + message(STATUS "Building CPU Only.") + # OpenPose flag for Caffe + add_definitions(-DCPU_ONLY) +elseif (${GPU_MODE} MATCHES "OPENCL") + # OpenPose flag for Caffe + add_definitions(-DUSE_OPENCL) + add_definitions(-DUSE_GREENTEA) + message(STATUS "Building with OpenCL.") +endif (${GPU_MODE} MATCHES "CUDA") + +# Intel branch with MKL Support +if (${GPU_MODE} MATCHES "CPU_ONLY") + if (UNIX AND NOT APPLE) + OPTION(USE_MKL "Use MKL Intel Branch." OFF) + endif (UNIX AND NOT APPLE) +endif (${GPU_MODE} MATCHES "CPU_ONLY") + +if (${USE_MKL}) + # OpenPose flags + add_definitions(-DUSE_MKL) + message(STATUS "Building with MKL support.") +endif (${USE_MKL}) + +# Set/disable profiler +if (PROFILER_ENABLED) + add_definitions(-DPROFILER_ENABLED) +endif (PROFILER_ENABLED) + +# Suboptions for GPU architectures +if (${GPU_MODE} MATCHES "CUDA") + set(CUDA_ARCH Auto CACHE STRING "Select target NVIDIA GPU architecture.") + set_property(CACHE CUDA_ARCH PROPERTY STRINGS Auto All Manual) +endif (${GPU_MODE} MATCHES "CUDA") + +# Suboptions for acceleration library +if (${GPU_MODE} MATCHES "CUDA") + option(USE_CUDNN "Build OpenPose with cuDNN library support." ON) +endif (${GPU_MODE} MATCHES "CUDA") + +# Suboptions for OpenPose 3D Reconstruction module and demo +option(WITH_3D_RENDERER "Add OpenPose 3D renderer module (it requires FreeGLUT library)." OFF) +if (UNIX AND NOT APPLE) + option(WITH_CERES "Add Ceres support for advanced 3-D reconstruction." OFF) +endif (UNIX AND NOT APPLE) +option(WITH_FLIR_CAMERA "Add FLIR (formerly Point Grey) camera code (requires Spinnaker SDK already installed)." OFF) +# option(WITH_3D_ADAM_MODEL "Add 3-D Adam model (requires OpenGL, Ceres, Eigen, OpenMP, FreeImage, GLEW, and IGL already installed)." OFF) + +# Faster GUI rendering +# Note: It seems to work by default in Windows and Ubuntu, but not in Mac nor Android. +# More info: https://stackoverflow.com/questions/21129683/does-opengl-display-image-faster-than-opencv?answertab=active#tab-top +option(WITH_OPENCV_WITH_OPENGL "Much faster GUI display, but you must also enable OpenGL support in OpenCV by configuring OpenCV using CMake with WITH_OPENGL=ON flag." OFF) + +# Set the acceleration library +if (WIN32 OR APPLE) + set(WITH_EIGEN NONE CACHE STRING "Select the Eigen mode: NONE if not required, AUTOBUILD to let OpenPose download it, or FIND to let CMake find it (e.g., if you installed it manually).") +elseif (UNIX AND NOT APPLE) + set(WITH_EIGEN NONE CACHE STRING "Select the Eigen mode: NONE if not required, AUTOBUILD to let OpenPose download it, or FIND to let CMake find it (e.g., if you installed it manually or used `sudo apt-get install libeigen3-dev`).") +endif (WIN32 OR APPLE) +set_property(CACHE WITH_EIGEN PROPERTY STRINGS NONE AUTOBUILD FIND) + +# # Suboptions for OpenPose tracking +# if (UNIX AND NOT APPLE) +# option(WITH_TRACKING "Add OpenPose 3D tracking module (it requires OpenCV with CUDA support)." OFF) +# endif (UNIX AND NOT APPLE) + +# Download the models +option(DOWNLOAD_BODY_25_MODEL "Download body 25-keypoint (body COCO and 6-keypoint foot) model." ON) +option(DOWNLOAD_BODY_COCO_MODEL "Download body 18-keypoint COCO model." OFF) +option(DOWNLOAD_BODY_MPI_MODEL "Download body 15-keypoint MPI model." OFF) +option(DOWNLOAD_FACE_MODEL "Download face model." ON) +option(DOWNLOAD_HAND_MODEL "Download hand model." ON) + +# Asio +# option(USE_ASIO "Include Asio header-only library." OFF) + +# More options +option(BUILD_EXAMPLES "Build OpenPose examples." ON) +option(BUILD_DOCS "Build OpenPose documentation." OFF) +option(BUILD_PYTHON "Build OpenPose python." OFF) +if (WIN32) + option(BUILD_BIN_FOLDER "Copy all required 3rd-party DLL files into {build_directory}/bin. Disable to save some memory." ON) +endif (WIN32) + +# Unity +option(BUILD_UNITY_SUPPORT "Build OpenPose as a Unity plugin." OFF) + +# Build as shared library +option(BUILD_SHARED_LIBS "Build as shared lib." ON) + +# Speed profiler +option(PROFILER_ENABLED "If enabled, OpenPose will be able to print out speed information at runtime." OFF) + +# Threads - Pthread +if (${GPU_MODE} MATCHES "OPENCL" OR (UNIX OR APPLE)) + unset(CMAKE_THREAD_LIBS_INIT CACHE) + find_package(Threads) +endif (${GPU_MODE} MATCHES "OPENCL" OR (UNIX OR APPLE)) + +# Caffe OpenCL Boost Issue +if (APPLE) + if (${GPU_MODE} MATCHES "OPENCL" OR BUILD_PYTHON) + unset(Boost_SYSTEM_LIBRARY CACHE) + find_package(Boost COMPONENTS system REQUIRED) + else () + set(Boost_SYSTEM_LIBRARY "") + endif () +endif (APPLE) + +set(DOWNLOAD_SERVER "http://vcl.snu.ac.kr/OpenPose/" CACHE STRING "Server from which the models and 3rdparty libraries will be downloaded from.") +mark_as_advanced(DOWNLOAD_SERVER) + +### FIND REQUIRED PACKAGES +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules") + +if (${GPU_MODE} MATCHES "CUDA") + find_package(CUDA) +endif (${GPU_MODE} MATCHES "CUDA") + +# Adding 3D +if (WITH_OPENCV_WITH_OPENGL) + # OpenPose flags + add_definitions(-DUSE_OPENCV_WITH_OPENGL) +endif (WITH_OPENCV_WITH_OPENGL) +if (WITH_3D_RENDERER) + # OpenPose flags + add_definitions(-DUSE_3D_RENDERER) +endif (WITH_3D_RENDERER) +if (WITH_CERES) + add_definitions(-DUSE_CERES) +endif (WITH_CERES) +if (WITH_FLIR_CAMERA) + # OpenPose flags + add_definitions(-DUSE_FLIR_CAMERA) +endif (WITH_FLIR_CAMERA) +if (WITH_3D_ADAM_MODEL) + # OpenPose flags + add_definitions(-DUSE_3D_ADAM_MODEL) +endif (WITH_3D_ADAM_MODEL) + +# Adding tracking +if (WITH_TRACKING) + # OpenPose flags + add_definitions(-DUSE_TRACKING) +endif (WITH_TRACKING) + +# Unity +if (BUILD_UNITY_SUPPORT) + # OpenPose flags + add_definitions(-DUSE_UNITY_SUPPORT) +endif (BUILD_UNITY_SUPPORT) + +# Calibration +# No Eigen +if (${WITH_EIGEN} MATCHES "NONE") + if (WITH_CERES) + message(FATAL_ERROR "Eigen is required (enable `WITH_EIGEN`) if CERES is enabled.") + endif (WITH_CERES) +# If Eigen used +else (${WITH_EIGEN} MATCHES "NONE") + # OpenPose flags + add_definitions(-DUSE_EIGEN) + # OpenPose download/builds Eigen + if (${WITH_EIGEN} MATCHES "AUTOBUILD") + # Download it + set(OP_URL "${DOWNLOAD_SERVER}3rdparty/") + set(FIND_LIB_PREFIX ${CMAKE_SOURCE_DIR}/3rdparty/) + download_zip("eigen_2020_11_18.zip" ${OP_URL} ${FIND_LIB_PREFIX} 57672715C62C1A795300FE1AE4D2687E) + # Set path + set(EIGEN3_INCLUDE_DIRS "3rdparty/eigen/include/") + # Leave to CMake to find it + elseif (${WITH_EIGEN} MATCHES "FIND") + # Eigen + # # Option a) apt-get + # find_package(PkgConfig) + # pkg_check_modules(EIGEN3 REQUIRED eigen3) + # # Option b) Find it (including apt-get) + if (CUDA_VERSION_STRING STRGREATER "9.0") + find_package(Eigen3 3.3.5 REQUIRED NO_MODULE) + else (CUDA_VERSION_STRING STRGREATER "9.0") + find_package(Eigen3 3 REQUIRED NO_MODULE) + endif (CUDA_VERSION_STRING STRGREATER "9.0") + endif (${WITH_EIGEN} MATCHES "AUTOBUILD") +endif (${WITH_EIGEN} MATCHES "NONE") + +if (UNIX OR APPLE) + if (${GPU_MODE} MATCHES "CUDA") + include(cmake/Cuda.cmake) + find_package(CuDNN) + endif (${GPU_MODE} MATCHES "CUDA") + find_package(GFlags) # For Caffe and OpenPose + find_package(Glog) # For Caffe + find_package(Protobuf REQUIRED) # For Caffe + + if (OpenCV_CONFIG_FILE) + include (${OpenCV_CONFIG_FILE}) + # Allow explicitly setting the OpenCV includes and libs + elseif (OpenCV_INCLUDE_DIRS AND OpenCV_LIBS) + set(OpenCV_FOUND 1) + elseif (OpenCV_INCLUDE_DIRS AND OpenCV_LIBS_DIR) + file(GLOB_RECURSE OpenCV_LIBS "${OpenCV_LIBS_DIR}*.so") + set(OpenCV_FOUND 1) + else (OpenCV_CONFIG_FILE) + find_package(OpenCV) + endif (OpenCV_CONFIG_FILE) + + # 3D + if (WITH_3D_RENDERER) + # OpenGL + find_package(OpenGL REQUIRED) + # GLUT + find_package(GLUT REQUIRED) + # OpenGL + find_package(OpenGL REQUIRED) + endif (WITH_3D_RENDERER) + if (WITH_CERES) + # Eigen + Ceres + find_package(Ceres REQUIRED COMPONENTS SuiteSparse) + endif (WITH_CERES) + if (WITH_FLIR_CAMERA) + # Spinnaker + find_package(Spinnaker) + if (NOT SPINNAKER_FOUND) + message(FATAL_ERROR "Spinnaker not found. Either turn off the `WITH_FLIR_CAMERA` option or specify the path to + the Spinnaker includes and libs.") + endif (NOT SPINNAKER_FOUND) + endif (WITH_FLIR_CAMERA) + if (WITH_3D_ADAM_MODEL) + if (NOT WITH_3D_RENDERER) + message(FATAL_ERROR "WITH_3D_RENDERER is required if WITH_3D_ADAM_MODEL is enabled.") + endif (NOT WITH_3D_RENDERER) + # Eigen + # # Option a) apt-get + # find_package(PkgConfig) + # pkg_check_modules(EIGEN3 REQUIRED eigen3) + # # Option b) Find it (including apt-get) + if (CUDA_VERSION_STRING STRGREATER "9.0") + find_package(Eigen3 3.3.5 REQUIRED NO_MODULE) + else (CUDA_VERSION_STRING STRGREATER "9.0") + find_package(Eigen3 3 REQUIRED NO_MODULE) + endif (CUDA_VERSION_STRING STRGREATER "9.0") + # Others: sudo apt-get install libglm-dev + # http://ceres-solver.org + find_package(Ceres REQUIRED COMPONENTS SuiteSparse) + # sudo apt-get install libglew-dev + find_package(GLEW REQUIRED) + # find_package(GLUT REQUIRED) # TODO: Duplicated of WITH_3D_RENDERER, clean somehow (like Eigen) + # git clone --recursive https://github.com/libigl/libigl.git + # No installation, it's header only + # TODO: It's header only (as Eigen), do AUTOBUILD option too to download it + find_package(LIBIGL REQUIRED) + find_package(OpenMP REQUIRED) + # Only adam/renderer::Renderer::IdleSaveImage() uses it. Make dependency optional in hand_model + # FIND_LIBRARY(FREE_IMAGE_LIBRARY NAMES libfreeimage.so) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") + endif (WITH_3D_ADAM_MODEL) + + # OpenMP + if (${GPU_MODE} MATCHES "CPU_ONLY") + find_package(OpenMP) + if (OPENMP_FOUND) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") + endif (OPENMP_FOUND) + endif (${GPU_MODE} MATCHES "CPU_ONLY") + + if (${GPU_MODE} MATCHES "CUDA") + # Set CUDA Flags + set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -std=c++14") # Thrust library requires C++14 for CUDA >= 11 + set(CUDA_NVCC_FLAGS_DEBUG "${CUDA_NVCC_FLAGS_DEBUG} -D_DEBUG -g") + + if (NOT CUDA_FOUND) + message(STATUS "CUDA not found.") + execute_process(COMMAND cat install_cuda.sh WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/scripts/ubuntu) + message(FATAL_ERROR "Install CUDA using the above commands.") + endif (NOT CUDA_FOUND) + + if (USE_CUDNN AND NOT CUDNN_FOUND) + message(STATUS "cuDNN not found.") + execute_process(COMMAND cat install_cudnn_up_to_Ubuntu16.sh WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/scripts/ubuntu) + message(FATAL_ERROR "Install cuDNN using the above commands. or turn off cuDNN by setting USE_CUDNN to OFF.") + endif (USE_CUDNN AND NOT CUDNN_FOUND) + endif (${GPU_MODE} MATCHES "CUDA") + + if (NOT GLOG_FOUND) + message(FATAL_ERROR "Glog not found. Install Glog from the command line using the command(s) -\ + sudo apt-get install libgoogle-glog-dev") + endif (NOT GLOG_FOUND) + + if (NOT GFLAGS_FOUND) + message(FATAL_ERROR "GFlags not found. Install GFlags from the command line using the command(s) --\ + sudo apt-get install libgflags-dev") + endif (NOT GFLAGS_FOUND) + + if (NOT OpenCV_FOUND) + message(FATAL_ERROR "OpenCV not found. Install OpenCV from the command line using the command(s) --\ + sudo apt-get install libopencv-dev") + endif (NOT OpenCV_FOUND) + +endif (UNIX OR APPLE) + +if (WIN32) + + if ("${CMAKE_VERSION}" VERSION_GREATER 3.6.3) + set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT OpenPoseDemo) + endif ("${CMAKE_VERSION}" VERSION_GREATER 3.6.3) + + set_property(GLOBAL PROPERTY USE_FOLDERS ON) + set(FIND_LIB_PREFIX ${CMAKE_SOURCE_DIR}/3rdparty/windows) + + # Download Windows 3rd party + message(STATUS "Downloading windows dependencies...") + set(OP_WIN_URL "${DOWNLOAD_SERVER}3rdparty/windows") + set(OP_WIN_DIR "${CMAKE_SOURCE_DIR}/3rdparty/windows") + + # Download required zip files + download_zip("opencv_450_v15_2020_11_18.zip" ${OP_WIN_URL} ${FIND_LIB_PREFIX} AFB1BD1A160C43CF5FB856C8BB4FC483) + download_zip("caffe3rdparty_16_2020_11_14.zip" ${OP_WIN_URL} ${FIND_LIB_PREFIX} 83C17DC4473985B6AB3A29FD9AB93409) + if (${GPU_MODE} MATCHES "OPENCL") + download_zip("caffe_opencl_2018_02_13.zip" ${OP_WIN_URL} ${FIND_LIB_PREFIX} 3ac3e1acf5ee6a4e57920be73053067a) + elseif (${GPU_MODE} MATCHES "CPU_ONLY") + download_zip("caffe_cpu_2018_05_27.zip" ${OP_WIN_URL} ${FIND_LIB_PREFIX} 87E8401B6DFBAC5B8E909DD20E3B3390) + else (${GPU_MODE} MATCHES "OPENCL") + # download_zip("caffe_2019_03_12.zip" ${OP_WIN_URL} ${FIND_LIB_PREFIX} 859a592310f0928fd4f40da1456a217f) + # download_zip("caffe_15_2020_04_05.zip" ${OP_WIN_URL} ${FIND_LIB_PREFIX} cd4ec4d709a70c94aa6b151d2d040300) + download_zip("caffe_16_2020_11_14.zip" ${OP_WIN_URL} ${FIND_LIB_PREFIX} 33030DBEC9911533566E239199BB4716) + endif (${GPU_MODE} MATCHES "OPENCL") + if (WITH_3D_RENDERER) + download_zip("freeglut_2018_01_14.zip" ${OP_WIN_URL} ${FIND_LIB_PREFIX} BB182187285E06880F0EDE3A39530091) + endif (WITH_3D_RENDERER) + message(STATUS "Windows dependencies downloaded.") + + set(OPENCV_VS_VERSION "15") + find_library(OpenCV_LIBS_RELEASE opencv_world450 HINTS ${FIND_LIB_PREFIX}/opencv/x64/vc${OPENCV_VS_VERSION}/lib) + find_library(OpenCV_LIBS_DEBUG opencv_world450d HINTS ${FIND_LIB_PREFIX}/opencv/x64/vc${OPENCV_VS_VERSION}/lib) + find_library(GFLAGS_LIBRARY_RELEASE gflags HINTS ${FIND_LIB_PREFIX}/caffe3rdparty/lib) + find_library(GFLAGS_LIBRARY_DEBUG gflagsd HINTS ${FIND_LIB_PREFIX}/caffe3rdparty/lib) + find_library(GLOG_LIBRARY_RELEASE glog HINTS ${FIND_LIB_PREFIX}/caffe3rdparty/lib) + find_library(GLOG_LIBRARY_DEBUG glogd HINTS ${FIND_LIB_PREFIX}/caffe3rdparty/lib) + + # If OpenPose builds it + if (BUILD_CAFFE) + unset(Caffe_INCLUDE_DIRS CACHE) + unset(Caffe_LIB_RELEASE CACHE) + unset(Caffe_Proto_LIB_RELEASE CACHE) + endif (BUILD_CAFFE) + # OpenCL + if (${GPU_MODE} MATCHES "OPENCL") + set(VCXPROJ_FILE_GPU_MODE "_CL") + find_library(Caffe_LIB_RELEASE caffe HINTS ${FIND_LIB_PREFIX}/caffe_opencl/lib) + find_library(Caffe_Proto_LIB_RELEASE caffeproto HINTS ${FIND_LIB_PREFIX}/caffe_opencl/lib) + find_library(Caffe_LIB_DEBUG caffe-d HINTS ${FIND_LIB_PREFIX}/caffe_opencl/lib) + find_library(Caffe_Proto_LIB_DEBUG caffeproto-d HINTS ${FIND_LIB_PREFIX}/caffe_opencl/lib) + # CPU & CUDA + else (${GPU_MODE} MATCHES "OPENCL") + # CPU + if (${GPU_MODE} MATCHES "CPU_ONLY") + set(VCXPROJ_FILE_GPU_MODE "_CPU") + find_library(Caffe_LIB_RELEASE caffe HINTS ${FIND_LIB_PREFIX}/caffe_cpu/lib) + find_library(Caffe_Proto_LIB_RELEASE caffeproto HINTS ${FIND_LIB_PREFIX}/caffe_cpu/lib) + find_library(Caffe_LIB_DEBUG caffe-d HINTS ${FIND_LIB_PREFIX}/caffe_cpu/lib) + find_library(Caffe_Proto_LIB_DEBUG caffeproto-d HINTS ${FIND_LIB_PREFIX}/caffe_cpu/lib) + # CUDA + else (${GPU_MODE} MATCHES "CPU_ONLY") + set(VCXPROJ_FILE_GPU_MODE "") + find_library(Caffe_LIB_RELEASE caffe HINTS ${FIND_LIB_PREFIX}/caffe/lib) + find_library(Caffe_Proto_LIB_RELEASE caffeproto HINTS ${FIND_LIB_PREFIX}/caffe/lib) + find_library(Caffe_LIB_DEBUG caffe-d HINTS ${FIND_LIB_PREFIX}/caffe/lib) + find_library(Caffe_Proto_LIB_DEBUG caffeproto-d HINTS ${FIND_LIB_PREFIX}/caffe/lib) + endif (${GPU_MODE} MATCHES "CPU_ONLY") + endif (${GPU_MODE} MATCHES "OPENCL") + # Boost DepCopy over required DLL + find_library(BOOST_SYSTEM_LIB_RELEASE boost_system-vc142-mt-x64-1_74 HINTS ${FIND_LIB_PREFIX}/caffe3rdparty/lib) + find_library(BOOST_SYSTEM_LIB_DEBUG boost_system-vc142-mt-gd-x64-1_74 HINTS ${FIND_LIB_PREFIX}/caffe3rdparty/lib) + find_library(BOOST_FILESYSTEM_LIB_RELEASE boost_filesystem-vc142-mt-x64-1_74 HINTS ${FIND_LIB_PREFIX}/caffe3rdparty/lib) + find_library(BOOST_FILESYSTEM_LIB_DEBUG boost_filesystem-vc142-mt-gd-x64-1_74 HINTS ${FIND_LIB_PREFIX}/caffe3rdparty/lib) + # message(STATUS "\${BOOST_SYSTEM_LIB_RELEASE} = ${BOOST_SYSTEM_LIB_RELEASE}") + # message(STATUS "\${BOOST_SYSTEM_LIB_DEBUG} = ${BOOST_SYSTEM_LIB_DEBUG}") + # message(STATUS "\${BOOST_FILESYSTEM_LIB_RELEASE} = ${BOOST_FILESYSTEM_LIB_RELEASE}") + # message(STATUS "\${BOOST_FILESYSTEM_LIB_DEBUG} = ${BOOST_FILESYSTEM_LIB_DEBUG}") + if (WITH_3D_RENDERER) + find_library(GLUT_LIBRARY freeglut HINTS ${FIND_LIB_PREFIX}/freeglut/lib) + message(STATUS "\${GLUT_LIBRARY} = ${GLUT_LIBRARY}") + endif (WITH_3D_RENDERER) + if (WITH_FLIR_CAMERA) + find_library(SPINNAKER_LIB spinnaker_v140 HINTS ${FIND_LIB_PREFIX}/spinnaker/lib) + endif (WITH_FLIR_CAMERA) + set(Caffe_LIBS_RELEASE "${Caffe_LIB_RELEASE};${Caffe_Proto_LIB_RELEASE}") + set(Caffe_LIBS_DEBUG "${Caffe_LIB_DEBUG};${Caffe_Proto_LIB_DEBUG}") + set(OpenCV_INCLUDE_DIRS "3rdparty/windows/opencv/include") + # OpenCL + if (${GPU_MODE} MATCHES "OPENCL") + unset(Caffe_INCLUDE_DIRS CACHE) + set(Caffe_INCLUDE_DIRS "3rdparty/windows/caffe_opencl/include;3rdparty/windows/caffe_opencl/include2" CACHE FILEPATH "Caffe_INCLUDE_DIRS") + # CUDA and CPU + else (${GPU_MODE} MATCHES "OPENCL") + # CPU + if (${GPU_MODE} MATCHES "CPU_ONLY") + set(Caffe_INCLUDE_DIRS "3rdparty/windows/caffe_cpu/include;3rdparty/windows/caffe_cpu/include2" CACHE FILEPATH "Caffe_INCLUDE_DIRS") + # CUDA + else (${GPU_MODE} MATCHES "CPU_ONLY") + set(Caffe_INCLUDE_DIRS "3rdparty/windows/caffe/include;3rdparty/windows/caffe/include2" CACHE FILEPATH "Caffe_INCLUDE_DIRS") + endif (${GPU_MODE} MATCHES "CPU_ONLY") + endif (${GPU_MODE} MATCHES "OPENCL") + # set(Boost_INCLUDE_DIRS "3rdparty/windows/caffe3rdparty/include/boost-1_61") # Added in WINDOWS_INCLUDE_DIRS + set(WINDOWS_INCLUDE_DIRS "3rdparty/windows/caffe3rdparty/include") + if (WITH_3D_RENDERER) + set(GLUT_INCLUDE_DIRS "3rdparty/windows/freeglut/include") + endif (WITH_3D_RENDERER) + if (WITH_FLIR_CAMERA) + set(SPINNAKER_INCLUDE_DIRS "3rdparty/windows/spinnaker/include") + endif (WITH_FLIR_CAMERA) + set(Caffe_FOUND 1) + + # Build DLL Must be on if Build Python is on + if (BUILD_PYTHON) + if (NOT BUILD_BIN_FOLDER) + message(FATAL_ERROR "BUILD_BIN_FOLDER must be turned on to as well to build python library") + endif (NOT BUILD_BIN_FOLDER) + endif (BUILD_PYTHON) + + # Auto copy DLLs + if (BUILD_BIN_FOLDER) + # Copy DLLs into same folder + set(BIN_FOLDER ${CMAKE_BINARY_DIR}/bin) + file(MAKE_DIRECTORY ${BIN_FOLDER}) + # Locate and copy DLLs + # Caffe DLLs + if (${GPU_MODE} MATCHES "CUDA") + file(GLOB CAFFE_DLL "${CMAKE_SOURCE_DIR}/3rdparty/windows/caffe/bin/*.dll") + elseif (${GPU_MODE} MATCHES "OPENCL") + file(GLOB CAFFE_DLL "${CMAKE_SOURCE_DIR}/3rdparty/windows/caffe_opencl/bin/*.dll") + elseif (${GPU_MODE} MATCHES "CPU_ONLY") + file(GLOB CAFFE_DLL "${CMAKE_SOURCE_DIR}/3rdparty/windows/caffe_cpu/bin/*.dll") + endif () + file(COPY ${CAFFE_DLL} DESTINATION ${BIN_FOLDER}) + # Caffe 3rd-party DLLs + file(GLOB CAFFE_3RD_PARTY_DLL "${CMAKE_SOURCE_DIR}/3rdparty/windows/caffe3rdparty/lib/*.dll") + file(COPY ${CAFFE_3RD_PARTY_DLL} DESTINATION ${BIN_FOLDER}) + # OpenCV DLLs + file(GLOB OPENCV_DLL "${CMAKE_SOURCE_DIR}/3rdparty/windows/opencv/x64/vc${OPENCV_VS_VERSION}/bin/*.dll") + file(COPY ${OPENCV_DLL} DESTINATION ${BIN_FOLDER}) + # GLUT DLLs + if (WITH_3D_RENDERER OR WITH_3D_ADAM_MODEL) + file(GLOB GLUT_DLL "${CMAKE_SOURCE_DIR}/3rdparty/windows/freeglut/bin/*.dll") + file(COPY ${GLUT_DLL} DESTINATION ${BIN_FOLDER}) + endif (WITH_3D_RENDERER OR WITH_3D_ADAM_MODEL) + # Spinnaker DLLs and other files + if (WITH_FLIR_CAMERA) + file(GLOB SPINNAKER_DLL "${CMAKE_SOURCE_DIR}/3rdparty/windows/spinnaker/bin/*") + file(COPY ${SPINNAKER_DLL} DESTINATION ${BIN_FOLDER}) + endif (WITH_FLIR_CAMERA) + endif (BUILD_BIN_FOLDER) + +endif (WIN32) + + +### CAFFE/NVCAFFE in Ubuntu +if (UNIX OR APPLE) + if (${DL_FRAMEWORK} MATCHES "CAFFE" OR ${DL_FRAMEWORK} MATCHES "NV_CAFFE") + # Check if the user specified caffe paths + if (Caffe_INCLUDE_DIRS AND Caffe_LIBS AND NOT BUILD_CAFFE) + message(STATUS "\${Caffe_INCLUDE_DIRS} set by the user to " ${Caffe_INCLUDE_DIRS}) + message(STATUS "\${Caffe_LIBS} set by the user to " ${Caffe_LIBS}) + set(Caffe_FOUND 1) + endif (Caffe_INCLUDE_DIRS AND Caffe_LIBS AND NOT BUILD_CAFFE) + + # Else build from scratch + if (BUILD_CAFFE) + + # Download Caffe + message(STATUS "Caffe will be downloaded from source now. NOTE: This process might take several minutes depending + on your internet connection.") + + # Check if pulled + file(GLOB CAFFE_DIR_VALID ${CMAKE_SOURCE_DIR}/3rdparty/caffe/*) + list(LENGTH CAFFE_DIR_VALID CAFFE_DIR_VALID_LENGTH) + if (CAFFE_DIR_VALID_LENGTH EQUAL 0) + execute_process(COMMAND git submodule update --init ${CMAKE_SOURCE_DIR}/3rdparty/caffe) + # execute_process(COMMAND git submodule update --init --recursive --remote) # This would initialize them all + else (CAFFE_DIR_VALID_LENGTH EQUAL 0) + message(STATUS "Caffe has already been downloaded.") + endif (CAFFE_DIR_VALID_LENGTH EQUAL 0) + + # Build Process + set(CAFFE_CPU_ONLY OFF) + if (${GPU_MODE} MATCHES "CUDA") + # execute_process(COMMAND git checkout master WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty/caffe) + execute_process(COMMAND git checkout 1807aad WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty/caffe) + elseif (${GPU_MODE} MATCHES "CPU_ONLY") + if (USE_MKL) + #execute_process(COMMAND git checkout intel WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty/caffe) + execute_process(COMMAND git checkout b6712ce WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty/caffe) + execute_process(COMMAND sh prepare_mkl.sh WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty/caffe/external/mkl + OUTPUT_VARIABLE rv) + set( MLIST ${rv} ) + separate_arguments(MLIST) + list(GET MLIST 0 MKL_PATH) + message(STATUS ${MKL_PATH}) + file(GLOB MKL_SO + "${MKL_PATH}lib/*" + ) + file(COPY ${MKL_SO} DESTINATION ${CMAKE_BINARY_DIR}/caffe) + + # New MLSL Lib + #execute_process(COMMAND sh prepare_mlsl.sh WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty/caffe/external/mlsl + # OUTPUT_VARIABLE rv) + #set( MLIST ${rv} ) + #separate_arguments(MLIST) + #list(GET MLIST 0 MLSL_PATH) + #message(STATUS ${MLSL_PATH}) + #file(GLOB MLSL_SO + # "${MLSL_PATH}/intel64/lib/*" + # ) + #file(COPY ${MLSL_SO} DESTINATION ${CMAKE_BINARY_DIR}/caffe) + + set(MKL_LIBS + #"${CMAKE_BINARY_DIR}/caffe/libmlsl.so" + "${CMAKE_BINARY_DIR}/caffe/libiomp5.so" + "${CMAKE_BINARY_DIR}/caffe/libmklml_intel.so" + "${CMAKE_BINARY_DIR}/caffe/lib/libmkldnn.so" + ) + else (USE_MKL) + # execute_process(COMMAND git checkout master WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty/caffe) + execute_process(COMMAND git checkout 1807aad WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty/caffe) + endif (USE_MKL) + set(CAFFE_CPU_ONLY ON) + set(USE_CUDNN OFF) + elseif (${GPU_MODE} MATCHES "OPENCL") + execute_process(COMMAND git checkout fe2a1102 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty/caffe) + set(USE_CUDNN OFF) + endif (${GPU_MODE} MATCHES "CUDA") + + # Build Caffe + message(STATUS "Caffe will be built from source now.") + find_package(Caffe) + include(ExternalProject) + set(CAFFE_PREFIX caffe) + set(CAFFE_URL ${CMAKE_SOURCE_DIR}/3rdparty/caffe) + + # One for Intel Branch and one for Master + if (USE_MKL) + ExternalProject_Add(openpose_lib + SOURCE_DIR ${CAFFE_URL} + PREFIX ${CAFFE_PREFIX} + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= + -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} + -DMKLDNN_INSTALL_DIR:PATH= + -DUSE_MKL2017_AS_DEFAULT_ENGINE=${CAFFE_CPU_ONLY} + -DUSE_CUDNN=${USE_CUDNN} + -DCUDA_ARCH_NAME=${CUDA_ARCH} + -DCUDA_ARCH_BIN=${CUDA_ARCH_BIN} + -DCUDA_ARCH_PTX=${CUDA_ARCH_PTX} + -DCPU_ONLY=${CAFFE_CPU_ONLY} + -DCMAKE_BUILD_TYPE=Release + -DBUILD_docs=OFF + -DBUILD_python=OFF + -DBUILD_python_layer=OFF + -DUSE_LEVELDB=OFF + -DUSE_LMDB=OFF + -DUSE_OPENCV=OFF) + # -DOpenCV_DIR=${OpenCV_DIR}) + else (USE_MKL) + ExternalProject_Add(openpose_lib + SOURCE_DIR ${CAFFE_URL} + PREFIX ${CAFFE_PREFIX} + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= + -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} + -DUSE_CUDNN=${USE_CUDNN} + -DCUDA_ARCH_NAME=${CUDA_ARCH} + -DCUDA_ARCH_BIN=${CUDA_ARCH_BIN} + -DCUDA_ARCH_PTX=${CUDA_ARCH_PTX} + -DCPU_ONLY=${CAFFE_CPU_ONLY} + -DCMAKE_BUILD_TYPE=Release + -DBUILD_docs=OFF + -DBUILD_python=OFF + -DBUILD_python_layer=OFF + -DUSE_LEVELDB=OFF + -DUSE_LMDB=OFF + -DUSE_OPENCV=OFF) + # -DOpenCV_DIR=${OpenCV_DIR}) + endif (USE_MKL) + + ExternalProject_Get_Property(openpose_lib install_dir) + + if (NOT Caffe_FOUND) + add_custom_command(TARGET openpose_lib + POST_BUILD + COMMAND ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR} + COMMAND $(MAKE) + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Rerunning cmake after building Caffe submodule") + endif (NOT Caffe_FOUND) + + endif (BUILD_CAFFE) + + if (NOT Caffe_FOUND AND NOT BUILD_CAFFE) + message(FATAL_ERROR "Caffe not found. Either turn on the BUILD_CAFFE option or specify the path of Caffe includes + and libs using -DCaffe_INCLUDE_DIRS and -DCaffe_LIBS.") + endif (NOT Caffe_FOUND AND NOT BUILD_CAFFE) + endif (${DL_FRAMEWORK} MATCHES "CAFFE" OR ${DL_FRAMEWORK} MATCHES "NV_CAFFE") +endif (UNIX OR APPLE) + +### PROJECT INCLUDES +# Specify the include directories +include_directories( + include + ${Protobuf_INCLUDE_DIRS} + ${GFLAGS_INCLUDE_DIR} + ${GLOG_INCLUDE_DIR} + ${OpenCV_INCLUDE_DIRS}) + +if (USE_ASIO) + include_directories(${CMAKE_SOURCE_DIR}/3rdparty/asio/include/) + # OpenPose flags + add_definitions(-DUSE_ASIO) + # Tell Asio it is not using Boost + add_definitions(-DASIO_STANDALONE) +endif (USE_ASIO) + +# Calibration +if (NOT ${WITH_EIGEN} MATCHES "NONE") + include_directories(${EIGEN3_INCLUDE_DIRS}) + if (${WITH_EIGEN} MATCHES "FIND") + set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} Eigen3::Eigen) + endif (${WITH_EIGEN} MATCHES "FIND") +endif (NOT ${WITH_EIGEN} MATCHES "NONE") + +if (APPLE) + include_directories("/usr/local/opt/openblas/include") +endif (APPLE) + +if (USE_MKL) + include_directories("${MKL_PATH}/include/") +endif (USE_MKL) + +if (Caffe_FOUND) + include_directories(${Caffe_INCLUDE_DIRS}) +endif (Caffe_FOUND) + +if (${GPU_MODE} MATCHES "CUDA") + include_directories(${CUDA_INCLUDE_DIRS}) +elseif (${GPU_MODE} MATCHES "OPENCL") + include_directories(${OpenCL_INCLUDE_DIRS}) +endif (${GPU_MODE} MATCHES "CUDA") +# 3D +if (WITH_3D_RENDERER) + include_directories(${GLUT_INCLUDE_DIRS}) +endif (WITH_3D_RENDERER) +if (WITH_CERES) + include_directories(${CERES_INCLUDE_DIRS}) +endif (WITH_CERES) +if (WITH_FLIR_CAMERA) + include_directories(SYSTEM ${SPINNAKER_INCLUDE_DIRS}) # To remove its warnings, equiv. to -isystem +endif (WITH_FLIR_CAMERA) +if (WITH_3D_ADAM_MODEL) + include_directories(include/adam) # TODO: TEMPORARY - TO BE REMOVED IN THE FUTURE + include_directories(${CERES_INCLUDE_DIRS}) + include_directories(${EIGEN3_INCLUDE_DIRS}) + set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} Eigen3::Eigen) + include_directories(${IGL_INCLUDE_DIRS}) + include_directories(${LIBIGL_INCLUDE_DIRS}) + include_directories(${OPENGL_INCLUDE_DIR} ${GLUT_INCLUDE_DIRS} ${GLEW_INCLUDE_DIRS}) +endif (WITH_3D_ADAM_MODEL) +# Windows includes +if (WIN32) + include_directories(${WINDOWS_INCLUDE_DIRS}) +endif (WIN32) + + +### COLLECT ALL 3RD-PARTY LIBRARIES TO BE LINKED AGAINST +if (UNIX OR APPLE) + set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} ${OpenCV_LIBS} ${GLOG_LIBRARY}) +elseif (WIN32) + set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} + debug ${OpenCV_LIBS_DEBUG} optimized ${OpenCV_LIBS_RELEASE} + debug ${GFLAGS_LIBRARY_DEBUG} optimized ${GFLAGS_LIBRARY_RELEASE} + debug ${GLOG_LIBRARY_DEBUG} optimized ${GLOG_LIBRARY_RELEASE}) +endif (UNIX OR APPLE) +# G Flags (for demos) +if (UNIX OR APPLE) + set(examples_3rdparty_libraries ${OpenPose_3rdparty_libraries} ${GFLAGS_LIBRARY}) +endif (UNIX OR APPLE) +# Deep net Framework +if (${DL_FRAMEWORK} MATCHES "CAFFE" OR ${DL_FRAMEWORK} MATCHES "NV_CAFFE") + if (UNIX OR APPLE) + set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} ${Caffe_LIBS}) + elseif (WIN32) + set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} + debug ${Caffe_LIBS_DEBUG} optimized ${Caffe_LIBS_RELEASE}) + endif (UNIX OR APPLE) +endif (${DL_FRAMEWORK} MATCHES "CAFFE" OR ${DL_FRAMEWORK} MATCHES "NV_CAFFE") +# CPU vs. GPU +if (USE_MKL) + set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} ${MKL_LIBS}) +endif (USE_MKL) +if (${GPU_MODE} MATCHES "OPENCL") + set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} ${CMAKE_THREAD_LIBS_INIT} ${OpenCL_LIBRARIES}) +endif (${GPU_MODE} MATCHES "OPENCL") +# Boost +if (WIN32) + if (${GPU_MODE} MATCHES "CPU_ONLY" OR ${GPU_MODE} MATCHES "OPENCL" OR BUILD_PYTHON) + set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} + debug ${BOOST_SYSTEM_LIB_RELEASE} optimized ${BOOST_SYSTEM_LIB_RELEASE}) + set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} + debug ${BOOST_FILESYSTEM_LIB_RELEASE} optimized ${BOOST_FILESYSTEM_LIB_RELEASE}) + endif () +endif (WIN32) +# 3-D +if (WITH_3D_ADAM_MODEL) + set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} + ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${GLEW_LIBRARY} ${FREE_IMAGE_LIBRARY}) +endif (WITH_3D_ADAM_MODEL) +if (WITH_3D_RENDERER) + set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} ${GLUT_LIBRARY} ${OPENGL_LIBRARIES}) +endif (WITH_3D_RENDERER) +if (WITH_CERES) + set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} ${CERES_LIBRARIES}) +endif (WITH_CERES) +if (WITH_FLIR_CAMERA) + set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} ${SPINNAKER_LIB}) +endif (WITH_FLIR_CAMERA) +# Pthread +if (UNIX OR APPLE) + set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} pthread) +endif (UNIX OR APPLE) + + + +### ADD SUBDIRECTORIES +if (Caffe_FOUND) + add_subdirectory(src) + if (BUILD_EXAMPLES) + add_subdirectory(examples) + endif (BUILD_EXAMPLES) +endif (Caffe_FOUND) + + +### DOWNLOAD MODELS +# Download the models if flag is set +message(STATUS "Download the models.") + +# URL to the models +set(OPENPOSE_URL "${DOWNLOAD_SERVER}models/") + +download_model("BODY_25" ${DOWNLOAD_BODY_25_MODEL} pose/body_25/pose_iter_584000.caffemodel + 78287B57CF85FA89C03F1393D368E5B7) # Body (BODY_25) +download_model("body (COCO)" ${DOWNLOAD_BODY_COCO_MODEL} pose/coco/pose_iter_440000.caffemodel + 5156d31f670511fce9b4e28b403f2939) # Body (COCO) +download_model("body (MPI)" ${DOWNLOAD_BODY_MPI_MODEL} pose/mpi/pose_iter_160000.caffemodel + 2ca0990c7562bd7ae03f3f54afa96e00) # Body (MPI) +download_model("face" ${DOWNLOAD_FACE_MODEL} face/pose_iter_116000.caffemodel + e747180d728fa4e4418c465828384333) # Face +download_model("hand" ${DOWNLOAD_HAND_MODEL} hand/pose_iter_102000.caffemodel + a82cfc3fea7c62f159e11bd3674c1531) # Hand + +message(STATUS "Models Downloaded.") + + +### PYTHON +if (BUILD_PYTHON) + if (WIN32) + execute_process(COMMAND cmd /c cd ${CMAKE_SOURCE_DIR} & git submodule update --init 3rdparty/pybind11/) + add_subdirectory(3rdparty/pybind11) + add_subdirectory(python) + elseif (UNIX OR APPLE) + if (Caffe_FOUND) + execute_process(COMMAND git submodule update --init ${CMAKE_SOURCE_DIR}/3rdparty/pybind11/) + # execute_process(COMMAND git submodule update --init --recursive --remote) # This would initialize them all + add_subdirectory(3rdparty/pybind11) + add_subdirectory(python) + endif (Caffe_FOUND) + else (WIN32) + message(FATAL_ERROR "Unknown OS.") + endif (WIN32) +endif (BUILD_PYTHON) + + +### GENERATE DOCUMENTATION +if (UNIX OR APPLE) + + if (BUILD_DOCS) + find_package(Doxygen) + if (DOXYGEN_FOUND) + # Set input and output files + set(DOXYGEN_FILE ${CMAKE_SOURCE_DIR}/.doc_autogeneration.doxygen) + + # Custom target to build the documentation + add_custom_target(doc_doxygen ALL + COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_FILE} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/doc + COMMENT "Generating API documentation with Doxygen" + VERBATIM) + else (DOXYGEN_FOUND) + message(FATAL_ERROR "Doxygen needs to be installed to generate the doxygen documentation.") + endif (DOXYGEN_FOUND) + endif (BUILD_DOCS) + +endif (UNIX OR APPLE) + + +### INSTALL +if (UNIX OR APPLE) + if (Caffe_FOUND) + # Install the headers + install(DIRECTORY ${CMAKE_SOURCE_DIR}/include/openpose DESTINATION include) + install(EXPORT OpenPose DESTINATION lib/OpenPose) + if (BUILD_CAFFE) + install(DIRECTORY ${CMAKE_BINARY_DIR}/caffe/include/caffe DESTINATION include) + install(DIRECTORY ${CMAKE_BINARY_DIR}/caffe/lib/ DESTINATION lib) + endif (BUILD_CAFFE) + + # Compute installation prefix relative to this file + configure_file( + ${CMAKE_SOURCE_DIR}/cmake/OpenPoseConfig.cmake.in + ${CMAKE_BINARY_DIR}/cmake/OpenPoseConfig.cmake @ONLY) + + install(FILES ${CMAKE_BINARY_DIR}/cmake/OpenPoseConfig.cmake + DESTINATION lib/OpenPose) + + # Uninstall target + configure_file( + "${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" + "${CMAKE_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + + add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) + endif (Caffe_FOUND) +endif (UNIX OR APPLE) diff --git a/openpose/LICENSE b/openpose/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..71739cad8355a58f3f64aa31e8863bf1416d7ac8 --- /dev/null +++ b/openpose/LICENSE @@ -0,0 +1,108 @@ +OPENPOSE: MULTIPERSON KEYPOINT DETECTION +SOFTWARE LICENSE AGREEMENT +ACADEMIC OR NON-PROFIT ORGANIZATION NONCOMMERCIAL RESEARCH USE ONLY + +BY USING OR DOWNLOADING THE SOFTWARE, YOU ARE AGREEING TO THE TERMS OF THIS LICENSE AGREEMENT. IF YOU DO NOT AGREE WITH THESE TERMS, YOU MAY NOT USE OR DOWNLOAD THE SOFTWARE. + +This is a license agreement ("Agreement") between your academic institution or non-profit organization or self (called "Licensee" or "You" in this Agreement) and Carnegie Mellon University (called "Licensor" in this Agreement). All rights not specifically granted to you in this Agreement are reserved for Licensor. + +RESERVATION OF OWNERSHIP AND GRANT OF LICENSE: +Licensor retains exclusive ownership of any copy of the Software (as defined below) licensed under this Agreement and hereby grants to Licensee a personal, non-exclusive, +non-transferable license to use the Software for noncommercial research purposes, without the right to sublicense, pursuant to the terms and conditions of this Agreement. As used in this Agreement, the term "Software" means (i) the actual copy of all or any portion of code for program routines made accessible to Licensee by Licensor pursuant to this Agreement, inclusive of backups, updates, and/or merged copies permitted hereunder or subsequently supplied by Licensor, including all or any file structures, programming instructions, user interfaces and screen formats and sequences as well as any and all documentation and instructions related to it, and (ii) all or any derivatives and/or modifications created or made by You to any of the items specified in (i). + +CONFIDENTIALITY: Licensee acknowledges that the Software is proprietary to Licensor, and as such, Licensee agrees to receive all such materials in confidence and use the Software only in accordance with the terms of this Agreement. Licensee agrees to use reasonable effort to protect the Software from unauthorized use, reproduction, distribution, or publication. + +COPYRIGHT: The Software is owned by Licensor and is protected by United +States copyright laws and applicable international treaties and/or conventions. + +PERMITTED USES: The Software may be used for your own noncommercial internal research purposes. You understand and agree that Licensor is not obligated to implement any suggestions and/or feedback you might provide regarding the Software, but to the extent Licensor does so, you are not entitled to any compensation related thereto. + +DERIVATIVES: You may create derivatives of or make modifications to the Software, however, You agree that all and any such derivatives and modifications will be owned by Licensor and become a part of the Software licensed to You under this Agreement.  You may only use such derivatives and modifications for your own noncommercial internal research purposes, and you may not otherwise use, distribute or copy such derivatives and modifications in violation of this Agreement. + +BACKUPS: If Licensee is an organization, it may make that number of copies of the Software necessary for internal noncommercial use at a single site within its organization provided that all information appearing in or on the original labels, including the copyright and trademark notices are copied onto the labels of the copies. + +USES NOT PERMITTED: You may not distribute, copy or use the Software except as explicitly permitted herein. Licensee has not been granted any trademark license as part of this Agreement and may not use the name or mark “OpenPose", "Carnegie Mellon" or any renditions thereof without the prior written permission of Licensor. + +You may not sell, rent, lease, sublicense, lend, time-share or transfer, in whole or in part, or provide third parties access to prior or present versions (or any parts thereof) of the Software. + +ASSIGNMENT: You may not assign this Agreement or your rights hereunder without the prior written consent of Licensor. Any attempted assignment without such consent shall be null and void. + +TERM: The term of the license granted by this Agreement is from Licensee's acceptance of this Agreement by downloading the Software or by using the Software until terminated as provided below. + +The Agreement automatically terminates without notice if you fail to comply with any provision of this Agreement. Licensee may terminate this Agreement by ceasing using the Software. Upon any termination of this Agreement, Licensee will delete any and all copies of the Software. You agree that all provisions which operate to protect the proprietary rights of Licensor shall remain in force should breach occur and that the obligation of confidentiality described in this Agreement is binding in perpetuity and, as such, survives the term of the Agreement. + +FEE: Provided Licensee abides completely by the terms and conditions of this Agreement, there is no fee due to Licensor for Licensee's use of the Software in accordance with this Agreement. + +DISCLAIMER OF WARRANTIES: THE SOFTWARE IS PROVIDED "AS-IS" WITHOUT WARRANTY OF ANY KIND INCLUDING ANY WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE OR PURPOSE OR OF NON-INFRINGEMENT. LICENSEE BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF THE SOFTWARE AND RELATED MATERIALS. + +SUPPORT AND MAINTENANCE: No Software support or training by the Licensor is provided as part of this Agreement. + +EXCLUSIVE REMEDY AND LIMITATION OF LIABILITY: To the maximum extent permitted under applicable law, Licensor shall not be liable for direct, indirect, special, incidental, or consequential damages or lost profits related to Licensee's use of and/or inability to use the Software, even if Licensor is advised of the possibility of such damage. + +EXPORT REGULATION: Licensee agrees to comply with any and all applicable +U.S. export control laws, regulations, and/or other laws related to embargoes and sanction programs administered by the Office of Foreign Assets Control. + +SEVERABILITY: If any provision(s) of this Agreement shall be held to be invalid, illegal, or unenforceable by a court or other tribunal of competent jurisdiction, the validity, legality and enforceability of the remaining provisions shall not in any way be affected or impaired thereby. + +NO IMPLIED WAIVERS: No failure or delay by Licensor in enforcing any right or remedy under this Agreement shall be construed as a waiver of any future or other exercise of such right or remedy by Licensor. + +GOVERNING LAW: This Agreement shall be construed and enforced in accordance with the laws of the Commonwealth of Pennsylvania without reference to conflict of laws principles. You consent to the personal jurisdiction of the courts of this County and waive their rights to venue outside of Allegheny County, Pennsylvania. + +ENTIRE AGREEMENT AND AMENDMENTS: This Agreement constitutes the sole and entire agreement between Licensee and Licensor as to the matter set forth herein and supersedes any previous agreements, understandings, and arrangements between the parties relating hereto. + + + +************************************************************************ + +THIRD-PARTY SOFTWARE NOTICES AND INFORMATION + +This project incorporates material from the project(s) listed below (collectively, "Third Party Code"). This Third Party Code is licensed to you under their original license terms set forth below. We reserves all other rights not expressly granted, whether by implication, estoppel or otherwise. + +1. Caffe, version 1.0.0, (https://github.com/BVLC/caffe/) + +COPYRIGHT + +All contributions by the University of California: +Copyright (c) 2014-2017 The Regents of the University of California (Regents) +All rights reserved. + +All other contributions: +Copyright (c) 2014-2017, the respective contributors +All rights reserved. + +Caffe uses a shared copyright model: each contributor holds copyright over +their contributions to Caffe. The project versioning records all such +contribution and copyright details. If a contributor wants to further mark +their specific copyright on a particular contribution, they should indicate +their copyright solely in the commit message of the change when it is +committed. + +LICENSE + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. 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. + +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 OWNER 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. + +CONTRIBUTION AGREEMENT + +By contributing to the BVLC/caffe repository through pull-request, comment, +or otherwise, the contributor releases their content to the +license and copyright terms herein. + +************END OF THIRD-PARTY SOFTWARE NOTICES AND INFORMATION********** diff --git a/openpose/README.md b/openpose/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b1b826e986a0acd3cef88b52334653a535b5ae8e --- /dev/null +++ b/openpose/README.md @@ -0,0 +1,190 @@ +
+ +
+ +----------------- + +| **Build Type** |`Linux` |`MacOS` |`Windows` | +| :---: | :---: | :---: | :---: | +| **Build Status** | [![Status](https://github.com/CMU-Perceptual-Computing-Lab/openpose/workflows/CI/badge.svg)](https://github.com/CMU-Perceptual-Computing-Lab/openpose/actions) | [![Status](https://github.com/CMU-Perceptual-Computing-Lab/openpose/workflows/CI/badge.svg)](https://github.com/CMU-Perceptual-Computing-Lab/openpose/actions) | [![Status](https://ci.appveyor.com/api/projects/status/5leescxxdwen77kg/branch/master?svg=true)](https://ci.appveyor.com/project/gineshidalgo99/openpose/branch/master) | + +[**OpenPose**](https://github.com/CMU-Perceptual-Computing-Lab/openpose) has represented the **first real-time multi-person system to jointly detect human body, hand, facial, and foot keypoints (in total 135 keypoints) on single images**. + +It is **authored by** [**Ginés Hidalgo**](https://www.gineshidalgo.com), [**Zhe Cao**](https://people.eecs.berkeley.edu/~zhecao), [**Tomas Simon**](http://www.cs.cmu.edu/~tsimon), [**Shih-En Wei**](https://scholar.google.com/citations?user=sFQD3k4AAAAJ&hl=en), [**Yaadhav Raaj**](https://www.raaj.tech), [**Hanbyul Joo**](https://jhugestar.github.io), **and** [**Yaser Sheikh**](http://www.cs.cmu.edu/~yaser). It is **maintained by** [**Ginés Hidalgo**](https://www.gineshidalgo.com) **and** [**Yaadhav Raaj**](https://www.raaj.tech). OpenPose would not be possible without the [**CMU Panoptic Studio dataset**](http://domedb.perception.cs.cmu.edu). We would also like to thank all the people who [have helped OpenPose in any way](doc/09_authors_and_contributors.md). + + + +

+ +
+ Authors Ginés Hidalgo (left) and Hanbyul Joo (right) in front of the CMU Panoptic Studio +

+ + + +## Contents +1. [Results](#results) +2. [Features](#features) +3. [Related Work](#related-work) +4. [Installation](#installation) +5. [Quick Start Overview](#quick-start-overview) +6. [Send Us Feedback!](#send-us-feedback) +7. [Citation](#citation) +8. [License](#license) + + + +## Results +### Whole-body (Body, Foot, Face, and Hands) 2D Pose Estimation +

+ + + +
+ Testing OpenPose: (Left) Crazy Uptown Funk flashmob in Sydney video sequence. (Center and right) Authors Ginés Hidalgo and Tomas Simon testing face and hands +

+ +### Whole-body 3D Pose Reconstruction and Estimation +

+ +
+ Tianyi Zhao testing the OpenPose 3D Module +

+ +### Unity Plugin +

+ + + +
+ Tianyi Zhao and Ginés Hidalgo testing the OpenPose Unity Plugin +

+ +### Runtime Analysis +We show an inference time comparison between the 3 available pose estimation libraries (same hardware and conditions): OpenPose, Alpha-Pose (fast Pytorch version), and Mask R-CNN. The OpenPose runtime is constant, while the runtime of Alpha-Pose and Mask R-CNN grow linearly with the number of people. More details [**here**](https://arxiv.org/abs/1812.08008). + +

+ +

+ + + +## Features +**Main Functionality**: +- **2D real-time multi-person keypoint detection**: + - 15, 18 or **25-keypoint body/foot keypoint estimation**, including **6 foot keypoints**. **Runtime invariant to number of detected people**. + - **2x21-keypoint hand keypoint estimation**. **Runtime depends on number of detected people**. See [**OpenPose Training**](https://github.com/CMU-Perceptual-Computing-Lab/openpose_train) for a runtime invariant alternative. + - **70-keypoint face keypoint estimation**. **Runtime depends on number of detected people**. See [**OpenPose Training**](https://github.com/CMU-Perceptual-Computing-Lab/openpose_train) for a runtime invariant alternative. +- [**3D real-time single-person keypoint detection**](doc/advanced/3d_reconstruction_module.md): + - 3D triangulation from multiple single views. + - Synchronization of Flir cameras handled. + - Compatible with Flir/Point Grey cameras. +- [**Calibration toolbox**](doc/advanced/calibration_module.md): Estimation of distortion, intrinsic, and extrinsic camera parameters. +- **Single-person tracking** for further speedup or visual smoothing. + +**Input**: Image, video, webcam, Flir/Point Grey, IP camera, and support to add your own custom input source (e.g., depth camera). + +**Output**: Basic image + keypoint display/saving (PNG, JPG, AVI, ...), keypoint saving (JSON, XML, YML, ...), keypoints as array class, and support to add your own custom output code (e.g., some fancy UI). + +**OS**: Ubuntu (20, 18, 16, 14), Windows (10, 8), Mac OSX, Nvidia TX2. + +**Hardware compatibility**: CUDA (Nvidia GPU), OpenCL (AMD GPU), and non-GPU (CPU-only) versions. + +**Usage Alternatives**: +- [**Command-line demo**](doc/01_demo.md) for built-in functionality. +- [**C++ API**](doc/04_cpp_api.md/) and [**Python API**](doc/03_python_api.md) for custom functionality. E.g., adding your custom inputs, pre-processing, post-posprocessing, and output steps. + +For further details, check the [major released features](doc/07_major_released_features.md) and [release notes](doc/08_release_notes.md) docs. + + + +## Related Work +- [**OpenPose training code**](https://github.com/CMU-Perceptual-Computing-Lab/openpose_train) +- [**OpenPose foot dataset**](https://cmu-perceptual-computing-lab.github.io/foot_keypoint_dataset/) +- [**OpenPose Unity Plugin**](https://github.com/CMU-Perceptual-Computing-Lab/openpose_unity_plugin) +- OpenPose papers published in **IEEE TPAMI and CVPR**. Cite them in your publications if OpenPose helps your research! (Links and more details in the [Citation](#citation) section below). + + + +## Installation +If you want to use OpenPose without installing or writing any code, simply [download and use the latest Windows portable version of OpenPose](doc/installation/0_index.md#windows-portable-demo)! + +Otherwise, you could [build OpenPose from source](doc/installation/0_index.md#compiling-and-running-openpose-from-source). See the [installation doc](doc/installation/0_index.md) for all the alternatives. + + + +## Quick Start Overview +Simply use the OpenPose Demo from your favorite command-line tool (e.g., Windows PowerShell or Ubuntu Terminal). E.g., this example runs OpenPose on your webcam and displays the body keypoints: +``` +# Ubuntu +./build/examples/openpose/openpose.bin +``` +``` +:: Windows - Portable Demo +bin\OpenPoseDemo.exe --video examples\media\video.avi +``` + +You can also add any of the available flags in any order. E.g., the following example runs on a video (`--video {PATH}`), enables face (`--face`) and hands (`--hand`), and saves the output keypoints on JSON files on disk (`--write_json {PATH}`). +``` +# Ubuntu +./build/examples/openpose/openpose.bin --video examples/media/video.avi --face --hand --write_json output_json_folder/ +``` +``` +:: Windows - Portable Demo +bin\OpenPoseDemo.exe --video examples\media\video.avi --face --hand --write_json output_json_folder/ +``` + +Optionally, you can also extend OpenPose's functionality from its Python and C++ APIs. After [installing](doc/installation/0_index.md) OpenPose, check its [official doc](doc/00_index.md) for a quick overview of all the alternatives and tutorials. + + + +## Send Us Feedback! +Our library is open source for research purposes, and we want to improve it! So let us know (create a new GitHub issue or pull request, email us, etc.) if you... +1. Find/fix any bug (in functionality or speed) or know how to speed up or improve any part of OpenPose. +2. Want to add/show some cool functionality/demo/project made on top of OpenPose. We can add your project link to our [Community-based Projects](doc/10_community_projects.md) section or even integrate it with OpenPose! + + + +## Citation +Please cite these papers in your publications if OpenPose helps your research. All of OpenPose is based on [OpenPose: Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields](https://arxiv.org/abs/1812.08008), while the hand and face detectors also use [Hand Keypoint Detection in Single Images using Multiview Bootstrapping](https://arxiv.org/abs/1704.07809) (the face detector was trained using the same procedure as the hand detector). + + @article{8765346, + author = {Z. {Cao} and G. {Hidalgo Martinez} and T. {Simon} and S. {Wei} and Y. A. {Sheikh}}, + journal = {IEEE Transactions on Pattern Analysis and Machine Intelligence}, + title = {OpenPose: Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields}, + year = {2019} + } + + @inproceedings{simon2017hand, + author = {Tomas Simon and Hanbyul Joo and Iain Matthews and Yaser Sheikh}, + booktitle = {CVPR}, + title = {Hand Keypoint Detection in Single Images using Multiview Bootstrapping}, + year = {2017} + } + + @inproceedings{cao2017realtime, + author = {Zhe Cao and Tomas Simon and Shih-En Wei and Yaser Sheikh}, + booktitle = {CVPR}, + title = {Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields}, + year = {2017} + } + + @inproceedings{wei2016cpm, + author = {Shih-En Wei and Varun Ramakrishna and Takeo Kanade and Yaser Sheikh}, + booktitle = {CVPR}, + title = {Convolutional pose machines}, + year = {2016} + } + +Paper links: +- OpenPose: Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields: + - [IEEE TPAMI](https://ieeexplore.ieee.org/document/8765346) + - [ArXiv](https://arxiv.org/abs/1812.08008) +- [Hand Keypoint Detection in Single Images using Multiview Bootstrapping](https://arxiv.org/abs/1704.07809) +- [Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields](https://arxiv.org/abs/1611.08050) +- [Convolutional Pose Machines](https://arxiv.org/abs/1602.00134) + + + +## License +OpenPose is freely available for free non-commercial use, and may be redistributed under these conditions. Please, see the [license](./LICENSE) for further details. Interested in a commercial license? Check this [FlintBox link](https://cmu.flintbox.com/#technologies/b820c21d-8443-4aa2-a49f-8919d93a8740). For commercial queries, use the `Contact` section from the [FlintBox link](https://cmu.flintbox.com/#technologies/b820c21d-8443-4aa2-a49f-8919d93a8740) and also send a copy of that message to [Yaser Sheikh](mailto:yaser@cs.cmu.edu). diff --git a/openpose/appveyor.yml b/openpose/appveyor.yml new file mode 100644 index 0000000000000000000000000000000000000000..394e8b6babfd07731bbc403844869f7c65c9b413 --- /dev/null +++ b/openpose/appveyor.yml @@ -0,0 +1,36 @@ +image: Visual Studio 2019 +clone_folder: c:\openpose + +build_script: + - mkdir build + - cd build + - cmake -DGPU_MODE=CPU_ONLY -G "Visual Studio 16 2019" -A x64 .. + - cmake --build . --config "Release" + +after_build: + - ps: cd .. + - ps: mkdir artifacts + - ps: mkdir artifacts/bin + - ps: mkdir artifacts/examples + - ps: mkdir artifacts/examples/media + - ps: mkdir artifacts/include + - ps: mkdir artifacts/lib + - ps: Get-ChildItem -Path build/x64/Release/*.exe -Recurse -File | Copy-Item -Destination artifacts/bin + - ps: Get-ChildItem -Path build/x64/Release/*.dll -Recurse -File | Copy-Item -Destination artifacts/bin + - ps: Get-ChildItem -Path build/bin/*.dll -Recurse -File | Copy-Item -Destination artifacts/bin + - ps: Get-ChildItem -Path examples/media/* -Recurse -File | Copy-Item -Destination artifacts/examples/media + - ps: Copy-Item include/openpose -Recurse -Destination artifacts/include/ + - ps: Copy-Item 3rdparty/windows/opencv/include/opencv2 -Recurse -Destination artifacts/include/ + - ps: Get-ChildItem -Path build/*.lib -Recurse -File | Copy-Item -Destination artifacts/lib + - ps: Get-ChildItem -Path 3rdparty/*.lib -Recurse -File | Copy-Item -Destination artifacts/lib + - ps: Copy-Item models -Recurse -Destination artifacts/ + - ps: cd artifacts + # - ps: 7z a ..\openpose.zip . # `artifacts` disabled + - ps: cd .. + # Test + - ps: .\artifacts\bin\OpenPoseDemo.exe --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0 + +# `artifacts` disabled because of the AppVeyor crash: "Maximum allowed artifact storage size of 50000 Mb will be exceeded." +# artifacts: +# - path: openpose.zip +# name: OpenPose diff --git a/openpose/cmake/Cuda.cmake b/openpose/cmake/Cuda.cmake new file mode 100644 index 0000000000000000000000000000000000000000..c6315dccbb1e74a2c3a8fe79cd8560f704782ed8 --- /dev/null +++ b/openpose/cmake/Cuda.cmake @@ -0,0 +1,340 @@ +# Copied from Caffe + +# More info on available architectures vs. CUDA version: +# http://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/ + +if (CPU_ONLY) + return() +endif () + +################################################################################################ +# Remove duplicates from list(s) +# Usage: +# op_list_unique( [] [...]) +macro(op_list_unique) + foreach(__lst ${ARGN}) + if (${__lst}) + list(REMOVE_DUPLICATES ${__lst}) + endif () + endforeach() +endmacro() + +# This list will be used for CUDA_ARCH = All option +# Fermi (3.2 <= CUDA <= 8) +# set(FERMI "20 21(20)") +# Kepler (CUDA >= 5) +set(KEPLER "35 37") # set(KEPLER "30 35 37") # This crashes with CUDA 10 +# Maxwell (CUDA >= 6) +set(MAXWELL "50 52 53") +# Pascal (CUDA >= 8) +set(PASCAL "60 61 62") +# Volta (CUDA >= 9) +set(VOLTA "70 72") # set(VOLTA "70 71 72") # This crashes with CUDA 10 +# Turing (CUDA >= 10) +set(TURING "75") +# Ampere (CUDA >= 11) +set(AMPERE "80 86") +if (UNIX AND NOT APPLE) + set(Caffe_known_gpu_archs "${KEPLER} ${MAXWELL} ${PASCAL} ${VOLTA} ${TURING} ${AMPERE}") + # set(Caffe_known_gpu_archs "${FERMI} ${KEPLER} ${MAXWELL} ${PASCAL} ${VOLTA} ${TURING}") + # set(Caffe_known_gpu_archs "20 21(20) 30 35 50 52 60 61") +elseif (WIN32) + set(Caffe_known_gpu_archs "${KEPLER} ${MAXWELL} ${PASCAL} ${VOLTA} ${TURING} ${AMPERE}") +endif () + + +################################################################################################ +# A function for automatic detection of GPUs installed (if autodetection is enabled) +# Usage: +# op_detect_installed_gpus(out_variable) +function(op_detect_installed_gpus out_variable) + if (NOT CUDA_gpu_detect_output) + set(__cufile ${PROJECT_BINARY_DIR}/detect_cuda_archs.cu) + + file(WRITE ${__cufile} "" + "#include \n" + "int main()\n" + "{\n" + " int count = 0;\n" + " if (cudaSuccess != cudaGetDeviceCount(&count)) return -1;\n" + " if (count == 0) return -1;\n" + " for (int device = 0; device < count; ++device)\n" + " {\n" + " cudaDeviceProp prop;\n" + " if (cudaSuccess == cudaGetDeviceProperties(&prop, device))\n" + " std::printf(\"%d.%d \", prop.major, prop.minor);\n" + " }\n" + " return 0;\n" + "}\n") + + execute_process(COMMAND "${CUDA_NVCC_EXECUTABLE}" "--run" "${__cufile}" + WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/CMakeFiles/" + RESULT_VARIABLE __nvcc_res OUTPUT_VARIABLE __nvcc_out + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + + if (__nvcc_res EQUAL 0) + if (NOT WIN32) + string(REPLACE "2.1" "2.1(2.0)" __nvcc_out "${__nvcc_out}") + endif (NOT WIN32) + set(CUDA_gpu_detect_output ${__nvcc_out} CACHE INTERNAL "Returned GPU architectures from op_detect_gpus tool" FORCE) + endif () + endif () + + if (NOT CUDA_gpu_detect_output) + message(STATUS "Automatic GPU detection failed. Building for all known architectures.") + set(${out_variable} ${Caffe_known_gpu_archs} PARENT_SCOPE) + else () + set(${out_variable} ${CUDA_gpu_detect_output} PARENT_SCOPE) + endif () +endfunction() + + +################################################################################################ +# Function for selecting GPU arch flags for nvcc based on CUDA_ARCH +# Usage: +# op_select_nvcc_arch_flags(out_variable) +function(op_select_nvcc_arch_flags out_variable) + # List of arch names + set(__archs_names "Kepler (CUDA >= 5)" "Maxwell (CUDA >= 6)" "Pascal (CUDA >= 8)" "Volta (CUDA >= 9)" "Turing (CUDA >= 10)" "All" "Manual") + # set(__archs_names "Fermi (3.2 <= CUDA <= 8)" "Kepler (CUDA >= 5)" "Maxwell (CUDA >= 6)" "Pascal (CUDA >= 8)" "Volta (CUDA >= 9)" "Turing (CUDA >= 10)" "All" "Manual") + set(__archs_name_default "All") + if (NOT CMAKE_CROSSCOMPILING) + list(APPEND __archs_names "Auto") + set(__archs_name_default "Auto") + endif () + + # set CUDA_ARCH strings (so it will be seen as dropbox in CMake-Gui) + # set(CUDA_ARCH ${__archs_name_default} CACHE STRING "Select target NVIDIA GPU architecture.") + # set_property( CACHE CUDA_ARCH PROPERTY STRINGS "" ${__archs_names} ) + # mark_as_advanced(CUDA_ARCH) + + # verify CUDA_ARCH value + if (NOT ";${__archs_names};" MATCHES ";${CUDA_ARCH};") + string(REPLACE ";" ", " __archs_names "${__archs_names}") + message(FATAL_ERROR "Only ${__archs_names} architecture names are supported.") + endif () + + if (${CUDA_ARCH} STREQUAL "Manual") + set(CUDA_ARCH_BIN ${Caffe_known_gpu_archs} CACHE STRING "Specify 'real' GPU architectures to build binaries for, BIN(PTX) format is supported") + set(CUDA_ARCH_PTX "50" CACHE STRING "Specify 'virtual' PTX architectures to build PTX intermediate code for") + # mark_as_advanced(CUDA_ARCH_BIN CUDA_ARCH_PTX) + else () + unset(CUDA_ARCH_BIN CACHE) + unset(CUDA_ARCH_PTX CACHE) + endif () + + if (${CUDA_ARCH} STREQUAL "Fermi (3.2 <= CUDA <= 8)" AND NOT WIN32) + set(__cuda_arch_bin ${FERMI}) + elseif (${CUDA_ARCH} STREQUAL "Kepler (CUDA >= 5)") + set(__cuda_arch_bin ${KEPLER}) + elseif (${CUDA_ARCH} STREQUAL "Maxwell (CUDA >= 6)") + set(__cuda_arch_bin ${MAXWELL}) + elseif (${CUDA_ARCH} STREQUAL "Pascal (CUDA >= 8)") + set(__cuda_arch_bin ${PASCAL}) + elseif (${CUDA_ARCH} STREQUAL "Volta (CUDA >= 9)") + set(__cuda_arch_bin ${VOLTA}) + elseif (${CUDA_ARCH} STREQUAL "Turing (CUDA >= 10)") + set(__cuda_arch_bin ${TURING}) + elseif (${CUDA_ARCH} STREQUAL "All") + set(__cuda_arch_bin ${Caffe_known_gpu_archs}) + elseif (${CUDA_ARCH} STREQUAL "Auto") + op_detect_installed_gpus(__cuda_arch_bin) + else () # (${CUDA_ARCH} STREQUAL "Manual") + set(__cuda_arch_bin ${CUDA_ARCH_BIN}) + endif () + + # remove dots and convert to lists + string(REGEX REPLACE "\\." "" __cuda_arch_bin "${__cuda_arch_bin}") + string(REGEX REPLACE "\\." "" __cuda_arch_ptx "${CUDA_ARCH_PTX}") + string(REGEX MATCHALL "[0-9()]+" __cuda_arch_bin "${__cuda_arch_bin}") + string(REGEX MATCHALL "[0-9]+" __cuda_arch_ptx "${__cuda_arch_ptx}") + op_list_unique(__cuda_arch_bin __cuda_arch_ptx) + + set(__nvcc_flags "") + set(__nvcc_archs_readable "") + + # Tell NVCC to add binaries for the specified GPUs + foreach(__arch ${__cuda_arch_bin}) + if (__arch MATCHES "([0-9]+)\\(([0-9]+)\\)") + # User explicitly specified PTX for the concrete BIN + list(APPEND __nvcc_flags -gencode arch=compute_${CMAKE_MATCH_2},code=sm_${CMAKE_MATCH_1}) + list(APPEND __nvcc_archs_readable sm_${CMAKE_MATCH_1}) + else () + # User didn't explicitly specify PTX for the concrete BIN, we assume PTX=BIN + list(APPEND __nvcc_flags -gencode arch=compute_${__arch},code=sm_${__arch}) + list(APPEND __nvcc_archs_readable sm_${__arch}) + endif () + endforeach() + + # Tell NVCC to add PTX intermediate code for the specified architectures + foreach(__arch ${__cuda_arch_ptx}) + list(APPEND __nvcc_flags -gencode arch=compute_${__arch},code=compute_${__arch}) + list(APPEND __nvcc_archs_readable compute_${__arch}) + endforeach() + + string(REPLACE ";" " " __nvcc_archs_readable "${__nvcc_archs_readable}") + set(${out_variable} ${__nvcc_flags} PARENT_SCOPE) + set(${out_variable}_readable ${__nvcc_archs_readable} PARENT_SCOPE) +endfunction() + +################################################################################################ +# Short command for cuda compilation +# Usage: +# op_cuda_compile( ) +macro(op_cuda_compile objlist_variable) + foreach(var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG) + set(${var}_backup_in_cuda_compile_ "${${var}}") + + # we remove /EHa as it generates warnings under windows + string(REPLACE "/EHa" "" ${var} "${${var}}") + + endforeach() + + if (UNIX OR APPLE) + list(APPEND CUDA_NVCC_FLAGS -Xcompiler -fPIC) + endif () + + if (APPLE) + list(APPEND CUDA_NVCC_FLAGS -Xcompiler -Wno-unused-function) + endif () + + cuda_compile(cuda_objcs ${ARGN}) + + foreach(var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG) + set(${var} "${${var}_backup_in_cuda_compile_}") + unset(${var}_backup_in_cuda_compile_) + endforeach() + + set(${objlist_variable} ${cuda_objcs}) +endmacro() + +################################################################################################ +# Short command for cuDNN detection. Believe it soon will be a part of CUDA toolkit distribution. +# That's why not FindcuDNN.cmake file, but just the macro +# Usage: +# detect_cuDNN() +function(detect_cuDNN) + set(CUDNN_ROOT "" CACHE PATH "CUDNN root folder") + + find_path(CUDNN_INCLUDE cudnn.h + PATHS ${CUDNN_ROOT} $ENV{CUDNN_ROOT} ${CUDA_TOOLKIT_INCLUDE} + DOC "Path to cuDNN include directory." ) + + # dynamic libs have different suffix in mac and linux + if (APPLE) + set(CUDNN_LIB_NAME "libcudnn.dylib") + else () + set(CUDNN_LIB_NAME "libcudnn.so") + endif () + + get_filename_component(__libpath_hist ${CUDA_CUDART_LIBRARY} PATH) + find_library(CUDNN_LIBRARY NAMES ${CUDNN_LIB_NAME} + PATHS ${CUDNN_ROOT} $ENV{CUDNN_ROOT} ${CUDNN_INCLUDE} ${__libpath_hist} ${__libpath_hist}/../lib + DOC "Path to cuDNN library.") + + if (CUDNN_INCLUDE AND CUDNN_LIBRARY) + set(HAVE_CUDNN TRUE PARENT_SCOPE) + set(CUDNN_FOUND TRUE PARENT_SCOPE) + + if(EXISTS "${CUDNN_INCLUDE}/cudnn_version.h") + file(READ ${CUDNN_INCLUDE}/cudnn_version.h CUDNN_VERSION_FILE_CONTENTS) + else() + file(READ ${CUDNN_INCLUDE}/cudnn.h CUDNN_VERSION_FILE_CONTENTS) + endif() + + # cuDNN v3 and beyond + string(REGEX MATCH "define CUDNN_MAJOR * +([0-9]+)" + CUDNN_VERSION_MAJOR "${CUDNN_VERSION_FILE_CONTENTS}") + string(REGEX REPLACE "define CUDNN_MAJOR * +([0-9]+)" "\\1" + CUDNN_VERSION_MAJOR "${CUDNN_VERSION_MAJOR}") + string(REGEX MATCH "define CUDNN_MINOR * +([0-9]+)" + CUDNN_VERSION_MINOR "${CUDNN_VERSION_FILE_CONTENTS}") + string(REGEX REPLACE "define CUDNN_MINOR * +([0-9]+)" "\\1" + CUDNN_VERSION_MINOR "${CUDNN_VERSION_MINOR}") + string(REGEX MATCH "define CUDNN_PATCHLEVEL * +([0-9]+)" + CUDNN_VERSION_PATCH "${CUDNN_VERSION_FILE_CONTENTS}") + string(REGEX REPLACE "define CUDNN_PATCHLEVEL * +([0-9]+)" "\\1" + CUDNN_VERSION_PATCH "${CUDNN_VERSION_PATCH}") + + if (NOT CUDNN_VERSION_MAJOR) + set(CUDNN_VERSION "???") + else () + set(CUDNN_VERSION "${CUDNN_VERSION_MAJOR}.${CUDNN_VERSION_MINOR}.${CUDNN_VERSION_PATCH}") + endif () + + message(STATUS "Found cuDNN: ver. ${CUDNN_VERSION} found (include: ${CUDNN_INCLUDE}, library: ${CUDNN_LIBRARY})") + + string(COMPARE LESS "${CUDNN_VERSION_MAJOR}" 3 cuDNNVersionIncompatible) + if (cuDNNVersionIncompatible) + message(FATAL_ERROR "cuDNN version >3 is required.") + endif () + + set(CUDNN_VERSION "${CUDNN_VERSION}" PARENT_SCOPE) + mark_as_advanced(CUDNN_INCLUDE CUDNN_LIBRARY CUDNN_ROOT) + + endif () +endfunction() + +################################################################################################ +### Non macro section +################################################################################################ + +find_package(CUDA 5.5 QUIET) +find_cuda_helper_libs(curand) # cmake 2.8.7 compartibility which doesn't search for curand + +if (NOT CUDA_FOUND) + return() +endif () + +set(HAVE_CUDA TRUE) +message(STATUS "CUDA detected: " ${CUDA_VERSION}) +list(APPEND Caffe_INCLUDE_DIRS PUBLIC ${CUDA_INCLUDE_DIRS}) +list(APPEND Caffe_LINKER_LIBS PUBLIC ${CUDA_CUDART_LIBRARY} + ${CUDA_curand_LIBRARY} ${CUDA_CUBLAS_LIBRARIES}) + +# cudnn detection +if (USE_CUDNN) + detect_cuDNN() + if (HAVE_CUDNN) + list(APPEND Caffe_DEFINITIONS PUBLIC -DUSE_CUDNN) + list(APPEND Caffe_INCLUDE_DIRS PUBLIC ${CUDNN_INCLUDE}) + list(APPEND Caffe_LINKER_LIBS PUBLIC ${CUDNN_LIBRARY}) + endif () +endif () + +# setting nvcc arch flags +op_select_nvcc_arch_flags(NVCC_FLAGS_EXTRA) +list(APPEND CUDA_NVCC_FLAGS ${NVCC_FLAGS_EXTRA}) +message(STATUS "Added CUDA NVCC flags for: ${NVCC_FLAGS_EXTRA_readable}") + +# Boost 1.55 workaround, see https://svn.boost.org/trac/boost/ticket/9392 or +# https://github.com/ComputationalRadiationPhysics/picongpu/blob/master/src/picongpu/CMakeLists.txt +if (Boost_VERSION EQUAL 105500) + message(STATUS "Cuda + Boost 1.55: Applying noinline work around") + # avoid warning for CMake >= 2.8.12 + set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} \"-DBOOST_NOINLINE=__attribute__((noinline))\" ") +endif () + +# disable some nvcc diagnostic that apears in boost, glog, glags, opencv, etc. +foreach(diag cc_clobber_ignored integer_sign_change useless_using_declaration set_but_not_used) + list(APPEND CUDA_NVCC_FLAGS -Xcudafe --diag_suppress=${diag}) +endforeach() + +# setting default testing device +if (NOT CUDA_TEST_DEVICE) + set(CUDA_TEST_DEVICE -1) +endif () + +mark_as_advanced(CUDA_BUILD_CUBIN CUDA_BUILD_EMULATION CUDA_VERBOSE_BUILD) +mark_as_advanced(CUDA_SDK_ROOT_DIR CUDA_SEPARABLE_COMPILATION) + +# Handle clang/libc++ issue +if (APPLE) + op_detect_darwin_version(OSX_VERSION) + + # OSX 10.9 and higher uses clang/libc++ by default which is incompatible with old CUDA toolkits + if (OSX_VERSION VERSION_GREATER 10.8) + # enabled by default if and only if CUDA version is less than 7.0 + op_option(USE_libstdcpp "Use libstdc++ instead of libc++" (CUDA_VERSION VERSION_LESS 7.0)) + endif () +endif () diff --git a/openpose/cmake/Modules/FindCaffe.cmake b/openpose/cmake/Modules/FindCaffe.cmake new file mode 100644 index 0000000000000000000000000000000000000000..c7992bb7cb29e6911a6c6078c9f804254ec82799 --- /dev/null +++ b/openpose/cmake/Modules/FindCaffe.cmake @@ -0,0 +1,27 @@ +# Copied from +# https://raw.githubusercontent.com/opencv/opencv_contrib/master/modules/cnn_3dobj/FindCaffe.cmake + +unset(Caffe_FOUND) +unset(Caffe_INCLUDE_DIRS) +unset(Caffe_LIBS) + +find_path(Caffe_INCLUDE_DIRS NAMES + caffe/caffe.hpp + caffe/common.hpp + caffe/net.hpp + caffe/proto/caffe.pb.h + caffe/util/io.hpp + HINTS + ${CMAKE_BINARY_DIR}/caffe/include + NO_DEFAULT_PATH) + + +find_library(Caffe_LIBS NAMES caffe + HINTS + ${CMAKE_BINARY_DIR}/caffe/lib + ${CMAKE_BINARY_DIR}/caffe/lib/x86_64-linux-gnu + NO_DEFAULT_PATH) + +if (Caffe_LIBS AND Caffe_INCLUDE_DIRS) + set(Caffe_FOUND 1) +endif (Caffe_LIBS AND Caffe_INCLUDE_DIRS) diff --git a/openpose/cmake/Modules/FindCuDNN.cmake b/openpose/cmake/Modules/FindCuDNN.cmake new file mode 100644 index 0000000000000000000000000000000000000000..182ee271c398a2f4c905d1f8b2b63a18c51b2d05 --- /dev/null +++ b/openpose/cmake/Modules/FindCuDNN.cmake @@ -0,0 +1,54 @@ +set(CUDNN_ROOT "" CACHE PATH "CUDNN root folder") +set(CUDNN_LIB_NAME "libcudnn.so") + +find_path(CUDNN_INCLUDE cudnn.h + PATHS ${CUDNN_ROOT} $ENV{CUDNN_ROOT} ${CUDA_TOOLKIT_INCLUDE} + DOC "Path to cuDNN include directory." ) + +get_filename_component(__libpath_hist ${CUDA_CUDART_LIBRARY} PATH) +find_library(CUDNN_LIBRARY NAMES ${CUDNN_LIB_NAME} + PATHS ${CUDNN_ROOT} $ENV{CUDNN_ROOT} ${CUDNN_INCLUDE} ${__libpath_hist} ${__libpath_hist}/../lib + DOC "Path to cuDNN library.") + +if(CUDNN_INCLUDE AND CUDNN_LIBRARY) + set(HAVE_CUDNN TRUE) + set(CUDNN_FOUND TRUE) + + if(EXISTS "${CUDNN_INCLUDE}/cudnn_version.h") + file(READ ${CUDNN_INCLUDE}/cudnn_version.h CUDNN_VERSION_FILE_CONTENTS) + else() + file(READ ${CUDNN_INCLUDE}/cudnn.h CUDNN_VERSION_FILE_CONTENTS) + endif() + + # cuDNN v3 and beyond + string(REGEX MATCH "define CUDNN_MAJOR * +([0-9]+)" + CUDNN_VERSION_MAJOR "${CUDNN_VERSION_FILE_CONTENTS}") + string(REGEX REPLACE "define CUDNN_MAJOR * +([0-9]+)" "\\1" + CUDNN_VERSION_MAJOR "${CUDNN_VERSION_MAJOR}") + string(REGEX MATCH "define CUDNN_MINOR * +([0-9]+)" + CUDNN_VERSION_MINOR "${CUDNN_VERSION_FILE_CONTENTS}") + string(REGEX REPLACE "define CUDNN_MINOR * +([0-9]+)" "\\1" + CUDNN_VERSION_MINOR "${CUDNN_VERSION_MINOR}") + string(REGEX MATCH "define CUDNN_PATCHLEVEL * +([0-9]+)" + CUDNN_VERSION_PATCH "${CUDNN_VERSION_FILE_CONTENTS}") + string(REGEX REPLACE "define CUDNN_PATCHLEVEL * +([0-9]+)" "\\1" + CUDNN_VERSION_PATCH "${CUDNN_VERSION_PATCH}") + + if (NOT CUDNN_VERSION_MAJOR) + set(CUDNN_VERSION "???") + else () + set(CUDNN_VERSION "${CUDNN_VERSION_MAJOR}.${CUDNN_VERSION_MINOR}.${CUDNN_VERSION_PATCH}") + endif() + + message(STATUS "Found cuDNN: ver. ${CUDNN_VERSION} found (include: ${CUDNN_INCLUDE}, library: ${CUDNN_LIBRARY})") + + string(COMPARE LESS "${CUDNN_VERSION_MAJOR}" 3 cuDNNVersionIncompatible) + if(cuDNNVersionIncompatible) + message(FATAL_ERROR "cuDNN version >3 is required.") + endif() + + set(CUDNN_VERSION "${CUDNN_VERSION}") + mark_as_advanced(CUDNN_INCLUDE CUDNN_LIBRARY CUDNN_ROOT) +else(CUDNN_INCLUDE AND CUDNN_LIBRARY) + message(STATUS "cuDNN not found") +endif() diff --git a/openpose/cmake/Modules/FindGFlags.cmake b/openpose/cmake/Modules/FindGFlags.cmake new file mode 100644 index 0000000000000000000000000000000000000000..29b60f05037bf2257b44eb191306d000dc64900f --- /dev/null +++ b/openpose/cmake/Modules/FindGFlags.cmake @@ -0,0 +1,50 @@ +# - Try to find GFLAGS +# +# The following variables are optionally searched for defaults +# GFLAGS_ROOT_DIR: Base directory where all GFLAGS components are found +# +# The following are set after configuration is done: +# GFLAGS_FOUND +# GFLAGS_INCLUDE_DIRS +# GFLAGS_LIBRARIES +# GFLAGS_LIBRARYRARY_DIRS + +include(FindPackageHandleStandardArgs) + +set(GFLAGS_ROOT_DIR "" CACHE PATH "Folder contains Gflags") + +# We are testing only a couple of files in the include directories +if(WIN32) + find_path(GFLAGS_INCLUDE_DIR gflags/gflags.h + PATHS ${GFLAGS_ROOT_DIR}/src/windows) +else() + find_path(GFLAGS_INCLUDE_DIR gflags/gflags.h + PATHS ${GFLAGS_ROOT_DIR}) +endif() + +if(MSVC) + find_library(GFLAGS_LIBRARY_RELEASE + NAMES libgflags + PATHS ${GFLAGS_ROOT_DIR} + PATH_SUFFIXES Release) + + find_library(GFLAGS_LIBRARY_DEBUG + NAMES libgflags-debug + PATHS ${GFLAGS_ROOT_DIR} + PATH_SUFFIXES Debug) + + set(GFLAGS_LIBRARY optimized ${GFLAGS_LIBRARY_RELEASE} debug ${GFLAGS_LIBRARY_DEBUG}) +else() + find_library(GFLAGS_LIBRARY gflags) +endif() + +find_package_handle_standard_args(GFlags DEFAULT_MSG GFLAGS_INCLUDE_DIR GFLAGS_LIBRARY) + + +if(GFLAGS_FOUND) + set(GFLAGS_INCLUDE_DIRS ${GFLAGS_INCLUDE_DIR}) + set(GFLAGS_LIBRARIES ${GFLAGS_LIBRARY}) + message(STATUS "Found gflags (include: ${GFLAGS_INCLUDE_DIR}, library: ${GFLAGS_LIBRARY})") + mark_as_advanced(GFLAGS_LIBRARY_DEBUG GFLAGS_LIBRARY_RELEASE + GFLAGS_LIBRARY GFLAGS_INCLUDE_DIR GFLAGS_ROOT_DIR) +endif() diff --git a/openpose/cmake/Modules/FindGlog.cmake b/openpose/cmake/Modules/FindGlog.cmake new file mode 100644 index 0000000000000000000000000000000000000000..79b8e23238d6674c045007e8060ef9eb656964cf --- /dev/null +++ b/openpose/cmake/Modules/FindGlog.cmake @@ -0,0 +1,48 @@ +# - Try to find Glog +# +# The following variables are optionally searched for defaults +# GLOG_ROOT_DIR: Base directory where all GLOG components are found +# +# The following are set after configuration is done: +# GLOG_FOUND +# GLOG_INCLUDE_DIRS +# GLOG_LIBRARIES +# GLOG_LIBRARYRARY_DIRS + +include(FindPackageHandleStandardArgs) + +set(GLOG_ROOT_DIR "" CACHE PATH "Folder contains Google glog") + +if (WIN32) + find_path(GLOG_INCLUDE_DIR glog/logging.h + PATHS ${GLOG_ROOT_DIR}/src/windows) +else () + find_path(GLOG_INCLUDE_DIR glog/logging.h + PATHS ${GLOG_ROOT_DIR}) +endif() + +if (MSVC) + find_library(GLOG_LIBRARY_RELEASE libglog_static + PATHS ${GLOG_ROOT_DIR} + PATH_SUFFIXES Release) + + find_library(GLOG_LIBRARY_DEBUG libglog_static + PATHS ${GLOG_ROOT_DIR} + PATH_SUFFIXES Debug) + + set(GLOG_LIBRARY optimized ${GLOG_LIBRARY_RELEASE} debug ${GLOG_LIBRARY_DEBUG}) +else () + find_library(GLOG_LIBRARY glog + PATHS ${GLOG_ROOT_DIR} + PATH_SUFFIXES lib lib64) +endif() + +find_package_handle_standard_args(Glog DEFAULT_MSG GLOG_INCLUDE_DIR GLOG_LIBRARY) + +if(GLOG_FOUND) + set(GLOG_INCLUDE_DIRS ${GLOG_INCLUDE_DIR}) + set(GLOG_LIBRARIES ${GLOG_LIBRARY}) + message(STATUS "Found glog (include: ${GLOG_INCLUDE_DIR}, library: ${GLOG_LIBRARY})") + mark_as_advanced(GLOG_ROOT_DIR GLOG_LIBRARY_RELEASE GLOG_LIBRARY_DEBUG + GLOG_LIBRARY GLOG_INCLUDE_DIR) +endif() diff --git a/openpose/cmake/Modules/FindLIBIGL.cmake b/openpose/cmake/Modules/FindLIBIGL.cmake new file mode 100644 index 0000000000000000000000000000000000000000..edecfc5c7981138e5924a89968e4c42c73f9b561 --- /dev/null +++ b/openpose/cmake/Modules/FindLIBIGL.cmake @@ -0,0 +1,216 @@ +# Copied from: +# https://github.com/libigl/libigl-examples/blob/master/cmake/FindLIBIGL.cmake + +# - Try to find the LIBIGL library +# Once done this will define +# +# LIBIGL_FOUND - system has LIBIGL +# LIBIGL_INCLUDE_DIR - **the** LIBIGL include directory +# LIBIGL_INCLUDE_DIRS - LIBIGL include directories +# LIBIGL_SOURCES - the LIBIGL source files +if(NOT LIBIGL_FOUND) + +FIND_PATH(LIBIGL_INCLUDE_DIR igl/readOBJ.h + ${PROJECT_SOURCE_DIR}/../../include + ${PROJECT_SOURCE_DIR}/../include + ${PROJECT_SOURCE_DIR}/include + ${PROJECT_SOURCE_DIR}/../libigl/include + ${PROJECT_SOURCE_DIR}/../../libigl/include + $ENV{LIBIGL}/include + $ENV{LIBIGLROOT}/include + $ENV{LIBIGL_ROOT}/include + $ENV{LIBIGL_DIR}/include + $ENV{LIBIGL_DIR}/inc + /usr/include + /usr/local/include + /usr/local/igl/libigl/include +) + + +if(LIBIGL_INCLUDE_DIR) + set(LIBIGL_FOUND TRUE) + set(LIBIGL_INCLUDE_DIRS ${LIBIGL_INCLUDE_DIR} ${LIBIGL_INCLUDE_DIR}/../external/Singular_Value_Decomposition) + #set(LIBIGL_SOURCES + # ${LIBIGL_INCLUDE_DIR}/igl/viewer/Viewer.cpp + #) +endif(LIBIGL_INCLUDE_DIR) + +if(LIBIGL_USE_STATIC_LIBRARY) + add_definitions(-DIGL_STATIC_LIBRARY) + set(LIBIGL_LIB_DIRS + ${CMAKE_BINARY_DIR}/ + ${PROJECT_SOURCE_DIR}/../../lib + ${PROJECT_SOURCE_DIR}/../lib + ${PROJECT_SOURCE_DIR}/lib + ${PROJECT_SOURCE_DIR}/../../libigl/lib + ${PROJECT_SOURCE_DIR}/../libigl/lib + $ENV{LIBIGL}/lib + $ENV{LIBIGLROOT}/lib + $ENV{LIBIGL_ROOT}/lib + $ENV{LIBIGL_DIR}/lib + /usr/lib + /usr/local/lib) + FIND_LIBRARY( LIBIGL_LIBRARY NAMES igl PATHS ${LIBIGL_LIB_DIRS}) + + # try to find pre-requisites + find_package(CORK QUIET) + find_package(CGAL QUIET) + find_package(EMBREE QUIET) + find_package(LIBCOMISO QUIET) + find_package(MATLAB QUIET) + find_package(MOSEK QUIET) + find_package(TETGEN QUIET) + find_package(TINYXML2 QUIET) + find_package(TRIANGLE QUIET) + + # Main library must be found + if(NOT LIBIGL_LIBRARY) + set(LIBIGL_FOUND FALSE) + message(FATAL_ERROR "could NOT find libigl") + endif(NOT LIBIGL_LIBRARY) + set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES} ${LIBIGL_LIBRARY}) + + FIND_LIBRARY( LIBIGLANTTWEAKBAR_LIBRARY NAMES iglanttweakbar PATHS ${LIBIGL_LIB_DIRS}) + if(NOT LIBIGLANTTWEAKBAR_LIBRARY) + set(LIBIGL_FOUND FALSE) + message(FATAL_ERROR "could NOT find libiglanttweakbar") + endif(NOT LIBIGLANTTWEAKBAR_LIBRARY) + set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES} ${LIBIGLANTTWEAKBAR_LIBRARY}) + + # libiglbbw will work with/without mosek + FIND_LIBRARY( LIBIGLBBW_LIBRARY NAMES iglbbw PATHS ${LIBIGL_LIB_DIRS}) + if(NOT LIBIGLBBW_LIBRARY) + set(LIBIGL_FOUND FALSE) + message(FATAL_ERROR "could NOT find libiglbbw") + endif(NOT LIBIGLBBW_LIBRARY) + set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES} ${LIBIGLBBW_LIBRARY}) + + if(LIBCOMISO_FOUND) + FIND_LIBRARY(LIBIGLCOMISO_LIBRARY NAMES iglcomiso PATHS ${LIBIGL_LIB_DIRS}) + if(NOT LIBIGLCOMISO_LIBRARY) + set(LIBIGL_FOUND FALSE) + message(FATAL_ERROR "could NOT find libiglcomiso") + endif(NOT LIBIGLCOMISO_LIBRARY) + set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES} ${LIBIGLCOMISO_LIBRARY}) + endif(LIBCOMISO_FOUND) + + if(CGAL_FOUND) + + FIND_LIBRARY( LIBIGLCGAL_LIBRARY NAMES iglcgal PATHS ${LIBIGL_LIB_DIRS}) + if(NOT LIBIGLCGAL_LIBRARY) + set(LIBIGL_FOUND FALSE) + message(FATAL_ERROR "could NOT find libiglcgal") + endif(NOT LIBIGLCGAL_LIBRARY) + set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES} ${LIBIGLCGAL_LIBRARY}) + endif(CGAL_FOUND) + + if(EMBREE_FOUND) + FIND_LIBRARY( LIBIGLEMBREE_LIBRARY NAMES iglembree PATHS ${LIBIGL_LIB_DIRS}) + if(NOT LIBIGLEMBREE_LIBRARY) + set(LIBIGL_FOUND FALSE) + message(FATAL_ERROR "could NOT find libiglembree") + endif(NOT LIBIGLEMBREE_LIBRARY) + set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES} ${LIBIGLEMBREE_LIBRARY}) + endif(EMBREE_FOUND) + + if(LIM_FOUND) + FIND_LIBRARY( LIBIGLLIM_LIBRARY NAMES igllim PATHS ${LIBIGL_LIB_DIRS}) + if(NOT LIBIGLLIM_LIBRARY) + set(LIBIGL_FOUND FALSE) + message(FATAL_ERROR "could NOT find libigllim") + endif(NOT LIBIGLLIM_LIBRARY) + set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES} ${LIBIGLLIM_LIBRARY}) + endif(LIM_FOUND) + + if(MATLAB_FOUND) + FIND_LIBRARY( LIBIGLMATLAB_LIBRARY NAMES iglmatlab PATHS ${LIBIGL_LIB_DIRS}) + if(NOT LIBIGLMATLAB_LIBRARY) + set(LIBIGL_FOUND FALSE) + message(FATAL_ERROR "could NOT find libiglmatlab") + endif(NOT LIBIGLMATLAB_LIBRARY) + set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES} ${LIBIGLMATLAB_LIBRARY}) + endif(MATLAB_FOUND) + + # mosek support should be determined before trying to find bbw + if(MOSEK_FOUND) + FIND_LIBRARY( LIBIGLMOSEK_LIBRARY NAMES iglmosek PATHS ${LIBIGL_LIB_DIRS}) + if(NOT LIBIGLMOSEK_LIBRARY) + set(LIBIGL_FOUND FALSE) + message(FATAL_ERROR "could NOT find libiglmosek") + endif(NOT LIBIGLMOSEK_LIBRARY) + set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES} ${LIBIGLMOSEK_LIBRARY}) + endif(MOSEK_FOUND) + + FIND_LIBRARY( LIBIGLOPENGL_LIBRARY NAMES iglopengl PATHS ${LIBIGL_LIB_DIRS}) + if(NOT LIBIGLOPENGL_LIBRARY) + set(LIBIGL_FOUND FALSE) + message(FATAL_ERROR "could NOT find libiglopengl") + endif(NOT LIBIGLOPENGL_LIBRARY) + set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES} ${LIBIGLOPENGL_LIBRARY}) + + FIND_LIBRARY( LIBIGLOPENGL2_LIBRARY NAMES iglopengl2 PATHS ${LIBIGL_LIB_DIRS}) + if(NOT LIBIGLOPENGL2_LIBRARY) + set(LIBIGL_FOUND FALSE) + message(FATAL_ERROR "could NOT find libiglopengl2") + endif(NOT LIBIGLOPENGL2_LIBRARY) + set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES} ${LIBIGLOPENGL2_LIBRARY}) + + if(TETGEN_FOUND) + FIND_LIBRARY( LIBIGLTETGEN_LIBRARY NAMES igltetgen PATHS ${LIBIGL_LIB_DIRS}) + if(NOT LIBIGLTETGEN_LIBRARY) + set(LIBIGL_FOUND FALSE) + message(FATAL_ERROR "could NOT find libigltetgen") + endif(NOT LIBIGLTETGEN_LIBRARY) + set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES} ${LIBIGLTETGEN_LIBRARY}) + endif(TETGEN_FOUND) + + if(TINYXML2_FOUND) + FIND_LIBRARY( LIBIGLXML_LIBRARY NAMES iglxml PATHS ${LIBIGL_LIB_DIRS}) + if(NOT LIBIGLXML_LIBRARY) + set(LIBIGL_FOUND FALSE) + message(FATAL_ERROR "could NOT find libiglxml") + endif(NOT LIBIGLXML_LIBRARY) + set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES} ${LIBIGLXML_LIBRARY}) + endif(TINYXML2_FOUND) + + if(TRIANGLE_FOUND) + FIND_LIBRARY( LIBIGLTRIANGLE_LIBRARY NAMES igltriangle PATHS ${LIBIGL_LIB_DIRS}) + if(NOT LIBIGLTRIANGLE_LIBRARY) + set(LIBIGL_FOUND FALSE) + message(FATAL_ERROR "could NOT find libigltriangle") + endif(NOT LIBIGLTRIANGLE_LIBRARY) + set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES} ${LIBIGLTRIANGLE_LIBRARY}) + endif(TRIANGLE_FOUND) + + # libiglviewer is required + FIND_LIBRARY( LIBIGLVIEWER_LIBRARY NAMES iglviewer PATHS ${LIBIGL_LIB_DIRS}) + if(NOT LIBIGLVIEWER_LIBRARY) + set(LIBIGL_FOUND FALSE) + message(FATAL_ERROR "could NOT find libiglviewer") + endif(NOT LIBIGLVIEWER_LIBRARY) + set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES} ${LIBIGLVIEWER_LIBRARY}) + + find_package(OpenMP) + if (OPENMP_FOUND) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + endif(OPENMP_FOUND) + + +endif(LIBIGL_USE_STATIC_LIBRARY) + + + +if(LIBIGL_FOUND) + if(NOT LIBIGL_FIND_QUIETLY) + message(STATUS "Found LIBIGL: ${LIBIGL_INCLUDE_DIR}") + endif(NOT LIBIGL_FIND_QUIETLY) +else(LIBIGL_FOUND) + if(LIBIGL_FIND_REQUIRED) + message(FATAL_ERROR "could NOT find LIBIGL") + endif(LIBIGL_FIND_REQUIRED) +endif(LIBIGL_FOUND) + +MARK_AS_ADVANCED(LIBIGL_INCLUDE_DIRS LIBIGL_INCLUDE_DIR LIBIGL_LIBRARIES IGL_VIEWER_SOURCES) + +endif(NOT LIBIGL_FOUND) diff --git a/openpose/cmake/Modules/FindSpinnaker.cmake b/openpose/cmake/Modules/FindSpinnaker.cmake new file mode 100644 index 0000000000000000000000000000000000000000..6c5cffbea3dd8fb73fc1cb966c5452bc6b56d96b --- /dev/null +++ b/openpose/cmake/Modules/FindSpinnaker.cmake @@ -0,0 +1,20 @@ +# Based on `FindCaffe.cmake` + +unset(SPINNAKER_FOUND) +unset(SPINNAKER_INCLUDE_DIRS) +unset(SPINNAKER_LIB) + +find_path(SPINNAKER_INCLUDE_DIRS NAMES + Spinnaker.h + HINTS + /usr/include/spinnaker/ + /usr/local/include/spinnaker/) + +find_library(SPINNAKER_LIB NAMES Spinnaker + HINTS + /usr/lib + /usr/local/lib) + +if (SPINNAKER_INCLUDE_DIRS AND SPINNAKER_LIB) + set(SPINNAKER_FOUND 1) +endif (SPINNAKER_INCLUDE_DIRS AND SPINNAKER_LIB) diff --git a/openpose/cmake/OpenPose.vcxproj.user b/openpose/cmake/OpenPose.vcxproj.user new file mode 100644 index 0000000000000000000000000000000000000000..409e998a45858a3cde91393e104d62d7861b6fcf --- /dev/null +++ b/openpose/cmake/OpenPose.vcxproj.user @@ -0,0 +1,16 @@ + + + + + PATH=%PATH%;3rdparty\windows\caffe\bin\;3rdparty\windows\opencv\x64\vc15\bin;3rdparty\windows\freeglut\bin\;3rdparty\windows\spinnaker\bin\ + WindowsLocalDebugger + ..\..\.. + + + + PATH=%PATH%;3rdparty\windows\caffe\bin\;3rdparty\windows\opencv\x64\vc15\bin;3rdparty\windows\freeglut\bin\;3rdparty\windows\spinnaker\bin\ + WindowsLocalDebugger + ..\..\.. + + + \ No newline at end of file diff --git a/openpose/cmake/OpenPoseConfig.cmake.in b/openpose/cmake/OpenPoseConfig.cmake.in new file mode 100644 index 0000000000000000000000000000000000000000..7aefa69dd5dc505080306ee56fb838123069bdfa --- /dev/null +++ b/openpose/cmake/OpenPoseConfig.cmake.in @@ -0,0 +1,39 @@ +# Compute and install package configuration and version files +get_filename_component(_dir "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_prefix "${_dir}/../.." ABSOLUTE) + +# Import the targets +include("${_prefix}/lib/OpenPose/OpenPose.cmake") +if (@BUILD_CAFFE@) + set(Caffe_INCLUDE_DIRS "${_prefix}/include/") + # set(Caffe_LIBS "${_prefix}/lib/libcaffe.so") +endif (@BUILD_CAFFE@) + +# Report other information +set(OpenPose_INCLUDE_DIRS "${_prefix}/include/") +set(OpenPose_VERSION_MAJOR @OpenPose_VERSION_MAJOR@) +set(OpenPose_VERSION_MINOR @OpenPose_VERSION_MINOR@) +set(OpenPose_VERSION_PATCH @OpenPose_VERSION_PATCH@) +set(OpenPose_VERSION @OpenPose_VERSION@) + +# Check that the user requested components +# are actually targets that are part of this build +if (OpenPose_FIND_COMPONENTS) + foreach (comp ${OpenPose_FIND_COMPONENTS}) + if (NOT TARGET ${comp}) + set (OpenPose_${comp}_FOUND 0) + if (OpenPose_FIND_REQUIRED_${comp}) + message(FATAL_ERROR "OpenPose ${comp} not available.") + endif (OpenPose_FIND_REQUIRED_${comp}) + else (NOT TARGET ${comp}) + set(OpenPose_${comp}_FOUND 1) + set(OpenPose_LIBS "${comp};${OpenPose_LIBS}") + endif (NOT TARGET ${comp}) + endforeach () +else (OpenPose_FIND_COMPONENTS) + set(OpenPose_LIBS "openpose") +endif (OpenPose_FIND_COMPONENTS) + +if (OpenPose_INCLUDE_DIRS AND OpenPose_LIBS) + set(OpenPose_FOUND 1) +endif (OpenPose_INCLUDE_DIRS AND OpenPose_LIBS) diff --git a/openpose/cmake/OpenPose_CL.vcxproj.user b/openpose/cmake/OpenPose_CL.vcxproj.user new file mode 100644 index 0000000000000000000000000000000000000000..f3d42ebef7879d35512f10eb1c9047a9ffb6b94c --- /dev/null +++ b/openpose/cmake/OpenPose_CL.vcxproj.user @@ -0,0 +1,16 @@ + + + + + PATH=%PATH%;3rdparty\windows\caffe_opencl\bin\;3rdparty\windows\opencv\x64\vc15\bin;3rdparty\windows\freeglut\bin\;3rdparty\windows\spinnaker\bin\ + WindowsLocalDebugger + ..\..\.. + + + + PATH=%PATH%;3rdparty\windows\caffe_opencl\bin\;3rdparty\windows\opencv\x64\vc15\bin;3rdparty\windows\freeglut\bin\;3rdparty\windows\spinnaker\bin\ + WindowsLocalDebugger + ..\..\.. + + + \ No newline at end of file diff --git a/openpose/cmake/OpenPose_CPU.vcxproj.user b/openpose/cmake/OpenPose_CPU.vcxproj.user new file mode 100644 index 0000000000000000000000000000000000000000..1fa5e11c309d8c36718a268fe81bfff24a66160f --- /dev/null +++ b/openpose/cmake/OpenPose_CPU.vcxproj.user @@ -0,0 +1,16 @@ + + + + + PATH=%PATH%;3rdparty\windows\caffe_cpu\bin\;3rdparty\windows\opencv\x64\vc15\bin;3rdparty\windows\freeglut\bin\;3rdparty\windows\spinnaker\bin\ + WindowsLocalDebugger + ..\..\.. + + + + PATH=%PATH%;3rdparty\windows\caffe_cpu\bin\;3rdparty\windows\opencv\x64\vc15\bin;3rdparty\windows\freeglut\bin\;3rdparty\windows\spinnaker\bin\ + WindowsLocalDebugger + ..\..\.. + + + \ No newline at end of file diff --git a/openpose/cmake/Utils.cmake b/openpose/cmake/Utils.cmake new file mode 100644 index 0000000000000000000000000000000000000000..6e8e98c763923634d53e08e88ec6e7a30c3d8f97 --- /dev/null +++ b/openpose/cmake/Utils.cmake @@ -0,0 +1,51 @@ +# Function to download models +function (download_model MODEL_NAME MODEL_DOWNLOAD_FLAG MODEL_RELATIVE_PATH CHECKSUM) + if (MODEL_DOWNLOAD_FLAG) + message(STATUS "Downloading ${MODEL_NAME} model...") + set(MODEL_FILENAME ${CMAKE_SOURCE_DIR}/models/${MODEL_RELATIVE_PATH}) + if (NOT EXISTS ${MODEL_FILENAME}) + message(STATUS "NOTE: This process might take several minutes depending on your internet connection.") + file(DOWNLOAD ${OPENPOSE_URL}${MODEL_RELATIVE_PATH} ${MODEL_FILENAME} + EXPECTED_MD5 ${CHECKSUM}) # SHOW_PROGRESS) + else (NOT EXISTS ${MODEL_FILENAME}) + message(STATUS "Model already exists.") + endif (NOT EXISTS ${MODEL_FILENAME}) + else (MODEL_DOWNLOAD_FLAG) + message(STATUS "Not downloading ${MODEL_NAME} model") + endif (MODEL_DOWNLOAD_FLAG) +endfunction (download_model) + +# Function to download zip files, then extracting them and then deleting them +function(download_zip FILE_NAME URL DOWNLOAD_PATH CHECKSUM) + set(FULL_FILE_PATH "${DOWNLOAD_PATH}/${FILE_NAME}") + if (NOT EXISTS ${FULL_FILE_PATH}) + message(STATUS "Downloading ${URL}/${FILE_NAME}...") + file(DOWNLOAD "${URL}/${FILE_NAME}" "${DOWNLOAD_PATH}/${FILE_NAME}" + EXPECTED_MD5 ${CHECKSUM}) + message(STATUS "Extracting ${FULL_FILE_PATH}...") + execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf ${FILE_NAME} WORKING_DIRECTORY ${DOWNLOAD_PATH}) + else (NOT EXISTS ${FULL_FILE_PATH}) + message(STATUS "${FILE_NAME} already exists.") + endif (NOT EXISTS ${FULL_FILE_PATH}) +endfunction(download_zip) + +# Function to prepend filenames with common path +function(prepend var prefix) + set(listVar "") + foreach (f ${ARGN}) + list(APPEND listVar "${prefix}/${f}") + endforeach (f) + set(${var} "${listVar}" PARENT_SCOPE) +endfunction(prepend) + +# Get names of subdirectories in directory +macro(subdirlist result curdir) + FILE(GLOB children RELATIVE ${curdir} ${curdir}/*) + SET(dirlist "") + foreach (child ${children}) + if (IS_DIRECTORY ${curdir}/${child} AND NOT ${child} STREQUAL "CMakeFiles") + list(APPEND dirlist ${child}) + endif() + endforeach () + set(${result} ${dirlist}) +endmacro() \ No newline at end of file diff --git a/openpose/cmake/cmake_uninstall.cmake.in b/openpose/cmake/cmake_uninstall.cmake.in new file mode 100644 index 0000000000000000000000000000000000000000..d3c8ef8d70f1f49a25895970824091c2048dc2e6 --- /dev/null +++ b/openpose/cmake/cmake_uninstall.cmake.in @@ -0,0 +1,23 @@ +# Reference -- https://cmake.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F +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(IS_SYMLINK "$ENV{DESTDIR}${file}" OR 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(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + message(STATUS "File $ENV{DESTDIR}${file} does not exist.") + endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") +endforeach(file) + diff --git a/openpose/include/openpose/3d/cameraParameterReader.hpp b/openpose/include/openpose/3d/cameraParameterReader.hpp new file mode 100644 index 0000000000000000000000000000000000000000..32d51db862ee8f6ae74ff99dbe0cc41a66eb6f46 --- /dev/null +++ b/openpose/include/openpose/3d/cameraParameterReader.hpp @@ -0,0 +1,63 @@ +#ifndef OPENPOSE_3D_CAMERA_PARAMETER_READER_HPP +#define OPENPOSE_3D_CAMERA_PARAMETER_READER_HPP + +#include + +namespace op +{ + class OP_API CameraParameterReader + { + public: + explicit CameraParameterReader(); + + virtual ~CameraParameterReader(); + + // cameraExtrinsics is optional + explicit CameraParameterReader(const std::string& serialNumber, + const Matrix& cameraIntrinsics, + const Matrix& cameraDistortion, + const Matrix& cameraExtrinsics = Matrix(), + const Matrix& cameraExtrinsicsInitial = Matrix()); + + // serialNumbers is optional. If empty, it will load all the XML files available in the + // cameraParameterPath folder + void readParameters(const std::string& cameraParameterPath, + const std::vector& serialNumbers = {}); + + // It simply calls the previous readParameters with a single element + void readParameters(const std::string& cameraParameterPath, + const std::string& serialNumber); + + void writeParameters(const std::string& cameraParameterPath) const; + + unsigned long long getNumberCameras() const; + + const std::vector& getCameraSerialNumbers() const; + + const std::vector& getCameraMatrices() const; + + const std::vector& getCameraDistortions() const; + + const std::vector& getCameraIntrinsics() const; + + const std::vector& getCameraExtrinsics() const; + + const std::vector& getCameraExtrinsicsInitial() const; + + bool getUndistortImage() const; + + void setUndistortImage(const bool undistortImage); + + void undistort(Matrix& frame, const unsigned int cameraIndex = 0u); + + private: + // PIMPL idiom + // http://www.cppsamples.com/common-tasks/pimpl.html + struct ImplCameraParameterReader; + std::shared_ptr spImpl; + + DELETE_COPY(CameraParameterReader); + }; +} + +#endif // OPENPOSE_3D_CAMERA_PARAMETER_READER_HPP diff --git a/openpose/include/openpose/3d/headers.hpp b/openpose/include/openpose/3d/headers.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ed14f06ef004be4f04577c1f9d23e5c41ed0e6af --- /dev/null +++ b/openpose/include/openpose/3d/headers.hpp @@ -0,0 +1,11 @@ +#ifndef OPENPOSE_3D_HEADERS_HPP +#define OPENPOSE_3D_HEADERS_HPP + +// 3d module +#include +#include +#include +#include +#include + +#endif // OPENPOSE_3D_HEADERS_HPP diff --git a/openpose/include/openpose/3d/jointAngleEstimation.hpp b/openpose/include/openpose/3d/jointAngleEstimation.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f274e8a087884129f3c8210a9f51588e5c5fecd1 --- /dev/null +++ b/openpose/include/openpose/3d/jointAngleEstimation.hpp @@ -0,0 +1,50 @@ +#ifdef USE_3D_ADAM_MODEL +#ifndef OPENPOSE_3D_JOINT_ANGLE_ESTIMATION_HPP +#define OPENPOSE_3D_JOINT_ANGLE_ESTIMATION_HPP + +#ifdef USE_EIGEN + #include +#endif +#ifdef USE_3D_ADAM_MODEL + #include +#endif +#include + +namespace op +{ + OP_API int mapOPToAdam(const int oPPart); + + class OP_API JointAngleEstimation + { + public: + static const std::shared_ptr getTotalModel(); + + JointAngleEstimation(const bool returnJacobian); + + virtual ~JointAngleEstimation(); + + void initializationOnThread(); + + void adamFastFit(Eigen::Matrix& adamPose, + Eigen::Vector3d& adamTranslation, + Eigen::Matrix& vtVec, + Eigen::Matrix& j0Vec, + Eigen::VectorXd& adamFacecoeffsExp, + const Array& poseKeypoints3D, + const Array& faceKeypoints3D, + const std::array, 2>& handKeypoints3D); + + private: + // PIMPL idiom + // http://www.cppsamples.com/common-tasks/pimpl.html + struct ImplJointAngleEstimation; + std::shared_ptr spImpl; + + // PIMP requires DELETE_COPY & destructor, or extra code + // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html + DELETE_COPY(JointAngleEstimation); + }; +} + +#endif // OPENPOSE_3D_JOINT_ANGLE_ESTIMATION_HPP +#endif diff --git a/openpose/include/openpose/3d/poseTriangulation.hpp b/openpose/include/openpose/3d/poseTriangulation.hpp new file mode 100644 index 0000000000000000000000000000000000000000..aa50dce004fbc5c0737de68a60570c6fe6071ab5 --- /dev/null +++ b/openpose/include/openpose/3d/poseTriangulation.hpp @@ -0,0 +1,30 @@ +#ifndef OPENPOSE_3D_POSE_TRIANGULATION_HPP +#define OPENPOSE_3D_POSE_TRIANGULATION_HPP + +#include + +namespace op +{ + class OP_API PoseTriangulation + { + public: + PoseTriangulation(const int minViews3d); + + virtual ~PoseTriangulation(); + + void initializationOnThread(); + + Array reconstructArray( + const std::vector>& keypointsVector, const std::vector& cameraMatrices, + const std::vector>& imageSizes) const; + + std::vector> reconstructArray( + const std::vector>>& keypointsVector, const std::vector& cameraMatrices, + const std::vector>& imageSizes) const; + + private: + const int mMinViews3d; + }; +} + +#endif // OPENPOSE_3D_POSE_TRIANGULATION_HPP diff --git a/openpose/include/openpose/3d/wJointAngleEstimation.hpp b/openpose/include/openpose/3d/wJointAngleEstimation.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5c32a5add2e07bd40012ad555e2906ee54225a9f --- /dev/null +++ b/openpose/include/openpose/3d/wJointAngleEstimation.hpp @@ -0,0 +1,101 @@ +#ifdef USE_3D_ADAM_MODEL +#ifndef OPENPOSE_3D_W_JOINT_ANGLE_ESTIMATION_HPP +#define OPENPOSE_3D_W_JOINT_ANGLE_ESTIMATION_HPP + +#include +#include +#include + +namespace op +{ + template + class WJointAngleEstimation : public Worker + { + public: + explicit WJointAngleEstimation(const std::shared_ptr& jointAngleEstimation); + + virtual ~WJointAngleEstimation(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + const std::shared_ptr spJointAngleEstimation; + + DELETE_COPY(WJointAngleEstimation); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WJointAngleEstimation::WJointAngleEstimation(const std::shared_ptr& jointAngleEstimation) : + spJointAngleEstimation{jointAngleEstimation} + { + } + + template + WJointAngleEstimation::~WJointAngleEstimation() + { + } + + template + void WJointAngleEstimation::initializationOnThread() + { + try + { + spJointAngleEstimation->initializationOnThread(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WJointAngleEstimation::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Input + auto& tDatumPtr = tDatums->at(0); + const auto& poseKeypoints3D = tDatumPtr->poseKeypoints3D; + const auto& faceKeypoints3D = tDatumPtr->faceKeypoints3D; + const auto& handKeypoints3D = tDatumPtr->handKeypoints3D; + // Running Adam model + spJointAngleEstimation->adamFastFit( + tDatumPtr->adamPose, tDatumPtr->adamTranslation, tDatumPtr->vtVec, tDatumPtr->j0Vec, + tDatumPtr->adamFaceCoeffsExp, poseKeypoints3D, faceKeypoints3D, handKeypoints3D); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WJointAngleEstimation); +} + +#endif // OPENPOSE_3D_W_JOINT_ANGLE_ESTIMATION_HPP +#endif diff --git a/openpose/include/openpose/3d/wPoseTriangulation.hpp b/openpose/include/openpose/3d/wPoseTriangulation.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4dca916c1d44501d5257b46f091a704e43550f53 --- /dev/null +++ b/openpose/include/openpose/3d/wPoseTriangulation.hpp @@ -0,0 +1,119 @@ +#ifndef OPENPOSE_3D_W_POSE_TRIANGULATION_HPP +#define OPENPOSE_3D_W_POSE_TRIANGULATION_HPP + +#include +#include +#include + +namespace op +{ + template + class WPoseTriangulation : public Worker + { + public: + explicit WPoseTriangulation(const std::shared_ptr& poseTriangulation); + + virtual ~WPoseTriangulation(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + const std::shared_ptr spPoseTriangulation; + + DELETE_COPY(WPoseTriangulation); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WPoseTriangulation::WPoseTriangulation(const std::shared_ptr& poseTriangulation) : + spPoseTriangulation{poseTriangulation} + { + } + + template + WPoseTriangulation::~WPoseTriangulation() + { + } + + template + void WPoseTriangulation::initializationOnThread() + { + try + { + spPoseTriangulation->initializationOnThread(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WPoseTriangulation::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // 3-D triangulation and reconstruction + std::vector cameraMatrices; + std::vector> poseKeypointVector; + std::vector> faceKeypointVector; + std::vector> leftHandKeypointVector; + std::vector> rightHandKeypointVector; + std::vector> imageSizes; + for (auto& tDatumPtr : *tDatums) + { + poseKeypointVector.emplace_back(tDatumPtr->poseKeypoints); + faceKeypointVector.emplace_back(tDatumPtr->faceKeypoints); + leftHandKeypointVector.emplace_back(tDatumPtr->handKeypoints[0]); + rightHandKeypointVector.emplace_back(tDatumPtr->handKeypoints[1]); + cameraMatrices.emplace_back(tDatumPtr->cameraMatrix); + imageSizes.emplace_back( + Point{tDatumPtr->cvInputData.cols(), tDatumPtr->cvInputData.rows()}); + } + // Pose 3-D reconstruction + auto poseKeypoints3Ds = spPoseTriangulation->reconstructArray( + {poseKeypointVector, faceKeypointVector, leftHandKeypointVector, rightHandKeypointVector}, + cameraMatrices, imageSizes); + // Assign to all tDatums + for (auto& tDatumPtr : *tDatums) + { + tDatumPtr->poseKeypoints3D = poseKeypoints3Ds[0]; + tDatumPtr->faceKeypoints3D = poseKeypoints3Ds[1]; + tDatumPtr->handKeypoints3D[0] = poseKeypoints3Ds[2]; + tDatumPtr->handKeypoints3D[1] = poseKeypoints3Ds[3]; + } + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WPoseTriangulation); +} + +#endif // OPENPOSE_3D_W_POSE_TRIANGULATION_HPP diff --git a/openpose/include/openpose/calibration/cameraParameterEstimation.hpp b/openpose/include/openpose/calibration/cameraParameterEstimation.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c32f4e8859641ccfc4fa25e19815179f3f5cf95e --- /dev/null +++ b/openpose/include/openpose/calibration/cameraParameterEstimation.hpp @@ -0,0 +1,36 @@ +#ifndef OPENPOSE_CALIBRATION_CAMERA_PARAMETER_ESTIMATION_HPP +#define OPENPOSE_CALIBRATION_CAMERA_PARAMETER_ESTIMATION_HPP + +#include + +namespace op +{ + /** + * This function estimate and saves the intrinsic parameters (K and distortion coefficients). + * @param gridInnerCorners The Point of the board, i.e., the number of squares by width and height + * @param gridSquareSizeMm Floating number with the size of a square in your defined unit (point, millimeter,etc). + * @param flags Integer with the OpenCV flags for calibration (e.g., CALIB_RATIONAL_MODEL, + * CALIB_THIN_PRISM_MODEL, or CALIB_TILTED_MODEL) + * @param outputFilePath String with the name of the file where to write + */ + OP_API void estimateAndSaveIntrinsics( + const Point& gridInnerCorners, const float gridSquareSizeMm, const int flags, + const std::string& outputParameterFolder, const std::string& imageFolder, const std::string& serialNumber, + const bool saveImagesWithCorners = false); + + OP_API void estimateAndSaveExtrinsics( + const std::string& parameterFolder, const std::string& imageFolder, const Point& gridInnerCorners, + const float gridSquareSizeMm, const int index0, const int index1, const bool imagesAreUndistorted, + const bool combineCam0Extrinsics); + + OP_API void refineAndSaveExtrinsics( + const std::string& parameterFolder, const std::string& imageFolder, const Point& gridInnerCorners, + const float gridSquareSizeMm, const int numberCameras, const bool imagesAreUndistorted, + const bool saveImagesWithCorners = false); + + OP_API void estimateAndSaveSiftFile( + const Point& gridInnerCorners, const std::string& imageFolder, const int numberCameras, + const bool saveImagesWithCorners = false); +} + +#endif // OPENPOSE_CALIBRATION_CAMERA_PARAMETER_ESTIMATION_HPP diff --git a/openpose/include/openpose/calibration/headers.hpp b/openpose/include/openpose/calibration/headers.hpp new file mode 100644 index 0000000000000000000000000000000000000000..55d0cc50c138b8aa4816df49bf9ca43c0cced57e --- /dev/null +++ b/openpose/include/openpose/calibration/headers.hpp @@ -0,0 +1,7 @@ +#ifndef OPENPOSE_CALIBRATION_HEADERS_HPP +#define OPENPOSE_CALIBRATION_HEADERS_HPP + +// calibration module +#include + +#endif // OPENPOSE_CALIBRATION_HEADERS_HPP diff --git a/openpose/include/openpose/core/array.hpp b/openpose/include/openpose/core/array.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7e0b707c008c73a69d82156d249dff8d094af3c1 --- /dev/null +++ b/openpose/include/openpose/core/array.hpp @@ -0,0 +1,516 @@ +#ifndef OPENPOSE_CORE_ARRAY_HPP +#define OPENPOSE_CORE_ARRAY_HPP + +#include // std::shared_ptr +#include +#include +#include +#include + +namespace op +{ + /** + * Array: The OpenPose Basic Raw Data Container + * This template class implements a multidimensional data array. It is our basic data container, analogous to + * Mat in OpenCV, Tensor in Torch/TensorFlow or Blob in Caffe. + * It wraps a Matrix and a std::shared_ptr, both of them pointing to the same raw data. I.e. they both share the + * same memory, so we can read and modify this data in both formats with no performance impact. + * Hence, it keeps high performance while adding high-level functions. + */ + template + class Array + { + public: + // ------------------------------ Constructors and Data Allocator Functions ------------------------------ // + /** + * Array constructor. + * Equivalent to default constructor + reset(const int size). + * @param size Integer with the number of T element to be allocated. E.g., size = 5 is internally similar to + * `new T[5]`. + */ + explicit Array(const int size); + + /** + * Array constructor. + * Equivalent to default constructor + reset(const std::vector& size = {}). + * @param sizes Vector with the size of each dimension. E.g., size = {3, 5, 2} is internally similar to + * `new T[3*5*2]`. + */ + explicit Array(const std::vector& sizes = {}); + + /** + * Array constructor. + * Equivalent to default constructor + reset(const int size, const T value). + * @param size Integer with the number of T element to be allocated. E.g., size = 5 is internally similar to + * `new T[5]`. + * @param value Initial value for each component of the Array. + */ + Array(const int size, const T value); + + /** + * Array constructor. + * Equivalent to default constructor + reset(const std::vector& size, const T value). + * @param sizes Vector with the size of each dimension. E.g., size = {3, 5, 2} is internally similar to: + * `new T[3*5*2]`. + * @param value Initial value for each component of the Array. + */ + Array(const std::vector& sizes, const T value); + + /** + * Array constructor. + * Equivalent to default constructor, but it does not allocate memory, but rather use dataPtr. + * @param size Integer with the number of T element to be allocated. E.g., size = 5 is internally similar to + * `new T[5]`. + * @param dataPtr Pointer to the memory to be used by the Array. + */ + Array(const int size, T* const dataPtr); + + /** + * Array constructor. + * Equivalent to default constructor, but it does not allocate memory, but rather use dataPtr. + * @param sizes Vector with the size of each dimension. E.g., size = {3, 5, 2} is internally similar to: + * `new T[3*5*2]`. + * @param dataPtr Pointer to the memory to be used by the Array. + */ + Array(const std::vector& sizes, T* const dataPtr); + + /** + * Array constructor. + * @param array Array with the original data array to slice. + * @param index indicates the index of the array to extract. + * @param noCopy indicates whether to perform a copy. Copy will never go to undefined behavior, however, if + * noCopy == true, then: + * 1. It is faster, as no data copy is involved, but... + * 2. If the Array array goes out of scope, then the resulting Array will provoke an undefined behavior. + * 3. If the returned Array is modified, the information in the Array array will also be. + * @return Array with the same dimension than array expect the first dimension being 1. E.g., if array + * is {p,k,m}, the resulting Array is {1,k,m}. + */ + Array(const Array& array, const int index, const bool noCopy = false); + + /** + * Array constructor. It manually copies the Array into the new Array + * @param array Array with a format T2 different to the current Array type T. + */ + template + Array(const Array& array) : + Array{array.getSize()} + { + try + { + // Copy + for (auto i = 0u ; i < array.getVolume() ; i++) + pData[i] = T(array[i]); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + /** + * Copy constructor. + * It performs `fast copy`: For performance purpose, copying a Array or Datum or cv::Mat just copies the + * reference, it still shares the same internal data. + * Modifying the copied element will modify the original one. + * Use clone() for a slower but real copy, similarly to cv::Mat and Array. + * @param array Array to be copied. + */ + Array(const Array& array); + + /** + * Copy assignment. + * Similar to Array(const Array& array). + * @param array Array to be copied. + * @return The resulting Array. + */ + Array& operator=(const Array& array); + + /** + * Move constructor. + * It destroys the original Array to be moved. + * @param array Array to be moved. + */ + Array(Array&& array); + + /** + * Move assignment. + * Similar to Array(Array&& array). + * @param array Array to be moved. + * @return The resulting Array. + */ + Array& operator=(Array&& array); + + /** + * Clone function. + * Similar to cv::Mat::clone and Datum::clone. + * It performs a real but slow copy of the data, i.e., even if the copied element is modified, the original + * one is not. + * @return The resulting Array. + */ + Array clone() const; + + /** + * Data allocation function. + * It allocates the required space for the memory (it does not initialize that memory). + * @param size Integer with the number of T element to be allocated. E.g., size = 5 is internally similar to + * `new T[5]`. + */ + void reset(const int size); + + /** + * Data allocation function. + * Similar to reset(const int size), but it allocates a multi-dimensional array of dimensions each of the + * values of the argument. + * @param sizes Vector with the size of each dimension. E.g., size = {3, 5, 2} is internally similar to + * `new T[3*5*2]`. + */ + void reset(const std::vector& sizes = {}); + + /** + * Data allocation function. + * Similar to reset(const int size), but initializing the data to the value specified by the second argument. + * @param size Integer with the number of T element to be allocated. E.g., size = 5 is internally similar to + * `new T[5]`. + * @param value Initial value for each component of the Array. + */ + void reset(const int size, const T value); + + /** + * Data allocation function. + * Similar to reset(const std::vector& size), but initializing the data to the value specified by the + * second argument. + * @param sizes Vector with the size of each dimension. E.g., size = {3, 5, 2} is internally similar to + * `new T[3*5*2]`. + * @param value Initial value for each component of the Array. + */ + void reset(const std::vector& sizes, const T value); + + /** + * Data allocation function. + * Equivalent to default constructor, but it does not allocate memory, but rather use dataPtr. + * @param size Integer with the number of T element to be allocated. E.g., size = 5 is internally similar to + * `new T[5]`. + * @param dataPtr Pointer to the memory to be used by the Array. + */ + void reset(const int size, T* const dataPtr); + + /** + * Data allocation function. + * Equivalent to default constructor, but it does not allocate memory, but rather use dataPtr. + * @param sizes Vector with the size of each dimension. E.g., size = {3, 5, 2} is internally similar to: + * `new T[3*5*2]`. + * @param dataPtr Pointer to the memory to be used by the Array. + */ + void reset(const std::vector& sizes, T* const dataPtr); + + /** + * Data allocation function. + * It internally allocates memory and copies the data of the argument to the Array allocated memory. + * @param cvMat Matrix to be copied. + */ + void setFrom(const Matrix& cvMat); + + /** + * Data allocation function. + * It internally assigns all the allocated memory to the value indicated by the argument. + * @param value Value for each component of the Array. + */ + void setTo(const T value); + + + + // ------------------------------ Data Information Functions ------------------------------ // + /** + * Check whether memory has been allocated. + * @return True if no memory has been allocated, false otherwise. + */ + inline bool empty() const + { + return (mVolume == 0); + } + + /** + * Return a vector with the size of each dimension allocated. + * @return A std::vector with the size of each dimension. If no memory has been allocated, it will return + * an empty std::vector. + */ + inline std::vector getSize() const + { + return mSize; + } + + /** + * Return a vector with the size of the desired dimension. + * @param index Dimension to check its size. + * @return Size of the desired dimension. It will return 0 if the requested dimension is higher than the number + * of dimensions. + */ + int getSize(const int index) const; + + /** + * Return a string with the size of each dimension allocated. + * @return A std::stringwith the size of each dimension. If no memory has been allocated, it will return an + * empty string. + */ + std::string printSize() const; + + /** + * Return the total number of dimensions, equivalent to getSize().size(). + * @return The number of dimensions. If no memory is allocated, it returns 0. + */ + inline size_t getNumberDimensions() const + { + return mSize.size(); + } + + /** + * Return the total number of elements allocated, equivalent to multiply all the components from getSize(). + * E.g., for a Array of size = {2,5,3}, the volume or total number of elements is: 2x5x3 = 30. + * @return The total volume of the allocated data. If no memory is allocated, it returns 0. + */ + inline size_t getVolume() const + { + return mVolume; + } + + /** + * Similar to getVolume(), but in this case it just returns the volume between the desired dimensions. + * E.g., for a Array of size = {2,5,3}, the volume or total number of elements for getVolume(1,2) is + * 5x3 = 15. + * @param indexA Dimension where to start. + * @param indexB Dimension where to stop. If indexB == -1, then it will take up to the last dimension. + * @return The total volume of the allocated data between the desired dimensions. If the index are out of + * bounds, it throws an error. + */ + size_t getVolume(const int indexA, const int indexB = -1) const; + + /** + * Return the stride or step size of the array. + * E.g., given and Array of size 5x3, getStride() would return the following vector: + * {5x3sizeof(T), 3sizeof(T), sizeof(T)}. + */ + std::vector getStride() const; + + /** + * Return the stride or step size of the array at the index-th dimension. + * E.g., given and Array of size 5x3, getStride(2) would return sizeof(T). + */ + int getStride(const int index) const; + + + + // ------------------------------ Data Access Functions And Operators ------------------------------ // + /** + * Return a raw pointer to the data. Similar to: std::shared_ptr::get(). + * Note: if you modify the pointer data, you will directly modify it in the Array instance too. + * If you know you do not want to modify the data, then use getConstPtr() instead. + * @return A raw pointer to the data. + */ + inline T* getPtr() + { + return pData; // spData.get() + } + + /** + * Similar to getPtr(), but it forbids the data to be edited. + * @return A raw const pointer to the data. + */ + inline const T* getConstPtr() const + { + return pData; // spData.get() + } + + /** + * Similar to getConstPtr(), but it allows the data to be edited. + * This function is only implemented for Pybind11 usage. + * @return A raw pointer to the data. + */ + inline T* getPseudoConstPtr() const + { + return pData; // spData.get() + } + + /** + * Return a Matrix wrapper to the data. It forbids the data to be modified. + * OpenCV only admits unsigned char, signed char, int, float & double. If the T class is not supported by + * OpenCV, it will throw an error. + * Note: Array does not return an editable Matrix because some OpenCV functions reallocate memory and it + * would not longer point to the Array instance. + * If you want to perform some OpenCV operation on the Array data, you can use: + * editedCvMat = array.getConstCvMat().clone(); + * // modify data + * array.setFrom(editedCvMat) + * @return A const Matrix pointing to the data. + */ + const Matrix& getConstCvMat() const; + + /** + * Analogous to getConstCvMat, but in this case it returns a editable Matrix. + * Very important: Only allowed functions which do not provoke data reallocation. + * E.g., resizing functions will not work and they would provoke an undefined behavior and/or execution + * crashes. + * @return A Matrix pointing to the data. + */ + Matrix& getCvMat(); + + /** + * [] operator + * Similar to the [] operator for raw pointer data. + * If debug mode is enabled, then it will check that the desired index is in the data range, and it will throw + * an exception otherwise (similar to the at operator). + * @param index The desired memory location. + * @return A editable reference to the data on the desired index location. + */ + inline T& operator[](const int index) + { + #ifdef NDEBUG + return pData[index]; // spData.get()[index] + #else + return at(index); + #endif + } + + /** + * [] operator + * Same functionality as operator[](const int index), but it forbids modifying the value. Otherwise, const + * functions would not be able to call the [] operator. + * @param index The desired memory location. + * @return A non-editable reference to the data on the desired index location. + */ + inline const T& operator[](const int index) const + { + #ifdef NDEBUG + return pData[index]; // spData.get()[index] + #else + return at(index); + #endif + } + + /** + * [] operator + * Same functionality as operator[](const int index), but it lets the user introduce the multi-dimensional + * index. + * E.g., given a (10 x 10 x 10) array, array[11] is equivalent to array[{1,1,0}] + * @param indexes Vector with the desired memory location. + * @return A editable reference to the data on the desired index location. + */ + inline T& operator[](const std::vector& indexes) + { + return operator[](getIndex(indexes)); + } + + /** + * [] operator + * Same functionality as operator[](const std::vector& indexes), but it forbids modifying the value. + * Otherwise, const functions would not be able to call the [] operator. + * @param indexes Vector with the desired memory location. + * @return A non-editable reference to the data on the desired index location. + */ + inline const T& operator[](const std::vector& indexes) const + { + return operator[](getIndex(indexes)); + } + + /** + * at() function + * Same functionality as operator[](const int index), but it always check whether the indexes are within the + * data bounds. Otherwise, it will throw an error. + * @param index The desired memory location. + * @return A editable reference to the data on the desired index location. + */ + inline T& at(const int index) + { + return commonAt(index); + } + + /** + * at() function + * Same functionality as operator[](const int index) const, but it always check whether the indexes are within + * the data bounds. Otherwise, it will throw an error. + * @param index The desired memory location. + * @return A non-editable reference to the data on the desired index location. + */ + inline const T& at(const int index) const + { + return commonAt(index); + } + + /** + * at() function + * Same functionality as operator[](const std::vector& indexes), but it always check whether the indexes + * are within the data bounds. Otherwise, it will throw an error. + * @param indexes Vector with the desired memory location. + * @return A editable reference to the data on the desired index location. + */ + inline T& at(const std::vector& indexes) + { + return at(getIndexAndCheck(indexes)); + } + + /** + * at() function + * Same functionality as operator[](const std::vector& indexes) const, but it always check whether the + * indexes are within the data bounds. Otherwise, it will throw an error. + * @param indexes Vector with the desired memory location. + * @return A non-editable reference to the data on the desired index location. + */ + inline const T& at(const std::vector& indexes) const + { + return at(getIndexAndCheck(indexes)); + } + + /** + * It returns a string with the whole array data. Useful for debugging. + * The format is: values separated by a space, and a enter for each dimension. E.g., + * For the Array{2, 2, 3}, it will print: + * Array::toString(): + * x1 x2 x3 + * x4 x5 x6 + * + * x7 x8 x9 + * x10 x11 x12 + * @return A string with the array values in the above format. + */ + const std::string toString() const; + + private: + std::vector mSize; + size_t mVolume; + std::shared_ptr spData; + T* pData; // pData is a wrapper of spData. Used for Pybind11 binding. + std::pair mCvMatData; + + /** + * Auxiliary function that both operator[](const std::vector& indexes) and + * operator[](const std::vector& indexes) const use. + * It turn the multi-dimensions indexes into the 1-dimension equivalent index. + * @param indexes Vector with the desired memory location. + * @return The equivalent 1-D index. + */ + int getIndex(const std::vector& indexes) const; + + /** + * Similar to getIndex(const std::vector& indexes) const, but used for at(const std::vector& indexes) + * and at(const std::vector& indexes) const. + * It also checks whether the index is within the allocated memory. + * @param indexes Vector with the desired memory location. + * @return The equivalent 1-D index. + */ + int getIndexAndCheck(const std::vector& indexes) const; + + /** + * Auxiliary function that both at(const int index) and at(const int index) const use. + * @param index The desired memory location. + * @return A non-editable reference to the data on the desired index location. + */ + T& commonAt(const int index) const; + + void resetAuxiliary(const std::vector& sizes, T* const dataPtr = nullptr); + }; + + // Static methods + OVERLOAD_C_OUT(Array) +} + +#endif // OPENPOSE_CORE_ARRAY_HPP diff --git a/openpose/include/openpose/core/arrayCpuGpu.hpp b/openpose/include/openpose/core/arrayCpuGpu.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ed6451be578238b4bd876560324d7c76b848a490 --- /dev/null +++ b/openpose/include/openpose/core/arrayCpuGpu.hpp @@ -0,0 +1,112 @@ +#ifndef OPENPOSE_CORE_ARRAY_CPU_GPU_HPP +#define OPENPOSE_CORE_ARRAY_CPU_GPU_HPP + +#include // std::shared_ptr +#include +#include +#include + +namespace op +{ + /** + * ArrayCpuGpu: Bind of caffe::Blob to avoid Caffe as dependency in the headers. + */ + template + class ArrayCpuGpu + { + public: + ArrayCpuGpu(); + /** + * @param caffeBlobTPtr should be a caffe::Blob* element or it will provoke a core dumped. Done to + * avoid explicitly exposing 3rdparty libraries on the headers. + */ + explicit ArrayCpuGpu(const void* caffeBlobTPtr); + /** + * Create an ArrayCpuGpu from the data in the Array element (it will automatically copy that data). + * @param array Array where the data to be copied is. + * @param copyFromGpu If false (default), it will copy the data to the CPU. If true, it will copy it to the + * GPU memory (using CUDA copy function). + */ + explicit ArrayCpuGpu(const Array& array, const bool copyFromGpu); + explicit ArrayCpuGpu(const int num, const int channels, const int height, const int width); + // explicit ArrayCpuGpu(const std::vector& shape); + + void Reshape(const int num, const int channels, const int height, const int width); + void Reshape(const std::vector& shape); + // // void Reshape(const BlobShape& shape); + // // void ReshapeLike(const Blob& other); + // void ReshapeLike(const ArrayCpuGpu& other); + std::string shape_string() const; + const std::vector& shape() const; + int shape(const int index) const; + int num_axes() const; + int count() const; + int count(const int start_axis, const int end_axis) const; + int count(const int start_axis) const; + + int CanonicalAxisIndex(const int axis_index) const; + + int num() const; + int channels() const; + int height() const; + int width() const; + int LegacyShape(const int index) const; + + int offset(const int n, const int c = 0, const int h = 0, const int w = 0) const; + // int offset(const std::vector& indices) const; // Caffe warning + + // // void CopyFrom(const Blob& source, bool copy_diff = false, bool reshape = false); + // void CopyFrom(const ArrayCpuGpu& source, bool copy_diff = false, bool reshape = false); + + T data_at(const int n, const int c, const int h, const int w) const; + T diff_at(const int n, const int c, const int h, const int w) const; + // T data_at(const std::vector& index) const; // Caffe warning + // T diff_at(const std::vector& index) const; // Caffe warning + + // const boost::shared_ptr& data() const; + // const boost::shared_ptr& diff() const; + + const T* cpu_data() const; + void set_cpu_data(T* data); + const int* gpu_shape() const; + const T* gpu_data() const; + void set_gpu_data(T* data); + const T* cpu_diff() const; + const T* gpu_diff() const; + T* mutable_cpu_data(); + T* mutable_gpu_data(); + T* mutable_cpu_diff(); + T* mutable_gpu_diff(); + void Update(); + // void FromProto(const BlobProto& proto, bool reshape = true); + // void ToProto(BlobProto* proto, bool write_diff = false) const; + + T asum_data() const; + T asum_diff() const; + T sumsq_data() const; + T sumsq_diff() const; + + void scale_data(const T scale_factor); + void scale_diff(const T scale_factor); + + // void ShareData(const Blob& other); + // void ShareDiff(const Blob& other); + + // bool ShapeEquals(const BlobProto& other); + + private: + // PIMPL idiom + // http://www.cppsamples.com/common-tasks/pimpl.html + struct ImplArrayCpuGpu; + std::shared_ptr spImpl; + + // PIMP requires DELETE_COPY & destructor, or extra code + // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html + DELETE_COPY(ArrayCpuGpu); + }; + + // // Static methods + // OVERLOAD_C_OUT(ArrayCpuGpu) +} + +#endif // OPENPOSE_CORE_ARRAY_CPU_GPU_HPP diff --git a/openpose/include/openpose/core/common.hpp b/openpose/include/openpose/core/common.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6b30d99dc7c2b7eda99d2008aacb997e0fd870b4 --- /dev/null +++ b/openpose/include/openpose/core/common.hpp @@ -0,0 +1,22 @@ +#ifndef OPENPOSE_CORE_COMMON_HPP +#define OPENPOSE_CORE_COMMON_HPP + +// Std library most used classes +#include +#include // std::shared_ptr, std::unique_ptr +#include +#include +// OpenPose most used classes +#include +#include +#include +#include +#include +#include +#include +#include +#include +// Datum at the end, otherwise circular dependency with array, point & rectangle +#include + +#endif // OPENPOSE_CORE_COMMON_HPP diff --git a/openpose/include/openpose/core/cvMatToOpInput.hpp b/openpose/include/openpose/core/cvMatToOpInput.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7480051ec64e9df40689e096b0b14ffaa6688d45 --- /dev/null +++ b/openpose/include/openpose/core/cvMatToOpInput.hpp @@ -0,0 +1,31 @@ +#ifndef OPENPOSE_CORE_CV_MAT_TO_OP_INPUT_HPP +#define OPENPOSE_CORE_CV_MAT_TO_OP_INPUT_HPP + +#include +#include + +namespace op +{ + class OP_API CvMatToOpInput + { + public: + CvMatToOpInput(const PoseModel poseModel = PoseModel::BODY_25, const bool gpuResize = false); + + virtual ~CvMatToOpInput(); + + std::vector> createArray( + const Matrix& inputData, const std::vector& scaleInputToNetInputs, + const std::vector>& netInputSizes); + + private: + const PoseModel mPoseModel; + const bool mGpuResize; + unsigned char* pInputImageCuda; + float* pInputImageReorderedCuda; + float* pOutputImageCuda; + unsigned long long pInputMaxSize; + unsigned long long pOutputMaxSize; + }; +} + +#endif // OPENPOSE_CORE_CV_MAT_TO_OP_INPUT_HPP diff --git a/openpose/include/openpose/core/cvMatToOpOutput.hpp b/openpose/include/openpose/core/cvMatToOpOutput.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0644d74a7acd9e6bc98d714c2cb7e6e9c0d85924 --- /dev/null +++ b/openpose/include/openpose/core/cvMatToOpOutput.hpp @@ -0,0 +1,31 @@ +#ifndef OPENPOSE_CORE_CV_MAT_TO_OP_OUTPUT_HPP +#define OPENPOSE_CORE_CV_MAT_TO_OP_OUTPUT_HPP + +#include + +namespace op +{ + class OP_API CvMatToOpOutput + { + public: + CvMatToOpOutput(const bool gpuResize = false); + + virtual ~CvMatToOpOutput(); + + std::tuple, std::shared_ptr, std::shared_ptr> + getSharedParameters(); + + Array createArray( + const Matrix& inputData, const double scaleInputToOutput, const Point& outputResolution); + + private: + const bool mGpuResize; + unsigned char* pInputImageCuda; + std::shared_ptr spOutputImageCuda; + unsigned long long pInputMaxSize; + std::shared_ptr spOutputMaxSize; + std::shared_ptr spGpuMemoryAllocated; + }; +} + +#endif // OPENPOSE_CORE_CV_MAT_TO_OP_OUTPUT_HPP diff --git a/openpose/include/openpose/core/datum.hpp b/openpose/include/openpose/core/datum.hpp new file mode 100644 index 0000000000000000000000000000000000000000..da93c6941fd4f3d0c890898672d2c430c85c0d46 --- /dev/null +++ b/openpose/include/openpose/core/datum.hpp @@ -0,0 +1,410 @@ +#ifndef OPENPOSE_CORE_DATUM_HPP +#define OPENPOSE_CORE_DATUM_HPP + +#ifdef USE_3D_ADAM_MODEL + #ifdef USE_EIGEN + #include + #endif +#endif +#include + +namespace op +{ + /** + * Datum: The OpenPose Basic Piece of Information Between Threads + * Datum is one the main OpenPose classes/structs. The workers and threads share by default a + * std::shared_ptr>. It contains all the parameters that the different workers and threads need + * to exchange. + */ + struct OP_API Datum + { + // ---------------------------------------- ID parameters ---------------------------------------- // + unsigned long long id; /**< Datum ID. Internally used to sort the Datums if multi-threading is used. */ + + unsigned long long subId; /**< Datum sub-ID. Internally used to sort the Datums if multi-threading is used. */ + + unsigned long long subIdMax; /**< Datum maximum sub-ID. Used to sort the Datums if multi-threading is used. */ + + /** + * Name used when saving the data to disk (e.g., `write_images` or `write_keypoint` flags in the demo). + */ + std::string name; + + /** + * Corresponding frame number. + * If the producer (e.g., video) starts from frame 0 and does not repeat any frame, then frameNumber should + * match the field id. + */ + unsigned long long frameNumber; + + // ------------------------------ Input image and rendered version parameters ------------------------------ // + /** + * Original image to be processed in cv::Mat uchar format. + * Size: (input_width x input_height) x 3 channels + */ + Matrix cvInputData; + + /** + * Original image to be processed in Array format. + * It has been resized to the net input resolution, as well as reformatted Array format to be compatible + * with the net. + * If >1 scales, each scale is right- and bottom-padded to fill the greatest resolution. The + * scales are sorted from bigger to smaller. + * Vector size: #scales + * Each array size: 3 x input_net_height x input_net_width + */ + std::vector> inputNetData; + + /** + * Rendered image in Array format. + * It consists of a blending of the cvInputData and the pose/body part(s) heatmap/PAF(s). + * If rendering is disabled (e.g., `no_render_pose` flag in the demo), outputData will be empty. + * Size: 3 x output_net_height x output_net_width + */ + Array outputData; + + /** + * Rendered image in cv::Mat uchar format. + * It has been resized to the desired output resolution (e.g., `resolution` flag in the demo). + * If outputData is empty, cvOutputData will also be empty. + * Size: (output_height x output_width) x 3 channels + */ + Matrix cvOutputData; + + /** + * Rendered 3D image in cv::Mat uchar format. + */ + Matrix cvOutputData3D; + + // ------------------------------ Resulting Array data parameters ------------------------------ // + /** + * Body pose (x,y,score) locations for each person in the image. + * It has been resized to the desired output resolution (e.g., `resolution` flag in the demo). + * Size: #people x #body parts (e.g., 18 for COCO or 15 for MPI) x 3 ((x,y) coordinates + score) + */ + Array poseKeypoints; + + /** + * People ID + * It returns a person ID for each body pose, providing temporal consistency. The ID will be the same one + * for a person across frames. I.e. this ID allows to keep track of the same person in time. + * If either person identification is disabled or poseKeypoints is empty, poseIds will also be empty. + * Size: #people + */ + Array poseIds; + + /** + * Body pose global confidence/score for each person in the image. + * It does not only consider the score of each body keypoint, but also the score of each PAF association. + * Optimized for COCO evaluation metric. + * It will highly penalyze people with missing body parts (e.g., cropped people on the borders of the image). + * If poseKeypoints is empty, poseScores will also be empty. + * Size: #people + */ + Array poseScores; + + /** + * Body pose heatmaps (body parts, background and/or PAFs) for the whole image. + * This parameter is by default empty and disabled for performance. Each group (body parts, background and + * PAFs) can be individually enabled. + * #heatmaps = #body parts (if enabled) + 1 (if background enabled) + 2 x #PAFs (if enabled). Each PAF has 2 + * consecutive channels, one for x- and one for y-coordinates. + * Order heatmaps: body parts + background (as appears in POSE_BODY_PART_MAPPING) + (x,y) channel of each PAF + * (sorted as appears in POSE_BODY_PART_PAIRS). See `pose/poseParameters.hpp`. + * The user can choose the heatmaps normalization: ranges [0, 1], [-1, 1] or [0, 255]. Check the + * `heatmaps_scale` flag in {OpenPose_path}/doc/advanced/demo_advanced.md for more details. + * Size: #heatmaps x output_net_height x output_net_width + */ + Array poseHeatMaps; + + /** + * Body pose candidates for the whole image. + * This parameter is by default empty and disabled for performance. It can be enabled with `candidates_body`. + * Candidates refer to all the detected body parts, before being assembled into people. Note that the number + * of candidates is equal or higher than the number of body parts after being assembled into people. + * Size: #body parts x min(part candidates, POSE_MAX_PEOPLE) x 3 (x,y,score). + * Rather than vector, it should ideally be: + * std::array>, #BP> poseCandidates; + */ + std::vector>> poseCandidates; + + /** + * Face detection locations (x,y,width,height) for each person in the image. + * It is resized to cvInputData.size(). + * Size: #people + */ + std::vector> faceRectangles; + + /** + * Face keypoints (x,y,score) locations for each person in the image. + * It has been resized to the same resolution as `poseKeypoints`. + * Size: #people x #face parts (70) x 3 ((x,y) coordinates + score) + */ + Array faceKeypoints; + + /** + * Face pose heatmaps (face parts and/or background) for the whole image. + * Analogous of bodyHeatMaps applied to face. However, there is no PAFs and the size is different. + * Size: #people x #face parts (70) x output_net_height x output_net_width + */ + Array faceHeatMaps; + + /** + * Hand detection locations (x,y,width,height) for each person in the image. + * It is resized to cvInputData.size(). + * Size: #people + */ + std::vector, 2>> handRectangles; + + /** + * Hand keypoints (x,y,score) locations for each person in the image. + * It has been resized to the same resolution as `poseKeypoints`. + * handKeypoints[0] corresponds to left hands, and handKeypoints[1] to right ones. + * Size each Array: #people x #hand parts (21) x 3 ((x,y) coordinates + score) + */ + std::array, 2> handKeypoints; + + /** + * Hand pose heatmaps (hand parts and/or background) for the whole image. + * Analogous of faceHeatMaps applied to face. + * Size each Array: #people x #hand parts (21) x output_net_height x output_net_width + */ + std::array, 2> handHeatMaps; + + // ---------------------------------------- 3-D Reconstruction parameters ---------------------------------------- // + /** + * Body pose (x,y,z,score) locations for each person in the image. + * Size: #people x #body parts (e.g., 18 for COCO or 15 for MPI) x 4 ((x,y,z) coordinates + score) + */ + Array poseKeypoints3D; + + /** + * Face keypoints (x,y,z,score) locations for each person in the image. + * It has been resized to the same resolution as `poseKeypoints3D`. + * Size: #people x #face parts (70) x 4 ((x,y,z) coordinates + score) + */ + Array faceKeypoints3D; + + /** + * Hand keypoints (x,y,z,score) locations for each person in the image. + * It has been resized to the same resolution as `poseKeypoints3D`. + * handKeypoints[0] corresponds to left hands, and handKeypoints[1] to right ones. + * Size each Array: #people x #hand parts (21) x 4 ((x,y,z) coordinates + score) + */ + std::array, 2> handKeypoints3D; + + /** + * 3x4 camera matrix of the camera (equivalent to cameraIntrinsics * cameraExtrinsics). + */ + Matrix cameraMatrix; + + /** + * 3x4 extrinsic parameters of the camera. + */ + Matrix cameraExtrinsics; + + /** + * 3x3 intrinsic parameters of the camera. + */ + Matrix cameraIntrinsics; + + /** + * If it is not empty, OpenPose will not run its internal body pose estimation network and will instead use + * this data as the substitute of its network. The size of this element must match the size of the output of + * its internal network, or it will lead to core dumped (segmentation) errors. You can modify the pose + * estimation flags to match the dimension of both elements (e.g., `--net_resolution`, `--scale_number`, etc.). + */ + Array poseNetOutput; + + // ---------------------------------------- Other (internal) parameters ---------------------------------------- // + /** + * Scale ratio between the input Datum::cvInputData and the net input size. + */ + std::vector scaleInputToNetInputs; + + /** + * Size(s) (width x height) of the image(s) fed to the pose deep net. + * The size of the std::vector corresponds to the number of scales. + */ + std::vector> netInputSizes; + + /** + * Scale ratio between the input Datum::cvInputData and the output Datum::cvOutputData. + */ + double scaleInputToOutput; + + /** + * Size (width x height) of the image returned by the deep net. + */ + Point netOutputSize; + + /** + * Scale ratio between the net output and the final output Datum::cvOutputData. + */ + double scaleNetToOutput; + + /** + * Pair with the element key id POSE_BODY_PART_MAPPING on `pose/poseParameters.hpp` and its mapped value (e.g. + * 1 and "Neck"). + */ + std::pair elementRendered; + + // 3D/Adam parameters (experimental code not meant to be publicly used) + #ifdef USE_3D_ADAM_MODEL + // Adam/Unity params + std::vector adamPosePtr; + int adamPoseRows; + std::vector adamTranslationPtr; + std::vector vtVecPtr; + int vtVecRows; + std::vector j0VecPtr; + int j0VecRows; + std::vector adamFaceCoeffsExpPtr; + int adamFaceCoeffsExpRows; + #ifdef USE_EIGEN + // Adam/Unity params + Eigen::Matrix adamPose; + Eigen::Vector3d adamTranslation; + // Adam params (Jacobians) + Eigen::Matrix vtVec; + Eigen::Matrix j0Vec; + Eigen::VectorXd adamFaceCoeffsExp; + #endif + #endif + + + + + + // ---------------------------------------- Functions ---------------------------------------- // + /** + * Default constructor struct. + * It simply initializes the struct, id is temporary set to 0 and each other variable is assigned to its + * default value. + */ + explicit Datum(); + + /** + * Copy constructor. + * It performs `fast copy`: For performance purpose, copying a Datum or Array or cv::Mat just copies the + * reference, it still shares the same internal data. + * Modifying the copied element will modify the original one. + * Use clone() for a slower but real copy, similarly to cv::Mat and Array. + * @param datum Datum to be copied. + */ + Datum(const Datum& datum); + + /** + * Copy assignment. + * Similar to Datum::Datum(const Datum& datum). + * @param datum Datum to be copied. + * @return The resulting Datum. + */ + Datum& operator=(const Datum& datum); + + /** + * Move constructor. + * It destroys the original Datum to be moved. + * @param datum Datum to be moved. + */ + Datum(Datum&& datum); + + /** + * Move assignment. + * Similar to Datum::Datum(Datum&& datum). + * @param datum Datum to be moved. + * @return The resulting Datum. + */ + Datum& operator=(Datum&& datum); + + /** + * Destructor class. + * Declared virtual so that Datum can be inherited. + */ + virtual ~Datum(); + + /** + * Clone function. + * Similar to cv::Mat::clone and Array::clone. + * It performs a real but slow copy of the data, i.e., even if the copied element is modified, the original + * one is not. + * @return The resulting Datum. + */ + Datum clone() const; + + + + + + // ---------------------------------------- Comparison operators ---------------------------------------- // + /** + * Less comparison operator. + * @param datum Datum to be compared. + * @result Whether the instance satisfies the condition with respect to datum. + */ + inline bool operator<(const Datum& datum) const + { + // return id < datum.id; + return id < datum.id || (id == datum.id && subId < datum.subId); + } + /** + * Greater comparison operator. + * @param datum Datum to be compared. + * @result Whether the instance satisfies the condition with respect to datum. + */ + inline bool operator>(const Datum& datum) const + { + // return id > datum.id; + return id > datum.id || (id == datum.id && subId > datum.subId); + } + /** + * Less or equal comparison operator. + * @param datum Datum to be compared. + * @result Whether the instance satisfies the condition with respect to datum. + */ + inline bool operator<=(const Datum& datum) const + { + // return id <= datum.id; + return id < datum.id || (id == datum.id && subId <= datum.subId); + } + /** + * Greater or equal comparison operator. + * @param datum Datum to be compared. + * @result Whether the instance satisfies the condition with respect to datum. + */ + inline bool operator>=(const Datum& datum) const + { + // return id >= datum.id; + return id > datum.id || (id == datum.id && subId >= datum.subId); + } + /** + * Equal comparison operator. + * @param datum Datum to be compared. + * @result Whether the instance satisfies the condition with respect to datum. + */ + inline bool operator==(const Datum& datum) const + { + // return id == datum.id; + return id == datum.id && subId == datum.subId; + } + /** + * Not equal comparison operator. + * @param datum Datum to be compared. + * @result Whether the instance satisfies the condition with respect to datum. + */ + inline bool operator!=(const Datum& datum) const + { + // return id != datum.id; + return id != datum.id || subId != datum.subId; + } + }; + + // Defines for Datum. Added here rather than in `macros.hpp` to avoid circular dependencies + #define BASE_DATUM Datum + #define BASE_DATUMS std::vector> + #define BASE_DATUMS_SH std::shared_ptr + #define DEFINE_TEMPLATE_DATUM(templateName) template class OP_API templateName + #define COMPILE_TEMPLATE_DATUM(templateName) extern template class templateName +} + +#endif // OPENPOSE_CORE_DATUM_HPP diff --git a/openpose/include/openpose/core/enumClasses.hpp b/openpose/include/openpose/core/enumClasses.hpp new file mode 100644 index 0000000000000000000000000000000000000000..783aa974a8deb3823f76c27aedb3138be7dd2808 --- /dev/null +++ b/openpose/include/openpose/core/enumClasses.hpp @@ -0,0 +1,43 @@ +#ifndef OPENPOSE_CORE_ENUM_CLASSES_HPP +#define OPENPOSE_CORE_ENUM_CLASSES_HPP + +namespace op +{ + enum class ScaleMode : unsigned char + { + InputResolution, + NetOutputResolution, + OutputResolution, + ZeroToOne, // [0, 1] + ZeroToOneFixedAspect, // [0, 1] + PlusMinusOne, // [-1, 1] + PlusMinusOneFixedAspect, // [-1, 1] + UnsignedChar, // [0, 255] + NoScale, + }; + + enum class HeatMapType : unsigned char + { + Parts, + Background, + PAFs, + }; + + enum class RenderMode : unsigned char + { + None, + Auto, // It will select Gpu if CUDA version, or Cpu otherwise + Cpu, + Gpu, + }; + + enum class ElementToRender : unsigned char + { + Skeleton, + Background, + AddKeypoints, + AddPAFs, + }; +} + +#endif // OPENPOSE_CORE_ENUM_CLASSES_HPP diff --git a/openpose/include/openpose/core/gpuRenderer.hpp b/openpose/include/openpose/core/gpuRenderer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6b53f7feb20a6d7bf4558ce732e3d82536d7d79c --- /dev/null +++ b/openpose/include/openpose/core/gpuRenderer.hpp @@ -0,0 +1,51 @@ +#ifndef OPENPOSE_CORE_GPU_RENDERER_HPP +#define OPENPOSE_CORE_GPU_RENDERER_HPP + +#include +#include +#include +#include + +namespace op +{ + class OP_API GpuRenderer : public Renderer + { + public: + explicit GpuRenderer( + const float renderThreshold, const float alphaKeypoint, const float alphaHeatMap, + const bool blendOriginalFrame = true, const unsigned int elementToRender = 0u, + const unsigned int numberElementsToRender = 0u); + + virtual ~GpuRenderer(); + + std::tuple, std::shared_ptr, std::shared_ptr>, + std::shared_ptr, std::shared_ptr> + getSharedParameters(); + + void setSharedParametersAndIfLast( + const std::tuple, std::shared_ptr, std::shared_ptr>, + std::shared_ptr, std::shared_ptr>& tuple, + const bool isLast); + + void setSharedParameters( + const std::tuple, std::shared_ptr, + std::shared_ptr>& tuple); + + protected: + std::shared_ptr spGpuMemory; + + void cpuToGpuMemoryIfNotCopiedYet(const float* const cpuMemory, const unsigned long long memoryVolume); + + void gpuToCpuMemoryIfLastRenderer(float* cpuMemory, const unsigned long long memoryVolume); + + private: + std::shared_ptr spVolume; + bool mIsFirstRenderer; + bool mIsLastRenderer; + std::shared_ptr spGpuMemoryAllocated; + + DELETE_COPY(GpuRenderer); + }; +} + +#endif // OPENPOSE_CORE_GPU_RENDERER_HPP diff --git a/openpose/include/openpose/core/headers.hpp b/openpose/include/openpose/core/headers.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a8a63c38b62eecc6a79680c4707dba951ed8bb2a --- /dev/null +++ b/openpose/include/openpose/core/headers.hpp @@ -0,0 +1,32 @@ +#ifndef OPENPOSE_CORE_HEADERS_HPP +#define OPENPOSE_CORE_HEADERS_HPP + +// core module +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // OPENPOSE_CORE_HEADERS_HPP diff --git a/openpose/include/openpose/core/keepTopNPeople.hpp b/openpose/include/openpose/core/keepTopNPeople.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f3e8a43388142fb5bdd841aae6afadb41a34e82b --- /dev/null +++ b/openpose/include/openpose/core/keepTopNPeople.hpp @@ -0,0 +1,22 @@ +#ifndef OPENPOSE_CORE_KEEP_TOP_N_PEOPLE_HPP +#define OPENPOSE_CORE_KEEP_TOP_N_PEOPLE_HPP + +#include + +namespace op +{ + class OP_API KeepTopNPeople + { + public: + explicit KeepTopNPeople(const int numberPeopleMax); + + virtual ~KeepTopNPeople(); + + Array keepTopPeople(const Array& peopleArrays, const Array& poseScores) const; + + private: + const int mNumberPeopleMax; + }; +} + +#endif // OPENPOSE_CORE_KEEP_TOP_N_PEOPLE_HPP diff --git a/openpose/include/openpose/core/keypointScaler.hpp b/openpose/include/openpose/core/keypointScaler.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a37da645b99044b963114e42d6fe8f50188c765f --- /dev/null +++ b/openpose/include/openpose/core/keypointScaler.hpp @@ -0,0 +1,30 @@ +#ifndef OPENPOSE_CORE_KEYPOINT_SCALER_HPP +#define OPENPOSE_CORE_KEYPOINT_SCALER_HPP + +#include +#include + +namespace op +{ + class OP_API KeypointScaler + { + public: + explicit KeypointScaler(const ScaleMode scaleMode); + + virtual ~KeypointScaler(); + + void scale(Array& arrayToScale, const double scaleInputToOutput, const double scaleNetToOutput, + const Point& producerSize) const; + + void scale(std::vector>& arraysToScale, const double scaleInputToOutput, + const double scaleNetToOutput, const Point& producerSize) const; + + void scale(std::vector>>& poseCandidates, const double scaleInputToOutput, + const double scaleNetToOutput, const Point& producerSize) const; + + private: + const ScaleMode mScaleMode; + }; +} + +#endif // OPENPOSE_CORE_KEYPOINT_SCALER_HPP diff --git a/openpose/include/openpose/core/macros.hpp b/openpose/include/openpose/core/macros.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9b84b016d43b0e699101773495be46f1fdf6d7c3 --- /dev/null +++ b/openpose/include/openpose/core/macros.hpp @@ -0,0 +1,88 @@ +#ifndef OPENPOSE_CORE_MACROS_HPP +#define OPENPOSE_CORE_MACROS_HPP + +#include // std::chrono:: functionaligy, e.g., std::chrono::milliseconds +#include // std::shared_ptr +#include +#include +#include // std::this_thread +#include + +// OpenPose name and version +const std::string OPEN_POSE_NAME_STRING = "OpenPose"; +const std::string OPEN_POSE_VERSION_STRING = "1.7.0"; +const std::string OPEN_POSE_NAME_AND_VERSION = OPEN_POSE_NAME_STRING + " " + OPEN_POSE_VERSION_STRING; +// #define COMMERCIAL_LICENSE + +#ifndef _WIN32 + #define OP_API +#elif defined OP_EXPORTS + #define OP_API __declspec(dllexport) +#else + #define OP_API __declspec(dllimport) +#endif + +// Disable some Windows Warnings +#ifdef _WIN32 + #pragma warning(disable: 4251) // 'XXX': class 'YYY' needs to have dll-interface to be used by clients of class 'ZZZ' +#endif + +#define UNUSED(unusedVariable) (void)(unusedVariable) + +#define DELETE_COPY(className) \ + className(const className&) = delete; \ + className& operator=(const className&) = delete + +// Instantiate a class with all the basic types +#define COMPILE_TEMPLATE_BASIC_TYPES_CLASS(className) COMPILE_TEMPLATE_BASIC_TYPES(className, class) +#define COMPILE_TEMPLATE_BASIC_TYPES_STRUCT(className) COMPILE_TEMPLATE_BASIC_TYPES(className, struct) +#define COMPILE_TEMPLATE_BASIC_TYPES(className, classType) \ + template classType OP_API className; \ + template classType OP_API className; \ + template classType OP_API className; \ + template classType OP_API className; \ + template classType OP_API className; \ + template classType OP_API className; \ + template classType OP_API className; \ + template classType OP_API className; \ + template classType OP_API className; \ + template classType OP_API className; \ + template classType OP_API className; \ + template classType OP_API className; \ + template classType OP_API className; \ + template classType OP_API className + +// Instantiate a class with float and double specifications +#define COMPILE_TEMPLATE_FLOATING_TYPES_CLASS(className) COMPILE_TEMPLATE_FLOATING_TYPES(className, class) +#define COMPILE_TEMPLATE_FLOATING_TYPES_STRUCT(className) COMPILE_TEMPLATE_FLOATING_TYPES(className, struct) +#define COMPILE_TEMPLATE_FLOATING_TYPES(className, classType) \ + char gInstantiationGuard##className; \ + template classType OP_API className; \ + template classType OP_API className + +// Instantiate a class with float and double specifications +#define COMPILE_TEMPLATE_FLOATING_INT_TYPES_CLASS(className) COMPILE_TEMPLATE_FLOATING_INT_TYPES(className, class) +#define COMPILE_TEMPLATE_FLOATING_INT_TYPES_STRUCT(className) COMPILE_TEMPLATE_FLOATING_INT_TYPES(className, struct) +#define COMPILE_TEMPLATE_FLOATING_INT_TYPES(className, classType) \ + char gInstantiationGuard##className; \ + template classType OP_API className; \ + template classType OP_API className; \ + template classType OP_API className; \ + template classType OP_API className + +/** + * cout operator overload calling toString() function + * @return std::ostream containing output from toString() + */ +#define OVERLOAD_C_OUT(className) \ + template std::ostream &operator<<(std::ostream& ostream, const op::className& obj) \ + { \ + ostream << obj.toString(); \ + return ostream; \ + } + +// PIMPL does not work if function arguments need the 3rd-party class. Alternative: +// stackoverflow.com/questions/13978775/how-to-avoid-include-dependency-to-external-library?answertab=active#tab-top +struct dim3; + +#endif // OPENPOSE_CORE_MACROS_HPP diff --git a/openpose/include/openpose/core/matrix.hpp b/openpose/include/openpose/core/matrix.hpp new file mode 100644 index 0000000000000000000000000000000000000000..67d77812fb00b479b66845f0a21856ce0a71aee1 --- /dev/null +++ b/openpose/include/openpose/core/matrix.hpp @@ -0,0 +1,208 @@ +#ifndef OPENPOSE_CORE_MAT_HPP +#define OPENPOSE_CORE_MAT_HPP + +#include // std::shared_ptr +#include + +namespace op +{ + // Convert from Matrix into cv::Mat. Usage example: + // #include + // ... + // cv::Mat opMat = OP2CVMAT(cv::Mat()); + #define OP_OP2CVMAT(opMat) \ + (*((cv::Mat*)((opMat).getCvMat()))) + + // Convert from Matrix into const cv::Mat. Usage example: + // #include + // ... + // cv::Mat opMat = OP2CVCONSTMAT(cv::Mat()); + #define OP_OP2CVCONSTMAT(opMat) \ + (*((cv::Mat*)((opMat).getConstCvMat()))) + + // Convert from cv::Mat into Matrix. Usage example: + // #include + // ... + // Matrix opMat = CV2OPMAT(Matrix()); + #define OP_CV2OPMAT(cvMat) \ + (op::Matrix((void*)&(cvMat))) + + // Convert from cv::Mat into const Matrix. Usage example: + // #include + // ... + // Matrix opMat = CV2OPCONSTMAT(Matrix()); + #define OP_CV2OPCONSTMAT(cvMat) \ + (op::Matrix((const void*)&(cvMat))) + + // Convert from std::vector into std::vector. Usage example: + // #include + // ... + // std::vector opMats; // Assume filled + // OP_OP2CVVECTORMAT(cvMats, opMats); + #define OP_OP2CVVECTORMAT(cvMats, opMats) \ + std::vector cvMats; \ + for (auto& opMat : (opMats)) \ + { \ + const auto cvMat = OP_OP2CVCONSTMAT(opMat); \ + cvMats.emplace_back(cvMat); \ + } + + // Convert from std::vector into std::vector. Usage example: + // #include + // ... + // std::vector cvMats; // Assume filled + // OP_CV2OPVECTORMAT(opMats, cvMats); + #define OP_CV2OPVECTORMAT(opMats, cvMats) \ + std::vector opMats; \ + for (auto& cvMat : (cvMats)) \ + { \ + const auto opMat = OP_CV2OPMAT(cvMat); \ + opMats.emplace_back(opMat); \ + } + + // Convert from std::vector into std::vector. Usage example: + // #include + // ... + // // Equivalents: + // OP_CV_VOID_FUNCTION(opMat, size()); + // // and + // OP_OP2CVMAT(cvMat, opMat); + // cvMat.size(); + #define OP_MAT_VOID_FUNCTION(opMat, function) \ + { \ + cv::Mat cvMat = OP_OP2CVMAT(cvMat, opMat); \ + cvMat.function; \ + } + #define OP_CONST_MAT_VOID_FUNCTION(opMat, function) \ + { \ + const cv::Mat cvMat = OP_OP2CVCONSTMAT(opMat); \ + cvMat.function; \ + } + #define OP_MAT_RETURN_FUNCTION(outputVariable, opMat, function) \ + { \ + cv::Mat cvMat = OP_OP2CVMAT(cvMat, opMat); \ + outputVariable = cvMat.function; \ + } + #define OP_CONST_MAT_RETURN_FUNCTION(outputVariable, opMat, function) \ + { \ + const cv::Mat cvMat = OP_OP2CVCONSTMAT(opMat); \ + outputVariable = cvMat.function; \ + } + + /** + * Matrix: Bind of cv::Mat to avoid OpenCV as dependency in the headers. + */ + class OP_API Matrix + { + public: + /** + * @param matrixesResized For 3-D OpenPose, if >1, it will assume the image is composed of + * numberImagesStackedHorizontally horizontally stacked images. It must be already resized to avoid + * internally allocating/removing elements of std::vector (to avoid errors if using different std DLLs) + * @param cvMatPtr should be a cv::Mat element or it will provoke a core dumped. Done to + * avoid explicitly exposing 3rdparty libraries on the headers. + */ + static void splitCvMatIntoVectorMatrix(std::vector& matrixesResized, const void* const cvMatPtr); + + Matrix(); + + /** + * @param cvMatPtr should be a cv::Mat element or it will provoke a core dumped. Done to + * avoid explicitly exposing 3rdparty libraries on the headers. + */ + explicit Matrix(const void* cvMatPtr); + + /** + * Analog to cv::Mat(int rows, int cols, int type, void *data, size_t step=AUTO_STEP) + */ + explicit Matrix(const int rows, const int cols, const int type); + + /** + * Analog to cv::Mat(int rows, int cols, int type, void *data, size_t step=AUTO_STEP) + * Very important: This Matrix will only "borrow" this pointer, so the caller must make sure to maintain the + * memory allocated until this Matrix destructor is called and also to handle the ucharPtr memory deallocation. + * @param ucharPtr should be a cv::Mat::data (or analog) element or it will provoke a core dumped. Done to + * avoid explicitly exposing 3rdparty libraries on the headers. + */ + explicit Matrix(const int rows, const int cols, const int type, void* cvMatPtr); + + Matrix clone() const; + + /** + * @return cv::Mat*. + */ + void* getCvMat(); + + /** + * @return const cv::Mat*. + */ + const void* getConstCvMat() const; + + /** + * Equivalent to cv::Mat::data + * @return A raw pointer to the internal data of cv::Mat. + */ + unsigned char* data(); + /** + * Equivalent to cv::Mat::data + * @return A raw pointer to the internal data of cv::Mat. + */ + const unsigned char* dataConst() const; + /** + * Similar to dataConst(), but it allows the data to be edited. + * This function is only implemented for Pybind11 usage. + * @return A raw pointer to the internal data of cv::Mat. + */ + unsigned char* dataPseudoConst() const; + + /** + * Equivalent to cv::Mat::eye + */ + static Matrix eye(const int rows, const int cols, const int type); + /** + * Equivalent to cv::Mat::cols + */ + int cols() const; + /** + * Equivalent to cv::Mat::rows + */ + int rows() const; + /** + * Equivalent to cv::Mat::size[dimension] + */ + int size(const int dimension) const; + /** + * Equivalent to cv::Mat::dims + */ + int dims() const; + + /** + * Equivalent to their analog cv::Mat functions + */ + bool isContinuous() const; + bool isSubmatrix() const; + size_t elemSize() const; + size_t elemSize1() const; + int type() const; + int depth() const; + int channels() const; + size_t step1(const int i = 0) const; + bool empty() const; + size_t total() const; + int checkVector(const int elemChannels, const int depth = -1, const bool requireContinuous = true) const; + + /** + * Similar to their analog cv::Mat functions + */ + void setTo(const double value); + void copyTo(Matrix& outputMat) const; + + private: + // PIMPL idiom + // http://www.cppsamples.com/common-tasks/pimpl.html + struct ImplMatrix; + std::shared_ptr spImpl; + }; +} + +#endif // OPENPOSE_CORE_MAT_HPP diff --git a/openpose/include/openpose/core/opOutputToCvMat.hpp b/openpose/include/openpose/core/opOutputToCvMat.hpp new file mode 100644 index 0000000000000000000000000000000000000000..77eb2b4cc91416b0a2b51e9b8fe5cec81aa4e3f8 --- /dev/null +++ b/openpose/include/openpose/core/opOutputToCvMat.hpp @@ -0,0 +1,32 @@ +#ifndef OPENPOSE_CORE_OP_OUTPUT_TO_CV_MAT_HPP +#define OPENPOSE_CORE_OP_OUTPUT_TO_CV_MAT_HPP + +#include + +namespace op +{ + class OP_API OpOutputToCvMat + { + public: + OpOutputToCvMat(const bool gpuResize = false); + + virtual ~OpOutputToCvMat(); + + void setSharedParameters( + const std::tuple, std::shared_ptr, std::shared_ptr>& tuple); + + Matrix formatToCvMat(const Array& outputData); + + private: + const bool mGpuResize; + // Shared variables + std::shared_ptr spOutputImageFloatCuda; + std::shared_ptr spOutputMaxSize; + std::shared_ptr spGpuMemoryAllocated; + // Local variables + unsigned char* pOutputImageUCharCuda; + unsigned long long mOutputMaxSizeUChar; + }; +} + +#endif // OPENPOSE_CORE_OP_OUTPUT_TO_CV_MAT_HPP diff --git a/openpose/include/openpose/core/point.hpp b/openpose/include/openpose/core/point.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f5486dadef08fd0220a9aa4ab79898e87886af2c --- /dev/null +++ b/openpose/include/openpose/core/point.hpp @@ -0,0 +1,161 @@ +#ifndef OPENPOSE_CORE_POINT_HPP +#define OPENPOSE_CORE_POINT_HPP + +#include +#include + +namespace op +{ + template + struct Point + { + T x; + T y; + + Point(const T x = 0, const T y = 0); + + /** + * Copy constructor. + * It performs `fast copy`: For performance purpose, copying a Point or Point or cv::Mat just copies the + * reference, it still shares the same internal data. + * Modifying the copied element will modify the original one. + * Use clone() for a slower but real copy, similarly to cv::Mat and Point. + * @param point Point to be copied. + */ + Point(const Point& point); + + /** + * Copy assignment. + * Similar to Point(const Point& point). + * @param point Point to be copied. + * @return The resulting Point. + */ + Point& operator=(const Point& point); + + /** + * Move constructor. + * It destroys the original Point to be moved. + * @param point Point to be moved. + */ + Point(Point&& point); + + /** + * Move assignment. + * Similar to Point(Point&& point). + * @param point Point to be moved. + * @return The resulting Point. + */ + Point& operator=(Point&& point); + + inline T area() const + { + return x * y; + } + + /** + * It returns a string with the whole Point data. Useful for debugging. + * The format is: `[x, y]` + * @return A string with the Point values in the above format. + */ + std::string toString() const; + + + + + + // ------------------------------ Comparison operators ------------------------------ // + /** + * Less comparison operator. + * @param point Point to be compared. + * @result Whether the instance satisfies the condition with respect to point. + */ + inline bool operator<(const Point& point) const + { + return area() < point.area(); + } + + /** + * Greater comparison operator. + * @param point Point to be compared. + * @result Whether the instance satisfies the condition with respect to point. + */ + inline bool operator>(const Point& point) const + { + return area() > point.area(); + } + + /** + * Less or equal comparison operator. + * @param point Point to be compared. + * @result Whether the instance satisfies the condition with respect to point. + */ + inline bool operator<=(const Point& point) const + { + return area() <= point.area(); + } + + /** + * Greater or equal comparison operator. + * @param point Point to be compared. + * @result Whether the instance satisfies the condition with respect to point. + */ + inline bool operator>=(const Point& point) const + { + return area() >= point.area(); + } + + /** + * Equal comparison operator. + * @param point Point to be compared. + * @result Whether the instance satisfies the condition with respect to point. + */ + inline bool operator==(const Point& point) const + { + return area() == point.area(); + } + + /** + * Not equal comparison operator. + * @param point Point to be compared. + * @result Whether the instance satisfies the condition with respect to point. + */ + inline bool operator!=(const Point& point) const + { + return area() != point.area(); + } + + + + + + // ------------------------------ Basic Operators ------------------------------ // + Point& operator+=(const Point& point); + + Point operator+(const Point& point) const; + + Point& operator+=(const T value); + + Point operator+(const T value) const; + + Point& operator-=(const Point& point); + + Point operator-(const Point& point) const; + + Point& operator-=(const T value); + + Point operator-(const T value) const; + + Point& operator*=(const T value); + + Point operator*(const T value) const; + + Point& operator/=(const T value); + + Point operator/(const T value) const; + }; + + // Static methods + OVERLOAD_C_OUT(Point) +} + +#endif // OPENPOSE_CORE_POINT_HPP diff --git a/openpose/include/openpose/core/rectangle.hpp b/openpose/include/openpose/core/rectangle.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b5ffe0a5e6e189fdbb011915a1319d12b52647f9 --- /dev/null +++ b/openpose/include/openpose/core/rectangle.hpp @@ -0,0 +1,93 @@ +#ifndef OPENPOSE_CORE_RECTANGLE_HPP +#define OPENPOSE_CORE_RECTANGLE_HPP + +#include +#include +#include + +namespace op +{ + template + struct Rectangle + { + T x; + T y; + T width; + T height; + + Rectangle(const T x = 0, const T y = 0, const T width = 0, const T height = 0); + + /** + * Copy constructor. + * It performs `fast copy`: For performance purpose, copying a Rectangle or Datum or cv::Mat just copies + * the reference, it still shares the same internal data. + * Modifying the copied element will modify the original one. + * Use clone() for a slower but real copy, similarly to cv::Mat and Rectangle. + * @param rectangle Rectangle to be copied. + */ + Rectangle(const Rectangle& rectangle); + + /** + * Copy assignment. + * Similar to Rectangle(const Rectangle& rectangle). + * @param rectangle Rectangle to be copied. + * @return The resulting Rectangle. + */ + Rectangle& operator=(const Rectangle& rectangle); + + /** + * Move constructor. + * It destroys the original Rectangle to be moved. + * @param rectangle Rectangle to be moved. + */ + Rectangle(Rectangle&& rectangle); + + /** + * Move assignment. + * Similar to Rectangle(Rectangle&& rectangle). + * @param rectangle Rectangle to be moved. + * @return The resulting Rectangle. + */ + Rectangle& operator=(Rectangle&& rectangle); + + Point center() const; + + inline Point topLeft() const + { + return Point{x, y}; + } + + Point bottomRight() const; + + inline T area() const + { + return width * height; + } + + void recenter(const T newWidth, const T newHeight); + + /** + * It returns a string with the whole Rectangle data. Useful for debugging. + * The format is: `[x, y, width, height]` + * @return A string with the Rectangle values in the above format. + */ + std::string toString() const; + + // ------------------------------ Basic Operators ------------------------------ // + Rectangle& operator*=(const T value); + + Rectangle operator*(const T value) const; + + Rectangle& operator/=(const T value); + + Rectangle operator/(const T value) const; + }; + + // Static methods + template + Rectangle recenter(const Rectangle& rectangle, const T newWidth, const T newHeight); + + OVERLOAD_C_OUT(Rectangle) +} + +#endif // OPENPOSE_CORE_RECTANGLE_HPP diff --git a/openpose/include/openpose/core/renderer.hpp b/openpose/include/openpose/core/renderer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b5fb0f3b81bb42f9a2ce6c7067d0264a033b7dc6 --- /dev/null +++ b/openpose/include/openpose/core/renderer.hpp @@ -0,0 +1,56 @@ +#ifndef OPENPOSE_CORE_RENDERER_HPP +#define OPENPOSE_CORE_RENDERER_HPP + +#include +#include +#include + +namespace op +{ + class OP_API Renderer + { + public: + explicit Renderer(const float renderThreshold, const float alphaKeypoint, const float alphaHeatMap, + const bool blendOriginalFrame = true, const unsigned int elementToRender = 0u, + const unsigned int numberElementsToRender = 0u); + + virtual ~Renderer(); + + void increaseElementToRender(const int increment); + + void setElementToRender(const int elementToRender); + + void setElementToRender(const ElementToRender elementToRender); + + bool getBlendOriginalFrame() const; + + void setBlendOriginalFrame(const bool blendOriginalFrame); + + float getAlphaKeypoint() const; + + void setAlphaKeypoint(const float alphaKeypoint); + + float getAlphaHeatMap() const; + + void setAlphaHeatMap(const float alphaHeatMap); + + bool getShowGooglyEyes() const; + + void setShowGooglyEyes(const bool showGooglyEyes); + + protected: + const float mRenderThreshold; + std::atomic mBlendOriginalFrame; + std::shared_ptr> spElementToRender; + std::shared_ptr spNumberElementsToRender; + std::atomic mShowGooglyEyes; + + private: + float mAlphaKeypoint; + float mAlphaHeatMap; + + DELETE_COPY(Renderer); + }; +} + +#endif // OPENPOSE_CORE_RENDERER_HPP diff --git a/openpose/include/openpose/core/scaleAndSizeExtractor.hpp b/openpose/include/openpose/core/scaleAndSizeExtractor.hpp new file mode 100644 index 0000000000000000000000000000000000000000..cace5a29086a4c445f56cb7d8a6b8ffbc0d3156b --- /dev/null +++ b/openpose/include/openpose/core/scaleAndSizeExtractor.hpp @@ -0,0 +1,29 @@ +#ifndef OPENPOSE_CORE_SCALE_AND_SIZE_EXTRACTOR_HPP +#define OPENPOSE_CORE_SCALE_AND_SIZE_EXTRACTOR_HPP + +#include +#include + +namespace op +{ + class OP_API ScaleAndSizeExtractor + { + public: + ScaleAndSizeExtractor(const Point& netInputResolution, const float netInputResolutionDynamicBehavior, + const Point& outputResolution, const int scaleNumber = 1, const double scaleGap = 0.25); + + virtual ~ScaleAndSizeExtractor(); + + std::tuple, std::vector>, double, Point> extract( + const Point& inputResolution) const; + + private: + const Point mNetInputResolution; + const float mNetInputResolutionDynamicBehavior; + const Point mOutputSize; + const int mScaleNumber; + const double mScaleGap; + }; +} + +#endif // OPENPOSE_CORE_SCALE_AND_SIZE_EXTRACTOR_HPP diff --git a/openpose/include/openpose/core/string.hpp b/openpose/include/openpose/core/string.hpp new file mode 100644 index 0000000000000000000000000000000000000000..76407204d601a7ef9a8d37d7f74bcdf12cc52090 --- /dev/null +++ b/openpose/include/openpose/core/string.hpp @@ -0,0 +1,43 @@ +#ifndef OPENPOSE_CORE_STRING_HPP +#define OPENPOSE_CORE_STRING_HPP + +#include // std::shared_ptr +#include +#include + +namespace op +{ + /** + * String: Basic container for std::string to avoid std::string in the WrapperStructXXX classes. Otherwise, + * cryptic runtime DLL errors could occur when exporting OpenPose to other projects using different STL DLLs. + */ + class OP_API String + { + public: + String(); + + /** + * It will force a copy of the char* of std::string to avoid DLL runtime errors. Example usages: + * std::string stdString = "This is a std::string"; + * String string(stdString.c_str()); + */ + String(const char* charPtr); + + /** + * It will force a copy of string + */ + explicit String(const std::string& string); + + const std::string& getStdString() const; + + bool empty() const; + + private: + // PIMPL idiom + // http://www.cppsamples.com/common-tasks/pimpl.html + struct ImplString; + std::shared_ptr spImpl; + }; +} + +#endif // OPENPOSE_CORE_STRING_HPP diff --git a/openpose/include/openpose/core/verbosePrinter.hpp b/openpose/include/openpose/core/verbosePrinter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ccc1615b4c5c1b7aaad3cf371a4271d8190bdcd1 --- /dev/null +++ b/openpose/include/openpose/core/verbosePrinter.hpp @@ -0,0 +1,24 @@ +#ifndef OPENPOSE_CORE_VERBOSE_PRINTER_HPP +#define OPENPOSE_CORE_VERBOSE_PRINTER_HPP + +#include + +namespace op +{ + class OP_API VerbosePrinter + { + public: + VerbosePrinter(const double verbose, const unsigned long long numberFrames); + + virtual ~VerbosePrinter(); + + void printVerbose(const unsigned long long frameNumber) const; + + private: + const unsigned long long mNumberFrames; + const std::string mNumberFramesString; + const double mVerbose; + }; +} + +#endif // OPENPOSE_CORE_VERBOSE_PRINTER_HPP diff --git a/openpose/include/openpose/core/wCvMatToOpInput.hpp b/openpose/include/openpose/core/wCvMatToOpInput.hpp new file mode 100644 index 0000000000000000000000000000000000000000..80d08ffc3ef85af1133a8524eb2b2a0515609b89 --- /dev/null +++ b/openpose/include/openpose/core/wCvMatToOpInput.hpp @@ -0,0 +1,86 @@ +#ifndef OPENPOSE_CORE_W_CV_MAT_TO_OP_INPUT_HPP +#define OPENPOSE_CORE_W_CV_MAT_TO_OP_INPUT_HPP + +#include +#include +#include + +namespace op +{ + template + class WCvMatToOpInput : public Worker + { + public: + explicit WCvMatToOpInput(const std::shared_ptr& cvMatToOpInput); + + virtual ~WCvMatToOpInput(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + const std::shared_ptr spCvMatToOpInput; + + DELETE_COPY(WCvMatToOpInput); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WCvMatToOpInput::WCvMatToOpInput(const std::shared_ptr& cvMatToOpInput) : + spCvMatToOpInput{cvMatToOpInput} + { + } + + template + WCvMatToOpInput::~WCvMatToOpInput() + { + } + + template + void WCvMatToOpInput::initializationOnThread() + { + } + + template + void WCvMatToOpInput::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // cv::Mat -> float* + for (auto& tDatumPtr : *tDatums) + tDatumPtr->inputNetData = spCvMatToOpInput->createArray( + tDatumPtr->cvInputData, tDatumPtr->scaleInputToNetInputs, tDatumPtr->netInputSizes); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WCvMatToOpInput); +} + +#endif // OPENPOSE_CORE_W_CV_MAT_TO_OP_INPUT_HPP diff --git a/openpose/include/openpose/core/wCvMatToOpOutput.hpp b/openpose/include/openpose/core/wCvMatToOpOutput.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e4d819a6f2305f5409ac2c08fe78e47fa9e63d9f --- /dev/null +++ b/openpose/include/openpose/core/wCvMatToOpOutput.hpp @@ -0,0 +1,89 @@ +#ifndef OPENPOSE_CORE_W_CV_MAT_TO_OP_OUTPUT_HPP +#define OPENPOSE_CORE_W_CV_MAT_TO_OP_OUTPUT_HPP + +#include +#include +#include + +namespace op +{ + template + class WCvMatToOpOutput : public Worker + { + public: + explicit WCvMatToOpOutput(const std::shared_ptr& cvMatToOpOutput); + + virtual ~WCvMatToOpOutput(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + const std::shared_ptr spCvMatToOpOutput; + + DELETE_COPY(WCvMatToOpOutput); + }; +} + + + + + +// Implementation +#include +#include +namespace op +{ + template + WCvMatToOpOutput::WCvMatToOpOutput(const std::shared_ptr& cvMatToOpOutput) : + spCvMatToOpOutput{cvMatToOpOutput} + { + } + + template + WCvMatToOpOutput::~WCvMatToOpOutput() + { + } + + template + void WCvMatToOpOutput::initializationOnThread() + { + } + + template + void WCvMatToOpOutput::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // T* to T + auto& tDatumsNoPtr = *tDatums; + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // cv::Mat -> float* + for (auto& tDatumPtr : tDatumsNoPtr) + tDatumPtr->outputData = spCvMatToOpOutput->createArray( + tDatumPtr->cvInputData, tDatumPtr->scaleInputToOutput, tDatumPtr->netOutputSize); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WCvMatToOpOutput); +} + +#endif // OPENPOSE_CORE_W_CV_MAT_TO_OP_OUTPUT_HPP diff --git a/openpose/include/openpose/core/wKeepTopNPeople.hpp b/openpose/include/openpose/core/wKeepTopNPeople.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b0dd7dd9e07b3a6ccebb065789876231a15f688e --- /dev/null +++ b/openpose/include/openpose/core/wKeepTopNPeople.hpp @@ -0,0 +1,92 @@ +#ifndef OPENPOSE_CORE_W_KEEP_TOP_N_PEOPLE_HPP +#define OPENPOSE_CORE_W_KEEP_TOP_N_PEOPLE_HPP + +#include +#include +#include + +namespace op +{ + template + class WKeepTopNPeople : public Worker + { + public: + explicit WKeepTopNPeople(const std::shared_ptr& keepTopNPeople); + + virtual ~WKeepTopNPeople(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + std::shared_ptr spKeepTopNPeople; + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WKeepTopNPeople::WKeepTopNPeople(const std::shared_ptr& keepTopNPeople) : + spKeepTopNPeople{keepTopNPeople} + { + } + + template + WKeepTopNPeople::~WKeepTopNPeople() + { + } + + template + void WKeepTopNPeople::initializationOnThread() + { + } + + template + void WKeepTopNPeople::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Rescale pose data + for (auto& tDatumPtr : *tDatums) + { + tDatumPtr->poseKeypoints = spKeepTopNPeople->keepTopPeople( + tDatumPtr->poseKeypoints, tDatumPtr->poseScores); + tDatumPtr->faceKeypoints = spKeepTopNPeople->keepTopPeople( + tDatumPtr->faceKeypoints, tDatumPtr->poseScores); + tDatumPtr->handKeypoints[0] = spKeepTopNPeople->keepTopPeople( + tDatumPtr->handKeypoints[0], tDatumPtr->poseScores); + tDatumPtr->handKeypoints[1] = spKeepTopNPeople->keepTopPeople( + tDatumPtr->handKeypoints[1], tDatumPtr->poseScores); + } + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WKeepTopNPeople); +} + +#endif // OPENPOSE_CORE_W_KEEP_TOP_N_PEOPLE_HPP diff --git a/openpose/include/openpose/core/wKeypointScaler.hpp b/openpose/include/openpose/core/wKeypointScaler.hpp new file mode 100644 index 0000000000000000000000000000000000000000..74ceaa2d97fde3df3f095931f7097b7c8450d213 --- /dev/null +++ b/openpose/include/openpose/core/wKeypointScaler.hpp @@ -0,0 +1,94 @@ +#ifndef OPENPOSE_CORE_W_KEYPOINT_SCALER_HPP +#define OPENPOSE_CORE_W_KEYPOINT_SCALER_HPP + +#include +#include +#include + +namespace op +{ + template + class WKeypointScaler : public Worker + { + public: + explicit WKeypointScaler(const std::shared_ptr& keypointScaler); + + virtual ~WKeypointScaler(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + std::shared_ptr spKeypointScaler; + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WKeypointScaler::WKeypointScaler(const std::shared_ptr& keypointScaler) : + spKeypointScaler{keypointScaler} + { + } + + template + WKeypointScaler::~WKeypointScaler() + { + } + + template + void WKeypointScaler::initializationOnThread() + { + } + + template + void WKeypointScaler::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Rescale pose data + for (auto& tDatumPtr : *tDatums) + { + std::vector> arraysToScale{ + tDatumPtr->poseKeypoints, tDatumPtr->handKeypoints[0], + tDatumPtr->handKeypoints[1], tDatumPtr->faceKeypoints}; + spKeypointScaler->scale( + arraysToScale, tDatumPtr->scaleInputToOutput, tDatumPtr->scaleNetToOutput, + Point{tDatumPtr->cvInputData.cols(), tDatumPtr->cvInputData.rows()}); + // Rescale part candidates + spKeypointScaler->scale( + tDatumPtr->poseCandidates, tDatumPtr->scaleInputToOutput, tDatumPtr->scaleNetToOutput, + Point{tDatumPtr->cvInputData.cols(), tDatumPtr->cvInputData.rows()}); + } + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WKeypointScaler); +} + +#endif // OPENPOSE_CORE_W_KEYPOINT_SCALER_HPP diff --git a/openpose/include/openpose/core/wOpOutputToCvMat.hpp b/openpose/include/openpose/core/wOpOutputToCvMat.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ececaa822ab3be3d72fb5f559284f98316835794 --- /dev/null +++ b/openpose/include/openpose/core/wOpOutputToCvMat.hpp @@ -0,0 +1,85 @@ +#ifndef OPENPOSE_CORE_W_OP_OUTPUT_TO_CV_MAT_HPP +#define OPENPOSE_CORE_W_OP_OUTPUT_TO_CV_MAT_HPP + +#include +#include +#include + +namespace op +{ + template + class WOpOutputToCvMat : public Worker + { + public: + explicit WOpOutputToCvMat(const std::shared_ptr& opOutputToCvMat); + + virtual ~WOpOutputToCvMat(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + const std::shared_ptr spOpOutputToCvMat; + + DELETE_COPY(WOpOutputToCvMat); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WOpOutputToCvMat::WOpOutputToCvMat(const std::shared_ptr& opOutputToCvMat) : + spOpOutputToCvMat{opOutputToCvMat} + { + } + + template + WOpOutputToCvMat::~WOpOutputToCvMat() + { + } + + template + void WOpOutputToCvMat::initializationOnThread() + { + } + + template + void WOpOutputToCvMat::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // float* -> cv::Mat + for (auto& tDatumPtr : *tDatums) + tDatumPtr->cvOutputData = spOpOutputToCvMat->formatToCvMat(tDatumPtr->outputData); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WOpOutputToCvMat); +} + +#endif // OPENPOSE_CORE_W_OP_OUTPUT_TO_CV_MAT_HPP diff --git a/openpose/include/openpose/core/wScaleAndSizeExtractor.hpp b/openpose/include/openpose/core/wScaleAndSizeExtractor.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d9640a76c56b27cb7f71a498ad4468fc38a09e05 --- /dev/null +++ b/openpose/include/openpose/core/wScaleAndSizeExtractor.hpp @@ -0,0 +1,90 @@ +#ifndef OPENPOSE_CORE_W_SCALE_AND_SIZE_EXTRACTOR_HPP +#define OPENPOSE_CORE_W_SCALE_AND_SIZE_EXTRACTOR_HPP + +#include +#include +#include + +namespace op +{ + template + class WScaleAndSizeExtractor : public Worker + { + public: + explicit WScaleAndSizeExtractor(const std::shared_ptr& scaleAndSizeExtractor); + + virtual ~WScaleAndSizeExtractor(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + const std::shared_ptr spScaleAndSizeExtractor; + + DELETE_COPY(WScaleAndSizeExtractor); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WScaleAndSizeExtractor::WScaleAndSizeExtractor( + const std::shared_ptr& scaleAndSizeExtractor) : + spScaleAndSizeExtractor{scaleAndSizeExtractor} + { + } + + template + WScaleAndSizeExtractor::~WScaleAndSizeExtractor() + { + } + + template + void WScaleAndSizeExtractor::initializationOnThread() + { + } + + template + void WScaleAndSizeExtractor::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // cv::Mat -> float* + for (auto& tDatumPtr : *tDatums) + { + const Point inputSize{tDatumPtr->cvInputData.cols(), tDatumPtr->cvInputData.rows()}; + std::tie(tDatumPtr->scaleInputToNetInputs, tDatumPtr->netInputSizes, tDatumPtr->scaleInputToOutput, + tDatumPtr->netOutputSize) = spScaleAndSizeExtractor->extract(inputSize); + } + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WScaleAndSizeExtractor); +} + +#endif // OPENPOSE_CORE_W_SCALE_AND_SIZE_EXTRACTOR_HPP diff --git a/openpose/include/openpose/core/wVerbosePrinter.hpp b/openpose/include/openpose/core/wVerbosePrinter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5109bde9dc502f9069a6d4a5f51d243a6574ca79 --- /dev/null +++ b/openpose/include/openpose/core/wVerbosePrinter.hpp @@ -0,0 +1,89 @@ +#ifndef OPENPOSE_CORE_W_VERBOSE_PRINTER_HPP +#define OPENPOSE_CORE_W_VERBOSE_PRINTER_HPP + +#include +#include +#include + +namespace op +{ + template + class WVerbosePrinter : public Worker + { + public: + explicit WVerbosePrinter(const std::shared_ptr& verbosePrinter); + + virtual ~WVerbosePrinter(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + const std::shared_ptr spVerbosePrinter; + + DELETE_COPY(WVerbosePrinter); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WVerbosePrinter::WVerbosePrinter( + const std::shared_ptr& verbosePrinter) : + spVerbosePrinter{verbosePrinter} + { + } + + template + WVerbosePrinter::~WVerbosePrinter() + { + } + + template + void WVerbosePrinter::initializationOnThread() + { + } + + template + void WVerbosePrinter::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Print verbose + if (checkNoNullNorEmpty(tDatums)) + { + const auto tDatumPtr = (*tDatums)[0]; + spVerbosePrinter->printVerbose(tDatumPtr->frameNumber); + } + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WVerbosePrinter); +} + +#endif // OPENPOSE_CORE_W_VERBOSE_PRINTER_HPP diff --git a/openpose/include/openpose/face/faceCpuRenderer.hpp b/openpose/include/openpose/face/faceCpuRenderer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3b8ec10ed17ed0f0141d682bcf0e5bf3c2fb4dba --- /dev/null +++ b/openpose/include/openpose/face/faceCpuRenderer.hpp @@ -0,0 +1,25 @@ +#ifndef OPENPOSE_FACE_FACE_CPU_RENDERER_HPP +#define OPENPOSE_FACE_FACE_CPU_RENDERER_HPP + +#include +#include +#include +#include + +namespace op +{ + class OP_API FaceCpuRenderer : public Renderer, public FaceRenderer + { + public: + FaceCpuRenderer(const float renderThreshold, const float alphaKeypoint = FACE_DEFAULT_ALPHA_KEYPOINT, + const float alphaHeatMap = FACE_DEFAULT_ALPHA_HEAT_MAP); + + virtual ~FaceCpuRenderer(); + + void renderFaceInherited(Array& outputData, const Array& faceKeypoints); + + DELETE_COPY(FaceCpuRenderer); + }; +} + +#endif // OPENPOSE_FACE_FACE_CPU_RENDERER_HPP diff --git a/openpose/include/openpose/face/faceDetector.hpp b/openpose/include/openpose/face/faceDetector.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ff9b7648a1da3cb7ad6d01eb3a95f0cf3ec897a3 --- /dev/null +++ b/openpose/include/openpose/face/faceDetector.hpp @@ -0,0 +1,30 @@ +#ifndef OPENPOSE_FACE_FACE_DETECTOR_HPP +#define OPENPOSE_FACE_FACE_DETECTOR_HPP + +#include +#include + +namespace op +{ + class OP_API FaceDetector + { + public: + explicit FaceDetector(const PoseModel poseModel); + + virtual ~FaceDetector(); + + std::vector> detectFaces(const Array& poseKeypoints) const; + + private: + const unsigned int mNeck; + const unsigned int mNose; + const unsigned int mLEar; + const unsigned int mREar; + const unsigned int mLEye; + const unsigned int mREye; + + DELETE_COPY(FaceDetector); + }; +} + +#endif // OPENPOSE_FACE_FACE_DETECTOR_HPP diff --git a/openpose/include/openpose/face/faceDetectorOpenCV.hpp b/openpose/include/openpose/face/faceDetectorOpenCV.hpp new file mode 100644 index 0000000000000000000000000000000000000000..577aebef4b29681690665e9b016eee7418b243f7 --- /dev/null +++ b/openpose/include/openpose/face/faceDetectorOpenCV.hpp @@ -0,0 +1,28 @@ +#ifndef OPENPOSE_FACE_FACE_DETECTOR_OPENCV_HPP +#define OPENPOSE_FACE_FACE_DETECTOR_OPENCV_HPP + +#include + +namespace op +{ + class OP_API FaceDetectorOpenCV + { + public: + explicit FaceDetectorOpenCV(const std::string& modelFolder); + + virtual ~FaceDetectorOpenCV(); + + // No thread-save + std::vector> detectFaces(const Matrix& inputData); + + private: + // PIMPL idiom + // http://www.cppsamples.com/common-tasks/pimpl.html + struct ImplFaceDetectorOpenCV; + std::unique_ptr upImpl; + + DELETE_COPY(FaceDetectorOpenCV); + }; +} + +#endif // OPENPOSE_FACE_FACE_DETECTOR_OPENCV_HPP diff --git a/openpose/include/openpose/face/faceExtractorCaffe.hpp b/openpose/include/openpose/face/faceExtractorCaffe.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6bc40c25e62a7a7d2e2fd9510c9d3729c7357f1c --- /dev/null +++ b/openpose/include/openpose/face/faceExtractorCaffe.hpp @@ -0,0 +1,57 @@ +#ifndef OPENPOSE_FACE_FACE_EXTRACTOR_CAFFE_HPP +#define OPENPOSE_FACE_FACE_EXTRACTOR_CAFFE_HPP + +#include +#include +#include + +namespace op +{ + /** + * Face keypoint extractor class for Caffe framework. + */ + class OP_API FaceExtractorCaffe : public FaceExtractorNet + { + public: + /** + * Constructor of the FaceExtractor class. + * @param netInputSize Size at which the cropped image (where the face is located) is resized. + * @param netOutputSize Size of the final results. At the moment, it must be equal than netOutputSize. + */ + FaceExtractorCaffe(const Point& netInputSize, const Point& netOutputSize, + const std::string& modelFolder, const int gpuId, + const std::vector& heatMapTypes = {}, + const ScaleMode heatMapScaleMode = ScaleMode::ZeroToOneFixedAspect, + const bool enableGoogleLogging = true); + + virtual ~FaceExtractorCaffe(); + + /** + * This function must be call before using any other function. It must also be called inside the thread in + * which the functions are going to be used. + */ + void netInitializationOnThread(); + + /** + * This function extracts the face keypoints for each detected face in the image. + * @param faceRectangles location of the faces in the image. It is a length-variable std::vector, where + * each index corresponds to a different person in the image. Internally, a op::Rectangle + * (similar to cv::Rect for floating values) with the position of that face (or 0,0,0,0 if + * some face is missing, e.g., if a specific person has only half of the body inside the image). + * @param cvInputData Original image in Mat format and BGR format. + */ + void forwardPass(const std::vector>& faceRectangles, const Matrix& inputData); + + private: + // PIMPL idiom + // http://www.cppsamples.com/common-tasks/pimpl.html + struct ImplFaceExtractorCaffe; + std::unique_ptr upImpl; + + // PIMP requires DELETE_COPY & destructor, or extra code + // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html + DELETE_COPY(FaceExtractorCaffe); + }; +} + +#endif // OPENPOSE_FACE_FACE_EXTRACTOR_CAFFE_HPP diff --git a/openpose/include/openpose/face/faceExtractorNet.hpp b/openpose/include/openpose/face/faceExtractorNet.hpp new file mode 100644 index 0000000000000000000000000000000000000000..19f06362af76c2a172c8c8759b106bf4f6987d37 --- /dev/null +++ b/openpose/include/openpose/face/faceExtractorNet.hpp @@ -0,0 +1,85 @@ +#ifndef OPENPOSE_FACE_FACE_EXTRACTOR_HPP +#define OPENPOSE_FACE_FACE_EXTRACTOR_HPP + +#include +#include +#include + +namespace op +{ + /** + * Face keypoint extractor class. + */ + class OP_API FaceExtractorNet + { + public: + /** + * Constructor of the FaceExtractorNet class. + * @param netInputSize Size at which the cropped image (where the face is located) is resized. + * @param netOutputSize Size of the final results. At the moment, it must be equal than netOutputSize. + */ + explicit FaceExtractorNet(const Point& netInputSize, const Point& netOutputSize, + const std::vector& heatMapTypes = {}, + const ScaleMode heatMapScaleMode = ScaleMode::ZeroToOneFixedAspect); + + /** + * Virtual destructor of the HandExtractor class. + * Required to allow inheritance. + */ + virtual ~FaceExtractorNet(); + + /** + * This function must be call before using any other function. It must also be called inside the thread in + * which the functions are going to be used. + */ + void initializationOnThread(); + + /** + * This function extracts the face keypoints for each detected face in the image. + * @param faceRectangles location of the faces in the image. It is a length-variable std::vector, where + * each index corresponds to a different person in the image. Internally, a op::Rectangle + * (similar to cv::Rect for floating values) with the position of that face (or 0,0,0,0 if + * some face is missing, e.g., if a specific person has only half of the body inside the image). + * @param cvInputData Original image in Mat format and BGR format. + */ + virtual void forwardPass(const std::vector>& faceRectangles, const Matrix& inputData) = 0; + + Array getHeatMaps() const; + + /** + * This function returns the face keypoins. VERY IMPORTANT: use getFaceKeypoints().clone() if the keypoints are + * going to be edited in a different thread. + * @return A Array with all the face keypoints. It follows the pose structure, i.e., the first dimension + * corresponds to all the people in the image, the second to each specific keypoint, and the third one to + * (x, y, score). + */ + Array getFaceKeypoints() const; + + bool getEnabled() const; + + void setEnabled(const bool enabled); + + protected: + const Point mNetOutputSize; + Array mFaceImageCrop; + Array mFaceKeypoints; + // HeatMaps parameters + Array mHeatMaps; + const ScaleMode mHeatMapScaleMode; + const std::vector mHeatMapTypes; + // Temporarily disable it + std::atomic mEnabled; + + virtual void netInitializationOnThread() = 0; + + private: + // Init with thread + std::thread::id mThreadId; + + void checkThread() const; + + DELETE_COPY(FaceExtractorNet); + }; +} + +#endif // OPENPOSE_FACE_FACE_EXTRACTOR_HPP diff --git a/openpose/include/openpose/face/faceGpuRenderer.hpp b/openpose/include/openpose/face/faceGpuRenderer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f0d82a4b4c2dc06a1c0402df86dbdc888bb4f1da --- /dev/null +++ b/openpose/include/openpose/face/faceGpuRenderer.hpp @@ -0,0 +1,34 @@ +#ifndef OPENPOSE_FACE_FACE_GPU_RENDERER_HPP +#define OPENPOSE_FACE_FACE_GPU_RENDERER_HPP + +#include +#include +#include +#include + +namespace op +{ + class OP_API FaceGpuRenderer : public GpuRenderer, public FaceRenderer + { + public: + FaceGpuRenderer(const float renderThreshold, + const float alphaKeypoint = FACE_DEFAULT_ALPHA_KEYPOINT, + const float alphaHeatMap = FACE_DEFAULT_ALPHA_HEAT_MAP); + + virtual ~FaceGpuRenderer(); + + void initializationOnThread(); + + void renderFaceInherited(Array& outputData, const Array& faceKeypoints); + + private: + float* pGpuFace; // GPU aux memory + float* pMaxPtr; // GPU aux memory + float* pMinPtr; // GPU aux memory + float* pScalePtr; // GPU aux memory + + DELETE_COPY(FaceGpuRenderer); + }; +} + +#endif // OPENPOSE_FACE_FACE_GPU_RENDERER_HPP diff --git a/openpose/include/openpose/face/faceParameters.hpp b/openpose/include/openpose/face/faceParameters.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a5f1141d1e8538a8f7865dbb4b13cd42f4f626e9 --- /dev/null +++ b/openpose/include/openpose/face/faceParameters.hpp @@ -0,0 +1,33 @@ +#ifndef OPENPOSE_FACE_FACE_PARAMETERS_HPP +#define OPENPOSE_FACE_FACE_PARAMETERS_HPP + +#include +#include + +namespace op +{ + const auto FACE_MAX_FACES = POSE_MAX_PEOPLE; + + const auto FACE_NUMBER_PARTS = 70u; + #define FACE_PAIRS_RENDER_GPU \ + 0,1, 1,2, 2,3, 3,4, 4,5, 5,6, 6,7, 7,8, 8,9, 9,10, 10,11, 11,12, 12,13, 13,14, 14,15, 15,16, 17,18, 18,19, 19,20, \ + 20,21, 22,23, 23,24, 24,25, 25,26, 27,28, 28,29, 29,30, 31,32, 32,33, 33,34, 34,35, 36,37, 37,38, 38,39, 39,40, 40,41, \ + 41,36, 42,43, 43,44, 44,45, 45,46, 46,47, 47,42, 48,49, 49,50, 50,51, 51,52, 52,53, 53,54, 54,55, 55,56, 56,57, 57,58, \ + 58,59, 59,48, 60,61, 61,62, 62,63, 63,64, 64,65, 65,66, 66,67, 67,60 + #define FACE_SCALES_RENDER_GPU 1 + const std::vector FACE_PAIRS_RENDER {FACE_PAIRS_RENDER_GPU}; + #define FACE_COLORS_RENDER_GPU 255.f, 255.f, 255.f + const std::vector FACE_COLORS_RENDER{FACE_COLORS_RENDER_GPU}; + const std::vector FACE_SCALES_RENDER{FACE_SCALES_RENDER_GPU}; + + // Constant parameters + const auto FACE_CCN_DECREASE_FACTOR = 8.f; + const std::string FACE_PROTOTXT{"face/pose_deploy.prototxt"}; + const std::string FACE_TRAINED_MODEL{"face/pose_iter_116000.caffemodel"}; + + // Rendering parameters + const auto FACE_DEFAULT_ALPHA_KEYPOINT = POSE_DEFAULT_ALPHA_KEYPOINT; + const auto FACE_DEFAULT_ALPHA_HEAT_MAP = POSE_DEFAULT_ALPHA_HEAT_MAP; +} + +#endif // OPENPOSE_FACE_FACE_PARAMETERS_HPP diff --git a/openpose/include/openpose/face/faceRenderer.hpp b/openpose/include/openpose/face/faceRenderer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9cea5f9ef638966a8eddb20c7c5a03e81c835be2 --- /dev/null +++ b/openpose/include/openpose/face/faceRenderer.hpp @@ -0,0 +1,23 @@ +#ifndef OPENPOSE_FACE_FACE_RENDERER_HPP +#define OPENPOSE_FACE_FACE_RENDERER_HPP + +#include + +namespace op +{ + class OP_API FaceRenderer + { + public: + virtual ~FaceRenderer(){}; + + virtual void initializationOnThread(){}; + + void renderFace(Array& outputData, const Array& faceKeypoints, + const float scaleInputToOutput); + + private: + virtual void renderFaceInherited(Array& outputData, const Array& faceKeypoints) = 0; + }; +} + +#endif // OPENPOSE_FACE_FACE_RENDERER_HPP diff --git a/openpose/include/openpose/face/headers.hpp b/openpose/include/openpose/face/headers.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c0ecce607251ec8d714d733a208c2bc21d99f52b --- /dev/null +++ b/openpose/include/openpose/face/headers.hpp @@ -0,0 +1,19 @@ +#ifndef OPENPOSE_FACE_HEADERS_HPP +#define OPENPOSE_FACE_HEADERS_HPP + +// face module +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // OPENPOSE_FACE_HEADERS_HPP diff --git a/openpose/include/openpose/face/renderFace.hpp b/openpose/include/openpose/face/renderFace.hpp new file mode 100644 index 0000000000000000000000000000000000000000..771618b9de5ebeddc54cb7bbbbf9cfd73c4520d9 --- /dev/null +++ b/openpose/include/openpose/face/renderFace.hpp @@ -0,0 +1,18 @@ +#ifndef OPENPOSE_FACE_RENDER_FACE_HPP +#define OPENPOSE_FACE_RENDER_FACE_HPP + +#include +#include + +namespace op +{ + OP_API void renderFaceKeypointsCpu( + Array& frameArray, const Array& faceKeypoints, const float renderThreshold); + + void renderFaceKeypointsGpu( + float* framePtr, float* maxPtr, float* minPtr, float* scalePtr, const Point& frameSize, + const float* const facePtr, const int numberPeople, const float renderThreshold, + const float alphaColorToAdd = FACE_DEFAULT_ALPHA_KEYPOINT); +} + +#endif // OPENPOSE_FACE_RENDER_FACE_HPP diff --git a/openpose/include/openpose/face/wFaceDetector.hpp b/openpose/include/openpose/face/wFaceDetector.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f5da5f08367a7e1c487a93c714690a8bacc730b6 --- /dev/null +++ b/openpose/include/openpose/face/wFaceDetector.hpp @@ -0,0 +1,85 @@ +#ifndef OPENPOSE_FACE_W_FACE_EXTRACTOR_HPP +#define OPENPOSE_FACE_W_FACE_EXTRACTOR_HPP + +#include +#include +#include + +namespace op +{ + template + class WFaceDetector : public Worker + { + public: + explicit WFaceDetector(const std::shared_ptr& faceDetector); + + virtual ~WFaceDetector(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + std::shared_ptr spFaceDetector; + + DELETE_COPY(WFaceDetector); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WFaceDetector::WFaceDetector(const std::shared_ptr& faceDetector) : + spFaceDetector{faceDetector} + { + } + + template + WFaceDetector::~WFaceDetector() + { + } + + template + void WFaceDetector::initializationOnThread() + { + } + + template + void WFaceDetector::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Detect people face + for (auto& tDatumPtr : *tDatums) + tDatumPtr->faceRectangles = spFaceDetector->detectFaces(tDatumPtr->poseKeypoints); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WFaceDetector); +} + +#endif // OPENPOSE_FACE_W_FACE_EXTRACTOR_HPP diff --git a/openpose/include/openpose/face/wFaceDetectorOpenCV.hpp b/openpose/include/openpose/face/wFaceDetectorOpenCV.hpp new file mode 100644 index 0000000000000000000000000000000000000000..098b3fec1076539164ee6f637d3f5b76cbe5214d --- /dev/null +++ b/openpose/include/openpose/face/wFaceDetectorOpenCV.hpp @@ -0,0 +1,85 @@ +#ifndef OPENPOSE_FACE_W_FACE_EXTRACTOR_OPENCV_HPP +#define OPENPOSE_FACE_W_FACE_EXTRACTOR_OPENCV_HPP + +#include +#include +#include + +namespace op +{ + template + class WFaceDetectorOpenCV : public Worker + { + public: + explicit WFaceDetectorOpenCV(const std::shared_ptr& faceDetectorOpenCV); + + virtual ~WFaceDetectorOpenCV(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + std::shared_ptr spFaceDetectorOpenCV; + + DELETE_COPY(WFaceDetectorOpenCV); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WFaceDetectorOpenCV::WFaceDetectorOpenCV(const std::shared_ptr& faceDetectorOpenCV) : + spFaceDetectorOpenCV{faceDetectorOpenCV} + { + } + + template + WFaceDetectorOpenCV::~WFaceDetectorOpenCV() + { + } + + template + void WFaceDetectorOpenCV::initializationOnThread() + { + } + + template + void WFaceDetectorOpenCV::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Detect people face + for (auto& tDatumPtr : *tDatums) + tDatumPtr->faceRectangles = spFaceDetectorOpenCV->detectFaces(tDatumPtr->cvInputData); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WFaceDetectorOpenCV); +} + +#endif // OPENPOSE_FACE_W_FACE_EXTRACTOR_OPENCV_HPP diff --git a/openpose/include/openpose/face/wFaceExtractorNet.hpp b/openpose/include/openpose/face/wFaceExtractorNet.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9139bd4ac040e4b41e93f6e91234e161c1a0097f --- /dev/null +++ b/openpose/include/openpose/face/wFaceExtractorNet.hpp @@ -0,0 +1,90 @@ +#ifndef OPENPOSE_FACE_W_FACE_DETECTOR_NET_HPP +#define OPENPOSE_FACE_W_FACE_DETECTOR_NET_HPP + +#include +#include +#include + +namespace op +{ + template + class WFaceExtractorNet : public Worker + { + public: + explicit WFaceExtractorNet(const std::shared_ptr& faceExtractorNet); + + virtual ~WFaceExtractorNet(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + std::shared_ptr spFaceExtractorNet; + + DELETE_COPY(WFaceExtractorNet); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WFaceExtractorNet::WFaceExtractorNet(const std::shared_ptr& faceExtractorNet) : + spFaceExtractorNet{faceExtractorNet} + { + } + + template + WFaceExtractorNet::~WFaceExtractorNet() + { + } + + template + void WFaceExtractorNet::initializationOnThread() + { + spFaceExtractorNet->initializationOnThread(); + } + + template + void WFaceExtractorNet::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Extract people face + for (auto& tDatumPtr : *tDatums) + { + spFaceExtractorNet->forwardPass(tDatumPtr->faceRectangles, tDatumPtr->cvInputData); + tDatumPtr->faceHeatMaps = spFaceExtractorNet->getHeatMaps().clone(); + tDatumPtr->faceKeypoints = spFaceExtractorNet->getFaceKeypoints().clone(); + } + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WFaceExtractorNet); +} + +#endif // OPENPOSE_FACE_W_FACE_DETECTOR_NET_HPP diff --git a/openpose/include/openpose/face/wFaceRenderer.hpp b/openpose/include/openpose/face/wFaceRenderer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0986631cc9a856c1ecfa41aad1a1e41a2e441bfc --- /dev/null +++ b/openpose/include/openpose/face/wFaceRenderer.hpp @@ -0,0 +1,87 @@ +#ifndef OPENPOSE_FACE_W_FACE_RENDERER_HPP +#define OPENPOSE_FACE_W_FACE_RENDERER_HPP + +#include +#include +#include + +namespace op +{ + template + class WFaceRenderer : public Worker + { + public: + explicit WFaceRenderer(const std::shared_ptr& faceRenderer); + + virtual ~WFaceRenderer(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + std::shared_ptr spFaceRenderer; + + DELETE_COPY(WFaceRenderer); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WFaceRenderer::WFaceRenderer(const std::shared_ptr& faceRenderer) : + spFaceRenderer{faceRenderer} + { + } + + template + WFaceRenderer::~WFaceRenderer() + { + } + + template + void WFaceRenderer::initializationOnThread() + { + spFaceRenderer->initializationOnThread(); + } + + template + void WFaceRenderer::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Render people face + for (auto& tDatumPtr : *tDatums) + spFaceRenderer->renderFace( + tDatumPtr->outputData, tDatumPtr->faceKeypoints, (float)tDatumPtr->scaleInputToOutput); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WFaceRenderer); +} + +#endif // OPENPOSE_FACE_W_FACE_RENDERER_HPP diff --git a/openpose/include/openpose/filestream/bvhSaver.hpp b/openpose/include/openpose/filestream/bvhSaver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3ee708ff8681bbaddf02e0fd26e49a96c3784745 --- /dev/null +++ b/openpose/include/openpose/filestream/bvhSaver.hpp @@ -0,0 +1,41 @@ +#ifdef USE_3D_ADAM_MODEL +#ifndef OPENPOSE_FILESTREAM_BVH_SAVER_HPP +#define OPENPOSE_FILESTREAM_BVH_SAVER_HPP + +#ifdef USE_3D_ADAM_MODEL + #include +#endif +#include + +namespace op +{ + class OP_API BvhSaver + { + public: + BvhSaver(const std::string bvhFilePath, + const std::shared_ptr& totalModel = nullptr, + const double fps = 30.); + + virtual ~BvhSaver(); + + void initializationOnThread(); + + void updateBvh(const Eigen::Matrix& adamPose, + const Eigen::Vector3d& adamTranslation, + const Eigen::Matrix& j0Vec); + + + private: + // PIMPL idiom + // http://www.cppsamples.com/common-tasks/pimpl.html + struct ImplBvhSaver; + std::shared_ptr spImpl; + + // PIMP requires DELETE_COPY & destructor, or extra code + // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html + DELETE_COPY(BvhSaver); + }; +} + +#endif // OPENPOSE_FILESTREAM_BVH_SAVER_HPP +#endif diff --git a/openpose/include/openpose/filestream/cocoJsonSaver.hpp b/openpose/include/openpose/filestream/cocoJsonSaver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f4d5cc35e95755222bdb1fdd76246571aef0ade2 --- /dev/null +++ b/openpose/include/openpose/filestream/cocoJsonSaver.hpp @@ -0,0 +1,44 @@ +#ifndef OPENPOSE_FILESTREAM_POSE_JSON_COCO_SAVER_HPP +#define OPENPOSE_FILESTREAM_POSE_JSON_COCO_SAVER_HPP + +#include +#include +#include +#include + +namespace op +{ + /** + * The CocoJsonSaver class creates a COCO validation json file with details about the processed images. It + * inherits from Recorder. + */ + class OP_API CocoJsonSaver + { + public: + /** + * This constructor of CocoJsonSaver extends the Recorder::Recorder(const std::string & filePathToSave) + * constructor. + * @param filePathToSave const std::string parameter with the final file path where the generated json file + * will be saved. + */ + explicit CocoJsonSaver( + const std::string& filePathToSave, const PoseModel poseModel, const bool humanReadable = true, + const int cocoJsonVariants = 1, const CocoJsonFormat cocoJsonFormat = CocoJsonFormat::Body, + const int cocoJsonVariant = 0); + + virtual ~CocoJsonSaver(); + + void record( + const Array& poseKeypoints, const Array& poseScores, const std::string& imageName, + const unsigned long long frameNumber); + + private: + const PoseModel mPoseModel; + const int mCocoJsonVariant; + std::vector> mJsonOfstreams; + + DELETE_COPY(CocoJsonSaver); + }; +} + +#endif // OPENPOSE_FILESTREAM_POSE_JSON_COCO_SAVER_HPP diff --git a/openpose/include/openpose/filestream/enumClasses.hpp b/openpose/include/openpose/filestream/enumClasses.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ff8e984fe8d32e0a6d56b3161e3e97fd730739df --- /dev/null +++ b/openpose/include/openpose/filestream/enumClasses.hpp @@ -0,0 +1,26 @@ +#ifndef OPENPOSE_FILESTREAM_ENUM_CLASSES_HPP +#define OPENPOSE_FILESTREAM_ENUM_CLASSES_HPP + +namespace op +{ + enum class DataFormat : unsigned char + { + Json, + Xml, + Yaml, + Yml, + }; + + enum class CocoJsonFormat : unsigned char + { + Body, + Hand21, + Hand42, + Face, + Foot, + Car, + Size, + }; +} + +#endif // OPENPOSE_FILESTREAM_ENUM_CLASSES_HPP diff --git a/openpose/include/openpose/filestream/fileSaver.hpp b/openpose/include/openpose/filestream/fileSaver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..610ff0acc42aee8445778c4ded8b6dcbfb040f78 --- /dev/null +++ b/openpose/include/openpose/filestream/fileSaver.hpp @@ -0,0 +1,25 @@ +#ifndef OPENPOSE_FILESTREAM_DATA_SAVER_HPP +#define OPENPOSE_FILESTREAM_DATA_SAVER_HPP + +#include +#include + +namespace op +{ + class OP_API FileSaver + { + protected: + explicit FileSaver(const std::string& directoryPath); + + virtual ~FileSaver(); + + std::string getNextFileName(const unsigned long long index) const; + + std::string getNextFileName(const std::string& fileNameNoExtension) const; + + private: + const std::string mDirectoryPath; + }; +} + +#endif // OPENPOSE_FILESTREAM_DATA_SAVER_HPP diff --git a/openpose/include/openpose/filestream/fileStream.hpp b/openpose/include/openpose/filestream/fileStream.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c6478d67ba87a712b88b1dafbb911f9a914e581e --- /dev/null +++ b/openpose/include/openpose/filestream/fileStream.hpp @@ -0,0 +1,64 @@ +#ifndef OPENPOSE_FILESTREAM_FILE_STREAM_HPP +#define OPENPOSE_FILESTREAM_FILE_STREAM_HPP + +#include +#include +#include + +namespace op +{ + OP_API std::string dataFormatToString(const DataFormat dataFormat); + + OP_API DataFormat stringToDataFormat(const std::string& dataFormat); + + // Save custom float format + // Example to read it in Python, assuming a (18 x 300 x 500) size Array + // x = np.fromfile(heatMapFullPath, dtype=np.float32) + // assert x[0] == 3 # First parameter saves the number of dimensions (18x300x500 = 3 dimensions) + // shape_x = x[1:1+int(x[0])] + // assert len(shape_x[0]) == 3 # Number of dimensions + // assert shape_x[0] == 18 # Size of the first dimension + // assert shape_x[1] == 300 # Size of the second dimension + // assert shape_x[2] == 500 # Size of the third dimension + // arrayData = x[1+int(round(x[0])):] + OP_API void saveFloatArray(const Array& array, const std::string& fullFilePath); + + // Save/load json, xml, yaml, yml + OP_API void saveData( + const std::vector& opMats, const std::vector& cvMatNames, + const std::string& fileNameNoExtension, const DataFormat dataFormat); + + OP_API void saveData( + const Matrix& opMat, const std::string cvMatName, const std::string& fileNameNoExtension, + const DataFormat dataFormat); + + OP_API std::vector loadData( + const std::vector& cvMatNames, const std::string& fileNameNoExtension, + const DataFormat dataFormat); + + OP_API Matrix loadData( + const std::string& cvMatName, const std::string& fileNameNoExtension, const DataFormat dataFormat); + + // Json - Saving as *.json not available in OpenCV versions < 3.0, this function is a quick fix + OP_API void savePeopleJson( + const Array& keypoints, const std::vector>>& candidates, + const std::string& keypointName, const std::string& fileName, const bool humanReadable); + + // It will save a bunch of Array elements + OP_API void savePeopleJson( + const std::vector, std::string>>& keypointVector, + const std::vector>>& candidates, const std::string& fileName, + const bool humanReadable); + + // Save/load image + OP_API void saveImage( + const Matrix& matrix, const std::string& fullFilePath, + const std::vector& openCvCompressionParams + = {getCvImwriteJpegQuality(), 100, getCvImwritePngCompression(), 9}); + + OP_API Matrix loadImage(const std::string& fullFilePath, const int openCvFlags = getCvLoadImageAnydepth()); + + OP_API std::vector, 2>> loadHandDetectorTxt(const std::string& txtFilePath); +} + +#endif // OPENPOSE_FILESTREAM_FILE_STREAM_HPP diff --git a/openpose/include/openpose/filestream/headers.hpp b/openpose/include/openpose/filestream/headers.hpp new file mode 100644 index 0000000000000000000000000000000000000000..68db0bc56a71d776f301cfa8f8b991366aa86bf1 --- /dev/null +++ b/openpose/include/openpose/filestream/headers.hpp @@ -0,0 +1,29 @@ +#ifndef OPENPOSE_FILESTREAM_HEADERS_HPP +#define OPENPOSE_FILESTREAM_HEADERS_HPP + +// fileStream module +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // OPENPOSE_FILESTREAM_HEADERS_HPP diff --git a/openpose/include/openpose/filestream/heatMapSaver.hpp b/openpose/include/openpose/filestream/heatMapSaver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c9c58a47cad3ad53b17d1a3bfeacc1366f365775 --- /dev/null +++ b/openpose/include/openpose/filestream/heatMapSaver.hpp @@ -0,0 +1,23 @@ +#ifndef OPENPOSE_FILESTREAM_HEAT_MAP_SAVER_HPP +#define OPENPOSE_FILESTREAM_HEAT_MAP_SAVER_HPP + +#include +#include + +namespace op +{ + class OP_API HeatMapSaver : public FileSaver + { + public: + HeatMapSaver(const std::string& directoryPath, const std::string& imageFormat); + + virtual ~HeatMapSaver(); + + void saveHeatMaps(const std::vector>& heatMaps, const std::string& fileName) const; + + private: + const std::string mImageFormat; + }; +} + +#endif // OPENPOSE_FILESTREAM_HEAT_MAP_SAVER_HPP diff --git a/openpose/include/openpose/filestream/imageSaver.hpp b/openpose/include/openpose/filestream/imageSaver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0b1d9a0f561e4f9902ba8d44aa651d52fe5e153b --- /dev/null +++ b/openpose/include/openpose/filestream/imageSaver.hpp @@ -0,0 +1,25 @@ +#ifndef OPENPOSE_FILESTREAM_IMAGE_SAVER_HPP +#define OPENPOSE_FILESTREAM_IMAGE_SAVER_HPP + +#include +#include + +namespace op +{ + class OP_API ImageSaver : public FileSaver + { + public: + ImageSaver(const std::string& directoryPath, const std::string& imageFormat); + + virtual ~ImageSaver(); + + void saveImages(const Matrix& cvOutputData, const std::string& fileName) const; + + void saveImages(const std::vector& matOutputDatas, const std::string& fileName) const; + + private: + const std::string mImageFormat; + }; +} + +#endif // OPENPOSE_FILESTREAM_IMAGE_SAVER_HPP diff --git a/openpose/include/openpose/filestream/jsonOfstream.hpp b/openpose/include/openpose/filestream/jsonOfstream.hpp new file mode 100644 index 0000000000000000000000000000000000000000..768ab6c942dccbbe556b133064da279439ac8483 --- /dev/null +++ b/openpose/include/openpose/filestream/jsonOfstream.hpp @@ -0,0 +1,66 @@ +#ifndef OPENPOSE_FILESTREAM_JSON_OFSTREAM_HPP +#define OPENPOSE_FILESTREAM_JSON_OFSTREAM_HPP + +#include // std::ofstream +#include + +namespace op +{ + class OP_API JsonOfstream + { + public: + explicit JsonOfstream(const std::string& filePath, const bool humanReadable = true); + + /** + * Move constructor. + * It destroys the original JsonOfstream to be moved. + * @param array JsonOfstream to be moved. + */ + JsonOfstream(JsonOfstream&& jsonOfstream); + + /** + * Move assignment. + * Similar to JsonOfstream(JsonOfstream&& jsonOfstream). + * @param array JsonOfstream to be moved. + * @return The resulting JsonOfstream. + */ + JsonOfstream& operator=(JsonOfstream&& jsonOfstream); + + virtual ~JsonOfstream(); + + void objectOpen(); + + void objectClose(); + + void arrayOpen(); + + void arrayClose(); + + void version(const std::string& version); + + void key(const std::string& string); + + template + inline void plainText(const T& value) + { + *upOfstream << value; + } + + inline void comma() + { + *upOfstream << ","; + } + + void enter(); + + private: + bool mHumanReadable; + long long mBracesCounter; + long long mBracketsCounter; + std::unique_ptr upOfstream; // std::unique_ptr to solve std::move issue in GCC < 5 + + DELETE_COPY(JsonOfstream); + }; +} + +#endif // OPENPOSE_FILESTREAM_JSON_OFSTREAM_HPP diff --git a/openpose/include/openpose/filestream/keypointSaver.hpp b/openpose/include/openpose/filestream/keypointSaver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0c30a6e1b4e9aeda6af854eab6121c601704ae48 --- /dev/null +++ b/openpose/include/openpose/filestream/keypointSaver.hpp @@ -0,0 +1,25 @@ +#ifndef OPENPOSE_FILESTREAM_KEYPOINT_SAVER_HPP +#define OPENPOSE_FILESTREAM_KEYPOINT_SAVER_HPP + +#include +#include +#include + +namespace op +{ + class OP_API KeypointSaver : public FileSaver + { + public: + KeypointSaver(const std::string& directoryPath, const DataFormat format); + + virtual ~KeypointSaver(); + + void saveKeypoints(const std::vector>& keypointVector, const std::string& fileName, + const std::string& keypointName) const; + + private: + const DataFormat mFormat; + }; +} + +#endif // OPENPOSE_FILESTREAM_KEYPOINT_SAVER_HPP diff --git a/openpose/include/openpose/filestream/peopleJsonSaver.hpp b/openpose/include/openpose/filestream/peopleJsonSaver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9ed74df021329eb46e987be95882c34f583bdf6c --- /dev/null +++ b/openpose/include/openpose/filestream/peopleJsonSaver.hpp @@ -0,0 +1,23 @@ +#ifndef OPENPOSE_FILESTREAM_PEOPLE_JSON_SAVER_HPP +#define OPENPOSE_FILESTREAM_PEOPLE_JSON_SAVER_HPP + +#include +#include + +namespace op +{ + class OP_API PeopleJsonSaver : public FileSaver + { + public: + PeopleJsonSaver(const std::string& directoryPath); + + virtual ~PeopleJsonSaver(); + + void save( + const std::vector, std::string>>& keypointVector, + const std::vector>>& candidates, const std::string& fileName, + const bool humanReadable = true) const; + }; +} + +#endif // OPENPOSE_FILESTREAM_PEOPLE_JSON_SAVER_HPP diff --git a/openpose/include/openpose/filestream/udpSender.hpp b/openpose/include/openpose/filestream/udpSender.hpp new file mode 100644 index 0000000000000000000000000000000000000000..dfbf2dcbd286fba48f57b7b243408827ca62964c --- /dev/null +++ b/openpose/include/openpose/filestream/udpSender.hpp @@ -0,0 +1,31 @@ +#ifndef OPENPOSE_FILESTREAM_UDP_SENDER_HPP +#define OPENPOSE_FILESTREAM_UDP_SENDER_HPP + +#include + +namespace op +{ + class OP_API UdpSender + { + public: + UdpSender(const std::string& udpHost, const std::string& udpPort); + + virtual ~UdpSender(); + + void sendJointAngles(const double* const adamPosePtr, const int adamPoseRows, + const double* const adamTranslationPtr, + const double* const adamFaceCoeffsExpPtr, const int faceCoeffRows); + + private: + // PIMPL idiom + // http://www.cppsamples.com/common-tasks/pimpl.html + struct ImplUdpSender; + std::shared_ptr spImpl; + + // PIMP requires DELETE_COPY & destructor, or extra code + // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html + DELETE_COPY(UdpSender); + }; +} + +#endif // OPENPOSE_FILESTREAM_UDP_SENDER_HPP diff --git a/openpose/include/openpose/filestream/videoSaver.hpp b/openpose/include/openpose/filestream/videoSaver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f300ed03fd5c5ca444fa38e5cbda4a42a4b0ba83 --- /dev/null +++ b/openpose/include/openpose/filestream/videoSaver.hpp @@ -0,0 +1,33 @@ +#ifndef OPENPOSE_FILESTREAM_VIDEO_SAVER_HPP +#define OPENPOSE_FILESTREAM_VIDEO_SAVER_HPP + +#include + +namespace op +{ + class OP_API VideoSaver + { + public: + VideoSaver( + const std::string& videoSaverPath, const int cvFourcc, const double fps, + const std::string& addAudioFromThisVideo = ""); + + virtual ~VideoSaver(); + + bool isOpened(); + + void write(const Matrix& matToSave); + + void write(const std::vector& matsToSave); + + private: + // PIMPL idiom + // http://www.cppsamples.com/common-tasks/pimpl.html + struct ImplVideoSaver; + std::unique_ptr upImpl; + + DELETE_COPY(VideoSaver); + }; +} + +#endif // OPENPOSE_FILESTREAM_VIDEO_SAVER_HPP diff --git a/openpose/include/openpose/filestream/wBvhSaver.hpp b/openpose/include/openpose/filestream/wBvhSaver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..16335295107a22de91d71792d36118ebbc9310ee --- /dev/null +++ b/openpose/include/openpose/filestream/wBvhSaver.hpp @@ -0,0 +1,87 @@ +#ifdef USE_3D_ADAM_MODEL +#ifndef OPENPOSE_FILESTREAM_W_BVH_SAVER_HPP +#define OPENPOSE_FILESTREAM_W_BVH_SAVER_HPP + +#include +#include +#include + +namespace op +{ + template + class WBvhSaver : public WorkerConsumer + { + public: + explicit WBvhSaver(const std::shared_ptr& bvhSaver); + + virtual ~WBvhSaver(); + + void initializationOnThread(); + + void workConsumer(const TDatums& tDatums); + + private: + std::shared_ptr spBvhSaver; + + DELETE_COPY(WBvhSaver); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WBvhSaver::WBvhSaver(const std::shared_ptr& bvhSaver) : + spBvhSaver{bvhSaver} + { + } + + template + WBvhSaver::~WBvhSaver() + { + } + + template + void WBvhSaver::initializationOnThread() + { + } + + template + void WBvhSaver::workConsumer(const TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Record BVH file + const auto& tDatumPtr = (*tDatums)[0]; + if (!tDatumPtr->poseKeypoints3D.empty()) + spBvhSaver->updateBvh(tDatumPtr->adamPose, tDatumPtr->adamTranslation, tDatumPtr->j0Vec); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WBvhSaver); +} + +#endif // OPENPOSE_FILESTREAM_W_BVH_SAVER_HPP +#endif diff --git a/openpose/include/openpose/filestream/wCocoJsonSaver.hpp b/openpose/include/openpose/filestream/wCocoJsonSaver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3712dbf806c813d640c6027bc664be33a67040fe --- /dev/null +++ b/openpose/include/openpose/filestream/wCocoJsonSaver.hpp @@ -0,0 +1,89 @@ +#ifndef OPENPOSE_FILESTREAM_W_COCO_JSON_SAVER_HPP +#define OPENPOSE_FILESTREAM_W_COCO_JSON_SAVER_HPP + +#include +#include +#include + +namespace op +{ + template + class WCocoJsonSaver : public WorkerConsumer + { + public: + explicit WCocoJsonSaver(const std::shared_ptr& cocoJsonSaver); + + virtual ~WCocoJsonSaver(); + + void initializationOnThread(); + + void workConsumer(const TDatums& tDatums); + + private: + std::shared_ptr spCocoJsonSaver; + + DELETE_COPY(WCocoJsonSaver); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WCocoJsonSaver::WCocoJsonSaver(const std::shared_ptr& cocoJsonSaver) : + spCocoJsonSaver{cocoJsonSaver} + { + } + + template + WCocoJsonSaver::~WCocoJsonSaver() + { + } + + template + void WCocoJsonSaver::initializationOnThread() + { + } + + template + void WCocoJsonSaver::workConsumer(const TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Check tDatums->size() == 1 + if (tDatums->size() > 1) + error("Function only ready for tDatums->size() == 1", __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // T* to T + const auto& tDatumPtr = tDatums->at(0); + // Record json in COCO format + spCocoJsonSaver->record( + tDatumPtr->poseKeypoints, tDatumPtr->poseScores, tDatumPtr->name, tDatumPtr->frameNumber); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WCocoJsonSaver); +} + +#endif // OPENPOSE_FILESTREAM_W_COCO_JSON_SAVER_HPP diff --git a/openpose/include/openpose/filestream/wFaceSaver.hpp b/openpose/include/openpose/filestream/wFaceSaver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d0806dd4725a91453a1cf655b6d95c7b4e75a804 --- /dev/null +++ b/openpose/include/openpose/filestream/wFaceSaver.hpp @@ -0,0 +1,91 @@ +#ifndef OPENPOSE_FILESTREAM_W_FACE_SAVER_HPP +#define OPENPOSE_FILESTREAM_W_FACE_SAVER_HPP + +#include +#include +#include +#include + +namespace op +{ + template + class WFaceSaver : public WorkerConsumer + { + public: + explicit WFaceSaver(const std::shared_ptr& keypointSaver); + + virtual ~WFaceSaver(); + + void initializationOnThread(); + + void workConsumer(const TDatums& tDatums); + + private: + const std::shared_ptr spKeypointSaver; + + DELETE_COPY(WFaceSaver); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WFaceSaver::WFaceSaver(const std::shared_ptr& keypointSaver) : + spKeypointSaver{keypointSaver} + { + } + + template + WFaceSaver::~WFaceSaver() + { + } + + template + void WFaceSaver::initializationOnThread() + { + } + + template + void WFaceSaver::workConsumer(const TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // T* to T + auto& tDatumsNoPtr = *tDatums; + // Record people face keypoint data + std::vector> keypointVector(tDatumsNoPtr.size()); + for (auto i = 0u; i < tDatumsNoPtr.size(); i++) + keypointVector[i] = tDatumsNoPtr[i]->faceKeypoints; + const auto fileName = (!tDatumsNoPtr[0]->name.empty() + ? tDatumsNoPtr[0]->name : std::to_string(tDatumsNoPtr[0]->id)); + spKeypointSaver->saveKeypoints(keypointVector, fileName, "face"); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WFaceSaver); +} + +#endif // OPENPOSE_FILESTREAM_W_FACE_SAVER_HPP diff --git a/openpose/include/openpose/filestream/wHandSaver.hpp b/openpose/include/openpose/filestream/wHandSaver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0d6fb158eef138d25065885a08aaeab8eddad75c --- /dev/null +++ b/openpose/include/openpose/filestream/wHandSaver.hpp @@ -0,0 +1,96 @@ +#ifndef OPENPOSE_FILESTREAM_W_HAND_SAVER_HPP +#define OPENPOSE_FILESTREAM_W_HAND_SAVER_HPP + +#include +#include +#include +#include + +namespace op +{ + template + class WHandSaver : public WorkerConsumer + { + public: + explicit WHandSaver(const std::shared_ptr& keypointSaver); + + virtual ~WHandSaver(); + + void initializationOnThread(); + + void workConsumer(const TDatums& tDatums); + + private: + const std::shared_ptr spKeypointSaver; + + DELETE_COPY(WHandSaver); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WHandSaver::WHandSaver(const std::shared_ptr& keypointSaver) : + spKeypointSaver{keypointSaver} + { + } + + template + WHandSaver::~WHandSaver() + { + } + + template + void WHandSaver::initializationOnThread() + { + } + + template + void WHandSaver::workConsumer(const TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // T* to T + auto& tDatumsNoPtr = *tDatums; + // Record people hand keypoint data + const auto fileName = (!tDatumsNoPtr[0]->name.empty() + ? tDatumsNoPtr[0]->name : std::to_string(tDatumsNoPtr[0]->id)); + std::vector> keypointVector(tDatumsNoPtr.size()); + // Left hand + for (auto i = 0u; i < tDatumsNoPtr.size(); i++) + keypointVector[i] = tDatumsNoPtr[i]->handKeypoints[0]; + spKeypointSaver->saveKeypoints(keypointVector, fileName, "hand_left"); + // Right hand + for (auto i = 0u; i < tDatumsNoPtr.size(); i++) + keypointVector[i] = tDatumsNoPtr[i]->handKeypoints[1]; + spKeypointSaver->saveKeypoints(keypointVector, fileName, "hand_right"); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WHandSaver); +} + +#endif // OPENPOSE_FILESTREAM_W_HAND_SAVER_HPP diff --git a/openpose/include/openpose/filestream/wHeatMapSaver.hpp b/openpose/include/openpose/filestream/wHeatMapSaver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5a897a49e345968f7de3cf2b2f29e2db795e7805 --- /dev/null +++ b/openpose/include/openpose/filestream/wHeatMapSaver.hpp @@ -0,0 +1,91 @@ +#ifndef OPENPOSE_FILESTREAM_W_HEAT_MAP_SAVER_HPP +#define OPENPOSE_FILESTREAM_W_HEAT_MAP_SAVER_HPP + +#include +#include +#include + +namespace op +{ + template + class WHeatMapSaver : public WorkerConsumer + { + public: + explicit WHeatMapSaver(const std::shared_ptr& heatMapSaver); + + virtual ~WHeatMapSaver(); + + void initializationOnThread(); + + void workConsumer(const TDatums& tDatums); + + private: + const std::shared_ptr spHeatMapSaver; + + DELETE_COPY(WHeatMapSaver); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WHeatMapSaver::WHeatMapSaver(const std::shared_ptr& heatMapSaver) : + spHeatMapSaver{heatMapSaver} + { + } + + template + WHeatMapSaver::~WHeatMapSaver() + { + } + + template + void WHeatMapSaver::initializationOnThread() + { + } + + template + void WHeatMapSaver::workConsumer(const TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // T* to T + auto& tDatumsNoPtr = *tDatums; + // Record pose heatmap image(s) on disk + std::vector> poseHeatMaps(tDatumsNoPtr.size()); + for (auto i = 0u; i < tDatumsNoPtr.size(); i++) + poseHeatMaps[i] = tDatumsNoPtr[i]->poseHeatMaps; + const auto fileName = (!tDatumsNoPtr[0]->name.empty() + ? tDatumsNoPtr[0]->name : std::to_string(tDatumsNoPtr[0]->id)) + "_pose_heatmaps"; + spHeatMapSaver->saveHeatMaps(poseHeatMaps, fileName); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, + __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WHeatMapSaver); +} + +#endif // OPENPOSE_FILESTREAM_W_HEAT_MAP_SAVER_HPP diff --git a/openpose/include/openpose/filestream/wImageSaver.hpp b/openpose/include/openpose/filestream/wImageSaver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..66a4289957eb66234803303da132ef28f293b0b9 --- /dev/null +++ b/openpose/include/openpose/filestream/wImageSaver.hpp @@ -0,0 +1,90 @@ +#ifndef OPENPOSE_FILESTREAM_W_IMAGE_SAVER_HPP +#define OPENPOSE_FILESTREAM_W_IMAGE_SAVER_HPP + +#include +#include +#include + +namespace op +{ + template + class WImageSaver : public WorkerConsumer + { + public: + explicit WImageSaver(const std::shared_ptr& imageSaver); + + virtual ~WImageSaver(); + + void initializationOnThread(); + + void workConsumer(const TDatums& tDatums); + + private: + const std::shared_ptr spImageSaver; + + DELETE_COPY(WImageSaver); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WImageSaver::WImageSaver(const std::shared_ptr& imageSaver) : + spImageSaver{imageSaver} + { + } + + template + WImageSaver::~WImageSaver() + { + } + + template + void WImageSaver::initializationOnThread() + { + } + + template + void WImageSaver::workConsumer(const TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // T* to T + auto& tDatumsNoPtr = *tDatums; + // Record image(s) on disk + std::vector opOutputDatas(tDatumsNoPtr.size()); + for (auto i = 0u; i < tDatumsNoPtr.size(); i++) + opOutputDatas[i] = tDatumsNoPtr[i]->cvOutputData; + const auto fileName = (!tDatumsNoPtr[0]->name.empty() + ? tDatumsNoPtr[0]->name : std::to_string(tDatumsNoPtr[0]->id)); + spImageSaver->saveImages(opOutputDatas, fileName); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WImageSaver); +} + +#endif // OPENPOSE_FILESTREAM_W_IMAGE_SAVER_HPP diff --git a/openpose/include/openpose/filestream/wPeopleJsonSaver.hpp b/openpose/include/openpose/filestream/wPeopleJsonSaver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b17741b80c3345950b50019e357f3bd219d316f2 --- /dev/null +++ b/openpose/include/openpose/filestream/wPeopleJsonSaver.hpp @@ -0,0 +1,113 @@ +#ifndef OPENPOSE_FILESTREAM_W_PEOPLE_JSON_SAVER_HPP +#define OPENPOSE_FILESTREAM_W_PEOPLE_JSON_SAVER_HPP + +#include +#include +#include + +namespace op +{ + template + class WPeopleJsonSaver : public WorkerConsumer + { + public: + explicit WPeopleJsonSaver(const std::shared_ptr& peopleJsonSaver); + + virtual ~WPeopleJsonSaver(); + + void initializationOnThread(); + + void workConsumer(const TDatums& tDatums); + + private: + const std::shared_ptr spPeopleJsonSaver; + + DELETE_COPY(WPeopleJsonSaver); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WPeopleJsonSaver::WPeopleJsonSaver(const std::shared_ptr& peopleJsonSaver) : + spPeopleJsonSaver{peopleJsonSaver} + { + } + + template + WPeopleJsonSaver::~WPeopleJsonSaver() + { + } + + template + void WPeopleJsonSaver::initializationOnThread() + { + } + + template + void WPeopleJsonSaver::workConsumer(const TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Save body/face/hand keypoints to JSON file + const auto& tDatumFirstPtr = (*tDatums)[0]; + const auto baseFileName = (!tDatumFirstPtr->name.empty() ? tDatumFirstPtr->name + : std::to_string(tDatumFirstPtr->id)) + "_keypoints"; + const bool humanReadable = false; + for (auto i = 0u ; i < tDatums->size() ; i++) + { + const auto& tDatumPtr = (*tDatums)[i]; + // const auto fileName = baseFileName; + const auto fileName = baseFileName + (i != 0 ? "_" + std::to_string(i) : ""); + + // Pose IDs from long long to float + Array poseIds{tDatumPtr->poseIds}; + + const std::vector, std::string>> keypointVector{ + // Pose IDs + std::make_pair(poseIds, "person_id"), + // 2D + std::make_pair(tDatumPtr->poseKeypoints, "pose_keypoints_2d"), + std::make_pair(tDatumPtr->faceKeypoints, "face_keypoints_2d"), + std::make_pair(tDatumPtr->handKeypoints[0], "hand_left_keypoints_2d"), + std::make_pair(tDatumPtr->handKeypoints[1], "hand_right_keypoints_2d"), + // 3D + std::make_pair(tDatumPtr->poseKeypoints3D, "pose_keypoints_3d"), + std::make_pair(tDatumPtr->faceKeypoints3D, "face_keypoints_3d"), + std::make_pair(tDatumPtr->handKeypoints3D[0], "hand_left_keypoints_3d"), + std::make_pair(tDatumPtr->handKeypoints3D[1], "hand_right_keypoints_3d") + }; + // Save keypoints + spPeopleJsonSaver->save( + keypointVector, tDatumPtr->poseCandidates, fileName, humanReadable); + } + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WPeopleJsonSaver); +} + +#endif // OPENPOSE_FILESTREAM_W_PEOPLE_JSON_SAVER_HPP diff --git a/openpose/include/openpose/filestream/wPoseSaver.hpp b/openpose/include/openpose/filestream/wPoseSaver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..efeeaeb723cffcb2e5b772a6ca41904f8600c376 --- /dev/null +++ b/openpose/include/openpose/filestream/wPoseSaver.hpp @@ -0,0 +1,91 @@ +#ifndef OPENPOSE_FILESTREAM_W_POSE_SAVER_HPP +#define OPENPOSE_FILESTREAM_W_POSE_SAVER_HPP + +#include +#include +#include +#include + +namespace op +{ + template + class WPoseSaver : public WorkerConsumer + { + public: + explicit WPoseSaver(const std::shared_ptr& keypointSaver); + + virtual ~WPoseSaver(); + + void initializationOnThread(); + + void workConsumer(const TDatums& tDatums); + + private: + const std::shared_ptr spKeypointSaver; + + DELETE_COPY(WPoseSaver); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WPoseSaver::WPoseSaver(const std::shared_ptr& keypointSaver) : + spKeypointSaver{keypointSaver} + { + } + + template + WPoseSaver::~WPoseSaver() + { + } + + template + void WPoseSaver::initializationOnThread() + { + } + + template + void WPoseSaver::workConsumer(const TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // T* to T + auto& tDatumsNoPtr = *tDatums; + // Record people pose keypoint data + std::vector> keypointVector(tDatumsNoPtr.size()); + for (auto i = 0u; i < tDatumsNoPtr.size(); i++) + keypointVector[i] = tDatumsNoPtr[i]->poseKeypoints; + const auto fileName = (!tDatumsNoPtr[0]->name.empty() + ? tDatumsNoPtr[0]->name : std::to_string(tDatumsNoPtr[0]->id)); + spKeypointSaver->saveKeypoints(keypointVector, fileName, "pose"); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WPoseSaver); +} + +#endif // OPENPOSE_FILESTREAM_W_POSE_SAVER_HPP diff --git a/openpose/include/openpose/filestream/wUdpSender.hpp b/openpose/include/openpose/filestream/wUdpSender.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5f88c152eb7e9f698592f019b9c8fee8deca9226 --- /dev/null +++ b/openpose/include/openpose/filestream/wUdpSender.hpp @@ -0,0 +1,103 @@ +#ifndef OPENPOSE_FILESTREAM_W_UDP_SENDER_HPP +#define OPENPOSE_FILESTREAM_W_UDP_SENDER_HPP + +#include +#include +#include + +namespace op +{ + template + class WUdpSender : public WorkerConsumer + { + public: + explicit WUdpSender(const std::shared_ptr& udpSender); + + virtual ~WUdpSender(); + + void initializationOnThread(); + + void workConsumer(const TDatums& tDatums); + + private: + const std::shared_ptr spUdpSender; + + DELETE_COPY(WUdpSender); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WUdpSender::WUdpSender(const std::shared_ptr& udpSender) : + spUdpSender{udpSender} + { + } + + template + WUdpSender::~WUdpSender() + { + } + + template + void WUdpSender::initializationOnThread() + { + } + + template + void WUdpSender::workConsumer(const TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Send though UDP communication +#ifdef USE_3D_ADAM_MODEL + const auto& tDatumPtr = (*tDatums)[0]; + if (!tDatumPtr->poseKeypoints3D.empty()) + { + const auto& adamPose = tDatumPtr->adamPose; // Eigen::Matrix + const auto& adamTranslation = tDatumPtr->adamTranslation; // Eigen::Vector3d(3, 1) + const auto adamFaceCoeffsExp = tDatumPtr->adamFaceCoeffsExp; // Eigen::VectorXd resized to (200, 1) + //const float mouth_open = tDatumPtr->mouthOpening; // tDatumPtr->mouth_open; + //const float leye_open = tDatumPtr->rightEyeOpening; // tDatumPtr->leye_open; + //const float reye_open = tDatumPtr->leftEyeOpening; // tDatumPtr->reye_open; + //const float dist_root_foot = Datum.distanceRootFoot; // tDatumPtr->dist_root_foot; + // m_adam_t: + // 1. Total translation (centimeters) of the root in camera/global coordinate representation. + // m_adam_pose: + // 1. First row is global rotation, in AngleAxis representation. Radians (not degrees!) + // 2. Rest are joint-angles in Euler-Angle representation. Degrees. + spUdpSender->sendJointAngles( + adamPose.data(), adamPose.rows(), adamTranslation.data(), adamFaceCoeffsExp.data(), + adamFaceCoeffsExp.rows()); + } +#endif + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WUdpSender); +} + +#endif // OPENPOSE_FILESTREAM_W_UDP_SENDER_HPP diff --git a/openpose/include/openpose/filestream/wVideoSaver.hpp b/openpose/include/openpose/filestream/wVideoSaver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d8a43098f409407919e92eaf49880e3dec740c0b --- /dev/null +++ b/openpose/include/openpose/filestream/wVideoSaver.hpp @@ -0,0 +1,88 @@ +#ifndef OPENPOSE_FILESTREAM_W_VIDEO_SAVER_HPP +#define OPENPOSE_FILESTREAM_W_VIDEO_SAVER_HPP + +#include +#include +#include + +namespace op +{ + template + class WVideoSaver : public WorkerConsumer + { + public: + explicit WVideoSaver(const std::shared_ptr& videoSaver); + + virtual ~WVideoSaver(); + + void initializationOnThread(); + + void workConsumer(const TDatums& tDatums); + + private: + std::shared_ptr spVideoSaver; + + DELETE_COPY(WVideoSaver); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WVideoSaver::WVideoSaver(const std::shared_ptr& videoSaver) : + spVideoSaver{videoSaver} + { + } + + template + WVideoSaver::~WVideoSaver() + { + } + + template + void WVideoSaver::initializationOnThread() + { + } + + template + void WVideoSaver::workConsumer(const TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // T* to T + auto& tDatumsNoPtr = *tDatums; + // Record video(s) + std::vector opOutputDatas(tDatumsNoPtr.size()); + for (auto i = 0u ; i < opOutputDatas.size() ; i++) + opOutputDatas[i] = tDatumsNoPtr[i]->cvOutputData; + spVideoSaver->write(opOutputDatas); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WVideoSaver); +} + +#endif // OPENPOSE_FILESTREAM_W_VIDEO_SAVER_HPP diff --git a/openpose/include/openpose/filestream/wVideoSaver3D.hpp b/openpose/include/openpose/filestream/wVideoSaver3D.hpp new file mode 100644 index 0000000000000000000000000000000000000000..58d32634b0101de54e95ae391e95d7dad4fea02b --- /dev/null +++ b/openpose/include/openpose/filestream/wVideoSaver3D.hpp @@ -0,0 +1,86 @@ +#ifndef OPENPOSE_FILESTREAM_W_VIDEO_SAVER_3D_HPP +#define OPENPOSE_FILESTREAM_W_VIDEO_SAVER_3D_HPP + +#include +#include +#include + +namespace op +{ + template + class WVideoSaver3D : public WorkerConsumer + { + public: + explicit WVideoSaver3D(const std::shared_ptr& videoSaver); + + virtual ~WVideoSaver3D(); + + void initializationOnThread(); + + void workConsumer(const TDatums& tDatums); + + private: + std::shared_ptr spVideoSaver; + + DELETE_COPY(WVideoSaver3D); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WVideoSaver3D::WVideoSaver3D(const std::shared_ptr& videoSaver) : + spVideoSaver{videoSaver} + { + } + + template + WVideoSaver3D::~WVideoSaver3D() + { + } + + template + void WVideoSaver3D::initializationOnThread() + { + } + + template + void WVideoSaver3D::workConsumer(const TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // T* to T + auto& tDatumsNoPtr = *tDatums; + // Record video(s) + if (!tDatumsNoPtr.empty()) + spVideoSaver->write(tDatumsNoPtr[0]->cvOutputData3D); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WVideoSaver3D); +} + +#endif // OPENPOSE_FILESTREAM_W_VIDEO_SAVER_3D_HPP diff --git a/openpose/include/openpose/flags.hpp b/openpose/include/openpose/flags.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3f724e3b17e25b51f256985c33fbd2dc9ce125aa --- /dev/null +++ b/openpose/include/openpose/flags.hpp @@ -0,0 +1,280 @@ +#ifndef OPENPOSE_FLAGS_HPP +#define OPENPOSE_FLAGS_HPP + +// Note: This class is not included within the basic OpenPose `headers.hpp` and must be explicitly included. In +// addition, Google Flags library must also be linked to the resulting binary or library. OpenPose library does +// not force to use Google Flags, but the OpenPose examples do so. + +// GFlags: DEFINE_bool, _int32, _int64, _uint64, _double, _string +#include +// Allow Google Flags in Ubuntu 14 +#ifndef GFLAGS_GFLAGS_H_ + namespace gflags = google; +#endif + +// See all the available parameter options with the `--help` flag. E.g., `build/examples/openpose/openpose.bin --help` +// Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose +// executable. E.g., for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. +// Debugging/Other +DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any opLog() message," + " while 255 will not output any. Current OpenPose library messages are in the range 0-4:" + " 1 for low priority messages and 4 for important ones."); +DEFINE_bool(disable_multi_thread, false, "It would slightly reduce the frame rate in order to highly reduce the lag. Mainly useful" + " for 1) Cases where it is needed a low latency (e.g., webcam in real-time scenarios with" + " low-range GPU devices); and 2) Debugging OpenPose when it is crashing to locate the" + " error."); +DEFINE_int32(profile_speed, 1000, "If PROFILER_ENABLED was set in CMake or Makefile.config files, OpenPose will show some" + " runtime statistics at this frame number."); +#ifndef OPENPOSE_FLAGS_DISABLE_POSE +#ifndef OPENPOSE_FLAGS_DISABLE_PRODUCER +// Producer +DEFINE_int32(camera, -1, "The camera index for cv::VideoCapture. Integer in the range [0, 9]. Select a negative" + " number (by default), to auto-detect and open the first available camera."); +DEFINE_string(camera_resolution, "-1x-1", "Set the camera resolution (either `--camera` or `--flir_camera`). `-1x-1` will use the" + " default 1280x720 for `--camera`, or the maximum flir camera resolution available for" + " `--flir_camera`"); +DEFINE_string(video, "", "Use a video file instead of the camera. Use `examples/media/video.avi` for our default" + " example video."); +DEFINE_string(image_dir, "", "Process a directory of images. Use `examples/media/` for our default example folder with 20" + " images. Read all standard formats (jpg, png, bmp, etc.)."); +DEFINE_bool(flir_camera, false, "Whether to use FLIR (Point-Grey) stereo camera."); +DEFINE_int32(flir_camera_index, -1, "Select -1 (default) to run on all detected flir cameras at once. Otherwise, select the flir" + " camera index to run, where 0 corresponds to the detected flir camera with the lowest" + " serial number, and `n` to the `n`-th lowest serial number camera."); +DEFINE_string(ip_camera, "", "String with the IP camera URL. It supports protocols like RTSP and HTTP."); +DEFINE_uint64(frame_first, 0, "Start on desired frame number. Indexes are 0-based, i.e., the first frame has index 0."); +DEFINE_uint64(frame_step, 1, "Step or gap between processed frames. E.g., `--frame_step 5` would read and process frames" + " 0, 5, 10, etc.."); +DEFINE_uint64(frame_last, -1, "Finish on desired frame number. Select -1 to disable. Indexes are 0-based, e.g., if set to" + " 10, it will process 11 frames (0-10)."); +DEFINE_bool(frame_flip, false, "Flip/mirror each frame (e.g., for real time webcam demonstrations)."); +DEFINE_int32(frame_rotate, 0, "Rotate each frame, 4 possible values: 0, 90, 180, 270."); +DEFINE_bool(frames_repeat, false, "Repeat frames when finished."); +DEFINE_bool(process_real_time, false, "Enable to keep the original source frame rate (e.g., for video). If the processing time is" + " too long, it will skip frames. If it is too fast, it will slow it down."); +DEFINE_string(camera_parameter_path, "models/cameraParameters/flir/", "String with the folder where the camera parameters are located. If there" + " is only 1 XML file (for single video, webcam, or images from the same camera), you must" + " specify the whole XML file path (ending in .xml)."); +DEFINE_bool(frame_undistort, false, "If false (default), it will not undistort the image, if true, it will undistortionate them" + " based on the camera parameters found in `camera_parameter_path`"); +#endif // OPENPOSE_FLAGS_DISABLE_PRODUCER +// OpenPose +DEFINE_string(model_folder, "models/", "Folder path (absolute or relative) where the models (pose, face, ...) are located."); +DEFINE_string(prototxt_path, "", "The combination `--model_folder` + `--prototxt_path` represents the whole path to the" + " prototxt file. If empty, it will use the default OpenPose ProtoTxt file."); +DEFINE_string(caffemodel_path, "", "The combination `--model_folder` + `--caffemodel_path` represents the whole path to the" + " caffemodel file. If empty, it will use the default OpenPose CaffeModel file."); +DEFINE_string(output_resolution, "-1x-1", "The image resolution (display and output). Use \"-1x-1\" to force the program to use the" + " input image resolution."); +DEFINE_int32(num_gpu, -1, "The number of GPU devices to use. If negative, it will use all the available GPUs in your" + " machine."); +DEFINE_int32(num_gpu_start, 0, "GPU device start number."); +DEFINE_int32(keypoint_scale, 0, "Scaling of the (x,y) coordinates of the final pose data array, i.e., the scale of the (x,y)" + " coordinates that will be saved with the `write_json` & `write_keypoint` flags." + " Select `0` to scale it to the original source resolution; `1`to scale it to the net output" + " size (set with `net_resolution`); `2` to scale it to the final output size (set with" + " `resolution`); `3` to scale it in the range [0,1], where (0,0) would be the top-left" + " corner of the image, and (1,1) the bottom-right one; and 4 for range [-1,1], where" + " (-1,-1) would be the top-left corner of the image, and (1,1) the bottom-right one. Non" + " related with `scale_number` and `scale_gap`."); +DEFINE_int32(number_people_max, -1, "This parameter will limit the maximum number of people detected, by keeping the people with" + " top scores. The score is based in person area over the image, body part score, as well as" + " joint score (between each pair of connected body parts). Useful if you know the exact" + " number of people in the scene, so it can remove false positives (if all the people have" + " been detected. However, it might also include false negatives by removing very small or" + " highly occluded people. -1 will keep them all."); +DEFINE_bool(maximize_positives, false, "It reduces the thresholds to accept a person candidate. It highly increases both false and" + " true positives. I.e., it maximizes average recall but could harm average precision."); +DEFINE_double(fps_max, -1., "Maximum processing frame rate. By default (-1), OpenPose will process frames as fast as" + " possible. Example usage: If OpenPose is displaying images too quickly, this can reduce" + " the speed so the user can analyze better each frame from the GUI."); +// OpenPose Body Pose +DEFINE_int32(body, 1, "Select 0 to disable body keypoint detection (e.g., for faster but less accurate face" + " keypoint detection, custom hand detector, etc.), 1 (default) for body keypoint" + " estimation, and 2 to disable its internal body pose estimation network but still" + " still run the greedy association parsing algorithm"); +DEFINE_string(model_pose, "BODY_25", "Model to be used. E.g., `BODY_25` (fastest for CUDA version, most accurate, and includes" + " foot keypoints), `COCO` (18 keypoints), `MPI` (15 keypoints, least accurate model but" + " fastest on CPU), `MPI_4_layers` (15 keypoints, even faster but less accurate)."); +DEFINE_string(net_resolution, "-1x368", "Multiples of 16. If it is increased, the accuracy potentially increases. If it is" + " decreased, the speed increases. For maximum speed-accuracy balance, it should keep the" + " closest aspect ratio possible to the images or videos to be processed. Using `-1` in" + " any of the dimensions, OP will choose the optimal aspect ratio depending on the user's" + " input value. E.g., the default `-1x368` is equivalent to `656x368` in 16:9 resolutions," + " e.g., full HD (1980x1080) and HD (1280x720) resolutions."); +DEFINE_double(net_resolution_dynamic, 1., "This flag only applies to images or custom inputs (not to video or webcam). If it is zero" + " or a negative value, it means that using `-1` in `net_resolution` will behave as explained" + " in its description. Otherwise, and to avoid out of memory errors, the `-1` in" + " `net_resolution` will clip to this value times the default 16/9 aspect ratio value (which" + " is 656 width for a 368 height). E.g., `net_resolution_dynamic 10 net_resolution -1x368`" + " will clip to 6560x368 (10 x 656). Recommended 1 for small GPUs (to avoid out of memory" + " errors but maximize speed) and 0 for big GPUs (for maximum accuracy and speed)."); +DEFINE_int32(scale_number, 1, "Number of scales to average."); +DEFINE_double(scale_gap, 0.25, "Scale gap between scales. No effect unless scale_number > 1. Initial scale is always 1." + " If you want to change the initial scale, you actually want to multiply the" + " `net_resolution` by your desired initial scale."); +// OpenPose Body Pose Heatmaps and Part Candidates +DEFINE_bool(heatmaps_add_parts, false, "If true, it will fill op::Datum::poseHeatMaps array with the body part heatmaps, and" + " analogously face & hand heatmaps to op::Datum::faceHeatMaps & op::Datum::handHeatMaps." + " If more than one `add_heatmaps_X` flag is enabled, it will place then in sequential" + " memory order: body parts + bkg + PAFs. It will follow the order on" + " POSE_BODY_PART_MAPPING in `src/openpose/pose/poseParameters.cpp`. Program speed will" + " considerably decrease. Not required for OpenPose, enable it only if you intend to" + " explicitly use this information later."); +DEFINE_bool(heatmaps_add_bkg, false, "Same functionality as `add_heatmaps_parts`, but adding the heatmap corresponding to" + " background."); +DEFINE_bool(heatmaps_add_PAFs, false, "Same functionality as `add_heatmaps_parts`, but adding the PAFs."); +DEFINE_int32(heatmaps_scale, 2, "Set 0 to scale op::Datum::poseHeatMaps in the range [-1,1], 1 for [0,1]; 2 for integer" + " rounded [0,255]; and 3 for no scaling."); +DEFINE_bool(part_candidates, false, "Also enable `write_json` in order to save this information. If true, it will fill the" + " op::Datum::poseCandidates array with the body part candidates. Candidates refer to all" + " the detected body parts, before being assembled into people. Note that the number of" + " candidates is equal or higher than the number of final body parts (i.e., after being" + " assembled into people). The empty body parts are filled with 0s. Program speed will" + " slightly decrease. Not required for OpenPose, enable it only if you intend to explicitly" + " use this information."); +DEFINE_double(upsampling_ratio, 0., "Upsampling ratio between the `net_resolution` and the output net results. A value less" + " or equal than 0 (default) will use the network default value (recommended)."); +// OpenPose Face +DEFINE_bool(face, false, "Enables face keypoint detection. It will share some parameters from the body pose, e.g." + " `model_folder`. Note that this will considerable slow down the performance and increase" + " the required GPU memory. In addition, the greater number of people on the image, the" + " slower OpenPose will be."); +DEFINE_int32(face_detector, 0, "Kind of face rectangle detector. Select 0 (default) to select OpenPose body detector (most" + " accurate one and fastest one if body is enabled), 1 to select OpenCV face detector (not" + " implemented for hands), 2 to indicate that it will be provided by the user, or 3 to" + " also apply hand tracking (only for hand). Hand tracking might improve hand keypoint" + " detection for webcam (if the frame rate is high enough, i.e., >7 FPS per GPU) and video." + " This is not person ID tracking, it simply looks for hands in positions at which hands were" + " located in previous frames, but it does not guarantee the same person ID among frames."); +DEFINE_string(face_net_resolution, "368x368", "Multiples of 16 and squared. Analogous to `net_resolution` but applied to the face keypoint" + " detector. 320x320 usually works fine while giving a substantial speed up when multiple" + " faces on the image."); +// OpenPose Hand +DEFINE_bool(hand, false, "Enables hand keypoint detection. It will share some parameters from the body pose, e.g." + " `model_folder`. Analogously to `--face`, it will also slow down the performance, increase" + " the required GPU memory and its speed depends on the number of people."); +DEFINE_int32(hand_detector, 0, "Kind of hand rectangle detector. Analogous to `--face_detector`."); +DEFINE_string(hand_net_resolution, "368x368", "Multiples of 16 and squared. Analogous to `net_resolution` but applied to the hand keypoint" + " detector."); +DEFINE_int32(hand_scale_number, 1, "Analogous to `scale_number` but applied to the hand keypoint detector. Our best results" + " were found with `hand_scale_number` = 6 and `hand_scale_range` = 0.4."); +DEFINE_double(hand_scale_range, 0.4, "Analogous purpose than `scale_gap` but applied to the hand keypoint detector. Total range" + " between smallest and biggest scale. The scales will be centered in ratio 1. E.g., if" + " scaleRange = 0.4 and scalesNumber = 2, then there will be 2 scales, 0.8 and 1.2."); +// OpenPose 3-D Reconstruction +DEFINE_bool(3d, false, "Running OpenPose 3-D reconstruction demo: 1) Reading from a stereo camera system." + " 2) Performing 3-D reconstruction from the multiple views. 3) Displaying 3-D reconstruction" + " results. Note that it will only display 1 person. If multiple people is present, it will" + " fail."); +DEFINE_int32(3d_min_views, -1, "Minimum number of views required to reconstruct each keypoint. By default (-1), it will" + " require max(2, min(4, #cameras-1)) cameras to see the keypoint in order to reconstruct" + " it."); +DEFINE_int32(3d_views, -1, "Complementary option for `--image_dir` or `--video`. OpenPose will read as many images per" + " iteration, allowing tasks such as stereo camera processing (`--3d`). Note that" + " `--camera_parameter_path` must be set. OpenPose must find as many `xml` files in the" + " parameter folder as this number indicates."); +// Extra algorithms +DEFINE_bool(identification, false, "Experimental, not available yet. Whether to enable people identification across frames."); +DEFINE_int32(tracking, -1, "Experimental, not available yet. Whether to enable people tracking across frames. The" + " value indicates the number of frames where tracking is run between each OpenPose keypoint" + " detection. Select -1 (default) to disable it or 0 to run simultaneously OpenPose keypoint" + " detector and tracking for potentially higher accuracy than only OpenPose."); +DEFINE_int32(ik_threads, 0, "Experimental, not available yet. Whether to enable inverse kinematics (IK) from 3-D" + " keypoints to obtain 3-D joint angles. By default (0 threads), it is disabled. Increasing" + " the number of threads will increase the speed but also the global system latency."); +// OpenPose Rendering +DEFINE_int32(part_to_show, 0, "Prediction channel to visualize: 0 (default) for all the body parts, 1 for the background" + " heat map, 2 for the superposition of heatmaps, 3 for the superposition of PAFs," + " 4-(4+#keypoints) for each body part heat map, the following ones for each body part pair" + " PAF."); +DEFINE_bool(disable_blending, false, "If enabled, it will render the results (keypoint skeletons or heatmaps) on a black" + " background, instead of being rendered into the original image. Related: `part_to_show`," + " `alpha_pose`, and `alpha_pose`."); +// OpenPose Rendering Pose +DEFINE_double(render_threshold, 0.05, "Only estimated keypoints whose score confidences are higher than this threshold will be" + " rendered. Note: Rendered refers only to visual display in the OpenPose basic GUI, not in" + " the saved results. Generally, a high threshold (> 0.5) will only render very clear body" + " parts; while small thresholds (~0.1) will also output guessed and occluded keypoints," + " but also more false positives (i.e., wrong detections)."); +DEFINE_int32(render_pose, -1, "Set to 0 for no rendering, 1 for CPU rendering (slightly faster), and 2 for GPU rendering" + " (slower but greater functionality, e.g., `alpha_X` flags). If -1, it will pick CPU if" + " CPU_ONLY is enabled, or GPU if CUDA is enabled. If rendering is enabled, it will render" + " both `outputData` and `cvOutputData` with the original image and desired body part to be" + " shown (i.e., keypoints, heat maps or PAFs)."); +DEFINE_double(alpha_pose, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will" + " hide it. Only valid for GPU rendering."); +DEFINE_double(alpha_heatmap, 0.7, "Blending factor (range 0-1) between heatmap and original frame. 1 will only show the" + " heatmap, 0 will only show the frame. Only valid for GPU rendering."); +// OpenPose Rendering Face +DEFINE_double(face_render_threshold, 0.4, "Analogous to `render_threshold`, but applied to the face keypoints."); +DEFINE_int32(face_render, -1, "Analogous to `render_pose` but applied to the face. Extra option: -1 to use the same" + " configuration that `render_pose` is using."); +DEFINE_double(face_alpha_pose, 0.6, "Analogous to `alpha_pose` but applied to face."); +DEFINE_double(face_alpha_heatmap, 0.7, "Analogous to `alpha_heatmap` but applied to face."); +// OpenPose Rendering Hand +DEFINE_double(hand_render_threshold, 0.2, "Analogous to `render_threshold`, but applied to the hand keypoints."); +DEFINE_int32(hand_render, -1, "Analogous to `render_pose` but applied to the hand. Extra option: -1 to use the same" + " configuration that `render_pose` is using."); +DEFINE_double(hand_alpha_pose, 0.6, "Analogous to `alpha_pose` but applied to hand."); +DEFINE_double(hand_alpha_heatmap, 0.7, "Analogous to `alpha_heatmap` but applied to hand."); +#ifndef OPENPOSE_FLAGS_DISABLE_DISPLAY +// Display +DEFINE_bool(fullscreen, false, "Run in full-screen mode (press f during runtime to toggle)."); +DEFINE_bool(no_gui_verbose, false, "Do not write text on output images on GUI (e.g., number of current frame and people). It" + " does not affect the pose rendering."); +DEFINE_int32(display, -1, "Display mode: -1 for automatic selection; 0 for no display (useful if there is no X server" + " and/or to slightly speed up the processing if visual output is not required); 2 for 2-D" + " display; 3 for 3-D display (if `--3d` enabled); and 1 for both 2-D and 3-D display."); +#endif // OPENPOSE_FLAGS_DISABLE_DISPLAY +// Command Line Interface Verbose +DEFINE_double(cli_verbose, -1.f, "If -1, it will be disabled (default). If it is a positive integer number, it will print on" + " the command line every `verbose` frames. If number in the range (0,1), it will print the" + " progress every `verbose` times the total of frames."); +// Result Saving +DEFINE_string(write_images, "", "Directory to write rendered frames in `write_images_format` image format."); +DEFINE_string(write_images_format, "png", "File extension and format for `write_images`, e.g., png, jpg or bmp. Check the OpenCV" + " function cv::imwrite for all compatible extensions."); +DEFINE_string(write_video, "", "Full file path to write rendered frames in motion JPEG video format. It might fail if the" + " final path does not finish in `.avi`. It internally uses cv::VideoWriter. Flag" + " `write_video_fps` controls FPS. Alternatively, the video extension can be `.mp4`," + " resulting in a file with a much smaller size and allowing `--write_video_with_audio`." + " However, that would require: 1) Ubuntu or Mac system, 2) FFmpeg library installed" + " (`sudo apt-get install ffmpeg`), 3) the creation temporarily of a folder with the same" + " file path than the final video (without the extension) to storage the intermediate frames" + " that will later be used to generate the final MP4 video."); +DEFINE_double(write_video_fps, -1., "Frame rate for the recorded video. By default, it will try to get the input frames producer" + " frame rate (e.g., input video or webcam frame rate). If the input frames producer does not" + " have a set FPS (e.g., image_dir or webcam if OpenCV not compiled with its support), set" + " this value accordingly (e.g., to the frame rate displayed by the OpenPose GUI)."); +DEFINE_bool(write_video_with_audio, false, "If the input is video and the output is so too, it will save the video with audio. It" + " requires the output video file path finishing in `.mp4` format (see `write_video` for" + " details)."); +DEFINE_string(write_video_3d, "", "Analogous to `--write_video`, but applied to the 3D output."); +DEFINE_string(write_video_adam, "", "Experimental, not available yet. Analogous to `--write_video`, but applied to Adam model."); +DEFINE_string(write_json, "", "Directory to write OpenPose output in JSON format. It includes body, hand, and face pose" + " keypoints (2-D and 3-D), as well as pose candidates (if `--part_candidates` enabled)."); +DEFINE_string(write_coco_json, "", "Full file path to write people pose data with JSON COCO validation format. If foot, face," + " hands, etc. JSON is also desired (`--write_coco_json_variants`), they are saved with" + " different file name suffix."); +DEFINE_int32(write_coco_json_variants, 1, "Add 1 for body, add 2 for foot, 4 for face, and/or 8 for hands. Use 0 to use all the" + " possible candidates. E.g., 7 would mean body+foot+face COCO JSON."); +DEFINE_int32(write_coco_json_variant, 0, "Currently, this option is experimental and only makes effect on car JSON generation. It" + " selects the COCO variant for cocoJsonSaver."); +DEFINE_string(write_heatmaps, "", "Directory to write body pose heatmaps in PNG format. At least 1 `add_heatmaps_X` flag" + " must be enabled."); +DEFINE_string(write_heatmaps_format, "png", "File extension and format for `write_heatmaps`, analogous to `write_images_format`." + " For lossless compression, recommended `png` for integer `heatmaps_scale` and `float` for" + " floating values. See `doc/02_output.md` for more details."); +DEFINE_string(write_keypoint, "", "(Deprecated, use `write_json`) Directory to write the people pose keypoint data. Set format" + " with `write_keypoint_format`."); +DEFINE_string(write_keypoint_format, "yml", "(Deprecated, use `write_json`) File extension and format for `write_keypoint`: json, xml," + " yaml & yml. Json not available for OpenCV < 3.0, use `write_json` instead."); +// Result Saving - Extra Algorithms +DEFINE_string(write_bvh, "", "Experimental, not available yet. E.g., `~/Desktop/mocapResult.bvh`."); +// UDP Communication +DEFINE_string(udp_host, "", "Experimental, not available yet. IP for UDP communication. E.g., `192.168.0.1`."); +DEFINE_string(udp_port, "8051", "Experimental, not available yet. Port number for UDP communication."); +#endif // OPENPOSE_FLAGS_DISABLE_POSE + +#endif // OPENPOSE_FLAGS_HPP diff --git a/openpose/include/openpose/gpu/cuda.hpp b/openpose/include/openpose/gpu/cuda.hpp new file mode 100644 index 0000000000000000000000000000000000000000..50aad8cf95f48e9c6c16f87bc2378d29de9c3478 --- /dev/null +++ b/openpose/include/openpose/gpu/cuda.hpp @@ -0,0 +1,32 @@ +#ifndef OPENPOSE_GPU_CUDA_HPP +#define OPENPOSE_GPU_CUDA_HPP + +#include // std::pair +#include + +namespace op +{ + const auto CUDA_NUM_THREADS = 512u; + + OP_API void cudaCheck(const int line = -1, const std::string& function = "", const std::string& file = ""); + + OP_API int getCudaGpuNumber(); + + inline unsigned int getNumberCudaBlocks( + const unsigned int totalRequired, const unsigned int numberCudaThreads = CUDA_NUM_THREADS) + { + return (totalRequired + numberCudaThreads - 1) / numberCudaThreads; + } + + OP_API void getNumberCudaThreadsAndBlocks( + dim3& numberCudaThreads, dim3& numberCudaBlocks, const Point& frameSize); + + template + void reorderAndNormalize( + T* targetPtr, const unsigned char* const srcPtr, const int width, const int height, const int channels); + + template + void uCharImageCast(unsigned char* targetPtr, const T* const srcPtr, const int volume); +} + +#endif // OPENPOSE_GPU_CUDA_HPP diff --git a/openpose/include/openpose/gpu/enumClasses.hpp b/openpose/include/openpose/gpu/enumClasses.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d94b2296f7d0300a94d7ac6e051f950462aa65e7 --- /dev/null +++ b/openpose/include/openpose/gpu/enumClasses.hpp @@ -0,0 +1,15 @@ +#ifndef OPENPOSE_GPU_ENUM_CLASSES_HPP +#define OPENPOSE_GPU_ENUM_CLASSES_HPP + +namespace op +{ + enum class GpuMode : unsigned char + { + Cuda = 0, + OpenCL = 1, + NoGpu = 2, + Size, + }; +} + +#endif // OPENPOSE_GPU_ENUM_CLASSES_HPP diff --git a/openpose/include/openpose/gpu/gpu.hpp b/openpose/include/openpose/gpu/gpu.hpp new file mode 100644 index 0000000000000000000000000000000000000000..76c655681d84d6f78f7d61f010451407c143ca7c --- /dev/null +++ b/openpose/include/openpose/gpu/gpu.hpp @@ -0,0 +1,14 @@ +#ifndef OPENPOSE_GPU_GPU_HPP +#define OPENPOSE_GPU_GPU_HPP + +#include +#include + +namespace op +{ + OP_API int getGpuNumber(); + + OP_API GpuMode getGpuMode(); +} + +#endif // OPENPOSE_GPU_GPU_HPP diff --git a/openpose/include/openpose/gpu/headers.hpp b/openpose/include/openpose/gpu/headers.hpp new file mode 100644 index 0000000000000000000000000000000000000000..08f4b8531f2a589c8084ffff378b8cc680c3b8ad --- /dev/null +++ b/openpose/include/openpose/gpu/headers.hpp @@ -0,0 +1,9 @@ +#ifndef OPENPOSE_GPU_HEADERS_HPP +#define OPENPOSE_GPU_HEADERS_HPP + +// gpu module +#include +#include +#include + +#endif // OPENPOSE_GPU_HEADERS_HPP diff --git a/openpose/include/openpose/gui/enumClasses.hpp b/openpose/include/openpose/gui/enumClasses.hpp new file mode 100644 index 0000000000000000000000000000000000000000..924bc0c29281eaeae73203c0ad67accace6564d2 --- /dev/null +++ b/openpose/include/openpose/gui/enumClasses.hpp @@ -0,0 +1,30 @@ +#ifndef OPENPOSE_GUI_ENUM_CLASSES_HPP +#define OPENPOSE_GUI_ENUM_CLASSES_HPP + +namespace op +{ + /** + * GUI display modes. + * An enum class with the different output screen options. E.g., 2-D, 3-D, all, none. + */ + enum class DisplayMode : unsigned short + { + NoDisplay, /**< No display. */ + DisplayAll, /**< All (2-D and 3-D/Adam) displays */ + Display2D, /**< Only 2-D display. */ + Display3D, /**< Only 3-D display. */ + DisplayAdam /**< Only Adam display. */ + }; + + /** + * Full screen modes. + * An enum class with the different full screen mode options, i.e., full screen or windored. + */ + enum class FullScreenMode : bool + { + FullScreen, /**< Full screen mode. */ + Windowed, /**< Windowed mode, depending on the frame output size. */ + }; +} + +#endif // OPENPOSE_GUI_ENUM_CLASSES_HPP diff --git a/openpose/include/openpose/gui/frameDisplayer.hpp b/openpose/include/openpose/gui/frameDisplayer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e5347bd11d72c09406cf52e2441f0a22ef9ac938 --- /dev/null +++ b/openpose/include/openpose/gui/frameDisplayer.hpp @@ -0,0 +1,65 @@ +#ifndef OPENPOSE_GUI_FRAMES_DISPLAY_HPP +#define OPENPOSE_GUI_FRAMES_DISPLAY_HPP + +#include +#include + +namespace op +{ + /** + * The FrameDisplayer class is the one presenting visually the processed frame to the user. + */ + class OP_API FrameDisplayer + { + public: + /** + * Constructor of the FrameDisplayer class. + * @param windowedName const std::string value with the opencv resulting display name. Showed at the top-left + * part of the window. + * @param initialWindowedSize const Point with the initial window output resolution (width and height). + * @param fullScreen bool from which the FrameDisplayer::FullScreenMode property mFullScreenMode will be set, + * i.e., specifying the type of initial display (it can be changed later). + */ + FrameDisplayer(const std::string& windowedName = OPEN_POSE_NAME_AND_VERSION, + const Point& initialWindowedSize = Point{}, const bool fullScreen = false); + + virtual ~FrameDisplayer(); + + // Due to OpenCV visualization issues (all visualization functions must be in the same thread) + void initializationOnThread(); + + /** + * This function set the new FrameDisplayer::FullScreenMode (e.g., full screen). + * @param fullScreenMode New FrameDisplayer::FullScreenMode state. + */ + void setFullScreenMode(const FullScreenMode fullScreenMode); + + /** + * This function switch between full screen and windowed modes (e.g., when double-click on video players or + * Ctrt+Enter are presed). + */ + void switchFullScreenMode(); + + /** + * This function displays an image on the display. + * @param frame Mat image to display. + * @param waitKeyValue int value that specifies the argument parameter for cv::waitKey (see OpenCV + * documentation for more information). Special cases: select -1 + * not to use cv::waitKey or 0 for cv::waitKey(0). OpenCV doc: + * http://docs.opencv.org/2.4/modules/highgui/doc/user_interface.html?highlight=waitkey + */ + void displayFrame(const Matrix& frame, const int waitKeyValue = -1); + + /** + * Analogous to the previous displayFrame, but first it horizontally concatenates all the frames + */ + void displayFrame(const std::vector& frames, const int waitKeyValue = -1); + + private: + const std::string mWindowName; + Point mWindowedSize; + FullScreenMode mFullScreenMode; + }; +} + +#endif // OPENPOSE_GUI_FRAMES_DISPLAY_HPP diff --git a/openpose/include/openpose/gui/gui.hpp b/openpose/include/openpose/gui/gui.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2f3aa050fb87a98ed94e09479bc84e786f56f347 --- /dev/null +++ b/openpose/include/openpose/gui/gui.hpp @@ -0,0 +1,53 @@ +#ifndef OPENPOSE_GUI_GUI_HPP +#define OPENPOSE_GUI_GUI_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace op +{ + class OP_API Gui + { + public: + Gui(const Point& outputSize, const bool fullScreen, + const std::shared_ptr>& isRunningSharedPtr, + const std::shared_ptr, std::atomic>>& videoSeekSharedPtr = nullptr, + const std::vector>& poseExtractorNets = {}, + const std::vector>& faceExtractorNets = {}, + const std::vector>& handExtractorNets = {}, + const std::vector>& renderers = {}, + const DisplayMode displayMode = DisplayMode::Display2D); + + virtual ~Gui(); + + virtual void initializationOnThread(); + + void setImage(const Matrix& cvMatOutput); + + void setImage(const std::vector& cvMatOutputs); + + virtual void update(); + + protected: + std::shared_ptr> spIsRunning; + DisplayMode mDisplayMode; + DisplayMode mDisplayModeOriginal; + + private: + // Frames display + FrameDisplayer mFrameDisplayer; + // Other variables + std::vector> mPoseExtractorNets; + std::vector> mFaceExtractorNets; + std::vector> mHandExtractorNets; + std::vector> mRenderers; + std::shared_ptr, std::atomic>> spVideoSeek; + }; +} + +#endif // OPENPOSE_GUI_GUI_HPP diff --git a/openpose/include/openpose/gui/gui3D.hpp b/openpose/include/openpose/gui/gui3D.hpp new file mode 100644 index 0000000000000000000000000000000000000000..61a2c4b4130c9633641e1aa1a09894adb6f28a85 --- /dev/null +++ b/openpose/include/openpose/gui/gui3D.hpp @@ -0,0 +1,42 @@ +#ifndef OPENPOSE_GUI_GUI_3D_HPP +#define OPENPOSE_GUI_GUI_3D_HPP + +#include +#include +#include +#include +#include + +namespace op +{ + class OP_API Gui3D : public Gui + { + public: + Gui3D(const Point& outputSize, const bool fullScreen, + const std::shared_ptr>& isRunningSharedPtr, + const std::shared_ptr, std::atomic>>& videoSeekSharedPtr = nullptr, + const std::vector>& poseExtractorNets = {}, + const std::vector>& faceExtractorNets = {}, + const std::vector>& handExtractorNets = {}, + const std::vector>& renderers = {}, + const PoseModel poseModel = PoseModel::BODY_25, + const DisplayMode displayMode = DisplayMode::DisplayAll, + const bool copyGlToCvMat = false); + + virtual ~Gui3D(); + + virtual void initializationOnThread(); + + void setKeypoints(const Array& poseKeypoints3D, const Array& faceKeypoints3D, + const Array& leftHandKeypoints3D, const Array& rightHandKeypoints3D); + + virtual void update(); + + virtual Matrix readCvMat(); + + private: + const bool mCopyGlToCvMat; + }; +} + +#endif // OPENPOSE_GUI_GUI_3D_HPP diff --git a/openpose/include/openpose/gui/guiAdam.hpp b/openpose/include/openpose/gui/guiAdam.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0fce51efc3e1bb0f2f030fbd9fbb52feca6c6ca1 --- /dev/null +++ b/openpose/include/openpose/gui/guiAdam.hpp @@ -0,0 +1,56 @@ +#ifdef USE_3D_ADAM_MODEL +#ifndef OPENPOSE_GUI_GUI_ADAM_HPP +#define OPENPOSE_GUI_GUI_ADAM_HPP + +#ifdef USE_3D_ADAM_MODEL + #include +#endif +#include +#include +#include + +namespace op +{ + // This worker will do 3-D rendering + class OP_API GuiAdam : public Gui + { + public: + GuiAdam(const Point& outputSize, const bool fullScreen, + const std::shared_ptr>& isRunningSharedPtr, + const std::shared_ptr, std::atomic>>& videoSeekSharedPtr = nullptr, + const std::vector>& poseExtractorNets = {}, + const std::vector>& faceExtractorNets = {}, + const std::vector>& handExtractorNets = {}, + const std::vector>& renderers = {}, + const DisplayMode displayMode = DisplayMode::DisplayAll, + const std::shared_ptr& totalModel = nullptr, + const std::string& adamRenderedVideoPath = ""); + + virtual ~GuiAdam(); + + virtual void initializationOnThread(); + + void generateMesh(const Array& poseKeypoints3D, const Array& faceKeypoints3D, + const std::array, 2>& handKeypoints3D, + const double* const adamPosePtr, + const double* const adamTranslationPtr, + const double* const vtVecPtr, const int vtVecRows, + const double* const j0VecPtr, const int j0VecRows, + const double* const adamFaceCoeffsExpPtr); + + virtual void update(); + + private: + // PIMPL idiom + // http://www.cppsamples.com/common-tasks/pimpl.html + struct ImplGuiAdam; + std::shared_ptr spImpl; + + // PIMP requires DELETE_COPY & destructor, or extra code + // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html + DELETE_COPY(GuiAdam); + }; +} + +#endif // OPENPOSE_GUI_GUI_ADAM_HPP +#endif diff --git a/openpose/include/openpose/gui/guiInfoAdder.hpp b/openpose/include/openpose/gui/guiInfoAdder.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f03e80fa517030fc4bbc0ebdb9106f2d9889c100 --- /dev/null +++ b/openpose/include/openpose/gui/guiInfoAdder.hpp @@ -0,0 +1,35 @@ +#ifndef OPENPOSE_GUI_ADD_GUI_INFO_HPP +#define OPENPOSE_GUI_ADD_GUI_INFO_HPP + +#include +#include + +namespace op +{ + class OP_API GuiInfoAdder + { + public: + GuiInfoAdder(const int numberGpus, const bool guiEnabled = false); + + virtual ~GuiInfoAdder(); + + void addInfo(Matrix& outputData, const int numberPeople, const unsigned long long id, + const std::string& elementRenderedName, const unsigned long long frameNumber, + const Array& poseIds = Array{}, + const Array& poseKeypoints = Array{}); + + private: + // Const variables + const int mNumberGpus; + const bool mGuiEnabled; + // Other variables + std::queue mFpsQueue; + double mFps; + unsigned int mFpsCounter; + std::string mLastElementRenderedName; + int mLastElementRenderedCounter; + unsigned long long mLastId; + }; +} + +#endif // OPENPOSE_GUI_ADD_GUI_INFO_HPP diff --git a/openpose/include/openpose/gui/headers.hpp b/openpose/include/openpose/gui/headers.hpp new file mode 100644 index 0000000000000000000000000000000000000000..257889c487de2f531904c117726cb933df039a21 --- /dev/null +++ b/openpose/include/openpose/gui/headers.hpp @@ -0,0 +1,16 @@ +#ifndef OPENPOSE_GUI_HEADERS_HPP +#define OPENPOSE_GUI_HEADERS_HPP + +// gui module +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // OPENPOSE_GUI_HEADERS_HPP diff --git a/openpose/include/openpose/gui/wGui.hpp b/openpose/include/openpose/gui/wGui.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7c847cc7ffad923b508f2007f133440ccea3ce58 --- /dev/null +++ b/openpose/include/openpose/gui/wGui.hpp @@ -0,0 +1,103 @@ +#ifndef OPENPOSE_GUI_W_GUI_HPP +#define OPENPOSE_GUI_W_GUI_HPP + +#include +#include +#include + +namespace op +{ + template + class WGui : public WorkerConsumer + { + public: + explicit WGui(const std::shared_ptr& gui); + + virtual ~WGui(); + + void initializationOnThread(); + + void workConsumer(const TDatums& tDatums); + + private: + std::shared_ptr spGui; + + DELETE_COPY(WGui); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WGui::WGui(const std::shared_ptr& gui) : + spGui{gui} + { + } + + template + WGui::~WGui() + { + } + + template + void WGui::initializationOnThread() + { + try + { + spGui->initializationOnThread(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WGui::workConsumer(const TDatums& tDatums) + { + try + { + // tDatums might be empty but we still wanna update the GUI + if (tDatums != nullptr) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Update cvMat + if (!tDatums->empty()) + { + std::vector cvOutputDatas; + for (auto& tDatumPtr : *tDatums) + cvOutputDatas.emplace_back(tDatumPtr->cvOutputData); + spGui->setImage(cvOutputDatas); + } + // Refresh/update GUI + spGui->update(); + // Profiling speed + if (!tDatums->empty()) + { + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + } + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WGui); +} + +#endif // OPENPOSE_GUI_W_GUI_HPP diff --git a/openpose/include/openpose/gui/wGui3D.hpp b/openpose/include/openpose/gui/wGui3D.hpp new file mode 100644 index 0000000000000000000000000000000000000000..654579ae47404e9dbb793ad69e1d827866e8d8fd --- /dev/null +++ b/openpose/include/openpose/gui/wGui3D.hpp @@ -0,0 +1,116 @@ +#ifndef OPENPOSE_GUI_W_GUI_3D_HPP +#define OPENPOSE_GUI_W_GUI_3D_HPP + +#include +#include +#include + +namespace op +{ + // This worker will do 3-D rendering + template + class WGui3D : public WorkerConsumer + { + public: + explicit WGui3D(const std::shared_ptr& gui3D); + + virtual ~WGui3D(); + + void initializationOnThread(); + + void workConsumer(const TDatums& tDatums); + + private: + std::shared_ptr spGui3D; + + DELETE_COPY(WGui3D); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WGui3D::WGui3D(const std::shared_ptr& gui3D) : + spGui3D{gui3D} + { + } + + template + WGui3D::~WGui3D() + { + } + + template + void WGui3D::initializationOnThread() + { + try + { + spGui3D->initializationOnThread(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WGui3D::workConsumer(const TDatums& tDatums) + { + try + { + // tDatums might be empty but we still wanna update the GUI + if (tDatums != nullptr) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Update cvMat & keypoints + if (!tDatums->empty()) + { + // Update cvMat + std::vector cvOutputDatas; + for (auto& tDatumPtr : *tDatums) + cvOutputDatas.emplace_back(tDatumPtr->cvOutputData); + spGui3D->setImage(cvOutputDatas); + // Update keypoints + auto& tDatumPtr = (*tDatums)[0]; + spGui3D->setKeypoints( + tDatumPtr->poseKeypoints3D, tDatumPtr->faceKeypoints3D, tDatumPtr->handKeypoints3D[0], + tDatumPtr->handKeypoints3D[1]); + } + // Refresh/update GUI + spGui3D->update(); + // Read OpenCV mat equivalent + if (!tDatums->empty()) + { + auto& tDatumPtr = (*tDatums)[0]; + tDatumPtr->cvOutputData3D = spGui3D->readCvMat(); + } + // Profiling speed + if (!tDatums->empty()) + { + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + } + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WGui3D); +} + +#endif // OPENPOSE_GUI_W_GUI_3D_HPP diff --git a/openpose/include/openpose/gui/wGuiAdam.hpp b/openpose/include/openpose/gui/wGuiAdam.hpp new file mode 100644 index 0000000000000000000000000000000000000000..507579945fe76d9be390d9150948ac9a2e907155 --- /dev/null +++ b/openpose/include/openpose/gui/wGuiAdam.hpp @@ -0,0 +1,114 @@ +#ifdef USE_3D_ADAM_MODEL +#ifndef OPENPOSE_GUI_W_GUI_ADAM_HPP +#define OPENPOSE_GUI_W_GUI_ADAM_HPP + +#include +#include +#include + +namespace op +{ + template + class WGuiAdam : public WorkerConsumer + { + public: + explicit WGuiAdam(const std::shared_ptr& guiAdam); + + virtual ~WGuiAdam(); + + void initializationOnThread(); + + void workConsumer(const TDatums& tDatums); + + private: + std::shared_ptr spGuiAdam; + + DELETE_COPY(WGuiAdam); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WGuiAdam::WGuiAdam(const std::shared_ptr& guiAdam) : + spGuiAdam{guiAdam} + { + } + + template + WGuiAdam::~WGuiAdam() + { + } + + template + void WGuiAdam::initializationOnThread() + { + try + { + spGuiAdam->initializationOnThread(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WGuiAdam::workConsumer(const TDatums& tDatums) + { + try + { + // tDatums might be empty but we still wanna update the GUI + if (tDatums != nullptr) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Update cvMat & keypoints + if (!tDatums->empty()) + { + // Update cvMat + std::vector cvOutputDatas; + for (auto& tDatum : *tDatums) + cvOutputDatas.emplace_back(tDatumPtr->cvOutputData); + spGuiAdam->setImage(cvOutputDatas); + // Update keypoints + const auto& tDatumPtr = (*tDatums)[0]; + if (!tDatumPtr->poseKeypoints3D.empty()) + spGuiAdam->generateMesh( + tDatumPtr->poseKeypoints3D, tDatumPtr->faceKeypoints3D, tDatumPtr->handKeypoints3D, + tDatumPtr->adamPose.data(), tDatumPtr->adamTranslation.data(), tDatumPtr->vtVec.data(), + tDatumPtr->vtVec.rows(), tDatumPtr->j0Vec.data(), tDatumPtr->j0Vec.rows(), + tDatumPtr->adamFaceCoeffsExp.data()); + } + // Refresh/update GUI + spGuiAdam->update(); + // Profiling speed + if (!tDatums->empty()) + { + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + } + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WGuiAdam); +} + +#endif // OPENPOSE_GUI_W_GUI_ADAM_HPP +#endif diff --git a/openpose/include/openpose/gui/wGuiInfoAdder.hpp b/openpose/include/openpose/gui/wGuiInfoAdder.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f23e25e97e97da8a571c039092129066b875159c --- /dev/null +++ b/openpose/include/openpose/gui/wGuiInfoAdder.hpp @@ -0,0 +1,89 @@ +#ifndef OPENPOSE_GUI_W_ADD_GUI_INFO_HPP +#define OPENPOSE_GUI_W_ADD_GUI_INFO_HPP + +#include +#include +#include + +namespace op +{ + template + class WGuiInfoAdder : public Worker + { + public: + explicit WGuiInfoAdder(const std::shared_ptr& guiInfoAdder); + + virtual ~WGuiInfoAdder(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + std::shared_ptr spGuiInfoAdder; + + DELETE_COPY(WGuiInfoAdder); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WGuiInfoAdder::WGuiInfoAdder(const std::shared_ptr& guiInfoAdder) : + spGuiInfoAdder{guiInfoAdder} + { + } + + template + WGuiInfoAdder::~WGuiInfoAdder() + { + } + + template + void WGuiInfoAdder::initializationOnThread() + { + } + + template + void WGuiInfoAdder::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Add GUI components to frame + for (auto& tDatumPtr : *tDatums) + spGuiInfoAdder->addInfo( + tDatumPtr->cvOutputData, + std::max(tDatumPtr->poseKeypoints.getSize(0), tDatumPtr->faceKeypoints.getSize(0)), + tDatumPtr->id, tDatumPtr->elementRendered.second, tDatumPtr->frameNumber, + tDatumPtr->poseIds, tDatumPtr->poseKeypoints); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WGuiInfoAdder); +} + +#endif // OPENPOSE_GUI_W_ADD_GUI_INFO_HPP diff --git a/openpose/include/openpose/hand/handCpuRenderer.hpp b/openpose/include/openpose/hand/handCpuRenderer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a5140a0e06a27f25d7a9e26c87f809247b261e4d --- /dev/null +++ b/openpose/include/openpose/hand/handCpuRenderer.hpp @@ -0,0 +1,25 @@ +#ifndef OPENPOSE_HAND_HAND_CPU_RENDERER_HPP +#define OPENPOSE_HAND_HAND_CPU_RENDERER_HPP + +#include +#include +#include +#include + +namespace op +{ + class OP_API HandCpuRenderer : public Renderer, public HandRenderer + { + public: + HandCpuRenderer(const float renderThreshold, const float alphaKeypoint = HAND_DEFAULT_ALPHA_KEYPOINT, + const float alphaHeatMap = HAND_DEFAULT_ALPHA_HEAT_MAP); + + virtual ~HandCpuRenderer(); + + void renderHandInherited(Array& outputData, const std::array, 2>& handKeypoints); + + DELETE_COPY(HandCpuRenderer); + }; +} + +#endif // OPENPOSE_HAND_HAND_CPU_RENDERER_HPP diff --git a/openpose/include/openpose/hand/handDetector.hpp b/openpose/include/openpose/hand/handDetector.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e52ba5b24bce8a5f1961b48a533cf7ede0b80471 --- /dev/null +++ b/openpose/include/openpose/hand/handDetector.hpp @@ -0,0 +1,51 @@ +#ifndef OPENPOSE_HAND_HAND_DETECTOR_HPP +#define OPENPOSE_HAND_HAND_DETECTOR_HPP + +#include +#include +#include + +namespace op +{ + // Note: This class is thread-safe, so several GPUs can be running hands and using `updateTracker`, and updateTracker will keep the latest known + // tracking + class OP_API HandDetector + { + public: + explicit HandDetector(const PoseModel poseModel); + + virtual ~HandDetector(); + + std::vector, 2>> detectHands(const Array& poseKeypoints) const; + + std::vector, 2>> trackHands(const Array& poseKeypoints); + + void updateTracker(const std::array, 2>& handKeypoints, const unsigned long long id); + + private: + enum class PosePart : unsigned int + { + LWrist = 0, + LElbow, + LShoulder, + RWrist, + RElbow, + RShoulder, + Size, + }; + + const std::array mPoseIndexes; + std::vector, (int)PosePart::Size>> mPoseTrack; + std::vector> mHandLeftPrevious; + std::vector> mHandRightPrevious; + unsigned long long mCurrentId; + std::mutex mMutex; + + std::array getPoseKeypoints(const PoseModel poseModel, + const std::array& poseStrings) const; + + DELETE_COPY(HandDetector); + }; +} + +#endif // OPENPOSE_HAND_HAND_DETECTOR_HPP diff --git a/openpose/include/openpose/hand/handDetectorFromTxt.hpp b/openpose/include/openpose/hand/handDetectorFromTxt.hpp new file mode 100644 index 0000000000000000000000000000000000000000..abfeb67008d01a6cd5bca31e2d91a004c37369e7 --- /dev/null +++ b/openpose/include/openpose/hand/handDetectorFromTxt.hpp @@ -0,0 +1,27 @@ +#ifndef OPENPOSE_HAND_HAND_DETECTOR_FROM_TXT_HPP +#define OPENPOSE_HAND_HAND_DETECTOR_FROM_TXT_HPP + +#include +#include + +namespace op +{ + class OP_API HandDetectorFromTxt + { + public: + explicit HandDetectorFromTxt(const std::string& txtDirectoryPath); + + virtual ~HandDetectorFromTxt(); + + std::vector, 2>> detectHands(); + + private: + const std::string mTxtDirectoryPath; + const std::vector mFilePaths; + long long mFrameNameCounter; + + DELETE_COPY(HandDetectorFromTxt); + }; +} + +#endif // OPENPOSE_HAND_HAND_DETECTOR_FROM_TXT_HPP diff --git a/openpose/include/openpose/hand/handExtractorCaffe.hpp b/openpose/include/openpose/hand/handExtractorCaffe.hpp new file mode 100644 index 0000000000000000000000000000000000000000..cc654648b515a92885482dc17ad60c687aa0261d --- /dev/null +++ b/openpose/include/openpose/hand/handExtractorCaffe.hpp @@ -0,0 +1,70 @@ +#ifndef OPENPOSE_HAND_HAND_EXTRACTOR_CAFFE_HPP +#define OPENPOSE_HAND_HAND_EXTRACTOR_CAFFE_HPP + +#include +#include +#include + +namespace op +{ + /** + * Hand keypoint extractor class for Caffe framework. + */ + class OP_API HandExtractorCaffe : public HandExtractorNet + { + public: + /** + * Constructor of the HandExtractorCaffe class. + * @param netInputSize Size at which the cropped image (where the hand is located) is resized. + * @param netOutputSize Size of the final results. At the moment, it must be equal than netOutputSize. + * @param modelFolder Folder where the models are located. + * @param gpuId The GPU index (0-based) which the deep net will use. + * @param numberScales Number of scales to run. The more scales, the slower it will be but possibly also more + * accurate. + * @param rangeScales The range between the smaller and bigger scale. + */ + HandExtractorCaffe(const Point& netInputSize, const Point& netOutputSize, + const std::string& modelFolder, const int gpuId, + const int numberScales = 1, const float rangeScales = 0.4f, + const std::vector& heatMapTypes = {}, + const ScaleMode heatMapScaleMode = ScaleMode::ZeroToOneFixedAspect, + const bool enableGoogleLogging = true); + + /** + * Virtual destructor of the HandExtractor class. + * Required to allow inheritance. + */ + virtual ~HandExtractorCaffe(); + + /** + * This function must be call before using any other function. It must also be called inside the thread in + * which the functions are going to be used. + */ + void netInitializationOnThread(); + + /** + * This function extracts the hand keypoints for each detected hand in the image. + * @param handRectangles location of the hands in the image. It is a length-variable std::vector, where + * each index corresponds to a different person in the image. Internally the std::vector, a std::array of 2 + * elements: index 0 and 1 for left and right hand respectively. Inside each array element, a + * op::Rectangle (similar to cv::Rect for floating values) with the position of that hand (or 0,0,0,0 if + * some hand is missing, e.g., if a specific person has only half of the body inside the image). + * @param inputData Original image in Mat format and BGR format. + */ + void forwardPass(const std::vector, 2>> handRectangles, const Matrix& inputData); + + private: + // PIMPL idiom + // http://www.cppsamples.com/common-tasks/pimpl.html + struct ImplHandExtractorCaffe; + std::unique_ptr upImpl; + + Array getHeatMapsFromLastPass() const; + + // PIMP requires DELETE_COPY & destructor, or extra code + // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html + DELETE_COPY(HandExtractorCaffe); + }; +} + +#endif // OPENPOSE_HAND_HAND_EXTRACTOR_CAFFE_HPP diff --git a/openpose/include/openpose/hand/handExtractorNet.hpp b/openpose/include/openpose/hand/handExtractorNet.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7687d4077c826e786a2e4bab30b80a20b4a62492 --- /dev/null +++ b/openpose/include/openpose/hand/handExtractorNet.hpp @@ -0,0 +1,92 @@ +#ifndef OPENPOSE_HAND_HAND_EXTRACTOR_HPP +#define OPENPOSE_HAND_HAND_EXTRACTOR_HPP + +#include +#include +#include + +namespace op +{ + /** + * Hand keypoint extractor class. + */ + class OP_API HandExtractorNet + { + public: + /** + * Constructor of the HandExtractorNet class. + * @param netInputSize Size at which the cropped image (where the hand is located) is resized. + * @param netOutputSize Size of the final results. At the moment, it must be equal than netOutputSize. + * @param numberScales Number of scales to run. The more scales, the slower it will be but possibly also more + * accurate. + * @param rangeScales The range between the smaller and bigger scale. + */ + explicit HandExtractorNet(const Point& netInputSize, const Point& netOutputSize, + const int numberScales = 1, const float rangeScales = 0.4f, + const std::vector& heatMapTypes = {}, + const ScaleMode heatMapScaleMode = ScaleMode::ZeroToOneFixedAspect); + + /** + * Virtual destructor of the HandExtractorNet class. + * Required to allow inheritance. + */ + virtual ~HandExtractorNet(); + + /** + * This function must be call before using any other function. It must also be called inside the thread in + * which the functions are going to be used. + */ + void initializationOnThread(); + + /** + * This function extracts the hand keypoints for each detected hand in the image. + * @param handRectangles location of the hands in the image. It is a length-variable std::vector, where + * each index corresponds to a different person in the image. Internally the std::vector, a std::array of 2 + * elements: index 0 and 1 for left and right hand respectively. Inside each array element, a + * op::Rectangle (similar to cv::Rect for floating values) with the position of that hand (or 0,0,0,0 if + * some hand is missing, e.g., if a specific person has only half of the body inside the image). + * @param cvInputData Original image in Mat format and BGR format. + */ + virtual void forwardPass(const std::vector, 2>> handRectangles, + const Matrix& cvInputData) = 0; + + std::array, 2> getHeatMaps() const; + + /** + * This function returns the hand keypoins. VERY IMPORTANT: use getHandKeypoints().clone() if the keypoints are + * going to be edited in a different thread. + * @return A std::array with all the left hand keypoints (index 0) and all the right ones (index 1). Each + * Array follows the pose structure, i.e., the first dimension corresponds to all the people in the + * image, the second to each specific keypoint, and the third one to (x, y, score). + */ + std::array, 2> getHandKeypoints() const; + + bool getEnabled() const; + + void setEnabled(const bool enabled); + + protected: + const std::pair mMultiScaleNumberAndRange; + const Point mNetOutputSize; + Array mHandImageCrop; + std::array, 2> mHandKeypoints; + // HeatMaps parameters + const ScaleMode mHeatMapScaleMode; + const std::vector mHeatMapTypes; + std::array, 2> mHeatMaps; + // Temporarily disable it + std::atomic mEnabled; + + virtual void netInitializationOnThread() = 0; + + private: + // Init with thread + std::thread::id mThreadId; + + void checkThread() const; + + DELETE_COPY(HandExtractorNet); + }; +} + +#endif // OPENPOSE_HAND_HAND_EXTRACTOR_HPP diff --git a/openpose/include/openpose/hand/handGpuRenderer.hpp b/openpose/include/openpose/hand/handGpuRenderer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..47e59b08aa7fb8cd257a1f85df141f0387b4e259 --- /dev/null +++ b/openpose/include/openpose/hand/handGpuRenderer.hpp @@ -0,0 +1,34 @@ +#ifndef OPENPOSE_HAND_HAND_GPU_RENDERER_HPP +#define OPENPOSE_HAND_HAND_GPU_RENDERER_HPP + +#include +#include +#include +#include + +namespace op +{ + class OP_API HandGpuRenderer : public GpuRenderer, public HandRenderer + { + public: + HandGpuRenderer(const float renderThreshold, + const float alphaKeypoint = HAND_DEFAULT_ALPHA_KEYPOINT, + const float alphaHeatMap = HAND_DEFAULT_ALPHA_HEAT_MAP); + + virtual ~HandGpuRenderer(); + + void initializationOnThread(); + + void renderHandInherited(Array& outputData, const std::array, 2>& handKeypoints); + + private: + float* pGpuHand; // GPU aux memory + float* pMaxPtr; // GPU aux memory + float* pMinPtr; // GPU aux memory + float* pScalePtr; // GPU aux memory + + DELETE_COPY(HandGpuRenderer); + }; +} + +#endif // OPENPOSE_HAND_HAND_GPU_RENDERER_HPP diff --git a/openpose/include/openpose/hand/handParameters.hpp b/openpose/include/openpose/hand/handParameters.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a131be94df6f1df36f42e3acc4bdc31d33ccb3b4 --- /dev/null +++ b/openpose/include/openpose/hand/handParameters.hpp @@ -0,0 +1,52 @@ +#ifndef OPENPOSE_HAND_HAND_PARAMETERS_HPP +#define OPENPOSE_HAND_HAND_PARAMETERS_HPP + +#include +#include + +namespace op +{ + const auto HAND_MAX_HANDS = 2*POSE_MAX_PEOPLE; + + const auto HAND_NUMBER_PARTS = 21u; + #define HAND_PAIRS_RENDER_GPU \ + 0,1, 1,2, 2,3, 3,4, 0,5, 5,6, 6,7, 7,8, 0,9, 9,10, 10,11, 11,12, 0,13, 13,14, 14,15, 15,16, 0,17, 17,18, 18,19, 19,20 + #define HAND_SCALES_RENDER_GPU 1 + const std::vector HAND_PAIRS_RENDER {HAND_PAIRS_RENDER_GPU}; + #define HAND_COLORS_RENDER_GPU \ + 100.f, 100.f, 100.f, \ + 100.f, 0.f, 0.f, \ + 150.f, 0.f, 0.f, \ + 200.f, 0.f, 0.f, \ + 255.f, 0.f, 0.f, \ + 100.f, 100.f, 0.f, \ + 150.f, 150.f, 0.f, \ + 200.f, 200.f, 0.f, \ + 255.f, 255.f, 0.f, \ + 0.f, 100.f, 50.f, \ + 0.f, 150.f, 75.f, \ + 0.f, 200.f, 100.f, \ + 0.f, 255.f, 125.f, \ + 0.f, 50.f, 100.f, \ + 0.f, 75.f, 150.f, \ + 0.f, 100.f, 200.f, \ + 0.f, 125.f, 255.f, \ + 100.f, 0.f, 100.f, \ + 150.f, 0.f, 150.f, \ + 200.f, 0.f, 200.f, \ + 255.f, 0.f, 255.f + const std::vector HAND_COLORS_RENDER{HAND_COLORS_RENDER_GPU}; + const std::vector HAND_SCALES_RENDER{HAND_SCALES_RENDER_GPU}; + + + // Constant parameters + const auto HAND_CCN_DECREASE_FACTOR = 8.f; + const std::string HAND_PROTOTXT{"hand/pose_deploy.prototxt"}; + const std::string HAND_TRAINED_MODEL{"hand/pose_iter_102000.caffemodel"}; + + // Rendering parameters + const auto HAND_DEFAULT_ALPHA_KEYPOINT = POSE_DEFAULT_ALPHA_KEYPOINT; + const auto HAND_DEFAULT_ALPHA_HEAT_MAP = POSE_DEFAULT_ALPHA_HEAT_MAP; +} + +#endif // OPENPOSE_HAND_HAND_PARAMETERS_HPP diff --git a/openpose/include/openpose/hand/handRenderer.hpp b/openpose/include/openpose/hand/handRenderer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..db009bd0205c6736c5db696620857c3ed72bdc63 --- /dev/null +++ b/openpose/include/openpose/hand/handRenderer.hpp @@ -0,0 +1,24 @@ +#ifndef OPENPOSE_HAND_HAND_RENDERER_HPP +#define OPENPOSE_HAND_HAND_RENDERER_HPP + +#include + +namespace op +{ + class OP_API HandRenderer + { + public: + virtual ~HandRenderer(){}; + + virtual void initializationOnThread(){}; + + void renderHand(Array& outputData, const std::array, 2>& handKeypoints, + const float scaleInputToOutput); + + private: + virtual void renderHandInherited(Array& outputData, + const std::array, 2>& handKeypoints) = 0; + }; +} + +#endif // OPENPOSE_HAND_HAND_RENDERER_HPP diff --git a/openpose/include/openpose/hand/headers.hpp b/openpose/include/openpose/hand/headers.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f33b4b441d08461a074482cde280f54545d24452 --- /dev/null +++ b/openpose/include/openpose/hand/headers.hpp @@ -0,0 +1,21 @@ +#ifndef OPENPOSE_HAND_HEADERS_HPP +#define OPENPOSE_HAND_HEADERS_HPP + +// hand module +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // OPENPOSE_HAND_HEADERS_HPP diff --git a/openpose/include/openpose/hand/renderHand.hpp b/openpose/include/openpose/hand/renderHand.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ec2acbe9733ecdb9aba3250cb3c04cad93ce2a7a --- /dev/null +++ b/openpose/include/openpose/hand/renderHand.hpp @@ -0,0 +1,18 @@ +#ifndef OPENPOSE_HAND_GPU_HAND_RENDER_HPP +#define OPENPOSE_HAND_GPU_HAND_RENDER_HPP + +#include +#include + +namespace op +{ + OP_API void renderHandKeypointsCpu( + Array& frameArray, const std::array, 2>& handKeypoints, const float renderThreshold); + + void renderHandKeypointsGpu( + float* framePtr, float* maxPtr, float* minPtr, float* scalePtr, const Point& frameSize, + const float* const handsPtr, const int numberHands, const float renderThreshold, + const float alphaColorToAdd = HAND_DEFAULT_ALPHA_KEYPOINT); +} + +#endif // OPENPOSE_HAND_GPU_HAND_RENDER_HPP diff --git a/openpose/include/openpose/hand/wHandDetector.hpp b/openpose/include/openpose/hand/wHandDetector.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8b6facb8bfc6cb3009a0342aad19f22fc2eefc33 --- /dev/null +++ b/openpose/include/openpose/hand/wHandDetector.hpp @@ -0,0 +1,85 @@ +#ifndef OPENPOSE_HAND_W_HAND_DETECTOR_HPP +#define OPENPOSE_HAND_W_HAND_DETECTOR_HPP + +#include +#include +#include + +namespace op +{ + template + class WHandDetector : public Worker + { + public: + explicit WHandDetector(const std::shared_ptr& handDetector); + + virtual ~WHandDetector(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + std::shared_ptr spHandDetector; + + DELETE_COPY(WHandDetector); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WHandDetector::WHandDetector(const std::shared_ptr& handDetector) : + spHandDetector{handDetector} + { + } + + template + WHandDetector::~WHandDetector() + { + } + + template + void WHandDetector::initializationOnThread() + { + } + + template + void WHandDetector::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Detect people hand + for (auto& tDatumPtr : *tDatums) + tDatumPtr->handRectangles = spHandDetector->detectHands(tDatumPtr->poseKeypoints); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WHandDetector); +} + +#endif // OPENPOSE_HAND_W_HAND_DETECTOR_HPP diff --git a/openpose/include/openpose/hand/wHandDetectorFromTxt.hpp b/openpose/include/openpose/hand/wHandDetectorFromTxt.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c77c7b8fff408c76b49d739f127637e87d8519b1 --- /dev/null +++ b/openpose/include/openpose/hand/wHandDetectorFromTxt.hpp @@ -0,0 +1,85 @@ +#ifndef OPENPOSE_HAND_W_HAND_DETECTOR_FROM_JSON_HPP +#define OPENPOSE_HAND_W_HAND_DETECTOR_FROM_JSON_HPP + +#include +#include +#include + +namespace op +{ + template + class WHandDetectorFromTxt : public Worker + { + public: + explicit WHandDetectorFromTxt(const std::shared_ptr& handDetectorFromTxt); + + virtual ~WHandDetectorFromTxt(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + std::shared_ptr spHandDetectorFromTxt; + + DELETE_COPY(WHandDetectorFromTxt); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WHandDetectorFromTxt::WHandDetectorFromTxt(const std::shared_ptr& handDetectorFromTxt) : + spHandDetectorFromTxt{handDetectorFromTxt} + { + } + + template + WHandDetectorFromTxt::~WHandDetectorFromTxt() + { + } + + template + void WHandDetectorFromTxt::initializationOnThread() + { + } + + template + void WHandDetectorFromTxt::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Detect people hand + for (auto& tDatumPtr : *tDatums) + tDatumPtr->handRectangles = spHandDetectorFromTxt->detectHands(); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WHandDetectorFromTxt); +} + +#endif // OPENPOSE_HAND_W_HAND_DETECTOR_FROM_JSON_HPP diff --git a/openpose/include/openpose/hand/wHandDetectorTracking.hpp b/openpose/include/openpose/hand/wHandDetectorTracking.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8272f2690f35b9bb28f766005568284a14646990 --- /dev/null +++ b/openpose/include/openpose/hand/wHandDetectorTracking.hpp @@ -0,0 +1,85 @@ +#ifndef OPENPOSE_HAND_W_HAND_DETECTOR_TRACKING_HPP +#define OPENPOSE_HAND_W_HAND_DETECTOR_TRACKING_HPP + +#include +#include +#include + +namespace op +{ + template + class WHandDetectorTracking : public Worker + { + public: + explicit WHandDetectorTracking(const std::shared_ptr& handDetector); + + virtual ~WHandDetectorTracking(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + std::shared_ptr spHandDetector; + + DELETE_COPY(WHandDetectorTracking); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WHandDetectorTracking::WHandDetectorTracking(const std::shared_ptr& handDetector) : + spHandDetector{handDetector} + { + } + + template + WHandDetectorTracking::~WHandDetectorTracking() + { + } + + template + void WHandDetectorTracking::initializationOnThread() + { + } + + template + void WHandDetectorTracking::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Detect people hand + for (auto& tDatumPtr : *tDatums) + tDatumPtr->handRectangles = spHandDetector->trackHands(tDatumPtr->poseKeypoints); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WHandDetectorTracking); +} + +#endif // OPENPOSE_HAND_W_HAND_DETECTOR_TRACKING_HPP diff --git a/openpose/include/openpose/hand/wHandDetectorUpdate.hpp b/openpose/include/openpose/hand/wHandDetectorUpdate.hpp new file mode 100644 index 0000000000000000000000000000000000000000..510733e345fadfc245186690ebd792a6979265f3 --- /dev/null +++ b/openpose/include/openpose/hand/wHandDetectorUpdate.hpp @@ -0,0 +1,85 @@ +#ifndef OPENPOSE_HAND_W_HAND_DETECTOR_UPDATE_HPP +#define OPENPOSE_HAND_W_HAND_DETECTOR_UPDATE_HPP + +#include +#include +#include + +namespace op +{ + template + class WHandDetectorUpdate : public Worker + { + public: + explicit WHandDetectorUpdate(const std::shared_ptr& handDetector); + + virtual ~WHandDetectorUpdate(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + std::shared_ptr spHandDetector; + + DELETE_COPY(WHandDetectorUpdate); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WHandDetectorUpdate::WHandDetectorUpdate(const std::shared_ptr& handDetector) : + spHandDetector{handDetector} + { + } + + template + WHandDetectorUpdate::~WHandDetectorUpdate() + { + } + + template + void WHandDetectorUpdate::initializationOnThread() + { + } + + template + void WHandDetectorUpdate::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Detect people hand + for (auto& tDatumPtr : *tDatums) + spHandDetector->updateTracker(tDatumPtr->handKeypoints, tDatumPtr->id); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WHandDetectorUpdate); +} + +#endif // OPENPOSE_HAND_W_HAND_DETECTOR_UPDATE_HPP diff --git a/openpose/include/openpose/hand/wHandExtractorNet.hpp b/openpose/include/openpose/hand/wHandExtractorNet.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e29bcb4addbd929906dedb41c724c3390f326723 --- /dev/null +++ b/openpose/include/openpose/hand/wHandExtractorNet.hpp @@ -0,0 +1,93 @@ +#ifndef OPENPOSE_HAND_W_HAND_EXTRACTOR_NET_HPP +#define OPENPOSE_HAND_W_HAND_EXTRACTOR_NET_HPP + +#include +#include +#include + +namespace op +{ + template + class WHandExtractorNet : public Worker + { + public: + explicit WHandExtractorNet(const std::shared_ptr& handExtractorNet); + + virtual ~WHandExtractorNet(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + std::shared_ptr spHandExtractorNet; + + DELETE_COPY(WHandExtractorNet); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WHandExtractorNet::WHandExtractorNet(const std::shared_ptr& handExtractorNet) : + spHandExtractorNet{handExtractorNet} + { + } + + template + WHandExtractorNet::~WHandExtractorNet() + { + } + + template + void WHandExtractorNet::initializationOnThread() + { + spHandExtractorNet->initializationOnThread(); + } + + template + void WHandExtractorNet::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Extract people hands + for (auto& tDatumPtr : *tDatums) + { + spHandExtractorNet->forwardPass(tDatumPtr->handRectangles, tDatumPtr->cvInputData); + for (auto hand = 0 ; hand < 2 ; hand++) + { + tDatumPtr->handHeatMaps[hand] = spHandExtractorNet->getHeatMaps()[hand].clone(); + tDatumPtr->handKeypoints[hand] = spHandExtractorNet->getHandKeypoints()[hand].clone(); + } + } + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WHandExtractorNet); +} + +#endif // OPENPOSE_HAND_W_HAND_EXTRACTOR_NET_HPP diff --git a/openpose/include/openpose/hand/wHandRenderer.hpp b/openpose/include/openpose/hand/wHandRenderer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b9aebd918c6da2929d5e45cc3eb481a2cb90b5ca --- /dev/null +++ b/openpose/include/openpose/hand/wHandRenderer.hpp @@ -0,0 +1,87 @@ +#ifndef OPENPOSE_HAND_W_HAND_RENDERER_HPP +#define OPENPOSE_HAND_W_HAND_RENDERER_HPP + +#include +#include +#include + +namespace op +{ + template + class WHandRenderer : public Worker + { + public: + explicit WHandRenderer(const std::shared_ptr& handRenderer); + + virtual ~WHandRenderer(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + std::shared_ptr spHandRenderer; + + DELETE_COPY(WHandRenderer); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WHandRenderer::WHandRenderer(const std::shared_ptr& handRenderer) : + spHandRenderer{handRenderer} + { + } + + template + WHandRenderer::~WHandRenderer() + { + } + + template + void WHandRenderer::initializationOnThread() + { + spHandRenderer->initializationOnThread(); + } + + template + void WHandRenderer::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Render people hands + for (auto& tDatumPtr : *tDatums) + spHandRenderer->renderHand( + tDatumPtr->outputData, tDatumPtr->handKeypoints, (float)tDatumPtr->scaleInputToOutput); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WHandRenderer); +} + +#endif // OPENPOSE_HAND_W_HAND_RENDERER_HPP diff --git a/openpose/include/openpose/headers.hpp b/openpose/include/openpose/headers.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ebc682ac0568602639891e844d66478902bccfa4 --- /dev/null +++ b/openpose/include/openpose/headers.hpp @@ -0,0 +1,49 @@ +#ifndef OPENPOSE_HEADERS_HPP +#define OPENPOSE_HEADERS_HPP + +// 3d module +#include + +// calibration module +#include + +// core module +#include + +// face module +#include + +// filestream module +#include + +// gui module +#include + +// hand module +#include + +// net module +#include + +// pose module +#include + +// producer module +#include + +// threading module +#include + +// tracking module +#include + +// unity module +#include + +// utilities module +#include + +// wrapper module +#include + +#endif // OPENPOSE_HEADERS_HPP diff --git a/openpose/include/openpose/net/bodyPartConnectorBase.hpp b/openpose/include/openpose/net/bodyPartConnectorBase.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d609d921f45a9901c53527bb9f20a5bcd349daee --- /dev/null +++ b/openpose/include/openpose/net/bodyPartConnectorBase.hpp @@ -0,0 +1,69 @@ +#ifndef OPENPOSE_POSE_BODY_PARTS_CONNECTOR_HPP +#define OPENPOSE_POSE_BODY_PARTS_CONNECTOR_HPP + +#include +#include + +namespace op +{ + template + void connectBodyPartsCpu( + Array& poseKeypoints, Array& poseScores, const T* const heatMapPtr, const T* const peaksPtr, + const PoseModel poseModel, const Point& heatMapSize, const int maxPeaks, const T interMinAboveThreshold, + const T interThreshold, const int minSubsetCnt, const T minSubsetScore, const T defaultNmsThreshold, + const T scaleFactor = 1.f, const bool maximizePositives = false); + + // Windows: Cuda functions do not include OP_API + template + void connectBodyPartsGpu( + Array& poseKeypoints, Array& poseScores, const T* const heatMapGpuPtr, const T* const peaksPtr, + const PoseModel poseModel, const Point& heatMapSize, const int maxPeaks, const T interMinAboveThreshold, + const T interThreshold, const int minSubsetCnt, const T minSubsetScore, const T defaultNmsThreshold, + const T scaleFactor, const bool maximizePositives, Array pairScoresCpu, T* pairScoresGpuPtr, + const unsigned int* const bodyPartPairsGpuPtr, const unsigned int* const mapIdxGpuPtr, + const T* const peaksGpuPtr); + + template + void connectBodyPartsOcl( + Array& poseKeypoints, Array& poseScores, const T* const heatMapGpuPtr, const T* const peaksPtr, + const PoseModel poseModel, const Point& heatMapSize, const int maxPeaks, const T interMinAboveThreshold, + const T interThreshold, const int minSubsetCnt, const T minSubsetScore, const T defaultNmsThreshold, + const T scaleFactor = 1.f, const bool maximizePositives = false, + Array pairScoresCpu = Array{}, T* pairScoresGpuPtr = nullptr, + const unsigned int* const bodyPartPairsGpuPtr = nullptr, const unsigned int* const mapIdxGpuPtr = nullptr, + const T* const peaksGpuPtr = nullptr, const int gpuID = 0); + + // Private functions used by the 2 above functions + template + std::vector, T>> createPeopleVector( + const T* const heatMapPtr, const T* const peaksPtr, const PoseModel poseModel, const Point& heatMapSize, + const int maxPeaks, const T interThreshold, const T interMinAboveThreshold, + const std::vector& bodyPartPairs, const unsigned int numberBodyParts, + const unsigned int numberBodyPartPairs, const T defaultNmsThreshold, + const Array& precomputedPAFs = Array()); + + template + void removePeopleBelowThresholdsAndFillFaces( + std::vector& validSubsetIndexes, int& numberPeople, + std::vector, T>>& subsets, const unsigned int numberBodyParts, + const int minSubsetCnt, const T minSubsetScore, const bool maximizePositives, const T* const peaksPtr); + + template + void peopleVectorToPeopleArray( + Array& poseKeypoints, Array& poseScores, const T scaleFactor, + const std::vector, T>>& subsets, const std::vector& validSubsetIndexes, + const T* const peaksPtr, const int numberPeople, const unsigned int numberBodyParts, + const unsigned int numberBodyPartPairs); + + template + std::vector> pafPtrIntoVector( + const Array& pairScores, const T* const peaksPtr, const int maxPeaks, + const std::vector& bodyPartPairs, const unsigned int numberBodyPartPairs); + + template + std::vector, T>> pafVectorIntoPeopleVector( + const std::vector>& pairScores, const T* const peaksPtr, const int maxPeaks, + const std::vector& bodyPartPairs, const unsigned int numberBodyParts); +} + +#endif // OPENPOSE_POSE_BODY_PARTS_CONNECTOR_HPP diff --git a/openpose/include/openpose/net/bodyPartConnectorCaffe.hpp b/openpose/include/openpose/net/bodyPartConnectorCaffe.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ac1d5d9f1b3c32d18df8888109fb29c60582c2d9 --- /dev/null +++ b/openpose/include/openpose/net/bodyPartConnectorCaffe.hpp @@ -0,0 +1,81 @@ +#ifndef OPENPOSE_POSE_BODY_PART_CONNECTOR_CAFFE_HPP +#define OPENPOSE_POSE_BODY_PART_CONNECTOR_CAFFE_HPP + +#include +#include + +namespace op +{ + // It mostly follows the Caffe::layer implementation, so Caffe users can easily use it. However, in order to keep + // the compatibility with any generic Caffe version, we keep this 'layer' inside our library rather than in the + // Caffe code. + template + class BodyPartConnectorCaffe + { + public: + explicit BodyPartConnectorCaffe(); + + virtual ~BodyPartConnectorCaffe(); + + virtual void Reshape(const std::vector*>& bottom, const int gpuID = 0); + + virtual inline const char* type() const { return "BodyPartConnector"; } + + void setPoseModel(const PoseModel poseModel); + + void setMaximizePositives(const bool maximizePositives); + + void setDefaultNmsThreshold(const T defaultNmsThreshold); + + void setInterMinAboveThreshold(const T interMinAboveThreshold); + + void setInterThreshold(const T interThreshold); + + void setMinSubsetCnt(const int minSubsetCnt); + + void setMinSubsetScore(const T minSubsetScore); + + void setScaleNetToOutput(const T scaleNetToOutput); + + virtual void Forward(const std::vector*>& bottom, Array& poseKeypoints, + Array& poseScores); + + virtual void Forward_cpu(const std::vector*>& bottom, Array& poseKeypoints, + Array& poseScores); + + virtual void Forward_gpu(const std::vector*>& bottom, Array& poseKeypoints, + Array& poseScores); + + virtual void Forward_ocl(const std::vector*>& bottom, Array& poseKeypoints, + Array& poseScores); + + virtual void Backward_cpu(const std::vector*>& top, const std::vector& propagate_down, + const std::vector*>& bottom); + + virtual void Backward_gpu(const std::vector*>& top, const std::vector& propagate_down, + const std::vector*>& bottom); + + private: + PoseModel mPoseModel; + bool mMaximizePositives; + T mDefaultNmsThreshold; + T mInterMinAboveThreshold; + T mInterThreshold; + int mMinSubsetCnt; + T mMinSubsetScore; + T mScaleNetToOutput; + std::array mHeatMapsSize; + std::array mPeaksSize; + std::array mTopSize; + // GPU auxiliary + unsigned int* pBodyPartPairsGpuPtr; + unsigned int* pMapIdxGpuPtr; + Array mFinalOutputCpu; + T* pFinalOutputGpuPtr; + int mGpuID; + + DELETE_COPY(BodyPartConnectorCaffe); + }; +} + +#endif // OPENPOSE_POSE_BODY_PART_CONNECTOR_CAFFE_HPP diff --git a/openpose/include/openpose/net/headers.hpp b/openpose/include/openpose/net/headers.hpp new file mode 100644 index 0000000000000000000000000000000000000000..997c26a1338ef0d2e78a6eda2718f482698ced3f --- /dev/null +++ b/openpose/include/openpose/net/headers.hpp @@ -0,0 +1,17 @@ +#ifndef OPENPOSE_NET_HEADERS_HPP +#define OPENPOSE_NET_HEADERS_HPP + +// net module +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // OPENPOSE_NET_HEADERS_HPP diff --git a/openpose/include/openpose/net/maximumBase.hpp b/openpose/include/openpose/net/maximumBase.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8732e1de0876439a483e41fcc5a0560b67857e5a --- /dev/null +++ b/openpose/include/openpose/net/maximumBase.hpp @@ -0,0 +1,18 @@ +#ifndef OPENPOSE_NET_MAXIMUM_BASE_HPP +#define OPENPOSE_NET_MAXIMUM_BASE_HPP + +#include + +namespace op +{ + template + void maximumCpu(T* targetPtr, const T* const sourcePtr, const std::array& targetSize, + const std::array& sourceSize); + + // Windows: Cuda functions do not include OP_API + template + void maximumGpu(T* targetPtr, const T* const sourcePtr, const std::array& targetSize, + const std::array& sourceSize); +} + +#endif // OPENPOSE_NET_MAXIMUM_BASE_HPP diff --git a/openpose/include/openpose/net/maximumCaffe.hpp b/openpose/include/openpose/net/maximumCaffe.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8ecfcc4b0cc511dc49aad46da8562d62bc747956 --- /dev/null +++ b/openpose/include/openpose/net/maximumCaffe.hpp @@ -0,0 +1,43 @@ +#ifndef OPENPOSE_NET_MAXIMUM_CAFFE_HPP +#define OPENPOSE_NET_MAXIMUM_CAFFE_HPP + +#include + +namespace op +{ + // It mostly follows the Caffe::layer implementation, so Caffe users can easily use it. However, in order to keep + // the compatibility with any generic Caffe version, we keep this 'layer' inside our library rather than in the + // Caffe code. + template + class MaximumCaffe + { + public: + explicit MaximumCaffe(); + + virtual ~MaximumCaffe(); + + virtual void LayerSetUp(const std::vector*>& bottom, const std::vector*>& top); + + virtual void Reshape(const std::vector*>& bottom, const std::vector*>& top); + + virtual inline const char* type() const { return "Maximum"; } + + virtual void Forward(const std::vector*>& bottom, const std::vector*>& top); + + virtual void Forward_cpu(const std::vector*>& bottom, const std::vector*>& top); + + virtual void Forward_gpu(const std::vector*>& bottom, const std::vector*>& top); + + virtual void Backward_cpu(const std::vector*>& top, const std::vector& propagate_down, + const std::vector*>& bottom); + + virtual void Backward_gpu(const std::vector*>& top, const std::vector& propagate_down, + const std::vector*>& bottom); + + private: + std::array mBottomSize; + std::array mTopSize; + }; +} + +#endif // OPENPOSE_NET_MAXIMUM_CAFFE_HPP diff --git a/openpose/include/openpose/net/net.hpp b/openpose/include/openpose/net/net.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5e44aaed07a8349a33aff3243b113f0e0db2df0c --- /dev/null +++ b/openpose/include/openpose/net/net.hpp @@ -0,0 +1,21 @@ +#ifndef OPENPOSE_NET_NET_HPP +#define OPENPOSE_NET_NET_HPP + +#include + +namespace op +{ + class OP_API Net + { + public: + virtual ~Net(){} + + virtual void initializationOnThread() = 0; + + virtual void forwardPass(const Array& inputData) const = 0; + + virtual std::shared_ptr> getOutputBlobArray() const = 0; + }; +} + +#endif // OPENPOSE_NET_NET_HPP diff --git a/openpose/include/openpose/net/netCaffe.hpp b/openpose/include/openpose/net/netCaffe.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ffe131e8766bb4c86f94be99dba2ef268801352b --- /dev/null +++ b/openpose/include/openpose/net/netCaffe.hpp @@ -0,0 +1,35 @@ +#ifndef OPENPOSE_NET_NET_CAFFE_HPP +#define OPENPOSE_NET_NET_CAFFE_HPP + +#include +#include + +namespace op +{ + class OP_API NetCaffe : public Net + { + public: + NetCaffe(const std::string& caffeProto, const std::string& caffeTrainedModel, const int gpuId = 0, + const bool enableGoogleLogging = true, const std::string& lastBlobName = "net_output"); + + virtual ~NetCaffe(); + + void initializationOnThread(); + + void forwardPass(const Array& inputNetData) const; + + std::shared_ptr> getOutputBlobArray() const; + + private: + // PIMPL idiom + // http://www.cppsamples.com/common-tasks/pimpl.html + struct ImplNetCaffe; + std::unique_ptr upImpl; + + // PIMP requires DELETE_COPY & destructor, or extra code + // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html + DELETE_COPY(NetCaffe); + }; +} + +#endif // OPENPOSE_NET_NET_CAFFE_HPP diff --git a/openpose/include/openpose/net/netOpenCv.hpp b/openpose/include/openpose/net/netOpenCv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3a767a7c9a5bd9cab95b6ceede07fa71d53021a4 --- /dev/null +++ b/openpose/include/openpose/net/netOpenCv.hpp @@ -0,0 +1,34 @@ +#ifndef OPENPOSE_NET_NET_OPEN_CV_HPP +#define OPENPOSE_NET_NET_OPEN_CV_HPP + +#include +#include + +namespace op +{ + class OP_API NetOpenCv : public Net + { + public: + NetOpenCv(const std::string& caffeProto, const std::string& caffeTrainedModel, const int gpuId = 0); + + virtual ~NetOpenCv(); + + void initializationOnThread(); + + void forwardPass(const Array& inputNetData) const; + + std::shared_ptr> getOutputBlobArray() const; + + private: + // PIMPL idiom + // http://www.cppsamples.com/common-tasks/pimpl.html + struct ImplNetOpenCv; + std::unique_ptr upImpl; + + // PIMP requires DELETE_COPY & destructor, or extra code + // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html + DELETE_COPY(NetOpenCv); + }; +} + +#endif // OPENPOSE_NET_NET_OPEN_CV_HPP diff --git a/openpose/include/openpose/net/nmsBase.hpp b/openpose/include/openpose/net/nmsBase.hpp new file mode 100644 index 0000000000000000000000000000000000000000..dd1b7b28647070d2d866df67cf8cc6be1903d1e4 --- /dev/null +++ b/openpose/include/openpose/net/nmsBase.hpp @@ -0,0 +1,26 @@ +#ifndef OPENPOSE_NET_NMS_BASE_HPP +#define OPENPOSE_NET_NMS_BASE_HPP + +#include + +namespace op +{ + template + void nmsCpu( + T* targetPtr, int* kernelPtr, const T* const sourcePtr, const T threshold, const std::array& targetSize, + const std::array& sourceSize, const Point& offset); + + // Windows: Cuda functions do not include OP_API + template + void nmsGpu( + T* targetPtr, int* kernelPtr, const T* const sourcePtr, const T threshold, const std::array& targetSize, + const std::array& sourceSize, const Point& offset); + + // Windows: OpenCL functions do not include OP_API + template + void nmsOcl( + T* targetPtr, uint8_t* kernelGpuPtr, uint8_t* kernelCpuPtr, const T* const sourcePtr, const T threshold, const std::array& targetSize, + const std::array& sourceSize, const Point& offset, const int gpuID = 0); +} + +#endif // OPENPOSE_NET_NMS_BASE_HPP diff --git a/openpose/include/openpose/net/nmsCaffe.hpp b/openpose/include/openpose/net/nmsCaffe.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f91eb85e1499c9bd74fc746eefd8afc0936efe0d --- /dev/null +++ b/openpose/include/openpose/net/nmsCaffe.hpp @@ -0,0 +1,61 @@ +#ifndef OPENPOSE_NET_NMS_CAFFE_HPP +#define OPENPOSE_NET_NMS_CAFFE_HPP + +#include + +namespace op +{ + // It mostly follows the Caffe::layer implementation, so Caffe users can easily use it. However, in order to keep + // the compatibility with any generic Caffe version, we keep this 'layer' inside our library rather than in the + // Caffe code. + template + class NmsCaffe + { + public: + explicit NmsCaffe(); + + virtual ~NmsCaffe(); + + virtual void LayerSetUp(const std::vector*>& bottom, const std::vector*>& top); + + virtual void Reshape(const std::vector*>& bottom, const std::vector*>& top, + const int maxPeaks, const int outputChannels = -1, const int gpuID = 0); + + virtual inline const char* type() const { return "Nms"; } + + void setThreshold(const T threshold); + + // Empirically gives better results (copied from Matlab original code) + void setOffset(const Point& offset); + + virtual void Forward(const std::vector*>& bottom, const std::vector*>& top); + + virtual void Forward_cpu(const std::vector*>& bottom, const std::vector*>& top); + + virtual void Forward_gpu(const std::vector*>& bottom, const std::vector*>& top); + + virtual void Forward_ocl(const std::vector*>& bottom, const std::vector*>& top); + + virtual void Backward_cpu(const std::vector*>& top, const std::vector& propagate_down, + const std::vector*>& bottom); + + virtual void Backward_gpu(const std::vector*>& top, const std::vector& propagate_down, + const std::vector*>& bottom); + + private: + T mThreshold; + Point mOffset; + int mGpuID; + + // PIMPL idiom + // http://www.cppsamples.com/common-tasks/pimpl.html + struct ImplNmsCaffe; + std::unique_ptr upImpl; + + // PIMP requires DELETE_COPY & destructor, or extra code + // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html + DELETE_COPY(NmsCaffe); + }; +} + +#endif // OPENPOSE_NET_NMS_CAFFE_HPP diff --git a/openpose/include/openpose/net/resizeAndMergeBase.hpp b/openpose/include/openpose/net/resizeAndMergeBase.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4c0f8cc05d5e41037fac95b86c250a86030a82ff --- /dev/null +++ b/openpose/include/openpose/net/resizeAndMergeBase.hpp @@ -0,0 +1,37 @@ +#ifndef OPENPOSE_NET_RESIZE_AND_MERGE_BASE_HPP +#define OPENPOSE_NET_RESIZE_AND_MERGE_BASE_HPP + +#include + +namespace op +{ + template + void resizeAndMergeCpu( + T* targetPtr, const std::vector& sourcePtrs, const std::array& targetSize, + const std::vector>& sourceSizes, const std::vector& scaleInputToNetInputs = {1.f}); + + // Windows: Cuda functions do not include OP_API + template + void resizeAndMergeGpu( + T* targetPtr, const std::vector& sourcePtrs, const std::array& targetSize, + const std::vector>& sourceSizes, const std::vector& scaleInputToNetInputs = {1.f}); + + // Windows: OpenCL functions do not include OP_API + template + void resizeAndMergeOcl( + T* targetPtr, const std::vector& sourcePtrs, std::vector& sourceTempPtrs, + const std::array& targetSize, const std::vector>& sourceSizes, + const std::vector& scaleInputToNetInputs = {1.f}, const int gpuID = 0); + + // Functions for cvMatToOpInput/cvMatToOpOutput + template + void resizeAndPadRbgGpu( + T* targetPtr, const T* const srcPtr, const int sourceWidth, const int sourceHeight, + const int targetWidth, const int targetHeight, const T scaleFactor); + + template + void resizeAndPadRbgGpu( + T* targetPtr, const unsigned char* const srcPtr, const int sourceWidth, const int sourceHeight, + const int targetWidth, const int targetHeight, const T scaleFactor); +} +#endif // OPENPOSE_NET_RESIZE_AND_MERGE_BASE_HPP diff --git a/openpose/include/openpose/net/resizeAndMergeCaffe.hpp b/openpose/include/openpose/net/resizeAndMergeCaffe.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b28b94a99d2ec6515b9dbf3b31f71cc390bae4e4 --- /dev/null +++ b/openpose/include/openpose/net/resizeAndMergeCaffe.hpp @@ -0,0 +1,54 @@ +#ifndef OPENPOSE_NET_RESIZE_AND_MERGE_CAFFE_HPP +#define OPENPOSE_NET_RESIZE_AND_MERGE_CAFFE_HPP + +#include + +namespace op +{ + // It mostly follows the Caffe::layer implementation, so Caffe users can easily use it. However, in order to keep + // the compatibility with any generic Caffe version, we keep this 'layer' inside our library rather than in the + // Caffe code. + template + class ResizeAndMergeCaffe + { + public: + explicit ResizeAndMergeCaffe(); + + virtual ~ResizeAndMergeCaffe(); + + virtual void LayerSetUp(const std::vector*>& bottom, const std::vector*>& top); + + virtual void Reshape(const std::vector*>& bottom, const std::vector*>& top, + const T netFactor, const T scaleFactor, const bool mergeFirstDimension = true, + const int gpuID = 0); + + virtual inline const char* type() const { return "ResizeAndMerge"; } + + void setScaleRatios(const std::vector& scaleRatios); + + virtual void Forward(const std::vector*>& bottom, const std::vector*>& top); + + virtual void Forward_cpu(const std::vector*>& bottom, const std::vector*>& top); + + virtual void Forward_gpu(const std::vector*>& bottom, const std::vector*>& top); + + virtual void Forward_ocl(const std::vector*>& bottom, const std::vector*>& top); + + virtual void Backward_cpu(const std::vector*>& top, const std::vector& propagate_down, + const std::vector*>& bottom); + + virtual void Backward_gpu(const std::vector*>& top, const std::vector& propagate_down, + const std::vector*>& bottom); + + private: + std::vector mTempGPUData; + std::vector mScaleRatios; + std::vector> mBottomSizes; + std::array mTopSize; + int mGpuID; + + DELETE_COPY(ResizeAndMergeCaffe); + }; +} + +#endif // OPENPOSE_NET_RESIZE_AND_MERGE_CAFFE_HPP diff --git a/openpose/include/openpose/pose/enumClasses.hpp b/openpose/include/openpose/pose/enumClasses.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c5880de229151861dc52a8aba96584162d4a953c --- /dev/null +++ b/openpose/include/openpose/pose/enumClasses.hpp @@ -0,0 +1,43 @@ +#ifndef OPENPOSE_POSE_ENUM_CLASSES_HPP +#define OPENPOSE_POSE_ENUM_CLASSES_HPP + +namespace op +{ + /** + * An enum class in which all the possible type of pose estimation models are included. + */ + enum class PoseModel : unsigned char + { + /** + * COCO + 6 foot keypoints + neck + lower abs model, with 25+1 components (see poseParameters.hpp for details). + */ + BODY_25 = 0, + COCO_18, /**< COCO model + neck, with 18+1 components (see poseParameters.hpp for details). */ + MPI_15, /**< MPI model, with 15+1 components (see poseParameters.hpp for details). */ + MPI_15_4, /**< Variation of the MPI model, reduced number of CNN stages to 4: faster but less accurate.*/ + BODY_19, /**< Experimental. Do not use. */ + BODY_19_X2, /**< Experimental. Do not use. */ + BODY_19N, /**< Experimental. Do not use. */ + BODY_25E, /**< Experimental. Do not use. */ + CAR_12, /**< Experimental. Do not use. */ + BODY_25D, /**< Experimental. Do not use. */ + BODY_23, /**< Experimental. Do not use. */ + CAR_22, /**< Experimental. Do not use. */ + BODY_19E, /**< Experimental. Do not use. */ + BODY_25B, /**< Experimental. Do not use. */ + BODY_135, /**< Experimental. Do not use. */ + Size, + }; + + enum class PoseProperty : unsigned char + { + NMSThreshold = 0, + ConnectInterMinAboveThreshold, + ConnectInterThreshold, + ConnectMinSubsetCnt, + ConnectMinSubsetScore, + Size, + }; +} + +#endif // OPENPOSE_POSE_ENUM_CLASSES_HPP diff --git a/openpose/include/openpose/pose/headers.hpp b/openpose/include/openpose/pose/headers.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9d788ec666d8666ad091fb9dab159c62b034ccc3 --- /dev/null +++ b/openpose/include/openpose/pose/headers.hpp @@ -0,0 +1,19 @@ +#ifndef OPENPOSE_POSE_HEADERS_HPP +#define OPENPOSE_POSE_HEADERS_HPP + +// pose module +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // OPENPOSE_POSE_HEADERS_HPP diff --git a/openpose/include/openpose/pose/poseCpuRenderer.hpp b/openpose/include/openpose/pose/poseCpuRenderer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4197b0bd45d37cc313788f3519dbed4b6542f7d0 --- /dev/null +++ b/openpose/include/openpose/pose/poseCpuRenderer.hpp @@ -0,0 +1,31 @@ +#ifndef OPENPOSE_POSE_POSE_CPU_RENDERER_HPP +#define OPENPOSE_POSE_POSE_CPU_RENDERER_HPP + +#include +#include +#include +#include +#include + +namespace op +{ + class OP_API PoseCpuRenderer : public Renderer, public PoseRenderer + { + public: + PoseCpuRenderer( + const PoseModel poseModel, const float renderThreshold, const bool blendOriginalFrame = true, + const float alphaKeypoint = POSE_DEFAULT_ALPHA_KEYPOINT, + const float alphaHeatMap = POSE_DEFAULT_ALPHA_HEAT_MAP, const unsigned int elementToRender = 0u); + + virtual ~PoseCpuRenderer(); + + std::pair renderPose( + Array& outputData, const Array& poseKeypoints, const float scaleInputToOutput, + const float scaleNetToOutput = -1.f); + + private: + DELETE_COPY(PoseCpuRenderer); + }; +} + +#endif // OPENPOSE_POSE_POSE_CPU_RENDERER_HPP diff --git a/openpose/include/openpose/pose/poseExtractor.hpp b/openpose/include/openpose/pose/poseExtractor.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a4692ed79e46ac57e3f746a55c65e67b35587f76 --- /dev/null +++ b/openpose/include/openpose/pose/poseExtractor.hpp @@ -0,0 +1,78 @@ +#ifndef OPENPOSE_POSE_POSE_EXTRACTOR_HPP +#define OPENPOSE_POSE_POSE_EXTRACTOR_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace op +{ + class OP_API PoseExtractor + { + public: + PoseExtractor(const std::shared_ptr& poseExtractorNet, + const std::shared_ptr& keepTopNPeople = nullptr, + const std::shared_ptr& personIdExtractor = nullptr, + const std::shared_ptr>>& personTracker = {}, + const int numberPeopleMax = -1, const int tracking = -1); + + virtual ~PoseExtractor(); + + void initializationOnThread(); + + void forwardPass(const std::vector>& inputNetData, + const Point& inputDataSize, + const std::vector& scaleRatios, + const Array& poseNetOutput = Array{}, + const long long frameId = -1ll); + + // PoseExtractorNet functions + Array getHeatMapsCopy() const; + + std::vector>> getCandidatesCopy() const; + + Array getPoseKeypoints() const; + + Array getPoseScores() const; + + float getScaleNetToOutput() const; + + // KeepTopNPeople functions + void keepTopPeople(Array& poseKeypoints, const Array& poseScores) const; + + // PersonIdExtractor functions + // Not thread-safe + Array extractIds(const Array& poseKeypoints, const Matrix& cvMatInput, + const unsigned long long imageIndex = 0ull); + + // Same than extractIds but thread-safe + Array extractIdsLockThread(const Array& poseKeypoints, const Matrix& cvMatInput, + const unsigned long long imageIndex, + const long long frameId); + + // PersonTracker functions + void track(Array& poseKeypoints, Array& poseIds, + const Matrix& cvMatInput, const unsigned long long imageViewIndex = 0ull); + + void trackLockThread(Array& poseKeypoints, Array& poseIds, + const Matrix& cvMatInput, + const unsigned long long imageViewIndex, + const long long frameId); + + private: + const int mNumberPeopleMax; + const int mTracking; + const std::shared_ptr spPoseExtractorNet; + const std::shared_ptr spKeepTopNPeople; + const std::shared_ptr spPersonIdExtractor; + const std::shared_ptr>> spPersonTrackers; + + DELETE_COPY(PoseExtractor); + }; +} + +#endif // OPENPOSE_POSE_POSE_EXTRACTOR_HPP diff --git a/openpose/include/openpose/pose/poseExtractorCaffe.hpp b/openpose/include/openpose/pose/poseExtractorCaffe.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a956fab9bf45e3f6107d4c4f422eadd4a6991611 --- /dev/null +++ b/openpose/include/openpose/pose/poseExtractorCaffe.hpp @@ -0,0 +1,83 @@ +#ifndef OPENPOSE_POSE_POSE_EXTRACTOR_CAFFE_HPP +#define OPENPOSE_POSE_POSE_EXTRACTOR_CAFFE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace op +{ + class OP_API PoseExtractorCaffe : public PoseExtractorNet + { + public: + PoseExtractorCaffe( + const PoseModel poseModel, const std::string& modelFolder, const int gpuId, + const std::vector& heatMapTypes = {}, + const ScaleMode heatMapScaleMode = ScaleMode::ZeroToOneFixedAspect, + const bool addPartCandidates = false, const bool maximizePositives = false, + const std::string& protoTxtPath = "", const std::string& caffeModelPath = "", + const float upsamplingRatio = 0.f, const bool enableNet = true, + const bool enableGoogleLogging = true); + + virtual ~PoseExtractorCaffe(); + + virtual void netInitializationOnThread(); + + /** + * @param poseNetOutput If it is not empty, OpenPose will not run its internal body pose estimation network + * and will instead use this data as the substitute of its network. The size of this element must match the + * size of the output of its internal network, or it will lead to core dumped (segmentation) errors. You can + * modify the pose estimation flags to match the dimension of both elements (e.g., `--net_resolution`, + * `--scale_number`, etc.). + */ + virtual void forwardPass( + const std::vector>& inputNetData, const Point& inputDataSize, + const std::vector& scaleInputToNetInputs = {1.f}, + const Array& poseNetOutput = Array{}); + + const float* getCandidatesCpuConstPtr() const; + + const float* getCandidatesGpuConstPtr() const; + + const float* getHeatMapCpuConstPtr() const; + + const float* getHeatMapGpuConstPtr() const; + + std::vector getHeatMapSize() const; + + const float* getPoseGpuConstPtr() const; + + private: + // Used when increasing spNets + const PoseModel mPoseModel; + const int mGpuId; + const std::string mModelFolder; + const std::string mProtoTxtPath; + const std::string mCaffeModelPath; + const float mUpsamplingRatio; + const bool mEnableNet; + const bool mEnableGoogleLogging; + // General parameters + std::vector> spNets; + std::shared_ptr> spResizeAndMergeCaffe; + std::shared_ptr> spNmsCaffe; + std::shared_ptr> spBodyPartConnectorCaffe; + std::shared_ptr> spMaximumCaffe; + std::vector> mNetInput4DSizes; + // Init with thread + std::vector>> spCaffeNetOutputBlobs; + std::shared_ptr> spHeatMapsBlob; + std::shared_ptr> spPeaksBlob; + std::shared_ptr> spMaximumPeaksBlob; + + DELETE_COPY(PoseExtractorCaffe); + }; +} + +#endif // OPENPOSE_POSE_POSE_EXTRACTOR_CAFFE_HPP diff --git a/openpose/include/openpose/pose/poseExtractorNet.hpp b/openpose/include/openpose/pose/poseExtractorNet.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0891e0548a1ca82b158d2e7a1e27171795956bcb --- /dev/null +++ b/openpose/include/openpose/pose/poseExtractorNet.hpp @@ -0,0 +1,80 @@ +#ifndef OPENPOSE_POSE_POSE_EXTRACTOR_NET_HPP +#define OPENPOSE_POSE_POSE_EXTRACTOR_NET_HPP + +#include +#include +#include +#include + +namespace op +{ + class OP_API PoseExtractorNet + { + public: + PoseExtractorNet(const PoseModel poseModel, + const std::vector& heatMapTypes = {}, + const ScaleMode heatMapScaleMode = ScaleMode::ZeroToOneFixedAspect, + const bool addPartCandidates = false, + const bool maximizePositives = false); + + virtual ~PoseExtractorNet(); + + void initializationOnThread(); + + virtual void forwardPass( + const std::vector>& inputNetData, const Point& inputDataSize, + const std::vector& scaleRatios = {1.f}, const Array& poseNetOutput = Array{}) = 0; + + virtual const float* getCandidatesCpuConstPtr() const = 0; + + virtual const float* getCandidatesGpuConstPtr() const = 0; + + virtual const float* getHeatMapCpuConstPtr() const = 0; + + virtual const float* getHeatMapGpuConstPtr() const = 0; + + virtual std::vector getHeatMapSize() const = 0; + + Array getHeatMapsCopy() const; + + std::vector>> getCandidatesCopy() const; + + virtual const float* getPoseGpuConstPtr() const = 0; + + Array getPoseKeypoints() const; + + Array getPoseScores() const; + + float getScaleNetToOutput() const; + + double get(const PoseProperty property) const; + + void set(const PoseProperty property, const double value); + + void increase(const PoseProperty property, const double value); + + void clear(); + + protected: + const PoseModel mPoseModel; + Point mNetOutputSize; + Array mPoseKeypoints; + Array mPoseScores; + float mScaleNetToOutput; + + void checkThread() const; + + virtual void netInitializationOnThread() = 0; + + private: + const std::vector mHeatMapTypes; + const ScaleMode mHeatMapScaleMode; + const bool mAddPartCandidates; + std::array, (int)PoseProperty::Size> mProperties; + std::thread::id mThreadId; + + DELETE_COPY(PoseExtractorNet); + }; +} + +#endif // OPENPOSE_POSE_POSE_EXTRACTOR_NET_HPP diff --git a/openpose/include/openpose/pose/poseGpuRenderer.hpp b/openpose/include/openpose/pose/poseGpuRenderer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..bd792648944eba03364e65fecddfbf35871d9795 --- /dev/null +++ b/openpose/include/openpose/pose/poseGpuRenderer.hpp @@ -0,0 +1,43 @@ +#ifndef OPENPOSE_POSE_POSE_GPU_RENDERER_HPP +#define OPENPOSE_POSE_POSE_GPU_RENDERER_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace op +{ + class OP_API PoseGpuRenderer : public GpuRenderer, public PoseRenderer + { + public: + PoseGpuRenderer( + const PoseModel poseModel, const std::shared_ptr& poseExtractorNet, + const float renderThreshold, const bool blendOriginalFrame = true, + const float alphaKeypoint = POSE_DEFAULT_ALPHA_KEYPOINT, + const float alphaHeatMap = POSE_DEFAULT_ALPHA_HEAT_MAP, const unsigned int elementToRender = 0u); + + virtual ~PoseGpuRenderer(); + + void initializationOnThread(); + + std::pair renderPose(Array& outputData, const Array& poseKeypoints, + const float scaleInputToOutput, + const float scaleNetToOutput = -1.f); + + private: + const std::shared_ptr spPoseExtractorNet; + // Init with thread + float* pGpuPose; // GPU aux memory + float* pMaxPtr; // GPU aux memory + float* pMinPtr; // GPU aux memory + float* pScalePtr; // GPU aux memory + + DELETE_COPY(PoseGpuRenderer); + }; +} + +#endif // OPENPOSE_POSE_POSE_GPU_RENDERER_HPP diff --git a/openpose/include/openpose/pose/poseParameters.hpp b/openpose/include/openpose/pose/poseParameters.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e4213d7e453e4263f367fc1d60d8c7e90fb51302 --- /dev/null +++ b/openpose/include/openpose/pose/poseParameters.hpp @@ -0,0 +1,37 @@ +#ifndef OPENPOSE_POSE_POSE_PARAMETERS_HPP +#define OPENPOSE_POSE_POSE_PARAMETERS_HPP + +#include +#include +#include + +namespace op +{ + // Constant Global Parameters + // For OpenCL-NMS in Ubuntu, (POSE_MAX_PEOPLE+1)*3(x,y,score) must be divisible by 32. Easy fix: + // POSE_MAX_PEOPLE = 32n - 1 + // For OpenCL-NMS in Windows, it must be by 64, so 64n - 1 + const auto POSE_MAX_PEOPLE = 127u; + + // Model functions + OP_API const std::map& getPoseBodyPartMapping(const PoseModel poseModel); + OP_API const std::string& getPoseProtoTxt(const PoseModel poseModel); + OP_API const std::string& getPoseTrainedModel(const PoseModel poseModel); + OP_API unsigned int getPoseNumberBodyParts(const PoseModel poseModel); + OP_API const std::vector& getPosePartPairs(const PoseModel poseModel); + OP_API const std::vector& getPoseMapIndex(const PoseModel poseModel); + OP_API unsigned int getPoseMaxPeaks(); + OP_API float getPoseNetDecreaseFactor(const PoseModel poseModel); + OP_API unsigned int poseBodyPartMapStringToKey(const PoseModel poseModel, const std::string& string); + OP_API unsigned int poseBodyPartMapStringToKey(const PoseModel poseModel, const std::vector& strings); + + // Default NSM and body connector parameters + OP_API float getPoseDefaultNmsThreshold(const PoseModel poseModel, const bool maximizePositives = false); + OP_API float getPoseDefaultConnectInterMinAboveThreshold(const bool maximizePositives = false); + OP_API float getPoseDefaultConnectInterThreshold(const PoseModel poseModel, const bool maximizePositives = false); + OP_API unsigned int getPoseDefaultMinSubsetCnt(const bool maximizePositives = false); + OP_API float getPoseDefaultConnectMinSubsetScore(const bool maximizePositives = false); + OP_API bool addBkgChannel(const PoseModel poseModel); +} + +#endif // OPENPOSE_POSE_POSE_PARAMETERS_HPP diff --git a/openpose/include/openpose/pose/poseParametersRender.hpp b/openpose/include/openpose/pose/poseParametersRender.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ddd61e7fbe08a6b88f2cd15504e2d1ba5d0e4104 --- /dev/null +++ b/openpose/include/openpose/pose/poseParametersRender.hpp @@ -0,0 +1,425 @@ +#ifndef OPENPOSE_POSE_POSE_PARAMETERS_RENDER_HPP +#define OPENPOSE_POSE_POSE_PARAMETERS_RENDER_HPP + +#include +#include + +namespace op +{ + // Rendering parameters + const auto POSE_DEFAULT_ALPHA_KEYPOINT = 0.6f; + const auto POSE_DEFAULT_ALPHA_HEAT_MAP = 0.7f; + + // Model-Dependent Parameters + // CUDA-code Model-Dependent Parameters must be defined with #define + // BODY_25 + #define POSE_BODY_25_PAIRS_RENDER_GPU \ + 1,8, 1,2, 1,5, 2,3, 3,4, 5,6, 6,7, 8,9, 9,10, 10,11, 8,12, 12,13, 13,14, 1,0, 0,15, 15,17, 0,16, 16,18, 14,19,19,20,14,21, 11,22,22,23,11,24 + #define POSE_BODY_25_SCALES_RENDER_GPU 1 + #define POSE_BODY_25_COLORS_RENDER_GPU \ + 255.f, 0.f, 85.f, \ + 255.f, 0.f, 0.f, \ + 255.f, 85.f, 0.f, \ + 255.f, 170.f, 0.f, \ + 255.f, 255.f, 0.f, \ + 170.f, 255.f, 0.f, \ + 85.f, 255.f, 0.f, \ + 0.f, 255.f, 0.f, \ + 255.f, 0.f, 0.f, \ + 0.f, 255.f, 85.f, \ + 0.f, 255.f, 170.f, \ + 0.f, 255.f, 255.f, \ + 0.f, 170.f, 255.f, \ + 0.f, 85.f, 255.f, \ + 0.f, 0.f, 255.f, \ + 255.f, 0.f, 170.f, \ + 170.f, 0.f, 255.f, \ + 255.f, 0.f, 255.f, \ + 85.f, 0.f, 255.f, \ + 0.f, 0.f, 255.f, \ + 0.f, 0.f, 255.f, \ + 0.f, 0.f, 255.f, \ + 0.f, 255.f, 255.f, \ + 0.f, 255.f, 255.f, \ + 0.f, 255.f, 255.f + // COCO + #define POSE_COCO_PAIRS_RENDER_GPU \ + 1,2, 1,5, 2,3, 3,4, 5,6, 6,7, 1,8, 8,9, 9,10, 1,11, 11,12, 12,13, 1,0, 0,14, 14,16, 0,15, 15,17 + #define POSE_COCO_SCALES_RENDER_GPU 1 + #define POSE_COCO_COLORS_RENDER_GPU \ + 255.f, 0.f, 85.f, \ + 255.f, 0.f, 0.f, \ + 255.f, 85.f, 0.f, \ + 255.f, 170.f, 0.f, \ + 255.f, 255.f, 0.f, \ + 170.f, 255.f, 0.f, \ + 85.f, 255.f, 0.f, \ + 0.f, 255.f, 0.f, \ + 0.f, 255.f, 85.f, \ + 0.f, 255.f, 170.f, \ + 0.f, 255.f, 255.f, \ + 0.f, 170.f, 255.f, \ + 0.f, 85.f, 255.f, \ + 0.f, 0.f, 255.f, \ + 255.f, 0.f, 170.f, \ + 170.f, 0.f, 255.f, \ + 255.f, 0.f, 255.f, \ + 85.f, 0.f, 255.f + // MPI + // MPI colors chosen such that they are closed to COCO colors + #define POSE_MPI_PAIRS_RENDER_GPU \ + 0,1, 1,2, 2,3, 3,4, 1,5, 5,6, 6,7, 1,14, 14,8, 8,9, 9,10, 14,11, 11,12, 12,13 + #define POSE_MPI_SCALES_RENDER_GPU 1 + #define POSE_MPI_COLORS_RENDER_GPU \ + 255.f, 0.f, 85.f, \ + 255.f, 0.f, 0.f, \ + 255.f, 85.f, 0.f, \ + 255.f, 170.f, 0.f, \ + 255.f, 255.f, 0.f, \ + 170.f, 255.f, 0.f, \ + 85.f, 255.f, 0.f, \ + 43.f, 255.f, 0.f, \ + 0.f, 255.f, 0.f, \ + 0.f, 255.f, 85.f, \ + 0.f, 255.f, 170.f, \ + 0.f, 255.f, 255.f, \ + 0.f, 170.f, 255.f, \ + 0.f, 85.f, 255.f, \ + 0.f, 0.f, 255.f + // BODY_19 + #define POSE_BODY_19_PAIRS_RENDER_GPU \ + 1,8, 1,2, 1,5, 2,3, 3,4, 5,6, 6,7, 8,9, 9,10, 10,11, 8,12, 12,13, 13,14, 1,0, 0,15, 15,17, 0,16, 16,18 + #define POSE_BODY_19_SCALES_RENDER_GPU 1 + #define POSE_BODY_19_COLORS_RENDER_GPU \ + 255.f, 0.f, 85.f, \ + 255.f, 0.f, 0.f, \ + 255.f, 85.f, 0.f, \ + 255.f, 170.f, 0.f, \ + 255.f, 255.f, 0.f, \ + 170.f, 255.f, 0.f, \ + 85.f, 255.f, 0.f, \ + 0.f, 255.f, 0.f, \ + 255.f, 0.f, 0.f, \ + 0.f, 255.f, 85.f, \ + 0.f, 255.f, 170.f, \ + 0.f, 255.f, 255.f, \ + 0.f, 170.f, 255.f, \ + 0.f, 85.f, 255.f, \ + 0.f, 0.f, 255.f, \ + 255.f, 0.f, 170.f, \ + 170.f, 0.f, 255.f, \ + 255.f, 0.f, 255.f, \ + 85.f, 0.f, 255.f + // BODY_23 + #define POSE_BODY_23_PAIRS_RENDER_GPU \ + 1,7, 4,10, 0,1, 0,4, 1,2, 2,3, 4,5, 5,6, 7,8, 8,9, 10,11, 11,12, 0,13, 13,15, 0,14, 14,16, 12,17,17,18,12,19, 9,20,20,21,9,22 + #define POSE_BODY_23_SCALES_RENDER_GPU 1 + #define POSE_BODY_23_COLORS_RENDER_GPU \ + 255.f, 0.f, 85.f, \ + 255.f, 0.f, 0.f, \ + 255.f, 85.f, 0.f, \ + 255.f, 170.f, 0.f, \ + 255.f, 255.f, 0.f, \ + 170.f, 255.f, 0.f, \ + 85.f, 255.f, 0.f, \ + 0.f, 255.f, 0.f, \ + 255.f, 0.f, 0.f, \ + 0.f, 255.f, 85.f, \ + 0.f, 255.f, 170.f, \ + 0.f, 255.f, 255.f, \ + 0.f, 170.f, 255.f, \ + 0.f, 85.f, 255.f, \ + 0.f, 0.f, 255.f, \ + 255.f, 0.f, 170.f, \ + 170.f, 0.f, 255.f, \ + 255.f, 0.f, 255.f, \ + 85.f, 0.f, 255.f, \ + 0.f, 0.f, 255.f, \ + 0.f, 0.f, 255.f, \ + 0.f, 0.f, 255.f, \ + 0.f, 255.f, 255.f, \ + 0.f, 255.f, 255.f, \ + 0.f, 255.f, 255.f + // BODY_25B + #define POSE_BODY_25B_PAIRS_RENDER_GPU \ + 0,1, 0,2, 1,3, 2,4, 5,7, 6,8, 7,9, 8,10, 5,11, 6,12, 11,13, 12,14, 13,15, 14,16, \ + 15,19, 19,20, 15,21, 16,22, 22,23, 16,24, 5,17, \ + 6,17, 17,18, 11,12 + #define POSE_BODY_25B_SCALES_RENDER_GPU 1 + #define POSE_BODY_25B_COLORS_RENDER_GPU \ + 255.f, 0.f, 85.f, \ + 170.f, 0.f, 255.f, \ + 255.f, 0.f, 170.f, \ + 85.f, 0.f, 255.f, \ + 255.f, 0.f, 255.f, \ + 170.f, 255.f, 0.f, \ + 255.f, 85.f, 0.f, \ + 85.f, 255.f, 0.f, \ + 255.f, 170.f, 0.f, \ + 0.f, 255.f, 0.f, \ + 255.f, 255.f, 0.f, \ + 0.f, 170.f, 255.f, \ + 0.f, 255.f, 85.f, \ + 0.f, 85.f, 255.f, \ + 0.f, 255.f, 170.f, \ + 0.f, 0.f, 255.f, \ + 0.f, 255.f, 255.f, \ + 255.f, 0.f, 0.f, \ + 255.f, 0.f, 0.f, \ + 0.f, 0.f, 255.f, \ + 0.f, 0.f, 255.f, \ + 0.f, 0.f, 255.f, \ + 0.f, 255.f, 255.f, \ + 0.f, 255.f, 255.f, \ + 0.f, 255.f, 255.f + // BODY_135 + // Hand color selection + // http://www.perbang.dk/rgbgradient/ + // 1. Main color + // - Each finger of the right hand: 11 steps from FF0000 to FF0001 and pick last 5 from HSV gradient. + // - Each finger of the left hand: 21 steps from FF0000 to FF0001, choosing 4 among first 6 (HSV grad.), + // and then green. + // Note: Choosing first 5 from 11 steps was giving 2 very close greens + // 2. Gradient color from wrist to finger tips + // - Inside each finger: 5 steps from main color to 000000, and selecting first 4 from RGB gradient. + // Note: Used HSV gradient for red finger. + const auto H135 = 25; + const auto F135 = H135 + 40; + // 15,19, 19,20, 15,21, 16,22, 22,23, 16,24, 5,17, + // 6,17, 17,18, 11,12, + #define POSE_BODY_135_PAIRS_RENDER_GPU \ + 0,1, 0,2, 1,3, 2,4, 5,7, 6,8, 7,9, 8,10, 5,11, 6,12, 11,13, 12,14, 13,15, 14,16, \ + 15,19, 19,20, 15,21, 16,22, 22,23, 16,24, 5,6, 17,18, 11,12, \ + \ + 9,H135+0, H135+0,H135+1, H135+1,H135+2, H135+2,H135+3, 9,H135+4, H135+4,H135+5, H135+5,H135+6, H135+6,H135+7, \ + 9,H135+8, H135+8,H135+9, H135+9,H135+10, H135+10,H135+11, 9,H135+12, H135+12,H135+13, H135+13,H135+14, H135+14,H135+15, \ + 9,H135+16, H135+16,H135+17, H135+17,H135+18, H135+18,H135+19, \ + \ + 10,H135+20, H135+20,H135+21, H135+21,H135+22, H135+22,H135+23, 10,H135+24, H135+24,H135+25, H135+25,H135+26, H135+26,H135+27, \ + 10,H135+28, H135+28,H135+29, H135+29,H135+30, H135+30,H135+31, 10,H135+32, H135+32,H135+33, H135+33,H135+34, H135+34,H135+35, \ + 10,H135+36, H135+36,H135+37, H135+37,H135+38, H135+38,H135+39, \ + \ + F135+0,F135+1, F135+1,F135+2, F135+2,F135+3, F135+3,F135+4, F135+4,F135+5, F135+5,F135+6, F135+6,F135+7, F135+7,F135+8, F135+8,F135+9, F135+9,F135+10, F135+10,F135+11, F135+11,F135+12, F135+12,F135+13, F135+13,F135+14, F135+14,F135+15, F135+15,F135+16, F135+17,F135+18, F135+18,F135+19, F135+19,F135+20, \ + F135+20,F135+21, F135+22,F135+23, F135+23,F135+24, F135+24,F135+25, F135+25,F135+26, F135+27,F135+28, F135+28,F135+29, F135+29,F135+30, F135+31,F135+32, F135+32,F135+33, F135+33,F135+34, F135+34,F135+35, F135+36,F135+37, F135+37,F135+38, F135+38,F135+39, F135+39,F135+40, F135+40,F135+41, \ + F135+41,F135+36, F135+42,F135+43, F135+43,F135+44, F135+44,F135+45, F135+45,F135+46, F135+46,F135+47, F135+47,F135+42, F135+48,F135+49, F135+49,F135+50, F135+50,F135+51, F135+51,F135+52, F135+52,F135+53, F135+53,F135+54, F135+54,F135+55, F135+55,F135+56, F135+56,F135+57, F135+57,F135+58, \ + F135+58,F135+59, F135+59,F135+48, F135+60,F135+61, F135+61,F135+62, F135+62,F135+63, F135+63,F135+64, F135+64,F135+65, F135+65,F135+66, F135+66,F135+67, F135+67,F135+60 + // Disabled really noisy values + #define POSE_BODY_135_SCALES_RENDER_GPU \ + 1.f,1.f,1.f,1.f,1.f, 1.f,1.f,1.f,1.f,1.f, 1.f,1.f,1.f,1.f,1.f, 1.f,1.f, \ + 0.00f,0.00f, \ + 1.f,1.f,1.f,1.f,1.f,1.f, \ + 0.60f,0.60f,0.60f,0.60f,0.60f, 0.60f,0.60f,0.60f,0.60f,0.60f, 0.60f,0.60f,0.60f,0.60f,0.60f, 0.60f,0.60f,0.60f,0.60f,0.60f, \ + 0.60f,0.60f,0.60f,0.60f,0.60f, 0.60f,0.60f,0.60f,0.60f,0.60f, 0.60f,0.60f,0.60f,0.60f,0.60f, 0.60f,0.60f,0.60f,0.60f,0.60f, \ + 0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f, \ + 0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f, \ + 0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f, \ + 0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f + // First 0.45f row: + // 0.00f,0.00f,0.00f,0.00f,0.00f, 0.00f,0.00f,0.00f,0.00f,0.00f, 0.00f,0.00f,0.00f,0.00f,0.00f, 0.00f,0.00f,0.45f,0.45f,0.45f, + #define POSE_BODY_135_COLORS_RENDER_GPU \ + 255.f, 0.f, 85.f, \ + 170.f, 0.f, 255.f, \ + 255.f, 0.f, 170.f, \ + 85.f, 0.f, 255.f, \ + 255.f, 0.f, 255.f, \ + 170.f, 255.f, 0.f, \ + 255.f, 85.f, 0.f, \ + 85.f, 255.f, 0.f, \ + 255.f, 170.f, 0.f, \ + 0.f, 255.f, 0.f, \ + 255.f, 255.f, 0.f, \ + 0.f, 170.f, 255.f, \ + 0.f, 255.f, 85.f, \ + 0.f, 85.f, 255.f, \ + 0.f, 255.f, 170.f, \ + 0.f, 0.f, 255.f, \ + 0.f, 255.f, 255.f, \ + 255.f, 0.f, 0.f, \ + 255.f, 0.f, 0.f, \ + \ + 0.f, 0.f, 255.f, \ + 0.f, 0.f, 255.f, \ + 0.f, 0.f, 255.f, \ + 0.f, 255.f, 255.f, \ + 0.f, 255.f, 255.f, \ + 0.f, 255.f, 255.f, \ + \ + 255.f, 0.f, 0.f, \ + 191.f, 47.f, 47.f, \ + 127.f, 63.f, 63.f, \ + 63.f, 47.f, 47.f, \ + 255.f, 76.f, 0.f, \ + 191.f, 57.f, 0.f, \ + 127.f, 38.f, 0.f, \ + 63.f, 19.f, 0.f, \ + 255.f, 152.f, 0.f, \ + 191.f, 114.f, 0.f, \ + 127.f, 76.f, 0.f, \ + 63.f, 38.f, 0.f, \ + 255.f, 255.f, 0.f, \ + 191.f, 191.f, 0.f, \ + 127.f, 127.f, 0.f, \ + 63.f, 63.f, 0.f, \ + 0.f, 255.f, 0.f, \ + 0.f, 191.f, 0.f, \ + 0.f, 127.f, 0.f, \ + 0.f, 63.f, 0.f, \ + \ + 255.f, 0.f, 153.f, \ + 191.f, 0.f, 114.f, \ + 127.f, 0.f, 76.f, \ + 63.f, 0.f, 38.f, \ + 203.f, 0.f, 255.f, \ + 152.f, 0.f, 191.f, \ + 101.f, 0.f, 127.f, \ + 50.f, 0.f, 63.f, \ + 50.f, 0.f, 255.f, \ + 37.f, 0.f, 191.f, \ + 25.f, 0.f, 127.f, \ + 12.f, 0.f, 63.f, \ + 0.f, 102.f, 255.f, \ + 0.f, 76.f, 191.f, \ + 0.f, 51.f, 127.f, \ + 0.f, 25.f, 63.f, \ + 0.f, 255.f, 255.f, \ + 0.f, 191.f, 191.f, \ + 0.f, 127.f, 127.f, \ + 0.f, 63.f, 63.f, \ + \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f, \ + 255.f, 255.f, 255.f + + // CAR_12 + #define POSE_CAR_12_PAIRS_RENDER_GPU \ + 4,5, 4,6, 4,0, 0,2, 4,8, 8,10, 5,7, 5,1, 1,3, 5,9, 9,11, 0,1, 8,9, 2,3, 6,7, 10,11, 6,2,7,3, 6,10,7,11 + // 4,5, 4,6, 4,0, 0,2, 4,8, 8,10, 5,7, 5,1, 1,3, 5,9, 9,11 + #define POSE_CAR_12_SCALES_RENDER_GPU 0.5 + #define POSE_CAR_12_COLORS_RENDER_GPU \ + 0.f, 255.f, 0.f, \ + 0.f, 255.f, 0.f, \ + 255.f, 255.f, 0.f, \ + 255.f, 255.f, 0.f, \ + \ + 255.f, 0.f, 0.f, \ + 255.f, 0.f, 0.f, \ + 255.f, 75.f, 75.f, \ + 255.f, 75.f, 75.f, \ + \ + 0.f, 0.f, 255.f, \ + 0.f, 0.f, 255.f, \ + 255.f, 0.f, 255.f, \ + 255.f, 0.f, 255.f + + // CAR_22 + #define POSE_CAR_22_PAIRS_RENDER_GPU \ + 0,1,1,3,3,2,2,0, 6,7,7,16,16,17,17,6, 12,13,13,14,14,15,15,12, 6,8,7,8,6,9,7,9,6,4,7,5, 12,11,13,10, \ + 16,18,17,18,16,19,17,19, 6,21,7,20 + #define POSE_CAR_22_SCALES_RENDER_GPU 0.625 + #define POSE_CAR_22_COLORS_RENDER_GPU \ + 255.f, 128.f, 128.f, \ + 255.f, 0.f, 0.f, \ + 64.f, 0.f, 0.f, \ + 255.f, 0.f, 0.f, \ + \ + 0.f, 255.f, 0.f, \ + 0.f, 255.f, 0.f, \ + \ + 0.f, 0.f, 64.f, \ + 128.f, 128.f, 255.f, \ + \ + 0.f, 255.f, 0.f, \ + 0.f, 255.f, 0.f, \ + \ + 0.f, 255.f, 0.f, \ + 0.f, 255.f, 0.f, \ + \ + 64.f, 0.f, 0.f, \ + 255.f, 128.f, 128.f, \ + 255.f, 0.f, 0.f, \ + 255.f, 0.f, 0.f, \ + \ + 0.f, 0.f, 255.f, \ + 0.f, 0.f, 255.f, \ + \ + 0.f, 255.f, 0.f, \ + 0.f, 255.f, 0.f, \ + \ + 0.f, 0.f, 255.f, \ + 0.f, 0.f, 64.f + + // Rendering functions + OP_API const std::vector& getPoseScales(const PoseModel poseModel); + OP_API const std::vector& getPoseColors(const PoseModel poseModel); + OP_API const std::vector& getPoseBodyPartPairsRender(const PoseModel poseModel); + OP_API unsigned int getNumberElementsToRender(const PoseModel poseModel); +} + +#endif // OPENPOSE_POSE_POSE_PARAMETERS_RENDER_HPP diff --git a/openpose/include/openpose/pose/poseRenderer.hpp b/openpose/include/openpose/pose/poseRenderer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..83fe90707be5fc17cb9cd3749f589ca23f85f398 --- /dev/null +++ b/openpose/include/openpose/pose/poseRenderer.hpp @@ -0,0 +1,33 @@ +#ifndef OPENPOSE_POSE_POSE_RENDERER_HPP +#define OPENPOSE_POSE_POSE_RENDERER_HPP + +#include +#include +#include + +namespace op +{ + class OP_API PoseRenderer + { + public: + PoseRenderer(const PoseModel poseModel); + + virtual ~PoseRenderer(); + + virtual void initializationOnThread(){}; + + virtual std::pair renderPose( + Array& outputData, const Array& poseKeypoints, const float scaleInputToOutput, + const float scaleNetToOutput = -1.f) = 0; + + protected: + const PoseModel mPoseModel; + const std::map mPartIndexToName; + + private: + + DELETE_COPY(PoseRenderer); + }; +} + +#endif // OPENPOSE_POSE_POSE_RENDERER_HPP diff --git a/openpose/include/openpose/pose/renderPose.hpp b/openpose/include/openpose/pose/renderPose.hpp new file mode 100644 index 0000000000000000000000000000000000000000..41da3e680c07532ce22fbf4b01632c798ec27fc8 --- /dev/null +++ b/openpose/include/openpose/pose/renderPose.hpp @@ -0,0 +1,45 @@ +#ifndef OPENPOSE_POSE_RENDER_POSE_HPP +#define OPENPOSE_POSE_RENDER_POSE_HPP + +#include +#include +#include + +namespace op +{ + OP_API void renderPoseKeypointsCpu( + Array& frameArray, const Array& poseKeypoints, const PoseModel poseModel, + const float renderThreshold, const bool blendOriginalFrame = true); + + void renderPoseKeypointsGpu( + float* framePtr, float* maxPtr, float* minPtr, float* scalePtr, const PoseModel poseModel, + const int numberPeople, const Point& frameSize, const float* const posePtr, + const float renderThreshold, const bool googlyEyes = false, const bool blendOriginalFrame = true, + const float alphaBlending = POSE_DEFAULT_ALPHA_KEYPOINT); + + void renderPoseHeatMapGpu( + float* frame, const Point& frameSize, const float* const heatMapPtr, const Point& heatMapSize, + const float scaleToKeepRatio, const unsigned int part, + const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP); + + void renderPoseHeatMapsGpu( + float* frame, const PoseModel poseModel, const Point& frameSize, const float* const heatMapPtr, + const Point& heatMapSize, const float scaleToKeepRatio, + const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP); + + void renderPosePAFGpu( + float* framePtr, const PoseModel poseModel, const Point& frameSize, const float* const heatMapPtr, + const Point& heatMapSize, const float scaleToKeepRatio, const int part, + const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP); + + void renderPosePAFsGpu( + float* framePtr, const PoseModel poseModel, const Point& frameSize, const float* const heatMapPtr, + const Point& heatMapSize, const float scaleToKeepRatio, + const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP); + + void renderPoseDistanceGpu( + float* framePtr, const Point& frameSize, const float* const heatMapPtr, const Point& heatMapSize, + const float scaleToKeepRatio, const unsigned int part, const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP); +} + +#endif // OPENPOSE_POSE_RENDER_POSE_HPP diff --git a/openpose/include/openpose/pose/wPoseExtractor.hpp b/openpose/include/openpose/pose/wPoseExtractor.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0b1980a6889dce8641ba7ff8b87ae227b3d16e6e --- /dev/null +++ b/openpose/include/openpose/pose/wPoseExtractor.hpp @@ -0,0 +1,114 @@ +#ifndef OPENPOSE_POSE_W_POSE_EXTRACTOR_HPP +#define OPENPOSE_POSE_W_POSE_EXTRACTOR_HPP + +#include +#include +#include + +namespace op +{ + template + class WPoseExtractor : public Worker + { + public: + explicit WPoseExtractor(const std::shared_ptr& poseExtractorSharedPtr); + + virtual ~WPoseExtractor(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + std::shared_ptr spPoseExtractor; + + DELETE_COPY(WPoseExtractor); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WPoseExtractor::WPoseExtractor(const std::shared_ptr& poseExtractorSharedPtr) : + spPoseExtractor{poseExtractorSharedPtr} + { + } + + template + WPoseExtractor::~WPoseExtractor() + { + } + + template + void WPoseExtractor::initializationOnThread() + { + try + { + spPoseExtractor->initializationOnThread(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WPoseExtractor::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Extract people pose + for (auto i = 0u ; i < tDatums->size() ; i++) + // for (auto& tDatum : *tDatums) + { + auto& tDatumPtr = (*tDatums)[i]; + // OpenPose net forward pass + spPoseExtractor->forwardPass( + tDatumPtr->inputNetData, Point{tDatumPtr->cvInputData.cols(), tDatumPtr->cvInputData.rows()}, + tDatumPtr->scaleInputToNetInputs, tDatumPtr->poseNetOutput, tDatumPtr->id); + // OpenPose keypoint detector + tDatumPtr->poseCandidates = spPoseExtractor->getCandidatesCopy(); + tDatumPtr->poseHeatMaps = spPoseExtractor->getHeatMapsCopy(); + tDatumPtr->poseKeypoints = spPoseExtractor->getPoseKeypoints().clone(); + tDatumPtr->poseScores = spPoseExtractor->getPoseScores().clone(); + tDatumPtr->scaleNetToOutput = spPoseExtractor->getScaleNetToOutput(); + // Keep desired top N people + spPoseExtractor->keepTopPeople(tDatumPtr->poseKeypoints, tDatumPtr->poseScores); + // ID extractor (experimental) + tDatumPtr->poseIds = spPoseExtractor->extractIdsLockThread( + tDatumPtr->poseKeypoints, tDatumPtr->cvInputData, i, tDatumPtr->id); + // Tracking (experimental) + spPoseExtractor->trackLockThread( + tDatumPtr->poseKeypoints, tDatumPtr->poseIds, tDatumPtr->cvInputData, i, tDatumPtr->id); + } + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WPoseExtractor); +} + +#endif // OPENPOSE_POSE_W_POSE_EXTRACTOR_HPP diff --git a/openpose/include/openpose/pose/wPoseExtractorNet.hpp b/openpose/include/openpose/pose/wPoseExtractorNet.hpp new file mode 100644 index 0000000000000000000000000000000000000000..868300894607a2a0aee3a61d494866370287ee96 --- /dev/null +++ b/openpose/include/openpose/pose/wPoseExtractorNet.hpp @@ -0,0 +1,102 @@ +#ifndef OPENPOSE_POSE_W_POSE_EXTRACTOR_NET_HPP +#define OPENPOSE_POSE_W_POSE_EXTRACTOR_NET_HPP + +#include +#include +#include + +namespace op +{ + template + class WPoseExtractorNet : public Worker + { + public: + explicit WPoseExtractorNet(const std::shared_ptr& poseExtractorSharedPtr); + + virtual ~WPoseExtractorNet(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + std::shared_ptr spPoseExtractorNet; + + DELETE_COPY(WPoseExtractorNet); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WPoseExtractorNet::WPoseExtractorNet(const std::shared_ptr& poseExtractorSharedPtr) : + spPoseExtractorNet{poseExtractorSharedPtr} + { + } + + template + WPoseExtractorNet::~WPoseExtractorNet() + { + } + + template + void WPoseExtractorNet::initializationOnThread() + { + try + { + spPoseExtractorNet->initializationOnThread(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WPoseExtractorNet::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Extract people pose + for (auto& tDatumPtr : *tDatums) + { + spPoseExtractorNet->forwardPass( + tDatumPtr->inputNetData, Point{tDatumPtr->cvInputData.cols(), tDatumPtr->cvInputData.rows()}, + tDatumPtr->scaleInputToNetInputs, tDatumPtr->poseNetOutput); + tDatumPtr->poseCandidates = spPoseExtractorNet->getCandidatesCopy(); + tDatumPtr->poseHeatMaps = spPoseExtractorNet->getHeatMapsCopy(); + tDatumPtr->poseKeypoints = spPoseExtractorNet->getPoseKeypoints().clone(); + tDatumPtr->poseScores = spPoseExtractorNet->getPoseScores().clone(); + tDatumPtr->scaleNetToOutput = spPoseExtractorNet->getScaleNetToOutput(); + } + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WPoseExtractorNet); +} + +#endif // OPENPOSE_POSE_W_POSE_EXTRACTOR_NET_HPP diff --git a/openpose/include/openpose/pose/wPoseRenderer.hpp b/openpose/include/openpose/pose/wPoseRenderer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c706b416c596023e7faa04c9bcdd4aa9f9ee3ba4 --- /dev/null +++ b/openpose/include/openpose/pose/wPoseRenderer.hpp @@ -0,0 +1,95 @@ +#ifndef OPENPOSE_POSE_W_POSE_RENDERER_HPP +#define OPENPOSE_POSE_W_POSE_RENDERER_HPP + +#include +#include +#include + +namespace op +{ + template + class WPoseRenderer : public Worker + { + public: + explicit WPoseRenderer(const std::shared_ptr& poseRendererSharedPtr); + + virtual ~WPoseRenderer(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + std::shared_ptr spPoseRenderer; + + DELETE_COPY(WPoseRenderer); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WPoseRenderer::WPoseRenderer(const std::shared_ptr& poseRendererSharedPtr) : + spPoseRenderer{poseRendererSharedPtr} + { + } + + template + WPoseRenderer::~WPoseRenderer() + { + } + + template + void WPoseRenderer::initializationOnThread() + { + try + { + spPoseRenderer->initializationOnThread(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WPoseRenderer::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Render people pose + for (auto& tDatumPtr : *tDatums) + tDatumPtr->elementRendered = spPoseRenderer->renderPose( + tDatumPtr->outputData, tDatumPtr->poseKeypoints, (float)tDatumPtr->scaleInputToOutput, + (float)tDatumPtr->scaleNetToOutput); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WPoseRenderer); +} + +#endif // OPENPOSE_POSE_W_POSE_RENDERER_HPP diff --git a/openpose/include/openpose/producer/datumProducer.hpp b/openpose/include/openpose/producer/datumProducer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..062c65f3eaf71914b2d9c59fd6391416523bedd2 --- /dev/null +++ b/openpose/include/openpose/producer/datumProducer.hpp @@ -0,0 +1,193 @@ +#ifndef OPENPOSE_PRODUCER_DATUM_PRODUCER_HPP +#define OPENPOSE_PRODUCER_DATUM_PRODUCER_HPP + +#include +#include // std::numeric_limits +#include +#include +#include +#include + +namespace op +{ + template + class DatumProducer + { + public: + explicit DatumProducer( + const std::shared_ptr& producerSharedPtr, + const unsigned long long frameFirst = 0, const unsigned long long frameStep = 1, + const unsigned long long frameLast = std::numeric_limits::max(), + const std::shared_ptr, std::atomic>>& videoSeekSharedPtr = nullptr); + + virtual ~DatumProducer(); + + std::pair>>> checkIfRunningAndGetDatum(); + + private: + const unsigned long long mNumberFramesToProcess; + std::shared_ptr spProducer; + unsigned long long mGlobalCounter; + unsigned long long mFrameStep; + unsigned int mNumberConsecutiveEmptyFrames; + std::shared_ptr, std::atomic>> spVideoSeek; + + void checkIfTooManyConsecutiveEmptyFrames( + unsigned int& numberConsecutiveEmptyFrames, const bool emptyFrame) const; + + DELETE_COPY(DatumProducer); + }; +} + + + + + +// Implementation +#include +#include +namespace op +{ + // Auxiliary functions for DatumProducer in order to 1) Reduce compiling time and 2) Remove OpenCV deps. + OP_API void datumProducerConstructor( + const std::shared_ptr& producerSharedPtr, const unsigned long long frameFirst, + const unsigned long long frameStep, const unsigned long long frameLast); + OP_API void datumProducerConstructorTooManyConsecutiveEmptyFrames( + unsigned int& numberConsecutiveEmptyFrames, const bool emptyFrame); + OP_API bool datumProducerConstructorRunningAndGetDatumIsDatumProducerRunning( + const std::shared_ptr& producerSharedPtr, const unsigned long long numberFramesToProcess, + const unsigned long long globalCounter); + OP_API void datumProducerConstructorRunningAndGetDatumApplyPlayerControls( + const std::shared_ptr& producerSharedPtr, + const std::shared_ptr, std::atomic>>& videoSeekSharedPtr); + OP_API unsigned long long datumProducerConstructorRunningAndGetNextFrameNumber( + const std::shared_ptr& producerSharedPtr); + OP_API void datumProducerConstructorRunningAndGetDatumFrameIntegrity(Matrix& matrix); + + template + DatumProducer::DatumProducer( + const std::shared_ptr& producerSharedPtr, + const unsigned long long frameFirst, const unsigned long long frameStep, + const unsigned long long frameLast, + const std::shared_ptr, std::atomic>>& videoSeekSharedPtr) : + mNumberFramesToProcess{(frameLast != std::numeric_limits::max() + ? frameLast - frameFirst : frameLast)}, + spProducer{producerSharedPtr}, + mGlobalCounter{0ll}, + mFrameStep{frameStep}, + mNumberConsecutiveEmptyFrames{0u}, + spVideoSeek{videoSeekSharedPtr} + { + try + { + datumProducerConstructor(producerSharedPtr, frameFirst, frameStep, frameLast); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + DatumProducer::~DatumProducer() + { + } + + template + std::pair>>> DatumProducer::checkIfRunningAndGetDatum() + { + try + { + // If producer released -> it sends an empty Matrix + a datumProducerRunning signal + const bool datumProducerRunning = datumProducerConstructorRunningAndGetDatumIsDatumProducerRunning( + spProducer, mNumberFramesToProcess, mGlobalCounter); + // If device is open + auto datums = std::make_shared>>(); + if (datumProducerRunning) + { + // Fast forward/backward - Seek to specific frame index desired + datumProducerConstructorRunningAndGetDatumApplyPlayerControls(spProducer, spVideoSeek); + // Get Matrix vector + std::string nextFrameName = spProducer->getNextFrameName(); + const unsigned long long nextFrameNumber = datumProducerConstructorRunningAndGetNextFrameNumber( + spProducer); + const std::vector matrices = spProducer->getFrames(); + // Check frames are not empty + checkIfTooManyConsecutiveEmptyFrames( + mNumberConsecutiveEmptyFrames, matrices.empty() || matrices[0].empty()); + if (!matrices.empty()) + { + // Get camera parameters + const std::vector cameraMatrices = spProducer->getCameraMatrices(); + const std::vector cameraExtrinsics = spProducer->getCameraExtrinsics(); + const std::vector cameraIntrinsics = spProducer->getCameraIntrinsics(); + // Resize datum + datums->resize(matrices.size()); + // Datum cannot be assigned before resize() + auto& datumPtr = (*datums)[0]; + datumPtr = std::make_shared(); + // Filling first element + std::swap(datumPtr->name, nextFrameName); + datumPtr->frameNumber = nextFrameNumber; + datumPtr->cvInputData = matrices[0]; + datumProducerConstructorRunningAndGetDatumFrameIntegrity(datumPtr->cvInputData); + if (!cameraMatrices.empty()) + { + datumPtr->cameraMatrix = cameraMatrices[0]; + datumPtr->cameraExtrinsics = cameraExtrinsics[0]; + datumPtr->cameraIntrinsics = cameraIntrinsics[0]; + } + // Initially, cvOutputData = cvInputData. No performance hit (both cv::Mat share raw memory) + datumPtr->cvOutputData = datumPtr->cvInputData; + // Resize if it's stereo-system + if (datums->size() > 1) + { + // Stereo-system: Assign all Matrices + for (auto i = 1u ; i < datums->size() ; i++) + { + auto& datumIPtr = (*datums)[i]; + datumIPtr = std::make_shared(); + datumIPtr->name = datumPtr->name; + datumIPtr->frameNumber = datumPtr->frameNumber; + datumIPtr->cvInputData = matrices[i]; + datumProducerConstructorRunningAndGetDatumFrameIntegrity(datumPtr->cvInputData); + datumIPtr->cvOutputData = datumIPtr->cvInputData; + if (cameraMatrices.size() > i) + { + datumIPtr->cameraMatrix = cameraMatrices[i]; + datumIPtr->cameraExtrinsics = cameraExtrinsics[i]; + datumIPtr->cameraIntrinsics = cameraIntrinsics[i]; + } + } + } + // Check producer is running + if ((*datums)[0]->cvInputData.empty()) + datums = nullptr; + // Increase counter if successful image + if (datums != nullptr) + mGlobalCounter += mFrameStep; + } + } + // Return result + return std::make_pair(datumProducerRunning, datums); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return std::make_pair(false, std::make_shared>>()); + } + } + + template + void DatumProducer::checkIfTooManyConsecutiveEmptyFrames( + unsigned int& numberConsecutiveEmptyFrames, const bool emptyFrame) const + { + datumProducerConstructorTooManyConsecutiveEmptyFrames( + numberConsecutiveEmptyFrames, emptyFrame); + } + + extern template class DatumProducer; +} + + +#endif // OPENPOSE_PRODUCER_DATUM_PRODUCER_HPP diff --git a/openpose/include/openpose/producer/enumClasses.hpp b/openpose/include/openpose/producer/enumClasses.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2bb4d7e9e644e4677b5de4653f3f4e1629fa9d33 --- /dev/null +++ b/openpose/include/openpose/producer/enumClasses.hpp @@ -0,0 +1,48 @@ +#ifndef OPENPOSE_PRODUCER_ENUM_CLASSES_HPP +#define OPENPOSE_PRODUCER_ENUM_CLASSES_HPP + +namespace op +{ + enum class ProducerFpsMode : bool + { + /** The frames will be extracted at the original source fps (frames might be skipped or repeated). */ + OriginalFps, + /** The frames will be extracted when the software retrieves them (frames will not be skipped or repeated). */ + RetrievalFps, + }; + + enum class ProducerProperty : unsigned char + { + AutoRepeat = 0, + Flip, + Rotation, + FrameStep, + NumberViews, + Size, + }; + + /** + * Type of producers + * An enum class in which all the possible type of Producer are included. In order to add a new Producer, + * include its name in this enum and add a new 'else if' statement inside ProducerFactory::createProducer(). + */ + enum class ProducerType : unsigned char + { + /** Stereo FLIR (Point-Grey) camera reader. Based on Spinnaker SDK. */ + FlirCamera, + /** An image directory reader. It is able to read images on a folder with a interface similar to the OpenCV + * cv::VideoCapture. + */ + ImageDirectory, + /** An IP camera frames extractor, extending the functionality of cv::VideoCapture. */ + IPCamera, + /** A video frames extractor, extending the functionality of cv::VideoCapture. */ + Video, + /** A webcam frames extractor, extending the functionality of cv::VideoCapture. */ + Webcam, + /** No type defined. Default state when no specific Producer has been picked yet. */ + None, + }; +} + +#endif // OPENPOSE_PRODUCER_ENUM_CLASSES_HPP diff --git a/openpose/include/openpose/producer/flirReader.hpp b/openpose/include/openpose/producer/flirReader.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0470089527fd775093e6e86cda16465e4229ac97 --- /dev/null +++ b/openpose/include/openpose/producer/flirReader.hpp @@ -0,0 +1,55 @@ +#ifndef OPENPOSE_PRODUCER_FLIR_READER_HPP +#define OPENPOSE_PRODUCER_FLIR_READER_HPP + +#include +#include +#include + +namespace op +{ + /** + * FlirReader is an abstract class to extract frames from a FLIR stereo-camera system. Its interface imitates the + * cv::VideoCapture class, so it can be used quite similarly to the cv::VideoCapture class. Thus, + * it is quite similar to VideoReader and WebcamReader. + */ + class OP_API FlirReader : public Producer + { + public: + /** + * Constructor of FlirReader. It opens all the available FLIR cameras + */ + explicit FlirReader(const std::string& cameraParametersPath, const Point& cameraResolution, + const bool undistortImage = true, const int cameraIndex = -1); + + virtual ~FlirReader(); + + std::vector getCameraMatrices(); + + std::vector getCameraExtrinsics(); + + std::vector getCameraIntrinsics(); + + std::string getNextFrameName(); + + bool isOpened() const; + + void release(); + + double get(const int capProperty); + + void set(const int capProperty, const double value); + + private: + SpinnakerWrapper mSpinnakerWrapper; + Point mResolution; + unsigned long long mFrameNameCounter; + + Matrix getRawFrame(); + + std::vector getRawFrames(); + + DELETE_COPY(FlirReader); + }; +} + +#endif // OPENPOSE_PRODUCER_FLIR_READER_HPP diff --git a/openpose/include/openpose/producer/headers.hpp b/openpose/include/openpose/producer/headers.hpp new file mode 100644 index 0000000000000000000000000000000000000000..55e84af84d798c899f8a884a8f0473aaedd162f5 --- /dev/null +++ b/openpose/include/openpose/producer/headers.hpp @@ -0,0 +1,17 @@ +#ifndef OPENPOSE_PRODUCER_HEADERS_HPP +#define OPENPOSE_PRODUCER_HEADERS_HPP + +// producer module +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // OPENPOSE_PRODUCER_HEADERS_HPP diff --git a/openpose/include/openpose/producer/imageDirectoryReader.hpp b/openpose/include/openpose/producer/imageDirectoryReader.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3a832687796692793f3dd62386a07def92b3b96d --- /dev/null +++ b/openpose/include/openpose/producer/imageDirectoryReader.hpp @@ -0,0 +1,62 @@ +#ifndef OPENPOSE_PRODUCER_IMAGE_DIRECTORY_READER_HPP +#define OPENPOSE_PRODUCER_IMAGE_DIRECTORY_READER_HPP + +#include +#include + +namespace op +{ + /** + * ImageDirectoryReader is an abstract class to extract frames from a image directory. Its interface imitates the + * cv::VideoCapture class, so it can be used quite similarly to the cv::VideoCapture class. Thus, + * it is quite similar to VideoReader and WebcamReader. + */ + class OP_API ImageDirectoryReader : public Producer + { + public: + /** + * Constructor of ImageDirectoryReader. It sets the image directory path from which the images will be loaded + * and generates a std::vector with the list of images on that directory. + * @param imageDirectoryPath const std::string parameter with the folder path containing the images. + * @param cameraParameterPath const std::string parameter with the folder path containing the camera + * parameters (only required if imageDirectorystereo > 1). + * @param numberViews const int parameter with the number of images per iteration (>1 would represent + * stereo processing). + */ + explicit ImageDirectoryReader( + const std::string& imageDirectoryPath, const std::string& cameraParameterPath = "", + const bool undistortImage = false, const int numberViews = -1); + + virtual ~ImageDirectoryReader(); + + std::string getNextFrameName(); + + inline bool isOpened() const + { + return (mFrameNameCounter >= 0); + } + + inline void release() + { + mFrameNameCounter = {-1ll}; + } + + double get(const int capProperty); + + void set(const int capProperty, const double value); + + private: + const std::string mImageDirectoryPath; + const std::vector mFilePaths; + Point mResolution; + long long mFrameNameCounter; + + Matrix getRawFrame(); + + std::vector getRawFrames(); + + DELETE_COPY(ImageDirectoryReader); + }; +} + +#endif // OPENPOSE_PRODUCER_IMAGE_DIRECTORY_READER_HPP diff --git a/openpose/include/openpose/producer/ipCameraReader.hpp b/openpose/include/openpose/producer/ipCameraReader.hpp new file mode 100644 index 0000000000000000000000000000000000000000..47bd890b3afcdbb6068deff2e778d9a3e2edf914 --- /dev/null +++ b/openpose/include/openpose/producer/ipCameraReader.hpp @@ -0,0 +1,52 @@ +#ifndef OPENPOSE_PRODUCER_IP_CAMERA_READER_HPP +#define OPENPOSE_PRODUCER_IP_CAMERA_READER_HPP + +#include +#include + +namespace op +{ + /** + * IpCameraReader is a wrapper of the cv::VideoCapture class for IP camera streaming. + */ + class OP_API IpCameraReader : public VideoCaptureReader + { + public: + /** + * Constructor of IpCameraReader. It opens the IP camera as a wrapper of cv::VideoCapture. + * @param cameraPath const std::string parameter with the full camera IP link. + */ + explicit IpCameraReader(const std::string& cameraPath, const std::string& cameraParameterPath = "", + const bool undistortImage = false); + + virtual ~IpCameraReader(); + + std::string getNextFrameName(); + + inline bool isOpened() const + { + return VideoCaptureReader::isOpened(); + } + + inline double get(const int capProperty) + { + return VideoCaptureReader::get(capProperty); + } + + inline void set(const int capProperty, const double value) + { + VideoCaptureReader::set(capProperty, value); + } + + private: + const std::string mPathName; + + Matrix getRawFrame(); + + std::vector getRawFrames(); + + DELETE_COPY(IpCameraReader); + }; +} + +#endif // OPENPOSE_PRODUCER_IP_CAMERA_READER_HPP diff --git a/openpose/include/openpose/producer/producer.hpp b/openpose/include/openpose/producer/producer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c00d43bfb3843ab90e2c351ab2115a1fa0520cdb --- /dev/null +++ b/openpose/include/openpose/producer/producer.hpp @@ -0,0 +1,189 @@ +#ifndef OPENPOSE_PRODUCER_PRODUCER_HPP +#define OPENPOSE_PRODUCER_PRODUCER_HPP + +#include +#include +#include + +namespace op +{ + /** + * Producer is an abstract class to extract frames from a source (image directory, video file, + * webcam stream, etc.). It has the basic and common functions (e.g., getFrame, release & isOpened). + */ + class OP_API Producer + { + public: + /** + * Constructor of Producer. + */ + explicit Producer(const ProducerType type, const std::string& cameraParameterPath, const bool undistortImage, + const int mNumberViews); + + /** + * Destructor of Producer. It is virtual so that any children class can implement + * its own destructor. + */ + virtual ~Producer(); + + /** + * Main function of Producer, it retrieves and returns a new frame from the frames producer. + * @return Mat with the new frame. + */ + Matrix getFrame(); + + /** + * Analogous to getFrame, but it could return > 1 frame. + * @return std::vector with the new frame(s). + */ + std::vector getFrames(); + + /** + * It retrieves and returns the camera matrixes from the frames producer. + * Virtual class because FlirReader implements their own. + * @return std::vector with the camera matrices. + */ + virtual std::vector getCameraMatrices(); + + /** + * It retrieves and returns the camera extrinsic parameters from the frames producer. + * Virtual class because FlirReader implements their own. + * @return std::vector with the camera extrinsic parameters. + */ + virtual std::vector getCameraExtrinsics(); + + /** + * It retrieves and returns the camera intrinsic parameters from the frames producer. + * Virtual class because FlirReader implements their own. + * @return std::vector with the camera intrinsic parameters. + */ + virtual std::vector getCameraIntrinsics(); + + /** + * This function returns a unique frame name (e.g., the frame number for video, the + * frame counter for webcam, the image name for image directory reader, etc.). + * @return std::string with an unique frame name. + */ + virtual std::string getNextFrameName() = 0; + + /** + * This function sets whether the producer must keep the original fps frame rate or extract the frames as quick + * as possible. + * @param fpsMode ProducerFpsMode parameter specifying the new value. + */ + void setProducerFpsMode(const ProducerFpsMode fpsMode); + + /** + * This function returns the type of producer (video, webcam, ...). + * @return ProducerType with the kind of producer. + */ + inline ProducerType getType() + { + return mType; + } + + /** + * This function returns whether the Producer instance is still opened and able + * to retrieve more frames. + * @return bool indicating whether the Producer is opened. + */ + virtual bool isOpened() const = 0; + + /** + * This function releases and closes the Producer. After it is called, no more frames + * can be retrieved from Producer::getFrames. + */ + virtual void release() = 0; + + /** + * This function is a wrapper of cv::VideoCapture::get. It allows getting different properties + * of the Producer (fps, width, height, etc.). See the OpenCV documentation for all the + * available properties. + * @param capProperty int indicating the property to be modified. + * @return double returning the property value. + */ + virtual double get(const int capProperty) = 0; + + /** + * This function is a wrapper of cv::VideoCapture::set. It allows setting different properties + * of the Producer (fps, width, height, etc.). See the OpenCV documentation for all the + * available properties. + * @param capProperty int indicating the property to be modified. + * @param value double indicating the new value to be assigned. + */ + virtual void set(const int capProperty, const double value) = 0; + + /** + * Extra attributes that VideoCapture::get/set do not contain. + * @param property ProducerProperty indicating the property to be modified. + */ + double get(const ProducerProperty property); + + /** + * Extra attributes that VideoCapture::get/set do not contain. + * @param property ProducerProperty indicating the property to be modified. + * @param value double indicating the new value to be assigned. + */ + void set(const ProducerProperty property, const double value); + + protected: + /** + * Protected function which checks that the frames keeps their integry (some OpenCV versions + * might return corrupted frames within a video or webcam with a size different to the + * standard resolution). If the frame is corrupted, it is set to an empty Mat. + * @param frame Mat with the frame matrix to be checked and modified. + */ + void checkFrameIntegrity(Matrix& frame); + + /** + * Protected function which checks that the frame producer has ended. If so, if resets + * or releases the producer according to mRepeatWhenFinished. + */ + void ifEndedResetOrRelease(); + + /** + * Protected function which forces the producer to get frames at the rate of get(CV_CAP_PROP_FPS). + */ + void keepDesiredFrameRate(); + + /** + * Function to be defined by its children class. It retrieves and returns a new frame from the frames producer. + * @return Mat with the new frame. + */ + virtual Matrix getRawFrame() = 0; + + /** + * Function to be defined by its children class. It retrieves and returns a new frame from the frames producer. + * It is equivalent to getRawFrame when more than 1 image can be returned. + * @return std::vector with the new frames. + */ + virtual std::vector getRawFrames() = 0; + + private: + const ProducerType mType; + ProducerFpsMode mProducerFpsMode; + std::array mProperties; + unsigned int mNumberEmptyFrames; + // For ProducerFpsMode::OriginalFps + bool mTrackingFps; + unsigned long long mFirstFrameTrackingFps; + unsigned long long mNumberFramesTrackingFps; + unsigned int mNumberSetPositionTrackingFps; + std::chrono::high_resolution_clock::time_point mClockTrackingFps; + // Camera parameters + CameraParameterReader mCameraParameterReader; + + DELETE_COPY(Producer); + }; + + /** + * This function returns the desired producer given the input parameters. + */ + OP_API std::shared_ptr createProducer( + const ProducerType producerType = ProducerType::None, const std::string& producerString = "", + const Point& cameraResolution = Point{-1,-1}, + const std::string& cameraParameterPath = "models/cameraParameters/", const bool undistortImage = true, + const int numberViews = -1); +} + +#endif // OPENPOSE_PRODUCER_PRODUCER_HPP diff --git a/openpose/include/openpose/producer/spinnakerWrapper.hpp b/openpose/include/openpose/producer/spinnakerWrapper.hpp new file mode 100644 index 0000000000000000000000000000000000000000..09fd09d857824f57f2c4108f7ab44ff9bc506c67 --- /dev/null +++ b/openpose/include/openpose/producer/spinnakerWrapper.hpp @@ -0,0 +1,52 @@ +#ifndef OPENPOSE_PRODUCER_SPINNAKER_WRAPPER_HPP +#define OPENPOSE_PRODUCER_SPINNAKER_WRAPPER_HPP + +#include + +namespace op +{ + /** + * SpinnakerWrapper is a subclass of SpinnakerWrapper. It decouples the final interface (meant to imitates + * cv::VideoCapture) from the Spinnaker SDK wrapper. + */ + class OP_API SpinnakerWrapper + { + public: + /** + * Constructor of SpinnakerWrapper. It opens all the available FLIR cameras + * cameraIndex = -1 means that all cameras are taken + */ + explicit SpinnakerWrapper(const std::string& cameraParameterPath, const Point& cameraResolution, + const bool undistortImage, const int cameraIndex = -1); + + virtual ~SpinnakerWrapper(); + + std::vector getRawFrames(); + + /** + * Note: The camera parameters are only read if undistortImage is true. This should be changed to add a + * new bool flag in the constructor, e.g., readCameraParameters + */ + std::vector getCameraMatrices() const; + + std::vector getCameraExtrinsics() const; + + std::vector getCameraIntrinsics() const; + + Point getResolution() const; + + bool isOpened() const; + + void release(); + + private: + // PIMPL idiom + // http://www.cppsamples.com/common-tasks/pimpl.html + struct ImplSpinnakerWrapper; + std::shared_ptr upImpl; + + DELETE_COPY(SpinnakerWrapper); + }; +} + +#endif // OPENPOSE_PRODUCER_SPINNAKER_WRAPPER_HPP diff --git a/openpose/include/openpose/producer/videoCaptureReader.hpp b/openpose/include/openpose/producer/videoCaptureReader.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d503d3594bea48cdc324cb79694f379ac95ca271 --- /dev/null +++ b/openpose/include/openpose/producer/videoCaptureReader.hpp @@ -0,0 +1,66 @@ +#ifndef OPENPOSE_PRODUCER_VIDEO_CAPTURE_READER_HPP +#define OPENPOSE_PRODUCER_VIDEO_CAPTURE_READER_HPP + +#include +#include + +namespace op +{ + /** + * VideoCaptureReader is an abstract class to extract frames from a cv::VideoCapture source (video file, + * webcam stream, etc.). It has the basic and common functions of the cv::VideoCapture class (e.g., get, set, etc.). + */ + class OP_API VideoCaptureReader : public Producer + { + public: + /** + * This constructor of VideoCaptureReader wraps cv::VideoCapture(const int). + * @param index const int indicating the cv::VideoCapture constructor int argument, in the range [0, 9]. + */ + explicit VideoCaptureReader(const int index, const bool throwExceptionIfNoOpened, + const std::string& cameraParameterPath, const bool undistortImage, + const int numberViews); + + /** + * This constructor of VideoCaptureReader wraps cv::VideoCapture(const std::string). + * @param path const std::string indicating the cv::VideoCapture constructor string argument. + * @param producerType const std::string indicating whether the frame source is an IP camera or video. + */ + explicit VideoCaptureReader(const std::string& path, const ProducerType producerType, + const std::string& cameraParameterPath, const bool undistortImage, + const int numberViews); + + /** + * Destructor of VideoCaptureReader. It releases the cv::VideoCapture member. It is virtual so that + * any children class can implement its own destructor. + */ + virtual ~VideoCaptureReader(); + + virtual std::string getNextFrameName() = 0; + + virtual bool isOpened() const; + + void release(); + + virtual double get(const int capProperty) = 0; + + virtual void set(const int capProperty, const double value) = 0; + + protected: + virtual Matrix getRawFrame() = 0; + + virtual std::vector getRawFrames() = 0; + + void resetWebcam(const int index, const bool throwExceptionIfNoOpened); + + private: + // PIMPL idiom + // http://www.cppsamples.com/common-tasks/pimpl.html + struct ImplVideoCaptureReader; + std::unique_ptr upImpl; + + DELETE_COPY(VideoCaptureReader); + }; +} + +#endif // OPENPOSE_PRODUCER_VIDEO_CAPTURE_READER_HPP diff --git a/openpose/include/openpose/producer/videoReader.hpp b/openpose/include/openpose/producer/videoReader.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1132d056690c671b57d8e17781efe8c77d7d6df3 --- /dev/null +++ b/openpose/include/openpose/producer/videoReader.hpp @@ -0,0 +1,53 @@ +#ifndef OPENPOSE_PRODUCER_VIDEO_READER_HPP +#define OPENPOSE_PRODUCER_VIDEO_READER_HPP + +#include +#include + +namespace op +{ + /** + * VideoReader is a wrapper of the cv::VideoCapture class for video. It allows controlling a video (e.g., extracting + * frames, setting resolution & fps, etc). + */ + class OP_API VideoReader : public VideoCaptureReader + { + public: + /** + * Constructor of VideoReader. It opens the video as a wrapper of cv::VideoCapture. It includes a flag to + * indicate whether the video should be repeated once it is completely read. + * @param videoPath const std::string parameter with the full video path location. + * @param cameraParameterPath const std::string parameter with the folder path containing the camera + * parameters (only required if imageDirectorystereo > 1). + * @param numberViews const int parameter with the number of images per iteration (>1 would represent + * stereo processing). + */ + explicit VideoReader( + const std::string& videoPath, const std::string& cameraParameterPath = "", + const bool undistortImage = false, const int numberViews = -1); + + virtual ~VideoReader(); + + std::string getNextFrameName(); + + inline bool isOpened() const + { + return VideoCaptureReader::isOpened(); + } + + double get(const int capProperty); + + void set(const int capProperty, const double value); + + private: + const std::string mPathName; + + Matrix getRawFrame(); + + std::vector getRawFrames(); + + DELETE_COPY(VideoReader); + }; +} + +#endif // OPENPOSE_PRODUCER_VIDEO_READER_HPP diff --git a/openpose/include/openpose/producer/wDatumProducer.hpp b/openpose/include/openpose/producer/wDatumProducer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1bb08dc1ba2f1b0062b9136a59f3819c5758db51 --- /dev/null +++ b/openpose/include/openpose/producer/wDatumProducer.hpp @@ -0,0 +1,118 @@ +#ifndef OPENPOSE_PRODUCER_W_DATUM_PRODUCER_HPP +#define OPENPOSE_PRODUCER_W_DATUM_PRODUCER_HPP + +#include // std::numeric_limits +#include // std::queue +#include +#include +#include + +namespace op +{ + template + class WDatumProducer : public WorkerProducer>>> + { + public: + explicit WDatumProducer(const std::shared_ptr>& datumProducer); + + virtual ~WDatumProducer(); + + void initializationOnThread(); + + std::shared_ptr>> workProducer(); + + private: + std::shared_ptr> spDatumProducer; + std::queue>>> mQueuedElements; + + DELETE_COPY(WDatumProducer); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WDatumProducer::WDatumProducer( + const std::shared_ptr>& datumProducer) : + spDatumProducer{datumProducer} + { + } + + template + WDatumProducer::~WDatumProducer() + { + } + + + template + void WDatumProducer::initializationOnThread() + { + } + + template + std::shared_ptr>> WDatumProducer::workProducer() + { + try + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Create and fill final shared pointer + std::shared_ptr>> tDatums; + // Producer + if (mQueuedElements.empty()) + { + bool isRunning; + std::tie(isRunning, tDatums) = spDatumProducer->checkIfRunningAndGetDatum(); + // Stop Worker if producer finished + if (!isRunning) + this->stop(); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + // Equivalent to WQueueSplitter + // Queued elements - Multiple views --> Split views into different shared pointers + if (tDatums != nullptr && tDatums->size() > 1) + { + // Add tDatums to mQueuedElements + for (auto i = 0u ; i < tDatums->size() ; i++) + { + auto& tDatumPtr = (*tDatums)[i]; + tDatumPtr->subId = i; + tDatumPtr->subIdMax = tDatums->size()-1; + mQueuedElements.emplace( + std::make_shared>>( + std::vector>{tDatumPtr})); + } + } + // Queued elements - Multiple views --> Return oldest view + if (!mQueuedElements.empty()) + { + tDatums = mQueuedElements.front(); + mQueuedElements.pop(); + } + // Return result + return tDatums; + } + catch (const std::exception& e) + { + this->stop(); + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return nullptr; + } + } + + extern template class WDatumProducer; +} + +#endif // OPENPOSE_PRODUCER_W_DATUM_PRODUCER_HPP diff --git a/openpose/include/openpose/producer/webcamReader.hpp b/openpose/include/openpose/producer/webcamReader.hpp new file mode 100644 index 0000000000000000000000000000000000000000..04b6f2c27494db161fb28f405874533906df9adb --- /dev/null +++ b/openpose/include/openpose/producer/webcamReader.hpp @@ -0,0 +1,67 @@ +#ifndef OPENPOSE_PRODUCER_WEBCAM_READER_HPP +#define OPENPOSE_PRODUCER_WEBCAM_READER_HPP + +#include +#include +#include +#include + +namespace op +{ + /** + * WebcamReader is a wrapper of the cv::VideoCapture class for webcam. It allows controlling a video (extracting + * frames, setting resolution & fps, seeking to a particular frame, etc). + */ + class OP_API WebcamReader : public VideoCaptureReader + { + public: + /** + * Constructor of WebcamReader. It opens the webcam as a wrapper of cv::VideoCapture. It includes an argument + * to indicate the desired resolution. + * @param webcamIndex const int indicating the camera source (see the OpenCV documentation about + * cv::VideoCapture for more details), in the range [0, 9]. + * @param webcamResolution const Point parameter which specifies the desired camera resolution. + * @param throwExceptionIfNoOpened Bool parameter which specifies whether to throw an exception if the camera + * cannot be opened. + */ + explicit WebcamReader(const int webcamIndex = 0, const Point& webcamResolution = Point{}, + const bool throwExceptionIfNoOpened = true, const std::string& cameraParameterPath = "", + const bool undistortImage = false); + + virtual ~WebcamReader(); + + std::string getNextFrameName(); + + bool isOpened() const; + + double get(const int capProperty); + + void set(const int capProperty, const double value); + + private: + const int mIndex; + const bool mWebcamStarted; + long long mFrameNameCounter; + bool mThreadOpened; + Matrix mBuffer; + std::mutex mBufferMutex; + std::atomic mCloseThread; + std::thread mThread; + // Detect camera unplugged + double mLastNorm; + std::atomic mDisconnectedCounter; + Point mResolution; + + Matrix getRawFrame(); + + std::vector getRawFrames(); + + void bufferingThread(); + + bool reset(); + + DELETE_COPY(WebcamReader); + }; +} + +#endif // OPENPOSE_PRODUCER_WEBCAM_READER_HPP diff --git a/openpose/include/openpose/thread/enumClasses.hpp b/openpose/include/openpose/thread/enumClasses.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3d648b5c3b5dc2a2c5f775d0e3e06e5cac019b08 --- /dev/null +++ b/openpose/include/openpose/thread/enumClasses.hpp @@ -0,0 +1,27 @@ +#ifndef OPENPOSE_THREAD_ENUM_CLASSES_HPP +#define OPENPOSE_THREAD_ENUM_CLASSES_HPP + +namespace op +{ + /** + * ThreadManager synchronization mode. + */ + enum class ThreadManagerMode : unsigned char + { + /** + * First and last queues of ThreadManager will be given to the user, so he must push elements to the first queue and retrieve + * them from the last one after being processed. + * Recommended for prototyping environments (easier to test but more error-prone and potentially slower in performance). + */ + Asynchronous, + AsynchronousIn, /**< Similar to Asynchronous, but only the input (first) queue is given to the user. */ + AsynchronousOut, /**< Similar to Asynchronous, but only the output (last) queue is given to the user. */ + /** + * Everything will run inside the ThreadManager. + * Recommended for production environments (more difficult to set up but faster in performance and less error-prone). + */ + Synchronous, + }; +} + +#endif // OPENPOSE_THREAD_ENUM_CLASSES_HPP diff --git a/openpose/include/openpose/thread/headers.hpp b/openpose/include/openpose/thread/headers.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1afcad9eda6ebbb777046d63ec413ec360f28a1c --- /dev/null +++ b/openpose/include/openpose/thread/headers.hpp @@ -0,0 +1,24 @@ +#ifndef OPENPOSE_THREAD_HEADERS_HPP +#define OPENPOSE_THREAD_HEADERS_HPP + +// thread module +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // OPENPOSE_THREAD_HEADERS_HPP diff --git a/openpose/include/openpose/thread/priorityQueue.hpp b/openpose/include/openpose/thread/priorityQueue.hpp new file mode 100644 index 0000000000000000000000000000000000000000..bac8caf9e6ed4aa90b052bb0c6b7decd24b1a097 --- /dev/null +++ b/openpose/include/openpose/thread/priorityQueue.hpp @@ -0,0 +1,88 @@ +#ifndef OPENPOSE_THREAD_PRIORITY_QUEUE_HPP +#define OPENPOSE_THREAD_PRIORITY_QUEUE_HPP + +#include // std::priority_queue +#include +#include + +namespace op +{ + template, std::greater>> + class PriorityQueue : public QueueBase + { + public: + explicit PriorityQueue(const long long maxSize = 256); + + virtual ~PriorityQueue(); + + TDatums front() const; + + private: + bool pop(TDatums& tDatums); + + DELETE_COPY(PriorityQueue); + }; +} + + + + + +// Implementation +#include // std::is_same +namespace op +{ + template + PriorityQueue::PriorityQueue(const long long maxSize) : + QueueBase{maxSize} + { + // Check TDatums = underlying value type of TQueue + typedef typename TQueue::value_type underlyingValueType; + static_assert(std::is_same::value, + "Error: The type of the queue must be the same as the type of the container"); + } + + template + PriorityQueue::~PriorityQueue() + { + } + + template + TDatums PriorityQueue::front() const + { + try + { + const std::lock_guard lock{this->mMutex}; + return this->mTQueue.top(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return TDatums{}; + } + } + + template + bool PriorityQueue::pop(TDatums& tDatums) + { + try + { + if (this->mPopIsStopped || this->mTQueue.empty()) + return false; + + tDatums = {std::move(this->mTQueue.top())}; + this->mTQueue.pop(); + this->mConditionVariable.notify_one(); + return true; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + COMPILE_TEMPLATE_DATUM(PriorityQueue); +} + +#endif // OPENPOSE_THREAD_PRIORITY_QUEUE_HPP diff --git a/openpose/include/openpose/thread/queue.hpp b/openpose/include/openpose/thread/queue.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7b34a9469107d769d58d6af35781e75892837495 --- /dev/null +++ b/openpose/include/openpose/thread/queue.hpp @@ -0,0 +1,88 @@ +#ifndef OPENPOSE_THREAD_QUEUE_HPP +#define OPENPOSE_THREAD_QUEUE_HPP + +#include // std::queue +#include +#include + +namespace op +{ + template> + class Queue : public QueueBase + { + public: + explicit Queue(const long long maxSize); + + virtual ~Queue(); + + TDatums front() const; + + private: + bool pop(TDatums& tDatums); + + DELETE_COPY(Queue); + }; +} + + + + + +// Implementation +#include // std::is_same +namespace op +{ + template + Queue::Queue(const long long maxSize) : + QueueBase{maxSize} + { + // Check TDatums = underlying value type of TQueue + typedef typename TQueue::value_type underlyingValueType; + static_assert(std::is_same::value, + "Error: The type of the queue must be the same as the type of the container"); + } + + template + Queue::~Queue() + { + } + + template + TDatums Queue::front() const + { + try + { + const std::lock_guard lock{this->mMutex}; + return this->mTQueue.front(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return TDatums{}; + } + } + + template + bool Queue::pop(TDatums& tDatums) + { + try + { + if (this->mPopIsStopped || this->mTQueue.empty()) + return false; + + tDatums = {std::move(this->mTQueue.front())}; + this->mTQueue.pop(); + this->mConditionVariable.notify_one(); + return true; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + COMPILE_TEMPLATE_DATUM(Queue); +} + +#endif // OPENPOSE_THREAD_QUEUE_HPP diff --git a/openpose/include/openpose/thread/queueBase.hpp b/openpose/include/openpose/thread/queueBase.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7d0221a106f7464a2edd6394c0640e300693a762 --- /dev/null +++ b/openpose/include/openpose/thread/queueBase.hpp @@ -0,0 +1,524 @@ +#ifndef OPENPOSE_THREAD_QUEUE_BASE_HPP +#define OPENPOSE_THREAD_QUEUE_BASE_HPP + +#include +#include +#include // std::queue & std::priority_queue +#include + +namespace op +{ + template + class QueueBase + { + public: + explicit QueueBase(const long long maxSize = -1); + + virtual ~QueueBase(); + + bool forceEmplace(TDatums& tDatums); + + bool tryEmplace(TDatums& tDatums); + + bool waitAndEmplace(TDatums& tDatums); + + bool forcePush(const TDatums& tDatums); + + bool tryPush(const TDatums& tDatums); + + bool waitAndPush(const TDatums& tDatums); + + bool tryPop(TDatums& tDatums); + + bool tryPop(); + + bool waitAndPop(TDatums& tDatums); + + bool waitAndPop(); + + bool empty() const; + + void stop(); + + void stopPusher(); + + void addPopper(); + + void addPusher(); + + bool isRunning() const; + + bool isFull() const; + + size_t size() const; + + void clear(); + + virtual TDatums front() const = 0; + + protected: + mutable std::mutex mMutex; + long long mPoppers; + long long mPushers; + long long mMaxPoppersPushers; + bool mPopIsStopped; + bool mPushIsStopped; + std::condition_variable mConditionVariable; + TQueue mTQueue; + + virtual bool pop(TDatums& tDatums) = 0; + + unsigned long long getMaxSize() const; + + private: + const long long mMaxSize; + + bool emplace(TDatums& tDatums); + + bool push(const TDatums& tDatums); + + bool pop(); + + void updateMaxPoppersPushers(); + + DELETE_COPY(QueueBase); + }; +} + + + + + +// Implementation +#include +#include +namespace op +{ + template + QueueBase::QueueBase(const long long maxSize) : + mPoppers{0ll}, + mPushers{0ll}, + mPopIsStopped{false}, + mPushIsStopped{false}, + mMaxSize{maxSize} + { + } + + // Virtual destructor + template + QueueBase::~QueueBase() + { + try + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + stop(); + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + bool QueueBase::forceEmplace(TDatums& tDatums) + { + try + { + const std::lock_guard lock{mMutex}; + if (mTQueue.size() >= getMaxSize()) + mTQueue.pop(); + return emplace(tDatums); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool QueueBase::tryEmplace(TDatums& tDatums) + { + try + { + const std::lock_guard lock{mMutex}; + if (mTQueue.size() >= getMaxSize()) + return false; + return emplace(tDatums); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool QueueBase::waitAndEmplace(TDatums& tDatums) + { + try + { + std::unique_lock lock{mMutex}; + mConditionVariable.wait(lock, [this]{return mTQueue.size() < getMaxSize() || mPushIsStopped; }); + return emplace(tDatums); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool QueueBase::forcePush(const TDatums& tDatums) + { + try + { + const std::lock_guard lock{mMutex}; + if (mTQueue.size() >= getMaxSize()) + mTQueue.pop(); + return push(tDatums); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool QueueBase::tryPush(const TDatums& tDatums) + { + try + { + const std::lock_guard lock{mMutex}; + if (mTQueue.size() >= getMaxSize()) + return false; + return push(tDatums); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool QueueBase::waitAndPush(const TDatums& tDatums) + { + try + { + std::unique_lock lock{mMutex}; + mConditionVariable.wait(lock, [this]{return mTQueue.size() < getMaxSize() || mPushIsStopped; }); + return push(tDatums); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool QueueBase::tryPop(TDatums& tDatums) + { + try + { + const std::lock_guard lock{mMutex}; + return pop(tDatums); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool QueueBase::tryPop() + { + try + { + const std::lock_guard lock{mMutex}; + return pop(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool QueueBase::waitAndPop(TDatums& tDatums) + { + try + { + std::unique_lock lock{mMutex}; + mConditionVariable.wait(lock, [this]{return !mTQueue.empty() || mPopIsStopped; }); + return pop(tDatums); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool QueueBase::waitAndPop() + { + try + { + std::unique_lock lock{mMutex}; + mConditionVariable.wait(lock, [this]{return !mTQueue.empty() || mPopIsStopped; }); + return pop(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool QueueBase::empty() const + { + try + { + const std::lock_guard lock{mMutex}; + return mTQueue.empty(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + void QueueBase::stop() + { + try + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + const std::lock_guard lock{mMutex}; + mPopIsStopped = {true}; + mPushIsStopped = {true}; + while (!mTQueue.empty()) + mTQueue.pop(); + mConditionVariable.notify_all(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void QueueBase::stopPusher() + { + try + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + const std::lock_guard lock{mMutex}; + mPushers--; + if (mPushers == 0) + { + mPushIsStopped = {true}; + if (mTQueue.empty()) + mPopIsStopped = {true}; + mConditionVariable.notify_all(); + } + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void QueueBase::addPopper() + { + try + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + const std::lock_guard lock{mMutex}; + mPoppers++; + updateMaxPoppersPushers(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void QueueBase::addPusher() + { + try + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + const std::lock_guard lock{mMutex}; + mPushers++; + updateMaxPoppersPushers(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + bool QueueBase::isRunning() const + { + try + { + const std::lock_guard lock{mMutex}; + return !(mPushIsStopped && (mPopIsStopped || mTQueue.empty())); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return true; + } + } + + template + bool QueueBase::isFull() const + { + try + { + // No mutex required because the size() and getMaxSize() are already thread-safe + return size() == getMaxSize(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + size_t QueueBase::size() const + { + try + { + const std::lock_guard lock{mMutex}; + return mTQueue.size(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return 0; + } + } + + template + void QueueBase::clear() + { + try + { + const std::lock_guard lock{mMutex}; + while (!mTQueue.empty()) + mTQueue.pop(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + unsigned long long QueueBase::getMaxSize() const + { + try + { + return (mMaxSize > 0 ? mMaxSize : fastMax(1ll, mMaxPoppersPushers)); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool QueueBase::emplace(TDatums& tDatums) + { + try + { + if (mPushIsStopped) + return false; + + mTQueue.emplace(tDatums); + mConditionVariable.notify_all(); + return true; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool QueueBase::push(const TDatums& tDatums) + { + try + { + if (mPushIsStopped) + return false; + + mTQueue.push(tDatums); + mConditionVariable.notify_all(); + return true; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool QueueBase::pop() + { + try + { + if (mPopIsStopped || mTQueue.empty()) + return false; + + mTQueue.pop(); + mConditionVariable.notify_all(); + return true; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + void QueueBase::updateMaxPoppersPushers() + { + try + { + mMaxPoppersPushers = fastMax(mPoppers, mPushers); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + extern template class QueueBase>; + extern template class QueueBase< + BASE_DATUMS_SH, + std::priority_queue, + std::greater>>; +} + +#endif // OPENPOSE_THREAD_QUEUE_BASE_HPP diff --git a/openpose/include/openpose/thread/subThread.hpp b/openpose/include/openpose/thread/subThread.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3e35989cd108744900432dd0fc7281b2ff19d698 --- /dev/null +++ b/openpose/include/openpose/thread/subThread.hpp @@ -0,0 +1,157 @@ +#ifndef OPENPOSE_THREAD_SUB_THREAD_HPP +#define OPENPOSE_THREAD_SUB_THREAD_HPP + +#include +#include + +namespace op +{ + template>> + class SubThread + { + public: + explicit SubThread(const std::vector& tWorkers); + + // Destructor + virtual ~SubThread(); + + void initializationOnThread(); + + virtual bool work() = 0; + + protected: + inline size_t getTWorkersSize() const + { + return mTWorkers.size(); + } + + bool workTWorkers(TDatums& tDatums, const bool inputIsRunning); + + private: + std::vector mTWorkers; + + DELETE_COPY(SubThread); + }; +} + + + + + +// Implementation +namespace op +{ + template + SubThread::SubThread(const std::vector& tWorkers) : + mTWorkers{tWorkers} + { + } + + template + SubThread::~SubThread() + { + } + + template + bool SubThread::workTWorkers(TDatums& tDatums, const bool inputIsRunning) + { + try + { + // If !inputIsRunning -> try to close TWorkers + if (!inputIsRunning) + { + for (auto& tWorkers : mTWorkers) + { + tWorkers->tryStop(); + if (tWorkers->isRunning()) + break; + } + } + + // If (at least) last TWorker still working -> make TWorkers work + if ((*mTWorkers.crbegin())->isRunning()) + { + // Iterate over all workers and check whether some of them stopped + auto allRunning = true; + auto lastOneStopped = false; + for (auto& worker : mTWorkers) + { + if (lastOneStopped) + worker->tryStop(); + + if (!worker->checkAndWork(tDatums)) + { + allRunning = false; + lastOneStopped = true; + } + else + lastOneStopped = false; + } + + if (allRunning) + return true; + else + { + // If last one still running -> try to stop workers + // If last one stopped -> return false + auto lastRunning = (*mTWorkers.crbegin())->isRunning(); + if (lastRunning) + { + // Check last one that stopped + auto lastIndexNotRunning = 0ull; + for (auto i = mTWorkers.size() - 1 ; i > 0 ; i--) + { + if (!mTWorkers[i]->checkAndWork(tDatums)) + { + lastIndexNotRunning = i; + break; + } + } + + // Stop workers before last index stopped + for (auto i = 0ull; i < lastIndexNotRunning ; i++) + mTWorkers[i]->stop(); + + // Try stopping workers after last index stopped + lastRunning = false; + for (auto i = lastIndexNotRunning+1; i < mTWorkers.size() ; i++) + { + mTWorkers[i]->tryStop(); + if (mTWorkers[i]->isRunning()) + { + lastRunning = true; + break; + } + } + } + return lastRunning; + } + } + else + return false; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + void SubThread::initializationOnThread() + { + try + { + for (auto& tWorker : mTWorkers) + tWorker->initializationOnThreadNoException(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(SubThread); +} + +#endif // OPENPOSE_THREAD_SUB_THREAD_HPP diff --git a/openpose/include/openpose/thread/subThreadNoQueue.hpp b/openpose/include/openpose/thread/subThreadNoQueue.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1331e26bc297949447950cd0252969ad42170b1a --- /dev/null +++ b/openpose/include/openpose/thread/subThreadNoQueue.hpp @@ -0,0 +1,60 @@ +#ifndef OPENPOSE_THREAD_THREAD_NO_QUEUE_HPP +#define OPENPOSE_THREAD_THREAD_NO_QUEUE_HPP + +#include +#include +#include + +namespace op +{ + template>> + class SubThreadNoQueue : public SubThread + { + public: + explicit SubThreadNoQueue(const std::vector& tWorkers); + + virtual ~SubThreadNoQueue(); + + bool work(); + + DELETE_COPY(SubThreadNoQueue); + }; +} + + + + + +// Implementation +namespace op +{ + template + SubThreadNoQueue::SubThreadNoQueue(const std::vector& tWorkers) : + SubThread{tWorkers} + { + } + + template + SubThreadNoQueue::~SubThreadNoQueue() + { + } + + template + bool SubThreadNoQueue::work() + { + try + { + TDatums tDatums; + return this->workTWorkers(tDatums, true); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + COMPILE_TEMPLATE_DATUM(SubThreadNoQueue); +} + +#endif // OPENPOSE_THREAD_THREAD_NO_QUEUE_HPP diff --git a/openpose/include/openpose/thread/subThreadQueueIn.hpp b/openpose/include/openpose/thread/subThreadQueueIn.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d6ecd9108c7177ef3b319a31dd199f3ad30cdc84 --- /dev/null +++ b/openpose/include/openpose/thread/subThreadQueueIn.hpp @@ -0,0 +1,80 @@ +#ifndef OPENPOSE_THREAD_THREAD_QUEUE_IN_HPP +#define OPENPOSE_THREAD_THREAD_QUEUE_IN_HPP + +#include +#include +#include +#include + +namespace op +{ + template>, typename TQueue = Queue> + class SubThreadQueueIn : public SubThread + { + public: + SubThreadQueueIn(const std::vector& tWorkers, const std::shared_ptr& tQueueIn); + + virtual ~SubThreadQueueIn(); + + bool work(); + + private: + std::shared_ptr spTQueueIn; + + DELETE_COPY(SubThreadQueueIn); + }; +} + + + + + +// Implementation +namespace op +{ + template + SubThreadQueueIn::SubThreadQueueIn(const std::vector& tWorkers, + const std::shared_ptr& tQueueIn) : + SubThread{tWorkers}, + spTQueueIn{tQueueIn} + { + // spTQueueIn->addPopper(); + } + + template + SubThreadQueueIn::~SubThreadQueueIn() + { + } + + template + bool SubThreadQueueIn::work() + { + try + { + // Pop TDatums + if (spTQueueIn->empty()) + std::this_thread::sleep_for(std::chrono::microseconds{100}); + TDatums tDatums; + bool queueIsRunning = spTQueueIn->tryPop(tDatums); + // Check queue not empty + if (!queueIsRunning) + queueIsRunning = spTQueueIn->isRunning(); + // Process TDatums + const auto workersAreRunning = this->workTWorkers(tDatums, queueIsRunning); + // Close queue input if all workers closed + if (!workersAreRunning) + spTQueueIn->stop(); + return workersAreRunning; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + spTQueueIn->stop(); + return false; + } + } + + COMPILE_TEMPLATE_DATUM(SubThreadQueueIn); +} + +#endif // OPENPOSE_THREAD_THREAD_QUEUE_IN_HPP diff --git a/openpose/include/openpose/thread/subThreadQueueInOut.hpp b/openpose/include/openpose/thread/subThreadQueueInOut.hpp new file mode 100644 index 0000000000000000000000000000000000000000..49e796531096982af0277a8b6751aa7fcc0a158c --- /dev/null +++ b/openpose/include/openpose/thread/subThreadQueueInOut.hpp @@ -0,0 +1,115 @@ +#ifndef OPENPOSE_THREAD_THREAD_QUEUE_IN_OUT_HPP +#define OPENPOSE_THREAD_THREAD_QUEUE_IN_OUT_HPP + +#include +#include +#include +#include + +namespace op +{ + template>, typename TQueue = Queue> + class SubThreadQueueInOut : public SubThread + { + public: + SubThreadQueueInOut(const std::vector& tWorkers, const std::shared_ptr& tQueueIn, + const std::shared_ptr& tQueueOut); + + virtual ~SubThreadQueueInOut(); + + bool work(); + + private: + std::shared_ptr spTQueueIn; + std::shared_ptr spTQueueOut; + + DELETE_COPY(SubThreadQueueInOut); + }; +} + + + + + +// Implementation +namespace op +{ + template + SubThreadQueueInOut::SubThreadQueueInOut(const std::vector& tWorkers, + const std::shared_ptr& tQueueIn, + const std::shared_ptr& tQueueOut) : + SubThread{tWorkers}, + spTQueueIn{tQueueIn}, + spTQueueOut{tQueueOut} + { + // spTQueueIn->addPopper(); + spTQueueOut->addPusher(); + } + + template + SubThreadQueueInOut::~SubThreadQueueInOut() + { + } + + template + bool SubThreadQueueInOut::work() + { + try + { + // If output queue is closed -> close input queue + if (!spTQueueOut->isRunning()) + { + spTQueueIn->stop(); + return false; + } + // If output queue running -> normal operation + else + { + // Don't work until next queue is not full + // This reduces latency to half + if (!spTQueueOut->isFull()) + { + // Pop TDatums + if (spTQueueIn->empty()) + std::this_thread::sleep_for(std::chrono::microseconds{100}); + TDatums tDatums; + bool workersAreRunning = spTQueueIn->tryPop(tDatums); + // Check queue not stopped + if (!workersAreRunning) + workersAreRunning = spTQueueIn->isRunning(); + // Process TDatums + workersAreRunning = this->workTWorkers(tDatums, workersAreRunning); + // Push/emplace tDatums if successfully processed + if (workersAreRunning) + { + if (tDatums != nullptr) + spTQueueOut->waitAndEmplace(tDatums); + } + // Close both queues otherwise + else + { + spTQueueIn->stop(); + spTQueueOut->stopPusher(); + } + return workersAreRunning; + } + else + { + std::this_thread::sleep_for(std::chrono::microseconds{100}); + return true; + } + } + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + spTQueueIn->stop(); + spTQueueOut->stop(); + return false; + } + } + + COMPILE_TEMPLATE_DATUM(SubThreadQueueInOut); +} + +#endif // OPENPOSE_THREAD_THREAD_QUEUE_IN_OUT_HPP diff --git a/openpose/include/openpose/thread/subThreadQueueOut.hpp b/openpose/include/openpose/thread/subThreadQueueOut.hpp new file mode 100644 index 0000000000000000000000000000000000000000..15181e1434b810fd6d5c44987e9a1d3ef9889a1b --- /dev/null +++ b/openpose/include/openpose/thread/subThreadQueueOut.hpp @@ -0,0 +1,95 @@ +#ifndef OPENPOSE_THREAD_THREAD_QUEUE_OUT_HPP +#define OPENPOSE_THREAD_THREAD_QUEUE_OUT_HPP + +#include +#include +#include +#include + +namespace op +{ + template>, typename TQueue = Queue> + class SubThreadQueueOut : public SubThread + { + public: + SubThreadQueueOut(const std::vector& tWorkers, const std::shared_ptr& tQueueOut); + + virtual ~SubThreadQueueOut(); + + bool work(); + + private: + std::shared_ptr spTQueueOut; + + DELETE_COPY(SubThreadQueueOut); + }; +} + + + + + +// Implementation +namespace op +{ + template + SubThreadQueueOut::SubThreadQueueOut(const std::vector& tWorkers, + const std::shared_ptr& tQueueOut) : + SubThread{tWorkers}, + spTQueueOut{tQueueOut} + { + spTQueueOut->addPusher(); + } + + template + SubThreadQueueOut::~SubThreadQueueOut() + { + } + + template + bool SubThreadQueueOut::work() + { + try + { + // If output queue is closed -> close input queue + if (!spTQueueOut->isRunning()) + return false; + else + { + // Don't work until next queue is not full + // This reduces latency to half + if (!spTQueueOut->isFull()) + { + // Process TDatums + TDatums tDatums; + const auto workersAreRunning = this->workTWorkers(tDatums, true); + // Push/emplace tDatums if successfully processed + if (workersAreRunning) + { + if (tDatums != nullptr) + spTQueueOut->waitAndEmplace(tDatums); + } + // Close queue otherwise + else + spTQueueOut->stopPusher(); + return workersAreRunning; + } + else + { + std::this_thread::sleep_for(std::chrono::microseconds{100}); + return true; + } + } + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + spTQueueOut->stop(); + return false; + } + } + + COMPILE_TEMPLATE_DATUM(SubThreadQueueOut); +} + +#endif // OPENPOSE_THREAD_THREAD_QUEUE_OUT_HPP diff --git a/openpose/include/openpose/thread/thread.hpp b/openpose/include/openpose/thread/thread.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4a38b0d872f1b6670078c0d2dfa09497417eea3c --- /dev/null +++ b/openpose/include/openpose/thread/thread.hpp @@ -0,0 +1,237 @@ +#ifndef OPENPOSE_THREAD_THREAD_HPP +#define OPENPOSE_THREAD_THREAD_HPP + +#include +#include +#include +#include + +namespace op +{ + template>> + class Thread + { + public: + explicit Thread(const std::shared_ptr>& isRunningSharedPtr = nullptr); + + // Move constructor + Thread(Thread&& t); + + // Move assignment + Thread& operator=(Thread&& t); + + // Destructor + virtual ~Thread(); + + void add(const std::vector>>& subThreads); + + void add(const std::shared_ptr>& subThread); + + void exec(const std::shared_ptr>& isRunningSharedPtr); + + void startInThread(); + + void stopAndJoin(); + + inline bool isRunning() const + { + return *spIsRunning; + } + + private: + std::shared_ptr> spIsRunning; + std::vector>> mSubThreads; + std::thread mThread; + + void initializationOnThread(); + + void threadFunction(); + + void stop(); + + void join(); + + DELETE_COPY(Thread); + }; +} + + + + + +// Implementation +namespace op +{ + template + Thread::Thread(const std::shared_ptr>& isRunningSharedPtr) : + spIsRunning{(isRunningSharedPtr != nullptr ? isRunningSharedPtr : std::make_shared>(false))} + { + } + + template + Thread::Thread(Thread&& t) : + spIsRunning{std::make_shared>(t.spIsRunning->load())} + { + std::swap(mSubThreads, t.mSubThreads); + std::swap(mThread, t.mThread); + } + + template + Thread& Thread::operator=(Thread&& t) + { + std::swap(mSubThreads, t.mSubThreads); + std::swap(mThread, t.mThread); + spIsRunning = {std::make_shared>(t.spIsRunning->load())}; + return *this; + } + + template + Thread::~Thread() + { + try + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + stopAndJoin(); + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + catch (const std::exception& e) + { + errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void Thread::add(const std::vector>>& subThreads) + { + for (const auto& subThread : subThreads) + mSubThreads.emplace_back(subThread); + } + + template + void Thread::add(const std::shared_ptr>& subThread) + { + add(std::vector>>{subThread}); + } + + template + void Thread::exec(const std::shared_ptr>& isRunningSharedPtr) + { + try + { + stopAndJoin(); + spIsRunning = isRunningSharedPtr; + *spIsRunning = true; + threadFunction(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void Thread::startInThread() + { + try + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + stopAndJoin(); + *spIsRunning = true; + mThread = {std::thread{&Thread::threadFunction, this}}; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void Thread::stopAndJoin() + { + try + { + stop(); + join(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void Thread::initializationOnThread() + { + try + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + for (auto& subThread : mSubThreads) + subThread->initializationOnThread(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void Thread::threadFunction() + { + try + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + initializationOnThread(); + + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + while (isRunning()) + { + bool allSubThreadsClosed = true; + for (auto& subThread : mSubThreads) + allSubThreadsClosed &= !subThread->work(); + + if (allSubThreadsClosed) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + stop(); + break; + } + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void Thread::stop() + { + try + { + *spIsRunning = false; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void Thread::join() + { + try + { + if (mThread.joinable()) + mThread.join(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(Thread); +} + +#endif // OPENPOSE_THREAD_THREAD_HPP diff --git a/openpose/include/openpose/thread/threadManager.hpp b/openpose/include/openpose/thread/threadManager.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d8e078d2c7ccfb4506bf2bfa47e2fb69ac418db7 --- /dev/null +++ b/openpose/include/openpose/thread/threadManager.hpp @@ -0,0 +1,554 @@ +#ifndef OPENPOSE_THREAD_THREAD_MANAGER_HPP +#define OPENPOSE_THREAD_THREAD_MANAGER_HPP + +#include +#include // std::multiset +#include +#include +#include +#include +#include +#include + +namespace op +{ + template>, typename TQueue = Queue> + class ThreadManager + { + public: + // Completely customizable case + explicit ThreadManager(const ThreadManagerMode threadManagerMode = ThreadManagerMode::Synchronous); + + virtual ~ThreadManager(); + + /** + * It sets the maximum number of elements in the queue. + * For maximum speed, set to a very large number, but the trade-off would be: + * - Latency will hugely increase. + * - The program might go out of RAM memory (so the computer might freeze). + * For minimum latency while keeping an optimal speed, set to -1, that will automatically + * detect the ideal number based on how many elements are connected to that queue. + * @param defaultMaxSizeQueues long long element with the maximum number of elements on the queue. + */ + void setDefaultMaxSizeQueues(const long long defaultMaxSizeQueues = -1); + + void add(const unsigned long long threadId, const std::vector& tWorkers, + const unsigned long long queueInId, const unsigned long long queueOutId); + + void add(const unsigned long long threadId, const TWorker& tWorker, const unsigned long long queueInId, + const unsigned long long queueOutId); + + void reset(); + + void exec(); + + void start(); + + void stop(); + + inline std::shared_ptr> getIsRunningSharedPtr() + { + return spIsRunning; + } + + inline bool isRunning() const + { + return *spIsRunning; + } + + bool tryEmplace(TDatums& tDatums); + + bool waitAndEmplace(TDatums& tDatums); + + bool tryPush(const TDatums& tDatums); + + bool waitAndPush(const TDatums& tDatums); + + bool tryPop(TDatums& tDatums); + + bool waitAndPop(TDatums& tDatums); + + private: + const ThreadManagerMode mThreadManagerMode; + std::shared_ptr> spIsRunning; + long long mDefaultMaxSizeQueues; + std::multiset, unsigned long long, unsigned long long>> mThreadWorkerQueues; + std::vector>> mThreads; + std::vector> mTQueues; + + void add(const std::vector, unsigned long long, unsigned long long>>& threadWorkerQueues); + + void add(const std::vector>& threadWorkerQueues); + + void multisetToThreads(); + + void checkAndCreateEmptyThreads(); + + void checkAndCreateQueues(); + + DELETE_COPY(ThreadManager); + }; +} + + + + + +// Implementation +#include // std::pair +#include +#include +#include +#include +#include +#include +namespace op +{ + template + ThreadManager::ThreadManager(const ThreadManagerMode threadManagerMode) : + mThreadManagerMode{threadManagerMode}, + spIsRunning{std::make_shared>(false)}, + mDefaultMaxSizeQueues{-1ll} + { + } + + template + ThreadManager::~ThreadManager() + { + } + + template + void ThreadManager::setDefaultMaxSizeQueues(const long long defaultMaxSizeQueues) + { + try + { + mDefaultMaxSizeQueues = {defaultMaxSizeQueues}; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void ThreadManager::add(const unsigned long long threadId, + const std::vector& tWorkers, + const unsigned long long queueInId, + const unsigned long long queueOutId) + { + try + { + add({std::make_tuple(threadId, tWorkers, queueInId, queueOutId)}); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void ThreadManager::add(const unsigned long long threadId, + const TWorker& tWorker, + const unsigned long long queueInId, + const unsigned long long queueOutId) + { + try + { + add({std::make_tuple(threadId, std::vector{tWorker}, queueInId, queueOutId)}); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void ThreadManager::reset() + { + try + { + mThreadWorkerQueues.clear(); + mThreads.clear(); + mTQueues.clear(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void ThreadManager::exec() + { + try + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Set threads + multisetToThreads(); + if (!mThreads.empty()) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Start threads + for (auto i = 0u; i < mThreads.size() - 1; i++) + mThreads.at(i)->startInThread(); + (*mThreads.rbegin())->exec(spIsRunning); + // Stop threads - It will arrive here when the exec() command has finished + stop(); + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void ThreadManager::start() + { + try + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Set threads + multisetToThreads(); + // Start threads + for (auto& thread : mThreads) + thread->startInThread(); + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void ThreadManager::stop() + { + try + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + for (auto& tQueue : mTQueues) + tQueue->stop(); + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + *spIsRunning = false; + for (auto& thread : mThreads) + thread->stopAndJoin(); + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + checkWorkerErrors(); + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + bool ThreadManager::tryEmplace(TDatums& tDatums) + { + try + { + if (mThreadManagerMode != ThreadManagerMode::Asynchronous + && mThreadManagerMode != ThreadManagerMode::AsynchronousIn) + error("Not available for this ThreadManagerMode.", __LINE__, __FUNCTION__, __FILE__); + if (mTQueues.empty()) + error("ThreadManager already stopped or not started yet.", __LINE__, __FUNCTION__, __FILE__); + return mTQueues[0]->tryEmplace(tDatums); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool ThreadManager::waitAndEmplace(TDatums& tDatums) + { + try + { + if (mThreadManagerMode != ThreadManagerMode::Asynchronous + && mThreadManagerMode != ThreadManagerMode::AsynchronousIn) + error("Not available for this ThreadManagerMode.", __LINE__, __FUNCTION__, __FILE__); + if (mTQueues.empty()) + error("ThreadManager already stopped or not started yet.", __LINE__, __FUNCTION__, __FILE__); + return mTQueues[0]->waitAndEmplace(tDatums); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool ThreadManager::tryPush(const TDatums& tDatums) + { + try + { + if (mThreadManagerMode != ThreadManagerMode::Asynchronous + && mThreadManagerMode != ThreadManagerMode::AsynchronousIn) + error("Not available for this ThreadManagerMode.", __LINE__, __FUNCTION__, __FILE__); + if (mTQueues.empty()) + error("ThreadManager already stopped or not started yet.", __LINE__, __FUNCTION__, __FILE__); + return mTQueues[0]->tryPush(tDatums); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool ThreadManager::waitAndPush(const TDatums& tDatums) + { + try + { + if (mThreadManagerMode != ThreadManagerMode::Asynchronous + && mThreadManagerMode != ThreadManagerMode::AsynchronousIn) + error("Not available for this ThreadManagerMode.", __LINE__, __FUNCTION__, __FILE__); + if (mTQueues.empty()) + error("ThreadManager already stopped or not started yet.", __LINE__, __FUNCTION__, __FILE__); + return mTQueues[0]->waitAndPush(tDatums); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool ThreadManager::tryPop(TDatums& tDatums) + { + try + { + if (mThreadManagerMode != ThreadManagerMode::Asynchronous + && mThreadManagerMode != ThreadManagerMode::AsynchronousOut) + error("Not available for this ThreadManagerMode.", __LINE__, __FUNCTION__, __FILE__); + if (mTQueues.empty()) + error("ThreadManager already stopped or not started yet.", __LINE__, __FUNCTION__, __FILE__); + return (*mTQueues.rbegin())->tryPop(tDatums); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool ThreadManager::waitAndPop(TDatums& tDatums) + { + try + { + if (mThreadManagerMode != ThreadManagerMode::Asynchronous + && mThreadManagerMode != ThreadManagerMode::AsynchronousOut) + error("Not available for this ThreadManagerMode.", __LINE__, __FUNCTION__, __FILE__); + if (mTQueues.empty()) + error("ThreadManager already stopped or not started yet.", __LINE__, __FUNCTION__, __FILE__); + return (*mTQueues.rbegin())->waitAndPop(tDatums); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + void ThreadManager::add(const std::vector, + unsigned long long, unsigned long long>>& threadWorkerQueues) + { + try + { + for (const auto& threadWorkerQueue : threadWorkerQueues) + mThreadWorkerQueues.insert(threadWorkerQueue); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void ThreadManager::add(const std::vector>& threadWorkerQueues) + { + try + { + for (const auto& threadWorkerQueue : threadWorkerQueues) + add({std::make_tuple(std::get<0>(threadWorkerQueue), + std::vector{std::get<1>(threadWorkerQueue)}, + std::get<2>(threadWorkerQueue), + std::get<3>(threadWorkerQueue))}); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void ThreadManager::multisetToThreads() + { + try + { + if (!mThreadWorkerQueues.empty()) + { + // This avoids extra std::cout if errors occur on different threads + setMainThread(); + + // Check threads + checkAndCreateEmptyThreads(); + + // Check and create queues + checkAndCreateQueues(); + + // Data + const auto maxQueueIdSynchronous = mTQueues.size()+1; + + // Set up threads + for (const auto& threadWorkerQueue : mThreadWorkerQueues) + { + auto& thread = mThreads[std::get<0>(threadWorkerQueue)]; + const auto& tWorkers = std::get<1>(threadWorkerQueue); + const auto queueIn = std::get<2>(threadWorkerQueue); + const auto queueOut = std::get<3>(threadWorkerQueue); + std::shared_ptr> subThread; + // If AsynchronousIn -> queue indexes are OK + if (mThreadManagerMode == ThreadManagerMode::Asynchronous + || mThreadManagerMode == ThreadManagerMode::AsynchronousIn) + { + if (mThreadManagerMode == ThreadManagerMode::AsynchronousIn + && queueOut == mTQueues.size()) + subThread = {std::make_shared>( + tWorkers, mTQueues.at(queueIn))}; + else + subThread = {std::make_shared>( + tWorkers, mTQueues.at(queueIn), mTQueues.at(queueOut))}; + } + // If !AsynchronousIn -> queue indexes - 1 + else if (queueOut != maxQueueIdSynchronous + || mThreadManagerMode == ThreadManagerMode::AsynchronousOut) + { + // Queue in + out + if (queueIn != 0) + subThread = {std::make_shared>( + tWorkers, mTQueues.at(queueIn-1), mTQueues.at(queueOut-1))}; + // Case queue out (first TWorker(s)) + else + subThread = {std::make_shared>( + tWorkers, mTQueues.at(queueOut-1))}; + } + // Case queue in (last TWorker(s)) + else if (queueIn != 0) // && queueOut == maxQueueIdSynchronous + subThread = {std::make_shared>( + tWorkers, mTQueues.at(queueIn-1))}; + // Case no queue + else // if (queueIn == 0 && queueOut == maxQueueIdSynchronous) + subThread = {std::make_shared>(tWorkers)}; + thread->add(subThread); + } + } + else + error("Empty, no TWorker(s) added.", __LINE__); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void ThreadManager::checkAndCreateEmptyThreads() + { + try + { + // Check all thread ids from 0-maxThreadId are present + const auto maxThreadId = std::get<0>(*mThreadWorkerQueues.crbegin()); + auto previousThreadId = std::get<0>(*mThreadWorkerQueues.cbegin()); + for (const auto& threadWorkerQueue : mThreadWorkerQueues) + { + const auto currentThreadId = std::get<0>(threadWorkerQueue); + if (currentThreadId - previousThreadId > 1) + error("Missing thread id " + std::to_string(currentThreadId) + " of " + + std::to_string(maxThreadId) + ".", __LINE__, __FUNCTION__, __FILE__); + previousThreadId = currentThreadId; + } + + // Create Threads + // #threads = maxThreadId+1 + mThreads.resize(maxThreadId); + for (auto& thread : mThreads) + thread = std::make_shared>(); + mThreads.emplace_back(std::make_shared>(spIsRunning)); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void ThreadManager::checkAndCreateQueues() + { + try + { + if (!mThreadWorkerQueues.empty()) + { + // Get max queue id to get queue size + auto maxQueueId = std::get<3>(*mThreadWorkerQueues.cbegin()); + for (const auto& threadWorkerQueue : mThreadWorkerQueues) + maxQueueId = fastMax( + maxQueueId, fastMax(std::get<2>(threadWorkerQueue), std::get<3>(threadWorkerQueue))); + + // Check each queue id has at least a worker that uses it as input and another one as output. + // Special cases: + std::vector> usedQueueIds(maxQueueId+1, {false, false}); + for (const auto& threadWorkerQueue : mThreadWorkerQueues) + { + usedQueueIds.at(std::get<2>(threadWorkerQueue)).first = true; + usedQueueIds.at(std::get<3>(threadWorkerQueue)).second = true; + } + // Id 0 must only needs a worker using it as input. + usedQueueIds.begin()->second = true; + // Id maxQueueId only needs a worker using it as output. + usedQueueIds.rbegin()->first = true; + // Error if missing queue id + for (auto i = 0ull ; i < usedQueueIds.size() ; i++) + { + if (!usedQueueIds[i].first) + error("Missing queue id " + std::to_string(i) + " (of " + + std::to_string(maxQueueId) + ") as input.", __LINE__, __FUNCTION__, __FILE__); + if (!usedQueueIds[i].second) + error("Missing queue id " + std::to_string(i) + " (of " + + std::to_string(maxQueueId) + ") as output.", __LINE__, __FUNCTION__, __FILE__); + } + + // Create Queues + if (mThreadManagerMode == ThreadManagerMode::Asynchronous) + mTQueues.resize(maxQueueId+1); // First and last one are queues + else if (mThreadManagerMode == ThreadManagerMode::Synchronous) + mTQueues.resize(maxQueueId-1); // First and last one are not actually queues + else if (mThreadManagerMode == ThreadManagerMode::AsynchronousIn + || mThreadManagerMode == ThreadManagerMode::AsynchronousOut) + mTQueues.resize(maxQueueId); // First or last one is queue + else + error("Unknown ThreadManagerMode", __LINE__, __FUNCTION__, __FILE__); + for (auto& tQueue : mTQueues) + tQueue = std::make_shared(mDefaultMaxSizeQueues); + } + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(ThreadManager); +} + +#endif // OPENPOSE_THREAD_THREAD_MANAGER_HPP diff --git a/openpose/include/openpose/thread/wFpsMax.hpp b/openpose/include/openpose/thread/wFpsMax.hpp new file mode 100644 index 0000000000000000000000000000000000000000..41451c2f59731dfc618b4a53e9b02774ccdeef51 --- /dev/null +++ b/openpose/include/openpose/thread/wFpsMax.hpp @@ -0,0 +1,83 @@ +#ifndef OPENPOSE_THREAD_W_FPS_MAX_HPP +#define OPENPOSE_THREAD_W_FPS_MAX_HPP + +#include +#include +#include +#include + +namespace op +{ + template + class WFpsMax : public Worker + { + public: + explicit WFpsMax(const double fpsMax); + + virtual ~WFpsMax(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + const unsigned long long mNanosecondsToSleep; + + DELETE_COPY(WFpsMax); + }; +} + + + + + +// Implementation +namespace op +{ + template + WFpsMax::WFpsMax(const double fpsMax) : + mNanosecondsToSleep{uLongLongRound(1e9/fpsMax)} + { + } + + template + WFpsMax::~WFpsMax() + { + } + + template + void WFpsMax::initializationOnThread() + { + } + + template + void WFpsMax::work(TDatums& tDatums) + { + try + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // tDatums not used --> Avoid warning + UNUSED(tDatums); + // Sleep the desired time + std::this_thread::sleep_for(std::chrono::nanoseconds{mNanosecondsToSleep}); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WFpsMax); +} + +#endif // OPENPOSE_THREAD_W_FPS_MAX_HPP diff --git a/openpose/include/openpose/thread/wIdGenerator.hpp b/openpose/include/openpose/thread/wIdGenerator.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0f79a61d8ac4b29f02bb64c11b1c97064f204d10 --- /dev/null +++ b/openpose/include/openpose/thread/wIdGenerator.hpp @@ -0,0 +1,92 @@ +#ifndef OPENPOSE_THREAD_W_ID_GENERATOR_HPP +#define OPENPOSE_THREAD_W_ID_GENERATOR_HPP + +#include // std::priority_queue +#include +#include +#include + +namespace op +{ + template + class WIdGenerator : public Worker + { + public: + explicit WIdGenerator(); + + virtual ~WIdGenerator(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + unsigned long long mGlobalCounter; + + DELETE_COPY(WIdGenerator); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WIdGenerator::WIdGenerator() : + mGlobalCounter{0ull} + { + } + + template + WIdGenerator::~WIdGenerator() + { + } + + template + void WIdGenerator::initializationOnThread() + { + } + + template + void WIdGenerator::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Add ID + for (auto& tDatumPtr : *tDatums) + // To avoid overwriting ID if e.g., custom input has already filled it + if (tDatumPtr->id == std::numeric_limits::max()) + tDatumPtr->id = mGlobalCounter; + // Increase ID + const auto& tDatumPtr = (*tDatums)[0]; + if (tDatumPtr->subId == tDatumPtr->subIdMax) + mGlobalCounter++; + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WIdGenerator); +} + +#endif // OPENPOSE_THREAD_W_ID_GENERATOR_HPP diff --git a/openpose/include/openpose/thread/wQueueAssembler.hpp b/openpose/include/openpose/thread/wQueueAssembler.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e0f3f9feb027368d96ef1b570e63f63676a8f34a --- /dev/null +++ b/openpose/include/openpose/thread/wQueueAssembler.hpp @@ -0,0 +1,112 @@ +#ifndef OPENPOSE_THREAD_W_QUEUE_ASSEMBLER_HPP +#define OPENPOSE_THREAD_W_QUEUE_ASSEMBLER_HPP + +#include // std::queue +#include +#include +#include + +namespace op +{ + // Note: The goal of WQueueAssembler and WQueueSplitter (integrated in wDatumProducer) is to reduce the latency + // of OpenPose. E.g., if 4 cameras in stereo mode, without this, OpenPose would have to process all 4 cameras + // with the same GPU. In this way, this work is parallelized over GPUs (1 view for each). + // Pros: Latency highly recuded, same speed + // Cons: Requires these extra 2 classes and proper threads for them + template + class WQueueAssembler : public Worker> + { + public: + explicit WQueueAssembler(); + + virtual ~WQueueAssembler(); + + void initializationOnThread(); + + void work(std::shared_ptr& tDatums); + + private: + std::shared_ptr mNextTDatums; + + DELETE_COPY(WQueueAssembler); + }; +} + + + + + +// Implementation +namespace op +{ + template + WQueueAssembler::WQueueAssembler() + { + } + + template + WQueueAssembler::~WQueueAssembler() + { + } + + template + void WQueueAssembler::initializationOnThread() + { + } + + template + void WQueueAssembler::work(std::shared_ptr& tDatums) + { + try + { + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Input TDatums -> enqueue it + if (checkNoNullNorEmpty(tDatums)) + { + // Sanity check + if (tDatums->size() > 1) + error("This function assumes that WQueueSplitter (inside WDatumProducer)" + " was applied in the first place, i.e., that there is only 1 element" + " per TDatums (size = " + std::to_string(tDatums->size()) + ").", + __LINE__, __FUNCTION__, __FILE__); + auto tDatumPtr = (*tDatums)[0]; + // Single view --> Return + if (tDatumPtr->subIdMax == 0) + return; + // Multiple view --> Merge views into different TDatums (1st frame) + if (mNextTDatums == nullptr) + mNextTDatums = std::make_shared(); + // Multiple view --> Merge views into different TDatums + mNextTDatums->emplace_back(tDatumPtr); + // Last view - Return frame + if (mNextTDatums->back()->subId == mNextTDatums->back()->subIdMax) + { + tDatums = mNextTDatums; + mNextTDatums = nullptr; + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + // Non-last view - Return nothing + else + tDatums = nullptr; + } + // Sleep if no new tDatums to either pop or push + else + std::this_thread::sleep_for(std::chrono::milliseconds{1}); + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + extern template class WQueueAssembler; +} + +#endif // OPENPOSE_THREAD_W_QUEUE_ASSEMBLER_HPP diff --git a/openpose/include/openpose/thread/wQueueOrderer.hpp b/openpose/include/openpose/thread/wQueueOrderer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..115d795eb2e52e4660bd4e9637cff553b21dff66 --- /dev/null +++ b/openpose/include/openpose/thread/wQueueOrderer.hpp @@ -0,0 +1,178 @@ +#ifndef OPENPOSE_THREAD_W_QUEUE_ORDERER_HPP +#define OPENPOSE_THREAD_W_QUEUE_ORDERER_HPP + +#include // std::priority_queue +#include +#include +#include + +namespace op +{ + template + class WQueueOrderer : public Worker + { + public: + explicit WQueueOrderer(const unsigned int maxBufferSize = 64u); + + virtual ~WQueueOrderer(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + void tryStop(); + + private: + const unsigned int mMaxBufferSize; + bool mStopWhenEmpty; + unsigned long long mNextExpectedId; + unsigned long long mNextExpectedSubId; + std::priority_queue, PointerContainerGreater> mPriorityQueueBuffer; + + DELETE_COPY(WQueueOrderer); + }; +} + + + + + +// Implementation +namespace op +{ + template + WQueueOrderer::WQueueOrderer(const unsigned int maxBufferSize) : + mMaxBufferSize{maxBufferSize}, + mStopWhenEmpty{false}, + mNextExpectedId{0}, + mNextExpectedSubId{0} + { + } + + template + WQueueOrderer::~WQueueOrderer() + { + } + + template + void WQueueOrderer::initializationOnThread() + { + } + + template + void WQueueOrderer::work(TDatums& tDatums) + { + try + { + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + bool profileSpeed = (tDatums != nullptr); + // Input TDatum -> enqueue or return it back + if (checkNoNullNorEmpty(tDatums)) + { + // T* to T + auto& tDatumsNoPtr = *tDatums; + // tDatums is the next expected, update counter + if (tDatumsNoPtr[0]->id == mNextExpectedId && tDatumsNoPtr[0]->subId == mNextExpectedSubId) + { + // If single-view + if (tDatumsNoPtr[0]->subIdMax == 0) + mNextExpectedId++; + // If muilti-view system + else + { + mNextExpectedSubId++; + if (mNextExpectedSubId > tDatumsNoPtr[0]->subIdMax) + { + mNextExpectedSubId = 0; + mNextExpectedId++; + } + } + } + // Else push it to our buffered queue + else + { + // Enqueue current tDatums + mPriorityQueueBuffer.emplace(tDatums); + tDatums = nullptr; + // Else if buffer full -> remove one tDatums + if (mPriorityQueueBuffer.size() > mMaxBufferSize) + { + tDatums = mPriorityQueueBuffer.top(); + mPriorityQueueBuffer.pop(); + } + } + } + // If input TDatum enqueued -> check if previously enqueued next desired frame and pop it + if (!checkNoNullNorEmpty(tDatums)) + { + // Retrieve frame if next is desired frame or if we want to stop this worker + if (!mPriorityQueueBuffer.empty() + && (mStopWhenEmpty || + ((*mPriorityQueueBuffer.top())[0]->id == mNextExpectedId + && (*mPriorityQueueBuffer.top())[0]->subId == mNextExpectedSubId))) + { + tDatums = { mPriorityQueueBuffer.top() }; + mPriorityQueueBuffer.pop(); + } + } + // If TDatum ready to be returned -> updated next expected id + if (checkNoNullNorEmpty(tDatums)) + { + const auto& tDatumsNoPtr = *tDatums; + // If single-view + if (tDatumsNoPtr[0]->subIdMax == 0) + mNextExpectedId = tDatumsNoPtr[0]->id + 1; + // If muilti-view system + else + { + mNextExpectedSubId = tDatumsNoPtr[0]->subId + 1; + if (mNextExpectedSubId > tDatumsNoPtr[0]->subIdMax) + { + mNextExpectedSubId = 0; + mNextExpectedId = tDatumsNoPtr[0]->id + 1; + } + } + } + // Sleep if no new tDatums to either pop or push + if (!checkNoNullNorEmpty(tDatums) && mPriorityQueueBuffer.size() < mMaxBufferSize / 2u) + std::this_thread::sleep_for(std::chrono::milliseconds{1}); + // If TDatum popped and/or pushed + if (profileSpeed || tDatums != nullptr) + { + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WQueueOrderer::tryStop() + { + try + { + // Close if all frames were retrieved from the queue + if (mPriorityQueueBuffer.empty()) + this->stop(); + mStopWhenEmpty = true; + + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WQueueOrderer); +} + +#endif // OPENPOSE_THREAD_W_QUEUE_ORDERER_HPP diff --git a/openpose/include/openpose/thread/worker.hpp b/openpose/include/openpose/thread/worker.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a84028431034de9c2764ab0b1eb72915d77ef566 --- /dev/null +++ b/openpose/include/openpose/thread/worker.hpp @@ -0,0 +1,101 @@ +#ifndef OPENPOSE_THREAD_WORKER_HPP +#define OPENPOSE_THREAD_WORKER_HPP + +#include + +namespace op +{ + template + class Worker + { + public: + Worker(); + + virtual ~Worker(); + + void initializationOnThreadNoException(); + + bool checkAndWork(TDatums& tDatums); + + inline bool isRunning() const + { + return mIsRunning; + } + + inline void stop() + { + mIsRunning = false; + } + + // Virtual in case some function needs special stopping (e.g., buffers might not stop immediately and need a + // few iterations) + inline virtual void tryStop() + { + stop(); + } + + protected: + virtual void initializationOnThread() = 0; + + virtual void work(TDatums& tDatums) = 0; + + private: + bool mIsRunning; + + DELETE_COPY(Worker); + }; +} + + + + + +// Implementation +namespace op +{ + template + Worker::Worker() : + mIsRunning{true} + { + } + + template + Worker::~Worker() + { + } + + template + void Worker::initializationOnThreadNoException() + { + try + { + this->initializationOnThread(); + } + catch (const std::exception& e) + { + this->stop(); + errorWorker(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + bool Worker::checkAndWork(TDatums& tDatums) + { + try + { + if (mIsRunning) + work(tDatums); + return mIsRunning; + } + catch (const std::exception& e) + { + this->stop(); + errorWorker(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + COMPILE_TEMPLATE_DATUM(Worker); +} + +#endif // OPENPOSE_THREAD_WORKER_HPP diff --git a/openpose/include/openpose/thread/workerConsumer.hpp b/openpose/include/openpose/thread/workerConsumer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9d87b1e9154cf4757d2d32cdf23dd9e6f5ec25ee --- /dev/null +++ b/openpose/include/openpose/thread/workerConsumer.hpp @@ -0,0 +1,51 @@ +#ifndef OPENPOSE_THREAD_WORKER_CONSUMER_HPP +#define OPENPOSE_THREAD_WORKER_CONSUMER_HPP + +#include +#include + +namespace op +{ + template + class WorkerConsumer : public Worker + { + public: + virtual ~WorkerConsumer(); + + void work(TDatums& tDatums); + + protected: + virtual void workConsumer(const TDatums& tDatums) = 0; + }; +} + + + + + +// Implementation +namespace op +{ + template + WorkerConsumer::~WorkerConsumer() + { + } + + template + void WorkerConsumer::work(TDatums& tDatums) + { + try + { + workConsumer(tDatums); + } + catch (const std::exception& e) + { + this->stop(); + errorWorker(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WorkerConsumer); +} + +#endif // OPENPOSE_THREAD_WORKER_CONSUMER_HPP diff --git a/openpose/include/openpose/thread/workerProducer.hpp b/openpose/include/openpose/thread/workerProducer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..22afca64fed9beca0d3f0e6c69019de8470e9b0f --- /dev/null +++ b/openpose/include/openpose/thread/workerProducer.hpp @@ -0,0 +1,51 @@ +#ifndef OPENPOSE_THREAD_WORKER_PRODUCER_HPP +#define OPENPOSE_THREAD_WORKER_PRODUCER_HPP + +#include +#include + +namespace op +{ + template + class WorkerProducer : public Worker + { + public: + virtual ~WorkerProducer(); + + void work(TDatums& tDatums); + + protected: + virtual TDatums workProducer() = 0; + }; +} + + + + + +// Implementation +namespace op +{ + template + WorkerProducer::~WorkerProducer() + { + } + + template + void WorkerProducer::work(TDatums& tDatums) + { + try + { + tDatums = std::move(workProducer()); + } + catch (const std::exception& e) + { + this->stop(); + errorWorker(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WorkerProducer); +} + +#endif // OPENPOSE_THREAD_WORKER_PRODUCER_HPP diff --git a/openpose/include/openpose/tracking/headers.hpp b/openpose/include/openpose/tracking/headers.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d2daf852c4efadf56d7f439de2a5bcb566f4ba3a --- /dev/null +++ b/openpose/include/openpose/tracking/headers.hpp @@ -0,0 +1,9 @@ +#ifndef OPENPOSE_TRACKING_HEADERS_HPP +#define OPENPOSE_TRACKING_HEADERS_HPP + +// tracking module +#include +#include +#include + +#endif // OPENPOSE_TRACKING_HEADERS_HPP diff --git a/openpose/include/openpose/tracking/personIdExtractor.hpp b/openpose/include/openpose/tracking/personIdExtractor.hpp new file mode 100644 index 0000000000000000000000000000000000000000..78565d559185207c3210036571464abd5684f6af --- /dev/null +++ b/openpose/include/openpose/tracking/personIdExtractor.hpp @@ -0,0 +1,33 @@ +#ifndef OPENPOSE_TRACKING_PERSON_ID_EXTRACTOR_HPP +#define OPENPOSE_TRACKING_PERSON_ID_EXTRACTOR_HPP + +#include + +namespace op +{ + class OP_API PersonIdExtractor + { + public: + PersonIdExtractor(const float confidenceThreshold = 0.1f, const float inlierRatioThreshold = 0.5f, + const float distanceThreshold = 30.f, const int numberFramesToDeletePerson = 10); + + virtual ~PersonIdExtractor(); + + Array extractIds(const Array& poseKeypoints, const Matrix& cvMatInput, + const unsigned long long imageViewIndex = 0ull); + + Array extractIdsLockThread(const Array& poseKeypoints, const Matrix& cvMatInput, + const unsigned long long imageViewIndex, + const long long frameId); + + private: + // PIMPL idiom + // http://www.cppsamples.com/common-tasks/pimpl.html + struct ImplPersonIdExtractor; + std::shared_ptr spImpl; + + DELETE_COPY(PersonIdExtractor); + }; +} + +#endif // OPENPOSE_TRACKING_PERSON_ID_EXTRACTOR_HPP diff --git a/openpose/include/openpose/tracking/personTracker.hpp b/openpose/include/openpose/tracking/personTracker.hpp new file mode 100644 index 0000000000000000000000000000000000000000..339901884b5329ed96f24986ddbe1315c7ffb15c --- /dev/null +++ b/openpose/include/openpose/tracking/personTracker.hpp @@ -0,0 +1,34 @@ +#ifndef OPENPOSE_OPENPOSE_PRIVATE_TRACKING_PERSON_TRACKER_HPP +#define OPENPOSE_OPENPOSE_PRIVATE_TRACKING_PERSON_TRACKER_HPP + +#include + +namespace op +{ + class OP_API PersonTracker + { + public: + PersonTracker(const bool mergeResults, const int levels = 3, const int patchSize = 31, + const float confidenceThreshold = 0.05f, const bool trackVelocity = false, + const bool scaleVarying = false, const float rescale = 640); + + virtual ~PersonTracker(); + + void track(Array& poseKeypoints, Array& poseIds, const Matrix& cvMatInput); + + void trackLockThread(Array& poseKeypoints, Array& poseIds, const Matrix& cvMatInput, + const long long frameId); + + bool getMergeResults() const; + + private: + // PIMPL idiom + // http://www.cppsamples.com/common-tasks/pimpl.html + struct ImplPersonTracker; + std::shared_ptr spImpl; + + DELETE_COPY(PersonTracker); + }; +} + +#endif // OPENPOSE_OPENPOSE_PRIVATE_TRACKING_PERSON_TRACKER_HPP diff --git a/openpose/include/openpose/tracking/wPersonIdExtractor.hpp b/openpose/include/openpose/tracking/wPersonIdExtractor.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8f97b2727543858c37434eff53468999cef06401 --- /dev/null +++ b/openpose/include/openpose/tracking/wPersonIdExtractor.hpp @@ -0,0 +1,86 @@ +#ifndef OPENPOSE_TRACKING_W_PERSON_ID_EXTRACTOR_HPP +#define OPENPOSE_TRACKING_W_PERSON_ID_EXTRACTOR_HPP + +#include +#include +#include + +namespace op +{ + template + class WPersonIdExtractor : public Worker + { + public: + explicit WPersonIdExtractor(const std::shared_ptr& personIdExtractor); + + virtual ~WPersonIdExtractor(); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + std::shared_ptr spPersonIdExtractor; + + DELETE_COPY(WPersonIdExtractor); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WPersonIdExtractor::WPersonIdExtractor(const std::shared_ptr& personIdExtractor) : + spPersonIdExtractor{personIdExtractor} + { + } + + template + WPersonIdExtractor::~WPersonIdExtractor() + { + } + + template + void WPersonIdExtractor::initializationOnThread() + { + } + + template + void WPersonIdExtractor::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // Render people pose + for (auto& tDatumPtr : *tDatums) + tDatumPtr->poseIds = spPersonIdExtractor->extractIds( + tDatumPtr->poseKeypoints, tDatumPtr->cvInputData); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + opLogIfDebug("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + COMPILE_TEMPLATE_DATUM(WPersonIdExtractor); +} + +#endif // OPENPOSE_TRACKING_W_PERSON_ID_EXTRACTOR_HPP diff --git a/openpose/include/openpose/unity/headers.hpp b/openpose/include/openpose/unity/headers.hpp new file mode 100644 index 0000000000000000000000000000000000000000..37a37e8a2175f314b7e3b71f2a1151047d93d436 --- /dev/null +++ b/openpose/include/openpose/unity/headers.hpp @@ -0,0 +1,7 @@ +#ifndef OPENPOSE_UNITY_HEADERS_HPP +#define OPENPOSE_UNITY_HEADERS_HPP + +// unity module +#include + +#endif // OPENPOSE_UNITY_HEADERS_HPP diff --git a/openpose/include/openpose/unity/unityBinding.hpp b/openpose/include/openpose/unity/unityBinding.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1a09ea815deece390ee0f6b1c003f16777ea66d7 --- /dev/null +++ b/openpose/include/openpose/unity/unityBinding.hpp @@ -0,0 +1,3 @@ +// Temporarily, all the code is located in +// src/openpose/unity/unityBinding.cpp +// TODO: Move functionality from unityBinding.cpp to this class diff --git a/openpose/include/openpose/utilities/check.hpp b/openpose/include/openpose/utilities/check.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5d773263d1ab1ae890697856ea2c475be638f1a7 --- /dev/null +++ b/openpose/include/openpose/utilities/check.hpp @@ -0,0 +1,79 @@ +#ifndef OPENPOSE_UTILITIES_CHECK_HPP +#define OPENPOSE_UTILITIES_CHECK_HPP + +#include + +namespace op +{ + // CHECK, CHECK_EQ, CHECK_NE, CHECK_LE, CHECK_LT, CHECK_GE, and CHECK_GT + template + void checkBool( + const bool condition, const T& message = "", const int line = -1, const std::string& function = "", + const std::string& file = "") + { + if (!condition) + error("Check failed: " + tToString(message), line, function, file); + } + + template + void checkEqual( + const T1& conditionA, const T2& conditionB, const T& message = "", const int line = -1, + const std::string& function = "", const std::string& file = "") + { + if (conditionA != conditionB) + error("CheckE failed (" + tToString(conditionA) + " vs. " + tToString(conditionB) + "): " + + tToString(message), line, function, file); + } + + template + void checkNotEqual( + const T1& conditionA, const T2& conditionB, const T& message = "", const int line = -1, + const std::string& function = "", const std::string& file = "") + { + if (conditionA == conditionB) + error("CheckNE failed (" + tToString(conditionA) + " vs. " + tToString(conditionB) + "): " + + tToString(message), line, function, file); + } + + template + void checkLessOrEqual( + const T1& conditionA, const T2& conditionB, const T& message = "", const int line = -1, + const std::string& function = "", const std::string& file = "") + { + if (conditionA > conditionB) + error("CheckLE failed (" + tToString(conditionA) + " vs. " + tToString(conditionB) + "): " + + tToString(message), line, function, file); + } + + template + void checkLessThan( + const T1& conditionA, const T2& conditionB, const T& message = "", const int line = -1, + const std::string& function = "", const std::string& file = "") + { + if (conditionA >= conditionB) + error("CheckLT failed (" + tToString(conditionA) + " vs. " + tToString(conditionB) + "): " + + tToString(message), line, function, file); + } + + template + void checkGreaterOrEqual( + const T1& conditionA, const T2& conditionB, const T& message = "", const int line = -1, + const std::string& function = "", const std::string& file = "") + { + if (conditionA < conditionB) + error("CheckGE failed (" + tToString(conditionA) + " vs. " + tToString(conditionB) + "): " + + tToString(message), line, function, file); + } + + template + void checkGreaterThan( + const T1& conditionA, const T2& conditionB, const T& message = "", const int line = -1, + const std::string& function = "", const std::string& file = "") + { + if (conditionA <= conditionB) + error("CheckGT failed (" + tToString(conditionA) + " vs. " + tToString(conditionB) + "): " + + tToString(message), line, function, file); + } +} + +#endif // OPENPOSE_UTILITIES_CHECK_HPP diff --git a/openpose/include/openpose/utilities/enumClasses.hpp b/openpose/include/openpose/utilities/enumClasses.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4b724a271ff04736d48745a4e03283611ab82ac7 --- /dev/null +++ b/openpose/include/openpose/utilities/enumClasses.hpp @@ -0,0 +1,38 @@ +#ifndef OPENPOSE_UTILITIES_ENUM_CLASSES_HPP +#define OPENPOSE_UTILITIES_ENUM_CLASSES_HPP + +namespace op +{ + enum class ErrorMode : unsigned char + { + StdRuntimeError, + FileLogging, + StdCerr, + All, + }; + + enum class LogMode : unsigned char + { + FileLogging, + StdCout, + All, + }; + + enum class Priority : unsigned char + { + None = 0, + Low = 1, + Normal = 2, + High = 3, + Max = 4, + NoOutput = 255, + }; + + enum class Extensions : unsigned char + { + Images, // jpg, png, ... + Size + }; +} + +#endif // OPENPOSE_UTILITIES_ENUM_CLASSES_HPP diff --git a/openpose/include/openpose/utilities/errorAndLog.hpp b/openpose/include/openpose/utilities/errorAndLog.hpp new file mode 100644 index 0000000000000000000000000000000000000000..edfdcfee21c9deb62d921d0169f26a9305d55393 --- /dev/null +++ b/openpose/include/openpose/utilities/errorAndLog.hpp @@ -0,0 +1,135 @@ +#ifndef OPENPOSE_UTILITIES_ERROR_AND_LOG_HPP +#define OPENPOSE_UTILITIES_ERROR_AND_LOG_HPP + +#include // std::stringstream +#include +#include +#include +#include + +namespace op +{ + OP_API void setMainThread(); + + OP_API std::string getThreadId(); + + OP_API bool getIfInMainThreadOrEmpty(); + + OP_API bool getIfNotInMainThreadOrEmpty(); + + template + std::string tToString(const T& message) + { + // Message -> ostringstream + std::ostringstream oss; + oss << message; + // ostringstream -> std::string + return oss.str(); + } + + /** + * Differences between different kind of errors: + * - error() is a normal error in the code. + * - errorWorker() is an error that occurred on a thread. Therefore, the machine will stop the threads, go back + * to the main thread, and then throw the error. + * - errorDestructor() is an error that occurred on a destructor. Exception on destructors provokes core dumped, + * so we simply output an error message via std::cerr. + */ + + // Error management - How to use: + // error(message, __LINE__, __FUNCTION__, __FILE__); + OP_API void error( + const std::string& message, const int line = -1, const std::string& function = "", + const std::string& file = ""); + + template + inline void error( + const T& message, const int line = -1, const std::string& function = "", const std::string& file = "") + { + error(tToString(message), line, function, file); + } + + // Worker error management + OP_API void checkWorkerErrors(); + + OP_API void errorWorker( + const std::string& message, const int line = -1, const std::string& function = "", + const std::string& file = ""); + + template + inline void errorWorker( + const T& message, const int line = -1, const std::string& function = "", const std::string& file = "") + { + errorWorker(tToString(message), line, function, file); + } + + // Destructor error management + OP_API void errorDestructor( + const std::string& message, const int line = -1, const std::string& function = "", + const std::string& file = ""); + + template + inline void errorDestructor( + const T& message, const int line = -1, const std::string& function = "", const std::string& file = "") + { + errorDestructor(tToString(message), line, function, file); + } + + // Printing info - How to use: + // It will print info if desiredPriority >= sPriorityThreshold + // opLog(message, desiredPriority, __LINE__, __FUNCTION__, __FILE__); + OP_API void opLog( + const std::string& message, const Priority priority = Priority::Max, const int line = -1, + const std::string& function = "", const std::string& file = ""); + + template + inline void opLog( + const T& message, const Priority priority = Priority::Max, const int line = -1, + const std::string& function = "", const std::string& file = "") + { + opLog(tToString(message), priority, line, function, file); + } + + // If only desired on debug mode (no computational cost at all on release mode): + // It will print info if desiredPriority >= sPriorityThreshold + // opLogIfDebug(message, desiredPriority, __LINE__, __FUNCTION__, __FILE__); + template + inline void opLogIfDebug( + const T& message, const Priority priority = Priority::Max, const int line = -1, + const std::string& function = "", const std::string& file = "") + { + #ifndef NDEBUG + opLog(message, priority, line, function, file); + #else + UNUSED(message); + UNUSED(priority); + UNUSED(line); + UNUSED(function); + UNUSED(file); + #endif + } + + // This class is thread-safe + namespace ConfigureError + { + OP_API std::vector getErrorModes(); + + OP_API void setErrorModes(const std::vector& errorModes); + } + + // This class is not fully thread-safe + namespace ConfigureLog + { + OP_API Priority getPriorityThreshold(); + + OP_API const std::vector& getLogModes(); + + // This function is not thread-safe. It must be run at the beginning + OP_API void setPriorityThreshold(const Priority priorityThreshold); + + // This function is not thread-safe. It must be run at the beginning + OP_API void setLogModes(const std::vector& loggingModes); + } +} + +#endif // OPENPOSE_UTILITIES_ERROR_AND_LOG_HPP diff --git a/openpose/include/openpose/utilities/fastMath.hpp b/openpose/include/openpose/utilities/fastMath.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a174f2f324751fb4388471a3ac45b146312adfc2 --- /dev/null +++ b/openpose/include/openpose/utilities/fastMath.hpp @@ -0,0 +1,91 @@ +#ifndef OPENPOSE_UTILITIES_MATH_HPP +#define OPENPOSE_UTILITIES_MATH_HPP + +namespace op +{ + // Use op::round/max/min for basic types (int, char, long, float, double, etc). Never with classes! + // `std::` alternatives uses 'const T&' instead of 'const T' as argument. + // E.g., std::round is really slow (~300 ms vs ~10 ms when I individually apply it to each element of a whole + // image array + + // VERY IMPORTANT: These fast functions does NOT work for negative integer numbers. + // E.g., positiveIntRound(-180.f) = -179. + + // Round functions + // Signed + template + inline char positiveCharRound(const T a) + { + return char(a+0.5f); + } + + template + inline signed char positiveSCharRound(const T a) + { + return (signed char)(a+0.5f); + } + + template + inline int positiveIntRound(const T a) + { + return int(a+0.5f); + } + + template + inline long positiveLongRound(const T a) + { + return long(a+0.5f); + } + + template + inline long long positiveLongLongRound(const T a) + { + return (long long)(a+0.5f); + } + + // Unsigned + template + inline unsigned char uCharRound(const T a) + { + return (unsigned char)(a+0.5f); + } + + template + inline unsigned int uIntRound(const T a) + { + return (unsigned int)(a+0.5f); + } + + template + inline unsigned long ulongRound(const T a) + { + return (unsigned long)(a+0.5f); + } + + template + inline unsigned long long uLongLongRound(const T a) + { + return (unsigned long long)(a+0.5f); + } + + // Max/min functions + template + inline T fastMax(const T a, const T b) + { + return (a > b ? a : b); + } + + template + inline T fastMin(const T a, const T b) + { + return (a < b ? a : b); + } + + template + inline T fastTruncate(T value, T min = 0, T max = 1) + { + return fastMin(max, fastMax(min, value)); + } +} + +#endif // OPENPOSE_UTILITIES_MATH_HPP diff --git a/openpose/include/openpose/utilities/fileSystem.hpp b/openpose/include/openpose/utilities/fileSystem.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d897fb98a8d60dbaac5945db2f09c0136f3f476e --- /dev/null +++ b/openpose/include/openpose/utilities/fileSystem.hpp @@ -0,0 +1,95 @@ +#ifndef OPENPOSE_UTILITIES_FILE_SYSTEM_HPP +#define OPENPOSE_UTILITIES_FILE_SYSTEM_HPP + +#include + +namespace op +{ + OP_API void makeDirectory(const std::string& directoryPath); + + OP_API bool existDirectory(const std::string& directoryPath); + + OP_API bool existFile(const std::string& filePath); + + /** + * This function makes sure that the directoryPathString is properly formatted. I.e., it + * changes all '\' by '/', and it makes sure that the string finishes with '/'. + * @param directoryPathString std::string with the directory path to be formatted. + * @return std::string with the formatted directory path. + */ + OP_API std::string formatAsDirectory(const std::string& directoryPathString); + + /** + * This function extracts the file name and extension from a full path. + * @param fullPath std::string with the full path. + * @return std::string with the file name with extension. + */ + OP_API std::string getFileNameAndExtension(const std::string& fullPath); + + /** + * This function extracts the file name (without extension) from a full path. + * @param fullPath std::string with the full path. + * @return std::string with the file name without extension. + */ + OP_API std::string getFileNameNoExtension(const std::string& fullPath); + + /** + * This function extracts the extension from a full path. + * E.g., if fullPath is `/media/document.txt`, output will be `txt` + * @param fullPath std::string with the full path. + * @return std::string with the file extension. + */ + OP_API std::string getFileExtension(const std::string& fullPath); + + /** + * This function extracts the full file path without its extension from a full file path. + * @param fullPath std::string with the full path. + * @return std::string with the full file path without extension. + */ + OP_API std::string getFullFilePathNoExtension(const std::string& fullPath); + + /** + * This function extracts the full file path of the folder where it is contained. + * @param fullPath std::string with the full path. + * @return std::string with the full file path of the folder. + */ + OP_API std::string getFileParentFolderPath(const std::string& fullPath); + + /** + * This function extracts all the files in a directory path with the desired + * extensions. If no extensions is specified, then all the file names are returned. + * @param directoryPath std::string with the directory path. + * @param extensions std::vector with the extensions of the desired files. + * @return std::vector with the existing file names. + */ + OP_API std::vector getFilesOnDirectory( + const std::string& directoryPath, const std::vector& extensions = {}); + + /** + * Analogous to getFilesOnDirectory(const std::string& directoryPath, const std::vector& extensions) + * for 1 specific extension. + * @param directoryPath std::string with the directory path. + * @param extension std::string with the extension of the desired files. + * @return std::vector with the existing file names. + */ + OP_API std::vector getFilesOnDirectory( + const std::string& directoryPath, const std::string& extension); + + /** + * This function extracts all the files in a directory path with the desired + * group of extensions (e.g., Extensions::Images). + * @param directoryPath std::string with the directory path. + * @param extensions Extensions with the kind of extensions desired (e.g., Extensions:Images). + * @return std::vector with the existing file names. + */ + OP_API std::vector getFilesOnDirectory( + const std::string& directoryPath, const Extensions extensions); + + OP_API std::string removeSpecialsCharacters(const std::string& stringToVariate); + + OP_API void removeAllOcurrencesOfSubString(std::string& stringToModify, const std::string& substring); + + OP_API void replaceAll(std::string& stringText, const char charToChange, const char charToAdd); +} + +#endif // OPENPOSE_UTILITIES_FILE_SYSTEM_HPP diff --git a/openpose/include/openpose/utilities/flagsToOpenPose.hpp b/openpose/include/openpose/utilities/flagsToOpenPose.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8cedea31bff593aefd47e5fdeef8ae54dfd9256f --- /dev/null +++ b/openpose/include/openpose/utilities/flagsToOpenPose.hpp @@ -0,0 +1,48 @@ +#ifndef OPENPOSE_UTILITIES_FLAGS_TO_OPEN_POSE_HPP +#define OPENPOSE_UTILITIES_FLAGS_TO_OPEN_POSE_HPP + +#include +#include +#include +#include +#include +#include + +namespace op +{ + OP_API PoseMode flagsToPoseMode(const int poseModeInt); + + OP_API PoseModel flagsToPoseModel(const String& poseModeString); + + OP_API ScaleMode flagsToScaleMode(const int keypointScaleMode); + + OP_API ScaleMode flagsToHeatMapScaleMode(const int heatMapScaleMode); + + OP_API Detector flagsToDetector(const int detector); + + // Determine type of frame source + OP_API ProducerType flagsToProducerType( + const String& imageDirectory, const String& videoPath, const String& ipCameraPath, + const int webcamIndex, const bool flirCamera); + + OP_API std::pair flagsToProducer( + const String& imageDirectory, const String& videoPath, const String& ipCameraPath = String(""), + const int webcamIndex = -1, const bool flirCamera = false, const int flirCameraIndex = -1); + + OP_API std::vector flagsToHeatMaps( + const bool heatMapsAddParts = false, const bool heatMapsAddBkg = false, + const bool heatMapsAddPAFs = false); + + OP_API RenderMode flagsToRenderMode( + const int renderFlag, const bool gpuBuggy = false, const int renderPoseFlag = -2); + + OP_API DisplayMode flagsToDisplayMode(const int display, const bool enabled3d); + + /** + * E.g., const Point netInputSize = flagsToPoint(op::String(FLAGS_net_resolution), "-1x368"); + * E.g., const Point resolution = flagsToPoint(resolutionString, "1280x720"); + */ + OP_API Point flagsToPoint(const String& pointString, const String& pointExample); +} + +#endif // OPENPOSE_UTILITIES_FLAGS_TO_OPEN_POSE_HPP diff --git a/openpose/include/openpose/utilities/headers.hpp b/openpose/include/openpose/utilities/headers.hpp new file mode 100644 index 0000000000000000000000000000000000000000..34bdc415a1413f17310f823ca81df35a113a6f92 --- /dev/null +++ b/openpose/include/openpose/utilities/headers.hpp @@ -0,0 +1,18 @@ +#ifndef OPENPOSE_UTILITIES_HEADERS_HPP +#define OPENPOSE_UTILITIES_HEADERS_HPP + +// utilities module +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // OPENPOSE_UTILITIES_HEADERS_HPP diff --git a/openpose/include/openpose/utilities/keypoint.hpp b/openpose/include/openpose/utilities/keypoint.hpp new file mode 100644 index 0000000000000000000000000000000000000000..de65a730fb32875fae31b18039938e1bcd1fd216 --- /dev/null +++ b/openpose/include/openpose/utilities/keypoint.hpp @@ -0,0 +1,82 @@ +#ifndef OPENPOSE_UTILITIES_KEYPOINT_HPP +#define OPENPOSE_UTILITIES_KEYPOINT_HPP + +#include + +namespace op +{ + template + T getDistance(const Array& keypoints, const int person, const int elementA, const int elementB); + + template + void averageKeypoints(Array& keypointsA, const Array& keypointsB, const int personA); + + template + void scaleKeypoints(Array& keypoints, const T scale); + + template + void scaleKeypoints2d(Array& keypoints, const T scaleX, const T scaleY); + + template + void scaleKeypoints2d(Array& keypoints, const T scaleX, const T scaleY, const T offsetX, const T offsetY); + + template + void renderKeypointsCpu( + Array& frameArray, const Array& keypoints, const std::vector& pairs, + const std::vector colors, const T thicknessCircleRatio, const T thicknessLineRatioWRTCircle, + const std::vector& poseScales, const T threshold); + + template + Rectangle getKeypointsRectangle( + const Array& keypoints, const int person, const T threshold, const int firstIndex = 0, + const int lastIndex = -1); + + template + T getAverageScore(const Array& keypoints, const int person); + + template + T getKeypointsArea(const Array& keypoints, const int person, const T threshold); + + template + int getBiggestPerson(const Array& keypoints, const T threshold); + + template + int getNonZeroKeypoints(const Array& keypoints, const int person, const T threshold); + + template + T getDistanceAverage(const Array& keypoints, const int personA, const int personB, const T threshold); + + template + T getDistanceAverage( + const Array& keypointsA, const int personA, const Array& keypointsB, const int personB, + const T threshold); + + /** + * Creates and Array with a specific person. + * @param keypoints Array with the original data array to slice. + * @param person indicates the index of the array to extract. + * @param noCopy indicates whether to perform a copy. Copy will never go to undefined behavior, however, if + * noCopy == true, then: + * 1. It is faster, as no data copy is involved, but... + * 2. If the Array keypoints goes out of scope, then the resulting Array will provoke an undefined behavior. + * 3. If the returned Array is modified, the information in the Array keypoints will also be. + * @return Array with the same dimension than keypoints expect the first dimension being 1. E.g., if keypoints + * is {p,k,m}, the resulting Array is {1,k,m}. + */ + template + Array getKeypointsPerson(const Array& keypoints, const int person, const bool noCopy = false); + + template + float getKeypointsRoi(const Array& keypoints, const int personA, const int personB, const T threshold); + + template + float getKeypointsRoi( + const Array& keypointsA, const int personA, const Array& keypointsB, const int personB, + const T threshold); + + template + float getKeypointsRoi( + const Rectangle& rectangleA, const Rectangle& rectangleB); +} + +#endif // OPENPOSE_UTILITIES_KEYPOINT_HPP diff --git a/openpose/include/openpose/utilities/openCv.hpp b/openpose/include/openpose/utilities/openCv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..fd8ae9cb02df8e1849be96d34b9861f7179cf8cb --- /dev/null +++ b/openpose/include/openpose/utilities/openCv.hpp @@ -0,0 +1,72 @@ +#ifndef OPENPOSE_UTILITIES_OPEN_CV_HPP +#define OPENPOSE_UTILITIES_OPEN_CV_HPP + +#include + +namespace op +{ + OP_API void unrollArrayToUCharCvMat(Matrix& matResult, const Array& array); + + OP_API void uCharCvMatToFloatPtr(float* floatPtrImage, const Matrix& matImage, const int normalize); + + OP_API double resizeGetScaleFactor(const Point& initialSize, const Point& targetSize); + + OP_API void keepRoiInside(Rectangle& roi, const int imageWidth, const int imageHeight); + + OP_API void transpose(Matrix& matrix); + + /** + * It performs rotation and flipping over the desired Mat. + * @param cvMat Mat with the frame matrix to be rotated and/or flipped. + * @param rotationAngle How much the cvMat element should be rotated. 0 would mean no rotation. + * @param flipFrame Whether to flip the cvMat element. Set to false to disable it. + */ + OP_API void rotateAndFlipFrame(Matrix& frame, const double rotationAngle, const bool flipFrame = false); + + /** + * Wrapper of CV_CAP_PROP_FRAME_COUNT to avoid leaving OpenCV dependencies on headers. + */ + OP_API int getCvCapPropFrameCount(); + + /** + * Wrapper of CV_CAP_PROP_FRAME_FPS to avoid leaving OpenCV dependencies on headers. + */ + OP_API int getCvCapPropFrameFps(); + + /** + * Wrapper of CV_CAP_PROP_FRAME_WIDTH to avoid leaving OpenCV dependencies on headers. + */ + OP_API int getCvCapPropFrameWidth(); + + /** + * Wrapper of CV_CAP_PROP_FRAME_HEIGHT to avoid leaving OpenCV dependencies on headers. + */ + OP_API int getCvCapPropFrameHeight(); + + /** + * Wrapper of CV_FOURCC to avoid leaving OpenCV dependencies on headers. + */ + OP_API int getCvFourcc(const char c1, const char c2, const char c3, const char c4); + + /** + * Wrapper of CV_IMWRITE_JPEG_QUALITY to avoid leaving OpenCV dependencies on headers. + */ + OP_API int getCvImwriteJpegQuality(); + + /** + * Wrapper of CV_IMWRITE_PNG_COMPRESSION to avoid leaving OpenCV dependencies on headers. + */ + OP_API int getCvImwritePngCompression(); + + /** + * Wrapper of CV_LOAD_IMAGE_ANYDEPTH to avoid leaving OpenCV dependencies on headers. + */ + OP_API int getCvLoadImageAnydepth(); + + /** + * Wrapper of CV_LOAD_IMAGE_GRAYSCALE to avoid leaving OpenCV dependencies on headers. + */ + OP_API int getCvLoadImageGrayScale(); +} + +#endif // OPENPOSE_UTILITIES_OPEN_CV_HPP diff --git a/openpose/include/openpose/utilities/pointerContainer.hpp b/openpose/include/openpose/utilities/pointerContainer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5e063978b70683b52e29dc4aa4040b133138eba8 --- /dev/null +++ b/openpose/include/openpose/utilities/pointerContainer.hpp @@ -0,0 +1,43 @@ +#ifndef OPENPOSE_UTILITIES_POINTER_CONTAINER_HPP +#define OPENPOSE_UTILITIES_POINTER_CONTAINER_HPP + +namespace op +{ + template + inline bool checkNoNullNorEmpty(const TPointerContainer& tPointerContainer) + { + return (tPointerContainer != nullptr && tPointerContainer->size() > 0); + } + + template + class PointerContainerGreater + { + public: + bool operator() (const TDatumsSP& a, const TDatumsSP& b) + { + if (!b || b->empty()) + return true; + else if (!a || a->empty()) + return false; + else + return *(*a)[0] > *(*b)[0]; + } + }; + + template + class PointerContainerLess + { + public: + bool operator() (const TDatumsSP& a, const TDatumsSP& b) + { + if (!b || b->empty()) + return false; + else if (!a || a->empty()) + return true; + else + return *(*a)[0] < *(*b)[0]; + } + }; +} + +#endif // OPENPOSE_UTILITIES_POINTER_CONTAINER_HPP diff --git a/openpose/include/openpose/utilities/profiler.hpp b/openpose/include/openpose/utilities/profiler.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7220137a6a8a01225f9cf050ae975322c8b7dd34 --- /dev/null +++ b/openpose/include/openpose/utilities/profiler.hpp @@ -0,0 +1,100 @@ +#ifndef OPENPOSE_UTILITIES_PROFILER_HPP +#define OPENPOSE_UTILITIES_PROFILER_HPP + +#include +#include +#include +#include + +namespace op +{ + // The following functions provides basic functions to measure time. Usage example: + // const auto timerInit = getTimerInit(); + // // [Some code in here] + // const auto timeSeconds = getTimeSeconds(timerInit); + // const printTime(timeSeconds, "Function X took ", " seconds."); + OP_API std::chrono::time_point getTimerInit(); + + OP_API double getTimeSeconds(const std::chrono::time_point& timerInit); + + OP_API void printTime( + const std::chrono::time_point& timerInit, const std::string& firstMessage, + const std::string& secondMessage, const Priority priority); + + // The following functions will run REPS times and average the final time in seconds. Usage example: + // const auto REPS = 1000; + // double time = 0.; + // OP_PROFILE_INIT(REPS); + // // [Some code in here] + // OP_PROFILE_END(time, 1e3, REPS); // Time in msec. 1 = sec, 1e3 = msec, 1e6 = usec, 1e9 = nsec, etc. + // opLog("Function X took " + std::to_string(time) + " milliseconds."); + #define OP_PROFILE_INIT(REPS) \ + { \ + const auto timerInit = getTimerInit(); \ + for (auto rep = 0 ; rep < (REPS) ; ++rep) \ + { + #define OP_PROFILE_END(finalTime, factor, REPS) \ + } \ + (finalTime) = (factor)/(float)(REPS)*getTimeSeconds(timerInit); \ + } + + // The following functions will run REPS times, wait for the kernels to finish, and then average the final time + // in seconds. Usage example: + // const auto REPS = 1000; + // double time = 0.; + // OP_CUDA_PROFILE_INIT(REPS); + // // [Some code with CUDA calls in here] + // OP_CUDA_PROFILE_END(time, 1e3, REPS); // Time in msec. 1 = sec, 1e3 = msec, 1e6 = usec, 1e9 = nsec, etc. + // opLog("Function X took " + std::to_string(time) + " milliseconds."); + // Analogous to OP_PROFILE_INIT, but also waits for CUDA kernels to finish their asynchronous operations + // It requires: #include + #define OP_CUDA_PROFILE_INIT(REPS) \ + { \ + cudaDeviceSynchronize(); \ + const auto timerInit = getTimerInit(); \ + for (auto rep = 0 ; rep < (REPS) ; ++rep) \ + { + // Analogous to OP_PROFILE_END, but also waits for CUDA kernels to finish their asynchronous operations + // It requires: #include + #define OP_CUDA_PROFILE_END(finalTime, factor, REPS) \ + } \ + cudaDeviceSynchronize(); \ + (finalTime) = (factor)/(float)(REPS)*getTimeSeconds(timerInit); \ + cudaCheck(__LINE__, __FUNCTION__, __FILE__); \ + } + + // Enable PROFILER_ENABLED on Makefile.config or CMake in order to use this function. Otherwise nothing will be outputted. + // How to use - example: + // For GPU - It can only be applied in the main.cpp file: + // Profiler::profileGpuMemory(__LINE__, __FUNCTION__, __FILE__); + // For time: + // // ... inside continuous loop ... + // const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + // // functions to do... + // Profiler::timerEnd(profilerKey); + // Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, NUMBER_ITERATIONS); + class OP_API Profiler + { + public: + static unsigned long long DEFAULT_X; + + // Non-thread safe, it must be performed at the beginning of the code before any parallelization occurs + static void setDefaultX(const unsigned long long defaultX); + + static const std::string timerInit(const int line, const std::string& function, const std::string& file); + + static void timerEnd(const std::string& key); + + static void printAveragedTimeMsOnIterationX( + const std::string& key, const int line, const std::string& function, const std::string& file, + const unsigned long long x = DEFAULT_X); + + static void printAveragedTimeMsEveryXIterations( + const std::string& key, const int line, const std::string& function, const std::string& file, + const unsigned long long x = DEFAULT_X); + + static void profileGpuMemory(const int line, const std::string& function, const std::string& file); + }; +} + +#endif // OPENPOSE_UTILITIES_PROFILER_HPP diff --git a/openpose/include/openpose/utilities/standard.hpp b/openpose/include/openpose/utilities/standard.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b249a25fd2f842b8de038ac81541ace123763c50 --- /dev/null +++ b/openpose/include/openpose/utilities/standard.hpp @@ -0,0 +1,57 @@ +#ifndef OPENPOSE_UTILITIES_STANDARD_HPP +#define OPENPOSE_UTILITIES_STANDARD_HPP + +#include + +namespace op +{ + template + bool vectorsAreEqual(const std::vector& vectorA, const std::vector& vectorB) + { + try + { + if (vectorA.size() != vectorB.size()) + return false; + else + { + for (auto i = 0u ; i < vectorA.size() ; i++) + if (vectorA[i] != vectorB[i]) + return false; + return true; + } + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + /** + * std::vector concatenator. + * Auxiliary function that concatenate std::vectors of any class type T. + * It assumes basic copy (ideal for smart pointers, pointers, etc.), so note that the copy still shares the same + * internal data. It will not work for element that cannot be copied. + * @param vectorA First std::shared_ptr element to be concatenated. + * @param vectorB Second std::shared_ptr element to be concatenated. + * @return Concatenated std::vector of both vectorA and vectorB. + */ + template + std::vector mergeVectors(const std::vector& vectorA, const std::vector& vectorB) + { + try + { + auto vectorToReturn(vectorA); + for (auto& tElement : vectorB) + vectorToReturn.emplace_back(tElement); + return vectorToReturn; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return std::vector{}; + } + } +} + +#endif // OPENPOSE_UTILITIES_STANDARD_HPP diff --git a/openpose/include/openpose/utilities/string.hpp b/openpose/include/openpose/utilities/string.hpp new file mode 100644 index 0000000000000000000000000000000000000000..31c13e0082cb56c0976283bdc54a6d66512b405f --- /dev/null +++ b/openpose/include/openpose/utilities/string.hpp @@ -0,0 +1,31 @@ +#ifndef OPENPOSE_UTILITIES_STRING_HPP +#define OPENPOSE_UTILITIES_STRING_HPP + +#include + +namespace op +{ + OP_API unsigned long long getLastNumber(const std::string& string); + + /** + * This template function turns an integer number into a fixed-length std::string. + * @param number T integer corresponding to the integer to be formatted. + * @param stringLength unsigned long long indicating the final length. If 0, the + * final length is the original number length. + * @return std::string with the formatted value. + */ + template + std::string toFixedLengthString(const T number, const unsigned long long stringLength = 0); + + OP_API std::vector splitString(const std::string& stringToSplit, const std::string& delimiter); + + OP_API std::string toLower(const std::string& string); + + OP_API std::string toUpper(const std::string& string); + + OP_API std::string remove0sFromString(const std::string& string); + + OP_API std::string getFirstNumberOnString(const std::string& string); +} + +#endif // OPENPOSE_UTILITIES_STRING_HPP diff --git a/openpose/include/openpose/wrapper/enumClasses.hpp b/openpose/include/openpose/wrapper/enumClasses.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3d8283054d1d8bce8eadc3abd159d244d19a73a2 --- /dev/null +++ b/openpose/include/openpose/wrapper/enumClasses.hpp @@ -0,0 +1,33 @@ +#ifndef OPENPOSE_WRAPPER_ENUM_CLASSES_HPP +#define OPENPOSE_WRAPPER_ENUM_CLASSES_HPP + +namespace op +{ + enum class PoseMode : unsigned char + { + Disabled = 0, + Enabled, + NoNetwork, + Size, + }; + + enum class Detector : unsigned char + { + Body = 0, + OpenCV, + Provided, + BodyWithTracking, + Size, + }; + + enum class WorkerType : unsigned char + { + Input = 0, + PreProcessing, + PostProcessing, + Output, + Size, + }; +} + +#endif // OPENPOSE_WRAPPER_ENUM_CLASSES_HPP diff --git a/openpose/include/openpose/wrapper/headers.hpp b/openpose/include/openpose/wrapper/headers.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1a49b8980fe0502a72d982f6a7f6d97dd7757b77 --- /dev/null +++ b/openpose/include/openpose/wrapper/headers.hpp @@ -0,0 +1,15 @@ +#ifndef OPENPOSE_WRAPPER_HEADERS_HPP +#define OPENPOSE_WRAPPER_HEADERS_HPP + +// wrapper module +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // OPENPOSE_WRAPPER_HEADERS_HPP diff --git a/openpose/include/openpose/wrapper/wrapper.hpp b/openpose/include/openpose/wrapper/wrapper.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f281bb4cdee0919f5f1c7943e6ddbd31eb503394 --- /dev/null +++ b/openpose/include/openpose/wrapper/wrapper.hpp @@ -0,0 +1,716 @@ +#ifndef OPENPOSE_WRAPPER_WRAPPER_HPP +#define OPENPOSE_WRAPPER_WRAPPER_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace op +{ + /** + * WrapperT: OpenPose all-in-one wrapper template class. Simplified into Wrapper for WrapperT> + * WrapperT allows the user to set up the input (video, webcam, custom input, etc.), pose, face and/or hands + * estimation and rendering, and output (integrated small GUI, custom output, etc.). + * + * This function can be used in 2 ways: + * - Synchronous mode: call the full constructor with your desired input and output workers. + * - Asynchronous mode: call the empty constructor WrapperT() + use the emplace and pop functions to push the + * original frames and retrieve the processed ones. + * - Mix of them: + * - Synchronous input + asynchronous output: call the constructor WrapperT(ThreadManagerMode::Synchronous, + * workersInput, {}, true) + * - Asynchronous input + synchronous output: call the constructor + * WrapperT(ThreadManagerMode::Synchronous, nullptr, workersOutput, irrelevantBoolean, true) + */ + template>, + typename TDatumsSP = std::shared_ptr, + typename TWorker = std::shared_ptr>> + class WrapperT + { + public: + /** + * Constructor. + * @param threadManagerMode Thread synchronization mode. If set to ThreadManagerMode::Synchronous, everything + * will run inside the WrapperT. If ThreadManagerMode::Synchronous(In/Out), then input (frames producer) and/or + * output (GUI, writing results, etc.) will be controlled outside the WrapperT class by the user. See + * ThreadManagerMode for a detailed explanation of when to use each one. + */ + explicit WrapperT(const ThreadManagerMode threadManagerMode = ThreadManagerMode::Synchronous); + + /** + * Destructor. + * It automatically frees resources. + */ + virtual ~WrapperT(); + + /** + * Disable multi-threading. + * Useful for debugging and logging, all the Workers will run in the same thread. + * Note that workerOnNewThread (argument for setWorker function) will not make any effect. + */ + void disableMultiThreading(); + + /** + * Add an user-defined extra Worker for a desired task (input, output, ...). + * @param workerType WorkerType to configure (e.g., Input, PreProcessing, PostProcessing, Output). + * @param worker TWorker to be added. + * @param workerOnNewThread Whether to add this TWorker on a new thread (if it is computationally demanding) or + * simply reuse existing threads (for light functions). Set to true if the performance time is unknown. + */ + void setWorker(const WorkerType workerType, const TWorker& worker, const bool workerOnNewThread = true); + + /** + * It configures the pose parameters. Do not call for default values. + */ + void configure(const WrapperStructPose& wrapperStructPose); + + /** + * Analogous to configure(WrapperStructPose) but applied to face (WrapperStructFace) + */ + void configure(const WrapperStructFace& wrapperStructFace); + + /** + * Analogous to configure() but applied to hand (WrapperStructHand) + */ + void configure(const WrapperStructHand& wrapperStructHand); + + /** + * Analogous to configure() but applied to the extra options (WrapperStructExtra) + */ + void configure(const WrapperStructExtra& wrapperStructExtra); + + /** + * Analogous to configure() but applied to the input (WrapperStructInput) + */ + void configure(const WrapperStructInput& wrapperStructInput); + + /** + * Analogous to configure() but applied to the output (WrapperStructOutput) + */ + void configure(const WrapperStructOutput& wrapperStructOutput); + + /** + * Analogous to configure() but applied to the GUI (WrapperStructGui) + */ + void configure(const WrapperStructGui& wrapperStructGui); + + /** + * Function to start multi-threading. + * Similar to start(), but exec() blocks the thread that calls the function (it saves 1 thread). Use exec() + * instead of start() if the calling thread will otherwise be waiting for the WrapperT to end. + */ + void exec(); + + /** + * Function to start multi-threading. + * Similar to exec(), but start() does not block the thread that calls the function. It just opens new threads, + * so it lets the user perform other tasks meanwhile on the calling thread. + * VERY IMPORTANT NOTE: if the GUI is selected and OpenCV is compiled with Qt support, this option will not + * work. Qt needs the main thread to plot visual results, so the final GUI (which uses OpenCV) would return an + * exception similar to: `QMetaMethod::invoke: Unable to invoke methods with return values in queued + * connections`. Use exec() in that case. + */ + void start(); + + /** + * Function to stop multi-threading. + * It can be called internally or externally. + */ + void stop(); + + /** + * Whether the WrapperT is running. + * It will return true after exec() or start() and before stop(), and false otherwise. + * @return Boolean specifying whether the WrapperT is running. + */ + bool isRunning() const; + + /** + * It sets the maximum number of elements in the queue. + * For maximum speed, set to a very large number, but the trade-off would be: + * - Latency will hugely increase. + * - The program might go out of RAM memory (so the computer might freeze). + * For minimum latency while keeping an optimal speed, set to -1, that will automatically + * detect the ideal number based on how many elements are connected to that queue. + * @param defaultMaxSizeQueues long long element with the maximum number of elements on the queue. + */ + void setDefaultMaxSizeQueues(const long long defaultMaxSizeQueues = -1); + + /** + * Emplace (move) an element on the first (input) queue. + * Only valid if ThreadManagerMode::Asynchronous or ThreadManagerMode::AsynchronousIn. + * If the input queue is full or the WrapperT was stopped, it will return false and not emplace it. + * @param tDatums TDatumsSP element to be emplaced. + * @return Boolean specifying whether the tDatums could be emplaced. + */ + bool tryEmplace(TDatumsSP& tDatums); + + /** + * Emplace (move) an element on the first (input) queue. + * Similar to tryEmplace. + * However, if the input queue is full, it will wait until it can emplace it. + * If the WrapperT class is stopped before adding the element, it will return false and not emplace it. + * @param tDatums TDatumsSP element to be emplaced. + * @return Boolean specifying whether the tDatums could be emplaced. + */ + bool waitAndEmplace(TDatumsSP& tDatums); + + /** + * Similar to waitAndEmplace(const TDatumsSP& tDatums), but it takes a Matrix as input. + * @param matrix Matrix with the image to be processed. + * @return Boolean specifying whether the tDatums could be emplaced. + */ + bool waitAndEmplace(Matrix& matrix); + + /** + * Push (copy) an element on the first (input) queue. + * Same as tryEmplace, but it copies the data instead of moving it. + * @param tDatums TDatumsSP element to be pushed. + * @return Boolean specifying whether the tDatums could be pushed. + */ + bool tryPush(const TDatumsSP& tDatums); + + /** + * Push (copy) an element on the first (input) queue. + * Same as waitAndEmplace, but it copies the data instead of moving it. + * @param tDatums TDatumsSP element to be pushed. + * @return Boolean specifying whether the tDatums could be pushed. + */ + bool waitAndPush(const TDatumsSP& tDatums); + + /** + * Similar to waitAndPush(const TDatumsSP& tDatums), but it takes a Matrix as input. + * @param matrix Matrix with the image to be processed. + * @return Boolean specifying whether the tDatums could be pushed. + */ + bool waitAndPush(const Matrix& matrix); + + /** + * Pop (retrieve) an element from the last (output) queue. + * Only valid if ThreadManagerMode::Asynchronous or ThreadManagerMode::AsynchronousOut. + * If the output queue is empty or the WrapperT was stopped, it will return false and not retrieve it. + * @param tDatums TDatumsSP element where the retrieved element will be placed. + * @return Boolean specifying whether the tDatums could be retrieved. + */ + bool tryPop(TDatumsSP& tDatums); + + /** + * Pop (retrieve) an element from the last (output) queue. + * Similar to tryPop. + * However, if the output queue is empty, it will wait until it can pop an element. + * If the WrapperT class is stopped before popping the element, it will return false and not retrieve it. + * @param tDatums TDatumsSP element where the retrieved element will be placed. + * @return Boolean specifying whether the tDatums could be retrieved. + */ + bool waitAndPop(TDatumsSP& tDatums); + + /** + * Runs both waitAndEmplace and waitAndPop. + * @param tDatums TDatumsSP element where the retrieved element will be placed. + * @return Boolean specifying whether the tDatums could be retrieved. + */ + bool emplaceAndPop(TDatumsSP& tDatums); + + /** + * Similar to emplaceAndPop(TDatumsSP& tDatums), but it takes a Matrix as input. + * @param matrix Matrix with the image to be processed. + * @return TDatumsSP element where the processed information will be placed. + */ + TDatumsSP emplaceAndPop(const Matrix& matrix); + + private: + const ThreadManagerMode mThreadManagerMode; + ThreadManager mThreadManager; + bool mMultiThreadEnabled; + // Configuration + WrapperStructPose mWrapperStructPose; + WrapperStructFace mWrapperStructFace; + WrapperStructHand mWrapperStructHand; + WrapperStructExtra mWrapperStructExtra; + WrapperStructInput mWrapperStructInput; + WrapperStructOutput mWrapperStructOutput; + WrapperStructGui mWrapperStructGui; + // User configurable workers + std::array mUserWsOnNewThread; + std::array, int(WorkerType::Size)> mUserWs; + + DELETE_COPY(WrapperT); + }; + + // Type + typedef WrapperT Wrapper; +} + + + + + +// Implementation +#include +namespace op +{ + template + WrapperT::WrapperT(const ThreadManagerMode threadManagerMode) : + mThreadManagerMode{threadManagerMode}, + mThreadManager{threadManagerMode}, + mMultiThreadEnabled{true} + { + } + + template + WrapperT::~WrapperT() + { + try + { + stop(); + // Reset mThreadManager + mThreadManager.reset(); + // Reset user workers + for (auto& userW : mUserWs) + userW.clear(); + } + catch (const std::exception& e) + { + errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WrapperT::disableMultiThreading() + { + try + { + mMultiThreadEnabled = false; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WrapperT::setWorker( + const WorkerType workerType, const TWorker& worker, const bool workerOnNewThread) + { + try + { + // Sanity check + if (worker == nullptr) + error("Your worker is a nullptr.", __LINE__, __FILE__, __FUNCTION__); + // Add worker + mUserWs[int(workerType)].clear(); + mUserWs[int(workerType)].emplace_back(worker); + mUserWsOnNewThread[int(workerType)] = workerOnNewThread; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WrapperT::configure(const WrapperStructPose& wrapperStructPose) + { + try + { + mWrapperStructPose = wrapperStructPose; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WrapperT::configure(const WrapperStructFace& wrapperStructFace) + { + try + { + mWrapperStructFace = wrapperStructFace; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WrapperT::configure(const WrapperStructHand& wrapperStructHand) + { + try + { + mWrapperStructHand = wrapperStructHand; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WrapperT::configure(const WrapperStructExtra& wrapperStructExtra) + { + try + { + mWrapperStructExtra = wrapperStructExtra; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WrapperT::configure(const WrapperStructInput& wrapperStructInput) + { + try + { + mWrapperStructInput = wrapperStructInput; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WrapperT::configure(const WrapperStructOutput& wrapperStructOutput) + { + try + { + mWrapperStructOutput = wrapperStructOutput; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WrapperT::configure(const WrapperStructGui& wrapperStructGui) + { + try + { + mWrapperStructGui = wrapperStructGui; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WrapperT::exec() + { + try + { + configureThreadManager( + mThreadManager, mMultiThreadEnabled, mThreadManagerMode, mWrapperStructPose, mWrapperStructFace, + mWrapperStructHand, mWrapperStructExtra, mWrapperStructInput, mWrapperStructOutput, mWrapperStructGui, + mUserWs, mUserWsOnNewThread); + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + mThreadManager.exec(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WrapperT::start() + { + try + { + configureThreadManager( + mThreadManager, mMultiThreadEnabled, mThreadManagerMode, mWrapperStructPose, mWrapperStructFace, + mWrapperStructHand, mWrapperStructExtra, mWrapperStructInput, mWrapperStructOutput, mWrapperStructGui, + mUserWs, mUserWsOnNewThread); + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + mThreadManager.start(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void WrapperT::stop() + { + try + { + mThreadManager.stop(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + bool WrapperT::isRunning() const + { + try + { + return mThreadManager.isRunning(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + void WrapperT::setDefaultMaxSizeQueues(const long long defaultMaxSizeQueues) + { + try + { + mThreadManager.setDefaultMaxSizeQueues(defaultMaxSizeQueues); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + bool WrapperT::tryEmplace(TDatumsSP& tDatums) + { + try + { + if (!mUserWs[int(WorkerType::Input)].empty()) + error("Emplace cannot be called if an input worker was already selected.", + __LINE__, __FUNCTION__, __FILE__); + // tryEmplace for 1 camera + if (tDatums->size() < 2) + { + return mThreadManager.tryEmplace(tDatums); + } + // tryEmplace for multiview + else + { + bool successfulEmplace = true; + for (auto datumIndex = 0u; datumIndex < tDatums->size(); ++datumIndex) + { + auto tDatumsSingle = std::make_shared(TDatums({ tDatums->at(datumIndex) })); + if (!tryEmplace(tDatumsSingle)) + { + successfulEmplace = false; + break; + } + } + return successfulEmplace; + } + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool WrapperT::waitAndEmplace(TDatumsSP& tDatums) + { + try + { + if (!mUserWs[int(WorkerType::Input)].empty()) + error("Emplace cannot be called if an input worker was already selected.", + __LINE__, __FUNCTION__, __FILE__); + // waitAndEmplace for 1 camera + if (tDatums->size() < 2) + { + return mThreadManager.waitAndEmplace(tDatums); + } + // waitAndEmplace for multiview + else + { + bool successfulEmplace = true; + for (auto datumIndex = 0u ; datumIndex < tDatums->size() ; ++datumIndex) + { + auto tDatumsSingle = std::make_shared(TDatums({tDatums->at(datumIndex)})); + if (!waitAndEmplace(tDatumsSingle)) + { + successfulEmplace = false; + opLog("Waiting to emplace for multi-camera failed.", + Priority::High, __LINE__, __FUNCTION__, __FILE__); + break; + } + } + return successfulEmplace; + } + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool WrapperT::waitAndEmplace(Matrix& matrix) + { + try + { + // Create new datum + auto datumsPtr = std::make_shared>>(); + datumsPtr->emplace_back(); + auto& tDatumPtr = datumsPtr->at(0); + tDatumPtr = std::make_shared(); + // Fill datum + std::swap(tDatumPtr->cvInputData, matrix); + // Return result + return waitAndEmplace(datumsPtr); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool WrapperT::tryPush(const TDatumsSP& tDatums) + { + try + { + if (!mUserWs[int(WorkerType::Input)].empty()) + error("Push cannot be called if an input worker was already selected.", + __LINE__, __FUNCTION__, __FILE__); + return mThreadManager.tryPush(tDatums); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool WrapperT::waitAndPush(const TDatumsSP& tDatums) + { + try + { + if (!mUserWs[int(WorkerType::Input)].empty()) + error("Push cannot be called if an input worker was already selected.", + __LINE__, __FUNCTION__, __FILE__); + return mThreadManager.waitAndPush(tDatums); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool WrapperT::waitAndPush(const Matrix& matrix) + { + try + { + // Create new datum + auto datumsPtr = std::make_shared>>(); + datumsPtr->emplace_back(); + auto& tDatumPtr = datumsPtr->at(0); + tDatumPtr = std::make_shared(); + // Fill datum + tDatumPtr->cvInputData = matrix.clone(); + // Return result + return waitAndEmplace(datumsPtr); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool WrapperT::tryPop(TDatumsSP& tDatums) + { + try + { + if (!mUserWs[int(WorkerType::Output)].empty()) + error("Pop cannot be called if an output worker was already selected.", + __LINE__, __FUNCTION__, __FILE__); + return mThreadManager.tryPop(tDatums); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool WrapperT::waitAndPop(TDatumsSP& tDatums) + { + try + { + if (!mUserWs[int(WorkerType::Output)].empty()) + error("Pop cannot be called if an output worker was already selected.", + __LINE__, __FUNCTION__, __FILE__); + return mThreadManager.waitAndPop(tDatums); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + bool WrapperT::emplaceAndPop(TDatumsSP& tDatums) + { + try + { + // Run waitAndEmplace + waitAndPop + if (waitAndEmplace(tDatums)) + return waitAndPop(tDatums); + return false; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + template + TDatumsSP WrapperT::emplaceAndPop(const Matrix& matrix) + { + try + { + // Create new datum + auto datumsPtr = std::make_shared>>(); + datumsPtr->emplace_back(); + auto& tDatumPtr = datumsPtr->at(0); + tDatumPtr = std::make_shared(); + // Fill datum + tDatumPtr->cvInputData = matrix; + // Emplace and pop + emplaceAndPop(datumsPtr); + // Return result + return datumsPtr; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return TDatumsSP{}; + } + } + + extern template class WrapperT; +} + +#endif // OPENPOSE_WRAPPER_WRAPPER_HPP diff --git a/openpose/include/openpose/wrapper/wrapperAuxiliary.hpp b/openpose/include/openpose/wrapper/wrapperAuxiliary.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c2820df17ad30e8b3a535184a7cf23b356474745 --- /dev/null +++ b/openpose/include/openpose/wrapper/wrapperAuxiliary.hpp @@ -0,0 +1,1275 @@ +#ifndef OPENPOSE_WRAPPER_WRAPPER_AUXILIARY_HPP +#define OPENPOSE_WRAPPER_WRAPPER_AUXILIARY_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace op +{ + /** + * It checks that no wrong/contradictory flags are enabled for Wrapper(T) + * @param wrapperStructPose + * @param wrapperStructFace + * @param wrapperStructHand + * @param wrapperStructExtra + * @param wrapperStructInput + * @param wrapperStructOutput + * @param renderOutput + * @param userOutputWsEmpty + * @param producerSharedPtr + * @param threadManagerMode + */ + OP_API void wrapperConfigureSanityChecks( + WrapperStructPose& wrapperStructPose, const WrapperStructFace& wrapperStructFace, + const WrapperStructHand& wrapperStructHand, const WrapperStructExtra& wrapperStructExtra, + const WrapperStructInput& wrapperStructInput, const WrapperStructOutput& wrapperStructOutput, + const WrapperStructGui& wrapperStructGui, const bool renderOutput, const bool userInputAndPreprocessingWsEmpty, + const bool userOutputWsEmpty, const std::shared_ptr& producerSharedPtr, + const ThreadManagerMode threadManagerMode); + + /** + * Thread ID increase (private internal function). + * If multi-threading mode, it increases the thread ID. + * If single-threading mode (for debugging), it does not modify it. + * Note that mThreadId must be re-initialized to 0 before starting a new Wrapper(T) configuration. + * @param threadId unsigned long long element with the current thread id value. I will be edited to the next + * `desired thread id number. + */ + OP_API void threadIdPP(unsigned long long& threadId, const bool multiThreadEnabled); + + /** + * Set ThreadManager from TWorkers (private internal function). + * After any configure() has been called, the TWorkers are initialized. This function resets the ThreadManager + * and adds them. + * Common code for start() and exec(). + */ + template>, + typename TDatumsSP = std::shared_ptr, + typename TWorker = std::shared_ptr>> + void configureThreadManager( + ThreadManager& threadManager, const bool multiThreadEnabled, + const ThreadManagerMode threadManagerMode, const WrapperStructPose& wrapperStructPose, + const WrapperStructFace& wrapperStructFace, const WrapperStructHand& wrapperStructHand, + const WrapperStructExtra& wrapperStructExtra, const WrapperStructInput& wrapperStructInput, + const WrapperStructOutput& wrapperStructOutput, const WrapperStructGui& wrapperStructGui, + const std::array, int(WorkerType::Size)>& userWs, + const std::array& userWsOnNewThread); + + /** + * It fills camera parameters and splits the cvMat depending on how many camera parameter matrices are found. + * For example usage, check `examples/tutorial_api_cpp/11_asynchronous_custom_input_multi_camera.cpp` + */ + template>, + typename TDatumsSP = std::shared_ptr> + void createMultiviewTDatum( + TDatumsSP& tDatumsSP, unsigned long long& frameCounter, + const CameraParameterReader& cameraParameterReader, const void* const cvMatPtr); +} + + + + + +// Implementation +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace op +{ + template + void configureThreadManager( + ThreadManager& threadManager, const bool multiThreadEnabledTemp, + const ThreadManagerMode threadManagerMode, const WrapperStructPose& wrapperStructPoseTemp, + const WrapperStructFace& wrapperStructFace, const WrapperStructHand& wrapperStructHand, + const WrapperStructExtra& wrapperStructExtra, const WrapperStructInput& wrapperStructInput, + const WrapperStructOutput& wrapperStructOutput, const WrapperStructGui& wrapperStructGui, + const std::array, int(WorkerType::Size)>& userWs, + const std::array& userWsOnNewThread) + { + try + { + opLog("Running configureThreadManager...", Priority::Normal); + + // Create producer + auto producerSharedPtr = createProducer( + wrapperStructInput.producerType, wrapperStructInput.producerString.getStdString(), + wrapperStructInput.cameraResolution, wrapperStructInput.cameraParameterPath.getStdString(), + wrapperStructInput.undistortImage, wrapperStructInput.numberViews); + + // Editable arguments + auto wrapperStructPose = wrapperStructPoseTemp; + auto multiThreadEnabled = multiThreadEnabledTemp; + + // User custom workers + const auto& userInputWs = userWs[int(WorkerType::Input)]; + const auto& userPreProcessingWs = userWs[int(WorkerType::PreProcessing)]; + const auto& userPostProcessingWs = userWs[int(WorkerType::PostProcessing)]; + const auto& userOutputWs = userWs[int(WorkerType::Output)]; + const auto userInputWsOnNewThread = userWsOnNewThread[int(WorkerType::Input)]; + const auto userPreProcessingWsOnNewThread = userWsOnNewThread[int(WorkerType::PreProcessing)]; + const auto userPostProcessingWsOnNewThread = userWsOnNewThread[int(WorkerType::PostProcessing)]; + const auto userOutputWsOnNewThread = userWsOnNewThread[int(WorkerType::Output)]; + + // Video seek + const auto spVideoSeek = std::make_shared, std::atomic>>(); + // It cannot be directly included in the constructor (compiler error for copying std::atomic) + spVideoSeek->first = false; + spVideoSeek->second = 0; + + // Required parameters + const auto gpuMode = getGpuMode(); + const auto renderModePose = ( + wrapperStructPose.renderMode != RenderMode::Auto + ? wrapperStructPose.renderMode + : (gpuMode == GpuMode::Cuda ? RenderMode::Gpu : RenderMode::Cpu)); + const auto renderModeFace = ( + wrapperStructFace.renderMode != RenderMode::Auto + ? wrapperStructFace.renderMode + : (gpuMode == GpuMode::Cuda ? RenderMode::Gpu : RenderMode::Cpu)); + const auto renderModeHand = ( + wrapperStructHand.renderMode != RenderMode::Auto + ? wrapperStructHand.renderMode + : (gpuMode == GpuMode::Cuda ? RenderMode::Gpu : RenderMode::Cpu)); + const auto renderOutput = renderModePose != RenderMode::None + || renderModeFace != RenderMode::None + || renderModeHand != RenderMode::None; + const bool renderOutputGpu = renderModePose == RenderMode::Gpu + || (wrapperStructFace.enable && renderModeFace == RenderMode::Gpu) + || (wrapperStructHand.enable && renderModeHand == RenderMode::Gpu); + const bool renderFace = wrapperStructFace.enable && renderModeFace != RenderMode::None; + const bool renderHand = wrapperStructHand.enable && renderModeHand != RenderMode::None; + const bool renderHandGpu = wrapperStructHand.enable && renderModeHand == RenderMode::Gpu; + opLog("renderModePose = " + std::to_string(int(renderModePose)), Priority::Normal); + opLog("renderModeFace = " + std::to_string(int(renderModeFace)), Priority::Normal); + opLog("renderModeHand = " + std::to_string(int(renderModeHand)), Priority::Normal); + opLog("renderOutput = " + std::to_string(int(renderOutput)), Priority::Normal); + opLog("renderOutputGpu = " + std::to_string(int(renderOutput)), Priority::Normal); + opLog("renderFace = " + std::to_string(int(renderFace)), Priority::Normal); + opLog("renderHand = " + std::to_string(int(renderHand)), Priority::Normal); + opLog("renderHandGpu = " + std::to_string(int(renderHandGpu)), Priority::Normal); + + // Check no wrong/contradictory flags enabled + const bool userInputAndPreprocessingWsEmpty = userInputWs.empty() && userPreProcessingWs.empty(); + const bool userOutputWsEmpty = userOutputWs.empty(); + wrapperConfigureSanityChecks( + wrapperStructPose, wrapperStructFace, wrapperStructHand, wrapperStructExtra, wrapperStructInput, + wrapperStructOutput, wrapperStructGui, renderOutput, userInputAndPreprocessingWsEmpty, + userOutputWsEmpty, producerSharedPtr, threadManagerMode); + opLog("userInputAndPreprocessingWsEmpty = " + std::to_string(int(userInputAndPreprocessingWsEmpty)), + Priority::Normal); + opLog("userOutputWsEmpty = " + std::to_string(int(userOutputWsEmpty)), Priority::Normal); + + // Get number threads + auto numberGpuThreads = wrapperStructPose.gpuNumber; + auto gpuNumberStart = wrapperStructPose.gpuNumberStart; + opLog("numberGpuThreads = " + std::to_string(numberGpuThreads), Priority::Normal); + opLog("gpuNumberStart = " + std::to_string(gpuNumberStart), Priority::Normal); + // CPU --> 1 thread or no pose extraction + if (gpuMode == GpuMode::NoGpu) + { + numberGpuThreads = (wrapperStructPose.gpuNumber == 0 ? 0 : 1); + gpuNumberStart = 0; + // Disabling multi-thread makes the code 400 ms faster (2.3 sec vs. 2.7 in i7-6850K) + // and fixes the bug that the screen was not properly displayed and only refreshed sometimes + // Note: The screen bug could be also fixed by using waitKey(30) rather than waitKey(1) + multiThreadEnabled = false; + } + // GPU --> user picks (<= #GPUs) + else + { + // Get total number GPUs + const auto totalGpuNumber = getGpuNumber(); + // If number GPU < 0 --> set it to all the available GPUs + if (numberGpuThreads < 0) + { + if (totalGpuNumber <= gpuNumberStart) + error("Number of initial GPU (`--number_gpu_start`) must be lower than the total number of" + " used GPUs (`--number_gpu`)", __LINE__, __FUNCTION__, __FILE__); + numberGpuThreads = totalGpuNumber - gpuNumberStart; + // Reset initial GPU to 0 (we want them all) + // Logging message + opLog("Auto-detecting all available GPUs... Detected " + std::to_string(totalGpuNumber) + + " GPU(s), using " + std::to_string(numberGpuThreads) + " of them starting at GPU " + + std::to_string(gpuNumberStart) + ".", Priority::High); + } + // Sanity check + if (gpuNumberStart + numberGpuThreads > totalGpuNumber) + error("Initial GPU selected (`--number_gpu_start`) + number GPUs to use (`--number_gpu`) must" + " be lower or equal than the total number of GPUs in your machine (" + + std::to_string(gpuNumberStart) + " + " + + std::to_string(numberGpuThreads) + " vs. " + + std::to_string(totalGpuNumber) + ").", + __LINE__, __FUNCTION__, __FILE__); + } + + // Proper format + const auto writeImagesCleaned = formatAsDirectory(wrapperStructOutput.writeImages.getStdString()); + const auto writeKeypointCleaned = formatAsDirectory(wrapperStructOutput.writeKeypoint.getStdString()); + const auto writeJsonCleaned = formatAsDirectory(wrapperStructOutput.writeJson.getStdString()); + const auto writeHeatMapsCleaned = formatAsDirectory(wrapperStructOutput.writeHeatMaps.getStdString()); + const auto modelFolder = formatAsDirectory(wrapperStructPose.modelFolder.getStdString()); + opLog("writeImagesCleaned = " + writeImagesCleaned, Priority::Normal); + opLog("writeKeypointCleaned = " + writeKeypointCleaned, Priority::Normal); + opLog("writeJsonCleaned = " + writeJsonCleaned, Priority::Normal); + opLog("writeHeatMapsCleaned = " + writeHeatMapsCleaned, Priority::Normal); + opLog("modelFolder = " + modelFolder, Priority::Normal); + + // Common parameters + auto finalOutputSize = wrapperStructPose.outputSize; + Point producerSize{-1,-1}; + const auto oPProducer = (producerSharedPtr != nullptr); + if (oPProducer) + { + // 1. Set producer properties + const auto displayProducerFpsMode = (wrapperStructInput.realTimeProcessing + ? ProducerFpsMode::OriginalFps : ProducerFpsMode::RetrievalFps); + producerSharedPtr->setProducerFpsMode(displayProducerFpsMode); + producerSharedPtr->set(ProducerProperty::Flip, wrapperStructInput.frameFlip); + producerSharedPtr->set(ProducerProperty::Rotation, wrapperStructInput.frameRotate); + producerSharedPtr->set(ProducerProperty::AutoRepeat, wrapperStructInput.framesRepeat); + // 2. Set finalOutputSize + producerSize = Point{(int)producerSharedPtr->get(getCvCapPropFrameWidth()), + (int)producerSharedPtr->get(getCvCapPropFrameHeight())}; + // Set finalOutputSize to input size if desired + if (finalOutputSize.x == -1 || finalOutputSize.y == -1) + finalOutputSize = producerSize; + } + opLog("finalOutputSize = [" + std::to_string(finalOutputSize.x) + "," + std::to_string(finalOutputSize.y) + + "]", Priority::Normal); + + // Producer + TWorker datumProducerW; + if (oPProducer) + { + const auto datumProducer = std::make_shared>( + producerSharedPtr, wrapperStructInput.frameFirst, wrapperStructInput.frameStep, + wrapperStructInput.frameLast, spVideoSeek + ); + datumProducerW = std::make_shared>(datumProducer); + } + else + datumProducerW = nullptr; + + std::vector> poseExtractorNets; + std::vector> faceExtractorNets; + std::vector> handExtractorNets; + std::vector> poseGpuRenderers; + // CUDA vs. CPU resize + std::vector> cvMatToOpOutputs; + std::vector> opOutputToCvMats; + std::shared_ptr poseCpuRenderer; + // Workers + TWorker scaleAndSizeExtractorW; + TWorker cvMatToOpInputW; + TWorker cvMatToOpOutputW; + bool addCvMatToOpOutput = renderOutput; + bool addCvMatToOpOutputInCpu = addCvMatToOpOutput; + std::vector> poseExtractorsWs; + std::vector> poseTriangulationsWs; + std::vector> jointAngleEstimationsWs; + std::vector postProcessingWs; + if (numberGpuThreads > 0) + { + // Get input scales and sizes + const auto scaleAndSizeExtractor = std::make_shared( + wrapperStructPose.netInputSize, (float)wrapperStructPose.netInputSizeDynamicBehavior, finalOutputSize, + wrapperStructPose.scalesNumber, wrapperStructPose.scaleGap); + scaleAndSizeExtractorW = std::make_shared>(scaleAndSizeExtractor); + + // Input cvMat to OpenPose input & output format + // Note: resize on GPU reduces accuracy about 0.1% + bool resizeOnCpu = true; + // const auto resizeOnCpu = (wrapperStructPose.poseMode != PoseMode::Enabled); + if (resizeOnCpu) + { + const auto gpuResize = false; + const auto cvMatToOpInput = std::make_shared( + wrapperStructPose.poseModel, gpuResize); + cvMatToOpInputW = std::make_shared>(cvMatToOpInput); + } + // Note: We realized that somehow doing it on GPU for any number of GPUs does speedup the whole OP + resizeOnCpu = false; + addCvMatToOpOutputInCpu = addCvMatToOpOutput + && (resizeOnCpu || !renderOutputGpu || wrapperStructPose.poseMode != PoseMode::Enabled + // Resize in GPU causing bug + || wrapperStructPose.outputSize.x != -1 || wrapperStructPose.outputSize.y != -1); + if (addCvMatToOpOutputInCpu) + { + const auto gpuResize = false; + const auto cvMatToOpOutput = std::make_shared(gpuResize); + cvMatToOpOutputW = std::make_shared>(cvMatToOpOutput); + } + + // Pose estimators & renderers + std::vector cpuRenderers; + poseExtractorsWs.clear(); + poseExtractorsWs.resize(numberGpuThreads); + if (wrapperStructPose.poseMode != PoseMode::Disabled) + { + // Pose estimators + for (auto gpuId = 0; gpuId < numberGpuThreads; gpuId++) + poseExtractorNets.emplace_back(std::make_shared( + wrapperStructPose.poseModel, modelFolder, gpuId + gpuNumberStart, + wrapperStructPose.heatMapTypes, wrapperStructPose.heatMapScaleMode, + wrapperStructPose.addPartCandidates, wrapperStructPose.maximizePositives, + wrapperStructPose.protoTxtPath.getStdString(), + wrapperStructPose.caffeModelPath.getStdString(), + wrapperStructPose.upsamplingRatio, wrapperStructPose.poseMode == PoseMode::Enabled, + wrapperStructPose.enableGoogleLogging + )); + + // Pose renderers + if (renderOutputGpu || renderModePose == RenderMode::Cpu) + { + // If renderModePose != RenderMode::Gpu but renderOutput, then we create an + // alpha = 0 pose renderer in order to keep the removing background option + const auto alphaKeypoint = (renderModePose != RenderMode::None + ? wrapperStructPose.alphaKeypoint : 0.f); + const auto alphaHeatMap = (renderModePose != RenderMode::None + ? wrapperStructPose.alphaHeatMap : 0.f); + // GPU rendering + if (renderOutputGpu) + { + for (const auto& poseExtractorNet : poseExtractorNets) + { + poseGpuRenderers.emplace_back(std::make_shared( + wrapperStructPose.poseModel, poseExtractorNet, wrapperStructPose.renderThreshold, + wrapperStructPose.blendOriginalFrame, alphaKeypoint, + alphaHeatMap, wrapperStructPose.defaultPartToRender + )); + } + } + // CPU rendering + if (renderModePose == RenderMode::Cpu) + { + poseCpuRenderer = std::make_shared( + wrapperStructPose.poseModel, wrapperStructPose.renderThreshold, + wrapperStructPose.blendOriginalFrame, alphaKeypoint, alphaHeatMap, + wrapperStructPose.defaultPartToRender); + cpuRenderers.emplace_back(std::make_shared>(poseCpuRenderer)); + } + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + + // Pose extractor(s) + poseExtractorsWs.resize(poseExtractorNets.size()); + const auto personIdExtractor = (wrapperStructExtra.identification + ? std::make_shared() : nullptr); + // Keep top N people + // Added right after PoseExtractorNet to avoid: + // 1) Rendering people that are later deleted (wrong visualization). + // 2) Processing faces and hands on people that will be deleted (speed up). + // 3) Running tracking before deleting the people. + // Add KeepTopNPeople for each PoseExtractorNet + const auto keepTopNPeople = (wrapperStructPose.numberPeopleMax > 0 ? + std::make_shared(wrapperStructPose.numberPeopleMax) + : nullptr); + // Person tracker + auto personTrackers = std::make_shared>>(); + if (wrapperStructExtra.tracking > -1) + personTrackers->emplace_back( + std::make_shared(wrapperStructExtra.tracking == 0)); + for (auto i = 0u; i < poseExtractorsWs.size(); i++) + { + // OpenPose keypoint detector + keepTopNPeople + // + ID extractor (experimental) + tracking (experimental) + const auto poseExtractor = std::make_shared( + poseExtractorNets.at(i), keepTopNPeople, personIdExtractor, personTrackers, + wrapperStructPose.numberPeopleMax, wrapperStructExtra.tracking); + // If we want the initial image resize on GPU + if (cvMatToOpInputW == nullptr) + { + const auto gpuResize = true; + const auto cvMatToOpInput = std::make_shared( + wrapperStructPose.poseModel, gpuResize); + poseExtractorsWs.at(i).emplace_back( + std::make_shared>(cvMatToOpInput)); + } + // If we want the final image resize on GPU + if (addCvMatToOpOutput && cvMatToOpOutputW == nullptr) + { + const auto gpuResize = true; + cvMatToOpOutputs.emplace_back(std::make_shared(gpuResize)); + poseExtractorsWs.at(i).emplace_back( + std::make_shared>(cvMatToOpOutputs.back())); + } + poseExtractorsWs.at(i).emplace_back( + std::make_shared>(poseExtractor)); + // poseExtractorsWs.at(i) = {std::make_shared>(poseExtractor)}; + // // Just OpenPose keypoint detector + // poseExtractorsWs.at(i) = {std::make_shared>( + // poseExtractorNets.at(i))}; + } + + // // (Before tracking / id extractor) + // // Added right after PoseExtractorNet to avoid: + // // 1) Rendering people that are later deleted (wrong visualization). + // // 2) Processing faces and hands on people that will be deleted (speed up). + // if (wrapperStructPose.numberPeopleMax > 0) + // { + // // Add KeepTopNPeople for each PoseExtractorNet + // const auto keepTopNPeople = std::make_shared( + // wrapperStructPose.numberPeopleMax); + // for (auto& wPose : poseExtractorsWs) + // wPose.emplace_back(std::make_shared>(keepTopNPeople)); + // } + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + + // Pose renderer(s) + if (!poseGpuRenderers.empty()) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + for (auto i = 0u; i < poseExtractorsWs.size(); i++) + { + poseExtractorsWs.at(i).emplace_back(std::make_shared>( + poseGpuRenderers.at(i))); + // Get shared params + if (!cvMatToOpOutputs.empty()) + poseGpuRenderers.at(i)->setSharedParameters( + cvMatToOpOutputs.at(i)->getSharedParameters()); + } + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + + // Face extractor(s) + if (wrapperStructFace.enable) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Face detector + // OpenPose body-based face detector + if (wrapperStructFace.detector == Detector::Body) + { + // Sanity check + if (wrapperStructPose.poseMode == PoseMode::Disabled) + error("Body keypoint detection is disabled but face Detector is set to Body. Either" + " re-enable OpenPose body or select a different face Detector (`--face_detector`).", + __LINE__, __FUNCTION__, __FILE__); + // Constructors + const auto faceDetector = std::make_shared(wrapperStructPose.poseModel); + for (auto& wPose : poseExtractorsWs) + wPose.emplace_back(std::make_shared>(faceDetector)); + } + // OpenCV face detector + else if (wrapperStructFace.detector == Detector::OpenCV) + { + opLog("Body keypoint detection is disabled. Hence, using OpenCV face detector (much less" + " accurate but faster).", Priority::High); + for (auto& wPose : poseExtractorsWs) + { + // 1 FaceDetectorOpenCV per thread, OpenCV face detector is not thread-safe + const auto faceDetectorOpenCV = std::make_shared(modelFolder); + wPose.emplace_back( + std::make_shared>(faceDetectorOpenCV) + ); + } + } + // If provided by user: We do not need to create a FaceDetector + // Unknown face Detector + else if (wrapperStructFace.detector != Detector::Provided) + error("Unknown face Detector. Select a valid face Detector (`--face_detector`).", + __LINE__, __FUNCTION__, __FILE__); + // Face keypoint extractor + for (auto gpu = 0u; gpu < poseExtractorsWs.size(); gpu++) + { + // Face keypoint extractor + const auto netOutputSize = wrapperStructFace.netInputSize; + const auto faceExtractorNet = std::make_shared( + wrapperStructFace.netInputSize, netOutputSize, modelFolder, + gpu + gpuNumberStart, wrapperStructPose.heatMapTypes, wrapperStructPose.heatMapScaleMode, + wrapperStructPose.enableGoogleLogging + ); + faceExtractorNets.emplace_back(faceExtractorNet); + poseExtractorsWs.at(gpu).emplace_back( + std::make_shared>(faceExtractorNet)); + } + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + + // Hand extractor(s) + if (wrapperStructHand.enable) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + const auto handDetector = std::make_shared(wrapperStructPose.poseModel); + for (auto gpu = 0u; gpu < poseExtractorsWs.size(); gpu++) + { + // Sanity check + if ((wrapperStructHand.detector == Detector::BodyWithTracking + || wrapperStructHand.detector == Detector::Body) + && wrapperStructPose.poseMode == PoseMode::Disabled) + error("Body keypoint detection is disabled but hand Detector is set to Body. Either" + " re-enable OpenPose body or select a different hand Detector (`--hand_detector`).", + __LINE__, __FUNCTION__, __FILE__); + // Hand detector + // OpenPose body-based hand detector with tracking + if (wrapperStructHand.detector == Detector::BodyWithTracking) + { + poseExtractorsWs.at(gpu).emplace_back( + std::make_shared>(handDetector)); + } + // OpenPose body-based hand detector + else if (wrapperStructHand.detector == Detector::Body) + { + poseExtractorsWs.at(gpu).emplace_back( + std::make_shared>(handDetector)); + } + // If provided by user: We do not need to create a FaceDetector + // Unknown hand Detector + else if (wrapperStructHand.detector != Detector::Provided) + error("Unknown hand Detector. Select a valid hand Detector (`--hand_detector`).", + __LINE__, __FUNCTION__, __FILE__); + // Hand keypoint extractor + const auto netOutputSize = wrapperStructHand.netInputSize; + const auto handExtractorNet = std::make_shared( + wrapperStructHand.netInputSize, netOutputSize, modelFolder, + gpu + gpuNumberStart, wrapperStructHand.scalesNumber, wrapperStructHand.scaleRange, + wrapperStructPose.heatMapTypes, wrapperStructPose.heatMapScaleMode, + wrapperStructPose.enableGoogleLogging + ); + handExtractorNets.emplace_back(handExtractorNet); + poseExtractorsWs.at(gpu).emplace_back( + std::make_shared>(handExtractorNet) + ); + // If OpenPose body-based hand detector with tracking + if (wrapperStructHand.detector == Detector::BodyWithTracking) + poseExtractorsWs.at(gpu).emplace_back( + std::make_shared>(handDetector)); + } + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + + // Face renderer(s) + if (renderFace) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // CPU rendering + if (renderModeFace == RenderMode::Cpu) + { + // Construct face renderer + const auto faceRenderer = std::make_shared( + wrapperStructFace.renderThreshold, wrapperStructFace.alphaKeypoint, + wrapperStructFace.alphaHeatMap); + // Add worker + cpuRenderers.emplace_back(std::make_shared>(faceRenderer)); + } + // GPU rendering + else if (renderModeFace == RenderMode::Gpu) + { + for (auto i = 0u; i < poseExtractorsWs.size(); i++) + { + // Construct face renderer + const auto faceRenderer = std::make_shared( + wrapperStructFace.renderThreshold, wrapperStructFace.alphaKeypoint, + wrapperStructFace.alphaHeatMap + ); + // Performance boost -> share spGpuMemory for all renderers + if (!poseGpuRenderers.empty()) + { + // const bool isLastRenderer = !renderHandGpu; + const bool isLastRenderer = !renderHandGpu && !(addCvMatToOpOutput && !addCvMatToOpOutputInCpu); + const auto renderer = std::static_pointer_cast( + poseGpuRenderers.at(i)); + faceRenderer->setSharedParametersAndIfLast( + renderer->getSharedParameters(), isLastRenderer); + } + // Add worker + poseExtractorsWs.at(i).emplace_back( + std::make_shared>(faceRenderer)); + } + } + else + error("Unknown RenderMode.", __LINE__, __FUNCTION__, __FILE__); + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + + // Hand renderer(s) + if (renderHand) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // CPU rendering + if (renderModeHand == RenderMode::Cpu) + { + // Construct hand renderer + const auto handRenderer = std::make_shared( + wrapperStructHand.renderThreshold, wrapperStructHand.alphaKeypoint, + wrapperStructHand.alphaHeatMap); + // Add worker + cpuRenderers.emplace_back(std::make_shared>(handRenderer)); + } + // GPU rendering + else if (renderModeHand == RenderMode::Gpu) + { + for (auto i = 0u; i < poseExtractorsWs.size(); i++) + { + // Construct hands renderer + const auto handRenderer = std::make_shared( + wrapperStructHand.renderThreshold, wrapperStructHand.alphaKeypoint, + wrapperStructHand.alphaHeatMap + ); + // Performance boost -> share spGpuMemory for all renderers + if (!poseGpuRenderers.empty()) + { + // const bool isLastRenderer = true; + const bool isLastRenderer = !(addCvMatToOpOutput && !addCvMatToOpOutputInCpu); + const auto renderer = std::static_pointer_cast( + poseGpuRenderers.at(i)); + handRenderer->setSharedParametersAndIfLast( + renderer->getSharedParameters(), isLastRenderer); + } + // Add worker + poseExtractorsWs.at(i).emplace_back( + std::make_shared>(handRenderer)); + } + } + else + error("Unknown RenderMode.", __LINE__, __FUNCTION__, __FILE__); + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + + // Frames processor (OpenPose format -> cv::Mat format) + if (addCvMatToOpOutput && !addCvMatToOpOutputInCpu) + { + // for (auto& poseExtractorsW : poseExtractorsWs) + for (auto i = 0u ; i < poseExtractorsWs.size() ; ++i) + { + const auto gpuResize = true; + opOutputToCvMats.emplace_back(std::make_shared(gpuResize)); + poseExtractorsWs.at(i).emplace_back( + std::make_shared>(opOutputToCvMats.back())); + // Assign shared parameters + opOutputToCvMats.back()->setSharedParameters( + cvMatToOpOutputs.at(i)->getSharedParameters()); + } + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + + // 3-D reconstruction + poseTriangulationsWs.clear(); + if (wrapperStructExtra.reconstruct3d) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // For all (body/face/hands): PoseTriangulations ~30 msec, 8 GPUS ~30 msec for keypoint estimation + poseTriangulationsWs.resize(fastMax(1, int(poseExtractorsWs.size() / 4))); + for (auto i = 0u ; i < poseTriangulationsWs.size() ; i++) + { + const auto poseTriangulation = std::make_shared( + wrapperStructExtra.minViews3d); + poseTriangulationsWs.at(i) = {std::make_shared>( + poseTriangulation)}; + } + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Itermediate workers (e.g., OpenPose format to cv::Mat, json & frames recorder, ...) + postProcessingWs.clear(); + // // Person ID identification (when no multi-thread and no dependency on tracking) + // if (wrapperStructExtra.identification) + // { + // const auto personIdExtractor = std::make_shared(); + // postProcessingWs.emplace_back( + // std::make_shared>(personIdExtractor) + // ); + // } + // Frames processor (OpenPose format -> cv::Mat format) + if (addCvMatToOpOutputInCpu) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + postProcessingWs = mergeVectors(postProcessingWs, cpuRenderers); + const auto opOutputToCvMat = std::make_shared(); + postProcessingWs.emplace_back(std::make_shared>(opOutputToCvMat)); + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Re-scale pose if desired + // If desired scale is not the current input + if (wrapperStructPose.keypointScaleMode != ScaleMode::InputResolution + // and desired scale is not output when size(input) = size(output) + && !(wrapperStructPose.keypointScaleMode == ScaleMode::OutputResolution && + (finalOutputSize == producerSize || finalOutputSize.x <= 0 || finalOutputSize.y <= 0)) + // and desired scale is not net output when size(input) = size(net output) + && !(wrapperStructPose.keypointScaleMode == ScaleMode::NetOutputResolution + && producerSize == wrapperStructPose.netInputSize)) + { + // Then we must rescale the keypoints + auto keypointScaler = std::make_shared(wrapperStructPose.keypointScaleMode); + postProcessingWs.emplace_back(std::make_shared>(keypointScaler)); + } + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + + // IK/Adam + const auto displayAdam = wrapperStructGui.displayMode == DisplayMode::DisplayAdam + || (wrapperStructGui.displayMode == DisplayMode::DisplayAll + && wrapperStructExtra.ikThreads > 0); + jointAngleEstimationsWs.clear(); +#ifdef USE_3D_ADAM_MODEL + if (wrapperStructExtra.ikThreads > 0) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + jointAngleEstimationsWs.resize(wrapperStructExtra.ikThreads); + // Pose extractor(s) + for (auto i = 0u; i < jointAngleEstimationsWs.size(); i++) + { + const auto jointAngleEstimation = std::make_shared(displayAdam); + jointAngleEstimationsWs.at(i) = {std::make_shared>( + jointAngleEstimation)}; + } + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); +#endif + + // Output workers + std::vector outputWs; + // Print verbose + if (wrapperStructOutput.verbose > 0.) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + const auto verbosePrinter = std::make_shared( + wrapperStructOutput.verbose, uLongLongRound(producerSharedPtr->get(getCvCapPropFrameCount()))); + outputWs.emplace_back(std::make_shared>(verbosePrinter)); + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Send information (e.g., to Unity) though UDP client-server communication + +#ifdef USE_3D_ADAM_MODEL + if (!wrapperStructOutput.udpHost.empty() && !wrapperStructOutput.udpPort.empty()) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + const auto udpSender = std::make_shared(wrapperStructOutput.udpHost, + wrapperStructOutput.udpPort); + outputWs.emplace_back(std::make_shared>(udpSender)); + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); +#endif + // Write people pose data on disk (json for OpenCV >= 3, xml, yml...) + if (!writeKeypointCleaned.empty()) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + const auto keypointSaver = std::make_shared(writeKeypointCleaned, + wrapperStructOutput.writeKeypointFormat); + outputWs.emplace_back(std::make_shared>(keypointSaver)); + if (wrapperStructFace.enable) + outputWs.emplace_back(std::make_shared>(keypointSaver)); + if (wrapperStructHand.enable) + outputWs.emplace_back(std::make_shared>(keypointSaver)); + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Write OpenPose output data on disk in JSON format (body/hand/face keypoints, body part locations if + // enabled, etc.) + if (!writeJsonCleaned.empty()) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + const auto peopleJsonSaver = std::make_shared(writeJsonCleaned); + outputWs.emplace_back(std::make_shared>(peopleJsonSaver)); + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Write people pose/foot/face/hand/etc. data on disk (COCO validation JSON format) + if (!wrapperStructOutput.writeCocoJson.empty()) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // If humanFormat: bigger size (& maybe slower to process), but easier for user to read it + const auto humanFormat = true; + const auto cocoJsonSaver = std::make_shared( + wrapperStructOutput.writeCocoJson.getStdString(), wrapperStructPose.poseModel, humanFormat, + wrapperStructOutput.writeCocoJsonVariants, + (wrapperStructPose.poseModel != PoseModel::CAR_22 + && wrapperStructPose.poseModel != PoseModel::CAR_12 + ? CocoJsonFormat::Body : CocoJsonFormat::Car), + wrapperStructOutput.writeCocoJsonVariant); + outputWs.emplace_back(std::make_shared>(cocoJsonSaver)); + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Write frames as desired image format on hard disk + if (!writeImagesCleaned.empty()) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + const auto imageSaver = std::make_shared( + writeImagesCleaned, wrapperStructOutput.writeImagesFormat.getStdString()); + outputWs.emplace_back(std::make_shared>(imageSaver)); + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + auto originalVideoFps = 0.; + if (!wrapperStructOutput.writeVideo.empty() || !wrapperStructOutput.writeVideo3D.empty() + || !wrapperStructOutput.writeBvh.empty()) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + if (wrapperStructOutput.writeVideoFps <= 0 + && (!oPProducer || producerSharedPtr->get(getCvCapPropFrameFps()) <= 0)) + error("The frame rate of the frames producer is unknown. Set `--write_video_fps` to your desired" + " FPS if you wanna record video (`--write_video`). E.g., if it is a folder of images, you" + " will have to know or guess the frame rate; if it is a webcam, you should use the OpenPose" + " displayed FPS as desired value. If you do not care, simply add `--write_video_fps 30`.", + __LINE__, __FUNCTION__, __FILE__); + originalVideoFps = ( + wrapperStructOutput.writeVideoFps > 0 ? + wrapperStructOutput.writeVideoFps : producerSharedPtr->get(getCvCapPropFrameFps())); + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Write frames as *.avi video on hard disk + if (!wrapperStructOutput.writeVideo.empty()) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Sanity checks + if (!oPProducer) + error("Video file can only be recorded inside `wrapper/wrapper.hpp` if the producer" + " is one of the default ones (e.g., video, webcam, ...).", + __LINE__, __FUNCTION__, __FILE__); + if (wrapperStructOutput.writeVideoWithAudio && producerSharedPtr->getType() != ProducerType::Video) + error("Audio can only be added to the output saved video if the input is also a video (either" + " disable `--write_video_with_audio` or use a video as input with `--video`).", + __LINE__, __FUNCTION__, __FILE__); + // Create video saver worker + const auto videoSaver = std::make_shared( + wrapperStructOutput.writeVideo.getStdString(), getCvFourcc('M','J','P','G'), originalVideoFps, + (wrapperStructOutput.writeVideoWithAudio ? wrapperStructInput.producerString.getStdString() : "")); + outputWs.emplace_back(std::make_shared>(videoSaver)); + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Write joint angles as *.bvh file on hard disk +#ifdef USE_3D_ADAM_MODEL + if (!wrapperStructOutput.writeBvh.empty()) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + const auto bvhSaver = std::make_shared( + wrapperStructOutput.writeBvh, JointAngleEstimation::getTotalModel(), originalVideoFps + ); + outputWs.emplace_back(std::make_shared>(bvhSaver)); + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); +#endif + // Write heat maps as desired image format on hard disk + if (!writeHeatMapsCleaned.empty()) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + const auto heatMapSaver = std::make_shared( + writeHeatMapsCleaned, wrapperStructOutput.writeHeatMapsFormat.getStdString()); + outputWs.emplace_back(std::make_shared>(heatMapSaver)); + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Add frame information for GUI + const bool guiEnabled = (wrapperStructGui.displayMode != DisplayMode::NoDisplay); + // If this WGuiInfoAdder instance is placed before the WImageSaver or WVideoSaver, then the resulting + // recorded frames will look exactly as the final displayed image by the GUI + if (wrapperStructGui.guiVerbose && (guiEnabled || !userOutputWs.empty() + || threadManagerMode == ThreadManagerMode::Asynchronous + || threadManagerMode == ThreadManagerMode::AsynchronousOut)) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + const auto guiInfoAdder = std::make_shared(numberGpuThreads, guiEnabled); + outputWs.emplace_back(std::make_shared>(guiInfoAdder)); + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Minimal graphical user interface (GUI) + TWorker guiW; + TWorker videoSaver3DW; + if (guiEnabled) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // PoseRenderers to Renderers + std::vector> renderers; + if (renderModePose == RenderMode::Cpu) + renderers.emplace_back(std::static_pointer_cast(poseCpuRenderer)); + else + for (const auto& poseGpuRenderer : poseGpuRenderers) + renderers.emplace_back(std::static_pointer_cast(poseGpuRenderer)); + // Display + const auto numberViews = (producerSharedPtr != nullptr + ? positiveIntRound(producerSharedPtr->get(ProducerProperty::NumberViews)) : 1); + auto finalOutputSizeGui = finalOutputSize; + if (numberViews > 1 && finalOutputSizeGui.x > 0) + finalOutputSizeGui.x *= numberViews; + // Adam (+3-D/2-D) display + if (displayAdam) + { +#ifdef USE_3D_ADAM_MODEL + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Gui + const auto gui = std::make_shared( + finalOutputSizeGui, wrapperStructGui.fullScreen, threadManager.getIsRunningSharedPtr(), + spVideoSeek, poseExtractorNets, faceExtractorNets, handExtractorNets, renderers, + wrapperStructGui.displayMode, JointAngleEstimation::getTotalModel(), + wrapperStructOutput.writeVideoAdam + ); + // WGui + guiW = {std::make_shared>(gui)}; + // Write 3D frames as *.avi video on hard disk + if (!wrapperStructOutput.writeVideo3D.empty()) + error("3D video can only be recorded if 3D render is enabled.", + __LINE__, __FUNCTION__, __FILE__); +#endif + } + // 3-D (+2-D) display + else if (wrapperStructGui.displayMode == DisplayMode::Display3D + || wrapperStructGui.displayMode == DisplayMode::DisplayAll) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Gui + const auto gui = std::make_shared( + finalOutputSizeGui, wrapperStructGui.fullScreen, threadManager.getIsRunningSharedPtr(), + spVideoSeek, poseExtractorNets, faceExtractorNets, handExtractorNets, renderers, + wrapperStructPose.poseModel, wrapperStructGui.displayMode, + !wrapperStructOutput.writeVideo3D.empty() + ); + // WGui + guiW = {std::make_shared>(gui)}; + // Write 3D frames as *.avi video on hard disk + if (!wrapperStructOutput.writeVideo3D.empty()) + { + const auto videoSaver = std::make_shared( + wrapperStructOutput.writeVideo3D.getStdString(), getCvFourcc('M','J','P','G'), originalVideoFps, ""); + videoSaver3DW = std::make_shared>(videoSaver); + } + } + // 2-D display + else if (wrapperStructGui.displayMode == DisplayMode::Display2D) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Gui + const auto gui = std::make_shared( + finalOutputSizeGui, wrapperStructGui.fullScreen, threadManager.getIsRunningSharedPtr(), + spVideoSeek, poseExtractorNets, faceExtractorNets, handExtractorNets, renderers + ); + // WGui + guiW = {std::make_shared>(gui)}; + // Write 3D frames as *.avi video on hard disk + if (!wrapperStructOutput.writeVideo3D.empty()) + error("3D video can only be recorded if 3D render is enabled.", + __LINE__, __FUNCTION__, __FILE__); + } + else + error("Unknown DisplayMode.", __LINE__, __FUNCTION__, __FILE__); + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Set FpsMax + TWorker wFpsMax; + if (wrapperStructPose.fpsMax > 0.) + wFpsMax = std::make_shared>(wrapperStructPose.fpsMax); + // Set wrapper as configured + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + + + + + + // The less number of queues -> the less threads opened, and potentially the less lag + + // Sanity checks + if ((datumProducerW == nullptr) == (userInputWs.empty()) + && threadManagerMode != ThreadManagerMode::Asynchronous + && threadManagerMode != ThreadManagerMode::AsynchronousIn) + { + const auto message = "You need to have 1 and only 1 producer selected. You can introduce your own" + " producer by using setWorker(WorkerType::Input, ...) or use the OpenPose" + " default producer by configuring it in the configure function) or use the" + " ThreadManagerMode::Asynchronous(In) mode."; + error(message, __LINE__, __FUNCTION__, __FILE__); + } + if (outputWs.empty() && userOutputWs.empty() && guiW == nullptr + && threadManagerMode != ThreadManagerMode::Asynchronous + && threadManagerMode != ThreadManagerMode::AsynchronousOut) + { + error("No output selected.", __LINE__, __FUNCTION__, __FILE__); + } + + // Thread Manager + // Clean previous thread manager (avoid configure to crash the program if used more than once) + threadManager.reset(); + unsigned long long threadId = 0ull; + auto queueIn = 0ull; + auto queueOut = 1ull; + // After producer + // ID generator (before any multi-threading or any function that requires the ID) + const auto wIdGenerator = std::make_shared>(); + // If custom user Worker and uses its own thread + std::vector workersAux; + if (!userPreProcessingWs.empty()) + { + // If custom user Worker in its own thread + if (userPreProcessingWsOnNewThread) + opLog("You chose to add your pre-processing function in a new thread. However, OpenPose will" + " add it in the same thread than the input frame producer.", + Priority::High, __LINE__, __FUNCTION__, __FILE__); + workersAux = mergeVectors(workersAux, {userPreProcessingWs}); + } + workersAux = mergeVectors(workersAux, {wIdGenerator}); + // Scale & cv::Mat to OP format + if (scaleAndSizeExtractorW != nullptr) + workersAux = mergeVectors(workersAux, {scaleAndSizeExtractorW}); + if (cvMatToOpInputW != nullptr) + workersAux = mergeVectors(workersAux, {cvMatToOpInputW}); + // cv::Mat to output format + if (cvMatToOpOutputW != nullptr) + workersAux = mergeVectors(workersAux, {cvMatToOpOutputW}); + + // Producer + // If custom user Worker and uses its own thread + if (!userInputWs.empty() && userInputWsOnNewThread) + { + // Thread 0, queues 0 -> 1 + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + threadManager.add(threadId, userInputWs, queueIn++, queueOut++); + threadIdPP(threadId, multiThreadEnabled); + } + // If custom user Worker in same thread + else if (!userInputWs.empty()) + workersAux = mergeVectors(userInputWs, workersAux); + // If OpenPose producer (same thread) + else if (datumProducerW != nullptr) + workersAux = mergeVectors({datumProducerW}, workersAux); + // Otherwise + else if (threadManagerMode != ThreadManagerMode::Asynchronous + && threadManagerMode != ThreadManagerMode::AsynchronousIn) + error("No input selected.", __LINE__, __FUNCTION__, __FILE__); + // Thread 0 or 1, queues 0 -> 1 + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + threadManager.add(threadId, workersAux, queueIn++, queueOut++); + // Increase thread + threadIdPP(threadId, multiThreadEnabled); + + // Pose estimation & rendering + // Thread 1 or 2...X, queues 1 -> 2, X = 2 + #GPUs + if (!poseExtractorsWs.empty()) + { + if (multiThreadEnabled) + { + for (auto& wPose : poseExtractorsWs) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + threadManager.add(threadId, wPose, queueIn, queueOut); + threadIdPP(threadId, multiThreadEnabled); + } + queueIn++; + queueOut++; + // Sort frames - Required own thread + if (poseExtractorsWs.size() > 1u) + { + const auto wQueueOrderer = std::make_shared>(); + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + threadManager.add(threadId, wQueueOrderer, queueIn++, queueOut++); + threadIdPP(threadId, multiThreadEnabled); + } + } + else + { + if (poseExtractorsWs.size() > 1) + opLog("Multi-threading disabled, only 1 thread running. All GPUs have been disabled but the" + " first one, which is defined by gpuNumberStart (e.g., in the OpenPose demo, it is set" + " with the `--num_gpu_start` flag).", Priority::High); + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + threadManager.add(threadId, poseExtractorsWs.at(0), queueIn++, queueOut++); + } + } + // Assemble all frames from same time instant (3-D module) + const auto wQueueAssembler = std::make_shared>(); + // 3-D reconstruction + if (!poseTriangulationsWs.empty()) + { + // Assemble frames + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + threadManager.add(threadId, wQueueAssembler, queueIn++, queueOut++); + threadIdPP(threadId, multiThreadEnabled); + // 3-D reconstruction + if (multiThreadEnabled) + { + for (auto& wPoseTriangulations : poseTriangulationsWs) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + threadManager.add(threadId, wPoseTriangulations, queueIn, queueOut); + threadIdPP(threadId, multiThreadEnabled); + } + queueIn++; + queueOut++; + // Sort frames + if (poseTriangulationsWs.size() > 1u) + { + const auto wQueueOrderer = std::make_shared>(); + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + threadManager.add(threadId, wQueueOrderer, queueIn++, queueOut++); + threadIdPP(threadId, multiThreadEnabled); + } + } + else + { + if (poseTriangulationsWs.size() > 1) + opLog("Multi-threading disabled, only 1 thread running for 3-D triangulation.", + Priority::High); + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + threadManager.add(threadId, poseTriangulationsWs.at(0), queueIn++, queueOut++); + } + } + else + postProcessingWs = mergeVectors({wQueueAssembler}, postProcessingWs); + // Adam/IK step + if (!jointAngleEstimationsWs.empty()) + { + if (multiThreadEnabled) + { + for (auto& wJointAngleEstimator : jointAngleEstimationsWs) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + threadManager.add(threadId, wJointAngleEstimator, queueIn, queueOut); + threadIdPP(threadId, multiThreadEnabled); + } + queueIn++; + queueOut++; + // Sort frames + if (jointAngleEstimationsWs.size() > 1) + { + const auto wQueueOrderer = std::make_shared>(); + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + threadManager.add(threadId, wQueueOrderer, queueIn++, queueOut++); + threadIdPP(threadId, multiThreadEnabled); + } + } + else + { + if (jointAngleEstimationsWs.size() > 1) + opLog("Multi-threading disabled, only 1 thread running for joint angle estimation.", + Priority::High); + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + threadManager.add(threadId, jointAngleEstimationsWs.at(0), queueIn++, queueOut++); + } + } + // Post processing workers + if (!postProcessingWs.empty()) + { + // Combining postProcessingWs and outputWs + outputWs = mergeVectors(postProcessingWs, outputWs); + // // If I wanna split them + // opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // threadManager.add(threadId, postProcessingWs, queueIn++, queueOut++); + // threadIdPP(threadId, multiThreadEnabled); + } + // If custom user Worker and uses its own thread + if (!userPostProcessingWs.empty()) + { + // If custom user Worker in its own thread + if (userPostProcessingWsOnNewThread) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + threadManager.add(threadId, userPostProcessingWs, queueIn++, queueOut++); + threadIdPP(threadId, multiThreadEnabled); + } + // If custom user Worker in same thread + // Merge with outputWs + else + outputWs = mergeVectors(outputWs, userPostProcessingWs); + } + // Output workers + if (!outputWs.empty()) + { + // Thread 4 or 5, queues 4 -> 5 + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + threadManager.add(threadId, outputWs, queueIn++, queueOut++); + threadIdPP(threadId, multiThreadEnabled); + } + // User output worker + // Thread Y, queues Q -> Q+1 + if (!userOutputWs.empty()) + { + if (userOutputWsOnNewThread) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + threadManager.add(threadId, userOutputWs, queueIn++, queueOut++); + threadIdPP(threadId, multiThreadEnabled); + } + else + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + threadManager.add(threadId-1, userOutputWs, queueIn++, queueOut++); + } + } + // OpenPose GUI + if (guiW != nullptr) + { + // Thread Y+1, queues Q+1 -> Q+2 + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + threadManager.add(threadId, guiW, queueIn++, queueOut++); + // Saving 3D output + if (videoSaver3DW != nullptr) + threadManager.add(threadId, videoSaver3DW, queueIn++, queueOut++); + threadIdPP(threadId, multiThreadEnabled); + } + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Setting maximum speed + if (wFpsMax != nullptr) + { + opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + threadManager.add(threadId, wFpsMax, queueIn++, queueOut++); + threadIdPP(threadId, multiThreadEnabled); + } + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + template + void createMultiviewTDatum( + TDatumsSP& tDatumsSP, unsigned long long& frameCounter, + const CameraParameterReader& cameraParameterReader, const void* const cvMatPtr) + { + try + { + // Sanity check + if (tDatumsSP == nullptr) + op::error("tDatumsSP was nullptr, it must be initialized.", __LINE__, __FUNCTION__, __FILE__); + // Camera parameters + const std::vector& cameraMatrices = cameraParameterReader.getCameraMatrices(); + const std::vector& cameraIntrinsics = cameraParameterReader.getCameraIntrinsics(); + const std::vector& cameraExtrinsics = cameraParameterReader.getCameraExtrinsics(); + const auto matrixesSize = cameraMatrices.size(); + // More sanity checks + if (cameraMatrices.size() < 2) + op::error("There is less than 2 camera parameter matrices.", + __LINE__, __FUNCTION__, __FILE__); + if (cameraMatrices.size() != cameraIntrinsics.size() || cameraMatrices.size() != cameraExtrinsics.size()) + op::error("Camera parameters must have the same size.", __LINE__, __FUNCTION__, __FILE__); + // Split image to process + std::vector imagesToProcess(matrixesSize); + op::Matrix::splitCvMatIntoVectorMatrix(imagesToProcess, cvMatPtr); + // Fill tDatumsSP + tDatumsSP->resize(cameraMatrices.size()); + for (auto datumIndex = 0 ; datumIndex < matrixesSize ; ++datumIndex) + { + auto& datumPtr = tDatumsSP->at(datumIndex); + datumPtr = std::make_shared(); + datumPtr->frameNumber = frameCounter; + datumPtr->cvInputData = imagesToProcess[datumIndex]; + if (matrixesSize > 1) + { + datumPtr->subId = datumIndex; + datumPtr->subIdMax = matrixesSize-1; + datumPtr->cameraMatrix = cameraMatrices[datumIndex]; + datumPtr->cameraExtrinsics = cameraExtrinsics[datumIndex]; + datumPtr->cameraIntrinsics = cameraIntrinsics[datumIndex]; + } + } + ++frameCounter; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } +} + +#endif // OPENPOSE_WRAPPER_WRAPPER_AUXILIARY_HPP diff --git a/openpose/include/openpose/wrapper/wrapperStructExtra.hpp b/openpose/include/openpose/wrapper/wrapperStructExtra.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d103281d78b0b0437862930bb205b4ab0aa000ef --- /dev/null +++ b/openpose/include/openpose/wrapper/wrapperStructExtra.hpp @@ -0,0 +1,60 @@ +#ifndef OPENPOSE_WRAPPER_WRAPPER_STRUCT_EXTRA_HPP +#define OPENPOSE_WRAPPER_WRAPPER_STRUCT_EXTRA_HPP + +#include + +namespace op +{ + /** + * WrapperStructExtra: Pose estimation and rendering configuration struct. + * WrapperStructExtra allows the user to set up the pose estimation and rendering parameters that will be used for + * the OpenPose WrapperT template and Wrapper class. + */ + struct OP_API WrapperStructExtra + { + /** + * Whether to run the 3-D reconstruction demo, i.e., + * 1) Reading from a stereo camera system. + * 2) Performing 3-D reconstruction from the multiple views. + * 3) Displaying 3-D reconstruction results. + */ + bool reconstruct3d; + + /** + * Minimum number of views required to reconstruct each keypoint. + * By default (-1), it will require max(2, min(4, #cameras-1)) cameras to see the keypoint in order to + * reconstruct it. + */ + int minViews3d; + + /** + * Whether to return a person ID for each body skeleton, providing temporal consistency. + */ + bool identification; + + /** + * Whether to enable people tracking across frames. The value indicates the number of frames where tracking + * is run between each OpenPose keypoint detection. Select -1 (default) to disable it or 0 to run + * simultaneously OpenPose keypoint detector and tracking for potentially higher accuracy than only OpenPose. + */ + int tracking; + + /** + * Whether to enable inverse kinematics (IK) from 3-D keypoints to obtain 3-D joint angles. By default + * (0 threads), it is disabled. Increasing the number of threads will increase the speed but also the + * global system latency. + */ + int ikThreads; + + /** + * Constructor of the struct. + * It has the recommended and default values we recommend for each element of the struct. + * Since all the elements of the struct are public, they can also be manually filled. + */ + WrapperStructExtra( + const bool reconstruct3d = false, const int minViews3d = -1, const bool identification = false, + const int tracking = -1, const int ikThreads = 0); + }; +} + +#endif // OPENPOSE_WRAPPER_WRAPPER_STRUCT_EXTRA_HPP diff --git a/openpose/include/openpose/wrapper/wrapperStructFace.hpp b/openpose/include/openpose/wrapper/wrapperStructFace.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a14da9f5bc80193e864146c3cce1f46545733bbf --- /dev/null +++ b/openpose/include/openpose/wrapper/wrapperStructFace.hpp @@ -0,0 +1,77 @@ +#ifndef OPENPOSE_WRAPPER_WRAPPER_STRUCT_FACE_HPP +#define OPENPOSE_WRAPPER_WRAPPER_STRUCT_FACE_HPP + +#include +#include +#include +#include + +namespace op +{ + /** + * WrapperStructFace: Face estimation and rendering configuration struct. + * WrapperStructFace allows the user to set up the face estimation and rendering parameters that will be used for + * the OpenPose WrapperT template and Wrapper class. + */ + struct OP_API WrapperStructFace + { + /** + * Whether to extract face. + */ + bool enable; + + /** + * Kind of face rectangle detector. Recommended Detector::Body (fastest one if body is enabled and most + * accurate one), which is based on the OpenPose body keypoint detector. + */ + Detector detector; + + /** + * CCN (Conv Net) input size. + * The greater, the slower and more memory it will be needed, but it will potentially increase accuracy. + * Both width and height must be divisible by 16. + */ + Point netInputSize; + + /** + * Whether to render the output (pose locations, body, background or PAF heat maps) with CPU or GPU. + * Select `None` for no rendering, `Cpu` or `Gpu` por CPU and GPU rendering respectively. + */ + RenderMode renderMode; + + /** + * Rendering blending alpha value of the pose point locations with respect to the background image. + * Value in the range [0, 1]. 0 will only render the background, 1 will fully render the pose. + */ + float alphaKeypoint; + + /** + * Rendering blending alpha value of the heat maps (face part, background or PAF) with respect to the + * background image. + * Value in the range [0, 1]. 0 will only render the background, 1 will only render the heat map. + */ + float alphaHeatMap; + + /** + * Rendering threshold. Only estimated keypoints whose score confidences are higher than this value will be + * rendered. Note: Rendered refers only to visual display in the OpenPose basic GUI, not in the saved results. + * Generally, a high threshold (> 0.5) will only render very clear body parts; while small thresholds + * (~0.1) will also output guessed and occluded keypoints, but also more false positives (i.e., wrong + * detections). + */ + float renderThreshold; + + /** + * Constructor of the struct. + * It has the recommended and default values we recommend for each element of the struct. + * Since all the elements of the struct are public, they can also be manually filled. + */ + WrapperStructFace( + const bool enable = false, const Detector detector = Detector::Body, + const Point& netInputSize = Point{368, 368}, const RenderMode renderMode = RenderMode::Auto, + const float alphaKeypoint = FACE_DEFAULT_ALPHA_KEYPOINT, + const float alphaHeatMap = FACE_DEFAULT_ALPHA_HEAT_MAP, const float renderThreshold = 0.4f); + }; +} + +#endif // OPENPOSE_WRAPPER_WRAPPER_STRUCT_FACE_HPP diff --git a/openpose/include/openpose/wrapper/wrapperStructGui.hpp b/openpose/include/openpose/wrapper/wrapperStructGui.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2c86e8e11a98cd749f0409761e54181868f0870a --- /dev/null +++ b/openpose/include/openpose/wrapper/wrapperStructGui.hpp @@ -0,0 +1,48 @@ +#ifndef OPENPOSE_WRAPPER_WRAPPER_STRUCT_GUI_HPP +#define OPENPOSE_WRAPPER_WRAPPER_STRUCT_GUI_HPP + +#include +#include + +namespace op +{ + /** + * WrapperStructGui: It controls a small GUI for quick visualization. + */ + struct OP_API WrapperStructGui + { + /** + * Display mode + * a) -1 for automatic selection. + * b) 0 for no display. Useful if there is no X server and/or to slightly speed up the processing if visual + * output is not required. + * c) 2 for 2-D display in the OpenPose small integrated GUI. + * d) 3 for 3-D display, if `--3d` was enabled. + * e) 1 for both 2-D and 3-D display. + */ + DisplayMode displayMode; + + /** + * Whether to add some information to the frame (number of frame, number people detected, etc.) after it is + * saved on disk and before it is displayed and/or returned to the user. + */ + bool guiVerbose; + + /** + * Whether to display the OpenPose small integrated GUI on fullscreen mode. It can be changed by interacting + * with the GUI itself. + */ + bool fullScreen; + + /** + * Constructor of the struct. + * It has the recommended and default values we recommend for each element of the struct. + * Since all the elements of the struct are public, they can also be manually filled. + */ + WrapperStructGui( + const DisplayMode displayMode = DisplayMode::NoDisplay, const bool guiVerbose = false, + const bool fullScreen = false); + }; +} + +#endif // OPENPOSE_WRAPPER_WRAPPER_STRUCT_GUI_HPP diff --git a/openpose/include/openpose/wrapper/wrapperStructHand.hpp b/openpose/include/openpose/wrapper/wrapperStructHand.hpp new file mode 100644 index 0000000000000000000000000000000000000000..00eb9c62de0eb6fd781a76db23a7eab98796b320 --- /dev/null +++ b/openpose/include/openpose/wrapper/wrapperStructHand.hpp @@ -0,0 +1,97 @@ +#ifndef OPENPOSE_WRAPPER_WRAPPER_STRUCT_HAND_HPP +#define OPENPOSE_WRAPPER_WRAPPER_STRUCT_HAND_HPP + +#include +#include +#include +#include + +namespace op +{ + /** + * WrapperStructHand: Hand estimation and rendering configuration struct. + * WrapperStructHand allows the user to set up the hand estimation and rendering parameters that will be used for + * the OpenPose WrapperT template and Wrapper class. + */ + struct OP_API WrapperStructHand + { + /** + * Whether to extract hand. + */ + bool enable; + + /** + * Kind of hand rectangle detector. Recommended Detector::Body (fastest one if body is enabled and most + * accurate one), which is based on the OpenPose body keypoint detector. + * For hand, there is the alternative of Detector::BodyWithTracking. If selected, it will add tracking + * between frames. Adding hand tracking might improve hand keypoints detection for webcam (if the frame + * rate is high enough, i.e., >7 FPS per GPU) and video. This is not person ID tracking, it simply looks + * for hands in positions at which hands were located in previous frames, but it does not guarantee the + * same person id among frames. + */ + Detector detector; + + /** + * CCN (Conv Net) input size. + * The greater, the slower and more memory it will be needed, but it will potentially increase accuracy. + * Both width and height must be divisible by 16. + */ + Point netInputSize; + + /** + * Number of scales to process. + * The greater, the slower and more memory it will be needed, but it will potentially increase accuracy. + * This parameter is related with scaleRange, such as the final pose estimation will be an average of the + * predicted results for each scale. + */ + int scalesNumber; + + /** + * Total range between smallest and biggest scale. The scales will be centered in ratio 1. E.g., if + * scaleRange = 0.4 and scalesNumber = 2, then there will be 2 scales, 0.8 and 1.2. + */ + float scaleRange; + + /** + * Whether to render the output (pose locations, body, background or PAF heat maps) with CPU or GPU. + * Select `None` for no rendering, `Cpu` or `Gpu` por CPU and GPU rendering respectively. + */ + RenderMode renderMode; + + /** + * Rendering blending alpha value of the pose point locations with respect to the background image. + * Value in the range [0, 1]. 0 will only render the background, 1 will fully render the pose. + */ + float alphaKeypoint; + + /** + * Rendering blending alpha value of the heat maps (hand part, background or PAF) with respect to the + * background image. + * Value in the range [0, 1]. 0 will only render the background, 1 will only render the heat map. + */ + float alphaHeatMap; + + /** + * Rendering threshold. Only estimated keypoints whose score confidences are higher than this value will be + * rendered. Note: Rendered refers only to visual display in the OpenPose basic GUI, not in the saved results. + * Generally, a high threshold (> 0.5) will only render very clear body parts; while small thresholds + * (~0.1) will also output guessed and occluded keypoints, but also more false positives (i.e., wrong + * detections). + */ + float renderThreshold; + + /** + * Constructor of the struct. + * It has the recommended and default values we recommend for each element of the struct. + * Since all the elements of the struct are public, they can also be manually filled. + */ + WrapperStructHand( + const bool enable = false, const Detector detector = Detector::Body, + const Point& netInputSize = Point{368, 368}, const int scalesNumber = 1, + const float scaleRange = 0.4f, const RenderMode renderMode = RenderMode::Auto, + const float alphaKeypoint = HAND_DEFAULT_ALPHA_KEYPOINT, + const float alphaHeatMap = HAND_DEFAULT_ALPHA_HEAT_MAP, const float renderThreshold = 0.2f); + }; +} + +#endif // OPENPOSE_WRAPPER_WRAPPER_STRUCT_HAND_HPP diff --git a/openpose/include/openpose/wrapper/wrapperStructInput.hpp b/openpose/include/openpose/wrapper/wrapperStructInput.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ff30487796521c1129b54301257f3c76a8291fd8 --- /dev/null +++ b/openpose/include/openpose/wrapper/wrapperStructInput.hpp @@ -0,0 +1,110 @@ +#ifndef OPENPOSE_WRAPPER_WRAPPER_STRUCT_INPUT_HPP +#define OPENPOSE_WRAPPER_WRAPPER_STRUCT_INPUT_HPP + +#include // std::numeric_limits +#include +#include + +namespace op +{ + /** + * WrapperStructInput: Input (images, video, webcam, etc.) configuration struct. + * WrapperStructInput allows the user to set up the input frames generator. + */ + struct OP_API WrapperStructInput + { + /** + * Desired type of producer (FlirCamera, ImageDirectory, IPCamera, Video, Webcam, None, etc.). + * Default: ProducerType::None. + */ + ProducerType producerType; + + /** + * Path of the producer (image directory path for ImageDirectory, video path for Video, + * camera index for Webcam and FlirCamera, URL for IPCamera, etc.). + * Default: "". + */ + String producerString; + + /** + * First image to process. + * Default: 0. + */ + unsigned long long frameFirst; + + /** + * Step or gap across processed frames. + * Default: 1 (i.e., process all frames). + * Example: A value of 5 would mean to process frames 0, 5, 10, etc. + */ + unsigned long long frameStep; + + /** + * Last image to process. + * Default: -1 (i.e., process all frames). + */ + unsigned long long frameLast; + + /** + * Whether to skip or sleep in order to keep the same FPS as the frames producer. + */ + bool realTimeProcessing; + + /** + * Whether to flip (mirror) the image. + */ + bool frameFlip; + + /** + * Image rotation. + * Only 4 possible values: 0 (default, no rotation), 90, 180 or 270 degrees + */ + int frameRotate; + + /** + * Whether to re-open the producer if it reaches the end (e.g., video or image directory after the last frame). + */ + bool framesRepeat; + + /** + * Camera resolution (only for Webcam and FlirCamera). + */ + Point cameraResolution; + + /** + * Directory path for the camera parameters (intrinsic and extrinsic parameters) or optionally XML file + * full path (if only 1 view). + */ + String cameraParameterPath; + + /** + * Whether to undistort the image given the camera parameters. + */ + bool undistortImage; + + /** + * Number of camera views. + * Complementary option for `--image_dir` or `--video` + * It is -1 for Flir cameras (# cameras detected at runtime), as well as for any other frames source (-1 and 1 + * are equivalent for those). It could be greater than 1 only for prerecorded produced sources, such as video + * and image directory. + */ + int numberViews; + + /** + * Constructor of the struct. + * It has the recommended and default values we recommend for each element of the struct. + * Since all the elements of the struct are public, they can also be manually filled. + */ + WrapperStructInput( + const ProducerType producerType = ProducerType::None, const String& producerString = "", + const unsigned long long frameFirst = 0, const unsigned long long frameStep = 1, + const unsigned long long frameLast = std::numeric_limits::max(), + const bool realTimeProcessing = false, const bool frameFlip = false, const int frameRotate = 0, + const bool framesRepeat = false, const Point& cameraResolution = Point{-1,-1}, + const String& cameraParameterPath = "models/cameraParameters/", + const bool undistortImage = false, const int numberViews = -1); + }; +} + +#endif // OPENPOSE_WRAPPER_WRAPPER_STRUCT_INPUT_HPP diff --git a/openpose/include/openpose/wrapper/wrapperStructOutput.hpp b/openpose/include/openpose/wrapper/wrapperStructOutput.hpp new file mode 100644 index 0000000000000000000000000000000000000000..257c2bc70f695069d8292e8172af366366401b57 --- /dev/null +++ b/openpose/include/openpose/wrapper/wrapperStructOutput.hpp @@ -0,0 +1,164 @@ +#ifndef OPENPOSE_WRAPPER_WRAPPER_STRUCT_OUTPUT_HPP +#define OPENPOSE_WRAPPER_WRAPPER_STRUCT_OUTPUT_HPP + +#include +#include +#include + +namespace op +{ + /** + * WrapperStructOutput: Output ( writing rendered results and/or pose data, etc.) configuration struct. + */ + struct OP_API WrapperStructOutput + { + /** + * Output verbose in the command line. + * If -1, it will be disabled (default). If it is a positive integer number, it will print on" + * the command line every `verbose` frames. If number in the range (0,1), it will print the" + * progress every `verbose` times the total of frames. + */ + double verbose; + + /** + * Pose (x, y, score) locations saving folder location. + * If it is empty (default), it is disabled. + * Select format with writeKeypointFormat. + */ + String writeKeypoint; + + /** + * Data format to save Pose (x, y, score) locations. + * Options: DataFormat::Json (default), DataFormat::Xml and DataFormat::Yml (equivalent to DataFormat::Yaml) + * JSON option only available for OpenCV >= 3.0. + */ + DataFormat writeKeypointFormat; + + /** + * Directory to write OpenPose output in JSON format. + * If it is empty (default), it is disabled. + * It includes: + * - `people` field with body, hand, and face pose keypoints in (x, y, score) format. + * - `part_candidates` field with body part candidates in (x, y, score) format (if enabled with + * `--part_candidates`). + */ + String writeJson; + + /** + * Pose (x, y, score) locations saving folder location in JSON COCO validation format. + * If it is empty (default), it is disabled. + */ + String writeCocoJson; + + /** + * It selects the COCO variants for cocoJsonSaver. + * Add 1 for body, add 2 for foot, 4 for face, and/or 8 for hands. Use 0 to use all the possible candidates. + * E.g., 7 would mean body+foot+face COCO JSON.. + */ + int writeCocoJsonVariants; + + /** + * Experimental option (only makes effect on car JSON generation). + * It selects the COCO variant for cocoJsonSaver. + */ + int writeCocoJsonVariant; + + /** + * Rendered image saving folder. + * If it is empty (default), it is disabled. + */ + String writeImages; + + /** + * Rendered image saving folder format. + * Check your OpenCV version documentation for a list of compatible formats. + * E.g., png, jpg, etc. + * If writeImages is empty (default), it makes no effect. + */ + String writeImagesFormat; + + /** + * Rendered images saving video path. + * Please, use *.avi format. + * If it is empty (default), it is disabled. + */ + String writeVideo; + + /** + * Frame rate of the recorded video. + * By default (-1.), it will try to get the input frames producer frame rate (e.g., input video or webcam frame + * rate). If the input frames producer does not have a set FPS (e.g., image_dir or webcam if OpenCV not + * compiled with its support), set this value accordingly (e.g., to the frame rate displayed by the OpenPose + * GUI). + */ + double writeVideoFps; + + /** + * Whether to save the output video with audio. The input producer must be a video too. + */ + bool writeVideoWithAudio; + + /** + * Rendered heat maps saving folder. + * In order to save the heatmaps, WrapperStructPose.heatMapTypes must also be filled. + * If it is empty (default), it is disabled. + */ + String writeHeatMaps; + + /** + * Heat maps image saving format. + * Analogous to writeImagesFormat. + */ + String writeHeatMapsFormat; + + /** + * Rendered 3D images saving video path. + * Please, use *.avi format. + * If it is empty (default), it is disabled. + */ + String writeVideo3D; + + /** + * Rendered Adam images saving video path. + * Please, use *.avi format. + * If it is empty (default), it is disabled. + */ + String writeVideoAdam; + + /** + * Path to save a 3-D joint angle BVH file. + * Please, use *.bvh format. + * If it is empty (default), it is disabled. + */ + String writeBvh; + + /** + * Target server IP address for UDP client-server communication. + */ + String udpHost; + + /** + * Target server IP port for UDP client-server communication. + */ + String udpPort; + + /** + * Constructor of the struct. + * It has the recommended and default values we recommend for each element of the struct. + * Since all the elements of the struct are public, they can also be manually filled. + */ + WrapperStructOutput( + const double verbose = -1, const String& writeKeypoint = "", + const DataFormat writeKeypointFormat = DataFormat::Xml, const String& writeJson = "", + const String& writeCocoJson = "", const int writeCocoJsonVariants = 1, + const int writeCocoJsonVariant = 1, const String& writeImages = "", + const String& writeImagesFormat = "png", const String& writeVideo = "", + const double writeVideoFps = -1., const bool writeVideoWithAudio = false, + const String& writeHeatMaps = "", const String& writeHeatMapsFormat = "png", + const String& writeVideo3D = "", const String& writeVideoAdam = "", + const String& writeBvh = "", const String& udpHost = "", + const String& udpPort = "8051"); + }; +} + +#endif // OPENPOSE_WRAPPER_WRAPPER_STRUCT_OUTPUT_HPP diff --git a/openpose/include/openpose/wrapper/wrapperStructPose.hpp b/openpose/include/openpose/wrapper/wrapperStructPose.hpp new file mode 100644 index 0000000000000000000000000000000000000000..72c1a4dcfdf81c485bc70bdee1cb9c504687bf1f --- /dev/null +++ b/openpose/include/openpose/wrapper/wrapperStructPose.hpp @@ -0,0 +1,238 @@ +#ifndef OPENPOSE_WRAPPER_WRAPPER_STRUCT_POSE_HPP +#define OPENPOSE_WRAPPER_WRAPPER_STRUCT_POSE_HPP + +#include +#include +#include +#include +#include +#include + +namespace op +{ + /** + * WrapperStructPose: Pose estimation and rendering configuration struct. + * WrapperStructPose allows the user to set up the pose estimation and rendering parameters that will be used for + * the OpenPose WrapperT template and Wrapper class. + */ + struct OP_API WrapperStructPose + { + /** + * Whether to extract body. + * It might be optionally disabled for very few cases (e.g., if only face keypoint detection is desired for + * speedup while reducing its accuracy). Otherwise, it must be always enabled. + */ + PoseMode poseMode; + + /** + * CCN (Conv Net) input size. + * The greater, the slower and more memory it will be needed, but it will potentially increase accuracy. + * Both width and height must be divisible by 16. + */ + Point netInputSize; + + /** + * Zero or negative means that using `-1` in netInputSize will behave as explained in its flag description. + * Otherwise, and to avoid out of memory errors, the `-1` in netInputSize will clip to this value times the + * default 16/9 aspect ratio value (i.e., 656 width for a 368 height). E.g., netInputSizeDynamicBehavior = 10 + * and netInputSize = {-1x368} will clip to 6560x368 (10 x 656). Recommended 1 for small GPUs (to avoid out of + * memory errors but maximize speed) and 0 for big GPUs (for maximum accuracy and speed). + */ + double netInputSizeDynamicBehavior; + + /** + * Output size of the final rendered image. + * It barely affects performance compared to netInputSize. + * The final Datum.poseKeypoints can be scaled with respect to outputSize if `keypointScaleMode` is set to + * ScaleMode::OutputResolution, even if the rendering is disabled. + */ + Point outputSize; + + /** + * Final scale of the Array Datum.poseKeypoints and the written pose data. + * The final Datum.poseKeypoints can be scaled with respect to input size (ScaleMode::InputResolution), net + * output size (ScaleMode::NetOutputResolution), output rendering size (ScaleMode::OutputResolution), from 0 to + * 1 (ScaleMode::ZeroToOne(FixedAspect)), and -1 to 1 (ScaleMode::PlusMinusOne(FixedAspect)). + */ + ScaleMode keypointScaleMode; + + /** + * Number of GPUs processing in parallel. + * The greater, the faster the algorithm will run, but potentially higher lag will appear (which only affects + * in real-time webcam scenarios). + */ + int gpuNumber; + + /** + * First GPU device. + * Such as the GPUs used will be the ones in the range: [gpuNumberStart, gpuNumberStart + gpuNumber]. + */ + int gpuNumberStart; + + /** + * Number of scales to process. + * The greater, the slower and more memory it will be needed, but it will potentially increase accuracy. + * This parameter is related with scaleGap, such as the final pose estimation will be an average of the + * predicted results for each scale. + */ + int scalesNumber; + + /** + * Gap between successive scales. + * The pose estimation will be estimation for the scales in the range [1, 1-scaleGap*scalesNumber], with a gap + * of scaleGap. + */ + float scaleGap; + + /** + * Whether to render the output (pose locations, body, background or PAF heat maps) with CPU or GPU. + * Select `None` for no rendering, `Cpu` or `Gpu` por CPU and GPU rendering respectively. + */ + RenderMode renderMode; + + /** + * Pose model, it affects the number of body parts to render + * Select PoseModel::BODY_25 for 25 body-part COCO + foot model; PoseModel::COCO_18 for 18 body-part COCO; + * PoseModel::MPI_15 for 15 body-part MPI; PoseModel::MPI_15_4 for faster version of MPI; etc.. + */ + PoseModel poseModel; + + /** + * Whether to blend the final results on top of the original image, or just render them on a flat background. + */ + bool blendOriginalFrame; + + /** + * Rendering blending alpha value of the pose point locations with respect to the background image. + * Value in the range [0, 1]. 0 will only render the background, 1 will fully render the pose. + */ + float alphaKeypoint; + + /** + * Rendering blending alpha value of the heat maps (body part, background or PAF) with respect to the + * background image. + * Value in the range [0, 1]. 0 will only render the background, 1 will only render the heat map. + */ + float alphaHeatMap; + + /** + * Element to initially render. + * Set 0 for pose, [1, #body parts] for each body part following the order on POSE_BODY_PART_MAPPING on + * `include/pose/poseParameters.hpp`, #body parts+1 for background, #body parts+2 for all body parts + * overlapped, #body parts+3 for all PAFs, and [#body parts+4, #body parts+4+#pair pairs] for each PAF + * following the order on POSE_BODY_PART_PAIRS. + */ + int defaultPartToRender; + + /** + * Folder where the pose Caffe models are located. + */ + String modelFolder; + + /** + * Whether and which heat maps to save on the Array Datum.heatmaps. + * Use HeatMapType::Parts for body parts, HeatMapType::Background for the background, and HeatMapType::PAFs for + * the Part Affinity Fields. + */ + std::vector heatMapTypes; + + /** + * Scale of the Datum.heatmaps. + * Select ScaleMode::ZeroToOne(FixedAspect) for range [0,1], ScaleMode::PlusMinusOne(FixedAspect) for [-1,1] + * and ScaleMode::UnsignedChar for [0, 255]. + * If heatMapTypes.empty(), then this parameters makes no effect. + */ + ScaleMode heatMapScaleMode; + + /** + * Whether to add the body part candidates. + * Candidates refer to all the detected body parts, before being assembled into people. + */ + bool addPartCandidates; + + /** + * Rendering threshold. Only estimated keypoints whose score confidences are higher than this value will be + * rendered. Note: Rendered refers only to visual display in the OpenPose basic GUI, not in the saved results. + * Generally, a high threshold (> 0.5) will only render very clear body parts; while small thresholds + * (~0.1) will also output guessed and occluded keypoints, but also more false positives (i.e., wrong + * detections). + */ + float renderThreshold; + + /** + * Maximum number of people to be detected. + * This parameter will limit the maximum number of people detected, by keeping the people with the + * `numberPeopleMax` top scores. + * Useful if you know the exact number of people in the scene, so it can remove false positives (if all the + * people have been detected. + * However, it might also include false negatives by removing very small or highly occluded people. + */ + int numberPeopleMax; + + /** + * Whether to maximize the number of positives. + * It reduces the thresholds to accept a person candidate. It highly increases both false and true positives. + * I.e., it maximizes average recall but could harm average precision. + */ + bool maximizePositives; + + /** + * Maximum processing frame rate. + * By default (-1), OpenPose will process frames as fast as possible. + * Example usage: If OpenPose is displaying images too quickly, this can reduce the speed so the user can + * analyze better each frame from the GUI. + */ + double fpsMax; + + /** + * Final path where the pose Caffe ProtoTxt file is located. + * The combination modelFolder + protoTxtPath represents the whole path to the prototxt file. + * If empty, it will use the default OpenPose ProtoTxt file. + */ + String protoTxtPath; + + /** + * Final path where the pose Caffe CaffeModel is located. + * The combination modelFolder + caffeModelPath represents the whole path to the caffemodel file. + * If empty, it will use the default OpenPose CaffeModel file. + */ + String caffeModelPath; + + /** + * The image upsampling scale. 8 is the stride of the network, so the ideal value to maximize the + * speed/accuracy trade-off. + */ + float upsamplingRatio; + + /** + * Whether to internally enable Google Logging. + * This option is only applicable if Caffe is used. + * Only disable it if the user is already calling google::InitGoogleLogging() in his code. + * If the user disables Google Logging and he does not call it by himself, then Caffe will start to pop up + * all the verbose messages. + */ + bool enableGoogleLogging; + + /** + * Constructor of the struct. + * It has the recommended and default values we recommend for each element of the struct. + * Since all the elements of the struct are public, they can also be manually filled. + */ + WrapperStructPose( + const PoseMode poseMode = PoseMode::Enabled, const Point& netInputSize = Point{-1, 368}, + const double netInputSizeDynamicBehavior = 1., + const Point& outputSize = Point{-1, -1}, + const ScaleMode keypointScaleMode = ScaleMode::InputResolution, const int gpuNumber = -1, + const int gpuNumberStart = 0, const int scalesNumber = 1, const float scaleGap = 0.25f, + const RenderMode renderMode = RenderMode::Auto, const PoseModel poseModel = PoseModel::BODY_25, + const bool blendOriginalFrame = true, const float alphaKeypoint = POSE_DEFAULT_ALPHA_KEYPOINT, + const float alphaHeatMap = POSE_DEFAULT_ALPHA_HEAT_MAP, const int defaultPartToRender = 0, + const String& modelFolder = "models/", const std::vector& heatMapTypes = {}, + const ScaleMode heatMapScaleMode = ScaleMode::UnsignedChar, const bool addPartCandidates = false, + const float renderThreshold = 0.05f, const int numberPeopleMax = -1, const bool maximizePositives = false, + const double fpsMax = -1., const String& protoTxtPath = "", const String& caffeModelPath = "", + const float upsamplingRatio = 0.f, const bool enableGoogleLogging = true); + }; +} + +#endif // OPENPOSE_WRAPPER_WRAPPER_STRUCT_POSE_HPP diff --git a/openpose/include/openpose_private/3d/poseTriangulationPrivate.hpp b/openpose/include/openpose_private/3d/poseTriangulationPrivate.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7c0b5fff83544a86cb7902d0fafb6074a56e9712 --- /dev/null +++ b/openpose/include/openpose_private/3d/poseTriangulationPrivate.hpp @@ -0,0 +1,28 @@ +#ifndef OPENPOSE_PRIVATE_3D_POSE_TRIANGULATION_PRIVATE_HPP +#define OPENPOSE_PRIVATE_3D_POSE_TRIANGULATION_PRIVATE_HPP + +#include +#include + +namespace op +{ + /** + * 3D triangulation given known camera parameter matrices and based on linear DLT algorithm. + * The returned cv::Mat is a 4x1 matrix, where the last coordinate is 1. + */ + double triangulate( + cv::Mat& reconstructedPoint, const std::vector& cameraMatrices, + const std::vector& pointsOnEachCamera); + + /** + * 3D triangulation given known camera parameter matrices and based on linear DLT algorithm with additional LMA + * non-linear refinement. + * The returned cv::Mat is a 4x1 matrix, where the last coordinate is 1. + * Note: If Ceres is not enabled, the LMA refinement is skipped and this function is equivalent to triangulate(). + */ + double triangulateWithOptimization( + cv::Mat& reconstructedPoint, const std::vector& cameraMatrices, + const std::vector& pointsOnEachCamera, const double reprojectionMaxAcceptable); +} + +#endif // OPENPOSE_PRIVATE_3D_POSE_TRIANGULATION_PRIVATE_HPP diff --git a/openpose/include/openpose_private/calibration/gridPatternFunctions.hpp b/openpose/include/openpose_private/calibration/gridPatternFunctions.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ddf1724b3c4d2426504162f8b0e875d30dadf7bc --- /dev/null +++ b/openpose/include/openpose_private/calibration/gridPatternFunctions.hpp @@ -0,0 +1,38 @@ +#ifndef OPENPOSE_PRIVATE_CALIBRATION_GRID_PATTERN_FUNCTIONS_HPP +#define OPENPOSE_PRIVATE_CALIBRATION_GRID_PATTERN_FUNCTIONS_HPP + +#include +#include + +namespace op +{ + enum class Points2DOrigin + { + TopLeft, + TopRight, + BottomLeft, + BottomRight + }; + + std::pair> findAccurateGridCorners( + const cv::Mat& image, const cv::Size& gridInnerCorners); + + std::vector getObjects3DVector( + const cv::Size& gridInnerCorners, const float gridSquareSizeMm); + + void drawGridCorners( + cv::Mat& image, const cv::Size& gridInnerCorners, const std::vector& points2DVector); + + std::array getOutterCornerIndices( + const std::vector& points2DVector, const cv::Size& gridInnerCorners); + + void reorderPoints( + std::vector& points2DVector, const cv::Size& gridInnerCorners, + const cv::Mat& image, const bool showWarning = true); + + void plotGridCorners( + const cv::Size& gridInnerCorners, const std::vector& points2DVector, + const std::string& imagePath, const cv::Mat& image); +} + +#endif // OPENPOSE_PRIVATE_CALIBRATION_GRID_PATTERN_FUNCTIONS_HPP diff --git a/openpose/include/openpose_private/gpu/cl2.hpp b/openpose/include/openpose_private/gpu/cl2.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7217261f7efe2287eb77ee3f118a0d6f901b865d --- /dev/null +++ b/openpose/include/openpose_private/gpu/cl2.hpp @@ -0,0 +1,9570 @@ +/******************************************************************************* + * Copyright (c) 2008-2016 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are 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 Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT + * https://www.khronos.org/registry/ + * + * THE MATERIALS ARE 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 + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + ******************************************************************************/ + +/*! \file + * + * \brief C++ bindings for OpenCL 1.0 (rev 48), OpenCL 1.1 (rev 33), + * OpenCL 1.2 (rev 15) and OpenCL 2.0 (rev 29) + * \author Lee Howes and Bruce Merry + * + * Derived from the OpenCL 1.x C++ bindings written by + * Benedict R. Gaster, Laurent Morichetti and Lee Howes + * With additions and fixes from: + * Brian Cole, March 3rd 2010 and April 2012 + * Matt Gruenke, April 2012. + * Bruce Merry, February 2013. + * Tom Deakin and Simon McIntosh-Smith, July 2013 + * James Price, 2015- + * + * \version 2.0.10 + * \date 2016-07-20 + * + * Optional extension support + * + * cl_ext_device_fission + * #define CL_HPP_USE_CL_DEVICE_FISSION + * cl_khr_d3d10_sharing + * #define CL_HPP_USE_DX_INTEROP + * cl_khr_sub_groups + * #define CL_HPP_USE_CL_SUB_GROUPS_KHR + * + * Doxygen documentation for this header is available here: + * + * http://khronosgroup.github.io/OpenCL-CLHPP/ + * + * The latest version of this header can be found on the GitHub releases page: + * + * https://github.com/KhronosGroup/OpenCL-CLHPP/releases + * + * Bugs and patches can be submitted to the GitHub repository: + * + * https://github.com/KhronosGroup/OpenCL-CLHPP + */ + +/*! \mainpage + * \section intro Introduction + * For many large applications C++ is the language of choice and so it seems + * reasonable to define C++ bindings for OpenCL. + * + * The interface is contained with a single C++ header file \em cl2.hpp and all + * definitions are contained within the namespace \em cl. There is no additional + * requirement to include \em cl.h and to use either the C++ or original C + * bindings; it is enough to simply include \em cl2.hpp. + * + * The bindings themselves are lightweight and correspond closely to the + * underlying C API. Using the C++ bindings introduces no additional execution + * overhead. + * + * There are numerous compatibility, portability and memory management + * fixes in the new header as well as additional OpenCL 2.0 features. + * As a result the header is not directly backward compatible and for this + * reason we release it as cl2.hpp rather than a new version of cl.hpp. + * + * + * \section compatibility Compatibility + * Due to the evolution of the underlying OpenCL API the 2.0 C++ bindings + * include an updated approach to defining supported feature versions + * and the range of valid underlying OpenCL runtime versions supported. + * + * The combination of preprocessor macros CL_HPP_TARGET_OPENCL_VERSION and + * CL_HPP_MINIMUM_OPENCL_VERSION control this range. These are three digit + * decimal values representing OpenCL runime versions. The default for + * the target is 200, representing OpenCL 2.0 and the minimum is also + * defined as 200. These settings would use 2.0 API calls only. + * If backward compatibility with a 1.2 runtime is required, the minimum + * version may be set to 120. + * + * Note that this is a compile-time setting, and so affects linking against + * a particular SDK version rather than the versioning of the loaded runtime. + * + * The earlier versions of the header included basic vector and string + * classes based loosely on STL versions. These were difficult to + * maintain and very rarely used. For the 2.0 header we now assume + * the presence of the standard library unless requested otherwise. + * We use std::array, std::vector, std::shared_ptr and std::string + * throughout to safely manage memory and reduce the chance of a + * recurrence of earlier memory management bugs. + * + * These classes are used through typedefs in the cl namespace: + * cl::array, cl::vector, cl::pointer and cl::string. + * In addition cl::allocate_pointer forwards to std::allocate_shared + * by default. + * In all cases these standard library classes can be replaced with + * custom interface-compatible versions using the CL_HPP_NO_STD_ARRAY, + * CL_HPP_NO_STD_VECTOR, CL_HPP_NO_STD_UNIQUE_PTR and + * CL_HPP_NO_STD_STRING macros. + * + * The OpenCL 1.x versions of the C++ bindings included a size_t wrapper + * class to interface with kernel enqueue. This caused unpleasant interactions + * with the standard size_t declaration and led to namespacing bugs. + * In the 2.0 version we have replaced this with a std::array-based interface. + * However, the old behaviour can be regained for backward compatibility + * using the CL_HPP_ENABLE_SIZE_T_COMPATIBILITY macro. + * + * Finally, the program construction interface used a clumsy vector-of-pairs + * design in the earlier versions. We have replaced that with a cleaner + * vector-of-vectors and vector-of-strings design. However, for backward + * compatibility old behaviour can be regained with the + * CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY macro. + * + * In OpenCL 2.0 OpenCL C is not entirely backward compatibility with + * earlier versions. As a result a flag must be passed to the OpenCL C + * compiled to request OpenCL 2.0 compilation of kernels with 1.2 as + * the default in the absence of the flag. + * In some cases the C++ bindings automatically compile code for ease. + * For those cases the compilation defaults to OpenCL C 2.0. + * If this is not wanted, the CL_HPP_CL_1_2_DEFAULT_BUILD macro may + * be specified to assume 1.2 compilation. + * If more fine-grained decisions on a per-kernel bases are required + * then explicit build operations that take the flag should be used. + * + * + * \section parameterization Parameters + * This header may be parameterized by a set of preprocessor macros. + * + * - CL_HPP_TARGET_OPENCL_VERSION + * + * Defines the target OpenCL runtime version to build the header + * against. Defaults to 200, representing OpenCL 2.0. + * + * - CL_HPP_NO_STD_STRING + * + * Do not use the standard library string class. cl::string is not + * defined and may be defined by the user before cl2.hpp is + * included. + * + * - CL_HPP_NO_STD_VECTOR + * + * Do not use the standard library vector class. cl::vector is not + * defined and may be defined by the user before cl2.hpp is + * included. + * + * - CL_HPP_NO_STD_ARRAY + * + * Do not use the standard library array class. cl::array is not + * defined and may be defined by the user before cl2.hpp is + * included. + * + * - CL_HPP_NO_STD_UNIQUE_PTR + * + * Do not use the standard library unique_ptr class. cl::pointer and + * the cl::allocate_pointer functions are not defined and may be + * defined by the user before cl2.hpp is included. + * + * - CL_HPP_ENABLE_DEVICE_FISSION + * + * Enables device fission for OpenCL 1.2 platforms. + * + * - CL_HPP_ENABLE_EXCEPTIONS + * + * Enable exceptions for use in the C++ bindings header. This is the + * preferred error handling mechanism but is not required. + * + * - CL_HPP_ENABLE_SIZE_T_COMPATIBILITY + * + * Backward compatibility option to support cl.hpp-style size_t + * class. Replaces the updated std::array derived version and + * removal of size_t from the namespace. Note that in this case the + * new size_t class is placed in the cl::compatibility namespace and + * thus requires an additional using declaration for direct backward + * compatibility. + * + * - CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY + * + * Enable older vector of pairs interface for construction of + * programs. + * + * - CL_HPP_CL_1_2_DEFAULT_BUILD + * + * Default to OpenCL C 1.2 compilation rather than OpenCL C 2.0 + * applies to use of cl::Program construction and other program + * build variants. + * + * + * \section example Example + * + * The following example shows a general use case for the C++ + * bindings, including support for the optional exception feature and + * also the supplied vector and string classes, see following sections for + * descriptions of these features. + * + * \code + #define CL_HPP_ENABLE_EXCEPTIONS + #define CL_HPP_TARGET_OPENCL_VERSION 200 + + #include + #include + #include + #include + #include + + const int numElements = 32; + + int main(void) + { + // Filter for a 2.0 platform and set it as the default + std::vector platforms; + cl::Platform::get(&platforms); + cl::Platform plat; + for (auto &p : platforms) { + std::string platver = p.getInfo(); + if (platver.find("OpenCL 2.") != std::string::npos) { + plat = p; + } + } + if (plat() == 0) { + std::cout << "No OpenCL 2.0 platform found."; + return -1; + } + + cl::Platform newP = cl::Platform::setDefault(plat); + if (newP != plat) { + std::cout << "Error setting default platform."; + return -1; + } + + // Use C++11 raw string literals for kernel source code + std::string kernel1{R"CLC( + global int globalA; + kernel void updateGlobal() + { + globalA = 75; + } + )CLC"}; + std::string kernel2{R"CLC( + typedef struct { global int *bar; } Foo; + kernel void vectorAdd(global const Foo* aNum, global const int *inputA, global const int *inputB, + global int *output, int val, write_only pipe int outPipe, queue_t childQueue) + { + output[get_global_id(0)] = inputA[get_global_id(0)] + inputB[get_global_id(0)] + val + *(aNum->bar); + write_pipe(outPipe, &val); + queue_t default_queue = get_default_queue(); + ndrange_t ndrange = ndrange_1D(get_global_size(0)/2, get_global_size(0)/2); + + // Have a child kernel write into third quarter of output + enqueue_kernel(default_queue, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, + ^{ + output[get_global_size(0)*2 + get_global_id(0)] = + inputA[get_global_size(0)*2 + get_global_id(0)] + inputB[get_global_size(0)*2 + get_global_id(0)] + globalA; + }); + + // Have a child kernel write into last quarter of output + enqueue_kernel(childQueue, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, + ^{ + output[get_global_size(0)*3 + get_global_id(0)] = + inputA[get_global_size(0)*3 + get_global_id(0)] + inputB[get_global_size(0)*3 + get_global_id(0)] + globalA + 2; + }); + } + )CLC"}; + + // New simpler string interface style + std::vector programStrings {kernel1, kernel2}; + + cl::Program vectorAddProgram(programStrings); + try { + vectorAddProgram.build("-cl-std=CL2.0"); + } + catch (...) { + // Print build info for all devices + cl_int buildErr = CL_SUCCESS; + auto buildInfo = vectorAddProgram.getBuildInfo(&buildErr); + for (auto &pair : buildInfo) { + std::cerr << pair.second << std::endl << std::endl; + } + + return 1; + } + + typedef struct { int *bar; } Foo; + + // Get and run kernel that initializes the program-scope global + // A test for kernels that take no arguments + auto program2Kernel = + cl::KernelFunctor<>(vectorAddProgram, "updateGlobal"); + program2Kernel( + cl::EnqueueArgs( + cl::NDRange(1))); + + ////////////////// + // SVM allocations + + auto anSVMInt = cl::allocate_svm>(); + *anSVMInt = 5; + cl::SVMAllocator>> svmAllocReadOnly; + auto fooPointer = cl::allocate_pointer(svmAllocReadOnly); + fooPointer->bar = anSVMInt.get(); + cl::SVMAllocator> svmAlloc; + std::vector>> inputA(numElements, 1, svmAlloc); + cl::coarse_svm_vector inputB(numElements, 2, svmAlloc); + + // + ////////////// + + // Traditional cl_mem allocations + std::vector output(numElements, 0xdeadbeef); + cl::Buffer outputBuffer(begin(output), end(output), false); + cl::Pipe aPipe(sizeof(cl_int), numElements / 2); + + // Default command queue, also passed in as a parameter + cl::DeviceCommandQueue defaultDeviceQueue = cl::DeviceCommandQueue::makeDefault( + cl::Context::getDefault(), cl::Device::getDefault()); + + auto vectorAddKernel = + cl::KernelFunctor< + decltype(fooPointer)&, + int*, + cl::coarse_svm_vector&, + cl::Buffer, + int, + cl::Pipe&, + cl::DeviceCommandQueue + >(vectorAddProgram, "vectorAdd"); + + // Ensure that the additional SVM pointer is available to the kernel + // This one was not passed as a parameter + vectorAddKernel.setSVMPointers(anSVMInt); + + // Hand control of coarse allocations to runtime + cl::enqueueUnmapSVM(anSVMInt); + cl::enqueueUnmapSVM(fooPointer); + cl::unmapSVM(inputB); + cl::unmapSVM(output2); + + cl_int error; + vectorAddKernel( + cl::EnqueueArgs( + cl::NDRange(numElements/2), + cl::NDRange(numElements/2)), + fooPointer, + inputA.data(), + inputB, + outputBuffer, + 3, + aPipe, + defaultDeviceQueue, + error + ); + + cl::copy(outputBuffer, begin(output), end(output)); + // Grab the SVM output vector using a map + cl::mapSVM(output2); + + cl::Device d = cl::Device::getDefault(); + + std::cout << "Output:\n"; + for (int i = 1; i < numElements; ++i) { + std::cout << "\t" << output[i] << "\n"; + } + std::cout << "\n\n"; + + return 0; + } + * + * \endcode + * + */ +#ifndef CL_HPP_ +#define CL_HPP_ + +/* Handle deprecated preprocessor definitions. In each case, we only check for + * the old name if the new name is not defined, so that user code can define + * both and hence work with either version of the bindings. + */ +#if !defined(CL_HPP_USE_DX_INTEROP) && defined(USE_DX_INTEROP) +# pragma message("cl2.hpp: USE_DX_INTEROP is deprecated. Define CL_HPP_USE_DX_INTEROP instead") +# define CL_HPP_USE_DX_INTEROP +#endif +#if !defined(CL_HPP_USE_CL_DEVICE_FISSION) && defined(USE_CL_DEVICE_FISSION) +# pragma message("cl2.hpp: USE_CL_DEVICE_FISSION is deprecated. Define CL_HPP_USE_CL_DEVICE_FISSION instead") +# define CL_HPP_USE_CL_DEVICE_FISSION +#endif +#if !defined(CL_HPP_ENABLE_EXCEPTIONS) && defined(__CL_ENABLE_EXCEPTIONS) +# pragma message("cl2.hpp: __CL_ENABLE_EXCEPTIONS is deprecated. Define CL_HPP_ENABLE_EXCEPTIONS instead") +# define CL_HPP_ENABLE_EXCEPTIONS +#endif +#if !defined(CL_HPP_NO_STD_VECTOR) && defined(__NO_STD_VECTOR) +# pragma message("cl2.hpp: __NO_STD_VECTOR is deprecated. Define CL_HPP_NO_STD_VECTOR instead") +# define CL_HPP_NO_STD_VECTOR +#endif +#if !defined(CL_HPP_NO_STD_STRING) && defined(__NO_STD_STRING) +# pragma message("cl2.hpp: __NO_STD_STRING is deprecated. Define CL_HPP_NO_STD_STRING instead") +# define CL_HPP_NO_STD_STRING +#endif +#if defined(VECTOR_CLASS) +# pragma message("cl2.hpp: VECTOR_CLASS is deprecated. Alias cl::vector instead") +#endif +#if defined(STRING_CLASS) +# pragma message("cl2.hpp: STRING_CLASS is deprecated. Alias cl::string instead.") +#endif +#if !defined(CL_HPP_USER_OVERRIDE_ERROR_STRINGS) && defined(__CL_USER_OVERRIDE_ERROR_STRINGS) +# pragma message("cl2.hpp: __CL_USER_OVERRIDE_ERROR_STRINGS is deprecated. Define CL_HPP_USER_OVERRIDE_ERROR_STRINGS instead") +# define CL_HPP_USER_OVERRIDE_ERROR_STRINGS +#endif + +/* Warn about features that are no longer supported + */ +#if defined(__USE_DEV_VECTOR) +# pragma message("cl2.hpp: __USE_DEV_VECTOR is no longer supported. Expect compilation errors") +#endif +#if defined(__USE_DEV_STRING) +# pragma message("cl2.hpp: __USE_DEV_STRING is no longer supported. Expect compilation errors") +#endif + +/* Detect which version to target */ +#if !defined(CL_HPP_TARGET_OPENCL_VERSION) +# pragma message("cl2.hpp: CL_HPP_TARGET_OPENCL_VERSION is not defined. It will default to 200 (OpenCL 2.0)") +# define CL_HPP_TARGET_OPENCL_VERSION 200 +#endif +#if CL_HPP_TARGET_OPENCL_VERSION != 100 && CL_HPP_TARGET_OPENCL_VERSION != 110 && CL_HPP_TARGET_OPENCL_VERSION != 120 && CL_HPP_TARGET_OPENCL_VERSION != 200 +# pragma message("cl2.hpp: CL_HPP_TARGET_OPENCL_VERSION is not a valid value (100, 110, 120 or 200). It will be set to 200") +# undef CL_HPP_TARGET_OPENCL_VERSION +# define CL_HPP_TARGET_OPENCL_VERSION 200 +#endif + +#if !defined(CL_HPP_MINIMUM_OPENCL_VERSION) +# define CL_HPP_MINIMUM_OPENCL_VERSION 200 +#endif +#if CL_HPP_MINIMUM_OPENCL_VERSION != 100 && CL_HPP_MINIMUM_OPENCL_VERSION != 110 && CL_HPP_MINIMUM_OPENCL_VERSION != 120 && CL_HPP_MINIMUM_OPENCL_VERSION != 200 +# pragma message("cl2.hpp: CL_HPP_MINIMUM_OPENCL_VERSION is not a valid value (100, 110, 120 or 200). It will be set to 100") +# undef CL_HPP_MINIMUM_OPENCL_VERSION +# define CL_HPP_MINIMUM_OPENCL_VERSION 100 +#endif +#if CL_HPP_MINIMUM_OPENCL_VERSION > CL_HPP_TARGET_OPENCL_VERSION +# error "CL_HPP_MINIMUM_OPENCL_VERSION must not be greater than CL_HPP_TARGET_OPENCL_VERSION" +#endif + +#if CL_HPP_MINIMUM_OPENCL_VERSION <= 100 && !defined(CL_USE_DEPRECATED_OPENCL_1_0_APIS) +# define CL_USE_DEPRECATED_OPENCL_1_0_APIS +#endif +#if CL_HPP_MINIMUM_OPENCL_VERSION <= 110 && !defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) +# define CL_USE_DEPRECATED_OPENCL_1_1_APIS +#endif +#if CL_HPP_MINIMUM_OPENCL_VERSION <= 120 && !defined(CL_USE_DEPRECATED_OPENCL_1_2_APIS) +# define CL_USE_DEPRECATED_OPENCL_1_2_APIS +#endif +#if CL_HPP_MINIMUM_OPENCL_VERSION <= 200 && !defined(CL_USE_DEPRECATED_OPENCL_2_0_APIS) +# define CL_USE_DEPRECATED_OPENCL_2_0_APIS +#endif + +#ifdef _WIN32 + +#include + +#if defined(CL_HPP_USE_DX_INTEROP) +#include +#include +#endif +#endif // _WIN32 + +#if defined(_MSC_VER) +#include +#endif // _MSC_VER + + // Check for a valid C++ version + +// Need to do both tests here because for some reason __cplusplus is not +// updated in visual studio +#if (!defined(_MSC_VER) && __cplusplus < 201103L) || (defined(_MSC_VER) && _MSC_VER < 1700) +#error Visual studio 2013 or another C++11-supporting compiler required +#endif + +// +#if defined(CL_HPP_USE_CL_DEVICE_FISSION) || defined(CL_HPP_USE_CL_SUB_GROUPS_KHR) +#include +#endif + +#if defined(__APPLE__) || defined(__MACOSX) +#include +#else +#include +#endif // !__APPLE__ + +#if (__cplusplus >= 201103L) +#define CL_HPP_NOEXCEPT_ noexcept +#else +#define CL_HPP_NOEXCEPT_ +#endif + +#if defined(_MSC_VER) +# define CL_HPP_DEFINE_STATIC_MEMBER_ __declspec(selectany) +#else +# define CL_HPP_DEFINE_STATIC_MEMBER_ __attribute__((weak)) +#endif // !_MSC_VER + +// Define deprecated prefixes and suffixes to ensure compilation +// in case they are not pre-defined +#if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED) +#define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED +#endif // #if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED) +#if !defined(CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED) +#define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED +#endif // #if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED) + +#if !defined(CL_EXT_PREFIX__VERSION_1_2_DEPRECATED) +#define CL_EXT_PREFIX__VERSION_1_2_DEPRECATED +#endif // #if !defined(CL_EXT_PREFIX__VERSION_1_2_DEPRECATED) +#if !defined(CL_EXT_SUFFIX__VERSION_1_2_DEPRECATED) +#define CL_EXT_SUFFIX__VERSION_1_2_DEPRECATED +#endif // #if !defined(CL_EXT_PREFIX__VERSION_1_2_DEPRECATED) + +#if !defined(CL_CALLBACK) +#define CL_CALLBACK +#endif //CL_CALLBACK + +#include +#include +#include +#include +#include +#include + + +// Define a size_type to represent a correctly resolved size_t +#if defined(CL_HPP_ENABLE_SIZE_T_COMPATIBILITY) +namespace cl { + using size_type = ::size_t; +} // namespace cl +#else // #if defined(CL_HPP_ENABLE_SIZE_T_COMPATIBILITY) +namespace cl { + using size_type = size_t; +} // namespace cl +#endif // #if defined(CL_HPP_ENABLE_SIZE_T_COMPATIBILITY) + + +#if defined(CL_HPP_ENABLE_EXCEPTIONS) +#include +#endif // #if defined(CL_HPP_ENABLE_EXCEPTIONS) + +#if !defined(CL_HPP_NO_STD_VECTOR) +#include +namespace cl { + template < class T, class Alloc = std::allocator > + using vector = std::vector; +} // namespace cl +#endif // #if !defined(CL_HPP_NO_STD_VECTOR) + +#if !defined(CL_HPP_NO_STD_STRING) +#include +namespace cl { + using string = std::string; +} // namespace cl +#endif // #if !defined(CL_HPP_NO_STD_STRING) + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 + +#if !defined(CL_HPP_NO_STD_UNIQUE_PTR) +#include +namespace cl { + // Replace unique_ptr and allocate_pointer for internal use + // to allow user to replace them + template + using pointer = std::unique_ptr; +} // namespace cl +#endif +#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200 +#if !defined(CL_HPP_NO_STD_ARRAY) +#include +namespace cl { + template < class T, size_type N > + using array = std::array; +} // namespace cl +#endif // #if !defined(CL_HPP_NO_STD_ARRAY) + +// Define size_type appropriately to allow backward-compatibility +// use of the old size_t interface class +#if defined(CL_HPP_ENABLE_SIZE_T_COMPATIBILITY) +namespace cl { + namespace compatibility { + /*! \brief class used to interface between C++ and + * OpenCL C calls that require arrays of size_t values, whose + * size is known statically. + */ + template + class size_t + { + private: + size_type data_[N]; + + public: + //! \brief Initialize size_t to all 0s + size_t() + { + for (int i = 0; i < N; ++i) { + data_[i] = 0; + } + } + + size_t(const array &rhs) + { + for (int i = 0; i < N; ++i) { + data_[i] = rhs[i]; + } + } + + size_type& operator[](int index) + { + return data_[index]; + } + + const size_type& operator[](int index) const + { + return data_[index]; + } + + //! \brief Conversion operator to T*. + operator size_type* () { return data_; } + + //! \brief Conversion operator to const T*. + operator const size_type* () const { return data_; } + + operator array() const + { + array ret; + + for (int i = 0; i < N; ++i) { + ret[i] = data_[i]; + } + return ret; + } + }; + } // namespace compatibility + + template + using size_t = compatibility::size_t; +} // namespace cl +#endif // #if defined(CL_HPP_ENABLE_SIZE_T_COMPATIBILITY) + +// Helper alias to avoid confusing the macros +namespace cl { + namespace detail { + using size_t_array = array; + } // namespace detail +} // namespace cl + + +/*! \namespace cl + * + * \brief The OpenCL C++ bindings are defined within this namespace. + * + */ +namespace cl { + class Memory; + +#define CL_HPP_INIT_CL_EXT_FCN_PTR_(name) \ + if (!pfn_##name) { \ + pfn_##name = (PFN_##name) \ + clGetExtensionFunctionAddress(#name); \ + if (!pfn_##name) { \ + } \ + } + +#define CL_HPP_INIT_CL_EXT_FCN_PTR_PLATFORM_(platform, name) \ + if (!pfn_##name) { \ + pfn_##name = (PFN_##name) \ + clGetExtensionFunctionAddressForPlatform(platform, #name); \ + if (!pfn_##name) { \ + } \ + } + + class Program; + class Device; + class Context; + class CommandQueue; + class DeviceCommandQueue; + class Memory; + class Buffer; + class Pipe; + +#if defined(CL_HPP_ENABLE_EXCEPTIONS) + /*! \brief Exception class + * + * This may be thrown by API functions when CL_HPP_ENABLE_EXCEPTIONS is defined. + */ + class Error : public std::exception + { + private: + cl_int err_; + const char * errStr_; + public: + /*! \brief Create a new CL error exception for a given error code + * and corresponding message. + * + * \param err error code value. + * + * \param errStr a descriptive string that must remain in scope until + * handling of the exception has concluded. If set, it + * will be returned by what(). + */ + Error(cl_int err, const char * errStr = NULL) : err_(err), errStr_(errStr) + {} + + ~Error() throw() {} + + /*! \brief Get error string associated with exception + * + * \return A memory pointer to the error message string. + */ + virtual const char * what() const throw () + { + if (errStr_ == NULL) { + return "empty"; + } + else { + return errStr_; + } + } + + /*! \brief Get error code associated with exception + * + * \return The error code. + */ + cl_int err(void) const { return err_; } + }; +#define CL_HPP_ERR_STR_(x) #x +#else +#define CL_HPP_ERR_STR_(x) NULL +#endif // CL_HPP_ENABLE_EXCEPTIONS + + +namespace detail +{ +#if defined(CL_HPP_ENABLE_EXCEPTIONS) +static inline cl_int errHandler ( + cl_int err, + const char * errStr = NULL) +{ + if (err != CL_SUCCESS) { + throw Error(err, errStr); + } + return err; +} +#else +static inline cl_int errHandler (cl_int err, const char * errStr = NULL) +{ + (void) errStr; // suppress unused variable warning + return err; +} +#endif // CL_HPP_ENABLE_EXCEPTIONS +} + + + +//! \cond DOXYGEN_DETAIL +#if !defined(CL_HPP_USER_OVERRIDE_ERROR_STRINGS) +#define __GET_DEVICE_INFO_ERR CL_HPP_ERR_STR_(clGetDeviceInfo) +#define __GET_PLATFORM_INFO_ERR CL_HPP_ERR_STR_(clGetPlatformInfo) +#define __GET_DEVICE_IDS_ERR CL_HPP_ERR_STR_(clGetDeviceIDs) +#define __GET_PLATFORM_IDS_ERR CL_HPP_ERR_STR_(clGetPlatformIDs) +#define __GET_CONTEXT_INFO_ERR CL_HPP_ERR_STR_(clGetContextInfo) +#define __GET_EVENT_INFO_ERR CL_HPP_ERR_STR_(clGetEventInfo) +#define __GET_EVENT_PROFILE_INFO_ERR CL_HPP_ERR_STR_(clGetEventProfileInfo) +#define __GET_MEM_OBJECT_INFO_ERR CL_HPP_ERR_STR_(clGetMemObjectInfo) +#define __GET_IMAGE_INFO_ERR CL_HPP_ERR_STR_(clGetImageInfo) +#define __GET_SAMPLER_INFO_ERR CL_HPP_ERR_STR_(clGetSamplerInfo) +#define __GET_KERNEL_INFO_ERR CL_HPP_ERR_STR_(clGetKernelInfo) +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 +#define __GET_KERNEL_ARG_INFO_ERR CL_HPP_ERR_STR_(clGetKernelArgInfo) +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 +#define __GET_KERNEL_WORK_GROUP_INFO_ERR CL_HPP_ERR_STR_(clGetKernelWorkGroupInfo) +#define __GET_PROGRAM_INFO_ERR CL_HPP_ERR_STR_(clGetProgramInfo) +#define __GET_PROGRAM_BUILD_INFO_ERR CL_HPP_ERR_STR_(clGetProgramBuildInfo) +#define __GET_COMMAND_QUEUE_INFO_ERR CL_HPP_ERR_STR_(clGetCommandQueueInfo) + +#define __CREATE_CONTEXT_ERR CL_HPP_ERR_STR_(clCreateContext) +#define __CREATE_CONTEXT_FROM_TYPE_ERR CL_HPP_ERR_STR_(clCreateContextFromType) +#define __GET_SUPPORTED_IMAGE_FORMATS_ERR CL_HPP_ERR_STR_(clGetSupportedImageFormats) + +#define __CREATE_BUFFER_ERR CL_HPP_ERR_STR_(clCreateBuffer) +#define __COPY_ERR CL_HPP_ERR_STR_(cl::copy) +#define __CREATE_SUBBUFFER_ERR CL_HPP_ERR_STR_(clCreateSubBuffer) +#define __CREATE_GL_BUFFER_ERR CL_HPP_ERR_STR_(clCreateFromGLBuffer) +#define __CREATE_GL_RENDER_BUFFER_ERR CL_HPP_ERR_STR_(clCreateFromGLBuffer) +#define __GET_GL_OBJECT_INFO_ERR CL_HPP_ERR_STR_(clGetGLObjectInfo) +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 +#define __CREATE_IMAGE_ERR CL_HPP_ERR_STR_(clCreateImage) +#define __CREATE_GL_TEXTURE_ERR CL_HPP_ERR_STR_(clCreateFromGLTexture) +#define __IMAGE_DIMENSION_ERR CL_HPP_ERR_STR_(Incorrect image dimensions) +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 +#define __SET_MEM_OBJECT_DESTRUCTOR_CALLBACK_ERR CL_HPP_ERR_STR_(clSetMemObjectDestructorCallback) + +#define __CREATE_USER_EVENT_ERR CL_HPP_ERR_STR_(clCreateUserEvent) +#define __SET_USER_EVENT_STATUS_ERR CL_HPP_ERR_STR_(clSetUserEventStatus) +#define __SET_EVENT_CALLBACK_ERR CL_HPP_ERR_STR_(clSetEventCallback) +#define __WAIT_FOR_EVENTS_ERR CL_HPP_ERR_STR_(clWaitForEvents) + +#define __CREATE_KERNEL_ERR CL_HPP_ERR_STR_(clCreateKernel) +#define __SET_KERNEL_ARGS_ERR CL_HPP_ERR_STR_(clSetKernelArg) +#define __CREATE_PROGRAM_WITH_SOURCE_ERR CL_HPP_ERR_STR_(clCreateProgramWithSource) +#define __CREATE_PROGRAM_WITH_BINARY_ERR CL_HPP_ERR_STR_(clCreateProgramWithBinary) +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 +#define __CREATE_PROGRAM_WITH_BUILT_IN_KERNELS_ERR CL_HPP_ERR_STR_(clCreateProgramWithBuiltInKernels) +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 +#define __BUILD_PROGRAM_ERR CL_HPP_ERR_STR_(clBuildProgram) +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 +#define __COMPILE_PROGRAM_ERR CL_HPP_ERR_STR_(clCompileProgram) +#define __LINK_PROGRAM_ERR CL_HPP_ERR_STR_(clLinkProgram) +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 +#define __CREATE_KERNELS_IN_PROGRAM_ERR CL_HPP_ERR_STR_(clCreateKernelsInProgram) + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 +#define __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR CL_HPP_ERR_STR_(clCreateCommandQueueWithProperties) +#define __CREATE_SAMPLER_WITH_PROPERTIES_ERR CL_HPP_ERR_STR_(clCreateSamplerWithProperties) +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 200 +#define __SET_COMMAND_QUEUE_PROPERTY_ERR CL_HPP_ERR_STR_(clSetCommandQueueProperty) +#define __ENQUEUE_READ_BUFFER_ERR CL_HPP_ERR_STR_(clEnqueueReadBuffer) +#define __ENQUEUE_READ_BUFFER_RECT_ERR CL_HPP_ERR_STR_(clEnqueueReadBufferRect) +#define __ENQUEUE_WRITE_BUFFER_ERR CL_HPP_ERR_STR_(clEnqueueWriteBuffer) +#define __ENQUEUE_WRITE_BUFFER_RECT_ERR CL_HPP_ERR_STR_(clEnqueueWriteBufferRect) +#define __ENQEUE_COPY_BUFFER_ERR CL_HPP_ERR_STR_(clEnqueueCopyBuffer) +#define __ENQEUE_COPY_BUFFER_RECT_ERR CL_HPP_ERR_STR_(clEnqueueCopyBufferRect) +#define __ENQUEUE_FILL_BUFFER_ERR CL_HPP_ERR_STR_(clEnqueueFillBuffer) +#define __ENQUEUE_READ_IMAGE_ERR CL_HPP_ERR_STR_(clEnqueueReadImage) +#define __ENQUEUE_WRITE_IMAGE_ERR CL_HPP_ERR_STR_(clEnqueueWriteImage) +#define __ENQUEUE_COPY_IMAGE_ERR CL_HPP_ERR_STR_(clEnqueueCopyImage) +#define __ENQUEUE_FILL_IMAGE_ERR CL_HPP_ERR_STR_(clEnqueueFillImage) +#define __ENQUEUE_COPY_IMAGE_TO_BUFFER_ERR CL_HPP_ERR_STR_(clEnqueueCopyImageToBuffer) +#define __ENQUEUE_COPY_BUFFER_TO_IMAGE_ERR CL_HPP_ERR_STR_(clEnqueueCopyBufferToImage) +#define __ENQUEUE_MAP_BUFFER_ERR CL_HPP_ERR_STR_(clEnqueueMapBuffer) +#define __ENQUEUE_MAP_IMAGE_ERR CL_HPP_ERR_STR_(clEnqueueMapImage) +#define __ENQUEUE_UNMAP_MEM_OBJECT_ERR CL_HPP_ERR_STR_(clEnqueueUnMapMemObject) +#define __ENQUEUE_NDRANGE_KERNEL_ERR CL_HPP_ERR_STR_(clEnqueueNDRangeKernel) +#define __ENQUEUE_NATIVE_KERNEL CL_HPP_ERR_STR_(clEnqueueNativeKernel) +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 +#define __ENQUEUE_MIGRATE_MEM_OBJECTS_ERR CL_HPP_ERR_STR_(clEnqueueMigrateMemObjects) +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 + +#define __ENQUEUE_ACQUIRE_GL_ERR CL_HPP_ERR_STR_(clEnqueueAcquireGLObjects) +#define __ENQUEUE_RELEASE_GL_ERR CL_HPP_ERR_STR_(clEnqueueReleaseGLObjects) + +#define __CREATE_PIPE_ERR CL_HPP_ERR_STR_(clCreatePipe) +#define __GET_PIPE_INFO_ERR CL_HPP_ERR_STR_(clGetPipeInfo) + + +#define __RETAIN_ERR CL_HPP_ERR_STR_(Retain Object) +#define __RELEASE_ERR CL_HPP_ERR_STR_(Release Object) +#define __FLUSH_ERR CL_HPP_ERR_STR_(clFlush) +#define __FINISH_ERR CL_HPP_ERR_STR_(clFinish) +#define __VECTOR_CAPACITY_ERR CL_HPP_ERR_STR_(Vector capacity error) + +/** + * CL 1.2 version that uses device fission. + */ +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 +#define __CREATE_SUB_DEVICES_ERR CL_HPP_ERR_STR_(clCreateSubDevices) +#else +#define __CREATE_SUB_DEVICES_ERR CL_HPP_ERR_STR_(clCreateSubDevicesEXT) +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 + +/** + * Deprecated APIs for 1.2 + */ +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) +#define __ENQUEUE_MARKER_ERR CL_HPP_ERR_STR_(clEnqueueMarker) +#define __ENQUEUE_WAIT_FOR_EVENTS_ERR CL_HPP_ERR_STR_(clEnqueueWaitForEvents) +#define __ENQUEUE_BARRIER_ERR CL_HPP_ERR_STR_(clEnqueueBarrier) +#define __UNLOAD_COMPILER_ERR CL_HPP_ERR_STR_(clUnloadCompiler) +#define __CREATE_GL_TEXTURE_2D_ERR CL_HPP_ERR_STR_(clCreateFromGLTexture2D) +#define __CREATE_GL_TEXTURE_3D_ERR CL_HPP_ERR_STR_(clCreateFromGLTexture3D) +#define __CREATE_IMAGE2D_ERR CL_HPP_ERR_STR_(clCreateImage2D) +#define __CREATE_IMAGE3D_ERR CL_HPP_ERR_STR_(clCreateImage3D) +#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + +/** + * Deprecated APIs for 2.0 + */ +#if defined(CL_USE_DEPRECATED_OPENCL_1_2_APIS) +#define __CREATE_COMMAND_QUEUE_ERR CL_HPP_ERR_STR_(clCreateCommandQueue) +#define __ENQUEUE_TASK_ERR CL_HPP_ERR_STR_(clEnqueueTask) +#define __CREATE_SAMPLER_ERR CL_HPP_ERR_STR_(clCreateSampler) +#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + +/** + * CL 1.2 marker and barrier commands + */ +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 +#define __ENQUEUE_MARKER_WAIT_LIST_ERR CL_HPP_ERR_STR_(clEnqueueMarkerWithWaitList) +#define __ENQUEUE_BARRIER_WAIT_LIST_ERR CL_HPP_ERR_STR_(clEnqueueBarrierWithWaitList) +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 + +#endif // CL_HPP_USER_OVERRIDE_ERROR_STRINGS +//! \endcond + + +namespace detail { + +// Generic getInfoHelper. The final parameter is used to guide overload +// resolution: the actual parameter passed is an int, which makes this +// a worse conversion sequence than a specialization that declares the +// parameter as an int. +template +inline cl_int getInfoHelper(Functor f, cl_uint name, T* param, long) +{ + return f(name, sizeof(T), param, NULL); +} + +// Specialized for getInfo +// Assumes that the output vector was correctly resized on the way in +template +inline cl_int getInfoHelper(Func f, cl_uint name, vector>* param, int) +{ + if (name != CL_PROGRAM_BINARIES) { + return CL_INVALID_VALUE; + } + if (param) { + // Create array of pointers, calculate total size and pass pointer array in + size_type numBinaries = param->size(); + vector binariesPointers(numBinaries); + + for (size_type i = 0; i < numBinaries; ++i) + { + binariesPointers[i] = (*param)[i].data(); + } + + cl_int err = f(name, numBinaries * sizeof(unsigned char*), binariesPointers.data(), NULL); + + if (err != CL_SUCCESS) { + return err; + } + } + + + return CL_SUCCESS; +} + +// Specialized getInfoHelper for vector params +template +inline cl_int getInfoHelper(Func f, cl_uint name, vector* param, long) +{ + size_type required; + cl_int err = f(name, 0, NULL, &required); + if (err != CL_SUCCESS) { + return err; + } + const size_type elements = required / sizeof(T); + + // Temporary to avoid changing param on an error + vector localData(elements); + err = f(name, required, localData.data(), NULL); + if (err != CL_SUCCESS) { + return err; + } + if (param) { + *param = std::move(localData); + } + + return CL_SUCCESS; +} + +/* Specialization for reference-counted types. This depends on the + * existence of Wrapper::cl_type, and none of the other types having the + * cl_type member. Note that simplify specifying the parameter as Wrapper + * does not work, because when using a derived type (e.g. Context) the generic + * template will provide a better match. + */ +template +inline cl_int getInfoHelper( + Func f, cl_uint name, vector* param, int, typename T::cl_type = 0) +{ + size_type required; + cl_int err = f(name, 0, NULL, &required); + if (err != CL_SUCCESS) { + return err; + } + + const size_type elements = required / sizeof(typename T::cl_type); + + vector value(elements); + err = f(name, required, value.data(), NULL); + if (err != CL_SUCCESS) { + return err; + } + + if (param) { + // Assign to convert CL type to T for each element + param->resize(elements); + + // Assign to param, constructing with retain behaviour + // to correctly capture each underlying CL object + for (size_type i = 0; i < elements; i++) { + (*param)[i] = T(value[i], true); + } + } + return CL_SUCCESS; +} + +// Specialized GetInfoHelper for string params +template +inline cl_int getInfoHelper(Func f, cl_uint name, string* param, long) +{ + size_type required; + cl_int err = f(name, 0, NULL, &required); + if (err != CL_SUCCESS) { + return err; + } + + // std::string has a constant data member + // a char vector does not + if (required > 0) { + vector value(required); + err = f(name, required, value.data(), NULL); + if (err != CL_SUCCESS) { + return err; + } + if (param) { + param->assign(begin(value), prev(end(value))); + } + } + else if (param) { + param->assign(""); + } + return CL_SUCCESS; +} + +// Specialized GetInfoHelper for clsize_t params +template +inline cl_int getInfoHelper(Func f, cl_uint name, array* param, long) +{ + size_type required; + cl_int err = f(name, 0, NULL, &required); + if (err != CL_SUCCESS) { + return err; + } + + size_type elements = required / sizeof(size_type); + vector value(elements, 0); + + err = f(name, required, value.data(), NULL); + if (err != CL_SUCCESS) { + return err; + } + + // Bound the copy with N to prevent overruns + // if passed N > than the amount copied + if (elements > N) { + elements = N; + } + for (size_type i = 0; i < elements; ++i) { + (*param)[i] = value[i]; + } + + return CL_SUCCESS; +} + +template struct ReferenceHandler; + +/* Specialization for reference-counted types. This depends on the + * existence of Wrapper::cl_type, and none of the other types having the + * cl_type member. Note that simplify specifying the parameter as Wrapper + * does not work, because when using a derived type (e.g. Context) the generic + * template will provide a better match. + */ +template +inline cl_int getInfoHelper(Func f, cl_uint name, T* param, int, typename T::cl_type = 0) +{ + typename T::cl_type value; + cl_int err = f(name, sizeof(value), &value, NULL); + if (err != CL_SUCCESS) { + return err; + } + *param = value; + if (value != NULL) + { + err = param->retain(); + if (err != CL_SUCCESS) { + return err; + } + } + return CL_SUCCESS; +} + +#define CL_HPP_PARAM_NAME_INFO_1_0_(F) \ + F(cl_platform_info, CL_PLATFORM_PROFILE, string) \ + F(cl_platform_info, CL_PLATFORM_VERSION, string) \ + F(cl_platform_info, CL_PLATFORM_NAME, string) \ + F(cl_platform_info, CL_PLATFORM_VENDOR, string) \ + F(cl_platform_info, CL_PLATFORM_EXTENSIONS, string) \ + \ + F(cl_device_info, CL_DEVICE_TYPE, cl_device_type) \ + F(cl_device_info, CL_DEVICE_VENDOR_ID, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_COMPUTE_UNITS, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_WORK_GROUP_SIZE, size_type) \ + F(cl_device_info, CL_DEVICE_MAX_WORK_ITEM_SIZES, cl::vector) \ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_CLOCK_FREQUENCY, cl_uint) \ + F(cl_device_info, CL_DEVICE_ADDRESS_BITS, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_READ_IMAGE_ARGS, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_MEM_ALLOC_SIZE, cl_ulong) \ + F(cl_device_info, CL_DEVICE_IMAGE2D_MAX_WIDTH, size_type) \ + F(cl_device_info, CL_DEVICE_IMAGE2D_MAX_HEIGHT, size_type) \ + F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_WIDTH, size_type) \ + F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_HEIGHT, size_type) \ + F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_DEPTH, size_type) \ + F(cl_device_info, CL_DEVICE_IMAGE_SUPPORT, cl_bool) \ + F(cl_device_info, CL_DEVICE_MAX_PARAMETER_SIZE, size_type) \ + F(cl_device_info, CL_DEVICE_MAX_SAMPLERS, cl_uint) \ + F(cl_device_info, CL_DEVICE_MEM_BASE_ADDR_ALIGN, cl_uint) \ + F(cl_device_info, CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE, cl_uint) \ + F(cl_device_info, CL_DEVICE_SINGLE_FP_CONFIG, cl_device_fp_config) \ + F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE, cl_device_mem_cache_type) \ + F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE, cl_uint)\ + F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, cl_ulong) \ + F(cl_device_info, CL_DEVICE_GLOBAL_MEM_SIZE, cl_ulong) \ + F(cl_device_info, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, cl_ulong) \ + F(cl_device_info, CL_DEVICE_MAX_CONSTANT_ARGS, cl_uint) \ + F(cl_device_info, CL_DEVICE_LOCAL_MEM_TYPE, cl_device_local_mem_type) \ + F(cl_device_info, CL_DEVICE_LOCAL_MEM_SIZE, cl_ulong) \ + F(cl_device_info, CL_DEVICE_ERROR_CORRECTION_SUPPORT, cl_bool) \ + F(cl_device_info, CL_DEVICE_PROFILING_TIMER_RESOLUTION, size_type) \ + F(cl_device_info, CL_DEVICE_ENDIAN_LITTLE, cl_bool) \ + F(cl_device_info, CL_DEVICE_AVAILABLE, cl_bool) \ + F(cl_device_info, CL_DEVICE_COMPILER_AVAILABLE, cl_bool) \ + F(cl_device_info, CL_DEVICE_EXECUTION_CAPABILITIES, cl_device_exec_capabilities) \ + F(cl_device_info, CL_DEVICE_PLATFORM, cl_platform_id) \ + F(cl_device_info, CL_DEVICE_NAME, string) \ + F(cl_device_info, CL_DEVICE_VENDOR, string) \ + F(cl_device_info, CL_DRIVER_VERSION, string) \ + F(cl_device_info, CL_DEVICE_PROFILE, string) \ + F(cl_device_info, CL_DEVICE_VERSION, string) \ + F(cl_device_info, CL_DEVICE_EXTENSIONS, string) \ + \ + F(cl_context_info, CL_CONTEXT_REFERENCE_COUNT, cl_uint) \ + F(cl_context_info, CL_CONTEXT_DEVICES, cl::vector) \ + F(cl_context_info, CL_CONTEXT_PROPERTIES, cl::vector) \ + \ + F(cl_event_info, CL_EVENT_COMMAND_QUEUE, cl::CommandQueue) \ + F(cl_event_info, CL_EVENT_COMMAND_TYPE, cl_command_type) \ + F(cl_event_info, CL_EVENT_REFERENCE_COUNT, cl_uint) \ + F(cl_event_info, CL_EVENT_COMMAND_EXECUTION_STATUS, cl_int) \ + \ + F(cl_profiling_info, CL_PROFILING_COMMAND_QUEUED, cl_ulong) \ + F(cl_profiling_info, CL_PROFILING_COMMAND_SUBMIT, cl_ulong) \ + F(cl_profiling_info, CL_PROFILING_COMMAND_START, cl_ulong) \ + F(cl_profiling_info, CL_PROFILING_COMMAND_END, cl_ulong) \ + \ + F(cl_mem_info, CL_MEM_TYPE, cl_mem_object_type) \ + F(cl_mem_info, CL_MEM_FLAGS, cl_mem_flags) \ + F(cl_mem_info, CL_MEM_SIZE, size_type) \ + F(cl_mem_info, CL_MEM_HOST_PTR, void*) \ + F(cl_mem_info, CL_MEM_MAP_COUNT, cl_uint) \ + F(cl_mem_info, CL_MEM_REFERENCE_COUNT, cl_uint) \ + F(cl_mem_info, CL_MEM_CONTEXT, cl::Context) \ + \ + F(cl_image_info, CL_IMAGE_FORMAT, cl_image_format) \ + F(cl_image_info, CL_IMAGE_ELEMENT_SIZE, size_type) \ + F(cl_image_info, CL_IMAGE_ROW_PITCH, size_type) \ + F(cl_image_info, CL_IMAGE_SLICE_PITCH, size_type) \ + F(cl_image_info, CL_IMAGE_WIDTH, size_type) \ + F(cl_image_info, CL_IMAGE_HEIGHT, size_type) \ + F(cl_image_info, CL_IMAGE_DEPTH, size_type) \ + \ + F(cl_sampler_info, CL_SAMPLER_REFERENCE_COUNT, cl_uint) \ + F(cl_sampler_info, CL_SAMPLER_CONTEXT, cl::Context) \ + F(cl_sampler_info, CL_SAMPLER_NORMALIZED_COORDS, cl_bool) \ + F(cl_sampler_info, CL_SAMPLER_ADDRESSING_MODE, cl_addressing_mode) \ + F(cl_sampler_info, CL_SAMPLER_FILTER_MODE, cl_filter_mode) \ + \ + F(cl_program_info, CL_PROGRAM_REFERENCE_COUNT, cl_uint) \ + F(cl_program_info, CL_PROGRAM_CONTEXT, cl::Context) \ + F(cl_program_info, CL_PROGRAM_NUM_DEVICES, cl_uint) \ + F(cl_program_info, CL_PROGRAM_DEVICES, cl::vector) \ + F(cl_program_info, CL_PROGRAM_SOURCE, string) \ + F(cl_program_info, CL_PROGRAM_BINARY_SIZES, cl::vector) \ + F(cl_program_info, CL_PROGRAM_BINARIES, cl::vector>) \ + \ + F(cl_program_build_info, CL_PROGRAM_BUILD_STATUS, cl_build_status) \ + F(cl_program_build_info, CL_PROGRAM_BUILD_OPTIONS, string) \ + F(cl_program_build_info, CL_PROGRAM_BUILD_LOG, string) \ + \ + F(cl_kernel_info, CL_KERNEL_FUNCTION_NAME, string) \ + F(cl_kernel_info, CL_KERNEL_NUM_ARGS, cl_uint) \ + F(cl_kernel_info, CL_KERNEL_REFERENCE_COUNT, cl_uint) \ + F(cl_kernel_info, CL_KERNEL_CONTEXT, cl::Context) \ + F(cl_kernel_info, CL_KERNEL_PROGRAM, cl::Program) \ + \ + F(cl_kernel_work_group_info, CL_KERNEL_WORK_GROUP_SIZE, size_type) \ + F(cl_kernel_work_group_info, CL_KERNEL_COMPILE_WORK_GROUP_SIZE, cl::detail::size_t_array) \ + F(cl_kernel_work_group_info, CL_KERNEL_LOCAL_MEM_SIZE, cl_ulong) \ + \ + F(cl_command_queue_info, CL_QUEUE_CONTEXT, cl::Context) \ + F(cl_command_queue_info, CL_QUEUE_DEVICE, cl::Device) \ + F(cl_command_queue_info, CL_QUEUE_REFERENCE_COUNT, cl_uint) \ + F(cl_command_queue_info, CL_QUEUE_PROPERTIES, cl_command_queue_properties) + + +#define CL_HPP_PARAM_NAME_INFO_1_1_(F) \ + F(cl_context_info, CL_CONTEXT_NUM_DEVICES, cl_uint)\ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_INT, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF, cl_uint) \ + F(cl_device_info, CL_DEVICE_DOUBLE_FP_CONFIG, cl_device_fp_config) \ + F(cl_device_info, CL_DEVICE_HALF_FP_CONFIG, cl_device_fp_config) \ + F(cl_device_info, CL_DEVICE_OPENCL_C_VERSION, string) \ + \ + F(cl_mem_info, CL_MEM_ASSOCIATED_MEMOBJECT, cl::Memory) \ + F(cl_mem_info, CL_MEM_OFFSET, size_type) \ + \ + F(cl_kernel_work_group_info, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, size_type) \ + F(cl_kernel_work_group_info, CL_KERNEL_PRIVATE_MEM_SIZE, cl_ulong) \ + \ + F(cl_event_info, CL_EVENT_CONTEXT, cl::Context) + +#define CL_HPP_PARAM_NAME_INFO_1_2_(F) \ + F(cl_program_info, CL_PROGRAM_NUM_KERNELS, size_type) \ + F(cl_program_info, CL_PROGRAM_KERNEL_NAMES, string) \ + \ + F(cl_program_build_info, CL_PROGRAM_BINARY_TYPE, cl_program_binary_type) \ + \ + F(cl_kernel_info, CL_KERNEL_ATTRIBUTES, string) \ + \ + F(cl_kernel_arg_info, CL_KERNEL_ARG_ADDRESS_QUALIFIER, cl_kernel_arg_address_qualifier) \ + F(cl_kernel_arg_info, CL_KERNEL_ARG_ACCESS_QUALIFIER, cl_kernel_arg_access_qualifier) \ + F(cl_kernel_arg_info, CL_KERNEL_ARG_TYPE_NAME, string) \ + F(cl_kernel_arg_info, CL_KERNEL_ARG_NAME, string) \ + F(cl_kernel_arg_info, CL_KERNEL_ARG_TYPE_QUALIFIER, cl_kernel_arg_type_qualifier) \ + \ + F(cl_device_info, CL_DEVICE_PARENT_DEVICE, cl::Device) \ + F(cl_device_info, CL_DEVICE_PARTITION_PROPERTIES, cl::vector) \ + F(cl_device_info, CL_DEVICE_PARTITION_TYPE, cl::vector) \ + F(cl_device_info, CL_DEVICE_REFERENCE_COUNT, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_INTEROP_USER_SYNC, size_type) \ + F(cl_device_info, CL_DEVICE_PARTITION_AFFINITY_DOMAIN, cl_device_affinity_domain) \ + F(cl_device_info, CL_DEVICE_BUILT_IN_KERNELS, string) \ + \ + F(cl_image_info, CL_IMAGE_ARRAY_SIZE, size_type) \ + F(cl_image_info, CL_IMAGE_NUM_MIP_LEVELS, cl_uint) \ + F(cl_image_info, CL_IMAGE_NUM_SAMPLES, cl_uint) + +#define CL_HPP_PARAM_NAME_INFO_2_0_(F) \ + F(cl_device_info, CL_DEVICE_QUEUE_ON_HOST_PROPERTIES, cl_command_queue_properties) \ + F(cl_device_info, CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES, cl_command_queue_properties) \ + F(cl_device_info, CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE, cl_uint) \ + F(cl_device_info, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_ON_DEVICE_QUEUES, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_ON_DEVICE_EVENTS, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_PIPE_ARGS, cl_uint) \ + F(cl_device_info, CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS, cl_uint) \ + F(cl_device_info, CL_DEVICE_PIPE_MAX_PACKET_SIZE, cl_uint) \ + F(cl_device_info, CL_DEVICE_SVM_CAPABILITIES, cl_device_svm_capabilities) \ + F(cl_device_info, CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT, cl_uint) \ + F(cl_command_queue_info, CL_QUEUE_SIZE, cl_uint) \ + F(cl_mem_info, CL_MEM_USES_SVM_POINTER, cl_bool) \ + F(cl_program_build_info, CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE, size_type) \ + F(cl_pipe_info, CL_PIPE_PACKET_SIZE, cl_uint) \ + F(cl_pipe_info, CL_PIPE_MAX_PACKETS, cl_uint) + +#define CL_HPP_PARAM_NAME_DEVICE_FISSION_(F) \ + F(cl_device_info, CL_DEVICE_PARENT_DEVICE_EXT, cl_device_id) \ + F(cl_device_info, CL_DEVICE_PARTITION_TYPES_EXT, cl::vector) \ + F(cl_device_info, CL_DEVICE_AFFINITY_DOMAINS_EXT, cl::vector) \ + F(cl_device_info, CL_DEVICE_REFERENCE_COUNT_EXT , cl_uint) \ + F(cl_device_info, CL_DEVICE_PARTITION_STYLE_EXT, cl::vector) + +template +struct param_traits {}; + +#define CL_HPP_DECLARE_PARAM_TRAITS_(token, param_name, T) \ +struct token; \ +template<> \ +struct param_traits \ +{ \ + enum { value = param_name }; \ + typedef T param_type; \ +}; + +CL_HPP_PARAM_NAME_INFO_1_0_(CL_HPP_DECLARE_PARAM_TRAITS_) +#if CL_HPP_TARGET_OPENCL_VERSION >= 110 +CL_HPP_PARAM_NAME_INFO_1_1_(CL_HPP_DECLARE_PARAM_TRAITS_) +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 110 +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 +CL_HPP_PARAM_NAME_INFO_1_2_(CL_HPP_DECLARE_PARAM_TRAITS_) +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 110 +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 +CL_HPP_PARAM_NAME_INFO_2_0_(CL_HPP_DECLARE_PARAM_TRAITS_) +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 110 + + +// Flags deprecated in OpenCL 2.0 +#define CL_HPP_PARAM_NAME_INFO_1_0_DEPRECATED_IN_2_0_(F) \ + F(cl_device_info, CL_DEVICE_QUEUE_PROPERTIES, cl_command_queue_properties) + +#define CL_HPP_PARAM_NAME_INFO_1_1_DEPRECATED_IN_2_0_(F) \ + F(cl_device_info, CL_DEVICE_HOST_UNIFIED_MEMORY, cl_bool) + +#define CL_HPP_PARAM_NAME_INFO_1_2_DEPRECATED_IN_2_0_(F) \ + F(cl_image_info, CL_IMAGE_BUFFER, cl::Buffer) + +// Include deprecated query flags based on versions +// Only include deprecated 1.0 flags if 2.0 not active as there is an enum clash +#if CL_HPP_TARGET_OPENCL_VERSION > 100 && CL_HPP_MINIMUM_OPENCL_VERSION < 200 && CL_HPP_TARGET_OPENCL_VERSION < 200 +CL_HPP_PARAM_NAME_INFO_1_0_DEPRECATED_IN_2_0_(CL_HPP_DECLARE_PARAM_TRAITS_) +#endif // CL_HPP_MINIMUM_OPENCL_VERSION < 110 +#if CL_HPP_TARGET_OPENCL_VERSION > 110 && CL_HPP_MINIMUM_OPENCL_VERSION < 200 +CL_HPP_PARAM_NAME_INFO_1_1_DEPRECATED_IN_2_0_(CL_HPP_DECLARE_PARAM_TRAITS_) +#endif // CL_HPP_MINIMUM_OPENCL_VERSION < 120 +#if CL_HPP_TARGET_OPENCL_VERSION > 120 && CL_HPP_MINIMUM_OPENCL_VERSION < 200 +CL_HPP_PARAM_NAME_INFO_1_2_DEPRECATED_IN_2_0_(CL_HPP_DECLARE_PARAM_TRAITS_) +#endif // CL_HPP_MINIMUM_OPENCL_VERSION < 200 + +#if defined(CL_HPP_USE_CL_DEVICE_FISSION) +CL_HPP_PARAM_NAME_DEVICE_FISSION_(CL_HPP_DECLARE_PARAM_TRAITS_); +#endif // CL_HPP_USE_CL_DEVICE_FISSION + +#ifdef CL_PLATFORM_ICD_SUFFIX_KHR +CL_HPP_DECLARE_PARAM_TRAITS_(cl_platform_info, CL_PLATFORM_ICD_SUFFIX_KHR, string) +#endif + +#ifdef CL_DEVICE_PROFILING_TIMER_OFFSET_AMD +CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_PROFILING_TIMER_OFFSET_AMD, cl_ulong) +#endif + +#ifdef CL_DEVICE_GLOBAL_FREE_MEMORY_AMD +CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_GLOBAL_FREE_MEMORY_AMD, vector) +#endif +#ifdef CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD +CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_SIMD_WIDTH_AMD +CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_SIMD_WIDTH_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD +CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_WAVEFRONT_WIDTH_AMD +CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_WAVEFRONT_WIDTH_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD +CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD +CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD +CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD +CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_LOCAL_MEM_BANKS_AMD +CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_LOCAL_MEM_BANKS_AMD, cl_uint) +#endif + +#ifdef CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV +CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV, cl_uint) +#endif +#ifdef CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV +CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV, cl_uint) +#endif +#ifdef CL_DEVICE_REGISTERS_PER_BLOCK_NV +CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_REGISTERS_PER_BLOCK_NV, cl_uint) +#endif +#ifdef CL_DEVICE_WARP_SIZE_NV +CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_WARP_SIZE_NV, cl_uint) +#endif +#ifdef CL_DEVICE_GPU_OVERLAP_NV +CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_GPU_OVERLAP_NV, cl_bool) +#endif +#ifdef CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV +CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV, cl_bool) +#endif +#ifdef CL_DEVICE_INTEGRATED_MEMORY_NV +CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_INTEGRATED_MEMORY_NV, cl_bool) +#endif + +// Convenience functions + +template +inline cl_int +getInfo(Func f, cl_uint name, T* param) +{ + return getInfoHelper(f, name, param, 0); +} + +template +struct GetInfoFunctor0 +{ + Func f_; const Arg0& arg0_; + cl_int operator ()( + cl_uint param, size_type size, void* value, size_type* size_ret) + { return f_(arg0_, param, size, value, size_ret); } +}; + +template +struct GetInfoFunctor1 +{ + Func f_; const Arg0& arg0_; const Arg1& arg1_; + cl_int operator ()( + cl_uint param, size_type size, void* value, size_type* size_ret) + { return f_(arg0_, arg1_, param, size, value, size_ret); } +}; + +template +inline cl_int +getInfo(Func f, const Arg0& arg0, cl_uint name, T* param) +{ + GetInfoFunctor0 f0 = { f, arg0 }; + return getInfoHelper(f0, name, param, 0); +} + +template +inline cl_int +getInfo(Func f, const Arg0& arg0, const Arg1& arg1, cl_uint name, T* param) +{ + GetInfoFunctor1 f0 = { f, arg0, arg1 }; + return getInfoHelper(f0, name, param, 0); +} + + +template +struct ReferenceHandler +{ }; + +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 +/** + * OpenCL 1.2 devices do have retain/release. + */ +template <> +struct ReferenceHandler +{ + /** + * Retain the device. + * \param device A valid device created using createSubDevices + * \return + * CL_SUCCESS if the function executed successfully. + * CL_INVALID_DEVICE if device was not a valid subdevice + * CL_OUT_OF_RESOURCES + * CL_OUT_OF_HOST_MEMORY + */ + static cl_int retain(cl_device_id device) + { return ::clRetainDevice(device); } + /** + * Retain the device. + * \param device A valid device created using createSubDevices + * \return + * CL_SUCCESS if the function executed successfully. + * CL_INVALID_DEVICE if device was not a valid subdevice + * CL_OUT_OF_RESOURCES + * CL_OUT_OF_HOST_MEMORY + */ + static cl_int release(cl_device_id device) + { return ::clReleaseDevice(device); } +}; +#else // CL_HPP_TARGET_OPENCL_VERSION >= 120 +/** + * OpenCL 1.1 devices do not have retain/release. + */ +template <> +struct ReferenceHandler +{ + // cl_device_id does not have retain(). + static cl_int retain(cl_device_id) + { return CL_SUCCESS; } + // cl_device_id does not have release(). + static cl_int release(cl_device_id) + { return CL_SUCCESS; } +}; +#endif // ! (CL_HPP_TARGET_OPENCL_VERSION >= 120) + +template <> +struct ReferenceHandler +{ + // cl_platform_id does not have retain(). + static cl_int retain(cl_platform_id) + { return CL_SUCCESS; } + // cl_platform_id does not have release(). + static cl_int release(cl_platform_id) + { return CL_SUCCESS; } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_context context) + { return ::clRetainContext(context); } + static cl_int release(cl_context context) + { return ::clReleaseContext(context); } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_command_queue queue) + { return ::clRetainCommandQueue(queue); } + static cl_int release(cl_command_queue queue) + { return ::clReleaseCommandQueue(queue); } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_mem memory) + { return ::clRetainMemObject(memory); } + static cl_int release(cl_mem memory) + { return ::clReleaseMemObject(memory); } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_sampler sampler) + { return ::clRetainSampler(sampler); } + static cl_int release(cl_sampler sampler) + { return ::clReleaseSampler(sampler); } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_program program) + { return ::clRetainProgram(program); } + static cl_int release(cl_program program) + { return ::clReleaseProgram(program); } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_kernel kernel) + { return ::clRetainKernel(kernel); } + static cl_int release(cl_kernel kernel) + { return ::clReleaseKernel(kernel); } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_event event) + { return ::clRetainEvent(event); } + static cl_int release(cl_event event) + { return ::clReleaseEvent(event); } +}; + + +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 && CL_HPP_MINIMUM_OPENCL_VERSION < 120 +// Extracts version number with major in the upper 16 bits, minor in the lower 16 +static cl_uint getVersion(const vector &versionInfo) +{ + int highVersion = 0; + int lowVersion = 0; + int index = 7; + while(versionInfo[index] != '.' ) { + highVersion *= 10; + highVersion += versionInfo[index]-'0'; + ++index; + } + ++index; + while(versionInfo[index] != ' ' && versionInfo[index] != '\0') { + lowVersion *= 10; + lowVersion += versionInfo[index]-'0'; + ++index; + } + return (highVersion << 16) | lowVersion; +} + +static cl_uint getPlatformVersion(cl_platform_id platform) +{ + size_type size = 0; + clGetPlatformInfo(platform, CL_PLATFORM_VERSION, 0, NULL, &size); + + vector versionInfo(size); + clGetPlatformInfo(platform, CL_PLATFORM_VERSION, size, versionInfo.data(), &size); + return getVersion(versionInfo); +} + +static cl_uint getDevicePlatformVersion(cl_device_id device) +{ + cl_platform_id platform; + clGetDeviceInfo(device, CL_DEVICE_PLATFORM, sizeof(platform), &platform, NULL); + return getPlatformVersion(platform); +} + +static cl_uint getContextPlatformVersion(cl_context context) +{ + // The platform cannot be queried directly, so we first have to grab a + // device and obtain its context + size_type size = 0; + clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &size); + if (size == 0) + return 0; + vector devices(size/sizeof(cl_device_id)); + clGetContextInfo(context, CL_CONTEXT_DEVICES, size, devices.data(), NULL); + return getDevicePlatformVersion(devices[0]); +} +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 && CL_HPP_MINIMUM_OPENCL_VERSION < 120 + +template +class Wrapper +{ +public: + typedef T cl_type; + +protected: + cl_type object_; + +public: + Wrapper() : object_(NULL) { } + + Wrapper(const cl_type &obj, bool retainObject) : object_(obj) + { + if (retainObject) { + detail::errHandler(retain(), __RETAIN_ERR); + } + } + + ~Wrapper() + { + if (object_ != NULL) { release(); } + } + + Wrapper(const Wrapper& rhs) + { + object_ = rhs.object_; + detail::errHandler(retain(), __RETAIN_ERR); + } + + Wrapper(Wrapper&& rhs) CL_HPP_NOEXCEPT_ + { + object_ = rhs.object_; + rhs.object_ = NULL; + } + + Wrapper& operator = (const Wrapper& rhs) + { + if (this != &rhs) { + detail::errHandler(release(), __RELEASE_ERR); + object_ = rhs.object_; + detail::errHandler(retain(), __RETAIN_ERR); + } + return *this; + } + + Wrapper& operator = (Wrapper&& rhs) + { + if (this != &rhs) { + detail::errHandler(release(), __RELEASE_ERR); + object_ = rhs.object_; + rhs.object_ = NULL; + } + return *this; + } + + Wrapper& operator = (const cl_type &rhs) + { + detail::errHandler(release(), __RELEASE_ERR); + object_ = rhs; + return *this; + } + + const cl_type& operator ()() const { return object_; } + + cl_type& operator ()() { return object_; } + + const cl_type get() const { return object_; } + + cl_type get() { return object_; } + + +protected: + template + friend inline cl_int getInfoHelper(Func, cl_uint, U*, int, typename U::cl_type); + + cl_int retain() const + { + if (object_ != nullptr) { + return ReferenceHandler::retain(object_); + } + else { + return CL_SUCCESS; + } + } + + cl_int release() const + { + if (object_ != nullptr) { + return ReferenceHandler::release(object_); + } + else { + return CL_SUCCESS; + } + } +}; + +template <> +class Wrapper +{ +public: + typedef cl_device_id cl_type; + +protected: + cl_type object_; + bool referenceCountable_; + + static bool isReferenceCountable(cl_device_id device) + { + bool retVal = false; +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 +#if CL_HPP_MINIMUM_OPENCL_VERSION < 120 + if (device != NULL) { + int version = getDevicePlatformVersion(device); + if(version > ((1 << 16) + 1)) { + retVal = true; + } + } +#else // CL_HPP_MINIMUM_OPENCL_VERSION < 120 + retVal = true; +#endif // CL_HPP_MINIMUM_OPENCL_VERSION < 120 +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 + return retVal; + } + +public: + Wrapper() : object_(NULL), referenceCountable_(false) + { + } + + Wrapper(const cl_type &obj, bool retainObject) : + object_(obj), + referenceCountable_(false) + { + referenceCountable_ = isReferenceCountable(obj); + + if (retainObject) { + detail::errHandler(retain(), __RETAIN_ERR); + } + } + + ~Wrapper() + { + release(); + } + + Wrapper(const Wrapper& rhs) + { + object_ = rhs.object_; + referenceCountable_ = isReferenceCountable(object_); + detail::errHandler(retain(), __RETAIN_ERR); + } + + Wrapper(Wrapper&& rhs) CL_HPP_NOEXCEPT_ + { + object_ = rhs.object_; + referenceCountable_ = rhs.referenceCountable_; + rhs.object_ = NULL; + rhs.referenceCountable_ = false; + } + + Wrapper& operator = (const Wrapper& rhs) + { + if (this != &rhs) { + detail::errHandler(release(), __RELEASE_ERR); + object_ = rhs.object_; + referenceCountable_ = rhs.referenceCountable_; + detail::errHandler(retain(), __RETAIN_ERR); + } + return *this; + } + + Wrapper& operator = (Wrapper&& rhs) + { + if (this != &rhs) { + detail::errHandler(release(), __RELEASE_ERR); + object_ = rhs.object_; + referenceCountable_ = rhs.referenceCountable_; + rhs.object_ = NULL; + rhs.referenceCountable_ = false; + } + return *this; + } + + Wrapper& operator = (const cl_type &rhs) + { + detail::errHandler(release(), __RELEASE_ERR); + object_ = rhs; + referenceCountable_ = isReferenceCountable(object_); + return *this; + } + + const cl_type& operator ()() const { return object_; } + + cl_type& operator ()() { return object_; } + + const cl_type get() const { return object_; } + + cl_type get() { return object_; } + +protected: + template + friend inline cl_int getInfoHelper(Func, cl_uint, U*, int, typename U::cl_type); + + template + friend inline cl_int getInfoHelper(Func, cl_uint, vector*, int, typename U::cl_type); + + cl_int retain() const + { + if( object_ != nullptr && referenceCountable_ ) { + return ReferenceHandler::retain(object_); + } + else { + return CL_SUCCESS; + } + } + + cl_int release() const + { + if (object_ != nullptr && referenceCountable_) { + return ReferenceHandler::release(object_); + } + else { + return CL_SUCCESS; + } + } +}; + +template +inline bool operator==(const Wrapper &lhs, const Wrapper &rhs) +{ + return lhs() == rhs(); +} + +template +inline bool operator!=(const Wrapper &lhs, const Wrapper &rhs) +{ + return !operator==(lhs, rhs); +} + +} // namespace detail +//! \endcond + + +using BuildLogType = vector::param_type>>; +#if defined(CL_HPP_ENABLE_EXCEPTIONS) +/** +* Exception class for build errors to carry build info +*/ +class BuildError : public Error +{ +private: + BuildLogType buildLogs; +public: + BuildError(cl_int err, const char * errStr, const BuildLogType &vec) : Error(err, errStr), buildLogs(vec) + { + } + + BuildLogType getBuildLog() const + { + return buildLogs; + } +}; +namespace detail { + static inline cl_int buildErrHandler( + cl_int err, + const char * errStr, + const BuildLogType &buildLogs) + { + if (err != CL_SUCCESS) { + throw BuildError(err, errStr, buildLogs); + } + return err; + } +} // namespace detail + +#else +namespace detail { + static inline cl_int buildErrHandler( + cl_int err, + const char * errStr, + const BuildLogType &buildLogs) + { + (void)buildLogs; // suppress unused variable warning + (void)errStr; + return err; + } +} // namespace detail +#endif // #if defined(CL_HPP_ENABLE_EXCEPTIONS) + + +/*! \struct ImageFormat + * \brief Adds constructors and member functions for cl_image_format. + * + * \see cl_image_format + */ +struct ImageFormat : public cl_image_format +{ + //! \brief Default constructor - performs no initialization. + ImageFormat(){} + + //! \brief Initializing constructor. + ImageFormat(cl_channel_order order, cl_channel_type type) + { + image_channel_order = order; + image_channel_data_type = type; + } + + //! \brief Assignment operator. + ImageFormat& operator = (const ImageFormat& rhs) + { + if (this != &rhs) { + this->image_channel_data_type = rhs.image_channel_data_type; + this->image_channel_order = rhs.image_channel_order; + } + return *this; + } +}; + +/*! \brief Class interface for cl_device_id. + * + * \note Copies of these objects are inexpensive, since they don't 'own' + * any underlying resources or data structures. + * + * \see cl_device_id + */ +class Device : public detail::Wrapper +{ +private: + static std::once_flag default_initialized_; + static Device default_; + static cl_int default_error_; + + /*! \brief Create the default context. + * + * This sets @c default_ and @c default_error_. It does not throw + * @c cl::Error. + */ + static void makeDefault(); + + /*! \brief Create the default platform from a provided platform. + * + * This sets @c default_. It does not throw + * @c cl::Error. + */ + static void makeDefaultProvided(const Device &p) { + default_ = p; + } + +public: +#ifdef CL_HPP_UNIT_TEST_ENABLE + /*! \brief Reset the default. + * + * This sets @c default_ to an empty value to support cleanup in + * the unit test framework. + * This function is not thread safe. + */ + static void unitTestClearDefault() { + default_ = Device(); + } +#endif // #ifdef CL_HPP_UNIT_TEST_ENABLE + + //! \brief Default constructor - initializes to NULL. + Device() : detail::Wrapper() { } + + /*! \brief Constructor from cl_device_id. + * + * This simply copies the device ID value, which is an inexpensive operation. + */ + explicit Device(const cl_device_id &device, bool retainObject = false) : + detail::Wrapper(device, retainObject) { } + + /*! \brief Returns the first device on the default context. + * + * \see Context::getDefault() + */ + static Device getDefault( + cl_int *errResult = NULL) + { + std::call_once(default_initialized_, makeDefault); + detail::errHandler(default_error_); + if (errResult != NULL) { + *errResult = default_error_; + } + return default_; + } + + /** + * Modify the default device to be used by + * subsequent operations. + * Will only set the default if no default was previously created. + * @return updated default device. + * Should be compared to the passed value to ensure that it was updated. + */ + static Device setDefault(const Device &default_device) + { + std::call_once(default_initialized_, makeDefaultProvided, std::cref(default_device)); + detail::errHandler(default_error_); + return default_; + } + + /*! \brief Assignment operator from cl_device_id. + * + * This simply copies the device ID value, which is an inexpensive operation. + */ + Device& operator = (const cl_device_id& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Device(const Device& dev) : detail::Wrapper(dev) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Device& operator = (const Device &dev) + { + detail::Wrapper::operator=(dev); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Device(Device&& dev) CL_HPP_NOEXCEPT_ : detail::Wrapper(std::move(dev)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Device& operator = (Device &&dev) + { + detail::Wrapper::operator=(std::move(dev)); + return *this; + } + + //! \brief Wrapper for clGetDeviceInfo(). + template + cl_int getInfo(cl_device_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetDeviceInfo, object_, name, param), + __GET_DEVICE_INFO_ERR); + } + + //! \brief Wrapper for clGetDeviceInfo() that returns by value. + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_device_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + /** + * CL 1.2 version + */ +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 + //! \brief Wrapper for clCreateSubDevices(). + cl_int createSubDevices( + const cl_device_partition_property * properties, + vector* devices) + { + cl_uint n = 0; + cl_int err = clCreateSubDevices(object_, properties, 0, NULL, &n); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __CREATE_SUB_DEVICES_ERR); + } + + vector ids(n); + err = clCreateSubDevices(object_, properties, n, ids.data(), NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __CREATE_SUB_DEVICES_ERR); + } + + // Cannot trivially assign because we need to capture intermediates + // with safe construction + if (devices) { + devices->resize(ids.size()); + + // Assign to param, constructing with retain behaviour + // to correctly capture each underlying CL object + for (size_type i = 0; i < ids.size(); i++) { + // We do not need to retain because this device is being created + // by the runtime + (*devices)[i] = Device(ids[i], false); + } + } + + return CL_SUCCESS; + } +#elif defined(CL_HPP_USE_CL_DEVICE_FISSION) + +/** + * CL 1.1 version that uses device fission extension. + */ + cl_int createSubDevices( + const cl_device_partition_property_ext * properties, + vector* devices) + { + typedef CL_API_ENTRY cl_int + ( CL_API_CALL * PFN_clCreateSubDevicesEXT)( + cl_device_id /*in_device*/, + const cl_device_partition_property_ext * /* properties */, + cl_uint /*num_entries*/, + cl_device_id * /*out_devices*/, + cl_uint * /*num_devices*/ ) CL_EXT_SUFFIX__VERSION_1_1; + + static PFN_clCreateSubDevicesEXT pfn_clCreateSubDevicesEXT = NULL; + CL_HPP_INIT_CL_EXT_FCN_PTR_(clCreateSubDevicesEXT); + + cl_uint n = 0; + cl_int err = pfn_clCreateSubDevicesEXT(object_, properties, 0, NULL, &n); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __CREATE_SUB_DEVICES_ERR); + } + + vector ids(n); + err = pfn_clCreateSubDevicesEXT(object_, properties, n, ids.data(), NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __CREATE_SUB_DEVICES_ERR); + } + // Cannot trivially assign because we need to capture intermediates + // with safe construction + if (devices) { + devices->resize(ids.size()); + + // Assign to param, constructing with retain behaviour + // to correctly capture each underlying CL object + for (size_type i = 0; i < ids.size(); i++) { + // We do not need to retain because this device is being created + // by the runtime + (*devices)[i] = Device(ids[i], false); + } + } + return CL_SUCCESS; + } +#endif // defined(CL_HPP_USE_CL_DEVICE_FISSION) +}; + +CL_HPP_DEFINE_STATIC_MEMBER_ std::once_flag Device::default_initialized_; +CL_HPP_DEFINE_STATIC_MEMBER_ Device Device::default_; +CL_HPP_DEFINE_STATIC_MEMBER_ cl_int Device::default_error_ = CL_SUCCESS; + +/*! \brief Class interface for cl_platform_id. + * + * \note Copies of these objects are inexpensive, since they don't 'own' + * any underlying resources or data structures. + * + * \see cl_platform_id + */ +class Platform : public detail::Wrapper +{ +private: + static std::once_flag default_initialized_; + static Platform default_; + static cl_int default_error_; + + /*! \brief Create the default context. + * + * This sets @c default_ and @c default_error_. It does not throw + * @c cl::Error. + */ + static void makeDefault() { + /* Throwing an exception from a call_once invocation does not do + * what we wish, so we catch it and save the error. + */ +#if defined(CL_HPP_ENABLE_EXCEPTIONS) + try +#endif + { + // If default wasn't passed ,generate one + // Otherwise set it + cl_uint n = 0; + + cl_int err = ::clGetPlatformIDs(0, NULL, &n); + if (err != CL_SUCCESS) { + default_error_ = err; + return; + } + if (n == 0) { + default_error_ = CL_INVALID_PLATFORM; + return; + } + + vector ids(n); + err = ::clGetPlatformIDs(n, ids.data(), NULL); + if (err != CL_SUCCESS) { + default_error_ = err; + return; + } + + default_ = Platform(ids[0]); + } +#if defined(CL_HPP_ENABLE_EXCEPTIONS) + catch (cl::Error &e) { + default_error_ = e.err(); + } +#endif + } + + /*! \brief Create the default platform from a provided platform. + * + * This sets @c default_. It does not throw + * @c cl::Error. + */ + static void makeDefaultProvided(const Platform &p) { + default_ = p; + } + +public: +#ifdef CL_HPP_UNIT_TEST_ENABLE + /*! \brief Reset the default. + * + * This sets @c default_ to an empty value to support cleanup in + * the unit test framework. + * This function is not thread safe. + */ + static void unitTestClearDefault() { + default_ = Platform(); + } +#endif // #ifdef CL_HPP_UNIT_TEST_ENABLE + + //! \brief Default constructor - initializes to NULL. + Platform() : detail::Wrapper() { } + + /*! \brief Constructor from cl_platform_id. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + * This simply copies the platform ID value, which is an inexpensive operation. + */ + explicit Platform(const cl_platform_id &platform, bool retainObject = false) : + detail::Wrapper(platform, retainObject) { } + + /*! \brief Assignment operator from cl_platform_id. + * + * This simply copies the platform ID value, which is an inexpensive operation. + */ + Platform& operator = (const cl_platform_id& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + static Platform getDefault( + cl_int *errResult = NULL) + { + std::call_once(default_initialized_, makeDefault); + detail::errHandler(default_error_); + if (errResult != NULL) { + *errResult = default_error_; + } + return default_; + } + + /** + * Modify the default platform to be used by + * subsequent operations. + * Will only set the default if no default was previously created. + * @return updated default platform. + * Should be compared to the passed value to ensure that it was updated. + */ + static Platform setDefault(const Platform &default_platform) + { + std::call_once(default_initialized_, makeDefaultProvided, std::cref(default_platform)); + detail::errHandler(default_error_); + return default_; + } + + //! \brief Wrapper for clGetPlatformInfo(). + cl_int getInfo(cl_platform_info name, string* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetPlatformInfo, object_, name, param), + __GET_PLATFORM_INFO_ERR); + } + + //! \brief Wrapper for clGetPlatformInfo() that returns by value. + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_platform_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + /*! \brief Gets a list of devices for this platform. + * + * Wraps clGetDeviceIDs(). + */ + cl_int getDevices( + cl_device_type type, + vector* devices) const + { + cl_uint n = 0; + if( devices == NULL ) { + return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_DEVICE_IDS_ERR); + } + cl_int err = ::clGetDeviceIDs(object_, type, 0, NULL, &n); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_DEVICE_IDS_ERR); + } + + vector ids(n); + err = ::clGetDeviceIDs(object_, type, n, ids.data(), NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_DEVICE_IDS_ERR); + } + + // Cannot trivially assign because we need to capture intermediates + // with safe construction + // We must retain things we obtain from the API to avoid releasing + // API-owned objects. + if (devices) { + devices->resize(ids.size()); + + // Assign to param, constructing with retain behaviour + // to correctly capture each underlying CL object + for (size_type i = 0; i < ids.size(); i++) { + (*devices)[i] = Device(ids[i], true); + } + } + return CL_SUCCESS; + } + +#if defined(CL_HPP_USE_DX_INTEROP) + /*! \brief Get the list of available D3D10 devices. + * + * \param d3d_device_source. + * + * \param d3d_object. + * + * \param d3d_device_set. + * + * \param devices returns a vector of OpenCL D3D10 devices found. The cl::Device + * values returned in devices can be used to identify a specific OpenCL + * device. If \a devices argument is NULL, this argument is ignored. + * + * \return One of the following values: + * - CL_SUCCESS if the function is executed successfully. + * + * The application can query specific capabilities of the OpenCL device(s) + * returned by cl::getDevices. This can be used by the application to + * determine which device(s) to use. + * + * \note In the case that exceptions are enabled and a return value + * other than CL_SUCCESS is generated, then cl::Error exception is + * generated. + */ + cl_int getDevices( + cl_d3d10_device_source_khr d3d_device_source, + void * d3d_object, + cl_d3d10_device_set_khr d3d_device_set, + vector* devices) const + { + typedef CL_API_ENTRY cl_int (CL_API_CALL *PFN_clGetDeviceIDsFromD3D10KHR)( + cl_platform_id platform, + cl_d3d10_device_source_khr d3d_device_source, + void * d3d_object, + cl_d3d10_device_set_khr d3d_device_set, + cl_uint num_entries, + cl_device_id * devices, + cl_uint* num_devices); + + if( devices == NULL ) { + return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_DEVICE_IDS_ERR); + } + + static PFN_clGetDeviceIDsFromD3D10KHR pfn_clGetDeviceIDsFromD3D10KHR = NULL; + CL_HPP_INIT_CL_EXT_FCN_PTR_PLATFORM_(object_, clGetDeviceIDsFromD3D10KHR); + + cl_uint n = 0; + cl_int err = pfn_clGetDeviceIDsFromD3D10KHR( + object_, + d3d_device_source, + d3d_object, + d3d_device_set, + 0, + NULL, + &n); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_DEVICE_IDS_ERR); + } + + vector ids(n); + err = pfn_clGetDeviceIDsFromD3D10KHR( + object_, + d3d_device_source, + d3d_object, + d3d_device_set, + n, + ids.data(), + NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_DEVICE_IDS_ERR); + } + + // Cannot trivially assign because we need to capture intermediates + // with safe construction + // We must retain things we obtain from the API to avoid releasing + // API-owned objects. + if (devices) { + devices->resize(ids.size()); + + // Assign to param, constructing with retain behaviour + // to correctly capture each underlying CL object + for (size_type i = 0; i < ids.size(); i++) { + (*devices)[i] = Device(ids[i], true); + } + } + return CL_SUCCESS; + } +#endif + + /*! \brief Gets a list of available platforms. + * + * Wraps clGetPlatformIDs(). + */ + static cl_int get( + vector* platforms) + { + cl_uint n = 0; + + if( platforms == NULL ) { + return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_PLATFORM_IDS_ERR); + } + + cl_int err = ::clGetPlatformIDs(0, NULL, &n); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_PLATFORM_IDS_ERR); + } + + vector ids(n); + err = ::clGetPlatformIDs(n, ids.data(), NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_PLATFORM_IDS_ERR); + } + + if (platforms) { + platforms->resize(ids.size()); + + // Platforms don't reference count + for (size_type i = 0; i < ids.size(); i++) { + (*platforms)[i] = Platform(ids[i]); + } + } + return CL_SUCCESS; + } + + /*! \brief Gets the first available platform. + * + * Wraps clGetPlatformIDs(), returning the first result. + */ + static cl_int get( + Platform * platform) + { + cl_int err; + Platform default_platform = Platform::getDefault(&err); + if (platform) { + *platform = default_platform; + } + return err; + } + + /*! \brief Gets the first available platform, returning it by value. + * + * \return Returns a valid platform if one is available. + * If no platform is available will return a null platform. + * Throws an exception if no platforms are available + * or an error condition occurs. + * Wraps clGetPlatformIDs(), returning the first result. + */ + static Platform get( + cl_int * errResult = NULL) + { + cl_int err; + Platform default_platform = Platform::getDefault(&err); + if (errResult) { + *errResult = err; + } + return default_platform; + } + +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 + //! \brief Wrapper for clUnloadCompiler(). + cl_int + unloadCompiler() + { + return ::clUnloadPlatformCompiler(object_); + } +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 +}; // class Platform + +CL_HPP_DEFINE_STATIC_MEMBER_ std::once_flag Platform::default_initialized_; +CL_HPP_DEFINE_STATIC_MEMBER_ Platform Platform::default_; +CL_HPP_DEFINE_STATIC_MEMBER_ cl_int Platform::default_error_ = CL_SUCCESS; + + +/** + * Deprecated APIs for 1.2 + */ +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) +/** + * Unload the OpenCL compiler. + * \note Deprecated for OpenCL 1.2. Use Platform::unloadCompiler instead. + */ +inline CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int +UnloadCompiler() CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED; +inline cl_int +UnloadCompiler() +{ + return ::clUnloadCompiler(); +} +#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + +/*! \brief Class interface for cl_context. + * + * \note Copies of these objects are shallow, meaning that the copy will refer + * to the same underlying cl_context as the original. For details, see + * clRetainContext() and clReleaseContext(). + * + * \see cl_context + */ +class Context + : public detail::Wrapper +{ +private: + static std::once_flag default_initialized_; + static Context default_; + static cl_int default_error_; + + /*! \brief Create the default context from the default device type in the default platform. + * + * This sets @c default_ and @c default_error_. It does not throw + * @c cl::Error. + */ + static void makeDefault() { + /* Throwing an exception from a call_once invocation does not do + * what we wish, so we catch it and save the error. + */ +#if defined(CL_HPP_ENABLE_EXCEPTIONS) + try +#endif + { +#if !defined(__APPLE__) && !defined(__MACOS) + const Platform &p = Platform::getDefault(); + cl_platform_id defaultPlatform = p(); + cl_context_properties properties[3] = { + CL_CONTEXT_PLATFORM, (cl_context_properties)defaultPlatform, 0 + }; +#else // #if !defined(__APPLE__) && !defined(__MACOS) + cl_context_properties *properties = nullptr; +#endif // #if !defined(__APPLE__) && !defined(__MACOS) + + default_ = Context( + CL_DEVICE_TYPE_DEFAULT, + properties, + NULL, + NULL, + &default_error_); + } +#if defined(CL_HPP_ENABLE_EXCEPTIONS) + catch (cl::Error &e) { + default_error_ = e.err(); + } +#endif + } + + + /*! \brief Create the default context from a provided Context. + * + * This sets @c default_. It does not throw + * @c cl::Error. + */ + static void makeDefaultProvided(const Context &c) { + default_ = c; + } + +public: +#ifdef CL_HPP_UNIT_TEST_ENABLE + /*! \brief Reset the default. + * + * This sets @c default_ to an empty value to support cleanup in + * the unit test framework. + * This function is not thread safe. + */ + static void unitTestClearDefault() { + default_ = Context(); + } +#endif // #ifdef CL_HPP_UNIT_TEST_ENABLE + + /*! \brief Constructs a context including a list of specified devices. + * + * Wraps clCreateContext(). + */ + Context( + const vector& devices, + cl_context_properties* properties = NULL, + void (CL_CALLBACK * notifyFptr)( + const char *, + const void *, + size_type, + void *) = NULL, + void* data = NULL, + cl_int* err = NULL) + { + cl_int error; + + size_type numDevices = devices.size(); + vector deviceIDs(numDevices); + + for( size_type deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) { + deviceIDs[deviceIndex] = (devices[deviceIndex])(); + } + + object_ = ::clCreateContext( + properties, (cl_uint) numDevices, + deviceIDs.data(), + notifyFptr, data, &error); + + detail::errHandler(error, __CREATE_CONTEXT_ERR); + if (err != NULL) { + *err = error; + } + } + + Context( + const Device& device, + cl_context_properties* properties = NULL, + void (CL_CALLBACK * notifyFptr)( + const char *, + const void *, + size_type, + void *) = NULL, + void* data = NULL, + cl_int* err = NULL) + { + cl_int error; + + cl_device_id deviceID = device(); + + object_ = ::clCreateContext( + properties, 1, + &deviceID, + notifyFptr, data, &error); + + detail::errHandler(error, __CREATE_CONTEXT_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! \brief Constructs a context including all or a subset of devices of a specified type. + * + * Wraps clCreateContextFromType(). + */ + Context( + cl_device_type type, + cl_context_properties* properties = NULL, + void (CL_CALLBACK * notifyFptr)( + const char *, + const void *, + size_type, + void *) = NULL, + void* data = NULL, + cl_int* err = NULL) + { + cl_int error; + +#if !defined(__APPLE__) && !defined(__MACOS) + cl_context_properties prop[4] = {CL_CONTEXT_PLATFORM, 0, 0, 0 }; + + if (properties == NULL) { + // Get a valid platform ID as we cannot send in a blank one + vector platforms; + error = Platform::get(&platforms); + if (error != CL_SUCCESS) { + detail::errHandler(error, __CREATE_CONTEXT_FROM_TYPE_ERR); + if (err != NULL) { + *err = error; + } + return; + } + + // Check the platforms we found for a device of our specified type + cl_context_properties platform_id = 0; + for (unsigned int i = 0; i < platforms.size(); i++) { + + vector devices; + +#if defined(CL_HPP_ENABLE_EXCEPTIONS) + try { +#endif + + error = platforms[i].getDevices(type, &devices); + +#if defined(CL_HPP_ENABLE_EXCEPTIONS) + } catch (Error) {} + // Catch if exceptions are enabled as we don't want to exit if first platform has no devices of type + // We do error checking next anyway, and can throw there if needed +#endif + + // Only squash CL_SUCCESS and CL_DEVICE_NOT_FOUND + if (error != CL_SUCCESS && error != CL_DEVICE_NOT_FOUND) { + detail::errHandler(error, __CREATE_CONTEXT_FROM_TYPE_ERR); + if (err != NULL) { + *err = error; + } + } + + if (devices.size() > 0) { + platform_id = (cl_context_properties)platforms[i](); + break; + } + } + + if (platform_id == 0) { + detail::errHandler(CL_DEVICE_NOT_FOUND, __CREATE_CONTEXT_FROM_TYPE_ERR); + if (err != NULL) { + *err = CL_DEVICE_NOT_FOUND; + } + return; + } + + prop[1] = platform_id; + properties = &prop[0]; + } +#endif + object_ = ::clCreateContextFromType( + properties, type, notifyFptr, data, &error); + + detail::errHandler(error, __CREATE_CONTEXT_FROM_TYPE_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Context(const Context& ctx) : detail::Wrapper(ctx) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Context& operator = (const Context &ctx) + { + detail::Wrapper::operator=(ctx); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Context(Context&& ctx) CL_HPP_NOEXCEPT_ : detail::Wrapper(std::move(ctx)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Context& operator = (Context &&ctx) + { + detail::Wrapper::operator=(std::move(ctx)); + return *this; + } + + + /*! \brief Returns a singleton context including all devices of CL_DEVICE_TYPE_DEFAULT. + * + * \note All calls to this function return the same cl_context as the first. + */ + static Context getDefault(cl_int * err = NULL) + { + std::call_once(default_initialized_, makeDefault); + detail::errHandler(default_error_); + if (err != NULL) { + *err = default_error_; + } + return default_; + } + + /** + * Modify the default context to be used by + * subsequent operations. + * Will only set the default if no default was previously created. + * @return updated default context. + * Should be compared to the passed value to ensure that it was updated. + */ + static Context setDefault(const Context &default_context) + { + std::call_once(default_initialized_, makeDefaultProvided, std::cref(default_context)); + detail::errHandler(default_error_); + return default_; + } + + //! \brief Default constructor - initializes to NULL. + Context() : detail::Wrapper() { } + + /*! \brief Constructor from cl_context - takes ownership. + * + * This effectively transfers ownership of a refcount on the cl_context + * into the new Context object. + */ + explicit Context(const cl_context& context, bool retainObject = false) : + detail::Wrapper(context, retainObject) { } + + /*! \brief Assignment operator from cl_context - takes ownership. + * + * This effectively transfers ownership of a refcount on the rhs and calls + * clReleaseContext() on the value previously held by this instance. + */ + Context& operator = (const cl_context& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + //! \brief Wrapper for clGetContextInfo(). + template + cl_int getInfo(cl_context_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetContextInfo, object_, name, param), + __GET_CONTEXT_INFO_ERR); + } + + //! \brief Wrapper for clGetContextInfo() that returns by value. + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_context_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + /*! \brief Gets a list of supported image formats. + * + * Wraps clGetSupportedImageFormats(). + */ + cl_int getSupportedImageFormats( + cl_mem_flags flags, + cl_mem_object_type type, + vector* formats) const + { + cl_uint numEntries; + + if (!formats) { + return CL_SUCCESS; + } + + cl_int err = ::clGetSupportedImageFormats( + object_, + flags, + type, + 0, + NULL, + &numEntries); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_SUPPORTED_IMAGE_FORMATS_ERR); + } + + if (numEntries > 0) { + vector value(numEntries); + err = ::clGetSupportedImageFormats( + object_, + flags, + type, + numEntries, + (cl_image_format*)value.data(), + NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_SUPPORTED_IMAGE_FORMATS_ERR); + } + + formats->assign(begin(value), end(value)); + } + else { + // If no values are being returned, ensure an empty vector comes back + formats->clear(); + } + + return CL_SUCCESS; + } +}; + +inline void Device::makeDefault() +{ + /* Throwing an exception from a call_once invocation does not do + * what we wish, so we catch it and save the error. + */ +#if defined(CL_HPP_ENABLE_EXCEPTIONS) + try +#endif + { + cl_int error = 0; + + Context context = Context::getDefault(&error); + detail::errHandler(error, __CREATE_CONTEXT_ERR); + + if (error != CL_SUCCESS) { + default_error_ = error; + } + else { + default_ = context.getInfo()[0]; + default_error_ = CL_SUCCESS; + } + } +#if defined(CL_HPP_ENABLE_EXCEPTIONS) + catch (cl::Error &e) { + default_error_ = e.err(); + } +#endif +} + +CL_HPP_DEFINE_STATIC_MEMBER_ std::once_flag Context::default_initialized_; +CL_HPP_DEFINE_STATIC_MEMBER_ Context Context::default_; +CL_HPP_DEFINE_STATIC_MEMBER_ cl_int Context::default_error_ = CL_SUCCESS; + +/*! \brief Class interface for cl_event. + * + * \note Copies of these objects are shallow, meaning that the copy will refer + * to the same underlying cl_event as the original. For details, see + * clRetainEvent() and clReleaseEvent(). + * + * \see cl_event + */ +class Event : public detail::Wrapper +{ +public: + //! \brief Default constructor - initializes to NULL. + Event() : detail::Wrapper() { } + + /*! \brief Constructor from cl_event - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + * This effectively transfers ownership of a refcount on the cl_event + * into the new Event object. + */ + explicit Event(const cl_event& event, bool retainObject = false) : + detail::Wrapper(event, retainObject) { } + + /*! \brief Assignment operator from cl_event - takes ownership. + * + * This effectively transfers ownership of a refcount on the rhs and calls + * clReleaseEvent() on the value previously held by this instance. + */ + Event& operator = (const cl_event& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + //! \brief Wrapper for clGetEventInfo(). + template + cl_int getInfo(cl_event_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetEventInfo, object_, name, param), + __GET_EVENT_INFO_ERR); + } + + //! \brief Wrapper for clGetEventInfo() that returns by value. + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_event_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + //! \brief Wrapper for clGetEventProfilingInfo(). + template + cl_int getProfilingInfo(cl_profiling_info name, T* param) const + { + return detail::errHandler(detail::getInfo( + &::clGetEventProfilingInfo, object_, name, param), + __GET_EVENT_PROFILE_INFO_ERR); + } + + //! \brief Wrapper for clGetEventProfilingInfo() that returns by value. + template typename + detail::param_traits::param_type + getProfilingInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_profiling_info, name>::param_type param; + cl_int result = getProfilingInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + /*! \brief Blocks the calling thread until this event completes. + * + * Wraps clWaitForEvents(). + */ + cl_int wait() const + { + return detail::errHandler( + ::clWaitForEvents(1, &object_), + __WAIT_FOR_EVENTS_ERR); + } + +#if CL_HPP_TARGET_OPENCL_VERSION >= 110 + /*! \brief Registers a user callback function for a specific command execution status. + * + * Wraps clSetEventCallback(). + */ + cl_int setCallback( + cl_int type, + void (CL_CALLBACK * pfn_notify)(cl_event, cl_int, void *), + void * user_data = NULL) + { + return detail::errHandler( + ::clSetEventCallback( + object_, + type, + pfn_notify, + user_data), + __SET_EVENT_CALLBACK_ERR); + } +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 110 + + /*! \brief Blocks the calling thread until every event specified is complete. + * + * Wraps clWaitForEvents(). + */ + static cl_int + waitForEvents(const vector& events) + { + return detail::errHandler( + ::clWaitForEvents( + (cl_uint) events.size(), (events.size() > 0) ? (cl_event*)&events.front() : NULL), + __WAIT_FOR_EVENTS_ERR); + } +}; + +#if CL_HPP_TARGET_OPENCL_VERSION >= 110 +/*! \brief Class interface for user events (a subset of cl_event's). + * + * See Event for details about copy semantics, etc. + */ +class UserEvent : public Event +{ +public: + /*! \brief Constructs a user event on a given context. + * + * Wraps clCreateUserEvent(). + */ + UserEvent( + const Context& context, + cl_int * err = NULL) + { + cl_int error; + object_ = ::clCreateUserEvent( + context(), + &error); + + detail::errHandler(error, __CREATE_USER_EVENT_ERR); + if (err != NULL) { + *err = error; + } + } + + //! \brief Default constructor - initializes to NULL. + UserEvent() : Event() { } + + /*! \brief Sets the execution status of a user event object. + * + * Wraps clSetUserEventStatus(). + */ + cl_int setStatus(cl_int status) + { + return detail::errHandler( + ::clSetUserEventStatus(object_,status), + __SET_USER_EVENT_STATUS_ERR); + } +}; +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 110 + +/*! \brief Blocks the calling thread until every event specified is complete. + * + * Wraps clWaitForEvents(). + */ +inline static cl_int +WaitForEvents(const vector& events) +{ + return detail::errHandler( + ::clWaitForEvents( + (cl_uint) events.size(), (events.size() > 0) ? (cl_event*)&events.front() : NULL), + __WAIT_FOR_EVENTS_ERR); +} + +/*! \brief Class interface for cl_mem. + * + * \note Copies of these objects are shallow, meaning that the copy will refer + * to the same underlying cl_mem as the original. For details, see + * clRetainMemObject() and clReleaseMemObject(). + * + * \see cl_mem + */ +class Memory : public detail::Wrapper +{ +public: + //! \brief Default constructor - initializes to NULL. + Memory() : detail::Wrapper() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * Optionally transfer ownership of a refcount on the cl_mem + * into the new Memory object. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + * + * See Memory for further details. + */ + explicit Memory(const cl_mem& memory, bool retainObject) : + detail::Wrapper(memory, retainObject) { } + + /*! \brief Assignment operator from cl_mem - takes ownership. + * + * This effectively transfers ownership of a refcount on the rhs and calls + * clReleaseMemObject() on the value previously held by this instance. + */ + Memory& operator = (const cl_mem& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Memory(const Memory& mem) : detail::Wrapper(mem) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Memory& operator = (const Memory &mem) + { + detail::Wrapper::operator=(mem); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Memory(Memory&& mem) CL_HPP_NOEXCEPT_ : detail::Wrapper(std::move(mem)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Memory& operator = (Memory &&mem) + { + detail::Wrapper::operator=(std::move(mem)); + return *this; + } + + + //! \brief Wrapper for clGetMemObjectInfo(). + template + cl_int getInfo(cl_mem_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetMemObjectInfo, object_, name, param), + __GET_MEM_OBJECT_INFO_ERR); + } + + //! \brief Wrapper for clGetMemObjectInfo() that returns by value. + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_mem_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + +#if CL_HPP_TARGET_OPENCL_VERSION >= 110 + /*! \brief Registers a callback function to be called when the memory object + * is no longer needed. + * + * Wraps clSetMemObjectDestructorCallback(). + * + * Repeated calls to this function, for a given cl_mem value, will append + * to the list of functions called (in reverse order) when memory object's + * resources are freed and the memory object is deleted. + * + * \note + * The registered callbacks are associated with the underlying cl_mem + * value - not the Memory class instance. + */ + cl_int setDestructorCallback( + void (CL_CALLBACK * pfn_notify)(cl_mem, void *), + void * user_data = NULL) + { + return detail::errHandler( + ::clSetMemObjectDestructorCallback( + object_, + pfn_notify, + user_data), + __SET_MEM_OBJECT_DESTRUCTOR_CALLBACK_ERR); + } +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 110 + +}; + +// Pre-declare copy functions +class Buffer; +template< typename IteratorType > +cl_int copy( IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer ); +template< typename IteratorType > +cl_int copy( const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator ); +template< typename IteratorType > +cl_int copy( const CommandQueue &queue, IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer ); +template< typename IteratorType > +cl_int copy( const CommandQueue &queue, const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator ); + + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 +namespace detail +{ + class SVMTraitNull + { + public: + static cl_svm_mem_flags getSVMMemFlags() + { + return 0; + } + }; +} // namespace detail + +template +class SVMTraitReadWrite +{ +public: + static cl_svm_mem_flags getSVMMemFlags() + { + return CL_MEM_READ_WRITE | + Trait::getSVMMemFlags(); + } +}; + +template +class SVMTraitReadOnly +{ +public: + static cl_svm_mem_flags getSVMMemFlags() + { + return CL_MEM_READ_ONLY | + Trait::getSVMMemFlags(); + } +}; + +template +class SVMTraitWriteOnly +{ +public: + static cl_svm_mem_flags getSVMMemFlags() + { + return CL_MEM_WRITE_ONLY | + Trait::getSVMMemFlags(); + } +}; + +template> +class SVMTraitCoarse +{ +public: + static cl_svm_mem_flags getSVMMemFlags() + { + return Trait::getSVMMemFlags(); + } +}; + +template> +class SVMTraitFine +{ +public: + static cl_svm_mem_flags getSVMMemFlags() + { + return CL_MEM_SVM_FINE_GRAIN_BUFFER | + Trait::getSVMMemFlags(); + } +}; + +template> +class SVMTraitAtomic +{ +public: + static cl_svm_mem_flags getSVMMemFlags() + { + return + CL_MEM_SVM_FINE_GRAIN_BUFFER | + CL_MEM_SVM_ATOMICS | + Trait::getSVMMemFlags(); + } +}; + +// Pre-declare SVM map function +template +inline cl_int enqueueMapSVM( + T* ptr, + cl_bool blocking, + cl_map_flags flags, + size_type size, + const vector* events = NULL, + Event* event = NULL); + +/** + * STL-like allocator class for managing SVM objects provided for convenience. + * + * Note that while this behaves like an allocator for the purposes of constructing vectors and similar objects, + * care must be taken when using with smart pointers. + * The allocator should not be used to construct a unique_ptr if we are using coarse-grained SVM mode because + * the coarse-grained management behaviour would behave incorrectly with respect to reference counting. + * + * Instead the allocator embeds a Deleter which may be used with unique_ptr and is used + * with the allocate_shared and allocate_ptr supplied operations. + */ +template +class SVMAllocator { +private: + Context context_; + +public: + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + template + struct rebind + { + typedef SVMAllocator other; + }; + + template + friend class SVMAllocator; + + SVMAllocator() : + context_(Context::getDefault()) + { + } + + explicit SVMAllocator(cl::Context context) : + context_(context) + { + } + + + SVMAllocator(const SVMAllocator &other) : + context_(other.context_) + { + } + + template + SVMAllocator(const SVMAllocator &other) : + context_(other.context_) + { + } + + ~SVMAllocator() + { + } + + pointer address(reference r) CL_HPP_NOEXCEPT_ + { + return std::addressof(r); + } + + const_pointer address(const_reference r) CL_HPP_NOEXCEPT_ + { + return std::addressof(r); + } + + /** + * Allocate an SVM pointer. + * + * If the allocator is coarse-grained, this will take ownership to allow + * containers to correctly construct data in place. + */ + pointer allocate( + size_type size, + typename cl::SVMAllocator::const_pointer = 0) + { + // Allocate memory with default alignment matching the size of the type + void* voidPointer = + clSVMAlloc( + context_(), + SVMTrait::getSVMMemFlags(), + size*sizeof(T), + 0); + pointer retValue = reinterpret_cast( + voidPointer); +#if defined(CL_HPP_ENABLE_EXCEPTIONS) + if (!retValue) { + std::bad_alloc excep; + throw excep; + } +#endif // #if defined(CL_HPP_ENABLE_EXCEPTIONS) + + // If allocation was coarse-grained then map it + if (!(SVMTrait::getSVMMemFlags() & CL_MEM_SVM_FINE_GRAIN_BUFFER)) { + cl_int err = enqueueMapSVM(retValue, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, size*sizeof(T)); + if (err != CL_SUCCESS) { + std::bad_alloc excep; + throw excep; + } + } + + // If exceptions disabled, return null pointer from allocator + return retValue; + } + + void deallocate(pointer p, size_type) + { + clSVMFree(context_(), p); + } + + /** + * Return the maximum possible allocation size. + * This is the minimum of the maximum sizes of all devices in the context. + */ + size_type max_size() const CL_HPP_NOEXCEPT_ + { + size_type maxSize = std::numeric_limits::max() / sizeof(T); + + for (Device &d : context_.getInfo()) { + maxSize = std::min( + maxSize, + static_cast(d.getInfo())); + } + + return maxSize; + } + + template< class U, class... Args > + void construct(U* p, Args&&... args) + { + new(p)T(args...); + } + + template< class U > + void destroy(U* p) + { + p->~U(); + } + + /** + * Returns true if the contexts match. + */ + inline bool operator==(SVMAllocator const& rhs) + { + return (context_==rhs.context_); + } + + inline bool operator!=(SVMAllocator const& a) + { + return !operator==(a); + } +}; // class SVMAllocator return cl::pointer(tmp, detail::Deleter{alloc, copies}); + + +template +class SVMAllocator { +public: + typedef void value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + + template + struct rebind + { + typedef SVMAllocator other; + }; + + template + friend class SVMAllocator; +}; + +#if !defined(CL_HPP_NO_STD_UNIQUE_PTR) +namespace detail +{ + template + class Deleter { + private: + Alloc alloc_; + size_type copies_; + + public: + typedef typename std::allocator_traits::pointer pointer; + + Deleter(const Alloc &alloc, size_type copies) : alloc_{ alloc }, copies_{ copies } + { + } + + void operator()(pointer ptr) const { + Alloc tmpAlloc{ alloc_ }; + std::allocator_traits::destroy(tmpAlloc, std::addressof(*ptr)); + std::allocator_traits::deallocate(tmpAlloc, ptr, copies_); + } + }; +} // namespace detail + +/** + * Allocation operation compatible with std::allocate_ptr. + * Creates a unique_ptr by default. + * This requirement is to ensure that the control block is not + * allocated in memory inaccessible to the host. + */ +template +cl::pointer> allocate_pointer(const Alloc &alloc_, Args&&... args) +{ + Alloc alloc(alloc_); + static const size_type copies = 1; + + // Ensure that creation of the management block and the + // object are dealt with separately such that we only provide a deleter + + T* tmp = std::allocator_traits::allocate(alloc, copies); + if (!tmp) { + std::bad_alloc excep; + throw excep; + } + try { + std::allocator_traits::construct( + alloc, + std::addressof(*tmp), + std::forward(args)...); + + return cl::pointer>(tmp, detail::Deleter{alloc, copies}); + } + catch (std::bad_alloc b) + { + std::allocator_traits::deallocate(alloc, tmp, copies); + throw; + } +} + +template< class T, class SVMTrait, class... Args > +cl::pointer>> allocate_svm(Args... args) +{ + SVMAllocator alloc; + return cl::allocate_pointer(alloc, args...); +} + +template< class T, class SVMTrait, class... Args > +cl::pointer>> allocate_svm(const cl::Context &c, Args... args) +{ + SVMAllocator alloc(c); + return cl::allocate_pointer(alloc, args...); +} +#endif // #if !defined(CL_HPP_NO_STD_UNIQUE_PTR) + +/*! \brief Vector alias to simplify construction of coarse-grained SVM containers. + * + */ +template < class T > +using coarse_svm_vector = vector>>; + +/*! \brief Vector alias to simplify construction of fine-grained SVM containers. +* +*/ +template < class T > +using fine_svm_vector = vector>>; + +/*! \brief Vector alias to simplify construction of fine-grained SVM containers that support platform atomics. +* +*/ +template < class T > +using atomic_svm_vector = vector>>; + +#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200 + + +/*! \brief Class interface for Buffer Memory Objects. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class Buffer : public Memory +{ +public: + + /*! \brief Constructs a Buffer in a specified context. + * + * Wraps clCreateBuffer(). + * + * \param host_ptr Storage to be used if the CL_MEM_USE_HOST_PTR flag was + * specified. Note alignment & exclusivity requirements. + */ + Buffer( + const Context& context, + cl_mem_flags flags, + size_type size, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + object_ = ::clCreateBuffer(context(), flags, size, host_ptr, &error); + + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! \brief Constructs a Buffer in the default context. + * + * Wraps clCreateBuffer(). + * + * \param host_ptr Storage to be used if the CL_MEM_USE_HOST_PTR flag was + * specified. Note alignment & exclusivity requirements. + * + * \see Context::getDefault() + */ + Buffer( + cl_mem_flags flags, + size_type size, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + + Context context = Context::getDefault(err); + + object_ = ::clCreateBuffer(context(), flags, size, host_ptr, &error); + + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! + * \brief Construct a Buffer from a host container via iterators. + * IteratorType must be random access. + * If useHostPtr is specified iterators must represent contiguous data. + */ + template< typename IteratorType > + Buffer( + IteratorType startIterator, + IteratorType endIterator, + bool readOnly, + bool useHostPtr = false, + cl_int* err = NULL) + { + typedef typename std::iterator_traits::value_type DataType; + cl_int error; + + cl_mem_flags flags = 0; + if( readOnly ) { + flags |= CL_MEM_READ_ONLY; + } + else { + flags |= CL_MEM_READ_WRITE; + } + if( useHostPtr ) { + flags |= CL_MEM_USE_HOST_PTR; + } + + size_type size = sizeof(DataType)*(endIterator - startIterator); + + Context context = Context::getDefault(err); + + if( useHostPtr ) { + object_ = ::clCreateBuffer(context(), flags, size, static_cast(&*startIterator), &error); + } else { + object_ = ::clCreateBuffer(context(), flags, size, 0, &error); + } + + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + + if( !useHostPtr ) { + error = cl::copy(startIterator, endIterator, *this); + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } + } + + /*! + * \brief Construct a Buffer from a host container via iterators using a specified context. + * IteratorType must be random access. + * If useHostPtr is specified iterators must represent contiguous data. + */ + template< typename IteratorType > + Buffer(const Context &context, IteratorType startIterator, IteratorType endIterator, + bool readOnly, bool useHostPtr = false, cl_int* err = NULL); + + /*! + * \brief Construct a Buffer from a host container via iterators using a specified queue. + * If useHostPtr is specified iterators must be random access. + */ + template< typename IteratorType > + Buffer(const CommandQueue &queue, IteratorType startIterator, IteratorType endIterator, + bool readOnly, bool useHostPtr = false, cl_int* err = NULL); + + //! \brief Default constructor - initializes to NULL. + Buffer() : Memory() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with earlier versions. + * + * See Memory for further details. + */ + explicit Buffer(const cl_mem& buffer, bool retainObject = false) : + Memory(buffer, retainObject) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Buffer& operator = (const cl_mem& rhs) + { + Memory::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Buffer(const Buffer& buf) : Memory(buf) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Buffer& operator = (const Buffer &buf) + { + Memory::operator=(buf); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Buffer(Buffer&& buf) CL_HPP_NOEXCEPT_ : Memory(std::move(buf)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Buffer& operator = (Buffer &&buf) + { + Memory::operator=(std::move(buf)); + return *this; + } + +#if CL_HPP_TARGET_OPENCL_VERSION >= 110 + /*! \brief Creates a new buffer object from this. + * + * Wraps clCreateSubBuffer(). + */ + Buffer createSubBuffer( + cl_mem_flags flags, + cl_buffer_create_type buffer_create_type, + const void * buffer_create_info, + cl_int * err = NULL) + { + Buffer result; + cl_int error; + result.object_ = ::clCreateSubBuffer( + object_, + flags, + buffer_create_type, + buffer_create_info, + &error); + + detail::errHandler(error, __CREATE_SUBBUFFER_ERR); + if (err != NULL) { + *err = error; + } + + return result; + } +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 110 +}; + +#if defined (CL_HPP_USE_DX_INTEROP) +/*! \brief Class interface for creating OpenCL buffers from ID3D10Buffer's. + * + * This is provided to facilitate interoperability with Direct3D. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class BufferD3D10 : public Buffer +{ +public: + + + /*! \brief Constructs a BufferD3D10, in a specified context, from a + * given ID3D10Buffer. + * + * Wraps clCreateFromD3D10BufferKHR(). + */ + BufferD3D10( + const Context& context, + cl_mem_flags flags, + ID3D10Buffer* bufobj, + cl_int * err = NULL) : pfn_clCreateFromD3D10BufferKHR(nullptr) + { + typedef CL_API_ENTRY cl_mem (CL_API_CALL *PFN_clCreateFromD3D10BufferKHR)( + cl_context context, cl_mem_flags flags, ID3D10Buffer* buffer, + cl_int* errcode_ret); + PFN_clCreateFromD3D10BufferKHR pfn_clCreateFromD3D10BufferKHR; +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 + vector props = context.getInfo(); + cl_platform platform = -1; + for( int i = 0; i < props.size(); ++i ) { + if( props[i] == CL_CONTEXT_PLATFORM ) { + platform = props[i+1]; + } + } + CL_HPP_INIT_CL_EXT_FCN_PTR_PLATFORM_(platform, clCreateFromD3D10BufferKHR); +#elif CL_HPP_TARGET_OPENCL_VERSION >= 110 + CL_HPP_INIT_CL_EXT_FCN_PTR_(clCreateFromD3D10BufferKHR); +#endif + + cl_int error; + object_ = pfn_clCreateFromD3D10BufferKHR( + context(), + flags, + bufobj, + &error); + + detail::errHandler(error, __CREATE_GL_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } + + //! \brief Default constructor - initializes to NULL. + BufferD3D10() : Buffer() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + * See Memory for further details. + */ + explicit BufferD3D10(const cl_mem& buffer, bool retainObject = false) : + Buffer(buffer, retainObject) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + BufferD3D10& operator = (const cl_mem& rhs) + { + Buffer::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + BufferD3D10(const BufferD3D10& buf) : + Buffer(buf) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + BufferD3D10& operator = (const BufferD3D10 &buf) + { + Buffer::operator=(buf); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + BufferD3D10(BufferD3D10&& buf) CL_HPP_NOEXCEPT_ : Buffer(std::move(buf)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + BufferD3D10& operator = (BufferD3D10 &&buf) + { + Buffer::operator=(std::move(buf)); + return *this; + } +}; +#endif + +/*! \brief Class interface for GL Buffer Memory Objects. + * + * This is provided to facilitate interoperability with OpenGL. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class BufferGL : public Buffer +{ +public: + /*! \brief Constructs a BufferGL in a specified context, from a given + * GL buffer. + * + * Wraps clCreateFromGLBuffer(). + */ + BufferGL( + const Context& context, + cl_mem_flags flags, + cl_GLuint bufobj, + cl_int * err = NULL) + { + cl_int error; + object_ = ::clCreateFromGLBuffer( + context(), + flags, + bufobj, + &error); + + detail::errHandler(error, __CREATE_GL_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } + + //! \brief Default constructor - initializes to NULL. + BufferGL() : Buffer() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + * See Memory for further details. + */ + explicit BufferGL(const cl_mem& buffer, bool retainObject = false) : + Buffer(buffer, retainObject) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + BufferGL& operator = (const cl_mem& rhs) + { + Buffer::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + BufferGL(const BufferGL& buf) : Buffer(buf) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + BufferGL& operator = (const BufferGL &buf) + { + Buffer::operator=(buf); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + BufferGL(BufferGL&& buf) CL_HPP_NOEXCEPT_ : Buffer(std::move(buf)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + BufferGL& operator = (BufferGL &&buf) + { + Buffer::operator=(std::move(buf)); + return *this; + } + + //! \brief Wrapper for clGetGLObjectInfo(). + cl_int getObjectInfo( + cl_gl_object_type *type, + cl_GLuint * gl_object_name) + { + return detail::errHandler( + ::clGetGLObjectInfo(object_,type,gl_object_name), + __GET_GL_OBJECT_INFO_ERR); + } +}; + +/*! \brief Class interface for GL Render Buffer Memory Objects. + * + * This is provided to facilitate interoperability with OpenGL. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class BufferRenderGL : public Buffer +{ +public: + /*! \brief Constructs a BufferRenderGL in a specified context, from a given + * GL Renderbuffer. + * + * Wraps clCreateFromGLRenderbuffer(). + */ + BufferRenderGL( + const Context& context, + cl_mem_flags flags, + cl_GLuint bufobj, + cl_int * err = NULL) + { + cl_int error; + object_ = ::clCreateFromGLRenderbuffer( + context(), + flags, + bufobj, + &error); + + detail::errHandler(error, __CREATE_GL_RENDER_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } + + //! \brief Default constructor - initializes to NULL. + BufferRenderGL() : Buffer() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + * See Memory for further details. + */ + explicit BufferRenderGL(const cl_mem& buffer, bool retainObject = false) : + Buffer(buffer, retainObject) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + BufferRenderGL& operator = (const cl_mem& rhs) + { + Buffer::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + BufferRenderGL(const BufferRenderGL& buf) : Buffer(buf) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + BufferRenderGL& operator = (const BufferRenderGL &buf) + { + Buffer::operator=(buf); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + BufferRenderGL(BufferRenderGL&& buf) CL_HPP_NOEXCEPT_ : Buffer(std::move(buf)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + BufferRenderGL& operator = (BufferRenderGL &&buf) + { + Buffer::operator=(std::move(buf)); + return *this; + } + + //! \brief Wrapper for clGetGLObjectInfo(). + cl_int getObjectInfo( + cl_gl_object_type *type, + cl_GLuint * gl_object_name) + { + return detail::errHandler( + ::clGetGLObjectInfo(object_,type,gl_object_name), + __GET_GL_OBJECT_INFO_ERR); + } +}; + +/*! \brief C++ base class for Image Memory objects. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class Image : public Memory +{ +protected: + //! \brief Default constructor - initializes to NULL. + Image() : Memory() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + * See Memory for further details. + */ + explicit Image(const cl_mem& image, bool retainObject = false) : + Memory(image, retainObject) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Image& operator = (const cl_mem& rhs) + { + Memory::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image(const Image& img) : Memory(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image& operator = (const Image &img) + { + Memory::operator=(img); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image(Image&& img) CL_HPP_NOEXCEPT_ : Memory(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image& operator = (Image &&img) + { + Memory::operator=(std::move(img)); + return *this; + } + + +public: + //! \brief Wrapper for clGetImageInfo(). + template + cl_int getImageInfo(cl_image_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetImageInfo, object_, name, param), + __GET_IMAGE_INFO_ERR); + } + + //! \brief Wrapper for clGetImageInfo() that returns by value. + template typename + detail::param_traits::param_type + getImageInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_image_info, name>::param_type param; + cl_int result = getImageInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } +}; + +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 +/*! \brief Class interface for 1D Image Memory objects. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class Image1D : public Image +{ +public: + /*! \brief Constructs a 1D Image in a specified context. + * + * Wraps clCreateImage(). + */ + Image1D( + const Context& context, + cl_mem_flags flags, + ImageFormat format, + size_type width, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE1D, + width, + 0, 0, 0, 0, 0, 0, 0, 0 + }; + object_ = ::clCreateImage( + context(), + flags, + &format, + &desc, + host_ptr, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + } + + //! \brief Default constructor - initializes to NULL. + Image1D() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + * See Memory for further details. + */ + explicit Image1D(const cl_mem& image1D, bool retainObject = false) : + Image(image1D, retainObject) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Image1D& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image1D(const Image1D& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image1D& operator = (const Image1D &img) + { + Image::operator=(img); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image1D(Image1D&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image1D& operator = (Image1D &&img) + { + Image::operator=(std::move(img)); + return *this; + } + +}; + +/*! \class Image1DBuffer + * \brief Image interface for 1D buffer images. + */ +class Image1DBuffer : public Image +{ +public: + Image1DBuffer( + const Context& context, + cl_mem_flags flags, + ImageFormat format, + size_type width, + const Buffer &buffer, + cl_int* err = NULL) + { + cl_int error; + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE1D_BUFFER, + width, + 0, 0, 0, 0, 0, 0, 0, + buffer() + }; + object_ = ::clCreateImage( + context(), + flags, + &format, + &desc, + NULL, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + } + + Image1DBuffer() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + * See Memory for further details. + */ + explicit Image1DBuffer(const cl_mem& image1D, bool retainObject = false) : + Image(image1D, retainObject) { } + + Image1DBuffer& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image1DBuffer(const Image1DBuffer& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image1DBuffer& operator = (const Image1DBuffer &img) + { + Image::operator=(img); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image1DBuffer(Image1DBuffer&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image1DBuffer& operator = (Image1DBuffer &&img) + { + Image::operator=(std::move(img)); + return *this; + } + +}; + +/*! \class Image1DArray + * \brief Image interface for arrays of 1D images. + */ +class Image1DArray : public Image +{ +public: + Image1DArray( + const Context& context, + cl_mem_flags flags, + ImageFormat format, + size_type arraySize, + size_type width, + size_type rowPitch, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE1D_ARRAY, + width, + 0, 0, // height, depth (unused) + arraySize, + rowPitch, + 0, 0, 0, 0 + }; + object_ = ::clCreateImage( + context(), + flags, + &format, + &desc, + host_ptr, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + } + + Image1DArray() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + * See Memory for further details. + */ + explicit Image1DArray(const cl_mem& imageArray, bool retainObject = false) : + Image(imageArray, retainObject) { } + + + Image1DArray& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image1DArray(const Image1DArray& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image1DArray& operator = (const Image1DArray &img) + { + Image::operator=(img); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image1DArray(Image1DArray&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image1DArray& operator = (Image1DArray &&img) + { + Image::operator=(std::move(img)); + return *this; + } + +}; +#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 120 + + +/*! \brief Class interface for 2D Image Memory objects. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class Image2D : public Image +{ +public: + /*! \brief Constructs a 2D Image in a specified context. + * + * Wraps clCreateImage(). + */ + Image2D( + const Context& context, + cl_mem_flags flags, + ImageFormat format, + size_type width, + size_type height, + size_type row_pitch = 0, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + bool useCreateImage; + +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 && CL_HPP_MINIMUM_OPENCL_VERSION < 120 + // Run-time decision based on the actual platform + { + cl_uint version = detail::getContextPlatformVersion(context()); + useCreateImage = (version >= 0x10002); // OpenCL 1.2 or above + } +#elif CL_HPP_TARGET_OPENCL_VERSION >= 120 + useCreateImage = true; +#else + useCreateImage = false; +#endif + +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 + if (useCreateImage) + { + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE2D, + width, + height, + 0, 0, // depth, array size (unused) + row_pitch, + 0, 0, 0, 0 + }; + object_ = ::clCreateImage( + context(), + flags, + &format, + &desc, + host_ptr, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + } +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 +#if CL_HPP_MINIMUM_OPENCL_VERSION < 120 + if (!useCreateImage) + { + object_ = ::clCreateImage2D( + context(), flags,&format, width, height, row_pitch, host_ptr, &error); + + detail::errHandler(error, __CREATE_IMAGE2D_ERR); + if (err != NULL) { + *err = error; + } + } +#endif // CL_HPP_MINIMUM_OPENCL_VERSION < 120 + } + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 + /*! \brief Constructs a 2D Image from a buffer. + * \note This will share storage with the underlying buffer. + * + * Wraps clCreateImage(). + */ + Image2D( + const Context& context, + ImageFormat format, + const Buffer &sourceBuffer, + size_type width, + size_type height, + size_type row_pitch = 0, + cl_int* err = nullptr) + { + cl_int error; + + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE2D, + width, + height, + 0, 0, // depth, array size (unused) + row_pitch, + 0, 0, 0, + // Use buffer as input to image + sourceBuffer() + }; + object_ = ::clCreateImage( + context(), + 0, // flags inherited from buffer + &format, + &desc, + nullptr, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != nullptr) { + *err = error; + } + } +#endif //#if CL_HPP_TARGET_OPENCL_VERSION >= 200 + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 + /*! \brief Constructs a 2D Image from an image. + * \note This will share storage with the underlying image but may + * reinterpret the channel order and type. + * + * The image will be created matching with a descriptor matching the source. + * + * \param order is the channel order to reinterpret the image data as. + * The channel order may differ as described in the OpenCL + * 2.0 API specification. + * + * Wraps clCreateImage(). + */ + Image2D( + const Context& context, + cl_channel_order order, + const Image &sourceImage, + cl_int* err = nullptr) + { + cl_int error; + + // Descriptor fields have to match source image + size_type sourceWidth = + sourceImage.getImageInfo(); + size_type sourceHeight = + sourceImage.getImageInfo(); + size_type sourceRowPitch = + sourceImage.getImageInfo(); + cl_uint sourceNumMIPLevels = + sourceImage.getImageInfo(); + cl_uint sourceNumSamples = + sourceImage.getImageInfo(); + cl_image_format sourceFormat = + sourceImage.getImageInfo(); + + // Update only the channel order. + // Channel format inherited from source. + sourceFormat.image_channel_order = order; + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE2D, + sourceWidth, + sourceHeight, + 0, 0, // depth (unused), array size (unused) + sourceRowPitch, + 0, // slice pitch (unused) + sourceNumMIPLevels, + sourceNumSamples, + // Use buffer as input to image + sourceImage() + }; + object_ = ::clCreateImage( + context(), + 0, // flags should be inherited from mem_object + &sourceFormat, + &desc, + nullptr, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != nullptr) { + *err = error; + } + } +#endif //#if CL_HPP_TARGET_OPENCL_VERSION >= 200 + + //! \brief Default constructor - initializes to NULL. + Image2D() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + * See Memory for further details. + */ + explicit Image2D(const cl_mem& image2D, bool retainObject = false) : + Image(image2D, retainObject) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Image2D& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image2D(const Image2D& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image2D& operator = (const Image2D &img) + { + Image::operator=(img); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image2D(Image2D&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image2D& operator = (Image2D &&img) + { + Image::operator=(std::move(img)); + return *this; + } + +}; + + +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) +/*! \brief Class interface for GL 2D Image Memory objects. + * + * This is provided to facilitate interoperability with OpenGL. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + * \note Deprecated for OpenCL 1.2. Please use ImageGL instead. + */ +class CL_EXT_PREFIX__VERSION_1_1_DEPRECATED Image2DGL : public Image2D +{ +public: + /*! \brief Constructs an Image2DGL in a specified context, from a given + * GL Texture. + * + * Wraps clCreateFromGLTexture2D(). + */ + Image2DGL( + const Context& context, + cl_mem_flags flags, + cl_GLenum target, + cl_GLint miplevel, + cl_GLuint texobj, + cl_int * err = NULL) + { + cl_int error; + object_ = ::clCreateFromGLTexture2D( + context(), + flags, + target, + miplevel, + texobj, + &error); + + detail::errHandler(error, __CREATE_GL_TEXTURE_2D_ERR); + if (err != NULL) { + *err = error; + } + + } + + //! \brief Default constructor - initializes to NULL. + Image2DGL() : Image2D() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + * See Memory for further details. + */ + explicit Image2DGL(const cl_mem& image, bool retainObject = false) : + Image2D(image, retainObject) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + *c + * See Memory for further details. + */ + Image2DGL& operator = (const cl_mem& rhs) + { + Image2D::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image2DGL(const Image2DGL& img) : Image2D(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image2DGL& operator = (const Image2DGL &img) + { + Image2D::operator=(img); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image2DGL(Image2DGL&& img) CL_HPP_NOEXCEPT_ : Image2D(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image2DGL& operator = (Image2DGL &&img) + { + Image2D::operator=(std::move(img)); + return *this; + } + +} CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED; +#endif // CL_USE_DEPRECATED_OPENCL_1_1_APIS + +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 +/*! \class Image2DArray + * \brief Image interface for arrays of 2D images. + */ +class Image2DArray : public Image +{ +public: + Image2DArray( + const Context& context, + cl_mem_flags flags, + ImageFormat format, + size_type arraySize, + size_type width, + size_type height, + size_type rowPitch, + size_type slicePitch, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE2D_ARRAY, + width, + height, + 0, // depth (unused) + arraySize, + rowPitch, + slicePitch, + 0, 0, 0 + }; + object_ = ::clCreateImage( + context(), + flags, + &format, + &desc, + host_ptr, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + } + + Image2DArray() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + * See Memory for further details. + */ + explicit Image2DArray(const cl_mem& imageArray, bool retainObject = false) : Image(imageArray, retainObject) { } + + Image2DArray& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image2DArray(const Image2DArray& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image2DArray& operator = (const Image2DArray &img) + { + Image::operator=(img); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image2DArray(Image2DArray&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image2DArray& operator = (Image2DArray &&img) + { + Image::operator=(std::move(img)); + return *this; + } +}; +#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 120 + +/*! \brief Class interface for 3D Image Memory objects. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class Image3D : public Image +{ +public: + /*! \brief Constructs a 3D Image in a specified context. + * + * Wraps clCreateImage(). + */ + Image3D( + const Context& context, + cl_mem_flags flags, + ImageFormat format, + size_type width, + size_type height, + size_type depth, + size_type row_pitch = 0, + size_type slice_pitch = 0, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + bool useCreateImage; + +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 && CL_HPP_MINIMUM_OPENCL_VERSION < 120 + // Run-time decision based on the actual platform + { + cl_uint version = detail::getContextPlatformVersion(context()); + useCreateImage = (version >= 0x10002); // OpenCL 1.2 or above + } +#elif CL_HPP_TARGET_OPENCL_VERSION >= 120 + useCreateImage = true; +#else + useCreateImage = false; +#endif + +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 + if (useCreateImage) + { + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE3D, + width, + height, + depth, + 0, // array size (unused) + row_pitch, + slice_pitch, + 0, 0, 0 + }; + object_ = ::clCreateImage( + context(), + flags, + &format, + &desc, + host_ptr, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + } +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 +#if CL_HPP_MINIMUM_OPENCL_VERSION < 120 + if (!useCreateImage) + { + object_ = ::clCreateImage3D( + context(), flags, &format, width, height, depth, row_pitch, + slice_pitch, host_ptr, &error); + + detail::errHandler(error, __CREATE_IMAGE3D_ERR); + if (err != NULL) { + *err = error; + } + } +#endif // CL_HPP_MINIMUM_OPENCL_VERSION < 120 + } + + //! \brief Default constructor - initializes to NULL. + Image3D() : Image() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + * See Memory for further details. + */ + explicit Image3D(const cl_mem& image3D, bool retainObject = false) : + Image(image3D, retainObject) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Image3D& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image3D(const Image3D& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image3D& operator = (const Image3D &img) + { + Image::operator=(img); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image3D(Image3D&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image3D& operator = (Image3D &&img) + { + Image::operator=(std::move(img)); + return *this; + } +}; + +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) +/*! \brief Class interface for GL 3D Image Memory objects. + * + * This is provided to facilitate interoperability with OpenGL. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class Image3DGL : public Image3D +{ +public: + /*! \brief Constructs an Image3DGL in a specified context, from a given + * GL Texture. + * + * Wraps clCreateFromGLTexture3D(). + */ + Image3DGL( + const Context& context, + cl_mem_flags flags, + cl_GLenum target, + cl_GLint miplevel, + cl_GLuint texobj, + cl_int * err = NULL) + { + cl_int error; + object_ = ::clCreateFromGLTexture3D( + context(), + flags, + target, + miplevel, + texobj, + &error); + + detail::errHandler(error, __CREATE_GL_TEXTURE_3D_ERR); + if (err != NULL) { + *err = error; + } + } + + //! \brief Default constructor - initializes to NULL. + Image3DGL() : Image3D() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + * See Memory for further details. + */ + explicit Image3DGL(const cl_mem& image, bool retainObject = false) : + Image3D(image, retainObject) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Image3DGL& operator = (const cl_mem& rhs) + { + Image3D::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image3DGL(const Image3DGL& img) : Image3D(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image3DGL& operator = (const Image3DGL &img) + { + Image3D::operator=(img); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image3DGL(Image3DGL&& img) CL_HPP_NOEXCEPT_ : Image3D(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image3DGL& operator = (Image3DGL &&img) + { + Image3D::operator=(std::move(img)); + return *this; + } +}; +#endif // CL_USE_DEPRECATED_OPENCL_1_1_APIS + +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 +/*! \class ImageGL + * \brief general image interface for GL interop. + * We abstract the 2D and 3D GL images into a single instance here + * that wraps all GL sourced images on the grounds that setup information + * was performed by OpenCL anyway. + */ +class ImageGL : public Image +{ +public: + ImageGL( + const Context& context, + cl_mem_flags flags, + cl_GLenum target, + cl_GLint miplevel, + cl_GLuint texobj, + cl_int * err = NULL) + { + cl_int error; + object_ = ::clCreateFromGLTexture( + context(), + flags, + target, + miplevel, + texobj, + &error); + + detail::errHandler(error, __CREATE_GL_TEXTURE_ERR); + if (err != NULL) { + *err = error; + } + } + + ImageGL() : Image() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + * See Memory for further details. + */ + explicit ImageGL(const cl_mem& image, bool retainObject = false) : + Image(image, retainObject) { } + + ImageGL& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + ImageGL(const ImageGL& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + ImageGL& operator = (const ImageGL &img) + { + Image::operator=(img); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + ImageGL(ImageGL&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + ImageGL& operator = (ImageGL &&img) + { + Image::operator=(std::move(img)); + return *this; + } +}; +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 + + + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 +/*! \brief Class interface for Pipe Memory Objects. +* +* See Memory for details about copy semantics, etc. +* +* \see Memory +*/ +class Pipe : public Memory +{ +public: + + /*! \brief Constructs a Pipe in a specified context. + * + * Wraps clCreatePipe(). + * @param context Context in which to create the pipe. + * @param flags Bitfield. Only CL_MEM_READ_WRITE and CL_MEM_HOST_NO_ACCESS are valid. + * @param packet_size Size in bytes of a single packet of the pipe. + * @param max_packets Number of packets that may be stored in the pipe. + * + */ + Pipe( + const Context& context, + cl_uint packet_size, + cl_uint max_packets, + cl_int* err = NULL) + { + cl_int error; + + cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_HOST_NO_ACCESS; + object_ = ::clCreatePipe(context(), flags, packet_size, max_packets, nullptr, &error); + + detail::errHandler(error, __CREATE_PIPE_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! \brief Constructs a Pipe in a the default context. + * + * Wraps clCreatePipe(). + * @param flags Bitfield. Only CL_MEM_READ_WRITE and CL_MEM_HOST_NO_ACCESS are valid. + * @param packet_size Size in bytes of a single packet of the pipe. + * @param max_packets Number of packets that may be stored in the pipe. + * + */ + Pipe( + cl_uint packet_size, + cl_uint max_packets, + cl_int* err = NULL) + { + cl_int error; + + Context context = Context::getDefault(err); + + cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_HOST_NO_ACCESS; + object_ = ::clCreatePipe(context(), flags, packet_size, max_packets, nullptr, &error); + + detail::errHandler(error, __CREATE_PIPE_ERR); + if (err != NULL) { + *err = error; + } + } + + //! \brief Default constructor - initializes to NULL. + Pipe() : Memory() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with earlier versions. + * + * See Memory for further details. + */ + explicit Pipe(const cl_mem& pipe, bool retainObject = false) : + Memory(pipe, retainObject) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Pipe& operator = (const cl_mem& rhs) + { + Memory::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Pipe(const Pipe& pipe) : Memory(pipe) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Pipe& operator = (const Pipe &pipe) + { + Memory::operator=(pipe); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Pipe(Pipe&& pipe) CL_HPP_NOEXCEPT_ : Memory(std::move(pipe)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Pipe& operator = (Pipe &&pipe) + { + Memory::operator=(std::move(pipe)); + return *this; + } + + //! \brief Wrapper for clGetMemObjectInfo(). + template + cl_int getInfo(cl_pipe_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetPipeInfo, object_, name, param), + __GET_PIPE_INFO_ERR); + } + + //! \brief Wrapper for clGetMemObjectInfo() that returns by value. + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_pipe_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } +}; // class Pipe +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 200 + + +/*! \brief Class interface for cl_sampler. + * + * \note Copies of these objects are shallow, meaning that the copy will refer + * to the same underlying cl_sampler as the original. For details, see + * clRetainSampler() and clReleaseSampler(). + * + * \see cl_sampler + */ +class Sampler : public detail::Wrapper +{ +public: + //! \brief Default constructor - initializes to NULL. + Sampler() { } + + /*! \brief Constructs a Sampler in a specified context. + * + * Wraps clCreateSampler(). + */ + Sampler( + const Context& context, + cl_bool normalized_coords, + cl_addressing_mode addressing_mode, + cl_filter_mode filter_mode, + cl_int* err = NULL) + { + cl_int error; + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 + cl_sampler_properties sampler_properties[] = { + CL_SAMPLER_NORMALIZED_COORDS, normalized_coords, + CL_SAMPLER_ADDRESSING_MODE, addressing_mode, + CL_SAMPLER_FILTER_MODE, filter_mode, + 0 }; + object_ = ::clCreateSamplerWithProperties( + context(), + sampler_properties, + &error); + + detail::errHandler(error, __CREATE_SAMPLER_WITH_PROPERTIES_ERR); + if (err != NULL) { + *err = error; + } +#else + object_ = ::clCreateSampler( + context(), + normalized_coords, + addressing_mode, + filter_mode, + &error); + + detail::errHandler(error, __CREATE_SAMPLER_ERR); + if (err != NULL) { + *err = error; + } +#endif + } + + /*! \brief Constructor from cl_sampler - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + * This effectively transfers ownership of a refcount on the cl_sampler + * into the new Sampler object. + */ + explicit Sampler(const cl_sampler& sampler, bool retainObject = false) : + detail::Wrapper(sampler, retainObject) { } + + /*! \brief Assignment operator from cl_sampler - takes ownership. + * + * This effectively transfers ownership of a refcount on the rhs and calls + * clReleaseSampler() on the value previously held by this instance. + */ + Sampler& operator = (const cl_sampler& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Sampler(const Sampler& sam) : detail::Wrapper(sam) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Sampler& operator = (const Sampler &sam) + { + detail::Wrapper::operator=(sam); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Sampler(Sampler&& sam) CL_HPP_NOEXCEPT_ : detail::Wrapper(std::move(sam)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Sampler& operator = (Sampler &&sam) + { + detail::Wrapper::operator=(std::move(sam)); + return *this; + } + + //! \brief Wrapper for clGetSamplerInfo(). + template + cl_int getInfo(cl_sampler_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetSamplerInfo, object_, name, param), + __GET_SAMPLER_INFO_ERR); + } + + //! \brief Wrapper for clGetSamplerInfo() that returns by value. + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_sampler_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } +}; + +class Program; +class CommandQueue; +class DeviceCommandQueue; +class Kernel; + +//! \brief Class interface for specifying NDRange values. +class NDRange +{ +private: + size_type sizes_[3]; + cl_uint dimensions_; + +public: + //! \brief Default constructor - resulting range has zero dimensions. + NDRange() + : dimensions_(0) + { + sizes_[0] = 0; + sizes_[1] = 0; + sizes_[2] = 0; + } + + //! \brief Constructs one-dimensional range. + NDRange(size_type size0) + : dimensions_(1) + { + sizes_[0] = size0; + sizes_[1] = 1; + sizes_[2] = 1; + } + + //! \brief Constructs two-dimensional range. + NDRange(size_type size0, size_type size1) + : dimensions_(2) + { + sizes_[0] = size0; + sizes_[1] = size1; + sizes_[2] = 1; + } + + //! \brief Constructs three-dimensional range. + NDRange(size_type size0, size_type size1, size_type size2) + : dimensions_(3) + { + sizes_[0] = size0; + sizes_[1] = size1; + sizes_[2] = size2; + } + + /*! \brief Conversion operator to const size_type *. + * + * \returns a pointer to the size of the first dimension. + */ + operator const size_type*() const { + return sizes_; + } + + //! \brief Queries the number of dimensions in the range. + size_type dimensions() const + { + return dimensions_; + } + + //! \brief Returns the size of the object in bytes based on the + // runtime number of dimensions + size_type size() const + { + return dimensions_*sizeof(size_type); + } + + size_type* get() + { + return sizes_; + } + + const size_type* get() const + { + return sizes_; + } +}; + +//! \brief A zero-dimensional range. +static const NDRange NullRange; + +//! \brief Local address wrapper for use with Kernel::setArg +struct LocalSpaceArg +{ + size_type size_; +}; + +namespace detail { + +template +struct KernelArgumentHandler; + +// Enable for objects that are not subclasses of memory +// Pointers, constants etc +template +struct KernelArgumentHandler::value>::type> +{ + static size_type size(const T&) { return sizeof(T); } + static const T* ptr(const T& value) { return &value; } +}; + +// Enable for subclasses of memory where we want to get a reference to the cl_mem out +// and pass that in for safety +template +struct KernelArgumentHandler::value>::type> +{ + static size_type size(const T&) { return sizeof(cl_mem); } + static const cl_mem* ptr(const T& value) { return &(value()); } +}; + +// Specialization for DeviceCommandQueue defined later + +template <> +struct KernelArgumentHandler +{ + static size_type size(const LocalSpaceArg& value) { return value.size_; } + static const void* ptr(const LocalSpaceArg&) { return NULL; } +}; + +} +//! \endcond + +/*! Local + * \brief Helper function for generating LocalSpaceArg objects. + */ +inline LocalSpaceArg +Local(size_type size) +{ + LocalSpaceArg ret = { size }; + return ret; +} + +/*! \brief Class interface for cl_kernel. + * + * \note Copies of these objects are shallow, meaning that the copy will refer + * to the same underlying cl_kernel as the original. For details, see + * clRetainKernel() and clReleaseKernel(). + * + * \see cl_kernel + */ +class Kernel : public detail::Wrapper +{ +public: + inline Kernel(const Program& program, const char* name, cl_int* err = NULL); + + //! \brief Default constructor - initializes to NULL. + Kernel() { } + + /*! \brief Constructor from cl_kernel - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + * This effectively transfers ownership of a refcount on the cl_kernel + * into the new Kernel object. + */ + explicit Kernel(const cl_kernel& kernel, bool retainObject = false) : + detail::Wrapper(kernel, retainObject) { } + + /*! \brief Assignment operator from cl_kernel - takes ownership. + * + * This effectively transfers ownership of a refcount on the rhs and calls + * clReleaseKernel() on the value previously held by this instance. + */ + Kernel& operator = (const cl_kernel& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Kernel(const Kernel& kernel) : detail::Wrapper(kernel) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Kernel& operator = (const Kernel &kernel) + { + detail::Wrapper::operator=(kernel); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Kernel(Kernel&& kernel) CL_HPP_NOEXCEPT_ : detail::Wrapper(std::move(kernel)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Kernel& operator = (Kernel &&kernel) + { + detail::Wrapper::operator=(std::move(kernel)); + return *this; + } + + template + cl_int getInfo(cl_kernel_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetKernelInfo, object_, name, param), + __GET_KERNEL_INFO_ERR); + } + + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_kernel_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 + template + cl_int getArgInfo(cl_uint argIndex, cl_kernel_arg_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetKernelArgInfo, object_, argIndex, name, param), + __GET_KERNEL_ARG_INFO_ERR); + } + + template typename + detail::param_traits::param_type + getArgInfo(cl_uint argIndex, cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_kernel_arg_info, name>::param_type param; + cl_int result = getArgInfo(argIndex, name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 + + template + cl_int getWorkGroupInfo( + const Device& device, cl_kernel_work_group_info name, T* param) const + { + return detail::errHandler( + detail::getInfo( + &::clGetKernelWorkGroupInfo, object_, device(), name, param), + __GET_KERNEL_WORK_GROUP_INFO_ERR); + } + + template typename + detail::param_traits::param_type + getWorkGroupInfo(const Device& device, cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_kernel_work_group_info, name>::param_type param; + cl_int result = getWorkGroupInfo(device, name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 +#if defined(CL_HPP_USE_CL_SUB_GROUPS_KHR) + cl_int getSubGroupInfo(const cl::Device &dev, cl_kernel_sub_group_info name, const cl::NDRange &range, size_type* param) const + { + typedef clGetKernelSubGroupInfoKHR_fn PFN_clGetKernelSubGroupInfoKHR; + static PFN_clGetKernelSubGroupInfoKHR pfn_clGetKernelSubGroupInfoKHR = NULL; + CL_HPP_INIT_CL_EXT_FCN_PTR_(clGetKernelSubGroupInfoKHR); + + return detail::errHandler( + pfn_clGetKernelSubGroupInfoKHR(object_, dev(), name, range.size(), range.get(), sizeof(size_type), param, nullptr), + __GET_KERNEL_ARG_INFO_ERR); + } + + template + size_type getSubGroupInfo(const cl::Device &dev, const cl::NDRange &range, cl_int* err = NULL) const + { + size_type param; + cl_int result = getSubGroupInfo(dev, name, range, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } +#endif // #if defined(CL_HPP_USE_CL_SUB_GROUPS_KHR) +#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200 + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 + /*! \brief setArg overload taking a shared_ptr type + */ + template + cl_int setArg(cl_uint index, const cl::pointer &argPtr) + { + return detail::errHandler( + ::clSetKernelArgSVMPointer(object_, index, argPtr.get()), + __SET_KERNEL_ARGS_ERR); + } + + /*! \brief setArg overload taking a vector type. + */ + template + cl_int setArg(cl_uint index, const cl::vector &argPtr) + { + return detail::errHandler( + ::clSetKernelArgSVMPointer(object_, index, argPtr.data()), + __SET_KERNEL_ARGS_ERR); + } + + /*! \brief setArg overload taking a pointer type + */ + template + typename std::enable_if::value, cl_int>::type + setArg(cl_uint index, const T argPtr) + { + return detail::errHandler( + ::clSetKernelArgSVMPointer(object_, index, argPtr), + __SET_KERNEL_ARGS_ERR); + } +#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200 + + /*! \brief setArg overload taking a POD type + */ + template + typename std::enable_if::value, cl_int>::type + setArg(cl_uint index, const T &value) + { + return detail::errHandler( + ::clSetKernelArg( + object_, + index, + detail::KernelArgumentHandler::size(value), + detail::KernelArgumentHandler::ptr(value)), + __SET_KERNEL_ARGS_ERR); + } + + cl_int setArg(cl_uint index, size_type size, const void* argPtr) + { + return detail::errHandler( + ::clSetKernelArg(object_, index, size, argPtr), + __SET_KERNEL_ARGS_ERR); + } + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 + /*! + * Specify a vector of SVM pointers that the kernel may access in + * addition to its arguments. + */ + cl_int setSVMPointers(const vector &pointerList) + { + return detail::errHandler( + ::clSetKernelExecInfo( + object_, + CL_KERNEL_EXEC_INFO_SVM_PTRS, + sizeof(void*)*pointerList.size(), + pointerList.data())); + } + + /*! + * Specify a std::array of SVM pointers that the kernel may access in + * addition to its arguments. + */ + template + cl_int setSVMPointers(const std::array &pointerList) + { + return detail::errHandler( + ::clSetKernelExecInfo( + object_, + CL_KERNEL_EXEC_INFO_SVM_PTRS, + sizeof(void*)*pointerList.size(), + pointerList.data())); + } + + /*! \brief Enable fine-grained system SVM. + * + * \note It is only possible to enable fine-grained system SVM if all devices + * in the context associated with kernel support it. + * + * \param svmEnabled True if fine-grained system SVM is requested. False otherwise. + * \return CL_SUCCESS if the function was executed successfully. CL_INVALID_OPERATION + * if no devices in the context support fine-grained system SVM. + * + * \see clSetKernelExecInfo + */ + cl_int enableFineGrainedSystemSVM(bool svmEnabled) + { + cl_bool svmEnabled_ = svmEnabled ? CL_TRUE : CL_FALSE; + return detail::errHandler( + ::clSetKernelExecInfo( + object_, + CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM, + sizeof(cl_bool), + &svmEnabled_ + ) + ); + } + + template + void setSVMPointersHelper(std::array &pointerList, const pointer &t0, Ts... ts) + { + pointerList[index] = static_cast(t0.get()); + setSVMPointersHelper(ts...); + } + + template + typename std::enable_if::value, void>::type + setSVMPointersHelper(std::array &pointerList, T0 t0, Ts... ts) + { + pointerList[index] = static_cast(t0); + setSVMPointersHelper(ts...); + } + + template + void setSVMPointersHelper(std::array &pointerList, const pointer &t0) + { + pointerList[index] = static_cast(t0.get()); + } + + template + typename std::enable_if::value, void>::type + setSVMPointersHelper(std::array &pointerList, T0 t0) + { + pointerList[index] = static_cast(t0); + } + + template + cl_int setSVMPointers(const T0 &t0, Ts... ts) + { + std::array pointerList; + + setSVMPointersHelper<0, 1 + sizeof...(Ts)>(pointerList, t0, ts...); + return detail::errHandler( + ::clSetKernelExecInfo( + object_, + CL_KERNEL_EXEC_INFO_SVM_PTRS, + sizeof(void*)*(1 + sizeof...(Ts)), + pointerList.data())); + } +#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200 +}; + +/*! \class Program + * \brief Program interface that implements cl_program. + */ +class Program : public detail::Wrapper +{ +public: +#if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY) + typedef vector> Binaries; + typedef vector Sources; +#else // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY) + typedef vector > Binaries; + typedef vector > Sources; +#endif // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY) + + Program( + const string& source, + bool build = false, + cl_int* err = NULL) + { + cl_int error; + + const char * strings = source.c_str(); + const size_type length = source.size(); + + Context context = Context::getDefault(err); + + object_ = ::clCreateProgramWithSource( + context(), (cl_uint)1, &strings, &length, &error); + + detail::errHandler(error, __CREATE_PROGRAM_WITH_SOURCE_ERR); + + if (error == CL_SUCCESS && build) { + + error = ::clBuildProgram( + object_, + 0, + NULL, +#if !defined(CL_HPP_CL_1_2_DEFAULT_BUILD) + "-cl-std=CL2.0", +#else + "", +#endif // #if !defined(CL_HPP_CL_1_2_DEFAULT_BUILD) + NULL, + NULL); + + detail::buildErrHandler(error, __BUILD_PROGRAM_ERR, getBuildInfo()); + } + + if (err != NULL) { + *err = error; + } + } + + Program( + const Context& context, + const string& source, + bool build = false, + cl_int* err = NULL) + { + cl_int error; + + const char * strings = source.c_str(); + const size_type length = source.size(); + + object_ = ::clCreateProgramWithSource( + context(), (cl_uint)1, &strings, &length, &error); + + detail::errHandler(error, __CREATE_PROGRAM_WITH_SOURCE_ERR); + + if (error == CL_SUCCESS && build) { + error = ::clBuildProgram( + object_, + 0, + NULL, +#if !defined(CL_HPP_CL_1_2_DEFAULT_BUILD) + "-cl-std=CL2.0", +#else + "", +#endif // #if !defined(CL_HPP_CL_1_2_DEFAULT_BUILD) + NULL, + NULL); + + detail::buildErrHandler(error, __BUILD_PROGRAM_ERR, getBuildInfo()); + } + + if (err != NULL) { + *err = error; + } + } + + /** + * Create a program from a vector of source strings and the default context. + * Does not compile or link the program. + */ + Program( + const Sources& sources, + cl_int* err = NULL) + { + cl_int error; + Context context = Context::getDefault(err); + + const size_type n = (size_type)sources.size(); + + vector lengths(n); + vector strings(n); + + for (size_type i = 0; i < n; ++i) { +#if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY) + strings[i] = sources[(int)i].data(); + lengths[i] = sources[(int)i].length(); +#else // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY) + strings[i] = sources[(int)i].first; + lengths[i] = sources[(int)i].second; +#endif // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY) + } + + object_ = ::clCreateProgramWithSource( + context(), (cl_uint)n, strings.data(), lengths.data(), &error); + + detail::errHandler(error, __CREATE_PROGRAM_WITH_SOURCE_ERR); + if (err != NULL) { + *err = error; + } + } + + /** + * Create a program from a vector of source strings and a provided context. + * Does not compile or link the program. + */ + Program( + const Context& context, + const Sources& sources, + cl_int* err = NULL) + { + cl_int error; + + const size_type n = (size_type)sources.size(); + + vector lengths(n); + vector strings(n); + + for (size_type i = 0; i < n; ++i) { +#if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY) + strings[i] = sources[(int)i].data(); + lengths[i] = sources[(int)i].length(); +#else // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY) + strings[i] = sources[(int)i].first; + lengths[i] = sources[(int)i].second; +#endif // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY) + } + + object_ = ::clCreateProgramWithSource( + context(), (cl_uint)n, strings.data(), lengths.data(), &error); + + detail::errHandler(error, __CREATE_PROGRAM_WITH_SOURCE_ERR); + if (err != NULL) { + *err = error; + } + } + + /** + * Construct a program object from a list of devices and a per-device list of binaries. + * \param context A valid OpenCL context in which to construct the program. + * \param devices A vector of OpenCL device objects for which the program will be created. + * \param binaries A vector of pairs of a pointer to a binary object and its length. + * \param binaryStatus An optional vector that on completion will be resized to + * match the size of binaries and filled with values to specify if each binary + * was successfully loaded. + * Set to CL_SUCCESS if the binary was successfully loaded. + * Set to CL_INVALID_VALUE if the length is 0 or the binary pointer is NULL. + * Set to CL_INVALID_BINARY if the binary provided is not valid for the matching device. + * \param err if non-NULL will be set to CL_SUCCESS on successful operation or one of the following errors: + * CL_INVALID_CONTEXT if context is not a valid context. + * CL_INVALID_VALUE if the length of devices is zero; or if the length of binaries does not match the length of devices; + * or if any entry in binaries is NULL or has length 0. + * CL_INVALID_DEVICE if OpenCL devices listed in devices are not in the list of devices associated with context. + * CL_INVALID_BINARY if an invalid program binary was encountered for any device. binaryStatus will return specific status for each device. + * CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources required by the OpenCL implementation on the host. + */ + Program( + const Context& context, + const vector& devices, + const Binaries& binaries, + vector* binaryStatus = NULL, + cl_int* err = NULL) + { + cl_int error; + + const size_type numDevices = devices.size(); + + // Catch size mismatch early and return + if(binaries.size() != numDevices) { + error = CL_INVALID_VALUE; + detail::errHandler(error, __CREATE_PROGRAM_WITH_BINARY_ERR); + if (err != NULL) { + *err = error; + } + return; + } + + + vector lengths(numDevices); + vector images(numDevices); +#if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY) + for (size_type i = 0; i < numDevices; ++i) { + images[i] = binaries[i].data(); + lengths[i] = binaries[(int)i].size(); + } +#else // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY) + for (size_type i = 0; i < numDevices; ++i) { + images[i] = (const unsigned char*)binaries[i].first; + lengths[i] = binaries[(int)i].second; + } +#endif // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY) + + vector deviceIDs(numDevices); + for( size_type deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) { + deviceIDs[deviceIndex] = (devices[deviceIndex])(); + } + + if(binaryStatus) { + binaryStatus->resize(numDevices); + } + + object_ = ::clCreateProgramWithBinary( + context(), (cl_uint) devices.size(), + deviceIDs.data(), + lengths.data(), images.data(), (binaryStatus != NULL && numDevices > 0) + ? &binaryStatus->front() + : NULL, &error); + + detail::errHandler(error, __CREATE_PROGRAM_WITH_BINARY_ERR); + if (err != NULL) { + *err = error; + } + } + + +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 + /** + * Create program using builtin kernels. + * \param kernelNames Semi-colon separated list of builtin kernel names + */ + Program( + const Context& context, + const vector& devices, + const string& kernelNames, + cl_int* err = NULL) + { + cl_int error; + + + size_type numDevices = devices.size(); + vector deviceIDs(numDevices); + for( size_type deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) { + deviceIDs[deviceIndex] = (devices[deviceIndex])(); + } + + object_ = ::clCreateProgramWithBuiltInKernels( + context(), + (cl_uint) devices.size(), + deviceIDs.data(), + kernelNames.c_str(), + &error); + + detail::errHandler(error, __CREATE_PROGRAM_WITH_BUILT_IN_KERNELS_ERR); + if (err != NULL) { + *err = error; + } + } +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 + + Program() { } + + + /*! \brief Constructor from cl_mem - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + */ + explicit Program(const cl_program& program, bool retainObject = false) : + detail::Wrapper(program, retainObject) { } + + Program& operator = (const cl_program& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Program(const Program& program) : detail::Wrapper(program) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Program& operator = (const Program &program) + { + detail::Wrapper::operator=(program); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Program(Program&& program) CL_HPP_NOEXCEPT_ : detail::Wrapper(std::move(program)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Program& operator = (Program &&program) + { + detail::Wrapper::operator=(std::move(program)); + return *this; + } + + cl_int build( + const vector& devices, + const char* options = NULL, + void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL, + void* data = NULL) const + { + size_type numDevices = devices.size(); + vector deviceIDs(numDevices); + + for( size_type deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) { + deviceIDs[deviceIndex] = (devices[deviceIndex])(); + } + + cl_int buildError = ::clBuildProgram( + object_, + (cl_uint) + devices.size(), + deviceIDs.data(), + options, + notifyFptr, + data); + + return detail::buildErrHandler(buildError, __BUILD_PROGRAM_ERR, getBuildInfo()); + } + + cl_int build( + const char* options = NULL, + void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL, + void* data = NULL) const + { + cl_int buildError = ::clBuildProgram( + object_, + 0, + NULL, + options, + notifyFptr, + data); + + + return detail::buildErrHandler(buildError, __BUILD_PROGRAM_ERR, getBuildInfo()); + } + +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 + cl_int compile( + const char* options = NULL, + void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL, + void* data = NULL) const + { + cl_int error = ::clCompileProgram( + object_, + 0, + NULL, + options, + 0, + NULL, + NULL, + notifyFptr, + data); + return detail::buildErrHandler(error, __COMPILE_PROGRAM_ERR, getBuildInfo()); + } +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 + + template + cl_int getInfo(cl_program_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetProgramInfo, object_, name, param), + __GET_PROGRAM_INFO_ERR); + } + + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_program_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + template + cl_int getBuildInfo( + const Device& device, cl_program_build_info name, T* param) const + { + return detail::errHandler( + detail::getInfo( + &::clGetProgramBuildInfo, object_, device(), name, param), + __GET_PROGRAM_BUILD_INFO_ERR); + } + + template typename + detail::param_traits::param_type + getBuildInfo(const Device& device, cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_program_build_info, name>::param_type param; + cl_int result = getBuildInfo(device, name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + /** + * Build info function that returns a vector of device/info pairs for the specified + * info type and for all devices in the program. + * On an error reading the info for any device, an empty vector of info will be returned. + */ + template + vector::param_type>> + getBuildInfo(cl_int *err = NULL) const + { + cl_int result = CL_SUCCESS; + + auto devs = getInfo(&result); + vector::param_type>> + devInfo; + + // If there was an initial error from getInfo return the error + if (result != CL_SUCCESS) { + if (err != NULL) { + *err = result; + } + return devInfo; + } + + for (cl::Device d : devs) { + typename detail::param_traits< + detail::cl_program_build_info, name>::param_type param; + result = getBuildInfo(d, name, ¶m); + devInfo.push_back( + std::pair::param_type> + (d, param)); + if (result != CL_SUCCESS) { + // On error, leave the loop and return the error code + break; + } + } + if (err != NULL) { + *err = result; + } + if (result != CL_SUCCESS) { + devInfo.clear(); + } + return devInfo; + } + + cl_int createKernels(vector* kernels) + { + cl_uint numKernels; + cl_int err = ::clCreateKernelsInProgram(object_, 0, NULL, &numKernels); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __CREATE_KERNELS_IN_PROGRAM_ERR); + } + + vector value(numKernels); + + err = ::clCreateKernelsInProgram( + object_, numKernels, value.data(), NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __CREATE_KERNELS_IN_PROGRAM_ERR); + } + + if (kernels) { + kernels->resize(value.size()); + + // Assign to param, constructing with retain behaviour + // to correctly capture each underlying CL object + for (size_type i = 0; i < value.size(); i++) { + // We do not need to retain because this kernel is being created + // by the runtime + (*kernels)[i] = Kernel(value[i], false); + } + } + return CL_SUCCESS; + } +}; + +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 +inline Program linkProgram( + Program input1, + Program input2, + const char* options = NULL, + void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL, + void* data = NULL, + cl_int* err = NULL) +{ + cl_int error_local = CL_SUCCESS; + + cl_program programs[2] = { input1(), input2() }; + + Context ctx = input1.getInfo(&error_local); + if(error_local!=CL_SUCCESS) { + detail::errHandler(error_local, __LINK_PROGRAM_ERR); + } + + cl_program prog = ::clLinkProgram( + ctx(), + 0, + NULL, + options, + 2, + programs, + notifyFptr, + data, + &error_local); + + detail::errHandler(error_local,__COMPILE_PROGRAM_ERR); + if (err != NULL) { + *err = error_local; + } + + return Program(prog); +} + +inline Program linkProgram( + vector inputPrograms, + const char* options = NULL, + void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL, + void* data = NULL, + cl_int* err = NULL) +{ + cl_int error_local = CL_SUCCESS; + + vector programs(inputPrograms.size()); + + for (unsigned int i = 0; i < inputPrograms.size(); i++) { + programs[i] = inputPrograms[i](); + } + + Context ctx; + if(inputPrograms.size() > 0) { + ctx = inputPrograms[0].getInfo(&error_local); + if(error_local!=CL_SUCCESS) { + detail::errHandler(error_local, __LINK_PROGRAM_ERR); + } + } + cl_program prog = ::clLinkProgram( + ctx(), + 0, + NULL, + options, + (cl_uint)inputPrograms.size(), + programs.data(), + notifyFptr, + data, + &error_local); + + detail::errHandler(error_local,__COMPILE_PROGRAM_ERR); + if (err != NULL) { + *err = error_local; + } + + return Program(prog, false); +} +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 + +// Template specialization for CL_PROGRAM_BINARIES +template <> +inline cl_int cl::Program::getInfo(cl_program_info name, vector>* param) const +{ + if (name != CL_PROGRAM_BINARIES) { + return CL_INVALID_VALUE; + } + if (param) { + // Resize the parameter array appropriately for each allocation + // and pass down to the helper + + vector sizes = getInfo(); + size_type numBinaries = sizes.size(); + + // Resize the parameter array and constituent arrays + param->resize(numBinaries); + for (size_type i = 0; i < numBinaries; ++i) { + (*param)[i].resize(sizes[i]); + } + + return detail::errHandler( + detail::getInfo(&::clGetProgramInfo, object_, name, param), + __GET_PROGRAM_INFO_ERR); + } + + return CL_SUCCESS; +} + +template<> +inline vector> cl::Program::getInfo(cl_int* err) const +{ + vector> binariesVectors; + + cl_int result = getInfo(CL_PROGRAM_BINARIES, &binariesVectors); + if (err != NULL) { + *err = result; + } + return binariesVectors; +} + +inline Kernel::Kernel(const Program& program, const char* name, cl_int* err) +{ + cl_int error; + + object_ = ::clCreateKernel(program(), name, &error); + detail::errHandler(error, __CREATE_KERNEL_ERR); + + if (err != NULL) { + *err = error; + } + +} + +enum class QueueProperties : cl_command_queue_properties +{ + None = 0, + Profiling = CL_QUEUE_PROFILING_ENABLE, + OutOfOrder = CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, +}; + +inline QueueProperties operator|(QueueProperties lhs, QueueProperties rhs) +{ + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + +/*! \class CommandQueue + * \brief CommandQueue interface for cl_command_queue. + */ +class CommandQueue : public detail::Wrapper +{ +private: + static std::once_flag default_initialized_; + static CommandQueue default_; + static cl_int default_error_; + + /*! \brief Create the default command queue returned by @ref getDefault. + * + * It sets default_error_ to indicate success or failure. It does not throw + * @c cl::Error. + */ + static void makeDefault() + { + /* We don't want to throw an error from this function, so we have to + * catch and set the error flag. + */ +#if defined(CL_HPP_ENABLE_EXCEPTIONS) + try +#endif + { + int error; + Context context = Context::getDefault(&error); + + if (error != CL_SUCCESS) { + default_error_ = error; + } + else { + Device device = Device::getDefault(); + default_ = CommandQueue(context, device, 0, &default_error_); + } + } +#if defined(CL_HPP_ENABLE_EXCEPTIONS) + catch (cl::Error &e) { + default_error_ = e.err(); + } +#endif + } + + /*! \brief Create the default command queue. + * + * This sets @c default_. It does not throw + * @c cl::Error. + */ + static void makeDefaultProvided(const CommandQueue &c) { + default_ = c; + } + +public: +#ifdef CL_HPP_UNIT_TEST_ENABLE + /*! \brief Reset the default. + * + * This sets @c default_ to an empty value to support cleanup in + * the unit test framework. + * This function is not thread safe. + */ + static void unitTestClearDefault() { + default_ = CommandQueue(); + } +#endif // #ifdef CL_HPP_UNIT_TEST_ENABLE + + + /*! + * \brief Constructs a CommandQueue based on passed properties. + * Will return an CL_INVALID_QUEUE_PROPERTIES error if CL_QUEUE_ON_DEVICE is specified. + */ + CommandQueue( + cl_command_queue_properties properties, + cl_int* err = NULL) + { + cl_int error; + + Context context = Context::getDefault(&error); + detail::errHandler(error, __CREATE_CONTEXT_ERR); + + if (error != CL_SUCCESS) { + if (err != NULL) { + *err = error; + } + } + else { + Device device = context.getInfo()[0]; + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 + cl_queue_properties queue_properties[] = { + CL_QUEUE_PROPERTIES, properties, 0 }; + if ((properties & CL_QUEUE_ON_DEVICE) == 0) { + object_ = ::clCreateCommandQueueWithProperties( + context(), device(), queue_properties, &error); + } + else { + error = CL_INVALID_QUEUE_PROPERTIES; + } + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR); + if (err != NULL) { + *err = error; + } +#else + object_ = ::clCreateCommandQueue( + context(), device(), properties, &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR); + if (err != NULL) { + *err = error; + } +#endif + } + } + + /*! + * \brief Constructs a CommandQueue based on passed properties. + * Will return an CL_INVALID_QUEUE_PROPERTIES error if CL_QUEUE_ON_DEVICE is specified. + */ + CommandQueue( + QueueProperties properties, + cl_int* err = NULL) + { + cl_int error; + + Context context = Context::getDefault(&error); + detail::errHandler(error, __CREATE_CONTEXT_ERR); + + if (error != CL_SUCCESS) { + if (err != NULL) { + *err = error; + } + } + else { + Device device = context.getInfo()[0]; + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 + cl_queue_properties queue_properties[] = { + CL_QUEUE_PROPERTIES, static_cast(properties), 0 }; + + object_ = ::clCreateCommandQueueWithProperties( + context(), device(), queue_properties, &error); + + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR); + if (err != NULL) { + *err = error; + } +#else + object_ = ::clCreateCommandQueue( + context(), device(), static_cast(properties), &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR); + if (err != NULL) { + *err = error; + } +#endif + } + } + + /*! + * \brief Constructs a CommandQueue for an implementation defined device in the given context + * Will return an CL_INVALID_QUEUE_PROPERTIES error if CL_QUEUE_ON_DEVICE is specified. + */ + explicit CommandQueue( + const Context& context, + cl_command_queue_properties properties = 0, + cl_int* err = NULL) + { + cl_int error; + vector devices; + error = context.getInfo(CL_CONTEXT_DEVICES, &devices); + + detail::errHandler(error, __CREATE_CONTEXT_ERR); + + if (error != CL_SUCCESS) + { + if (err != NULL) { + *err = error; + } + return; + } + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 + cl_queue_properties queue_properties[] = { + CL_QUEUE_PROPERTIES, properties, 0 }; + if ((properties & CL_QUEUE_ON_DEVICE) == 0) { + object_ = ::clCreateCommandQueueWithProperties( + context(), devices[0](), queue_properties, &error); + } + else { + error = CL_INVALID_QUEUE_PROPERTIES; + } + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR); + if (err != NULL) { + *err = error; + } +#else + object_ = ::clCreateCommandQueue( + context(), devices[0](), properties, &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR); + if (err != NULL) { + *err = error; + } +#endif + + } + + /*! + * \brief Constructs a CommandQueue for an implementation defined device in the given context + * Will return an CL_INVALID_QUEUE_PROPERTIES error if CL_QUEUE_ON_DEVICE is specified. + */ + explicit CommandQueue( + const Context& context, + QueueProperties properties, + cl_int* err = NULL) + { + cl_int error; + vector devices; + error = context.getInfo(CL_CONTEXT_DEVICES, &devices); + + detail::errHandler(error, __CREATE_CONTEXT_ERR); + + if (error != CL_SUCCESS) + { + if (err != NULL) { + *err = error; + } + return; + } + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 + cl_queue_properties queue_properties[] = { + CL_QUEUE_PROPERTIES, static_cast(properties), 0 }; + object_ = ::clCreateCommandQueueWithProperties( + context(), devices[0](), queue_properties, &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR); + if (err != NULL) { + *err = error; + } +#else + object_ = ::clCreateCommandQueue( + context(), devices[0](), static_cast(properties), &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR); + if (err != NULL) { + *err = error; + } +#endif + + } + + /*! + * \brief Constructs a CommandQueue for a passed device and context + * Will return an CL_INVALID_QUEUE_PROPERTIES error if CL_QUEUE_ON_DEVICE is specified. + */ + CommandQueue( + const Context& context, + const Device& device, + cl_command_queue_properties properties = 0, + cl_int* err = NULL) + { + cl_int error; + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 + cl_queue_properties queue_properties[] = { + CL_QUEUE_PROPERTIES, properties, 0 }; + object_ = ::clCreateCommandQueueWithProperties( + context(), device(), queue_properties, &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR); + if (err != NULL) { + *err = error; + } +#else + object_ = ::clCreateCommandQueue( + context(), device(), properties, &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR); + if (err != NULL) { + *err = error; + } +#endif + } + + /*! + * \brief Constructs a CommandQueue for a passed device and context + * Will return an CL_INVALID_QUEUE_PROPERTIES error if CL_QUEUE_ON_DEVICE is specified. + */ + CommandQueue( + const Context& context, + const Device& device, + QueueProperties properties, + cl_int* err = NULL) + { + cl_int error; + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 + cl_queue_properties queue_properties[] = { + CL_QUEUE_PROPERTIES, static_cast(properties), 0 }; + object_ = ::clCreateCommandQueueWithProperties( + context(), device(), queue_properties, &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR); + if (err != NULL) { + *err = error; + } +#else + object_ = ::clCreateCommandQueue( + context(), device(), static_cast(properties), &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR); + if (err != NULL) { + *err = error; + } +#endif + } + + static CommandQueue getDefault(cl_int * err = NULL) + { + std::call_once(default_initialized_, makeDefault); +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 + detail::errHandler(default_error_, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR); +#else // CL_HPP_TARGET_OPENCL_VERSION >= 200 + detail::errHandler(default_error_, __CREATE_COMMAND_QUEUE_ERR); +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 200 + if (err != NULL) { + *err = default_error_; + } + return default_; + } + + /** + * Modify the default command queue to be used by + * subsequent operations. + * Will only set the default if no default was previously created. + * @return updated default command queue. + * Should be compared to the passed value to ensure that it was updated. + */ + static CommandQueue setDefault(const CommandQueue &default_queue) + { + std::call_once(default_initialized_, makeDefaultProvided, std::cref(default_queue)); + detail::errHandler(default_error_); + return default_; + } + + CommandQueue() { } + + + /*! \brief Constructor from cl_mem - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + */ + explicit CommandQueue(const cl_command_queue& commandQueue, bool retainObject = false) : + detail::Wrapper(commandQueue, retainObject) { } + + CommandQueue& operator = (const cl_command_queue& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + CommandQueue(const CommandQueue& queue) : detail::Wrapper(queue) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + CommandQueue& operator = (const CommandQueue &queue) + { + detail::Wrapper::operator=(queue); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + CommandQueue(CommandQueue&& queue) CL_HPP_NOEXCEPT_ : detail::Wrapper(std::move(queue)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + CommandQueue& operator = (CommandQueue &&queue) + { + detail::Wrapper::operator=(std::move(queue)); + return *this; + } + + template + cl_int getInfo(cl_command_queue_info name, T* param) const + { + return detail::errHandler( + detail::getInfo( + &::clGetCommandQueueInfo, object_, name, param), + __GET_COMMAND_QUEUE_INFO_ERR); + } + + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_command_queue_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + cl_int enqueueReadBuffer( + const Buffer& buffer, + cl_bool blocking, + size_type offset, + size_type size, + void* ptr, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueReadBuffer( + object_, buffer(), blocking, offset, size, + ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_READ_BUFFER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueWriteBuffer( + const Buffer& buffer, + cl_bool blocking, + size_type offset, + size_type size, + const void* ptr, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueWriteBuffer( + object_, buffer(), blocking, offset, size, + ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_WRITE_BUFFER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueCopyBuffer( + const Buffer& src, + const Buffer& dst, + size_type src_offset, + size_type dst_offset, + size_type size, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueCopyBuffer( + object_, src(), dst(), src_offset, dst_offset, size, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQEUE_COPY_BUFFER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueReadBufferRect( + const Buffer& buffer, + cl_bool blocking, + const array& buffer_offset, + const array& host_offset, + const array& region, + size_type buffer_row_pitch, + size_type buffer_slice_pitch, + size_type host_row_pitch, + size_type host_slice_pitch, + void *ptr, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueReadBufferRect( + object_, + buffer(), + blocking, + buffer_offset.data(), + host_offset.data(), + region.data(), + buffer_row_pitch, + buffer_slice_pitch, + host_row_pitch, + host_slice_pitch, + ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_READ_BUFFER_RECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueWriteBufferRect( + const Buffer& buffer, + cl_bool blocking, + const array& buffer_offset, + const array& host_offset, + const array& region, + size_type buffer_row_pitch, + size_type buffer_slice_pitch, + size_type host_row_pitch, + size_type host_slice_pitch, + const void *ptr, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueWriteBufferRect( + object_, + buffer(), + blocking, + buffer_offset.data(), + host_offset.data(), + region.data(), + buffer_row_pitch, + buffer_slice_pitch, + host_row_pitch, + host_slice_pitch, + ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_WRITE_BUFFER_RECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueCopyBufferRect( + const Buffer& src, + const Buffer& dst, + const array& src_origin, + const array& dst_origin, + const array& region, + size_type src_row_pitch, + size_type src_slice_pitch, + size_type dst_row_pitch, + size_type dst_slice_pitch, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueCopyBufferRect( + object_, + src(), + dst(), + src_origin.data(), + dst_origin.data(), + region.data(), + src_row_pitch, + src_slice_pitch, + dst_row_pitch, + dst_slice_pitch, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQEUE_COPY_BUFFER_RECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 + /** + * Enqueue a command to fill a buffer object with a pattern + * of a given size. The pattern is specified as a vector type. + * \tparam PatternType The datatype of the pattern field. + * The pattern type must be an accepted OpenCL data type. + * \tparam offset Is the offset in bytes into the buffer at + * which to start filling. This must be a multiple of + * the pattern size. + * \tparam size Is the size in bytes of the region to fill. + * This must be a multiple of the pattern size. + */ + template + cl_int enqueueFillBuffer( + const Buffer& buffer, + PatternType pattern, + size_type offset, + size_type size, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueFillBuffer( + object_, + buffer(), + static_cast(&pattern), + sizeof(PatternType), + offset, + size, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_FILL_BUFFER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 + + cl_int enqueueReadImage( + const Image& image, + cl_bool blocking, + const array& origin, + const array& region, + size_type row_pitch, + size_type slice_pitch, + void* ptr, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueReadImage( + object_, + image(), + blocking, + origin.data(), + region.data(), + row_pitch, + slice_pitch, + ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_READ_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueWriteImage( + const Image& image, + cl_bool blocking, + const array& origin, + const array& region, + size_type row_pitch, + size_type slice_pitch, + const void* ptr, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueWriteImage( + object_, + image(), + blocking, + origin.data(), + region.data(), + row_pitch, + slice_pitch, + ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_WRITE_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueCopyImage( + const Image& src, + const Image& dst, + const array& src_origin, + const array& dst_origin, + const array& region, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueCopyImage( + object_, + src(), + dst(), + src_origin.data(), + dst_origin.data(), + region.data(), + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_COPY_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 + /** + * Enqueue a command to fill an image object with a specified color. + * \param fillColor is the color to use to fill the image. + * This is a four component RGBA floating-point color value if + * the image channel data type is not an unnormalized signed or + * unsigned data type. + */ + cl_int enqueueFillImage( + const Image& image, + cl_float4 fillColor, + const array& origin, + const array& region, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueFillImage( + object_, + image(), + static_cast(&fillColor), + origin.data(), + region.data(), + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_FILL_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + /** + * Enqueue a command to fill an image object with a specified color. + * \param fillColor is the color to use to fill the image. + * This is a four component RGBA signed integer color value if + * the image channel data type is an unnormalized signed integer + * type. + */ + cl_int enqueueFillImage( + const Image& image, + cl_int4 fillColor, + const array& origin, + const array& region, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueFillImage( + object_, + image(), + static_cast(&fillColor), + origin.data(), + region.data(), + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_FILL_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + /** + * Enqueue a command to fill an image object with a specified color. + * \param fillColor is the color to use to fill the image. + * This is a four component RGBA unsigned integer color value if + * the image channel data type is an unnormalized unsigned integer + * type. + */ + cl_int enqueueFillImage( + const Image& image, + cl_uint4 fillColor, + const array& origin, + const array& region, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueFillImage( + object_, + image(), + static_cast(&fillColor), + origin.data(), + region.data(), + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_FILL_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 + + cl_int enqueueCopyImageToBuffer( + const Image& src, + const Buffer& dst, + const array& src_origin, + const array& region, + size_type dst_offset, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueCopyImageToBuffer( + object_, + src(), + dst(), + src_origin.data(), + region.data(), + dst_offset, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_COPY_IMAGE_TO_BUFFER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueCopyBufferToImage( + const Buffer& src, + const Image& dst, + size_type src_offset, + const array& dst_origin, + const array& region, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueCopyBufferToImage( + object_, + src(), + dst(), + src_offset, + dst_origin.data(), + region.data(), + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_COPY_BUFFER_TO_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + void* enqueueMapBuffer( + const Buffer& buffer, + cl_bool blocking, + cl_map_flags flags, + size_type offset, + size_type size, + const vector* events = NULL, + Event* event = NULL, + cl_int* err = NULL) const + { + cl_event tmp; + cl_int error; + void * result = ::clEnqueueMapBuffer( + object_, buffer(), blocking, flags, offset, size, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL, + &error); + + detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + if (event != NULL && error == CL_SUCCESS) + *event = tmp; + + return result; + } + + void* enqueueMapImage( + const Image& buffer, + cl_bool blocking, + cl_map_flags flags, + const array& origin, + const array& region, + size_type * row_pitch, + size_type * slice_pitch, + const vector* events = NULL, + Event* event = NULL, + cl_int* err = NULL) const + { + cl_event tmp; + cl_int error; + void * result = ::clEnqueueMapImage( + object_, buffer(), blocking, flags, + origin.data(), + region.data(), + row_pitch, slice_pitch, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL, + &error); + + detail::errHandler(error, __ENQUEUE_MAP_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + if (event != NULL && error == CL_SUCCESS) + *event = tmp; + return result; + } + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 + /** + * Enqueues a command that will allow the host to update a region of a coarse-grained SVM buffer. + * This variant takes a raw SVM pointer. + */ + template + cl_int enqueueMapSVM( + T* ptr, + cl_bool blocking, + cl_map_flags flags, + size_type size, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler(::clEnqueueSVMMap( + object_, blocking, flags, static_cast(ptr), size, + (events != NULL) ? (cl_uint)events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_MAP_BUFFER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + + /** + * Enqueues a command that will allow the host to update a region of a coarse-grained SVM buffer. + * This variant takes a cl::pointer instance. + */ + template + cl_int enqueueMapSVM( + cl::pointer &ptr, + cl_bool blocking, + cl_map_flags flags, + size_type size, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler(::clEnqueueSVMMap( + object_, blocking, flags, static_cast(ptr.get()), size, + (events != NULL) ? (cl_uint)events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_MAP_BUFFER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + /** + * Enqueues a command that will allow the host to update a region of a coarse-grained SVM buffer. + * This variant takes a cl::vector instance. + */ + template + cl_int enqueueMapSVM( + cl::vector &container, + cl_bool blocking, + cl_map_flags flags, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler(::clEnqueueSVMMap( + object_, blocking, flags, static_cast(container.data()), container.size(), + (events != NULL) ? (cl_uint)events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_MAP_BUFFER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } +#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200 + + cl_int enqueueUnmapMemObject( + const Memory& memory, + void* mapped_ptr, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueUnmapMemObject( + object_, memory(), mapped_ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_UNMAP_MEM_OBJECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 + /** + * Enqueues a command that will release a coarse-grained SVM buffer back to the OpenCL runtime. + * This variant takes a raw SVM pointer. + */ + template + cl_int enqueueUnmapSVM( + T* ptr, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueSVMUnmap( + object_, static_cast(ptr), + (events != NULL) ? (cl_uint)events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_UNMAP_MEM_OBJECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + /** + * Enqueues a command that will release a coarse-grained SVM buffer back to the OpenCL runtime. + * This variant takes a cl::pointer instance. + */ + template + cl_int enqueueUnmapSVM( + cl::pointer &ptr, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueSVMUnmap( + object_, static_cast(ptr.get()), + (events != NULL) ? (cl_uint)events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_UNMAP_MEM_OBJECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + /** + * Enqueues a command that will release a coarse-grained SVM buffer back to the OpenCL runtime. + * This variant takes a cl::vector instance. + */ + template + cl_int enqueueUnmapSVM( + cl::vector &container, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueSVMUnmap( + object_, static_cast(container.data()), + (events != NULL) ? (cl_uint)events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_UNMAP_MEM_OBJECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } +#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200 + +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 + /** + * Enqueues a marker command which waits for either a list of events to complete, + * or all previously enqueued commands to complete. + * + * Enqueues a marker command which waits for either a list of events to complete, + * or if the list is empty it waits for all commands previously enqueued in command_queue + * to complete before it completes. This command returns an event which can be waited on, + * i.e. this event can be waited on to insure that all events either in the event_wait_list + * or all previously enqueued commands, queued before this command to command_queue, + * have completed. + */ + cl_int enqueueMarkerWithWaitList( + const vector *events = 0, + Event *event = 0) + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueMarkerWithWaitList( + object_, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_MARKER_WAIT_LIST_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + /** + * A synchronization point that enqueues a barrier operation. + * + * Enqueues a barrier command which waits for either a list of events to complete, + * or if the list is empty it waits for all commands previously enqueued in command_queue + * to complete before it completes. This command blocks command execution, that is, any + * following commands enqueued after it do not execute until it completes. This command + * returns an event which can be waited on, i.e. this event can be waited on to insure that + * all events either in the event_wait_list or all previously enqueued commands, queued + * before this command to command_queue, have completed. + */ + cl_int enqueueBarrierWithWaitList( + const vector *events = 0, + Event *event = 0) + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueBarrierWithWaitList( + object_, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_BARRIER_WAIT_LIST_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + /** + * Enqueues a command to indicate with which device a set of memory objects + * should be associated. + */ + cl_int enqueueMigrateMemObjects( + const vector &memObjects, + cl_mem_migration_flags flags, + const vector* events = NULL, + Event* event = NULL + ) + { + cl_event tmp; + + vector localMemObjects(memObjects.size()); + + for( int i = 0; i < (int)memObjects.size(); ++i ) { + localMemObjects[i] = memObjects[i](); + } + + + cl_int err = detail::errHandler( + ::clEnqueueMigrateMemObjects( + object_, + (cl_uint)memObjects.size(), + localMemObjects.data(), + flags, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_UNMAP_MEM_OBJECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 + + cl_int enqueueNDRangeKernel( + const Kernel& kernel, + const NDRange& offset, + const NDRange& global, + const NDRange& local = NullRange, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueNDRangeKernel( + object_, kernel(), (cl_uint) global.dimensions(), + offset.dimensions() != 0 ? (const size_type*) offset : NULL, + (const size_type*) global, + local.dimensions() != 0 ? (const size_type*) local : NULL, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_NDRANGE_KERNEL_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + +#if defined(CL_USE_DEPRECATED_OPENCL_1_2_APIS) + CL_EXT_PREFIX__VERSION_1_2_DEPRECATED cl_int enqueueTask( + const Kernel& kernel, + const vector* events = NULL, + Event* event = NULL) const CL_EXT_SUFFIX__VERSION_1_2_DEPRECATED + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueTask( + object_, kernel(), + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_TASK_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } +#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_2_APIS) + + cl_int enqueueNativeKernel( + void (CL_CALLBACK *userFptr)(void *), + std::pair args, + const vector* mem_objects = NULL, + const vector* mem_locs = NULL, + const vector* events = NULL, + Event* event = NULL) const + { + size_type elements = 0; + if (mem_objects != NULL) { + elements = mem_objects->size(); + } + vector mems(elements); + for (unsigned int i = 0; i < elements; i++) { + mems[i] = ((*mem_objects)[i])(); + } + + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueNativeKernel( + object_, userFptr, args.first, args.second, + (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0, + mems.data(), + (mem_locs != NULL && mem_locs->size() > 0) ? (const void **) &mem_locs->front() : NULL, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_NATIVE_KERNEL); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + +/** + * Deprecated APIs for 1.2 + */ +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + CL_EXT_PREFIX__VERSION_1_1_DEPRECATED + cl_int enqueueMarker(Event* event = NULL) const CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueMarker( + object_, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_MARKER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + CL_EXT_PREFIX__VERSION_1_1_DEPRECATED + cl_int enqueueWaitForEvents(const vector& events) const CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED + { + return detail::errHandler( + ::clEnqueueWaitForEvents( + object_, + (cl_uint) events.size(), + events.size() > 0 ? (const cl_event*) &events.front() : NULL), + __ENQUEUE_WAIT_FOR_EVENTS_ERR); + } +#endif // defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + + cl_int enqueueAcquireGLObjects( + const vector* mem_objects = NULL, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueAcquireGLObjects( + object_, + (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0, + (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_ACQUIRE_GL_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueReleaseGLObjects( + const vector* mem_objects = NULL, + const vector* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueReleaseGLObjects( + object_, + (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0, + (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_RELEASE_GL_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + +#if defined (CL_HPP_USE_DX_INTEROP) +typedef CL_API_ENTRY cl_int (CL_API_CALL *PFN_clEnqueueAcquireD3D10ObjectsKHR)( + cl_command_queue command_queue, cl_uint num_objects, + const cl_mem* mem_objects, cl_uint num_events_in_wait_list, + const cl_event* event_wait_list, cl_event* event); +typedef CL_API_ENTRY cl_int (CL_API_CALL *PFN_clEnqueueReleaseD3D10ObjectsKHR)( + cl_command_queue command_queue, cl_uint num_objects, + const cl_mem* mem_objects, cl_uint num_events_in_wait_list, + const cl_event* event_wait_list, cl_event* event); + + cl_int enqueueAcquireD3D10Objects( + const vector* mem_objects = NULL, + const vector* events = NULL, + Event* event = NULL) const + { + static PFN_clEnqueueAcquireD3D10ObjectsKHR pfn_clEnqueueAcquireD3D10ObjectsKHR = NULL; +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 + cl_context context = getInfo(); + cl::Device device(getInfo()); + cl_platform_id platform = device.getInfo(); + CL_HPP_INIT_CL_EXT_FCN_PTR_PLATFORM_(platform, clEnqueueAcquireD3D10ObjectsKHR); +#endif +#if CL_HPP_TARGET_OPENCL_VERSION >= 110 + CL_HPP_INIT_CL_EXT_FCN_PTR_(clEnqueueAcquireD3D10ObjectsKHR); +#endif + + cl_event tmp; + cl_int err = detail::errHandler( + pfn_clEnqueueAcquireD3D10ObjectsKHR( + object_, + (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0, + (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_ACQUIRE_GL_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueReleaseD3D10Objects( + const vector* mem_objects = NULL, + const vector* events = NULL, + Event* event = NULL) const + { + static PFN_clEnqueueReleaseD3D10ObjectsKHR pfn_clEnqueueReleaseD3D10ObjectsKHR = NULL; +#if CL_HPP_TARGET_OPENCL_VERSION >= 120 + cl_context context = getInfo(); + cl::Device device(getInfo()); + cl_platform_id platform = device.getInfo(); + CL_HPP_INIT_CL_EXT_FCN_PTR_PLATFORM_(platform, clEnqueueReleaseD3D10ObjectsKHR); +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 +#if CL_HPP_TARGET_OPENCL_VERSION >= 110 + CL_HPP_INIT_CL_EXT_FCN_PTR_(clEnqueueReleaseD3D10ObjectsKHR); +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 110 + + cl_event tmp; + cl_int err = detail::errHandler( + pfn_clEnqueueReleaseD3D10ObjectsKHR( + object_, + (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0, + (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_RELEASE_GL_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } +#endif + +/** + * Deprecated APIs for 1.2 + */ +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + CL_EXT_PREFIX__VERSION_1_1_DEPRECATED + cl_int enqueueBarrier() const CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED + { + return detail::errHandler( + ::clEnqueueBarrier(object_), + __ENQUEUE_BARRIER_ERR); + } +#endif // CL_USE_DEPRECATED_OPENCL_1_1_APIS + + cl_int flush() const + { + return detail::errHandler(::clFlush(object_), __FLUSH_ERR); + } + + cl_int finish() const + { + return detail::errHandler(::clFinish(object_), __FINISH_ERR); + } +}; // CommandQueue + +CL_HPP_DEFINE_STATIC_MEMBER_ std::once_flag CommandQueue::default_initialized_; +CL_HPP_DEFINE_STATIC_MEMBER_ CommandQueue CommandQueue::default_; +CL_HPP_DEFINE_STATIC_MEMBER_ cl_int CommandQueue::default_error_ = CL_SUCCESS; + + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 +enum class DeviceQueueProperties : cl_command_queue_properties +{ + None = 0, + Profiling = CL_QUEUE_PROFILING_ENABLE, +}; + +inline DeviceQueueProperties operator|(DeviceQueueProperties lhs, DeviceQueueProperties rhs) +{ + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + +/*! \class DeviceCommandQueue + * \brief DeviceCommandQueue interface for device cl_command_queues. + */ +class DeviceCommandQueue : public detail::Wrapper +{ +public: + + /*! + * Trivial empty constructor to create a null queue. + */ + DeviceCommandQueue() { } + + /*! + * Default construct device command queue on default context and device + */ + DeviceCommandQueue(DeviceQueueProperties properties, cl_int* err = NULL) + { + cl_int error; + cl::Context context = cl::Context::getDefault(); + cl::Device device = cl::Device::getDefault(); + + cl_command_queue_properties mergedProperties = + CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | static_cast(properties); + + cl_queue_properties queue_properties[] = { + CL_QUEUE_PROPERTIES, mergedProperties, 0 }; + object_ = ::clCreateCommandQueueWithProperties( + context(), device(), queue_properties, &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! + * Create a device command queue for a specified device in the passed context. + */ + DeviceCommandQueue( + const Context& context, + const Device& device, + DeviceQueueProperties properties = DeviceQueueProperties::None, + cl_int* err = NULL) + { + cl_int error; + + cl_command_queue_properties mergedProperties = + CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | static_cast(properties); + cl_queue_properties queue_properties[] = { + CL_QUEUE_PROPERTIES, mergedProperties, 0 }; + object_ = ::clCreateCommandQueueWithProperties( + context(), device(), queue_properties, &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! + * Create a device command queue for a specified device in the passed context. + */ + DeviceCommandQueue( + const Context& context, + const Device& device, + cl_uint queueSize, + DeviceQueueProperties properties = DeviceQueueProperties::None, + cl_int* err = NULL) + { + cl_int error; + + cl_command_queue_properties mergedProperties = + CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | static_cast(properties); + cl_queue_properties queue_properties[] = { + CL_QUEUE_PROPERTIES, mergedProperties, + CL_QUEUE_SIZE, queueSize, + 0 }; + object_ = ::clCreateCommandQueueWithProperties( + context(), device(), queue_properties, &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! \brief Constructor from cl_command_queue - takes ownership. + * + * \param retainObject will cause the constructor to retain its cl object. + * Defaults to false to maintain compatibility with + * earlier versions. + */ + explicit DeviceCommandQueue(const cl_command_queue& commandQueue, bool retainObject = false) : + detail::Wrapper(commandQueue, retainObject) { } + + DeviceCommandQueue& operator = (const cl_command_queue& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + DeviceCommandQueue(const DeviceCommandQueue& queue) : detail::Wrapper(queue) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + DeviceCommandQueue& operator = (const DeviceCommandQueue &queue) + { + detail::Wrapper::operator=(queue); + return *this; + } + + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + DeviceCommandQueue(DeviceCommandQueue&& queue) CL_HPP_NOEXCEPT_ : detail::Wrapper(std::move(queue)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + DeviceCommandQueue& operator = (DeviceCommandQueue &&queue) + { + detail::Wrapper::operator=(std::move(queue)); + return *this; + } + + template + cl_int getInfo(cl_command_queue_info name, T* param) const + { + return detail::errHandler( + detail::getInfo( + &::clGetCommandQueueInfo, object_, name, param), + __GET_COMMAND_QUEUE_INFO_ERR); + } + + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_command_queue_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + /*! + * Create a new default device command queue for the default device, + * in the default context and of the default size. + * If there is already a default queue for the specified device this + * function will return the pre-existing queue. + */ + static DeviceCommandQueue makeDefault( + cl_int *err = nullptr) + { + cl_int error; + cl::Context context = cl::Context::getDefault(); + cl::Device device = cl::Device::getDefault(); + + cl_command_queue_properties properties = + CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | CL_QUEUE_ON_DEVICE_DEFAULT; + cl_queue_properties queue_properties[] = { + CL_QUEUE_PROPERTIES, properties, + 0 }; + DeviceCommandQueue deviceQueue( + ::clCreateCommandQueueWithProperties( + context(), device(), queue_properties, &error)); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR); + if (err != NULL) { + *err = error; + } + + return deviceQueue; + } + + /*! + * Create a new default device command queue for the specified device + * and of the default size. + * If there is already a default queue for the specified device this + * function will return the pre-existing queue. + */ + static DeviceCommandQueue makeDefault( + const Context &context, const Device &device, cl_int *err = nullptr) + { + cl_int error; + + cl_command_queue_properties properties = + CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | CL_QUEUE_ON_DEVICE_DEFAULT; + cl_queue_properties queue_properties[] = { + CL_QUEUE_PROPERTIES, properties, + 0 }; + DeviceCommandQueue deviceQueue( + ::clCreateCommandQueueWithProperties( + context(), device(), queue_properties, &error)); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR); + if (err != NULL) { + *err = error; + } + + return deviceQueue; + } + + /*! + * Create a new default device command queue for the specified device + * and of the requested size in bytes. + * If there is already a default queue for the specified device this + * function will return the pre-existing queue. + */ + static DeviceCommandQueue makeDefault( + const Context &context, const Device &device, cl_uint queueSize, cl_int *err = nullptr) + { + cl_int error; + + cl_command_queue_properties properties = + CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | CL_QUEUE_ON_DEVICE_DEFAULT; + cl_queue_properties queue_properties[] = { + CL_QUEUE_PROPERTIES, properties, + CL_QUEUE_SIZE, queueSize, + 0 }; + DeviceCommandQueue deviceQueue( + ::clCreateCommandQueueWithProperties( + context(), device(), queue_properties, &error)); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR); + if (err != NULL) { + *err = error; + } + + return deviceQueue; + } +}; // DeviceCommandQueue + +namespace detail +{ + // Specialization for device command queue + template <> + struct KernelArgumentHandler + { + static size_type size(const cl::DeviceCommandQueue&) { return sizeof(cl_command_queue); } + static const cl_command_queue* ptr(const cl::DeviceCommandQueue& value) { return &(value()); } + }; +} // namespace detail + +#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200 + + +template< typename IteratorType > +Buffer::Buffer( + const Context &context, + IteratorType startIterator, + IteratorType endIterator, + bool readOnly, + bool useHostPtr, + cl_int* err) +{ + typedef typename std::iterator_traits::value_type DataType; + cl_int error; + + cl_mem_flags flags = 0; + if( readOnly ) { + flags |= CL_MEM_READ_ONLY; + } + else { + flags |= CL_MEM_READ_WRITE; + } + if( useHostPtr ) { + flags |= CL_MEM_USE_HOST_PTR; + } + + size_type size = sizeof(DataType)*(endIterator - startIterator); + + if( useHostPtr ) { + object_ = ::clCreateBuffer(context(), flags, size, static_cast(&*startIterator), &error); + } else { + object_ = ::clCreateBuffer(context(), flags, size, 0, &error); + } + + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + + if( !useHostPtr ) { + CommandQueue queue(context, 0, &error); + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + + error = cl::copy(queue, startIterator, endIterator, *this); + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } +} + +template< typename IteratorType > +Buffer::Buffer( + const CommandQueue &queue, + IteratorType startIterator, + IteratorType endIterator, + bool readOnly, + bool useHostPtr, + cl_int* err) +{ + typedef typename std::iterator_traits::value_type DataType; + cl_int error; + + cl_mem_flags flags = 0; + if (readOnly) { + flags |= CL_MEM_READ_ONLY; + } + else { + flags |= CL_MEM_READ_WRITE; + } + if (useHostPtr) { + flags |= CL_MEM_USE_HOST_PTR; + } + + size_type size = sizeof(DataType)*(endIterator - startIterator); + + Context context = queue.getInfo(); + + if (useHostPtr) { + object_ = ::clCreateBuffer(context(), flags, size, static_cast(&*startIterator), &error); + } + else { + object_ = ::clCreateBuffer(context(), flags, size, 0, &error); + } + + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + + if (!useHostPtr) { + error = cl::copy(queue, startIterator, endIterator, *this); + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } +} + +inline cl_int enqueueReadBuffer( + const Buffer& buffer, + cl_bool blocking, + size_type offset, + size_type size, + void* ptr, + const vector* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueReadBuffer(buffer, blocking, offset, size, ptr, events, event); +} + +inline cl_int enqueueWriteBuffer( + const Buffer& buffer, + cl_bool blocking, + size_type offset, + size_type size, + const void* ptr, + const vector* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueWriteBuffer(buffer, blocking, offset, size, ptr, events, event); +} + +inline void* enqueueMapBuffer( + const Buffer& buffer, + cl_bool blocking, + cl_map_flags flags, + size_type offset, + size_type size, + const vector* events = NULL, + Event* event = NULL, + cl_int* err = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + + void * result = ::clEnqueueMapBuffer( + queue(), buffer(), blocking, flags, offset, size, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (cl_event*) event, + &error); + + detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + return result; +} + + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 +/** + * Enqueues to the default queue a command that will allow the host to + * update a region of a coarse-grained SVM buffer. + * This variant takes a raw SVM pointer. + */ +template +inline cl_int enqueueMapSVM( + T* ptr, + cl_bool blocking, + cl_map_flags flags, + size_type size, + const vector* events, + Event* event) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + if (error != CL_SUCCESS) { + return detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR); + } + + return queue.enqueueMapSVM( + ptr, blocking, flags, size, events, event); +} + +/** + * Enqueues to the default queue a command that will allow the host to + * update a region of a coarse-grained SVM buffer. + * This variant takes a cl::pointer instance. + */ +template +inline cl_int enqueueMapSVM( + cl::pointer ptr, + cl_bool blocking, + cl_map_flags flags, + size_type size, + const vector* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + if (error != CL_SUCCESS) { + return detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR); + } + + return queue.enqueueMapSVM( + ptr, blocking, flags, size, events, event); +} + +/** + * Enqueues to the default queue a command that will allow the host to + * update a region of a coarse-grained SVM buffer. + * This variant takes a cl::vector instance. + */ +template +inline cl_int enqueueMapSVM( + cl::vector container, + cl_bool blocking, + cl_map_flags flags, + const vector* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + if (error != CL_SUCCESS) { + return detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR); + } + + return queue.enqueueMapSVM( + container, blocking, flags, events, event); +} + +#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200 + +inline cl_int enqueueUnmapMemObject( + const Memory& memory, + void* mapped_ptr, + const vector* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR); + if (error != CL_SUCCESS) { + return error; + } + + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueUnmapMemObject( + queue(), memory(), mapped_ptr, + (events != NULL) ? (cl_uint)events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_UNMAP_MEM_OBJECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; +} + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 +/** + * Enqueues to the default queue a command that will release a coarse-grained + * SVM buffer back to the OpenCL runtime. + * This variant takes a raw SVM pointer. + */ +template +inline cl_int enqueueUnmapSVM( + T* ptr, + const vector* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + if (error != CL_SUCCESS) { + return detail::errHandler(error, __ENQUEUE_UNMAP_MEM_OBJECT_ERR); + } + + return detail::errHandler(queue.enqueueUnmapSVM(ptr, events, event), + __ENQUEUE_UNMAP_MEM_OBJECT_ERR); + +} + +/** + * Enqueues to the default queue a command that will release a coarse-grained + * SVM buffer back to the OpenCL runtime. + * This variant takes a cl::pointer instance. + */ +template +inline cl_int enqueueUnmapSVM( + cl::pointer &ptr, + const vector* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + if (error != CL_SUCCESS) { + return detail::errHandler(error, __ENQUEUE_UNMAP_MEM_OBJECT_ERR); + } + + return detail::errHandler(queue.enqueueUnmapSVM(ptr, events, event), + __ENQUEUE_UNMAP_MEM_OBJECT_ERR); +} + +/** + * Enqueues to the default queue a command that will release a coarse-grained + * SVM buffer back to the OpenCL runtime. + * This variant takes a cl::vector instance. + */ +template +inline cl_int enqueueUnmapSVM( + cl::vector &container, + const vector* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + if (error != CL_SUCCESS) { + return detail::errHandler(error, __ENQUEUE_UNMAP_MEM_OBJECT_ERR); + } + + return detail::errHandler(queue.enqueueUnmapSVM(container, events, event), + __ENQUEUE_UNMAP_MEM_OBJECT_ERR); +} + +#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200 + +inline cl_int enqueueCopyBuffer( + const Buffer& src, + const Buffer& dst, + size_type src_offset, + size_type dst_offset, + size_type size, + const vector* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueCopyBuffer(src, dst, src_offset, dst_offset, size, events, event); +} + +/** + * Blocking copy operation between iterators and a buffer. + * Host to Device. + * Uses default command queue. + */ +template< typename IteratorType > +inline cl_int copy( IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer ) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + if (error != CL_SUCCESS) + return error; + + return cl::copy(queue, startIterator, endIterator, buffer); +} + +/** + * Blocking copy operation between iterators and a buffer. + * Device to Host. + * Uses default command queue. + */ +template< typename IteratorType > +inline cl_int copy( const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator ) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + if (error != CL_SUCCESS) + return error; + + return cl::copy(queue, buffer, startIterator, endIterator); +} + +/** + * Blocking copy operation between iterators and a buffer. + * Host to Device. + * Uses specified queue. + */ +template< typename IteratorType > +inline cl_int copy( const CommandQueue &queue, IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer ) +{ + typedef typename std::iterator_traits::value_type DataType; + cl_int error; + + size_type length = endIterator-startIterator; + size_type byteLength = length*sizeof(DataType); + + DataType *pointer = + static_cast(queue.enqueueMapBuffer(buffer, CL_TRUE, CL_MAP_WRITE, 0, byteLength, 0, 0, &error)); + // if exceptions enabled, enqueueMapBuffer will throw + if( error != CL_SUCCESS ) { + return error; + } +#if defined(_MSC_VER) + std::copy( + startIterator, + endIterator, + stdext::checked_array_iterator( + pointer, length)); +#else + std::copy(startIterator, endIterator, pointer); +#endif + Event endEvent; + error = queue.enqueueUnmapMemObject(buffer, pointer, 0, &endEvent); + // if exceptions enabled, enqueueUnmapMemObject will throw + if( error != CL_SUCCESS ) { + return error; + } + endEvent.wait(); + return CL_SUCCESS; +} + +/** + * Blocking copy operation between iterators and a buffer. + * Device to Host. + * Uses specified queue. + */ +template< typename IteratorType > +inline cl_int copy( const CommandQueue &queue, const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator ) +{ + typedef typename std::iterator_traits::value_type DataType; + cl_int error; + + size_type length = endIterator-startIterator; + size_type byteLength = length*sizeof(DataType); + + DataType *pointer = + static_cast(queue.enqueueMapBuffer(buffer, CL_TRUE, CL_MAP_READ, 0, byteLength, 0, 0, &error)); + // if exceptions enabled, enqueueMapBuffer will throw + if( error != CL_SUCCESS ) { + return error; + } + std::copy(pointer, pointer + length, startIterator); + Event endEvent; + error = queue.enqueueUnmapMemObject(buffer, pointer, 0, &endEvent); + // if exceptions enabled, enqueueUnmapMemObject will throw + if( error != CL_SUCCESS ) { + return error; + } + endEvent.wait(); + return CL_SUCCESS; +} + + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 +/** + * Blocking SVM map operation - performs a blocking map underneath. + */ +template +inline cl_int mapSVM(cl::vector &container) +{ + return enqueueMapSVM(container, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE); +} + +/** +* Blocking SVM map operation - performs a blocking map underneath. +*/ +template +inline cl_int unmapSVM(cl::vector &container) +{ + return enqueueUnmapSVM(container); +} + +#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200 + +#if CL_HPP_TARGET_OPENCL_VERSION >= 110 +inline cl_int enqueueReadBufferRect( + const Buffer& buffer, + cl_bool blocking, + const array& buffer_offset, + const array& host_offset, + const array& region, + size_type buffer_row_pitch, + size_type buffer_slice_pitch, + size_type host_row_pitch, + size_type host_slice_pitch, + void *ptr, + const vector* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueReadBufferRect( + buffer, + blocking, + buffer_offset, + host_offset, + region, + buffer_row_pitch, + buffer_slice_pitch, + host_row_pitch, + host_slice_pitch, + ptr, + events, + event); +} + +inline cl_int enqueueWriteBufferRect( + const Buffer& buffer, + cl_bool blocking, + const array& buffer_offset, + const array& host_offset, + const array& region, + size_type buffer_row_pitch, + size_type buffer_slice_pitch, + size_type host_row_pitch, + size_type host_slice_pitch, + const void *ptr, + const vector* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueWriteBufferRect( + buffer, + blocking, + buffer_offset, + host_offset, + region, + buffer_row_pitch, + buffer_slice_pitch, + host_row_pitch, + host_slice_pitch, + ptr, + events, + event); +} + +inline cl_int enqueueCopyBufferRect( + const Buffer& src, + const Buffer& dst, + const array& src_origin, + const array& dst_origin, + const array& region, + size_type src_row_pitch, + size_type src_slice_pitch, + size_type dst_row_pitch, + size_type dst_slice_pitch, + const vector* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueCopyBufferRect( + src, + dst, + src_origin, + dst_origin, + region, + src_row_pitch, + src_slice_pitch, + dst_row_pitch, + dst_slice_pitch, + events, + event); +} +#endif // CL_HPP_TARGET_OPENCL_VERSION >= 110 + +inline cl_int enqueueReadImage( + const Image& image, + cl_bool blocking, + const array& origin, + const array& region, + size_type row_pitch, + size_type slice_pitch, + void* ptr, + const vector* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueReadImage( + image, + blocking, + origin, + region, + row_pitch, + slice_pitch, + ptr, + events, + event); +} + +inline cl_int enqueueWriteImage( + const Image& image, + cl_bool blocking, + const array& origin, + const array& region, + size_type row_pitch, + size_type slice_pitch, + const void* ptr, + const vector* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueWriteImage( + image, + blocking, + origin, + region, + row_pitch, + slice_pitch, + ptr, + events, + event); +} + +inline cl_int enqueueCopyImage( + const Image& src, + const Image& dst, + const array& src_origin, + const array& dst_origin, + const array& region, + const vector* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueCopyImage( + src, + dst, + src_origin, + dst_origin, + region, + events, + event); +} + +inline cl_int enqueueCopyImageToBuffer( + const Image& src, + const Buffer& dst, + const array& src_origin, + const array& region, + size_type dst_offset, + const vector* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueCopyImageToBuffer( + src, + dst, + src_origin, + region, + dst_offset, + events, + event); +} + +inline cl_int enqueueCopyBufferToImage( + const Buffer& src, + const Image& dst, + size_type src_offset, + const array& dst_origin, + const array& region, + const vector* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueCopyBufferToImage( + src, + dst, + src_offset, + dst_origin, + region, + events, + event); +} + + +inline cl_int flush(void) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.flush(); +} + +inline cl_int finish(void) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + + return queue.finish(); +} + +class EnqueueArgs +{ +private: + CommandQueue queue_; + const NDRange offset_; + const NDRange global_; + const NDRange local_; + vector events_; + + template + friend class KernelFunctor; + +public: + EnqueueArgs(NDRange global) : + queue_(CommandQueue::getDefault()), + offset_(NullRange), + global_(global), + local_(NullRange) + { + + } + + EnqueueArgs(NDRange global, NDRange local) : + queue_(CommandQueue::getDefault()), + offset_(NullRange), + global_(global), + local_(local) + { + + } + + EnqueueArgs(NDRange offset, NDRange global, NDRange local) : + queue_(CommandQueue::getDefault()), + offset_(offset), + global_(global), + local_(local) + { + + } + + EnqueueArgs(Event e, NDRange global) : + queue_(CommandQueue::getDefault()), + offset_(NullRange), + global_(global), + local_(NullRange) + { + events_.push_back(e); + } + + EnqueueArgs(Event e, NDRange global, NDRange local) : + queue_(CommandQueue::getDefault()), + offset_(NullRange), + global_(global), + local_(local) + { + events_.push_back(e); + } + + EnqueueArgs(Event e, NDRange offset, NDRange global, NDRange local) : + queue_(CommandQueue::getDefault()), + offset_(offset), + global_(global), + local_(local) + { + events_.push_back(e); + } + + EnqueueArgs(const vector &events, NDRange global) : + queue_(CommandQueue::getDefault()), + offset_(NullRange), + global_(global), + local_(NullRange), + events_(events) + { + + } + + EnqueueArgs(const vector &events, NDRange global, NDRange local) : + queue_(CommandQueue::getDefault()), + offset_(NullRange), + global_(global), + local_(local), + events_(events) + { + + } + + EnqueueArgs(const vector &events, NDRange offset, NDRange global, NDRange local) : + queue_(CommandQueue::getDefault()), + offset_(offset), + global_(global), + local_(local), + events_(events) + { + + } + + EnqueueArgs(CommandQueue &queue, NDRange global) : + queue_(queue), + offset_(NullRange), + global_(global), + local_(NullRange) + { + + } + + EnqueueArgs(CommandQueue &queue, NDRange global, NDRange local) : + queue_(queue), + offset_(NullRange), + global_(global), + local_(local) + { + + } + + EnqueueArgs(CommandQueue &queue, NDRange offset, NDRange global, NDRange local) : + queue_(queue), + offset_(offset), + global_(global), + local_(local) + { + + } + + EnqueueArgs(CommandQueue &queue, Event e, NDRange global) : + queue_(queue), + offset_(NullRange), + global_(global), + local_(NullRange) + { + events_.push_back(e); + } + + EnqueueArgs(CommandQueue &queue, Event e, NDRange global, NDRange local) : + queue_(queue), + offset_(NullRange), + global_(global), + local_(local) + { + events_.push_back(e); + } + + EnqueueArgs(CommandQueue &queue, Event e, NDRange offset, NDRange global, NDRange local) : + queue_(queue), + offset_(offset), + global_(global), + local_(local) + { + events_.push_back(e); + } + + EnqueueArgs(CommandQueue &queue, const vector &events, NDRange global) : + queue_(queue), + offset_(NullRange), + global_(global), + local_(NullRange), + events_(events) + { + + } + + EnqueueArgs(CommandQueue &queue, const vector &events, NDRange global, NDRange local) : + queue_(queue), + offset_(NullRange), + global_(global), + local_(local), + events_(events) + { + + } + + EnqueueArgs(CommandQueue &queue, const vector &events, NDRange offset, NDRange global, NDRange local) : + queue_(queue), + offset_(offset), + global_(global), + local_(local), + events_(events) + { + + } +}; + + +//---------------------------------------------------------------------------------------------- + + +/** + * Type safe kernel functor. + * + */ +template +class KernelFunctor +{ +private: + Kernel kernel_; + + template + void setArgs(T0&& t0, T1s&&... t1s) + { + kernel_.setArg(index, t0); + setArgs(std::forward(t1s)...); + } + + template + void setArgs(T0&& t0) + { + kernel_.setArg(index, t0); + } + + template + void setArgs() + { + } + + +public: + KernelFunctor(Kernel kernel) : kernel_(kernel) + {} + + KernelFunctor( + const Program& program, + const string name, + cl_int * err = NULL) : + kernel_(program, name.c_str(), err) + {} + + //! \brief Return type of the functor + typedef Event result_type; + + /** + * Enqueue kernel. + * @param args Launch parameters of the kernel. + * @param t0... List of kernel arguments based on the template type of the functor. + */ + Event operator() ( + const EnqueueArgs& args, + Ts... ts) + { + Event event; + setArgs<0>(std::forward(ts)...); + + args.queue_.enqueueNDRangeKernel( + kernel_, + args.offset_, + args.global_, + args.local_, + &args.events_, + &event); + + return event; + } + + /** + * Enqueue kernel with support for error code. + * @param args Launch parameters of the kernel. + * @param t0... List of kernel arguments based on the template type of the functor. + * @param error Out parameter returning the error code from the execution. + */ + Event operator() ( + const EnqueueArgs& args, + Ts... ts, + cl_int &error) + { + Event event; + setArgs<0>(std::forward(ts)...); + + error = args.queue_.enqueueNDRangeKernel( + kernel_, + args.offset_, + args.global_, + args.local_, + &args.events_, + &event); + + return event; + } + +#if CL_HPP_TARGET_OPENCL_VERSION >= 200 + cl_int setSVMPointers(const vector &pointerList) + { + return kernel_.setSVMPointers(pointerList); + } + + template + cl_int setSVMPointers(const T0 &t0, T1s... ts) + { + return kernel_.setSVMPointers(t0, ts...); + } +#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200 + + Kernel getKernel() + { + return kernel_; + } +}; + +namespace compatibility { + /** + * Backward compatibility class to ensure that cl.hpp code works with cl2.hpp. + * Please use KernelFunctor directly. + */ + template + struct make_kernel + { + typedef KernelFunctor FunctorType; + + FunctorType functor_; + + make_kernel( + const Program& program, + const string name, + cl_int * err = NULL) : + functor_(FunctorType(program, name, err)) + {} + + make_kernel( + const Kernel kernel) : + functor_(FunctorType(kernel)) + {} + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + Ts...); + + Event operator()( + const EnqueueArgs& enqueueArgs, + Ts... args) + { + return functor_( + enqueueArgs, args...); + } + }; +} // namespace compatibility + + +//---------------------------------------------------------------------------------------------------------------------- + +#undef CL_HPP_ERR_STR_ +#if !defined(CL_HPP_USER_OVERRIDE_ERROR_STRINGS) +#undef __GET_DEVICE_INFO_ERR +#undef __GET_PLATFORM_INFO_ERR +#undef __GET_DEVICE_IDS_ERR +#undef __GET_CONTEXT_INFO_ERR +#undef __GET_EVENT_INFO_ERR +#undef __GET_EVENT_PROFILE_INFO_ERR +#undef __GET_MEM_OBJECT_INFO_ERR +#undef __GET_IMAGE_INFO_ERR +#undef __GET_SAMPLER_INFO_ERR +#undef __GET_KERNEL_INFO_ERR +#undef __GET_KERNEL_ARG_INFO_ERR +#undef __GET_KERNEL_WORK_GROUP_INFO_ERR +#undef __GET_PROGRAM_INFO_ERR +#undef __GET_PROGRAM_BUILD_INFO_ERR +#undef __GET_COMMAND_QUEUE_INFO_ERR + +#undef __CREATE_CONTEXT_ERR +#undef __CREATE_CONTEXT_FROM_TYPE_ERR +#undef __GET_SUPPORTED_IMAGE_FORMATS_ERR + +#undef __CREATE_BUFFER_ERR +#undef __CREATE_SUBBUFFER_ERR +#undef __CREATE_IMAGE2D_ERR +#undef __CREATE_IMAGE3D_ERR +#undef __CREATE_SAMPLER_ERR +#undef __SET_MEM_OBJECT_DESTRUCTOR_CALLBACK_ERR + +#undef __CREATE_USER_EVENT_ERR +#undef __SET_USER_EVENT_STATUS_ERR +#undef __SET_EVENT_CALLBACK_ERR +#undef __SET_PRINTF_CALLBACK_ERR + +#undef __WAIT_FOR_EVENTS_ERR + +#undef __CREATE_KERNEL_ERR +#undef __SET_KERNEL_ARGS_ERR +#undef __CREATE_PROGRAM_WITH_SOURCE_ERR +#undef __CREATE_PROGRAM_WITH_BINARY_ERR +#undef __CREATE_PROGRAM_WITH_BUILT_IN_KERNELS_ERR +#undef __BUILD_PROGRAM_ERR +#undef __CREATE_KERNELS_IN_PROGRAM_ERR + +#undef __CREATE_COMMAND_QUEUE_ERR +#undef __SET_COMMAND_QUEUE_PROPERTY_ERR +#undef __ENQUEUE_READ_BUFFER_ERR +#undef __ENQUEUE_WRITE_BUFFER_ERR +#undef __ENQUEUE_READ_BUFFER_RECT_ERR +#undef __ENQUEUE_WRITE_BUFFER_RECT_ERR +#undef __ENQEUE_COPY_BUFFER_ERR +#undef __ENQEUE_COPY_BUFFER_RECT_ERR +#undef __ENQUEUE_READ_IMAGE_ERR +#undef __ENQUEUE_WRITE_IMAGE_ERR +#undef __ENQUEUE_COPY_IMAGE_ERR +#undef __ENQUEUE_COPY_IMAGE_TO_BUFFER_ERR +#undef __ENQUEUE_COPY_BUFFER_TO_IMAGE_ERR +#undef __ENQUEUE_MAP_BUFFER_ERR +#undef __ENQUEUE_MAP_IMAGE_ERR +#undef __ENQUEUE_UNMAP_MEM_OBJECT_ERR +#undef __ENQUEUE_NDRANGE_KERNEL_ERR +#undef __ENQUEUE_TASK_ERR +#undef __ENQUEUE_NATIVE_KERNEL + +#undef __UNLOAD_COMPILER_ERR +#undef __CREATE_SUB_DEVICES_ERR + +#undef __CREATE_PIPE_ERR +#undef __GET_PIPE_INFO_ERR + +#endif //CL_HPP_USER_OVERRIDE_ERROR_STRINGS + +// Extensions +#undef CL_HPP_INIT_CL_EXT_FCN_PTR_ +#undef CL_HPP_INIT_CL_EXT_FCN_PTR_PLATFORM_ + +#if defined(CL_HPP_USE_CL_DEVICE_FISSION) +#undef CL_HPP_PARAM_NAME_DEVICE_FISSION_ +#endif // CL_HPP_USE_CL_DEVICE_FISSION + +#undef CL_HPP_NOEXCEPT_ +#undef CL_HPP_DEFINE_STATIC_MEMBER_ + +} // namespace cl + +#endif // CL_HPP_ diff --git a/openpose/include/openpose_private/gpu/cuda.hu b/openpose/include/openpose_private/gpu/cuda.hu new file mode 100644 index 0000000000000000000000000000000000000000..02512303728700ff35135a10d36bca7f6f6c4c6d --- /dev/null +++ b/openpose/include/openpose_private/gpu/cuda.hu @@ -0,0 +1,204 @@ +#ifndef OPENPOSE_PRIVATE_GPU_CUDA_HU +#define OPENPOSE_PRIVATE_GPU_CUDA_HU + +// Note: This class should only be included if CUDA is enabled + +#include +#include + +namespace op +{ + // VERY IMPORTANT: These fast functions does NOT work for negative integer numbers. + // E.g., positiveIntRound(-180.f) = -179. + + // Round functions + // Signed + template + inline __device__ char positiveCharRoundCuda(const T a) + { + return char(a+0.5f); + } + + template + inline __device__ signed char positiveSCharRoundCuda(const T a) + { + return (signed char)(a+0.5f); + } + + template + inline __device__ int positiveIntRoundCuda(const T a) + { + return int(a+0.5f); + } + + template + inline __device__ long positiveLongRoundCuda(const T a) + { + return long(a+0.5f); + } + + template + inline __device__ long long positiveLongLongRoundCuda(const T a) + { + return (long long)(a+0.5f); + } + + // Unsigned + template + inline __device__ unsigned char uCharRoundCuda(const T a) + { + return (unsigned char)(a+0.5f); + } + + template + inline __device__ unsigned int uIntRoundCuda(const T a) + { + return (unsigned int)(a+0.5f); + } + + template + inline __device__ unsigned long ulongRoundCuda(const T a) + { + return (unsigned long)(a+0.5f); + } + + template + inline __device__ unsigned long long uLongLongRoundCuda(const T a) + { + return (unsigned long long)(a+0.5f); + } + + // Max/min functions + template + inline __device__ T fastMaxCuda(const T a, const T b) + { + return (a > b ? a : b); + } + + template + inline __device__ T fastMinCuda(const T a, const T b) + { + return (a < b ? a : b); + } + + template + inline __device__ T fastTruncateCuda(const T value, const T min = 0, const T max = 1) + { + return fastMinCuda(max, fastMaxCuda(min, value)); + } + + // Cubic interpolation + template + inline __device__ void cubicSequentialData( + int* xIntArray, int* yIntArray, T& dx, T& dy, const T xSource, const T ySource, const int widthSource, + const int heightSource) + { + xIntArray[1] = fastTruncateCuda(int(floor(xSource)), 0, widthSource - 1); + xIntArray[0] = fastMaxCuda(0, xIntArray[1] - 1); + xIntArray[2] = fastMinCuda(widthSource - 1, xIntArray[1] + 1); + xIntArray[3] = fastMinCuda(widthSource - 1, xIntArray[2] + 1); + dx = xSource - xIntArray[1]; + + yIntArray[1] = fastTruncateCuda(int(floor(ySource)), 0, heightSource - 1); + yIntArray[0] = fastMaxCuda(0, yIntArray[1] - 1); + yIntArray[2] = fastMinCuda(heightSource - 1, yIntArray[1] + 1); + yIntArray[3] = fastMinCuda(heightSource - 1, yIntArray[2] + 1); + dy = ySource - yIntArray[1]; + } + + template + inline __device__ T cubicInterpolate(const T v0, const T v1, const T v2, const T v3, const T dx) + { + // http://www.paulinternet.nl/?page=bicubic + // const auto a = (-0.5f * v0 + 1.5f * v1 - 1.5f * v2 + 0.5f * v3); + // const auto b = (v0 - 2.5f * v1 + 2.0 * v2 - 0.5 * v3); + // const auto c = (-0.5f * v0 + 0.5f * v2); + // out = ((a * dx + b) * dx + c) * dx + v1; + return (-0.5f * v0 + 1.5f * v1 - 1.5f * v2 + 0.5f * v3) * dx * dx * dx + + (v0 - 2.5f * v1 + 2.f * v2 - 0.5f * v3) * dx * dx + - 0.5f * (v0 - v2) * dx // + (-0.5f * v0 + 0.5f * v2) * dx + + v1; + // return v1 + 0.5f * dx * (v2 - v0 + dx * (2.f * v0 - 5.f * v1 + 4.f * v2 - v3 + dx * (3.f * (v1 - v2) + v3 - v0))); + } + + template + inline __device__ T bicubicInterpolate( + const T* const sourcePtr, const T xSource, const T ySource, const int widthSource, const int heightSource, + const int widthSourcePtr) + { + int xIntArray[4]; + int yIntArray[4]; + T dx; + T dy; + cubicSequentialData(xIntArray, yIntArray, dx, dy, xSource, ySource, widthSource, heightSource); + + T temp[4]; + for (unsigned char i = 0; i < 4; i++) + { + const auto offset = yIntArray[i]*widthSourcePtr; + temp[i] = cubicInterpolate( + sourcePtr[offset + xIntArray[0]], sourcePtr[offset + xIntArray[1]], sourcePtr[offset + xIntArray[2]], + sourcePtr[offset + xIntArray[3]], dx); + } + return cubicInterpolate(temp[0], temp[1], temp[2], temp[3], dy); + } + + template + inline __device__ T bicubicInterpolate( + const unsigned char* const sourcePtr, const T xSource, const T ySource, const int widthSource, + const int heightSource, const int widthSourcePtr) + { + int xIntArray[4]; + int yIntArray[4]; + T dx; + T dy; + cubicSequentialData(xIntArray, yIntArray, dx, dy, xSource, ySource, widthSource, heightSource); + + T temp[4]; + for (unsigned char i = 0; i < 4; i++) + { + const auto offset = yIntArray[i]*widthSourcePtr; + temp[i] = cubicInterpolate( + T(sourcePtr[offset + xIntArray[0]]), T(sourcePtr[offset + xIntArray[1]]), + T(sourcePtr[offset + xIntArray[2]]), T(sourcePtr[offset + xIntArray[3]]), dx); + } + return cubicInterpolate(temp[0], temp[1], temp[2], temp[3], dy); + } + + template + inline __device__ T bicubicInterpolate8Times( + const T* const sourcePtr, const T xSource, const T ySource, const int widthSource, const int heightSource, + const int threadIdxX, const int threadIdxY) + { + // Now we only need dx and dy + const T dx = xSource - fastTruncateCuda(int(floor(xSource)), 0, widthSource - 1); + const T dy = ySource - fastTruncateCuda(int(floor(ySource)), 0, heightSource - 1); + + T temp[4]; + for (unsigned char i = 0; i < 4; i++) + { + const auto offset = 5 * (i + (threadIdxY > 3 ? 1 : 0)) + (threadIdxX > 3 ? 1 : 0); + temp[i] = cubicInterpolate( + sourcePtr[offset], sourcePtr[offset+1], sourcePtr[offset+2], + sourcePtr[offset+3], dx); + } + return cubicInterpolate(temp[0], temp[1], temp[2], temp[3], dy); + } + + template + inline __device__ T addWeighted(const T value1, const T value2, const T alphaValue2) + { + return (1.f - alphaValue2) * value1 + alphaValue2 * value2; + } + + template + inline __device__ void addColorWeighted( + T& colorR, T& colorG, T& colorB, const T* const colorToAdd, const T alphaColorToAdd) + { + colorR = addWeighted(colorR, colorToAdd[0], alphaColorToAdd); + colorG = addWeighted(colorG, colorToAdd[1], alphaColorToAdd); + colorB = addWeighted(colorB, colorToAdd[2], alphaColorToAdd); + } +} + +#endif // OPENPOSE_PRIVATE_GPU_CUDA_HU diff --git a/openpose/include/openpose_private/gpu/opencl.hcl b/openpose/include/openpose_private/gpu/opencl.hcl new file mode 100644 index 0000000000000000000000000000000000000000..82414d1d55b1e2a40c56bdb5c07e5631a9e229d1 --- /dev/null +++ b/openpose/include/openpose_private/gpu/opencl.hcl @@ -0,0 +1,76 @@ +#ifndef OPENPOSE_PRIVATE_GPU_OPENCL_HPP +#define OPENPOSE_PRIVATE_GPU_OPENCL_HPP + +#include + +#define MULTI_LINE_STRING(ARG) #ARG + +#define CL_HPP_ENABLE_EXCEPTIONS + +#ifdef LOWER_CL_VERSION + #define CL_HPP_MINIMUM_OPENCL_VERSION 120 + #define CL_HPP_TARGET_OPENCL_VERSION 120 +#else + #define CL_HPP_MINIMUM_OPENCL_VERSION 120 + #define CL_HPP_TARGET_OPENCL_VERSION 120 +#endif + +typedef struct _cl_buffer_region cl_buffer_region; +#define CL_DEVICE_TYPE_GPU (1 << 2) +namespace cl +{ + class CommandQueue; + class Kernel; + class Device; + class Context; +} + +// Singleton structure +// https://stackoverflow.com/questions/1008019/c-singleton-design-pattern + +namespace op +{ + class OpenCL + { + public: + static std::shared_ptr getInstance(const int deviceId = 0, const int deviceType = CL_DEVICE_TYPE_GPU, + bool getFromVienna = false); + ~OpenCL(); + + cl::CommandQueue& getQueue(); + + cl::Device& getDevice(); + + cl::Context& getContext(); + + template + bool buildKernelIntoManager(const std::string& kernelName, const std::string& src = "", bool isFile = false); + + template + cl::Kernel& getKernelFromManager(const std::string& kernelName, const std::string& src = "", bool isFile = false); + + template + inline K getKernelFunctorFromManager(const std::string& kernelName, const std::string& src = "", bool isFile = false) + { + return K(getKernelFromManager(kernelName, src, isFile)); + } + + template static void getBufferRegion(cl_buffer_region& region, const int origin, const int size); + + int getAlignment(); + + static std::string clErrorToString(int err); + + static int getTotalGPU(); + + private: + struct ImplCLManager; + std::unique_ptr upImpl; + + OpenCL(const int deviceId, const int deviceType, bool getFromVienna); + + DELETE_COPY(OpenCL); + }; +} + +#endif // OPENPOSE_PRIVATE_GPU_OPENCL_HPP diff --git a/openpose/include/openpose_private/tracking/pyramidalLK.hpp b/openpose/include/openpose_private/tracking/pyramidalLK.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d32c307d7676c4a4669dd2b188dbf412ba187ee3 --- /dev/null +++ b/openpose/include/openpose_private/tracking/pyramidalLK.hpp @@ -0,0 +1,27 @@ +#ifndef OPENPOSE_PRIVATE_TRACKING_LKPYRAMIDAL_HPP +#define OPENPOSE_PRIVATE_TRACKING_LKPYRAMIDAL_HPP + +#include // cv::Mat, cv::Point2f +#include + +namespace op +{ + void pyramidalLKCpu( + std::vector& coordI, std::vector& coordJ, + std::vector& pyramidImagesPrevious, std::vector& pyramidImagesCurrent, + std::vector& status, const cv::Mat& imagePrevious, const cv::Mat& imageCurrent, + const int levels = 3, const int patchSize = 21); + + int pyramidalLKGpu( + std::vector& ptsI, std::vector& ptsJ, + std::vector& status, const cv::Mat& imagePrevious, const cv::Mat& imageCurrent, + const int levels = 3, const int patchSize = 21); + + void pyramidalLKOcv( + std::vector& coordI, std::vector& coordJ, + std::vector& pyramidImagesPrevious, std::vector& pyramidImagesCurrent, + std::vector& status, const cv::Mat& imagePrevious, const cv::Mat& imageCurrent, + const int levels = 3, const int patchSize = 21, const bool initFlow = false); +} + +#endif // OPENPOSE_PRIVATE_TRACKING_LKPYRAMIDAL_HPP diff --git a/openpose/include/openpose_private/utilities/avx.hpp b/openpose/include/openpose_private/utilities/avx.hpp new file mode 100644 index 0000000000000000000000000000000000000000..cca24d35c152856c321b2585884b24aeb245325d --- /dev/null +++ b/openpose/include/openpose_private/utilities/avx.hpp @@ -0,0 +1,100 @@ +#ifndef OPENPOSE_PRIVATE_UTILITIES_AVX_HPP +#define OPENPOSE_PRIVATE_UTILITIES_AVX_HPP + +// Warning: +// This file contains auxiliary functions for AVX. +// This file should only be included from cpp files. +// Default #include does not include it. + +#ifdef WITH_AVX + #include // uintptr_t + #include // shared_ptr + #include + #include + + namespace op + { + #ifdef __GNUC__ + #define ALIGN32(x) x __attribute__((aligned(32))) + #elif defined(_MSC_VER) // defined(_WIN32) + #define ALIGN32(x) __declspec(align(32)) + #else + #error Unknown environment! + #endif + + // Functions + // Sources: + // - https://stackoverflow.com/questions/32612190/how-to-solve-the-32-byte-alignment-issue-for-avx-load-store-operations + // - https://embeddedartistry.com/blog/2017/2/20/implementing-aligned-malloc + // - https://embeddedartistry.com/blog/2017/2/23/c-smart-pointers-with-aligned-mallocfree + typedef unsigned long long offset_t; + #define PTR_OFFSET_SZ sizeof(offset_t) + #ifndef align_up + #define align_up(num, align) \ + (((num) + ((align) - 1)) & ~((align) - 1)) + #endif + inline void * aligned_malloc(const size_t align, const size_t size) + { + void * ptr = nullptr; + + // 2 conditions: + // - We want both align and size to be greater than 0 + // - We want it to be a power of two since align_up operates on powers of two + if (align && size && (align & (align - 1)) == 0) + { + // We know we have to fit an offset value + // We also allocate extra bytes to ensure we can meet the alignment + const auto hdr_size = PTR_OFFSET_SZ + (align - 1); + void * p = malloc(size + hdr_size); + + if (p) + { + // Add the offset size to malloc's pointer (we will always store that) + // Then align the resulting value to the arget alignment + ptr = (void *) align_up(((uintptr_t)p + PTR_OFFSET_SZ), align); + + // Calculate the offset and store it behind our aligned pointer + *((offset_t *)ptr - 1) = (offset_t)((uintptr_t)ptr - (uintptr_t)p); + + } // else nullptr, could not malloc + } // else nullptr, invalid arguments + + if (ptr == nullptr) + { + error("Shared pointer could not be allocated for Array data storage.", + __LINE__, __FUNCTION__, __FILE__); + } + + return ptr; + } + inline void aligned_free(void * ptr) + { + if (ptr == nullptr) + error("Received nullptr.", __LINE__, __FUNCTION__, __FILE__); + + // Walk backwards from the passed-in pointer to get the pointer offset + // We convert to an offset_t pointer and rely on pointer math to get the data + offset_t offset = *((offset_t *)ptr - 1); + + // Once we have the offset, we can get our original pointer and call free + void * p = (void *)((uint8_t *)ptr - offset); + free(p); + } + template + std::shared_ptr aligned_shared_ptr(const size_t size) + { + try + { + return std::shared_ptr(static_cast( + aligned_malloc(8*sizeof(T), sizeof(T)*size)), &aligned_free); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return std::shared_ptr{}; + } + } + } +#endif + +#endif // OPENPOSE_PRIVATE_UTILITIES_AVX_HPP diff --git a/openpose/include/openpose_private/utilities/openCvMultiversionHeaders.hpp b/openpose/include/openpose_private/utilities/openCvMultiversionHeaders.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4c7858376371db956ce17455efd2b0dfb4b13026 --- /dev/null +++ b/openpose/include/openpose_private/utilities/openCvMultiversionHeaders.hpp @@ -0,0 +1,50 @@ +#ifndef OPENPOSE_PRIVATE_UTILITIES_OPENCV_MULTIVERSION_HEADERS_HPP +#define OPENPOSE_PRIVATE_UTILITIES_OPENCV_MULTIVERSION_HEADERS_HPP + +#include + +// Compatibility for OpenCV 4.0 while preserving 2.4.X and 3.X HEADERS +// Note: +// - CV_VERSION: 2.4.9.1 | 4.0.0-beta +// - CV_MAJOR_VERSION: 2 | 4 +// - CV_MINOR_VERSION: 4 | 0 +// - CV_SUBMINOR_VERSION: 9 | 0 +// - CV_VERSION_EPOCH: 2 | Not defined +#if (defined(CV_MAJOR_VERSION) && CV_MAJOR_VERSION > 3) + #define OPEN_CV_IS_4_OR_HIGHER +#endif +#ifdef OPEN_CV_IS_4_OR_HIGHER + #define CV_BGR2GRAY cv::COLOR_BGR2GRAY + #define CV_BGR2RGB cv::COLOR_BGR2RGB + #define CV_CALIB_CB_ADAPTIVE_THRESH cv::CALIB_CB_ADAPTIVE_THRESH + #define CV_CALIB_CB_NORMALIZE_IMAGE cv::CALIB_CB_NORMALIZE_IMAGE + #define CV_CALIB_CB_FILTER_QUADS cv::CALIB_CB_FILTER_QUADS + #define CV_CAP_PROP_FPS cv::CAP_PROP_FPS + #define CV_CAP_PROP_FRAME_COUNT cv::CAP_PROP_FRAME_COUNT + #define CV_CAP_PROP_FRAME_HEIGHT cv::CAP_PROP_FRAME_HEIGHT + #define CV_CAP_PROP_FRAME_WIDTH cv::CAP_PROP_FRAME_WIDTH + #define CV_CAP_PROP_POS_FRAMES cv::CAP_PROP_POS_FRAMES + #define CV_FOURCC cv::VideoWriter::fourcc + #define CV_GRAY2BGR cv::COLOR_GRAY2BGR + #define CV_HAAR_SCALE_IMAGE cv::CASCADE_SCALE_IMAGE + #define CV_INTER_CUBIC cv::INTER_CUBIC + #define CV_INTER_LINEAR cv::INTER_LINEAR + #define CV_L2 cv::NORM_L2 + #define CV_RGB2BGR cv::COLOR_RGB2BGR + #define CV_TERMCRIT_EPS cv::TermCriteria::Type::EPS + #define CV_TERMCRIT_ITER cv::TermCriteria::Type::MAX_ITER + #define CV_WARP_INVERSE_MAP cv::WARP_INVERSE_MAP + #define CV_WINDOW_FULLSCREEN cv::WINDOW_FULLSCREEN + #define CV_WINDOW_KEEPRATIO cv::WINDOW_KEEPRATIO + #define CV_WINDOW_NORMAL cv::WINDOW_NORMAL + #define CV_WINDOW_OPENGL cv::WINDOW_OPENGL + #define CV_WND_PROP_FULLSCREEN cv::WND_PROP_FULLSCREEN + #include + #define CV_IMWRITE_JPEG_QUALITY cv::IMWRITE_JPEG_QUALITY + #define CV_IMWRITE_PNG_COMPRESSION cv::IMWRITE_PNG_COMPRESSION + #define CV_LOAD_IMAGE_ANYDEPTH cv::IMREAD_ANYDEPTH + #define CV_LOAD_IMAGE_COLOR cv::IMREAD_COLOR + #define CV_LOAD_IMAGE_GRAYSCALE cv::IMREAD_GRAYSCALE +#endif + +#endif // OPENPOSE_PRIVATE_UTILITIES_OPENCV_MULTIVERSION_HEADERS_HPP diff --git a/openpose/include/openpose_private/utilities/openCvPrivate.hpp b/openpose/include/openpose_private/utilities/openCvPrivate.hpp new file mode 100644 index 0000000000000000000000000000000000000000..70501589899c2a9665d2edf4ca4d57b9d67ef91f --- /dev/null +++ b/openpose/include/openpose_private/utilities/openCvPrivate.hpp @@ -0,0 +1,19 @@ +#ifndef OPENPOSE_PRIVATE_UTILITIES_OPEN_CV_PRIVATE_HPP +#define OPENPOSE_PRIVATE_UTILITIES_OPEN_CV_PRIVATE_HPP + +#include // cv::Mat, cv::Rect, cv::Scalar +#include // cv::BORDER_CONSTANT +#include + +namespace op +{ + void putTextOnCvMat( + cv::Mat& cvMat, const std::string& textToDisplay, const Point& position, + const cv::Scalar& color, const bool normalizeWidth, const int imageWidth); + + void resizeFixedAspectRatio( + cv::Mat& resizedCvMat, const cv::Mat& cvMat, const double scaleFactor, const Point& targetSize, + const int borderMode = cv::BORDER_CONSTANT, const cv::Scalar& borderValue = cv::Scalar{0,0,0}); +} + +#endif // OPENPOSE_PRIVATE_UTILITIES_OPEN_CV_PRIVATE_HPP diff --git a/openpose/include/openpose_private/utilities/render.hu b/openpose/include/openpose_private/utilities/render.hu new file mode 100644 index 0000000000000000000000000000000000000000..89622af8d3ccb76f1bb297ec5bd0833bed12a649 --- /dev/null +++ b/openpose/include/openpose_private/utilities/render.hu @@ -0,0 +1,388 @@ +#ifndef OPENPOSE_PRIVATE_UTILITIES_RENDER_HU +#define OPENPOSE_PRIVATE_UTILITIES_RENDER_HU + +namespace op +{ + __inline__ __device__ void getBoundingBoxPerPerson( + float* maxPtr, float* minPtr, float* scalePtr,const unsigned int targetWidth, const unsigned int targetHeight, + const float* const keypointsPtr, const int numberPeople, const int numberParts, const float threshold) + { + const unsigned long globalIdx = threadIdx.x; + + // Fill shared parameters + if (globalIdx < numberPeople) + { + float minValueX = (float)targetWidth; + float minValueY = (float)targetHeight; + float maxValueX = 0.f; + float maxValueY = 0.f; + for (auto part = 0 ; part < numberParts ; part++) + { + const unsigned long index = 3u * (globalIdx*numberParts + part); + const float x = keypointsPtr[index]; + const float y = keypointsPtr[index+1]; + const float score = keypointsPtr[index+2]; + if (score > threshold) + { + if (x < minValueX) + minValueX = x; + if (x > maxValueX) + maxValueX = x; + if (y < minValueY) + minValueY = y; + if (y > maxValueY) + maxValueY = y; + } + } + if (maxValueX != 0.f && maxValueY != 0.f) + { + const auto averageX = maxValueX - minValueX; + const auto averageY = maxValueY - minValueY; + // (averageX + averageY) / 2.f / 400.f + scalePtr[globalIdx] = fastTruncateCuda((averageX + averageY) / 400.f, 0.33f, 1.f); + const auto constantToAdd = 50.f; + maxValueX += constantToAdd; + maxValueY += constantToAdd; + minValueX -= constantToAdd; + minValueY -= constantToAdd; + } + + // const auto xIndex = 2*globalIdx; + // const auto yIndex = xIndex+1; + const auto xIndex = globalIdx; + const auto yIndex = numberPeople+globalIdx; + minPtr[xIndex] = minValueX; + minPtr[yIndex] = minValueY; + maxPtr[xIndex] = maxValueX; + maxPtr[yIndex] = maxValueY; + } + } + + // Note: renderKeypoints is not working for videos with many people, renderKeypointsOld speed was slightly improved instead + __inline__ __device__ void renderKeypoints( + float* targetPtr, float* sharedMaxs, float* sharedMins, float* sharedScaleF, const float* const maxPtr, + const float* const minPtr, const float* const scalePtr, const int globalIdx, const int x, const int y, + const unsigned int targetWidth, const unsigned int targetHeight, const float* const keypointsPtr, + const unsigned int* const partPairsPtr, const int numberPeople, const int numberParts, + const int numberPartPairs, const float* const rgbColorsPtr, const int numberColors, const float radius, + const float lineWidth, const float* const keypointScalePtr, const int numberScales, const float threshold, + const float alphaColorToAdd, const bool blendOriginalFrame = true, const int googlyEye1 = -1, + const int googlyEye2 = -1) + { + // Load shared memory + if (globalIdx < 2*numberPeople) + { + sharedMins[globalIdx] = minPtr[globalIdx]; + sharedMaxs[globalIdx] = maxPtr[globalIdx]; + if (globalIdx < numberPeople) + sharedScaleF[globalIdx] = scalePtr[globalIdx]; + } + __syncthreads(); + + // Fill each (x,y) target pixel + if (x < targetWidth && y < targetHeight) + { + const unsigned long baseIndex = 3u*(y * (unsigned long)targetWidth + x); + float b = targetPtr[baseIndex]; + float g = targetPtr[baseIndex+1]; + float r = targetPtr[baseIndex+2]; + if (!blendOriginalFrame) + { + b = 0.f; + g = 0.f; + r = 0.f; + } + + const auto lineWidthSquared = lineWidth * lineWidth; + const auto radiusSquared = radius * radius; + for (auto person = 0; person < numberPeople; person++) + { + // Make sure person x,y in the limits + // Make sure person is not empty. Assume all joints are below threshold. Then + // maxs = 0 and mins = width/height. So if statement would be false + // const auto xIndex = 2*person; + // const auto yIndex = xIndex+1; + const auto xIndex = person; + const auto yIndex = numberPeople+person; + if (x <= sharedMaxs[xIndex] && x >= sharedMins[xIndex] + && y <= sharedMaxs[yIndex] && y >= sharedMins[yIndex]) + { + // Part pair connections + for (auto partPair = 0; partPair < numberPartPairs; partPair++) + { + const auto partA = partPairsPtr[2*partPair]; + const auto partB = partPairsPtr[2*partPair+1]; + const auto indexA = person*numberParts*3 + partA*3; + const auto xA = keypointsPtr[indexA]; + const auto yA = keypointsPtr[indexA + 1]; + const auto scoreA = keypointsPtr[indexA + 2]; + const auto indexB = person*numberParts*3 + partB*3; + const auto xB = keypointsPtr[indexB]; + const auto yB = keypointsPtr[indexB + 1]; + const auto scoreB = keypointsPtr[indexB + 2]; + + if (scoreA > threshold && scoreB > threshold) + { + const auto keypointScale = keypointScalePtr[partB%numberScales] + * keypointScalePtr[partB%numberScales] + * keypointScalePtr[partB%numberScales]; + const auto lineWidthScaled = lineWidthSquared * keypointScale; + const auto bSqrt = sharedScaleF[person] * sharedScaleF[person] * lineWidthScaled; + + const auto xP = (xA + xB) / 2.f; + const auto yP = (yA + yB) / 2.f; + const auto aSqrt = (xA - xP) * (xA - xP) + (yA - yP) * (yA - yP); + + const auto angle = atan2f(yB - yA, xB - xA); + const auto sine = sinf(angle); + const auto cosine = cosf(angle); + const auto A = cosine * (x - xP) + sine * (y - yP); + const auto B = sine * (x - xP) - cosine * (y - yP); + + const auto judge = A * A / aSqrt + B * B / bSqrt; + const auto minV = 0.f; + const auto maxV = 1.f; + if (minV <= judge && judge <= maxV) + // Before used partPair vs partB + addColorWeighted(r, g, b, &rgbColorsPtr[(partB%numberColors)*3], alphaColorToAdd); + } + } + + // Part circles + for (auto part = 0u; part < numberParts; part++) + { + const auto index = 3 * (person*numberParts + part); + const auto localX = keypointsPtr[index]; + const auto localY = keypointsPtr[index + 1]; + const auto score = keypointsPtr[index + 2]; + + if (score > threshold) + { + const auto keypointScale = keypointScalePtr[part%numberScales] + * keypointScalePtr[part%numberScales] + * keypointScalePtr[part%numberScales]; + const auto radiusScaled = radiusSquared * keypointScale; + const auto dist2 = (x - localX) * (x - localX) + (y - localY) * (y - localY); + // Googly eyes + if (googlyEye1 == part || googlyEye2 == part) + { + const auto eyeRatio = 2.5f * sqrt(radiusScaled); + const auto minr2 = sharedScaleF[person] * sharedScaleF[person] + * (eyeRatio - 2) * (eyeRatio - 2); + const auto maxr2 = sharedScaleF[person] * sharedScaleF[person] * eyeRatio * eyeRatio; + if (dist2 <= maxr2) + { + float colorToAdd [3] = {0., 0., 0.}; + if (dist2 <= minr2) + for (auto& color : colorToAdd) + color = {255.f}; + if (dist2 <= minr2*0.6f) + { + const auto dist3 = (x-4 - localX) + * (x-4 - localX) + (y - localY+4) * (y - localY+4); + if (dist3 > 14.0625f) // 3.75f^2 + for (auto& color : colorToAdd) + color = {0.f}; + } + const auto alphaColorToAdd = 0.9f; + addColorWeighted(r, g, b, colorToAdd, alphaColorToAdd); + } + } + // Other parts + else + { + const auto minr2 = 0.f; + const auto maxr2 = sharedScaleF[person] * sharedScaleF[person] * radiusScaled; + if (minr2 <= dist2 && dist2 <= maxr2) + addColorWeighted(r, g, b, &rgbColorsPtr[(part%numberColors)*3], alphaColorToAdd); + } + } + } + } + } + targetPtr[baseIndex] = b; + targetPtr[baseIndex+1] = g; + targetPtr[baseIndex+2] = r; + } + } + + __inline__ __device__ void renderKeypointsOld( + float* targetPtr, float2* sharedMaxs, float2* sharedMins, float* sharedScaleF, const int globalIdx, + const int x, const int y, const unsigned int targetWidth, const unsigned int targetHeight, const float* const keypointsPtr, + const unsigned int* const partPairsPtr, const int numberPeople, const int numberParts, + const int numberPartPairs, const float* const rgbColorsPtr, const int numberColors, const float radius, + const float lineWidth, const float* const keypointScalePtr, const int numberScales, const float threshold, + const float alphaColorToAdd, const bool blendOriginalFrame = true, const int googlyEye1 = -1, + const int googlyEye2 = -1) + { + // Fill shared parameters + if (globalIdx < numberPeople) + { + float minValueX = (float)targetWidth; + float minValueY = (float)targetHeight; + float maxValueX = 0.f; + float maxValueY = 0.f; + for (auto part = 0 ; part < numberParts ; part++) + { + const unsigned long index = 3u * (((unsigned long)globalIdx)*numberParts + part); + const float x = keypointsPtr[index]; + const float y = keypointsPtr[index+1]; + const float score = keypointsPtr[index+2]; + if (score > threshold) + { + if (x < minValueX) + minValueX = x; + if (x > maxValueX) + maxValueX = x; + if (y < minValueY) + minValueY = y; + if (y > maxValueY) + maxValueY = y; + } + } + if (maxValueX != 0.f && maxValueY != 0.f) + { + const auto averageX = maxValueX - minValueX; + const auto averageY = maxValueY - minValueY; + // (averageX + averageY) / 2.f / 400.f + sharedScaleF[globalIdx] = fastTruncateCuda((averageX + averageY) / 400.f, 0.33f, 1.f); + const auto constantToAdd = 50.f; + maxValueX += constantToAdd; + maxValueY += constantToAdd; + minValueX -= constantToAdd; + minValueY -= constantToAdd; + } + + sharedMins[globalIdx].x = minValueX; + sharedMins[globalIdx].y = minValueY; + sharedMaxs[globalIdx].x = maxValueX; + sharedMaxs[globalIdx].y = maxValueY; + } + __syncthreads(); + + // Fill each (x,y) target pixel + if (x < targetWidth && y < targetHeight) + { + const unsigned long baseIndex = 3u*(y * (unsigned long)targetWidth + x); + float b = targetPtr[baseIndex]; + float g = targetPtr[baseIndex+1]; + float r = targetPtr[baseIndex+2]; + if (!blendOriginalFrame) + { + b = 0.f; + g = 0.f; + r = 0.f; + } + + const auto lineWidthSquared = lineWidth * lineWidth; + const auto radiusSquared = radius * radius; + for (auto person = 0; person < numberPeople; person++) + { + // Make sure person x,y in the limits + // Make sure person is not empty. Assume all joints are below threshold. Then + // maxs = 0 and mins = width/height. So if statement would be false + if (x <= sharedMaxs[person].x && x >= sharedMins[person].x + && y <= sharedMaxs[person].y && y >= sharedMins[person].y) + { + // Part pair connections + for (auto partPair = 0; partPair < numberPartPairs; partPair++) + { + const auto partA = partPairsPtr[2*partPair]; + const auto partB = partPairsPtr[2*partPair+1]; + const auto indexA = person*numberParts*3 + partA*3; + const auto xA = keypointsPtr[indexA]; + const auto yA = keypointsPtr[indexA + 1]; + const auto scoreA = keypointsPtr[indexA + 2]; + const auto indexB = person*numberParts*3 + partB*3; + const auto xB = keypointsPtr[indexB]; + const auto yB = keypointsPtr[indexB + 1]; + const auto scoreB = keypointsPtr[indexB + 2]; + + if (scoreA > threshold && scoreB > threshold) + { + const auto keypointScale = keypointScalePtr[partB%numberScales] + * keypointScalePtr[partB%numberScales] + * keypointScalePtr[partB%numberScales]; + const auto lineWidthScaled = lineWidthSquared * keypointScale; + const auto bSqrt = sharedScaleF[person] * sharedScaleF[person] * lineWidthScaled; + + const auto xP = (xA + xB) / 2.f; + const auto yP = (yA + yB) / 2.f; + const auto aSqrt = (xA - xP) * (xA - xP) + (yA - yP) * (yA - yP); + + const auto angle = atan2f(yB - yA, xB - xA); + const auto sine = sinf(angle); + const auto cosine = cosf(angle); + const auto A = cosine * (x - xP) + sine * (y - yP); + const auto B = sine * (x - xP) - cosine * (y - yP); + + const auto judge = A * A / aSqrt + B * B / bSqrt; + const auto minV = 0.f; + const auto maxV = 1.f; + if (minV <= judge && judge <= maxV) + // Before used partPair vs partB + addColorWeighted(r, g, b, &rgbColorsPtr[(partB%numberColors)*3], alphaColorToAdd); + } + } + + // Part circles + for (auto part = 0u; part < numberParts; part++) + { + const auto index = 3 * (person*numberParts + part); + const auto localX = keypointsPtr[index]; + const auto localY = keypointsPtr[index + 1]; + const auto score = keypointsPtr[index + 2]; + + if (score > threshold) + { + const auto keypointScale = keypointScalePtr[part%numberScales] + * keypointScalePtr[part%numberScales] + * keypointScalePtr[part%numberScales]; + const auto radiusScaled = radiusSquared * keypointScale; + const auto dist2 = (x - localX) * (x - localX) + (y - localY) * (y - localY); + // Googly eyes + if (googlyEye1 == part || googlyEye2 == part) + { + const auto eyeRatio = 2.5f * sqrt(radiusScaled); + const auto minr2 = sharedScaleF[person] * sharedScaleF[person] + * (eyeRatio - 2) * (eyeRatio - 2); + const auto maxr2 = sharedScaleF[person] * sharedScaleF[person] * eyeRatio * eyeRatio; + if (dist2 <= maxr2) + { + float colorToAdd [3] = {0., 0., 0.}; + if (dist2 <= minr2) + for (auto& color : colorToAdd) + color = {255.f}; + if (dist2 <= minr2*0.6f) + { + const auto dist3 = (x-4 - localX) + * (x-4 - localX) + (y - localY+4) * (y - localY+4); + if (dist3 > 14.0625f) // 3.75f^2 + for (auto& color : colorToAdd) + color = {0.f}; + } + const auto alphaColorToAdd = 0.9f; + addColorWeighted(r, g, b, colorToAdd, alphaColorToAdd); + } + } + // Other parts + else + { + const auto minr2 = 0.f; + const auto maxr2 = sharedScaleF[person] * sharedScaleF[person] * radiusScaled; + if (minr2 <= dist2 && dist2 <= maxr2) + addColorWeighted(r, g, b, &rgbColorsPtr[(part%numberColors)*3], alphaColorToAdd); + } + } + } + } + } + targetPtr[baseIndex] = b; + targetPtr[baseIndex+1] = g; + targetPtr[baseIndex+2] = r; + } + } +} + + +#endif // OPENPOSE_PRIVATE_UTILITIES_RENDER_HU diff --git a/openpose/models/cameraParameters/flir/17012332.xml.example b/openpose/models/cameraParameters/flir/17012332.xml.example new file mode 100644 index 0000000000000000000000000000000000000000..84aa5e0a155e8bf0eee4e12040d01f557c6c98e0 --- /dev/null +++ b/openpose/models/cameraParameters/flir/17012332.xml.example @@ -0,0 +1,28 @@ + + + + + 3 + 4 +
d
+ + 1. 0. 0. 0. + 0. 1. 0. 0. + 0. 0. 1. 0.
+ + 3 + 3 +
d
+ + 8.1793481631740565e+02 0. 6.0070689997785121e+02 0. + 8.1651774059837908e+02 5.1784529566329593e+02 0. 0. 1.
+ + 8 + 1 +
d
+ + -1.8102158829399091e+00 9.1966147162623262e+00 + -4.4293900343777355e-04 1.3638377686816653e-03 + 1.3303863414979364e+00 -1.4189051636354870e+00 + 8.4725535468475819e+00 4.7911023525901033e+00
+
diff --git a/openpose/models/face/pose_deploy.prototxt b/openpose/models/face/pose_deploy.prototxt new file mode 100644 index 0000000000000000000000000000000000000000..d347748cac0bd03b09a45bfe4772654145c7dda5 --- /dev/null +++ b/openpose/models/face/pose_deploy.prototxt @@ -0,0 +1,1728 @@ +input: "image" +input_dim: 1 +input_dim: 3 +input_dim: 1 # Original: 368 +input_dim: 1 # Original: 368 +# input: "weights" +# input_dim: 1 +# input_dim: 71 +# input_dim: 184 +# input_dim: 184 +# input: "labels" +# input_dim: 1 +# input_dim: 71 +# input_dim: 184 +# input_dim: 184 + +layer { + name: "conv1_1" + type: "Convolution" + bottom: "image" + top: "conv1_1" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 64 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "conv1_1_re" + type: "ReLU" + bottom: "conv1_1" + top: "conv1_1" +} +layer { + name: "conv1_2" + type: "Convolution" + bottom: "conv1_1" + top: "conv1_2" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 64 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "conv1_2_re" + type: "ReLU" + bottom: "conv1_2" + top: "conv1_2" +} +layer { + name: "pool1" + type: "Pooling" + bottom: "conv1_2" + top: "pool1" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layer { + name: "conv2_1" + type: "Convolution" + bottom: "pool1" + top: "conv2_1" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "conv2_1_re" + type: "ReLU" + bottom: "conv2_1" + top: "conv2_1" +} +layer { + name: "conv2_2" + type: "Convolution" + bottom: "conv2_1" + top: "conv2_2" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "conv2_2_re" + type: "ReLU" + bottom: "conv2_2" + top: "conv2_2" +} +layer { + name: "pool2" + type: "Pooling" + bottom: "conv2_2" + top: "pool2" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layer { + name: "conv3_1" + type: "Convolution" + bottom: "pool2" + top: "conv3_1" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "conv3_1_re" + type: "ReLU" + bottom: "conv3_1" + top: "conv3_1" +} +layer { + name: "conv3_2" + type: "Convolution" + bottom: "conv3_1" + top: "conv3_2" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "conv3_2_re" + type: "ReLU" + bottom: "conv3_2" + top: "conv3_2" +} +layer { + name: "conv3_3" + type: "Convolution" + bottom: "conv3_2" + top: "conv3_3" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "conv3_3_re" + type: "ReLU" + bottom: "conv3_3" + top: "conv3_3" +} +layer { + name: "conv3_4" + type: "Convolution" + bottom: "conv3_3" + top: "conv3_4" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "conv3_4_re" + type: "ReLU" + bottom: "conv3_4" + top: "conv3_4" +} +layer { + name: "pool3" + type: "Pooling" + bottom: "conv3_4" + top: "pool3" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layer { + name: "conv4_1" + type: "Convolution" + bottom: "pool3" + top: "conv4_1" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "conv4_1_re" + type: "ReLU" + bottom: "conv4_1" + top: "conv4_1" +} +layer { + name: "conv4_2" + type: "Convolution" + bottom: "conv4_1" + top: "conv4_2" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "conv4_2_re" + type: "ReLU" + bottom: "conv4_2" + top: "conv4_2" +} +layer { + name: "conv4_3" + type: "Convolution" + bottom: "conv4_2" + top: "conv4_3" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "conv4_3_re" + type: "ReLU" + bottom: "conv4_3" + top: "conv4_3" +} +layer { + name: "conv4_4" + type: "Convolution" + bottom: "conv4_3" + top: "conv4_4" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "conv4_4_re" + type: "ReLU" + bottom: "conv4_4" + top: "conv4_4" +} +layer { + name: "conv5_1" + type: "Convolution" + bottom: "conv4_4" + top: "conv5_1" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "conv5_1_re" + type: "ReLU" + bottom: "conv5_1" + top: "conv5_1" +} +layer { + name: "conv5_2" + type: "Convolution" + bottom: "conv5_1" + top: "conv5_2" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "conv5_2_re" + type: "ReLU" + bottom: "conv5_2" + top: "conv5_2" +} +layer { + name: "conv5_3_CPM" + type: "Convolution" + bottom: "conv5_2" + top: "conv5_3_CPM" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "conv5_3_CPM_re" + type: "ReLU" + bottom: "conv5_3_CPM" + top: "conv5_3_CPM" +} +layer { + name: "conv6_1_CPM" + type: "Convolution" + bottom: "conv5_3_CPM" + top: "conv6_1_CPM" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "conv6_1_CPM_re" + type: "ReLU" + bottom: "conv6_1_CPM" + top: "conv6_1_CPM" +} +layer { + name: "conv6_2_CPM" + type: "Convolution" + bottom: "conv6_1_CPM" + top: "conv6_2_CPM" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 71 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "features_in_stage_2" + type: "Concat" + bottom: "conv6_2_CPM" + bottom: "conv5_3_CPM" + top: "features_in_stage_2" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage2" + type: "Convolution" + bottom: "features_in_stage_2" + top: "Mconv1_stage2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv1_stage2_re" + type: "ReLU" + bottom: "Mconv1_stage2" + top: "Mconv1_stage2" +} +layer { + name: "Mconv2_stage2" + type: "Convolution" + bottom: "Mconv1_stage2" + top: "Mconv2_stage2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv2_stage2_re" + type: "ReLU" + bottom: "Mconv2_stage2" + top: "Mconv2_stage2" +} +layer { + name: "Mconv3_stage2" + type: "Convolution" + bottom: "Mconv2_stage2" + top: "Mconv3_stage2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv3_stage2_re" + type: "ReLU" + bottom: "Mconv3_stage2" + top: "Mconv3_stage2" +} +layer { + name: "Mconv4_stage2" + type: "Convolution" + bottom: "Mconv3_stage2" + top: "Mconv4_stage2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv4_stage2_re" + type: "ReLU" + bottom: "Mconv4_stage2" + top: "Mconv4_stage2" +} +layer { + name: "Mconv5_stage2" + type: "Convolution" + bottom: "Mconv4_stage2" + top: "Mconv5_stage2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv5_stage2_re" + type: "ReLU" + bottom: "Mconv5_stage2" + top: "Mconv5_stage2" +} +layer { + name: "Mconv6_stage2" + type: "Convolution" + bottom: "Mconv5_stage2" + top: "Mconv6_stage2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv6_stage2_re" + type: "ReLU" + bottom: "Mconv6_stage2" + top: "Mconv6_stage2" +} +layer { + name: "Mconv7_stage2" + type: "Convolution" + bottom: "Mconv6_stage2" + top: "Mconv7_stage2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 71 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "features_in_stage_3" + type: "Concat" + bottom: "Mconv7_stage2" + bottom: "conv5_3_CPM" + top: "features_in_stage_3" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage3" + type: "Convolution" + bottom: "features_in_stage_3" + top: "Mconv1_stage3" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv1_stage3_re" + type: "ReLU" + bottom: "Mconv1_stage3" + top: "Mconv1_stage3" +} +layer { + name: "Mconv2_stage3" + type: "Convolution" + bottom: "Mconv1_stage3" + top: "Mconv2_stage3" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv2_stage3_re" + type: "ReLU" + bottom: "Mconv2_stage3" + top: "Mconv2_stage3" +} +layer { + name: "Mconv3_stage3" + type: "Convolution" + bottom: "Mconv2_stage3" + top: "Mconv3_stage3" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv3_stage3_re" + type: "ReLU" + bottom: "Mconv3_stage3" + top: "Mconv3_stage3" +} +layer { + name: "Mconv4_stage3" + type: "Convolution" + bottom: "Mconv3_stage3" + top: "Mconv4_stage3" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv4_stage3_re" + type: "ReLU" + bottom: "Mconv4_stage3" + top: "Mconv4_stage3" +} +layer { + name: "Mconv5_stage3" + type: "Convolution" + bottom: "Mconv4_stage3" + top: "Mconv5_stage3" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv5_stage3_re" + type: "ReLU" + bottom: "Mconv5_stage3" + top: "Mconv5_stage3" +} +layer { + name: "Mconv6_stage3" + type: "Convolution" + bottom: "Mconv5_stage3" + top: "Mconv6_stage3" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv6_stage3_re" + type: "ReLU" + bottom: "Mconv6_stage3" + top: "Mconv6_stage3" +} +layer { + name: "Mconv7_stage3" + type: "Convolution" + bottom: "Mconv6_stage3" + top: "Mconv7_stage3" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 71 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "features_in_stage_4" + type: "Concat" + bottom: "Mconv7_stage3" + bottom: "conv5_3_CPM" + top: "features_in_stage_4" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage4" + type: "Convolution" + bottom: "features_in_stage_4" + top: "Mconv1_stage4" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv1_stage4_re" + type: "ReLU" + bottom: "Mconv1_stage4" + top: "Mconv1_stage4" +} +layer { + name: "Mconv2_stage4" + type: "Convolution" + bottom: "Mconv1_stage4" + top: "Mconv2_stage4" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv2_stage4_re" + type: "ReLU" + bottom: "Mconv2_stage4" + top: "Mconv2_stage4" +} +layer { + name: "Mconv3_stage4" + type: "Convolution" + bottom: "Mconv2_stage4" + top: "Mconv3_stage4" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv3_stage4_re" + type: "ReLU" + bottom: "Mconv3_stage4" + top: "Mconv3_stage4" +} +layer { + name: "Mconv4_stage4" + type: "Convolution" + bottom: "Mconv3_stage4" + top: "Mconv4_stage4" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv4_stage4_re" + type: "ReLU" + bottom: "Mconv4_stage4" + top: "Mconv4_stage4" +} +layer { + name: "Mconv5_stage4" + type: "Convolution" + bottom: "Mconv4_stage4" + top: "Mconv5_stage4" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv5_stage4_re" + type: "ReLU" + bottom: "Mconv5_stage4" + top: "Mconv5_stage4" +} +layer { + name: "Mconv6_stage4" + type: "Convolution" + bottom: "Mconv5_stage4" + top: "Mconv6_stage4" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv6_stage4_re" + type: "ReLU" + bottom: "Mconv6_stage4" + top: "Mconv6_stage4" +} +layer { + name: "Mconv7_stage4" + type: "Convolution" + bottom: "Mconv6_stage4" + top: "Mconv7_stage4" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 71 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "features_in_stage_5" + type: "Concat" + bottom: "Mconv7_stage4" + bottom: "conv5_3_CPM" + top: "features_in_stage_5" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage5" + type: "Convolution" + bottom: "features_in_stage_5" + top: "Mconv1_stage5" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv1_stage5_re" + type: "ReLU" + bottom: "Mconv1_stage5" + top: "Mconv1_stage5" +} +layer { + name: "Mconv2_stage5" + type: "Convolution" + bottom: "Mconv1_stage5" + top: "Mconv2_stage5" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv2_stage5_re" + type: "ReLU" + bottom: "Mconv2_stage5" + top: "Mconv2_stage5" +} +layer { + name: "Mconv3_stage5" + type: "Convolution" + bottom: "Mconv2_stage5" + top: "Mconv3_stage5" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv3_stage5_re" + type: "ReLU" + bottom: "Mconv3_stage5" + top: "Mconv3_stage5" +} +layer { + name: "Mconv4_stage5" + type: "Convolution" + bottom: "Mconv3_stage5" + top: "Mconv4_stage5" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv4_stage5_re" + type: "ReLU" + bottom: "Mconv4_stage5" + top: "Mconv4_stage5" +} +layer { + name: "Mconv5_stage5" + type: "Convolution" + bottom: "Mconv4_stage5" + top: "Mconv5_stage5" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv5_stage5_re" + type: "ReLU" + bottom: "Mconv5_stage5" + top: "Mconv5_stage5" +} +layer { + name: "Mconv6_stage5" + type: "Convolution" + bottom: "Mconv5_stage5" + top: "Mconv6_stage5" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv6_stage5_re" + type: "ReLU" + bottom: "Mconv6_stage5" + top: "Mconv6_stage5" +} +layer { + name: "Mconv7_stage5" + type: "Convolution" + bottom: "Mconv6_stage5" + top: "Mconv7_stage5" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 71 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "features_in_stage_6" + type: "Concat" + bottom: "Mconv7_stage5" + bottom: "conv5_3_CPM" + top: "features_in_stage_6" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage6" + type: "Convolution" + bottom: "features_in_stage_6" + top: "Mconv1_stage6" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv1_stage6_re" + type: "ReLU" + bottom: "Mconv1_stage6" + top: "Mconv1_stage6" +} +layer { + name: "Mconv2_stage6" + type: "Convolution" + bottom: "Mconv1_stage6" + top: "Mconv2_stage6" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv2_stage6_re" + type: "ReLU" + bottom: "Mconv2_stage6" + top: "Mconv2_stage6" +} +layer { + name: "Mconv3_stage6" + type: "Convolution" + bottom: "Mconv2_stage6" + top: "Mconv3_stage6" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv3_stage6_re" + type: "ReLU" + bottom: "Mconv3_stage6" + top: "Mconv3_stage6" +} +layer { + name: "Mconv4_stage6" + type: "Convolution" + bottom: "Mconv3_stage6" + top: "Mconv4_stage6" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv4_stage6_re" + type: "ReLU" + bottom: "Mconv4_stage6" + top: "Mconv4_stage6" +} +layer { + name: "Mconv5_stage6" + type: "Convolution" + bottom: "Mconv4_stage6" + top: "Mconv5_stage6" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv5_stage6_re" + type: "ReLU" + bottom: "Mconv5_stage6" + top: "Mconv5_stage6" +} +layer { + name: "Mconv6_stage6" + type: "Convolution" + bottom: "Mconv5_stage6" + top: "Mconv6_stage6" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv6_stage6_re" + type: "ReLU" + bottom: "Mconv6_stage6" + top: "Mconv6_stage6" +} +layer { + name: "Mconv7_stage6" + type: "Convolution" + bottom: "Mconv6_stage6" +# top: "Mconv7_stage6" + top: "net_output" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 71 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} diff --git a/openpose/models/getModels.bat b/openpose/models/getModels.bat new file mode 100644 index 0000000000000000000000000000000000000000..c74d7ec02d8a481760a9dbacef393b5e4f2f007e --- /dev/null +++ b/openpose/models/getModels.bat @@ -0,0 +1,43 @@ +:: Avoid printing all the comments in the Windows cmd +@echo off + +echo ------------------------- BODY, FOOT, FACE, AND HAND MODELS ------------------------- +echo ----- Downloading body pose (COCO and MPI), face and hand models ----- +SET WGET_EXE=..\3rdparty\windows\wget\wget.exe +SET OPENPOSE_URL=http://vcl.snu.ac.kr/OpenPose/models/ +SET POSE_FOLDER=pose/ +SET FACE_FOLDER=face/ +SET HAND_FOLDER=hand/ + +echo: +echo ------------------------- POSE (BODY+FOOT) MODELS ------------------------- +echo Body (BODY_25) +set BODY_25_FOLDER=%POSE_FOLDER%body_25/ +set BODY_25_MODEL=%BODY_25_FOLDER%pose_iter_584000.caffemodel +%WGET_EXE% -c %OPENPOSE_URL%%BODY_25_MODEL% -P %BODY_25_FOLDER% + +echo Body (COCO) +SET COCO_FOLDER=%POSE_FOLDER%coco/ +SET COCO_MODEL=%COCO_FOLDER%pose_iter_440000.caffemodel +%WGET_EXE% -c %OPENPOSE_URL%%COCO_MODEL% -P %COCO_FOLDER% + +echo: +echo Body (MPI) +SET MPI_FOLDER=%POSE_FOLDER%mpi/ +SET MPI_MODEL=%MPI_FOLDER%pose_iter_160000.caffemodel +%WGET_EXE% -c %OPENPOSE_URL%%MPI_MODEL% -P %MPI_FOLDER% +echo ----------------------- POSE DOWNLOADED ----------------------- + +echo: +echo ------------------------- FACE MODELS ------------------------- +echo Face +SET FACE_MODEL=%FACE_FOLDER%pose_iter_116000.caffemodel +%WGET_EXE% -c %OPENPOSE_URL%%FACE_MODEL% -P %FACE_FOLDER% +echo ----------------------- FACE DOWNLOADED ----------------------- + +echo: +echo ------------------------- HAND MODELS ------------------------- +echo Hand +SET HAND_MODEL=%HAND_FOLDER%pose_iter_102000.caffemodel +%WGET_EXE% -c %OPENPOSE_URL%%HAND_MODEL% -P %HAND_FOLDER% +echo ----------------------- HAND DOWNLOADED ----------------------- diff --git a/openpose/models/getModels.sh b/openpose/models/getModels.sh new file mode 100644 index 0000000000000000000000000000000000000000..7d420d42b49ad56648b50f7837694c825ccf42c7 --- /dev/null +++ b/openpose/models/getModels.sh @@ -0,0 +1,36 @@ +# ------------------------- BODY, FOOT, FACE, AND HAND MODELS ------------------------- +# Downloading body pose (COCO and MPI), face and hand models +OPENPOSE_URL="http://vcl.snu.ac.kr/OpenPose/models/" +POSE_FOLDER="pose/" +FACE_FOLDER="face/" +HAND_FOLDER="hand/" + +# ------------------------- POSE (BODY+FOOT) MODELS ------------------------- +# Body (BODY_25) +BODY_25_FOLDER=${POSE_FOLDER}"body_25/" +BODY_25_MODEL=${BODY_25_FOLDER}"pose_iter_584000.caffemodel" +wget -c ${OPENPOSE_URL}${BODY_25_MODEL} -P ${BODY_25_FOLDER} + +# Body (COCO) +COCO_FOLDER=${POSE_FOLDER}"coco/" +COCO_MODEL=${COCO_FOLDER}"pose_iter_440000.caffemodel" +wget -c ${OPENPOSE_URL}${COCO_MODEL} -P ${COCO_FOLDER} +# Alternative: it will not check whether file was fully downloaded +# if [ ! -f $COCO_MODEL ]; then +# wget ${OPENPOSE_URL}$COCO_MODEL -P $COCO_FOLDER +# fi + +# Body (MPI) +MPI_FOLDER=${POSE_FOLDER}"mpi/" +MPI_MODEL=${MPI_FOLDER}"pose_iter_160000.caffemodel" +wget -c ${OPENPOSE_URL}${MPI_MODEL} -P ${MPI_FOLDER} + +# "------------------------- FACE MODELS -------------------------" +# Face +FACE_MODEL=${FACE_FOLDER}"pose_iter_116000.caffemodel" +wget -c ${OPENPOSE_URL}${FACE_MODEL} -P ${FACE_FOLDER} + +# "------------------------- HAND MODELS -------------------------" +# Hand +HAND_MODEL=$HAND_FOLDER"pose_iter_102000.caffemodel" +wget -c ${OPENPOSE_URL}${HAND_MODEL} -P ${HAND_FOLDER} diff --git a/openpose/models/hand/pose_deploy.prototxt b/openpose/models/hand/pose_deploy.prototxt new file mode 100644 index 0000000000000000000000000000000000000000..3554c3a02e3dc545b3da4f32a0c954b452289706 --- /dev/null +++ b/openpose/models/hand/pose_deploy.prototxt @@ -0,0 +1,1756 @@ +input: "image" +input_dim: 1 # Original: 2 +input_dim: 3 # It crashes if not left to 3 +input_dim: 1 # Original: 368 +input_dim: 1 # Original: 368 +layer { + name: "conv1_1" + type: "Convolution" + bottom: "image" + top: "conv1_1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 64 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "relu1_1" + type: "ReLU" + bottom: "conv1_1" + top: "conv1_1" +} +layer { + name: "conv1_2" + type: "Convolution" + bottom: "conv1_1" + top: "conv1_2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 64 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "relu1_2" + type: "ReLU" + bottom: "conv1_2" + top: "conv1_2" +} +layer { + name: "pool1_stage1" + type: "Pooling" + bottom: "conv1_2" + top: "pool1_stage1" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layer { + name: "conv2_1" + type: "Convolution" + bottom: "pool1_stage1" + top: "conv2_1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "relu2_1" + type: "ReLU" + bottom: "conv2_1" + top: "conv2_1" +} +layer { + name: "conv2_2" + type: "Convolution" + bottom: "conv2_1" + top: "conv2_2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "relu2_2" + type: "ReLU" + bottom: "conv2_2" + top: "conv2_2" +} +layer { + name: "pool2_stage1" + type: "Pooling" + bottom: "conv2_2" + top: "pool2_stage1" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layer { + name: "conv3_1" + type: "Convolution" + bottom: "pool2_stage1" + top: "conv3_1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "relu3_1" + type: "ReLU" + bottom: "conv3_1" + top: "conv3_1" +} +layer { + name: "conv3_2" + type: "Convolution" + bottom: "conv3_1" + top: "conv3_2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "relu3_2" + type: "ReLU" + bottom: "conv3_2" + top: "conv3_2" +} +layer { + name: "conv3_3" + type: "Convolution" + bottom: "conv3_2" + top: "conv3_3" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "relu3_3" + type: "ReLU" + bottom: "conv3_3" + top: "conv3_3" +} +layer { + name: "conv3_4" + type: "Convolution" + bottom: "conv3_3" + top: "conv3_4" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "relu3_4" + type: "ReLU" + bottom: "conv3_4" + top: "conv3_4" +} +layer { + name: "pool3_stage1" + type: "Pooling" + bottom: "conv3_4" + top: "pool3_stage1" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layer { + name: "conv4_1" + type: "Convolution" + bottom: "pool3_stage1" + top: "conv4_1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "relu4_1" + type: "ReLU" + bottom: "conv4_1" + top: "conv4_1" +} +layer { + name: "conv4_2" + type: "Convolution" + bottom: "conv4_1" + top: "conv4_2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "relu4_2" + type: "ReLU" + bottom: "conv4_2" + top: "conv4_2" +} +layer { + name: "conv4_3" + type: "Convolution" + bottom: "conv4_2" + top: "conv4_3" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "relu4_3" + type: "ReLU" + bottom: "conv4_3" + top: "conv4_3" +} +layer { + name: "conv4_4" + type: "Convolution" + bottom: "conv4_3" + top: "conv4_4" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "relu4_4" + type: "ReLU" + bottom: "conv4_4" + top: "conv4_4" +} +layer { + name: "conv5_1" + type: "Convolution" + bottom: "conv4_4" + top: "conv5_1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "relu5_1" + type: "ReLU" + bottom: "conv5_1" + top: "conv5_1" +} +layer { + name: "conv5_2" + type: "Convolution" + bottom: "conv5_1" + top: "conv5_2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "relu5_2" + type: "ReLU" + bottom: "conv5_2" + top: "conv5_2" +} +layer { + name: "conv5_3_CPM" + type: "Convolution" + bottom: "conv5_2" + top: "conv5_3_CPM" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "relu5_4_stage1_3" + type: "ReLU" + bottom: "conv5_3_CPM" + top: "conv5_3_CPM" +} +layer { + name: "conv6_1_CPM" + type: "Convolution" + bottom: "conv5_3_CPM" + top: "conv6_1_CPM" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "relu6_4_stage1_1" + type: "ReLU" + bottom: "conv6_1_CPM" + top: "conv6_1_CPM" +} +layer { + name: "conv6_2_CPM" + type: "Convolution" + bottom: "conv6_1_CPM" + top: "conv6_2_CPM" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 22 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "concat_stage2" + type: "Concat" + bottom: "conv6_2_CPM" + bottom: "conv5_3_CPM" + top: "concat_stage2" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage2" + type: "Convolution" + bottom: "concat_stage2" + top: "Mconv1_stage2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_2_stage2_1" + type: "ReLU" + bottom: "Mconv1_stage2" + top: "Mconv1_stage2" +} +layer { + name: "Mconv2_stage2" + type: "Convolution" + bottom: "Mconv1_stage2" + top: "Mconv2_stage2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_3_stage2_2" + type: "ReLU" + bottom: "Mconv2_stage2" + top: "Mconv2_stage2" +} +layer { + name: "Mconv3_stage2" + type: "Convolution" + bottom: "Mconv2_stage2" + top: "Mconv3_stage2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_4_stage2_3" + type: "ReLU" + bottom: "Mconv3_stage2" + top: "Mconv3_stage2" +} +layer { + name: "Mconv4_stage2" + type: "Convolution" + bottom: "Mconv3_stage2" + top: "Mconv4_stage2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_5_stage2_4" + type: "ReLU" + bottom: "Mconv4_stage2" + top: "Mconv4_stage2" +} +layer { + name: "Mconv5_stage2" + type: "Convolution" + bottom: "Mconv4_stage2" + top: "Mconv5_stage2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_6_stage2_5" + type: "ReLU" + bottom: "Mconv5_stage2" + top: "Mconv5_stage2" +} +layer { + name: "Mconv6_stage2" + type: "Convolution" + bottom: "Mconv5_stage2" + top: "Mconv6_stage2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_7_stage2_6" + type: "ReLU" + bottom: "Mconv6_stage2" + top: "Mconv6_stage2" +} +layer { + name: "Mconv7_stage2" + type: "Convolution" + bottom: "Mconv6_stage2" + top: "Mconv7_stage2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 22 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "concat_stage3" + type: "Concat" + bottom: "Mconv7_stage2" + bottom: "conv5_3_CPM" + top: "concat_stage3" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage3" + type: "Convolution" + bottom: "concat_stage3" + top: "Mconv1_stage3" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_2_stage3_1" + type: "ReLU" + bottom: "Mconv1_stage3" + top: "Mconv1_stage3" +} +layer { + name: "Mconv2_stage3" + type: "Convolution" + bottom: "Mconv1_stage3" + top: "Mconv2_stage3" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_3_stage3_2" + type: "ReLU" + bottom: "Mconv2_stage3" + top: "Mconv2_stage3" +} +layer { + name: "Mconv3_stage3" + type: "Convolution" + bottom: "Mconv2_stage3" + top: "Mconv3_stage3" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_4_stage3_3" + type: "ReLU" + bottom: "Mconv3_stage3" + top: "Mconv3_stage3" +} +layer { + name: "Mconv4_stage3" + type: "Convolution" + bottom: "Mconv3_stage3" + top: "Mconv4_stage3" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_5_stage3_4" + type: "ReLU" + bottom: "Mconv4_stage3" + top: "Mconv4_stage3" +} +layer { + name: "Mconv5_stage3" + type: "Convolution" + bottom: "Mconv4_stage3" + top: "Mconv5_stage3" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_6_stage3_5" + type: "ReLU" + bottom: "Mconv5_stage3" + top: "Mconv5_stage3" +} +layer { + name: "Mconv6_stage3" + type: "Convolution" + bottom: "Mconv5_stage3" + top: "Mconv6_stage3" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_7_stage3_6" + type: "ReLU" + bottom: "Mconv6_stage3" + top: "Mconv6_stage3" +} +layer { + name: "Mconv7_stage3" + type: "Convolution" + bottom: "Mconv6_stage3" + top: "Mconv7_stage3" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 22 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "concat_stage4" + type: "Concat" + bottom: "Mconv7_stage3" + bottom: "conv5_3_CPM" + top: "concat_stage4" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage4" + type: "Convolution" + bottom: "concat_stage4" + top: "Mconv1_stage4" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_2_stage4_1" + type: "ReLU" + bottom: "Mconv1_stage4" + top: "Mconv1_stage4" +} +layer { + name: "Mconv2_stage4" + type: "Convolution" + bottom: "Mconv1_stage4" + top: "Mconv2_stage4" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_3_stage4_2" + type: "ReLU" + bottom: "Mconv2_stage4" + top: "Mconv2_stage4" +} +layer { + name: "Mconv3_stage4" + type: "Convolution" + bottom: "Mconv2_stage4" + top: "Mconv3_stage4" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_4_stage4_3" + type: "ReLU" + bottom: "Mconv3_stage4" + top: "Mconv3_stage4" +} +layer { + name: "Mconv4_stage4" + type: "Convolution" + bottom: "Mconv3_stage4" + top: "Mconv4_stage4" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_5_stage4_4" + type: "ReLU" + bottom: "Mconv4_stage4" + top: "Mconv4_stage4" +} +layer { + name: "Mconv5_stage4" + type: "Convolution" + bottom: "Mconv4_stage4" + top: "Mconv5_stage4" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_6_stage4_5" + type: "ReLU" + bottom: "Mconv5_stage4" + top: "Mconv5_stage4" +} +layer { + name: "Mconv6_stage4" + type: "Convolution" + bottom: "Mconv5_stage4" + top: "Mconv6_stage4" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_7_stage4_6" + type: "ReLU" + bottom: "Mconv6_stage4" + top: "Mconv6_stage4" +} +layer { + name: "Mconv7_stage4" + type: "Convolution" + bottom: "Mconv6_stage4" + top: "Mconv7_stage4" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 22 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "concat_stage5" + type: "Concat" + bottom: "Mconv7_stage4" + bottom: "conv5_3_CPM" + top: "concat_stage5" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage5" + type: "Convolution" + bottom: "concat_stage5" + top: "Mconv1_stage5" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_2_stage5_1" + type: "ReLU" + bottom: "Mconv1_stage5" + top: "Mconv1_stage5" +} +layer { + name: "Mconv2_stage5" + type: "Convolution" + bottom: "Mconv1_stage5" + top: "Mconv2_stage5" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_3_stage5_2" + type: "ReLU" + bottom: "Mconv2_stage5" + top: "Mconv2_stage5" +} +layer { + name: "Mconv3_stage5" + type: "Convolution" + bottom: "Mconv2_stage5" + top: "Mconv3_stage5" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_4_stage5_3" + type: "ReLU" + bottom: "Mconv3_stage5" + top: "Mconv3_stage5" +} +layer { + name: "Mconv4_stage5" + type: "Convolution" + bottom: "Mconv3_stage5" + top: "Mconv4_stage5" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_5_stage5_4" + type: "ReLU" + bottom: "Mconv4_stage5" + top: "Mconv4_stage5" +} +layer { + name: "Mconv5_stage5" + type: "Convolution" + bottom: "Mconv4_stage5" + top: "Mconv5_stage5" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_6_stage5_5" + type: "ReLU" + bottom: "Mconv5_stage5" + top: "Mconv5_stage5" +} +layer { + name: "Mconv6_stage5" + type: "Convolution" + bottom: "Mconv5_stage5" + top: "Mconv6_stage5" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_7_stage5_6" + type: "ReLU" + bottom: "Mconv6_stage5" + top: "Mconv6_stage5" +} +layer { + name: "Mconv7_stage5" + type: "Convolution" + bottom: "Mconv6_stage5" + top: "Mconv7_stage5" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 22 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "concat_stage6" + type: "Concat" + bottom: "Mconv7_stage5" + bottom: "conv5_3_CPM" + top: "concat_stage6" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage6" + type: "Convolution" + bottom: "concat_stage6" + top: "Mconv1_stage6" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_2_stage6_1" + type: "ReLU" + bottom: "Mconv1_stage6" + top: "Mconv1_stage6" +} +layer { + name: "Mconv2_stage6" + type: "Convolution" + bottom: "Mconv1_stage6" + top: "Mconv2_stage6" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_3_stage6_2" + type: "ReLU" + bottom: "Mconv2_stage6" + top: "Mconv2_stage6" +} +layer { + name: "Mconv3_stage6" + type: "Convolution" + bottom: "Mconv2_stage6" + top: "Mconv3_stage6" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_4_stage6_3" + type: "ReLU" + bottom: "Mconv3_stage6" + top: "Mconv3_stage6" +} +layer { + name: "Mconv4_stage6" + type: "Convolution" + bottom: "Mconv3_stage6" + top: "Mconv4_stage6" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_5_stage6_4" + type: "ReLU" + bottom: "Mconv4_stage6" + top: "Mconv4_stage6" +} +layer { + name: "Mconv5_stage6" + type: "Convolution" + bottom: "Mconv4_stage6" + top: "Mconv5_stage6" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_6_stage6_5" + type: "ReLU" + bottom: "Mconv5_stage6" + top: "Mconv5_stage6" +} +layer { + name: "Mconv6_stage6" + type: "Convolution" + bottom: "Mconv5_stage6" + top: "Mconv6_stage6" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} +layer { + name: "Mrelu1_7_stage6_6" + type: "ReLU" + bottom: "Mconv6_stage6" + top: "Mconv6_stage6" +} +layer { + name: "Mconv7_stage6" + type: "Convolution" + bottom: "Mconv6_stage6" +# top: "Mconv7_stage6" + top: "net_output" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 22 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + dilation: 1 + } +} + diff --git a/openpose/models/pose/body_25/pose_deploy.prototxt b/openpose/models/pose/body_25/pose_deploy.prototxt new file mode 100644 index 0000000000000000000000000000000000000000..bd18b9d3a225cf64c172a51cc7b03d9c481ca604 --- /dev/null +++ b/openpose/models/pose/body_25/pose_deploy.prototxt @@ -0,0 +1,2332 @@ +name: "OpenPose - BODY_25" +input: "image" +input_dim: 1 # This value will be defined at runtime +input_dim: 3 +input_dim: 16 # This value will be defined at runtime +input_dim: 16 # This value will be defined at runtime +layer { + name: "conv1_1" + type: "Convolution" + bottom: "image" + top: "conv1_1" + convolution_param { + num_output: 64 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "relu1_1" + type: "ReLU" + bottom: "conv1_1" + top: "conv1_1" +} +layer { + name: "conv1_2" + type: "Convolution" + bottom: "conv1_1" + top: "conv1_2" + convolution_param { + num_output: 64 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "relu1_2" + type: "ReLU" + bottom: "conv1_2" + top: "conv1_2" +} +layer { + name: "pool1_stage1" + type: "Pooling" + bottom: "conv1_2" + top: "pool1_stage1" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layer { + name: "conv2_1" + type: "Convolution" + bottom: "pool1_stage1" + top: "conv2_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "relu2_1" + type: "ReLU" + bottom: "conv2_1" + top: "conv2_1" +} +layer { + name: "conv2_2" + type: "Convolution" + bottom: "conv2_1" + top: "conv2_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "relu2_2" + type: "ReLU" + bottom: "conv2_2" + top: "conv2_2" +} +layer { + name: "pool2_stage1" + type: "Pooling" + bottom: "conv2_2" + top: "pool2_stage1" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layer { + name: "conv3_1" + type: "Convolution" + bottom: "pool2_stage1" + top: "conv3_1" + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "relu3_1" + type: "ReLU" + bottom: "conv3_1" + top: "conv3_1" +} +layer { + name: "conv3_2" + type: "Convolution" + bottom: "conv3_1" + top: "conv3_2" + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "relu3_2" + type: "ReLU" + bottom: "conv3_2" + top: "conv3_2" +} +layer { + name: "conv3_3" + type: "Convolution" + bottom: "conv3_2" + top: "conv3_3" + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "relu3_3" + type: "ReLU" + bottom: "conv3_3" + top: "conv3_3" +} +layer { + name: "conv3_4" + type: "Convolution" + bottom: "conv3_3" + top: "conv3_4" + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "relu3_4" + type: "ReLU" + bottom: "conv3_4" + top: "conv3_4" +} +layer { + name: "pool3_stage1" + type: "Pooling" + bottom: "conv3_4" + top: "pool3_stage1" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layer { + name: "conv4_1" + type: "Convolution" + bottom: "pool3_stage1" + top: "conv4_1" + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "relu4_1" + type: "ReLU" + bottom: "conv4_1" + top: "conv4_1" +} +layer { + name: "conv4_2" + type: "Convolution" + bottom: "conv4_1" + top: "conv4_2" + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "prelu4_2" + type: "PReLU" + bottom: "conv4_2" + top: "conv4_2" +} +layer { + name: "conv4_3_CPM" + type: "Convolution" + bottom: "conv4_2" + top: "conv4_3_CPM" + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "prelu4_3_CPM" + type: "PReLU" + bottom: "conv4_3_CPM" + top: "conv4_3_CPM" +} +layer { + name: "conv4_4_CPM" + type: "Convolution" + bottom: "conv4_3_CPM" + top: "conv4_4_CPM" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "prelu4_4_CPM" + type: "PReLU" + bottom: "conv4_4_CPM" + top: "conv4_4_CPM" +} +layer { + name: "Mconv1_stage0_L2_0" + type: "Convolution" + bottom: "conv4_4_CPM" + top: "Mconv1_stage0_L2_0" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu1_stage0_L2_0" + type: "PReLU" + bottom: "Mconv1_stage0_L2_0" + top: "Mconv1_stage0_L2_0" +} +layer { + name: "Mconv1_stage0_L2_1" + type: "Convolution" + bottom: "Mconv1_stage0_L2_0" + top: "Mconv1_stage0_L2_1" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu1_stage0_L2_1" + type: "PReLU" + bottom: "Mconv1_stage0_L2_1" + top: "Mconv1_stage0_L2_1" +} +layer { + name: "Mconv1_stage0_L2_2" + type: "Convolution" + bottom: "Mconv1_stage0_L2_1" + top: "Mconv1_stage0_L2_2" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu1_stage0_L2_2" + type: "PReLU" + bottom: "Mconv1_stage0_L2_2" + top: "Mconv1_stage0_L2_2" +} +layer { + name: "Mconv1_stage0_L2_concat" + type: "Concat" + bottom: "Mconv1_stage0_L2_0" + bottom: "Mconv1_stage0_L2_1" + bottom: "Mconv1_stage0_L2_2" + top: "Mconv1_stage0_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv2_stage0_L2_0" + type: "Convolution" + bottom: "Mconv1_stage0_L2_concat" + top: "Mconv2_stage0_L2_0" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu2_stage0_L2_0" + type: "PReLU" + bottom: "Mconv2_stage0_L2_0" + top: "Mconv2_stage0_L2_0" +} +layer { + name: "Mconv2_stage0_L2_1" + type: "Convolution" + bottom: "Mconv2_stage0_L2_0" + top: "Mconv2_stage0_L2_1" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu2_stage0_L2_1" + type: "PReLU" + bottom: "Mconv2_stage0_L2_1" + top: "Mconv2_stage0_L2_1" +} +layer { + name: "Mconv2_stage0_L2_2" + type: "Convolution" + bottom: "Mconv2_stage0_L2_1" + top: "Mconv2_stage0_L2_2" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu2_stage0_L2_2" + type: "PReLU" + bottom: "Mconv2_stage0_L2_2" + top: "Mconv2_stage0_L2_2" +} +layer { + name: "Mconv2_stage0_L2_concat" + type: "Concat" + bottom: "Mconv2_stage0_L2_0" + bottom: "Mconv2_stage0_L2_1" + bottom: "Mconv2_stage0_L2_2" + top: "Mconv2_stage0_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv3_stage0_L2_0" + type: "Convolution" + bottom: "Mconv2_stage0_L2_concat" + top: "Mconv3_stage0_L2_0" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu3_stage0_L2_0" + type: "PReLU" + bottom: "Mconv3_stage0_L2_0" + top: "Mconv3_stage0_L2_0" +} +layer { + name: "Mconv3_stage0_L2_1" + type: "Convolution" + bottom: "Mconv3_stage0_L2_0" + top: "Mconv3_stage0_L2_1" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu3_stage0_L2_1" + type: "PReLU" + bottom: "Mconv3_stage0_L2_1" + top: "Mconv3_stage0_L2_1" +} +layer { + name: "Mconv3_stage0_L2_2" + type: "Convolution" + bottom: "Mconv3_stage0_L2_1" + top: "Mconv3_stage0_L2_2" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu3_stage0_L2_2" + type: "PReLU" + bottom: "Mconv3_stage0_L2_2" + top: "Mconv3_stage0_L2_2" +} +layer { + name: "Mconv3_stage0_L2_concat" + type: "Concat" + bottom: "Mconv3_stage0_L2_0" + bottom: "Mconv3_stage0_L2_1" + bottom: "Mconv3_stage0_L2_2" + top: "Mconv3_stage0_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv4_stage0_L2_0" + type: "Convolution" + bottom: "Mconv3_stage0_L2_concat" + top: "Mconv4_stage0_L2_0" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu4_stage0_L2_0" + type: "PReLU" + bottom: "Mconv4_stage0_L2_0" + top: "Mconv4_stage0_L2_0" +} +layer { + name: "Mconv4_stage0_L2_1" + type: "Convolution" + bottom: "Mconv4_stage0_L2_0" + top: "Mconv4_stage0_L2_1" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu4_stage0_L2_1" + type: "PReLU" + bottom: "Mconv4_stage0_L2_1" + top: "Mconv4_stage0_L2_1" +} +layer { + name: "Mconv4_stage0_L2_2" + type: "Convolution" + bottom: "Mconv4_stage0_L2_1" + top: "Mconv4_stage0_L2_2" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu4_stage0_L2_2" + type: "PReLU" + bottom: "Mconv4_stage0_L2_2" + top: "Mconv4_stage0_L2_2" +} +layer { + name: "Mconv4_stage0_L2_concat" + type: "Concat" + bottom: "Mconv4_stage0_L2_0" + bottom: "Mconv4_stage0_L2_1" + bottom: "Mconv4_stage0_L2_2" + top: "Mconv4_stage0_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv5_stage0_L2_0" + type: "Convolution" + bottom: "Mconv4_stage0_L2_concat" + top: "Mconv5_stage0_L2_0" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu5_stage0_L2_0" + type: "PReLU" + bottom: "Mconv5_stage0_L2_0" + top: "Mconv5_stage0_L2_0" +} +layer { + name: "Mconv5_stage0_L2_1" + type: "Convolution" + bottom: "Mconv5_stage0_L2_0" + top: "Mconv5_stage0_L2_1" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu5_stage0_L2_1" + type: "PReLU" + bottom: "Mconv5_stage0_L2_1" + top: "Mconv5_stage0_L2_1" +} +layer { + name: "Mconv5_stage0_L2_2" + type: "Convolution" + bottom: "Mconv5_stage0_L2_1" + top: "Mconv5_stage0_L2_2" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu5_stage0_L2_2" + type: "PReLU" + bottom: "Mconv5_stage0_L2_2" + top: "Mconv5_stage0_L2_2" +} +layer { + name: "Mconv5_stage0_L2_concat" + type: "Concat" + bottom: "Mconv5_stage0_L2_0" + bottom: "Mconv5_stage0_L2_1" + bottom: "Mconv5_stage0_L2_2" + top: "Mconv5_stage0_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv6_stage0_L2" + type: "Convolution" + bottom: "Mconv5_stage0_L2_concat" + top: "Mconv6_stage0_L2" + convolution_param { + num_output: 256 + pad: 0 + kernel_size: 1 + } +} +layer { + name: "Mprelu6_stage0_L2" + type: "PReLU" + bottom: "Mconv6_stage0_L2" + top: "Mconv6_stage0_L2" +} +layer { + name: "Mconv7_stage0_L2" + type: "Convolution" + bottom: "Mconv6_stage0_L2" + top: "Mconv7_stage0_L2" + convolution_param { + num_output: 52 + pad: 0 + kernel_size: 1 + } +} +layer { + name: "concat_stage1_L2" + type: "Concat" + bottom: "conv4_4_CPM" + bottom: "Mconv7_stage0_L2" + top: "concat_stage1_L2" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage1_L2_0" + type: "Convolution" + bottom: "concat_stage1_L2" + top: "Mconv1_stage1_L2_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu1_stage1_L2_0" + type: "PReLU" + bottom: "Mconv1_stage1_L2_0" + top: "Mconv1_stage1_L2_0" +} +layer { + name: "Mconv1_stage1_L2_1" + type: "Convolution" + bottom: "Mconv1_stage1_L2_0" + top: "Mconv1_stage1_L2_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu1_stage1_L2_1" + type: "PReLU" + bottom: "Mconv1_stage1_L2_1" + top: "Mconv1_stage1_L2_1" +} +layer { + name: "Mconv1_stage1_L2_2" + type: "Convolution" + bottom: "Mconv1_stage1_L2_1" + top: "Mconv1_stage1_L2_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu1_stage1_L2_2" + type: "PReLU" + bottom: "Mconv1_stage1_L2_2" + top: "Mconv1_stage1_L2_2" +} +layer { + name: "Mconv1_stage1_L2_concat" + type: "Concat" + bottom: "Mconv1_stage1_L2_0" + bottom: "Mconv1_stage1_L2_1" + bottom: "Mconv1_stage1_L2_2" + top: "Mconv1_stage1_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv2_stage1_L2_0" + type: "Convolution" + bottom: "Mconv1_stage1_L2_concat" + top: "Mconv2_stage1_L2_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu2_stage1_L2_0" + type: "PReLU" + bottom: "Mconv2_stage1_L2_0" + top: "Mconv2_stage1_L2_0" +} +layer { + name: "Mconv2_stage1_L2_1" + type: "Convolution" + bottom: "Mconv2_stage1_L2_0" + top: "Mconv2_stage1_L2_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu2_stage1_L2_1" + type: "PReLU" + bottom: "Mconv2_stage1_L2_1" + top: "Mconv2_stage1_L2_1" +} +layer { + name: "Mconv2_stage1_L2_2" + type: "Convolution" + bottom: "Mconv2_stage1_L2_1" + top: "Mconv2_stage1_L2_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu2_stage1_L2_2" + type: "PReLU" + bottom: "Mconv2_stage1_L2_2" + top: "Mconv2_stage1_L2_2" +} +layer { + name: "Mconv2_stage1_L2_concat" + type: "Concat" + bottom: "Mconv2_stage1_L2_0" + bottom: "Mconv2_stage1_L2_1" + bottom: "Mconv2_stage1_L2_2" + top: "Mconv2_stage1_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv3_stage1_L2_0" + type: "Convolution" + bottom: "Mconv2_stage1_L2_concat" + top: "Mconv3_stage1_L2_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu3_stage1_L2_0" + type: "PReLU" + bottom: "Mconv3_stage1_L2_0" + top: "Mconv3_stage1_L2_0" +} +layer { + name: "Mconv3_stage1_L2_1" + type: "Convolution" + bottom: "Mconv3_stage1_L2_0" + top: "Mconv3_stage1_L2_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu3_stage1_L2_1" + type: "PReLU" + bottom: "Mconv3_stage1_L2_1" + top: "Mconv3_stage1_L2_1" +} +layer { + name: "Mconv3_stage1_L2_2" + type: "Convolution" + bottom: "Mconv3_stage1_L2_1" + top: "Mconv3_stage1_L2_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu3_stage1_L2_2" + type: "PReLU" + bottom: "Mconv3_stage1_L2_2" + top: "Mconv3_stage1_L2_2" +} +layer { + name: "Mconv3_stage1_L2_concat" + type: "Concat" + bottom: "Mconv3_stage1_L2_0" + bottom: "Mconv3_stage1_L2_1" + bottom: "Mconv3_stage1_L2_2" + top: "Mconv3_stage1_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv4_stage1_L2_0" + type: "Convolution" + bottom: "Mconv3_stage1_L2_concat" + top: "Mconv4_stage1_L2_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu4_stage1_L2_0" + type: "PReLU" + bottom: "Mconv4_stage1_L2_0" + top: "Mconv4_stage1_L2_0" +} +layer { + name: "Mconv4_stage1_L2_1" + type: "Convolution" + bottom: "Mconv4_stage1_L2_0" + top: "Mconv4_stage1_L2_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu4_stage1_L2_1" + type: "PReLU" + bottom: "Mconv4_stage1_L2_1" + top: "Mconv4_stage1_L2_1" +} +layer { + name: "Mconv4_stage1_L2_2" + type: "Convolution" + bottom: "Mconv4_stage1_L2_1" + top: "Mconv4_stage1_L2_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu4_stage1_L2_2" + type: "PReLU" + bottom: "Mconv4_stage1_L2_2" + top: "Mconv4_stage1_L2_2" +} +layer { + name: "Mconv4_stage1_L2_concat" + type: "Concat" + bottom: "Mconv4_stage1_L2_0" + bottom: "Mconv4_stage1_L2_1" + bottom: "Mconv4_stage1_L2_2" + top: "Mconv4_stage1_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv5_stage1_L2_0" + type: "Convolution" + bottom: "Mconv4_stage1_L2_concat" + top: "Mconv5_stage1_L2_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu5_stage1_L2_0" + type: "PReLU" + bottom: "Mconv5_stage1_L2_0" + top: "Mconv5_stage1_L2_0" +} +layer { + name: "Mconv5_stage1_L2_1" + type: "Convolution" + bottom: "Mconv5_stage1_L2_0" + top: "Mconv5_stage1_L2_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu5_stage1_L2_1" + type: "PReLU" + bottom: "Mconv5_stage1_L2_1" + top: "Mconv5_stage1_L2_1" +} +layer { + name: "Mconv5_stage1_L2_2" + type: "Convolution" + bottom: "Mconv5_stage1_L2_1" + top: "Mconv5_stage1_L2_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu5_stage1_L2_2" + type: "PReLU" + bottom: "Mconv5_stage1_L2_2" + top: "Mconv5_stage1_L2_2" +} +layer { + name: "Mconv5_stage1_L2_concat" + type: "Concat" + bottom: "Mconv5_stage1_L2_0" + bottom: "Mconv5_stage1_L2_1" + bottom: "Mconv5_stage1_L2_2" + top: "Mconv5_stage1_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv6_stage1_L2" + type: "Convolution" + bottom: "Mconv5_stage1_L2_concat" + top: "Mconv6_stage1_L2" + convolution_param { + num_output: 512 + pad: 0 + kernel_size: 1 + } +} +layer { + name: "Mprelu6_stage1_L2" + type: "PReLU" + bottom: "Mconv6_stage1_L2" + top: "Mconv6_stage1_L2" +} +layer { + name: "Mconv7_stage1_L2" + type: "Convolution" + bottom: "Mconv6_stage1_L2" + top: "Mconv7_stage1_L2" + convolution_param { + num_output: 52 + pad: 0 + kernel_size: 1 + } +} +layer { + name: "concat_stage2_L2" + type: "Concat" + bottom: "conv4_4_CPM" + bottom: "Mconv7_stage1_L2" + top: "concat_stage2_L2" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage2_L2_0" + type: "Convolution" + bottom: "concat_stage2_L2" + top: "Mconv1_stage2_L2_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu1_stage2_L2_0" + type: "PReLU" + bottom: "Mconv1_stage2_L2_0" + top: "Mconv1_stage2_L2_0" +} +layer { + name: "Mconv1_stage2_L2_1" + type: "Convolution" + bottom: "Mconv1_stage2_L2_0" + top: "Mconv1_stage2_L2_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu1_stage2_L2_1" + type: "PReLU" + bottom: "Mconv1_stage2_L2_1" + top: "Mconv1_stage2_L2_1" +} +layer { + name: "Mconv1_stage2_L2_2" + type: "Convolution" + bottom: "Mconv1_stage2_L2_1" + top: "Mconv1_stage2_L2_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu1_stage2_L2_2" + type: "PReLU" + bottom: "Mconv1_stage2_L2_2" + top: "Mconv1_stage2_L2_2" +} +layer { + name: "Mconv1_stage2_L2_concat" + type: "Concat" + bottom: "Mconv1_stage2_L2_0" + bottom: "Mconv1_stage2_L2_1" + bottom: "Mconv1_stage2_L2_2" + top: "Mconv1_stage2_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv2_stage2_L2_0" + type: "Convolution" + bottom: "Mconv1_stage2_L2_concat" + top: "Mconv2_stage2_L2_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu2_stage2_L2_0" + type: "PReLU" + bottom: "Mconv2_stage2_L2_0" + top: "Mconv2_stage2_L2_0" +} +layer { + name: "Mconv2_stage2_L2_1" + type: "Convolution" + bottom: "Mconv2_stage2_L2_0" + top: "Mconv2_stage2_L2_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu2_stage2_L2_1" + type: "PReLU" + bottom: "Mconv2_stage2_L2_1" + top: "Mconv2_stage2_L2_1" +} +layer { + name: "Mconv2_stage2_L2_2" + type: "Convolution" + bottom: "Mconv2_stage2_L2_1" + top: "Mconv2_stage2_L2_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu2_stage2_L2_2" + type: "PReLU" + bottom: "Mconv2_stage2_L2_2" + top: "Mconv2_stage2_L2_2" +} +layer { + name: "Mconv2_stage2_L2_concat" + type: "Concat" + bottom: "Mconv2_stage2_L2_0" + bottom: "Mconv2_stage2_L2_1" + bottom: "Mconv2_stage2_L2_2" + top: "Mconv2_stage2_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv3_stage2_L2_0" + type: "Convolution" + bottom: "Mconv2_stage2_L2_concat" + top: "Mconv3_stage2_L2_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu3_stage2_L2_0" + type: "PReLU" + bottom: "Mconv3_stage2_L2_0" + top: "Mconv3_stage2_L2_0" +} +layer { + name: "Mconv3_stage2_L2_1" + type: "Convolution" + bottom: "Mconv3_stage2_L2_0" + top: "Mconv3_stage2_L2_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu3_stage2_L2_1" + type: "PReLU" + bottom: "Mconv3_stage2_L2_1" + top: "Mconv3_stage2_L2_1" +} +layer { + name: "Mconv3_stage2_L2_2" + type: "Convolution" + bottom: "Mconv3_stage2_L2_1" + top: "Mconv3_stage2_L2_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu3_stage2_L2_2" + type: "PReLU" + bottom: "Mconv3_stage2_L2_2" + top: "Mconv3_stage2_L2_2" +} +layer { + name: "Mconv3_stage2_L2_concat" + type: "Concat" + bottom: "Mconv3_stage2_L2_0" + bottom: "Mconv3_stage2_L2_1" + bottom: "Mconv3_stage2_L2_2" + top: "Mconv3_stage2_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv4_stage2_L2_0" + type: "Convolution" + bottom: "Mconv3_stage2_L2_concat" + top: "Mconv4_stage2_L2_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu4_stage2_L2_0" + type: "PReLU" + bottom: "Mconv4_stage2_L2_0" + top: "Mconv4_stage2_L2_0" +} +layer { + name: "Mconv4_stage2_L2_1" + type: "Convolution" + bottom: "Mconv4_stage2_L2_0" + top: "Mconv4_stage2_L2_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu4_stage2_L2_1" + type: "PReLU" + bottom: "Mconv4_stage2_L2_1" + top: "Mconv4_stage2_L2_1" +} +layer { + name: "Mconv4_stage2_L2_2" + type: "Convolution" + bottom: "Mconv4_stage2_L2_1" + top: "Mconv4_stage2_L2_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu4_stage2_L2_2" + type: "PReLU" + bottom: "Mconv4_stage2_L2_2" + top: "Mconv4_stage2_L2_2" +} +layer { + name: "Mconv4_stage2_L2_concat" + type: "Concat" + bottom: "Mconv4_stage2_L2_0" + bottom: "Mconv4_stage2_L2_1" + bottom: "Mconv4_stage2_L2_2" + top: "Mconv4_stage2_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv5_stage2_L2_0" + type: "Convolution" + bottom: "Mconv4_stage2_L2_concat" + top: "Mconv5_stage2_L2_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu5_stage2_L2_0" + type: "PReLU" + bottom: "Mconv5_stage2_L2_0" + top: "Mconv5_stage2_L2_0" +} +layer { + name: "Mconv5_stage2_L2_1" + type: "Convolution" + bottom: "Mconv5_stage2_L2_0" + top: "Mconv5_stage2_L2_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu5_stage2_L2_1" + type: "PReLU" + bottom: "Mconv5_stage2_L2_1" + top: "Mconv5_stage2_L2_1" +} +layer { + name: "Mconv5_stage2_L2_2" + type: "Convolution" + bottom: "Mconv5_stage2_L2_1" + top: "Mconv5_stage2_L2_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu5_stage2_L2_2" + type: "PReLU" + bottom: "Mconv5_stage2_L2_2" + top: "Mconv5_stage2_L2_2" +} +layer { + name: "Mconv5_stage2_L2_concat" + type: "Concat" + bottom: "Mconv5_stage2_L2_0" + bottom: "Mconv5_stage2_L2_1" + bottom: "Mconv5_stage2_L2_2" + top: "Mconv5_stage2_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv6_stage2_L2" + type: "Convolution" + bottom: "Mconv5_stage2_L2_concat" + top: "Mconv6_stage2_L2" + convolution_param { + num_output: 512 + pad: 0 + kernel_size: 1 + } +} +layer { + name: "Mprelu6_stage2_L2" + type: "PReLU" + bottom: "Mconv6_stage2_L2" + top: "Mconv6_stage2_L2" +} +layer { + name: "Mconv7_stage2_L2" + type: "Convolution" + bottom: "Mconv6_stage2_L2" + top: "Mconv7_stage2_L2" + convolution_param { + num_output: 52 + pad: 0 + kernel_size: 1 + } +} +layer { + name: "concat_stage3_L2" + type: "Concat" + bottom: "conv4_4_CPM" + bottom: "Mconv7_stage2_L2" + top: "concat_stage3_L2" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage3_L2_0" + type: "Convolution" + bottom: "concat_stage3_L2" + top: "Mconv1_stage3_L2_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu1_stage3_L2_0" + type: "PReLU" + bottom: "Mconv1_stage3_L2_0" + top: "Mconv1_stage3_L2_0" +} +layer { + name: "Mconv1_stage3_L2_1" + type: "Convolution" + bottom: "Mconv1_stage3_L2_0" + top: "Mconv1_stage3_L2_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu1_stage3_L2_1" + type: "PReLU" + bottom: "Mconv1_stage3_L2_1" + top: "Mconv1_stage3_L2_1" +} +layer { + name: "Mconv1_stage3_L2_2" + type: "Convolution" + bottom: "Mconv1_stage3_L2_1" + top: "Mconv1_stage3_L2_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu1_stage3_L2_2" + type: "PReLU" + bottom: "Mconv1_stage3_L2_2" + top: "Mconv1_stage3_L2_2" +} +layer { + name: "Mconv1_stage3_L2_concat" + type: "Concat" + bottom: "Mconv1_stage3_L2_0" + bottom: "Mconv1_stage3_L2_1" + bottom: "Mconv1_stage3_L2_2" + top: "Mconv1_stage3_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv2_stage3_L2_0" + type: "Convolution" + bottom: "Mconv1_stage3_L2_concat" + top: "Mconv2_stage3_L2_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu2_stage3_L2_0" + type: "PReLU" + bottom: "Mconv2_stage3_L2_0" + top: "Mconv2_stage3_L2_0" +} +layer { + name: "Mconv2_stage3_L2_1" + type: "Convolution" + bottom: "Mconv2_stage3_L2_0" + top: "Mconv2_stage3_L2_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu2_stage3_L2_1" + type: "PReLU" + bottom: "Mconv2_stage3_L2_1" + top: "Mconv2_stage3_L2_1" +} +layer { + name: "Mconv2_stage3_L2_2" + type: "Convolution" + bottom: "Mconv2_stage3_L2_1" + top: "Mconv2_stage3_L2_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu2_stage3_L2_2" + type: "PReLU" + bottom: "Mconv2_stage3_L2_2" + top: "Mconv2_stage3_L2_2" +} +layer { + name: "Mconv2_stage3_L2_concat" + type: "Concat" + bottom: "Mconv2_stage3_L2_0" + bottom: "Mconv2_stage3_L2_1" + bottom: "Mconv2_stage3_L2_2" + top: "Mconv2_stage3_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv3_stage3_L2_0" + type: "Convolution" + bottom: "Mconv2_stage3_L2_concat" + top: "Mconv3_stage3_L2_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu3_stage3_L2_0" + type: "PReLU" + bottom: "Mconv3_stage3_L2_0" + top: "Mconv3_stage3_L2_0" +} +layer { + name: "Mconv3_stage3_L2_1" + type: "Convolution" + bottom: "Mconv3_stage3_L2_0" + top: "Mconv3_stage3_L2_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu3_stage3_L2_1" + type: "PReLU" + bottom: "Mconv3_stage3_L2_1" + top: "Mconv3_stage3_L2_1" +} +layer { + name: "Mconv3_stage3_L2_2" + type: "Convolution" + bottom: "Mconv3_stage3_L2_1" + top: "Mconv3_stage3_L2_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu3_stage3_L2_2" + type: "PReLU" + bottom: "Mconv3_stage3_L2_2" + top: "Mconv3_stage3_L2_2" +} +layer { + name: "Mconv3_stage3_L2_concat" + type: "Concat" + bottom: "Mconv3_stage3_L2_0" + bottom: "Mconv3_stage3_L2_1" + bottom: "Mconv3_stage3_L2_2" + top: "Mconv3_stage3_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv4_stage3_L2_0" + type: "Convolution" + bottom: "Mconv3_stage3_L2_concat" + top: "Mconv4_stage3_L2_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu4_stage3_L2_0" + type: "PReLU" + bottom: "Mconv4_stage3_L2_0" + top: "Mconv4_stage3_L2_0" +} +layer { + name: "Mconv4_stage3_L2_1" + type: "Convolution" + bottom: "Mconv4_stage3_L2_0" + top: "Mconv4_stage3_L2_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu4_stage3_L2_1" + type: "PReLU" + bottom: "Mconv4_stage3_L2_1" + top: "Mconv4_stage3_L2_1" +} +layer { + name: "Mconv4_stage3_L2_2" + type: "Convolution" + bottom: "Mconv4_stage3_L2_1" + top: "Mconv4_stage3_L2_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu4_stage3_L2_2" + type: "PReLU" + bottom: "Mconv4_stage3_L2_2" + top: "Mconv4_stage3_L2_2" +} +layer { + name: "Mconv4_stage3_L2_concat" + type: "Concat" + bottom: "Mconv4_stage3_L2_0" + bottom: "Mconv4_stage3_L2_1" + bottom: "Mconv4_stage3_L2_2" + top: "Mconv4_stage3_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv5_stage3_L2_0" + type: "Convolution" + bottom: "Mconv4_stage3_L2_concat" + top: "Mconv5_stage3_L2_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu5_stage3_L2_0" + type: "PReLU" + bottom: "Mconv5_stage3_L2_0" + top: "Mconv5_stage3_L2_0" +} +layer { + name: "Mconv5_stage3_L2_1" + type: "Convolution" + bottom: "Mconv5_stage3_L2_0" + top: "Mconv5_stage3_L2_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu5_stage3_L2_1" + type: "PReLU" + bottom: "Mconv5_stage3_L2_1" + top: "Mconv5_stage3_L2_1" +} +layer { + name: "Mconv5_stage3_L2_2" + type: "Convolution" + bottom: "Mconv5_stage3_L2_1" + top: "Mconv5_stage3_L2_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu5_stage3_L2_2" + type: "PReLU" + bottom: "Mconv5_stage3_L2_2" + top: "Mconv5_stage3_L2_2" +} +layer { + name: "Mconv5_stage3_L2_concat" + type: "Concat" + bottom: "Mconv5_stage3_L2_0" + bottom: "Mconv5_stage3_L2_1" + bottom: "Mconv5_stage3_L2_2" + top: "Mconv5_stage3_L2_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv6_stage3_L2" + type: "Convolution" + bottom: "Mconv5_stage3_L2_concat" + top: "Mconv6_stage3_L2" + convolution_param { + num_output: 512 + pad: 0 + kernel_size: 1 + } +} +layer { + name: "Mprelu6_stage3_L2" + type: "PReLU" + bottom: "Mconv6_stage3_L2" + top: "Mconv6_stage3_L2" +} +layer { + name: "Mconv7_stage3_L2" + type: "Convolution" + bottom: "Mconv6_stage3_L2" + top: "Mconv7_stage3_L2" + convolution_param { + num_output: 52 + pad: 0 + kernel_size: 1 + } +} +layer { + name: "concat_stage0_L1" + type: "Concat" + bottom: "conv4_4_CPM" + bottom: "Mconv7_stage3_L2" + top: "concat_stage0_L1" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage0_L1_0" + type: "Convolution" + bottom: "concat_stage0_L1" + top: "Mconv1_stage0_L1_0" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu1_stage0_L1_0" + type: "PReLU" + bottom: "Mconv1_stage0_L1_0" + top: "Mconv1_stage0_L1_0" +} +layer { + name: "Mconv1_stage0_L1_1" + type: "Convolution" + bottom: "Mconv1_stage0_L1_0" + top: "Mconv1_stage0_L1_1" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu1_stage0_L1_1" + type: "PReLU" + bottom: "Mconv1_stage0_L1_1" + top: "Mconv1_stage0_L1_1" +} +layer { + name: "Mconv1_stage0_L1_2" + type: "Convolution" + bottom: "Mconv1_stage0_L1_1" + top: "Mconv1_stage0_L1_2" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu1_stage0_L1_2" + type: "PReLU" + bottom: "Mconv1_stage0_L1_2" + top: "Mconv1_stage0_L1_2" +} +layer { + name: "Mconv1_stage0_L1_concat" + type: "Concat" + bottom: "Mconv1_stage0_L1_0" + bottom: "Mconv1_stage0_L1_1" + bottom: "Mconv1_stage0_L1_2" + top: "Mconv1_stage0_L1_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv2_stage0_L1_0" + type: "Convolution" + bottom: "Mconv1_stage0_L1_concat" + top: "Mconv2_stage0_L1_0" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu2_stage0_L1_0" + type: "PReLU" + bottom: "Mconv2_stage0_L1_0" + top: "Mconv2_stage0_L1_0" +} +layer { + name: "Mconv2_stage0_L1_1" + type: "Convolution" + bottom: "Mconv2_stage0_L1_0" + top: "Mconv2_stage0_L1_1" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu2_stage0_L1_1" + type: "PReLU" + bottom: "Mconv2_stage0_L1_1" + top: "Mconv2_stage0_L1_1" +} +layer { + name: "Mconv2_stage0_L1_2" + type: "Convolution" + bottom: "Mconv2_stage0_L1_1" + top: "Mconv2_stage0_L1_2" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu2_stage0_L1_2" + type: "PReLU" + bottom: "Mconv2_stage0_L1_2" + top: "Mconv2_stage0_L1_2" +} +layer { + name: "Mconv2_stage0_L1_concat" + type: "Concat" + bottom: "Mconv2_stage0_L1_0" + bottom: "Mconv2_stage0_L1_1" + bottom: "Mconv2_stage0_L1_2" + top: "Mconv2_stage0_L1_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv3_stage0_L1_0" + type: "Convolution" + bottom: "Mconv2_stage0_L1_concat" + top: "Mconv3_stage0_L1_0" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu3_stage0_L1_0" + type: "PReLU" + bottom: "Mconv3_stage0_L1_0" + top: "Mconv3_stage0_L1_0" +} +layer { + name: "Mconv3_stage0_L1_1" + type: "Convolution" + bottom: "Mconv3_stage0_L1_0" + top: "Mconv3_stage0_L1_1" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu3_stage0_L1_1" + type: "PReLU" + bottom: "Mconv3_stage0_L1_1" + top: "Mconv3_stage0_L1_1" +} +layer { + name: "Mconv3_stage0_L1_2" + type: "Convolution" + bottom: "Mconv3_stage0_L1_1" + top: "Mconv3_stage0_L1_2" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu3_stage0_L1_2" + type: "PReLU" + bottom: "Mconv3_stage0_L1_2" + top: "Mconv3_stage0_L1_2" +} +layer { + name: "Mconv3_stage0_L1_concat" + type: "Concat" + bottom: "Mconv3_stage0_L1_0" + bottom: "Mconv3_stage0_L1_1" + bottom: "Mconv3_stage0_L1_2" + top: "Mconv3_stage0_L1_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv4_stage0_L1_0" + type: "Convolution" + bottom: "Mconv3_stage0_L1_concat" + top: "Mconv4_stage0_L1_0" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu4_stage0_L1_0" + type: "PReLU" + bottom: "Mconv4_stage0_L1_0" + top: "Mconv4_stage0_L1_0" +} +layer { + name: "Mconv4_stage0_L1_1" + type: "Convolution" + bottom: "Mconv4_stage0_L1_0" + top: "Mconv4_stage0_L1_1" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu4_stage0_L1_1" + type: "PReLU" + bottom: "Mconv4_stage0_L1_1" + top: "Mconv4_stage0_L1_1" +} +layer { + name: "Mconv4_stage0_L1_2" + type: "Convolution" + bottom: "Mconv4_stage0_L1_1" + top: "Mconv4_stage0_L1_2" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu4_stage0_L1_2" + type: "PReLU" + bottom: "Mconv4_stage0_L1_2" + top: "Mconv4_stage0_L1_2" +} +layer { + name: "Mconv4_stage0_L1_concat" + type: "Concat" + bottom: "Mconv4_stage0_L1_0" + bottom: "Mconv4_stage0_L1_1" + bottom: "Mconv4_stage0_L1_2" + top: "Mconv4_stage0_L1_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv5_stage0_L1_0" + type: "Convolution" + bottom: "Mconv4_stage0_L1_concat" + top: "Mconv5_stage0_L1_0" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu5_stage0_L1_0" + type: "PReLU" + bottom: "Mconv5_stage0_L1_0" + top: "Mconv5_stage0_L1_0" +} +layer { + name: "Mconv5_stage0_L1_1" + type: "Convolution" + bottom: "Mconv5_stage0_L1_0" + top: "Mconv5_stage0_L1_1" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu5_stage0_L1_1" + type: "PReLU" + bottom: "Mconv5_stage0_L1_1" + top: "Mconv5_stage0_L1_1" +} +layer { + name: "Mconv5_stage0_L1_2" + type: "Convolution" + bottom: "Mconv5_stage0_L1_1" + top: "Mconv5_stage0_L1_2" + convolution_param { + num_output: 96 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu5_stage0_L1_2" + type: "PReLU" + bottom: "Mconv5_stage0_L1_2" + top: "Mconv5_stage0_L1_2" +} +layer { + name: "Mconv5_stage0_L1_concat" + type: "Concat" + bottom: "Mconv5_stage0_L1_0" + bottom: "Mconv5_stage0_L1_1" + bottom: "Mconv5_stage0_L1_2" + top: "Mconv5_stage0_L1_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv6_stage0_L1" + type: "Convolution" + bottom: "Mconv5_stage0_L1_concat" + top: "Mconv6_stage0_L1" + convolution_param { + num_output: 256 + pad: 0 + kernel_size: 1 + } +} +layer { + name: "Mprelu6_stage0_L1" + type: "PReLU" + bottom: "Mconv6_stage0_L1" + top: "Mconv6_stage0_L1" +} +layer { + name: "Mconv7_stage0_L1" + type: "Convolution" + bottom: "Mconv6_stage0_L1" + top: "Mconv7_stage0_L1" + convolution_param { + num_output: 26 + pad: 0 + kernel_size: 1 + } +} +layer { + name: "concat_stage1_L1" + type: "Concat" + bottom: "conv4_4_CPM" + bottom: "Mconv7_stage0_L1" + bottom: "Mconv7_stage3_L2" + top: "concat_stage1_L1" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage1_L1_0" + type: "Convolution" + bottom: "concat_stage1_L1" + top: "Mconv1_stage1_L1_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu1_stage1_L1_0" + type: "PReLU" + bottom: "Mconv1_stage1_L1_0" + top: "Mconv1_stage1_L1_0" +} +layer { + name: "Mconv1_stage1_L1_1" + type: "Convolution" + bottom: "Mconv1_stage1_L1_0" + top: "Mconv1_stage1_L1_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu1_stage1_L1_1" + type: "PReLU" + bottom: "Mconv1_stage1_L1_1" + top: "Mconv1_stage1_L1_1" +} +layer { + name: "Mconv1_stage1_L1_2" + type: "Convolution" + bottom: "Mconv1_stage1_L1_1" + top: "Mconv1_stage1_L1_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu1_stage1_L1_2" + type: "PReLU" + bottom: "Mconv1_stage1_L1_2" + top: "Mconv1_stage1_L1_2" +} +layer { + name: "Mconv1_stage1_L1_concat" + type: "Concat" + bottom: "Mconv1_stage1_L1_0" + bottom: "Mconv1_stage1_L1_1" + bottom: "Mconv1_stage1_L1_2" + top: "Mconv1_stage1_L1_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv2_stage1_L1_0" + type: "Convolution" + bottom: "Mconv1_stage1_L1_concat" + top: "Mconv2_stage1_L1_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu2_stage1_L1_0" + type: "PReLU" + bottom: "Mconv2_stage1_L1_0" + top: "Mconv2_stage1_L1_0" +} +layer { + name: "Mconv2_stage1_L1_1" + type: "Convolution" + bottom: "Mconv2_stage1_L1_0" + top: "Mconv2_stage1_L1_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu2_stage1_L1_1" + type: "PReLU" + bottom: "Mconv2_stage1_L1_1" + top: "Mconv2_stage1_L1_1" +} +layer { + name: "Mconv2_stage1_L1_2" + type: "Convolution" + bottom: "Mconv2_stage1_L1_1" + top: "Mconv2_stage1_L1_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu2_stage1_L1_2" + type: "PReLU" + bottom: "Mconv2_stage1_L1_2" + top: "Mconv2_stage1_L1_2" +} +layer { + name: "Mconv2_stage1_L1_concat" + type: "Concat" + bottom: "Mconv2_stage1_L1_0" + bottom: "Mconv2_stage1_L1_1" + bottom: "Mconv2_stage1_L1_2" + top: "Mconv2_stage1_L1_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv3_stage1_L1_0" + type: "Convolution" + bottom: "Mconv2_stage1_L1_concat" + top: "Mconv3_stage1_L1_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu3_stage1_L1_0" + type: "PReLU" + bottom: "Mconv3_stage1_L1_0" + top: "Mconv3_stage1_L1_0" +} +layer { + name: "Mconv3_stage1_L1_1" + type: "Convolution" + bottom: "Mconv3_stage1_L1_0" + top: "Mconv3_stage1_L1_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu3_stage1_L1_1" + type: "PReLU" + bottom: "Mconv3_stage1_L1_1" + top: "Mconv3_stage1_L1_1" +} +layer { + name: "Mconv3_stage1_L1_2" + type: "Convolution" + bottom: "Mconv3_stage1_L1_1" + top: "Mconv3_stage1_L1_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu3_stage1_L1_2" + type: "PReLU" + bottom: "Mconv3_stage1_L1_2" + top: "Mconv3_stage1_L1_2" +} +layer { + name: "Mconv3_stage1_L1_concat" + type: "Concat" + bottom: "Mconv3_stage1_L1_0" + bottom: "Mconv3_stage1_L1_1" + bottom: "Mconv3_stage1_L1_2" + top: "Mconv3_stage1_L1_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv4_stage1_L1_0" + type: "Convolution" + bottom: "Mconv3_stage1_L1_concat" + top: "Mconv4_stage1_L1_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu4_stage1_L1_0" + type: "PReLU" + bottom: "Mconv4_stage1_L1_0" + top: "Mconv4_stage1_L1_0" +} +layer { + name: "Mconv4_stage1_L1_1" + type: "Convolution" + bottom: "Mconv4_stage1_L1_0" + top: "Mconv4_stage1_L1_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu4_stage1_L1_1" + type: "PReLU" + bottom: "Mconv4_stage1_L1_1" + top: "Mconv4_stage1_L1_1" +} +layer { + name: "Mconv4_stage1_L1_2" + type: "Convolution" + bottom: "Mconv4_stage1_L1_1" + top: "Mconv4_stage1_L1_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu4_stage1_L1_2" + type: "PReLU" + bottom: "Mconv4_stage1_L1_2" + top: "Mconv4_stage1_L1_2" +} +layer { + name: "Mconv4_stage1_L1_concat" + type: "Concat" + bottom: "Mconv4_stage1_L1_0" + bottom: "Mconv4_stage1_L1_1" + bottom: "Mconv4_stage1_L1_2" + top: "Mconv4_stage1_L1_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv5_stage1_L1_0" + type: "Convolution" + bottom: "Mconv4_stage1_L1_concat" + top: "Mconv5_stage1_L1_0" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu5_stage1_L1_0" + type: "PReLU" + bottom: "Mconv5_stage1_L1_0" + top: "Mconv5_stage1_L1_0" +} +layer { + name: "Mconv5_stage1_L1_1" + type: "Convolution" + bottom: "Mconv5_stage1_L1_0" + top: "Mconv5_stage1_L1_1" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu5_stage1_L1_1" + type: "PReLU" + bottom: "Mconv5_stage1_L1_1" + top: "Mconv5_stage1_L1_1" +} +layer { + name: "Mconv5_stage1_L1_2" + type: "Convolution" + bottom: "Mconv5_stage1_L1_1" + top: "Mconv5_stage1_L1_2" + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + } +} +layer { + name: "Mprelu5_stage1_L1_2" + type: "PReLU" + bottom: "Mconv5_stage1_L1_2" + top: "Mconv5_stage1_L1_2" +} +layer { + name: "Mconv5_stage1_L1_concat" + type: "Concat" + bottom: "Mconv5_stage1_L1_0" + bottom: "Mconv5_stage1_L1_1" + bottom: "Mconv5_stage1_L1_2" + top: "Mconv5_stage1_L1_concat" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv6_stage1_L1" + type: "Convolution" + bottom: "Mconv5_stage1_L1_concat" + top: "Mconv6_stage1_L1" + convolution_param { + num_output: 512 + pad: 0 + kernel_size: 1 + } +} +layer { + name: "Mprelu6_stage1_L1" + type: "PReLU" + bottom: "Mconv6_stage1_L1" + top: "Mconv6_stage1_L1" +} +layer { + name: "Mconv7_stage1_L1" + type: "Convolution" + bottom: "Mconv6_stage1_L1" + top: "Mconv7_stage1_L1" + convolution_param { + num_output: 26 + pad: 0 + kernel_size: 1 + } +} +layer { + name: "net_output" + type: "Concat" + bottom: "Mconv7_stage1_L1" + bottom: "Mconv7_stage3_L2" + top: "net_output" + concat_param { + axis: 1 + } +} diff --git a/openpose/models/pose/coco/pose_deploy_linevec.prototxt b/openpose/models/pose/coco/pose_deploy_linevec.prototxt new file mode 100644 index 0000000000000000000000000000000000000000..fbe0c824588d61f079de03b06ab428e817b99819 --- /dev/null +++ b/openpose/models/pose/coco/pose_deploy_linevec.prototxt @@ -0,0 +1,2976 @@ +input: "image" +input_dim: 1 +input_dim: 3 +input_dim: 1 # This value will be defined at runtime +input_dim: 1 # This value will be defined at runtime +layer { + name: "conv1_1" + type: "Convolution" + bottom: "image" + top: "conv1_1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 64 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu1_1" + type: "ReLU" + bottom: "conv1_1" + top: "conv1_1" +} +layer { + name: "conv1_2" + type: "Convolution" + bottom: "conv1_1" + top: "conv1_2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 64 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu1_2" + type: "ReLU" + bottom: "conv1_2" + top: "conv1_2" +} +layer { + name: "pool1_stage1" + type: "Pooling" + bottom: "conv1_2" + top: "pool1_stage1" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layer { + name: "conv2_1" + type: "Convolution" + bottom: "pool1_stage1" + top: "conv2_1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu2_1" + type: "ReLU" + bottom: "conv2_1" + top: "conv2_1" +} +layer { + name: "conv2_2" + type: "Convolution" + bottom: "conv2_1" + top: "conv2_2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu2_2" + type: "ReLU" + bottom: "conv2_2" + top: "conv2_2" +} +layer { + name: "pool2_stage1" + type: "Pooling" + bottom: "conv2_2" + top: "pool2_stage1" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layer { + name: "conv3_1" + type: "Convolution" + bottom: "pool2_stage1" + top: "conv3_1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu3_1" + type: "ReLU" + bottom: "conv3_1" + top: "conv3_1" +} +layer { + name: "conv3_2" + type: "Convolution" + bottom: "conv3_1" + top: "conv3_2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu3_2" + type: "ReLU" + bottom: "conv3_2" + top: "conv3_2" +} +layer { + name: "conv3_3" + type: "Convolution" + bottom: "conv3_2" + top: "conv3_3" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu3_3" + type: "ReLU" + bottom: "conv3_3" + top: "conv3_3" +} +layer { + name: "conv3_4" + type: "Convolution" + bottom: "conv3_3" + top: "conv3_4" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu3_4" + type: "ReLU" + bottom: "conv3_4" + top: "conv3_4" +} +layer { + name: "pool3_stage1" + type: "Pooling" + bottom: "conv3_4" + top: "pool3_stage1" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layer { + name: "conv4_1" + type: "Convolution" + bottom: "pool3_stage1" + top: "conv4_1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu4_1" + type: "ReLU" + bottom: "conv4_1" + top: "conv4_1" +} +layer { + name: "conv4_2" + type: "Convolution" + bottom: "conv4_1" + top: "conv4_2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu4_2" + type: "ReLU" + bottom: "conv4_2" + top: "conv4_2" +} +layer { + name: "conv4_3_CPM" + type: "Convolution" + bottom: "conv4_2" + top: "conv4_3_CPM" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu4_3_CPM" + type: "ReLU" + bottom: "conv4_3_CPM" + top: "conv4_3_CPM" +} +layer { + name: "conv4_4_CPM" + type: "Convolution" + bottom: "conv4_3_CPM" + top: "conv4_4_CPM" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu4_4_CPM" + type: "ReLU" + bottom: "conv4_4_CPM" + top: "conv4_4_CPM" +} +layer { + name: "conv5_1_CPM_L1" + type: "Convolution" + bottom: "conv4_4_CPM" + top: "conv5_1_CPM_L1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_1_CPM_L1" + type: "ReLU" + bottom: "conv5_1_CPM_L1" + top: "conv5_1_CPM_L1" +} +layer { + name: "conv5_1_CPM_L2" + type: "Convolution" + bottom: "conv4_4_CPM" + top: "conv5_1_CPM_L2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_1_CPM_L2" + type: "ReLU" + bottom: "conv5_1_CPM_L2" + top: "conv5_1_CPM_L2" +} +layer { + name: "conv5_2_CPM_L1" + type: "Convolution" + bottom: "conv5_1_CPM_L1" + top: "conv5_2_CPM_L1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_2_CPM_L1" + type: "ReLU" + bottom: "conv5_2_CPM_L1" + top: "conv5_2_CPM_L1" +} +layer { + name: "conv5_2_CPM_L2" + type: "Convolution" + bottom: "conv5_1_CPM_L2" + top: "conv5_2_CPM_L2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_2_CPM_L2" + type: "ReLU" + bottom: "conv5_2_CPM_L2" + top: "conv5_2_CPM_L2" +} +layer { + name: "conv5_3_CPM_L1" + type: "Convolution" + bottom: "conv5_2_CPM_L1" + top: "conv5_3_CPM_L1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_3_CPM_L1" + type: "ReLU" + bottom: "conv5_3_CPM_L1" + top: "conv5_3_CPM_L1" +} +layer { + name: "conv5_3_CPM_L2" + type: "Convolution" + bottom: "conv5_2_CPM_L2" + top: "conv5_3_CPM_L2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_3_CPM_L2" + type: "ReLU" + bottom: "conv5_3_CPM_L2" + top: "conv5_3_CPM_L2" +} +layer { + name: "conv5_4_CPM_L1" + type: "Convolution" + bottom: "conv5_3_CPM_L1" + top: "conv5_4_CPM_L1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_4_CPM_L1" + type: "ReLU" + bottom: "conv5_4_CPM_L1" + top: "conv5_4_CPM_L1" +} +layer { + name: "conv5_4_CPM_L2" + type: "Convolution" + bottom: "conv5_3_CPM_L2" + top: "conv5_4_CPM_L2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_4_CPM_L2" + type: "ReLU" + bottom: "conv5_4_CPM_L2" + top: "conv5_4_CPM_L2" +} +layer { + name: "conv5_5_CPM_L1" + type: "Convolution" + bottom: "conv5_4_CPM_L1" + top: "conv5_5_CPM_L1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 38 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "conv5_5_CPM_L2" + type: "Convolution" + bottom: "conv5_4_CPM_L2" + top: "conv5_5_CPM_L2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 19 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "concat_stage2" + type: "Concat" + bottom: "conv5_5_CPM_L1" + bottom: "conv5_5_CPM_L2" + bottom: "conv4_4_CPM" + top: "concat_stage2" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage2_L1" + type: "Convolution" + bottom: "concat_stage2" + top: "Mconv1_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage2_L1" + type: "ReLU" + bottom: "Mconv1_stage2_L1" + top: "Mconv1_stage2_L1" +} +layer { + name: "Mconv1_stage2_L2" + type: "Convolution" + bottom: "concat_stage2" + top: "Mconv1_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage2_L2" + type: "ReLU" + bottom: "Mconv1_stage2_L2" + top: "Mconv1_stage2_L2" +} +layer { + name: "Mconv2_stage2_L1" + type: "Convolution" + bottom: "Mconv1_stage2_L1" + top: "Mconv2_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage2_L1" + type: "ReLU" + bottom: "Mconv2_stage2_L1" + top: "Mconv2_stage2_L1" +} +layer { + name: "Mconv2_stage2_L2" + type: "Convolution" + bottom: "Mconv1_stage2_L2" + top: "Mconv2_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage2_L2" + type: "ReLU" + bottom: "Mconv2_stage2_L2" + top: "Mconv2_stage2_L2" +} +layer { + name: "Mconv3_stage2_L1" + type: "Convolution" + bottom: "Mconv2_stage2_L1" + top: "Mconv3_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage2_L1" + type: "ReLU" + bottom: "Mconv3_stage2_L1" + top: "Mconv3_stage2_L1" +} +layer { + name: "Mconv3_stage2_L2" + type: "Convolution" + bottom: "Mconv2_stage2_L2" + top: "Mconv3_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage2_L2" + type: "ReLU" + bottom: "Mconv3_stage2_L2" + top: "Mconv3_stage2_L2" +} +layer { + name: "Mconv4_stage2_L1" + type: "Convolution" + bottom: "Mconv3_stage2_L1" + top: "Mconv4_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage2_L1" + type: "ReLU" + bottom: "Mconv4_stage2_L1" + top: "Mconv4_stage2_L1" +} +layer { + name: "Mconv4_stage2_L2" + type: "Convolution" + bottom: "Mconv3_stage2_L2" + top: "Mconv4_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage2_L2" + type: "ReLU" + bottom: "Mconv4_stage2_L2" + top: "Mconv4_stage2_L2" +} +layer { + name: "Mconv5_stage2_L1" + type: "Convolution" + bottom: "Mconv4_stage2_L1" + top: "Mconv5_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage2_L1" + type: "ReLU" + bottom: "Mconv5_stage2_L1" + top: "Mconv5_stage2_L1" +} +layer { + name: "Mconv5_stage2_L2" + type: "Convolution" + bottom: "Mconv4_stage2_L2" + top: "Mconv5_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage2_L2" + type: "ReLU" + bottom: "Mconv5_stage2_L2" + top: "Mconv5_stage2_L2" +} +layer { + name: "Mconv6_stage2_L1" + type: "Convolution" + bottom: "Mconv5_stage2_L1" + top: "Mconv6_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage2_L1" + type: "ReLU" + bottom: "Mconv6_stage2_L1" + top: "Mconv6_stage2_L1" +} +layer { + name: "Mconv6_stage2_L2" + type: "Convolution" + bottom: "Mconv5_stage2_L2" + top: "Mconv6_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage2_L2" + type: "ReLU" + bottom: "Mconv6_stage2_L2" + top: "Mconv6_stage2_L2" +} +layer { + name: "Mconv7_stage2_L1" + type: "Convolution" + bottom: "Mconv6_stage2_L1" + top: "Mconv7_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 38 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv7_stage2_L2" + type: "Convolution" + bottom: "Mconv6_stage2_L2" + top: "Mconv7_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 19 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "concat_stage3" + type: "Concat" + bottom: "Mconv7_stage2_L1" + bottom: "Mconv7_stage2_L2" + bottom: "conv4_4_CPM" + top: "concat_stage3" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage3_L1" + type: "Convolution" + bottom: "concat_stage3" + top: "Mconv1_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage3_L1" + type: "ReLU" + bottom: "Mconv1_stage3_L1" + top: "Mconv1_stage3_L1" +} +layer { + name: "Mconv1_stage3_L2" + type: "Convolution" + bottom: "concat_stage3" + top: "Mconv1_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage3_L2" + type: "ReLU" + bottom: "Mconv1_stage3_L2" + top: "Mconv1_stage3_L2" +} +layer { + name: "Mconv2_stage3_L1" + type: "Convolution" + bottom: "Mconv1_stage3_L1" + top: "Mconv2_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage3_L1" + type: "ReLU" + bottom: "Mconv2_stage3_L1" + top: "Mconv2_stage3_L1" +} +layer { + name: "Mconv2_stage3_L2" + type: "Convolution" + bottom: "Mconv1_stage3_L2" + top: "Mconv2_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage3_L2" + type: "ReLU" + bottom: "Mconv2_stage3_L2" + top: "Mconv2_stage3_L2" +} +layer { + name: "Mconv3_stage3_L1" + type: "Convolution" + bottom: "Mconv2_stage3_L1" + top: "Mconv3_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage3_L1" + type: "ReLU" + bottom: "Mconv3_stage3_L1" + top: "Mconv3_stage3_L1" +} +layer { + name: "Mconv3_stage3_L2" + type: "Convolution" + bottom: "Mconv2_stage3_L2" + top: "Mconv3_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage3_L2" + type: "ReLU" + bottom: "Mconv3_stage3_L2" + top: "Mconv3_stage3_L2" +} +layer { + name: "Mconv4_stage3_L1" + type: "Convolution" + bottom: "Mconv3_stage3_L1" + top: "Mconv4_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage3_L1" + type: "ReLU" + bottom: "Mconv4_stage3_L1" + top: "Mconv4_stage3_L1" +} +layer { + name: "Mconv4_stage3_L2" + type: "Convolution" + bottom: "Mconv3_stage3_L2" + top: "Mconv4_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage3_L2" + type: "ReLU" + bottom: "Mconv4_stage3_L2" + top: "Mconv4_stage3_L2" +} +layer { + name: "Mconv5_stage3_L1" + type: "Convolution" + bottom: "Mconv4_stage3_L1" + top: "Mconv5_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage3_L1" + type: "ReLU" + bottom: "Mconv5_stage3_L1" + top: "Mconv5_stage3_L1" +} +layer { + name: "Mconv5_stage3_L2" + type: "Convolution" + bottom: "Mconv4_stage3_L2" + top: "Mconv5_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage3_L2" + type: "ReLU" + bottom: "Mconv5_stage3_L2" + top: "Mconv5_stage3_L2" +} +layer { + name: "Mconv6_stage3_L1" + type: "Convolution" + bottom: "Mconv5_stage3_L1" + top: "Mconv6_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage3_L1" + type: "ReLU" + bottom: "Mconv6_stage3_L1" + top: "Mconv6_stage3_L1" +} +layer { + name: "Mconv6_stage3_L2" + type: "Convolution" + bottom: "Mconv5_stage3_L2" + top: "Mconv6_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage3_L2" + type: "ReLU" + bottom: "Mconv6_stage3_L2" + top: "Mconv6_stage3_L2" +} +layer { + name: "Mconv7_stage3_L1" + type: "Convolution" + bottom: "Mconv6_stage3_L1" + top: "Mconv7_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 38 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv7_stage3_L2" + type: "Convolution" + bottom: "Mconv6_stage3_L2" + top: "Mconv7_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 19 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "concat_stage4" + type: "Concat" + bottom: "Mconv7_stage3_L1" + bottom: "Mconv7_stage3_L2" + bottom: "conv4_4_CPM" + top: "concat_stage4" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage4_L1" + type: "Convolution" + bottom: "concat_stage4" + top: "Mconv1_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage4_L1" + type: "ReLU" + bottom: "Mconv1_stage4_L1" + top: "Mconv1_stage4_L1" +} +layer { + name: "Mconv1_stage4_L2" + type: "Convolution" + bottom: "concat_stage4" + top: "Mconv1_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage4_L2" + type: "ReLU" + bottom: "Mconv1_stage4_L2" + top: "Mconv1_stage4_L2" +} +layer { + name: "Mconv2_stage4_L1" + type: "Convolution" + bottom: "Mconv1_stage4_L1" + top: "Mconv2_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage4_L1" + type: "ReLU" + bottom: "Mconv2_stage4_L1" + top: "Mconv2_stage4_L1" +} +layer { + name: "Mconv2_stage4_L2" + type: "Convolution" + bottom: "Mconv1_stage4_L2" + top: "Mconv2_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage4_L2" + type: "ReLU" + bottom: "Mconv2_stage4_L2" + top: "Mconv2_stage4_L2" +} +layer { + name: "Mconv3_stage4_L1" + type: "Convolution" + bottom: "Mconv2_stage4_L1" + top: "Mconv3_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage4_L1" + type: "ReLU" + bottom: "Mconv3_stage4_L1" + top: "Mconv3_stage4_L1" +} +layer { + name: "Mconv3_stage4_L2" + type: "Convolution" + bottom: "Mconv2_stage4_L2" + top: "Mconv3_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage4_L2" + type: "ReLU" + bottom: "Mconv3_stage4_L2" + top: "Mconv3_stage4_L2" +} +layer { + name: "Mconv4_stage4_L1" + type: "Convolution" + bottom: "Mconv3_stage4_L1" + top: "Mconv4_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage4_L1" + type: "ReLU" + bottom: "Mconv4_stage4_L1" + top: "Mconv4_stage4_L1" +} +layer { + name: "Mconv4_stage4_L2" + type: "Convolution" + bottom: "Mconv3_stage4_L2" + top: "Mconv4_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage4_L2" + type: "ReLU" + bottom: "Mconv4_stage4_L2" + top: "Mconv4_stage4_L2" +} +layer { + name: "Mconv5_stage4_L1" + type: "Convolution" + bottom: "Mconv4_stage4_L1" + top: "Mconv5_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage4_L1" + type: "ReLU" + bottom: "Mconv5_stage4_L1" + top: "Mconv5_stage4_L1" +} +layer { + name: "Mconv5_stage4_L2" + type: "Convolution" + bottom: "Mconv4_stage4_L2" + top: "Mconv5_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage4_L2" + type: "ReLU" + bottom: "Mconv5_stage4_L2" + top: "Mconv5_stage4_L2" +} +layer { + name: "Mconv6_stage4_L1" + type: "Convolution" + bottom: "Mconv5_stage4_L1" + top: "Mconv6_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage4_L1" + type: "ReLU" + bottom: "Mconv6_stage4_L1" + top: "Mconv6_stage4_L1" +} +layer { + name: "Mconv6_stage4_L2" + type: "Convolution" + bottom: "Mconv5_stage4_L2" + top: "Mconv6_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage4_L2" + type: "ReLU" + bottom: "Mconv6_stage4_L2" + top: "Mconv6_stage4_L2" +} +layer { + name: "Mconv7_stage4_L1" + type: "Convolution" + bottom: "Mconv6_stage4_L1" + top: "Mconv7_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 38 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv7_stage4_L2" + type: "Convolution" + bottom: "Mconv6_stage4_L2" + top: "Mconv7_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 19 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "concat_stage5" + type: "Concat" + bottom: "Mconv7_stage4_L1" + bottom: "Mconv7_stage4_L2" + bottom: "conv4_4_CPM" + top: "concat_stage5" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage5_L1" + type: "Convolution" + bottom: "concat_stage5" + top: "Mconv1_stage5_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage5_L1" + type: "ReLU" + bottom: "Mconv1_stage5_L1" + top: "Mconv1_stage5_L1" +} +layer { + name: "Mconv1_stage5_L2" + type: "Convolution" + bottom: "concat_stage5" + top: "Mconv1_stage5_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage5_L2" + type: "ReLU" + bottom: "Mconv1_stage5_L2" + top: "Mconv1_stage5_L2" +} +layer { + name: "Mconv2_stage5_L1" + type: "Convolution" + bottom: "Mconv1_stage5_L1" + top: "Mconv2_stage5_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage5_L1" + type: "ReLU" + bottom: "Mconv2_stage5_L1" + top: "Mconv2_stage5_L1" +} +layer { + name: "Mconv2_stage5_L2" + type: "Convolution" + bottom: "Mconv1_stage5_L2" + top: "Mconv2_stage5_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage5_L2" + type: "ReLU" + bottom: "Mconv2_stage5_L2" + top: "Mconv2_stage5_L2" +} +layer { + name: "Mconv3_stage5_L1" + type: "Convolution" + bottom: "Mconv2_stage5_L1" + top: "Mconv3_stage5_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage5_L1" + type: "ReLU" + bottom: "Mconv3_stage5_L1" + top: "Mconv3_stage5_L1" +} +layer { + name: "Mconv3_stage5_L2" + type: "Convolution" + bottom: "Mconv2_stage5_L2" + top: "Mconv3_stage5_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage5_L2" + type: "ReLU" + bottom: "Mconv3_stage5_L2" + top: "Mconv3_stage5_L2" +} +layer { + name: "Mconv4_stage5_L1" + type: "Convolution" + bottom: "Mconv3_stage5_L1" + top: "Mconv4_stage5_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage5_L1" + type: "ReLU" + bottom: "Mconv4_stage5_L1" + top: "Mconv4_stage5_L1" +} +layer { + name: "Mconv4_stage5_L2" + type: "Convolution" + bottom: "Mconv3_stage5_L2" + top: "Mconv4_stage5_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage5_L2" + type: "ReLU" + bottom: "Mconv4_stage5_L2" + top: "Mconv4_stage5_L2" +} +layer { + name: "Mconv5_stage5_L1" + type: "Convolution" + bottom: "Mconv4_stage5_L1" + top: "Mconv5_stage5_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage5_L1" + type: "ReLU" + bottom: "Mconv5_stage5_L1" + top: "Mconv5_stage5_L1" +} +layer { + name: "Mconv5_stage5_L2" + type: "Convolution" + bottom: "Mconv4_stage5_L2" + top: "Mconv5_stage5_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage5_L2" + type: "ReLU" + bottom: "Mconv5_stage5_L2" + top: "Mconv5_stage5_L2" +} +layer { + name: "Mconv6_stage5_L1" + type: "Convolution" + bottom: "Mconv5_stage5_L1" + top: "Mconv6_stage5_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage5_L1" + type: "ReLU" + bottom: "Mconv6_stage5_L1" + top: "Mconv6_stage5_L1" +} +layer { + name: "Mconv6_stage5_L2" + type: "Convolution" + bottom: "Mconv5_stage5_L2" + top: "Mconv6_stage5_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage5_L2" + type: "ReLU" + bottom: "Mconv6_stage5_L2" + top: "Mconv6_stage5_L2" +} +layer { + name: "Mconv7_stage5_L1" + type: "Convolution" + bottom: "Mconv6_stage5_L1" + top: "Mconv7_stage5_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 38 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv7_stage5_L2" + type: "Convolution" + bottom: "Mconv6_stage5_L2" + top: "Mconv7_stage5_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 19 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "concat_stage6" + type: "Concat" + bottom: "Mconv7_stage5_L1" + bottom: "Mconv7_stage5_L2" + bottom: "conv4_4_CPM" + top: "concat_stage6" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage6_L1" + type: "Convolution" + bottom: "concat_stage6" + top: "Mconv1_stage6_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage6_L1" + type: "ReLU" + bottom: "Mconv1_stage6_L1" + top: "Mconv1_stage6_L1" +} +layer { + name: "Mconv1_stage6_L2" + type: "Convolution" + bottom: "concat_stage6" + top: "Mconv1_stage6_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage6_L2" + type: "ReLU" + bottom: "Mconv1_stage6_L2" + top: "Mconv1_stage6_L2" +} +layer { + name: "Mconv2_stage6_L1" + type: "Convolution" + bottom: "Mconv1_stage6_L1" + top: "Mconv2_stage6_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage6_L1" + type: "ReLU" + bottom: "Mconv2_stage6_L1" + top: "Mconv2_stage6_L1" +} +layer { + name: "Mconv2_stage6_L2" + type: "Convolution" + bottom: "Mconv1_stage6_L2" + top: "Mconv2_stage6_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage6_L2" + type: "ReLU" + bottom: "Mconv2_stage6_L2" + top: "Mconv2_stage6_L2" +} +layer { + name: "Mconv3_stage6_L1" + type: "Convolution" + bottom: "Mconv2_stage6_L1" + top: "Mconv3_stage6_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage6_L1" + type: "ReLU" + bottom: "Mconv3_stage6_L1" + top: "Mconv3_stage6_L1" +} +layer { + name: "Mconv3_stage6_L2" + type: "Convolution" + bottom: "Mconv2_stage6_L2" + top: "Mconv3_stage6_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage6_L2" + type: "ReLU" + bottom: "Mconv3_stage6_L2" + top: "Mconv3_stage6_L2" +} +layer { + name: "Mconv4_stage6_L1" + type: "Convolution" + bottom: "Mconv3_stage6_L1" + top: "Mconv4_stage6_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage6_L1" + type: "ReLU" + bottom: "Mconv4_stage6_L1" + top: "Mconv4_stage6_L1" +} +layer { + name: "Mconv4_stage6_L2" + type: "Convolution" + bottom: "Mconv3_stage6_L2" + top: "Mconv4_stage6_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage6_L2" + type: "ReLU" + bottom: "Mconv4_stage6_L2" + top: "Mconv4_stage6_L2" +} +layer { + name: "Mconv5_stage6_L1" + type: "Convolution" + bottom: "Mconv4_stage6_L1" + top: "Mconv5_stage6_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage6_L1" + type: "ReLU" + bottom: "Mconv5_stage6_L1" + top: "Mconv5_stage6_L1" +} +layer { + name: "Mconv5_stage6_L2" + type: "Convolution" + bottom: "Mconv4_stage6_L2" + top: "Mconv5_stage6_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage6_L2" + type: "ReLU" + bottom: "Mconv5_stage6_L2" + top: "Mconv5_stage6_L2" +} +layer { + name: "Mconv6_stage6_L1" + type: "Convolution" + bottom: "Mconv5_stage6_L1" + top: "Mconv6_stage6_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage6_L1" + type: "ReLU" + bottom: "Mconv6_stage6_L1" + top: "Mconv6_stage6_L1" +} +layer { + name: "Mconv6_stage6_L2" + type: "Convolution" + bottom: "Mconv5_stage6_L2" + top: "Mconv6_stage6_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage6_L2" + type: "ReLU" + bottom: "Mconv6_stage6_L2" + top: "Mconv6_stage6_L2" +} +layer { + name: "Mconv7_stage6_L1" + type: "Convolution" + bottom: "Mconv6_stage6_L1" + top: "Mconv7_stage6_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 38 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv7_stage6_L2" + type: "Convolution" + bottom: "Mconv6_stage6_L2" + top: "Mconv7_stage6_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 19 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "concat_stage7" + type: "Concat" + bottom: "Mconv7_stage6_L2" + bottom: "Mconv7_stage6_L1" + # top: "concat_stage7" + top: "net_output" + concat_param { + axis: 1 + } +} diff --git a/openpose/models/pose/mpi/pose_deploy_linevec.prototxt b/openpose/models/pose/mpi/pose_deploy_linevec.prototxt new file mode 100644 index 0000000000000000000000000000000000000000..54492d68a185cc50661078f370c7aa0041d8761a --- /dev/null +++ b/openpose/models/pose/mpi/pose_deploy_linevec.prototxt @@ -0,0 +1,2975 @@ +input: "image" +input_dim: 1 +input_dim: 3 +input_dim: 1 # This value will be defined at runtime +input_dim: 1 # This value will be defined at runtime +layer { + name: "conv1_1" + type: "Convolution" + bottom: "image" + top: "conv1_1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 64 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu1_1" + type: "ReLU" + bottom: "conv1_1" + top: "conv1_1" +} +layer { + name: "conv1_2" + type: "Convolution" + bottom: "conv1_1" + top: "conv1_2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 64 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu1_2" + type: "ReLU" + bottom: "conv1_2" + top: "conv1_2" +} +layer { + name: "pool1_stage1" + type: "Pooling" + bottom: "conv1_2" + top: "pool1_stage1" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layer { + name: "conv2_1" + type: "Convolution" + bottom: "pool1_stage1" + top: "conv2_1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu2_1" + type: "ReLU" + bottom: "conv2_1" + top: "conv2_1" +} +layer { + name: "conv2_2" + type: "Convolution" + bottom: "conv2_1" + top: "conv2_2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu2_2" + type: "ReLU" + bottom: "conv2_2" + top: "conv2_2" +} +layer { + name: "pool2_stage1" + type: "Pooling" + bottom: "conv2_2" + top: "pool2_stage1" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layer { + name: "conv3_1" + type: "Convolution" + bottom: "pool2_stage1" + top: "conv3_1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu3_1" + type: "ReLU" + bottom: "conv3_1" + top: "conv3_1" +} +layer { + name: "conv3_2" + type: "Convolution" + bottom: "conv3_1" + top: "conv3_2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu3_2" + type: "ReLU" + bottom: "conv3_2" + top: "conv3_2" +} +layer { + name: "conv3_3" + type: "Convolution" + bottom: "conv3_2" + top: "conv3_3" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu3_3" + type: "ReLU" + bottom: "conv3_3" + top: "conv3_3" +} +layer { + name: "conv3_4" + type: "Convolution" + bottom: "conv3_3" + top: "conv3_4" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu3_4" + type: "ReLU" + bottom: "conv3_4" + top: "conv3_4" +} +layer { + name: "pool3_stage1" + type: "Pooling" + bottom: "conv3_4" + top: "pool3_stage1" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layer { + name: "conv4_1" + type: "Convolution" + bottom: "pool3_stage1" + top: "conv4_1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu4_1" + type: "ReLU" + bottom: "conv4_1" + top: "conv4_1" +} +layer { + name: "conv4_2" + type: "Convolution" + bottom: "conv4_1" + top: "conv4_2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu4_2" + type: "ReLU" + bottom: "conv4_2" + top: "conv4_2" +} +layer { + name: "conv4_3_CPM" + type: "Convolution" + bottom: "conv4_2" + top: "conv4_3_CPM" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu4_3_CPM" + type: "ReLU" + bottom: "conv4_3_CPM" + top: "conv4_3_CPM" +} +layer { + name: "conv4_4_CPM" + type: "Convolution" + bottom: "conv4_3_CPM" + top: "conv4_4_CPM" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu4_4_CPM" + type: "ReLU" + bottom: "conv4_4_CPM" + top: "conv4_4_CPM" +} +layer { + name: "conv5_1_CPM_L1" + type: "Convolution" + bottom: "conv4_4_CPM" + top: "conv5_1_CPM_L1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_1_CPM_L1" + type: "ReLU" + bottom: "conv5_1_CPM_L1" + top: "conv5_1_CPM_L1" +} +layer { + name: "conv5_1_CPM_L2" + type: "Convolution" + bottom: "conv4_4_CPM" + top: "conv5_1_CPM_L2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_1_CPM_L2" + type: "ReLU" + bottom: "conv5_1_CPM_L2" + top: "conv5_1_CPM_L2" +} +layer { + name: "conv5_2_CPM_L1" + type: "Convolution" + bottom: "conv5_1_CPM_L1" + top: "conv5_2_CPM_L1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_2_CPM_L1" + type: "ReLU" + bottom: "conv5_2_CPM_L1" + top: "conv5_2_CPM_L1" +} +layer { + name: "conv5_2_CPM_L2" + type: "Convolution" + bottom: "conv5_1_CPM_L2" + top: "conv5_2_CPM_L2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_2_CPM_L2" + type: "ReLU" + bottom: "conv5_2_CPM_L2" + top: "conv5_2_CPM_L2" +} +layer { + name: "conv5_3_CPM_L1" + type: "Convolution" + bottom: "conv5_2_CPM_L1" + top: "conv5_3_CPM_L1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_3_CPM_L1" + type: "ReLU" + bottom: "conv5_3_CPM_L1" + top: "conv5_3_CPM_L1" +} +layer { + name: "conv5_3_CPM_L2" + type: "Convolution" + bottom: "conv5_2_CPM_L2" + top: "conv5_3_CPM_L2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_3_CPM_L2" + type: "ReLU" + bottom: "conv5_3_CPM_L2" + top: "conv5_3_CPM_L2" +} +layer { + name: "conv5_4_CPM_L1" + type: "Convolution" + bottom: "conv5_3_CPM_L1" + top: "conv5_4_CPM_L1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_4_CPM_L1" + type: "ReLU" + bottom: "conv5_4_CPM_L1" + top: "conv5_4_CPM_L1" +} +layer { + name: "conv5_4_CPM_L2" + type: "Convolution" + bottom: "conv5_3_CPM_L2" + top: "conv5_4_CPM_L2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_4_CPM_L2" + type: "ReLU" + bottom: "conv5_4_CPM_L2" + top: "conv5_4_CPM_L2" +} +layer { + name: "conv5_5_CPM_L1" + type: "Convolution" + bottom: "conv5_4_CPM_L1" + top: "conv5_5_CPM_L1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 28 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "conv5_5_CPM_L2" + type: "Convolution" + bottom: "conv5_4_CPM_L2" + top: "conv5_5_CPM_L2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 16 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "concat_stage2" + type: "Concat" + bottom: "conv5_5_CPM_L1" + bottom: "conv5_5_CPM_L2" + bottom: "conv4_4_CPM" + top: "concat_stage2" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage2_L1" + type: "Convolution" + bottom: "concat_stage2" + top: "Mconv1_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage2_L1" + type: "ReLU" + bottom: "Mconv1_stage2_L1" + top: "Mconv1_stage2_L1" +} +layer { + name: "Mconv1_stage2_L2" + type: "Convolution" + bottom: "concat_stage2" + top: "Mconv1_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage2_L2" + type: "ReLU" + bottom: "Mconv1_stage2_L2" + top: "Mconv1_stage2_L2" +} +layer { + name: "Mconv2_stage2_L1" + type: "Convolution" + bottom: "Mconv1_stage2_L1" + top: "Mconv2_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage2_L1" + type: "ReLU" + bottom: "Mconv2_stage2_L1" + top: "Mconv2_stage2_L1" +} +layer { + name: "Mconv2_stage2_L2" + type: "Convolution" + bottom: "Mconv1_stage2_L2" + top: "Mconv2_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage2_L2" + type: "ReLU" + bottom: "Mconv2_stage2_L2" + top: "Mconv2_stage2_L2" +} +layer { + name: "Mconv3_stage2_L1" + type: "Convolution" + bottom: "Mconv2_stage2_L1" + top: "Mconv3_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage2_L1" + type: "ReLU" + bottom: "Mconv3_stage2_L1" + top: "Mconv3_stage2_L1" +} +layer { + name: "Mconv3_stage2_L2" + type: "Convolution" + bottom: "Mconv2_stage2_L2" + top: "Mconv3_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage2_L2" + type: "ReLU" + bottom: "Mconv3_stage2_L2" + top: "Mconv3_stage2_L2" +} +layer { + name: "Mconv4_stage2_L1" + type: "Convolution" + bottom: "Mconv3_stage2_L1" + top: "Mconv4_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage2_L1" + type: "ReLU" + bottom: "Mconv4_stage2_L1" + top: "Mconv4_stage2_L1" +} +layer { + name: "Mconv4_stage2_L2" + type: "Convolution" + bottom: "Mconv3_stage2_L2" + top: "Mconv4_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage2_L2" + type: "ReLU" + bottom: "Mconv4_stage2_L2" + top: "Mconv4_stage2_L2" +} +layer { + name: "Mconv5_stage2_L1" + type: "Convolution" + bottom: "Mconv4_stage2_L1" + top: "Mconv5_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage2_L1" + type: "ReLU" + bottom: "Mconv5_stage2_L1" + top: "Mconv5_stage2_L1" +} +layer { + name: "Mconv5_stage2_L2" + type: "Convolution" + bottom: "Mconv4_stage2_L2" + top: "Mconv5_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage2_L2" + type: "ReLU" + bottom: "Mconv5_stage2_L2" + top: "Mconv5_stage2_L2" +} +layer { + name: "Mconv6_stage2_L1" + type: "Convolution" + bottom: "Mconv5_stage2_L1" + top: "Mconv6_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage2_L1" + type: "ReLU" + bottom: "Mconv6_stage2_L1" + top: "Mconv6_stage2_L1" +} +layer { + name: "Mconv6_stage2_L2" + type: "Convolution" + bottom: "Mconv5_stage2_L2" + top: "Mconv6_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage2_L2" + type: "ReLU" + bottom: "Mconv6_stage2_L2" + top: "Mconv6_stage2_L2" +} +layer { + name: "Mconv7_stage2_L1" + type: "Convolution" + bottom: "Mconv6_stage2_L1" + top: "Mconv7_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 28 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv7_stage2_L2" + type: "Convolution" + bottom: "Mconv6_stage2_L2" + top: "Mconv7_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 16 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "concat_stage3" + type: "Concat" + bottom: "Mconv7_stage2_L1" + bottom: "Mconv7_stage2_L2" + bottom: "conv4_4_CPM" + top: "concat_stage3" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage3_L1" + type: "Convolution" + bottom: "concat_stage3" + top: "Mconv1_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage3_L1" + type: "ReLU" + bottom: "Mconv1_stage3_L1" + top: "Mconv1_stage3_L1" +} +layer { + name: "Mconv1_stage3_L2" + type: "Convolution" + bottom: "concat_stage3" + top: "Mconv1_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage3_L2" + type: "ReLU" + bottom: "Mconv1_stage3_L2" + top: "Mconv1_stage3_L2" +} +layer { + name: "Mconv2_stage3_L1" + type: "Convolution" + bottom: "Mconv1_stage3_L1" + top: "Mconv2_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage3_L1" + type: "ReLU" + bottom: "Mconv2_stage3_L1" + top: "Mconv2_stage3_L1" +} +layer { + name: "Mconv2_stage3_L2" + type: "Convolution" + bottom: "Mconv1_stage3_L2" + top: "Mconv2_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage3_L2" + type: "ReLU" + bottom: "Mconv2_stage3_L2" + top: "Mconv2_stage3_L2" +} +layer { + name: "Mconv3_stage3_L1" + type: "Convolution" + bottom: "Mconv2_stage3_L1" + top: "Mconv3_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage3_L1" + type: "ReLU" + bottom: "Mconv3_stage3_L1" + top: "Mconv3_stage3_L1" +} +layer { + name: "Mconv3_stage3_L2" + type: "Convolution" + bottom: "Mconv2_stage3_L2" + top: "Mconv3_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage3_L2" + type: "ReLU" + bottom: "Mconv3_stage3_L2" + top: "Mconv3_stage3_L2" +} +layer { + name: "Mconv4_stage3_L1" + type: "Convolution" + bottom: "Mconv3_stage3_L1" + top: "Mconv4_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage3_L1" + type: "ReLU" + bottom: "Mconv4_stage3_L1" + top: "Mconv4_stage3_L1" +} +layer { + name: "Mconv4_stage3_L2" + type: "Convolution" + bottom: "Mconv3_stage3_L2" + top: "Mconv4_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage3_L2" + type: "ReLU" + bottom: "Mconv4_stage3_L2" + top: "Mconv4_stage3_L2" +} +layer { + name: "Mconv5_stage3_L1" + type: "Convolution" + bottom: "Mconv4_stage3_L1" + top: "Mconv5_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage3_L1" + type: "ReLU" + bottom: "Mconv5_stage3_L1" + top: "Mconv5_stage3_L1" +} +layer { + name: "Mconv5_stage3_L2" + type: "Convolution" + bottom: "Mconv4_stage3_L2" + top: "Mconv5_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage3_L2" + type: "ReLU" + bottom: "Mconv5_stage3_L2" + top: "Mconv5_stage3_L2" +} +layer { + name: "Mconv6_stage3_L1" + type: "Convolution" + bottom: "Mconv5_stage3_L1" + top: "Mconv6_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage3_L1" + type: "ReLU" + bottom: "Mconv6_stage3_L1" + top: "Mconv6_stage3_L1" +} +layer { + name: "Mconv6_stage3_L2" + type: "Convolution" + bottom: "Mconv5_stage3_L2" + top: "Mconv6_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage3_L2" + type: "ReLU" + bottom: "Mconv6_stage3_L2" + top: "Mconv6_stage3_L2" +} +layer { + name: "Mconv7_stage3_L1" + type: "Convolution" + bottom: "Mconv6_stage3_L1" + top: "Mconv7_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 28 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv7_stage3_L2" + type: "Convolution" + bottom: "Mconv6_stage3_L2" + top: "Mconv7_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 16 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "concat_stage4" + type: "Concat" + bottom: "Mconv7_stage3_L1" + bottom: "Mconv7_stage3_L2" + bottom: "conv4_4_CPM" + top: "concat_stage4" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage4_L1" + type: "Convolution" + bottom: "concat_stage4" + top: "Mconv1_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage4_L1" + type: "ReLU" + bottom: "Mconv1_stage4_L1" + top: "Mconv1_stage4_L1" +} +layer { + name: "Mconv1_stage4_L2" + type: "Convolution" + bottom: "concat_stage4" + top: "Mconv1_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage4_L2" + type: "ReLU" + bottom: "Mconv1_stage4_L2" + top: "Mconv1_stage4_L2" +} +layer { + name: "Mconv2_stage4_L1" + type: "Convolution" + bottom: "Mconv1_stage4_L1" + top: "Mconv2_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage4_L1" + type: "ReLU" + bottom: "Mconv2_stage4_L1" + top: "Mconv2_stage4_L1" +} +layer { + name: "Mconv2_stage4_L2" + type: "Convolution" + bottom: "Mconv1_stage4_L2" + top: "Mconv2_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage4_L2" + type: "ReLU" + bottom: "Mconv2_stage4_L2" + top: "Mconv2_stage4_L2" +} +layer { + name: "Mconv3_stage4_L1" + type: "Convolution" + bottom: "Mconv2_stage4_L1" + top: "Mconv3_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage4_L1" + type: "ReLU" + bottom: "Mconv3_stage4_L1" + top: "Mconv3_stage4_L1" +} +layer { + name: "Mconv3_stage4_L2" + type: "Convolution" + bottom: "Mconv2_stage4_L2" + top: "Mconv3_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage4_L2" + type: "ReLU" + bottom: "Mconv3_stage4_L2" + top: "Mconv3_stage4_L2" +} +layer { + name: "Mconv4_stage4_L1" + type: "Convolution" + bottom: "Mconv3_stage4_L1" + top: "Mconv4_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage4_L1" + type: "ReLU" + bottom: "Mconv4_stage4_L1" + top: "Mconv4_stage4_L1" +} +layer { + name: "Mconv4_stage4_L2" + type: "Convolution" + bottom: "Mconv3_stage4_L2" + top: "Mconv4_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage4_L2" + type: "ReLU" + bottom: "Mconv4_stage4_L2" + top: "Mconv4_stage4_L2" +} +layer { + name: "Mconv5_stage4_L1" + type: "Convolution" + bottom: "Mconv4_stage4_L1" + top: "Mconv5_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage4_L1" + type: "ReLU" + bottom: "Mconv5_stage4_L1" + top: "Mconv5_stage4_L1" +} +layer { + name: "Mconv5_stage4_L2" + type: "Convolution" + bottom: "Mconv4_stage4_L2" + top: "Mconv5_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage4_L2" + type: "ReLU" + bottom: "Mconv5_stage4_L2" + top: "Mconv5_stage4_L2" +} +layer { + name: "Mconv6_stage4_L1" + type: "Convolution" + bottom: "Mconv5_stage4_L1" + top: "Mconv6_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage4_L1" + type: "ReLU" + bottom: "Mconv6_stage4_L1" + top: "Mconv6_stage4_L1" +} +layer { + name: "Mconv6_stage4_L2" + type: "Convolution" + bottom: "Mconv5_stage4_L2" + top: "Mconv6_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage4_L2" + type: "ReLU" + bottom: "Mconv6_stage4_L2" + top: "Mconv6_stage4_L2" +} +layer { + name: "Mconv7_stage4_L1" + type: "Convolution" + bottom: "Mconv6_stage4_L1" + top: "Mconv7_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 28 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv7_stage4_L2" + type: "Convolution" + bottom: "Mconv6_stage4_L2" + top: "Mconv7_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 16 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "concat_stage5" + type: "Concat" + bottom: "Mconv7_stage4_L1" + bottom: "Mconv7_stage4_L2" + bottom: "conv4_4_CPM" + top: "concat_stage5" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage5_L1" + type: "Convolution" + bottom: "concat_stage5" + top: "Mconv1_stage5_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage5_L1" + type: "ReLU" + bottom: "Mconv1_stage5_L1" + top: "Mconv1_stage5_L1" +} +layer { + name: "Mconv1_stage5_L2" + type: "Convolution" + bottom: "concat_stage5" + top: "Mconv1_stage5_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage5_L2" + type: "ReLU" + bottom: "Mconv1_stage5_L2" + top: "Mconv1_stage5_L2" +} +layer { + name: "Mconv2_stage5_L1" + type: "Convolution" + bottom: "Mconv1_stage5_L1" + top: "Mconv2_stage5_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage5_L1" + type: "ReLU" + bottom: "Mconv2_stage5_L1" + top: "Mconv2_stage5_L1" +} +layer { + name: "Mconv2_stage5_L2" + type: "Convolution" + bottom: "Mconv1_stage5_L2" + top: "Mconv2_stage5_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage5_L2" + type: "ReLU" + bottom: "Mconv2_stage5_L2" + top: "Mconv2_stage5_L2" +} +layer { + name: "Mconv3_stage5_L1" + type: "Convolution" + bottom: "Mconv2_stage5_L1" + top: "Mconv3_stage5_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage5_L1" + type: "ReLU" + bottom: "Mconv3_stage5_L1" + top: "Mconv3_stage5_L1" +} +layer { + name: "Mconv3_stage5_L2" + type: "Convolution" + bottom: "Mconv2_stage5_L2" + top: "Mconv3_stage5_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage5_L2" + type: "ReLU" + bottom: "Mconv3_stage5_L2" + top: "Mconv3_stage5_L2" +} +layer { + name: "Mconv4_stage5_L1" + type: "Convolution" + bottom: "Mconv3_stage5_L1" + top: "Mconv4_stage5_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage5_L1" + type: "ReLU" + bottom: "Mconv4_stage5_L1" + top: "Mconv4_stage5_L1" +} +layer { + name: "Mconv4_stage5_L2" + type: "Convolution" + bottom: "Mconv3_stage5_L2" + top: "Mconv4_stage5_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage5_L2" + type: "ReLU" + bottom: "Mconv4_stage5_L2" + top: "Mconv4_stage5_L2" +} +layer { + name: "Mconv5_stage5_L1" + type: "Convolution" + bottom: "Mconv4_stage5_L1" + top: "Mconv5_stage5_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage5_L1" + type: "ReLU" + bottom: "Mconv5_stage5_L1" + top: "Mconv5_stage5_L1" +} +layer { + name: "Mconv5_stage5_L2" + type: "Convolution" + bottom: "Mconv4_stage5_L2" + top: "Mconv5_stage5_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage5_L2" + type: "ReLU" + bottom: "Mconv5_stage5_L2" + top: "Mconv5_stage5_L2" +} +layer { + name: "Mconv6_stage5_L1" + type: "Convolution" + bottom: "Mconv5_stage5_L1" + top: "Mconv6_stage5_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage5_L1" + type: "ReLU" + bottom: "Mconv6_stage5_L1" + top: "Mconv6_stage5_L1" +} +layer { + name: "Mconv6_stage5_L2" + type: "Convolution" + bottom: "Mconv5_stage5_L2" + top: "Mconv6_stage5_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage5_L2" + type: "ReLU" + bottom: "Mconv6_stage5_L2" + top: "Mconv6_stage5_L2" +} +layer { + name: "Mconv7_stage5_L1" + type: "Convolution" + bottom: "Mconv6_stage5_L1" + top: "Mconv7_stage5_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 28 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv7_stage5_L2" + type: "Convolution" + bottom: "Mconv6_stage5_L2" + top: "Mconv7_stage5_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 16 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "concat_stage6" + type: "Concat" + bottom: "Mconv7_stage5_L1" + bottom: "Mconv7_stage5_L2" + bottom: "conv4_4_CPM" + top: "concat_stage6" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage6_L1" + type: "Convolution" + bottom: "concat_stage6" + top: "Mconv1_stage6_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage6_L1" + type: "ReLU" + bottom: "Mconv1_stage6_L1" + top: "Mconv1_stage6_L1" +} +layer { + name: "Mconv1_stage6_L2" + type: "Convolution" + bottom: "concat_stage6" + top: "Mconv1_stage6_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage6_L2" + type: "ReLU" + bottom: "Mconv1_stage6_L2" + top: "Mconv1_stage6_L2" +} +layer { + name: "Mconv2_stage6_L1" + type: "Convolution" + bottom: "Mconv1_stage6_L1" + top: "Mconv2_stage6_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage6_L1" + type: "ReLU" + bottom: "Mconv2_stage6_L1" + top: "Mconv2_stage6_L1" +} +layer { + name: "Mconv2_stage6_L2" + type: "Convolution" + bottom: "Mconv1_stage6_L2" + top: "Mconv2_stage6_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage6_L2" + type: "ReLU" + bottom: "Mconv2_stage6_L2" + top: "Mconv2_stage6_L2" +} +layer { + name: "Mconv3_stage6_L1" + type: "Convolution" + bottom: "Mconv2_stage6_L1" + top: "Mconv3_stage6_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage6_L1" + type: "ReLU" + bottom: "Mconv3_stage6_L1" + top: "Mconv3_stage6_L1" +} +layer { + name: "Mconv3_stage6_L2" + type: "Convolution" + bottom: "Mconv2_stage6_L2" + top: "Mconv3_stage6_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage6_L2" + type: "ReLU" + bottom: "Mconv3_stage6_L2" + top: "Mconv3_stage6_L2" +} +layer { + name: "Mconv4_stage6_L1" + type: "Convolution" + bottom: "Mconv3_stage6_L1" + top: "Mconv4_stage6_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage6_L1" + type: "ReLU" + bottom: "Mconv4_stage6_L1" + top: "Mconv4_stage6_L1" +} +layer { + name: "Mconv4_stage6_L2" + type: "Convolution" + bottom: "Mconv3_stage6_L2" + top: "Mconv4_stage6_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage6_L2" + type: "ReLU" + bottom: "Mconv4_stage6_L2" + top: "Mconv4_stage6_L2" +} +layer { + name: "Mconv5_stage6_L1" + type: "Convolution" + bottom: "Mconv4_stage6_L1" + top: "Mconv5_stage6_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage6_L1" + type: "ReLU" + bottom: "Mconv5_stage6_L1" + top: "Mconv5_stage6_L1" +} +layer { + name: "Mconv5_stage6_L2" + type: "Convolution" + bottom: "Mconv4_stage6_L2" + top: "Mconv5_stage6_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage6_L2" + type: "ReLU" + bottom: "Mconv5_stage6_L2" + top: "Mconv5_stage6_L2" +} +layer { + name: "Mconv6_stage6_L1" + type: "Convolution" + bottom: "Mconv5_stage6_L1" + top: "Mconv6_stage6_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage6_L1" + type: "ReLU" + bottom: "Mconv6_stage6_L1" + top: "Mconv6_stage6_L1" +} +layer { + name: "Mconv6_stage6_L2" + type: "Convolution" + bottom: "Mconv5_stage6_L2" + top: "Mconv6_stage6_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage6_L2" + type: "ReLU" + bottom: "Mconv6_stage6_L2" + top: "Mconv6_stage6_L2" +} +layer { + name: "Mconv7_stage6_L1" + type: "Convolution" + bottom: "Mconv6_stage6_L1" + top: "Mconv7_stage6_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 28 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv7_stage6_L2" + type: "Convolution" + bottom: "Mconv6_stage6_L2" + top: "Mconv7_stage6_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 16 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "concat_stage7" + type: "Concat" + bottom: "Mconv7_stage6_L2" + bottom: "Mconv7_stage6_L1" + top: "net_output" + concat_param { + axis: 1 + } +} diff --git a/openpose/models/pose/mpi/pose_deploy_linevec_faster_4_stages.prototxt b/openpose/models/pose/mpi/pose_deploy_linevec_faster_4_stages.prototxt new file mode 100644 index 0000000000000000000000000000000000000000..02ec183300ecbf5509d897e73c7663f16fb3b1a6 --- /dev/null +++ b/openpose/models/pose/mpi/pose_deploy_linevec_faster_4_stages.prototxt @@ -0,0 +1,2081 @@ +input: "image" +input_dim: 1 +input_dim: 3 +input_dim: 1 # This value will be defined at runtime +input_dim: 1 # This value will be defined at runtime +layer { + name: "conv1_1" + type: "Convolution" + bottom: "image" + top: "conv1_1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 64 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu1_1" + type: "ReLU" + bottom: "conv1_1" + top: "conv1_1" +} +layer { + name: "conv1_2" + type: "Convolution" + bottom: "conv1_1" + top: "conv1_2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 64 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu1_2" + type: "ReLU" + bottom: "conv1_2" + top: "conv1_2" +} +layer { + name: "pool1_stage1" + type: "Pooling" + bottom: "conv1_2" + top: "pool1_stage1" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layer { + name: "conv2_1" + type: "Convolution" + bottom: "pool1_stage1" + top: "conv2_1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu2_1" + type: "ReLU" + bottom: "conv2_1" + top: "conv2_1" +} +layer { + name: "conv2_2" + type: "Convolution" + bottom: "conv2_1" + top: "conv2_2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu2_2" + type: "ReLU" + bottom: "conv2_2" + top: "conv2_2" +} +layer { + name: "pool2_stage1" + type: "Pooling" + bottom: "conv2_2" + top: "pool2_stage1" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layer { + name: "conv3_1" + type: "Convolution" + bottom: "pool2_stage1" + top: "conv3_1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu3_1" + type: "ReLU" + bottom: "conv3_1" + top: "conv3_1" +} +layer { + name: "conv3_2" + type: "Convolution" + bottom: "conv3_1" + top: "conv3_2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu3_2" + type: "ReLU" + bottom: "conv3_2" + top: "conv3_2" +} +layer { + name: "conv3_3" + type: "Convolution" + bottom: "conv3_2" + top: "conv3_3" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu3_3" + type: "ReLU" + bottom: "conv3_3" + top: "conv3_3" +} +layer { + name: "conv3_4" + type: "Convolution" + bottom: "conv3_3" + top: "conv3_4" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu3_4" + type: "ReLU" + bottom: "conv3_4" + top: "conv3_4" +} +layer { + name: "pool3_stage1" + type: "Pooling" + bottom: "conv3_4" + top: "pool3_stage1" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layer { + name: "conv4_1" + type: "Convolution" + bottom: "pool3_stage1" + top: "conv4_1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu4_1" + type: "ReLU" + bottom: "conv4_1" + top: "conv4_1" +} +layer { + name: "conv4_2" + type: "Convolution" + bottom: "conv4_1" + top: "conv4_2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu4_2" + type: "ReLU" + bottom: "conv4_2" + top: "conv4_2" +} +layer { + name: "conv4_3_CPM" + type: "Convolution" + bottom: "conv4_2" + top: "conv4_3_CPM" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu4_3_CPM" + type: "ReLU" + bottom: "conv4_3_CPM" + top: "conv4_3_CPM" +} +layer { + name: "conv4_4_CPM" + type: "Convolution" + bottom: "conv4_3_CPM" + top: "conv4_4_CPM" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu4_4_CPM" + type: "ReLU" + bottom: "conv4_4_CPM" + top: "conv4_4_CPM" +} +layer { + name: "conv5_1_CPM_L1" + type: "Convolution" + bottom: "conv4_4_CPM" + top: "conv5_1_CPM_L1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_1_CPM_L1" + type: "ReLU" + bottom: "conv5_1_CPM_L1" + top: "conv5_1_CPM_L1" +} +layer { + name: "conv5_1_CPM_L2" + type: "Convolution" + bottom: "conv4_4_CPM" + top: "conv5_1_CPM_L2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_1_CPM_L2" + type: "ReLU" + bottom: "conv5_1_CPM_L2" + top: "conv5_1_CPM_L2" +} +layer { + name: "conv5_2_CPM_L1" + type: "Convolution" + bottom: "conv5_1_CPM_L1" + top: "conv5_2_CPM_L1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_2_CPM_L1" + type: "ReLU" + bottom: "conv5_2_CPM_L1" + top: "conv5_2_CPM_L1" +} +layer { + name: "conv5_2_CPM_L2" + type: "Convolution" + bottom: "conv5_1_CPM_L2" + top: "conv5_2_CPM_L2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_2_CPM_L2" + type: "ReLU" + bottom: "conv5_2_CPM_L2" + top: "conv5_2_CPM_L2" +} +layer { + name: "conv5_3_CPM_L1" + type: "Convolution" + bottom: "conv5_2_CPM_L1" + top: "conv5_3_CPM_L1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_3_CPM_L1" + type: "ReLU" + bottom: "conv5_3_CPM_L1" + top: "conv5_3_CPM_L1" +} +layer { + name: "conv5_3_CPM_L2" + type: "Convolution" + bottom: "conv5_2_CPM_L2" + top: "conv5_3_CPM_L2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_3_CPM_L2" + type: "ReLU" + bottom: "conv5_3_CPM_L2" + top: "conv5_3_CPM_L2" +} +layer { + name: "conv5_4_CPM_L1" + type: "Convolution" + bottom: "conv5_3_CPM_L1" + top: "conv5_4_CPM_L1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_4_CPM_L1" + type: "ReLU" + bottom: "conv5_4_CPM_L1" + top: "conv5_4_CPM_L1" +} +layer { + name: "conv5_4_CPM_L2" + type: "Convolution" + bottom: "conv5_3_CPM_L2" + top: "conv5_4_CPM_L2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 512 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "relu5_4_CPM_L2" + type: "ReLU" + bottom: "conv5_4_CPM_L2" + top: "conv5_4_CPM_L2" +} +layer { + name: "conv5_5_CPM_L1" + type: "Convolution" + bottom: "conv5_4_CPM_L1" + top: "conv5_5_CPM_L1" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 28 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "conv5_5_CPM_L2" + type: "Convolution" + bottom: "conv5_4_CPM_L2" + top: "conv5_5_CPM_L2" + param { + lr_mult: 1.0 + decay_mult: 1 + } + param { + lr_mult: 2.0 + decay_mult: 0 + } + convolution_param { + num_output: 16 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "concat_stage2" + type: "Concat" + bottom: "conv5_5_CPM_L1" + bottom: "conv5_5_CPM_L2" + bottom: "conv4_4_CPM" + top: "concat_stage2" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage2_L1" + type: "Convolution" + bottom: "concat_stage2" + top: "Mconv1_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage2_L1" + type: "ReLU" + bottom: "Mconv1_stage2_L1" + top: "Mconv1_stage2_L1" +} +layer { + name: "Mconv1_stage2_L2" + type: "Convolution" + bottom: "concat_stage2" + top: "Mconv1_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage2_L2" + type: "ReLU" + bottom: "Mconv1_stage2_L2" + top: "Mconv1_stage2_L2" +} +layer { + name: "Mconv2_stage2_L1" + type: "Convolution" + bottom: "Mconv1_stage2_L1" + top: "Mconv2_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage2_L1" + type: "ReLU" + bottom: "Mconv2_stage2_L1" + top: "Mconv2_stage2_L1" +} +layer { + name: "Mconv2_stage2_L2" + type: "Convolution" + bottom: "Mconv1_stage2_L2" + top: "Mconv2_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage2_L2" + type: "ReLU" + bottom: "Mconv2_stage2_L2" + top: "Mconv2_stage2_L2" +} +layer { + name: "Mconv3_stage2_L1" + type: "Convolution" + bottom: "Mconv2_stage2_L1" + top: "Mconv3_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage2_L1" + type: "ReLU" + bottom: "Mconv3_stage2_L1" + top: "Mconv3_stage2_L1" +} +layer { + name: "Mconv3_stage2_L2" + type: "Convolution" + bottom: "Mconv2_stage2_L2" + top: "Mconv3_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage2_L2" + type: "ReLU" + bottom: "Mconv3_stage2_L2" + top: "Mconv3_stage2_L2" +} +layer { + name: "Mconv4_stage2_L1" + type: "Convolution" + bottom: "Mconv3_stage2_L1" + top: "Mconv4_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage2_L1" + type: "ReLU" + bottom: "Mconv4_stage2_L1" + top: "Mconv4_stage2_L1" +} +layer { + name: "Mconv4_stage2_L2" + type: "Convolution" + bottom: "Mconv3_stage2_L2" + top: "Mconv4_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage2_L2" + type: "ReLU" + bottom: "Mconv4_stage2_L2" + top: "Mconv4_stage2_L2" +} +layer { + name: "Mconv5_stage2_L1" + type: "Convolution" + bottom: "Mconv4_stage2_L1" + top: "Mconv5_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage2_L1" + type: "ReLU" + bottom: "Mconv5_stage2_L1" + top: "Mconv5_stage2_L1" +} +layer { + name: "Mconv5_stage2_L2" + type: "Convolution" + bottom: "Mconv4_stage2_L2" + top: "Mconv5_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage2_L2" + type: "ReLU" + bottom: "Mconv5_stage2_L2" + top: "Mconv5_stage2_L2" +} +layer { + name: "Mconv6_stage2_L1" + type: "Convolution" + bottom: "Mconv5_stage2_L1" + top: "Mconv6_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage2_L1" + type: "ReLU" + bottom: "Mconv6_stage2_L1" + top: "Mconv6_stage2_L1" +} +layer { + name: "Mconv6_stage2_L2" + type: "Convolution" + bottom: "Mconv5_stage2_L2" + top: "Mconv6_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage2_L2" + type: "ReLU" + bottom: "Mconv6_stage2_L2" + top: "Mconv6_stage2_L2" +} +layer { + name: "Mconv7_stage2_L1" + type: "Convolution" + bottom: "Mconv6_stage2_L1" + top: "Mconv7_stage2_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 28 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv7_stage2_L2" + type: "Convolution" + bottom: "Mconv6_stage2_L2" + top: "Mconv7_stage2_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 16 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "concat_stage3" + type: "Concat" + bottom: "Mconv7_stage2_L1" + bottom: "Mconv7_stage2_L2" + bottom: "conv4_4_CPM" + top: "concat_stage3" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage3_L1" + type: "Convolution" + bottom: "concat_stage3" + top: "Mconv1_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage3_L1" + type: "ReLU" + bottom: "Mconv1_stage3_L1" + top: "Mconv1_stage3_L1" +} +layer { + name: "Mconv1_stage3_L2" + type: "Convolution" + bottom: "concat_stage3" + top: "Mconv1_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage3_L2" + type: "ReLU" + bottom: "Mconv1_stage3_L2" + top: "Mconv1_stage3_L2" +} +layer { + name: "Mconv2_stage3_L1" + type: "Convolution" + bottom: "Mconv1_stage3_L1" + top: "Mconv2_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage3_L1" + type: "ReLU" + bottom: "Mconv2_stage3_L1" + top: "Mconv2_stage3_L1" +} +layer { + name: "Mconv2_stage3_L2" + type: "Convolution" + bottom: "Mconv1_stage3_L2" + top: "Mconv2_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage3_L2" + type: "ReLU" + bottom: "Mconv2_stage3_L2" + top: "Mconv2_stage3_L2" +} +layer { + name: "Mconv3_stage3_L1" + type: "Convolution" + bottom: "Mconv2_stage3_L1" + top: "Mconv3_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage3_L1" + type: "ReLU" + bottom: "Mconv3_stage3_L1" + top: "Mconv3_stage3_L1" +} +layer { + name: "Mconv3_stage3_L2" + type: "Convolution" + bottom: "Mconv2_stage3_L2" + top: "Mconv3_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage3_L2" + type: "ReLU" + bottom: "Mconv3_stage3_L2" + top: "Mconv3_stage3_L2" +} +layer { + name: "Mconv4_stage3_L1" + type: "Convolution" + bottom: "Mconv3_stage3_L1" + top: "Mconv4_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage3_L1" + type: "ReLU" + bottom: "Mconv4_stage3_L1" + top: "Mconv4_stage3_L1" +} +layer { + name: "Mconv4_stage3_L2" + type: "Convolution" + bottom: "Mconv3_stage3_L2" + top: "Mconv4_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage3_L2" + type: "ReLU" + bottom: "Mconv4_stage3_L2" + top: "Mconv4_stage3_L2" +} +layer { + name: "Mconv5_stage3_L1" + type: "Convolution" + bottom: "Mconv4_stage3_L1" + top: "Mconv5_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage3_L1" + type: "ReLU" + bottom: "Mconv5_stage3_L1" + top: "Mconv5_stage3_L1" +} +layer { + name: "Mconv5_stage3_L2" + type: "Convolution" + bottom: "Mconv4_stage3_L2" + top: "Mconv5_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage3_L2" + type: "ReLU" + bottom: "Mconv5_stage3_L2" + top: "Mconv5_stage3_L2" +} +layer { + name: "Mconv6_stage3_L1" + type: "Convolution" + bottom: "Mconv5_stage3_L1" + top: "Mconv6_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage3_L1" + type: "ReLU" + bottom: "Mconv6_stage3_L1" + top: "Mconv6_stage3_L1" +} +layer { + name: "Mconv6_stage3_L2" + type: "Convolution" + bottom: "Mconv5_stage3_L2" + top: "Mconv6_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage3_L2" + type: "ReLU" + bottom: "Mconv6_stage3_L2" + top: "Mconv6_stage3_L2" +} +layer { + name: "Mconv7_stage3_L1" + type: "Convolution" + bottom: "Mconv6_stage3_L1" + top: "Mconv7_stage3_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 28 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv7_stage3_L2" + type: "Convolution" + bottom: "Mconv6_stage3_L2" + top: "Mconv7_stage3_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 16 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "concat_stage4" + type: "Concat" + bottom: "Mconv7_stage3_L1" + bottom: "Mconv7_stage3_L2" + bottom: "conv4_4_CPM" + top: "concat_stage4" + concat_param { + axis: 1 + } +} +layer { + name: "Mconv1_stage4_L1" + type: "Convolution" + bottom: "concat_stage4" + top: "Mconv1_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage4_L1" + type: "ReLU" + bottom: "Mconv1_stage4_L1" + top: "Mconv1_stage4_L1" +} +layer { + name: "Mconv1_stage4_L2" + type: "Convolution" + bottom: "concat_stage4" + top: "Mconv1_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu1_stage4_L2" + type: "ReLU" + bottom: "Mconv1_stage4_L2" + top: "Mconv1_stage4_L2" +} +layer { + name: "Mconv2_stage4_L1" + type: "Convolution" + bottom: "Mconv1_stage4_L1" + top: "Mconv2_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage4_L1" + type: "ReLU" + bottom: "Mconv2_stage4_L1" + top: "Mconv2_stage4_L1" +} +layer { + name: "Mconv2_stage4_L2" + type: "Convolution" + bottom: "Mconv1_stage4_L2" + top: "Mconv2_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu2_stage4_L2" + type: "ReLU" + bottom: "Mconv2_stage4_L2" + top: "Mconv2_stage4_L2" +} +layer { + name: "Mconv3_stage4_L1" + type: "Convolution" + bottom: "Mconv2_stage4_L1" + top: "Mconv3_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage4_L1" + type: "ReLU" + bottom: "Mconv3_stage4_L1" + top: "Mconv3_stage4_L1" +} +layer { + name: "Mconv3_stage4_L2" + type: "Convolution" + bottom: "Mconv2_stage4_L2" + top: "Mconv3_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu3_stage4_L2" + type: "ReLU" + bottom: "Mconv3_stage4_L2" + top: "Mconv3_stage4_L2" +} +layer { + name: "Mconv4_stage4_L1" + type: "Convolution" + bottom: "Mconv3_stage4_L1" + top: "Mconv4_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage4_L1" + type: "ReLU" + bottom: "Mconv4_stage4_L1" + top: "Mconv4_stage4_L1" +} +layer { + name: "Mconv4_stage4_L2" + type: "Convolution" + bottom: "Mconv3_stage4_L2" + top: "Mconv4_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu4_stage4_L2" + type: "ReLU" + bottom: "Mconv4_stage4_L2" + top: "Mconv4_stage4_L2" +} +layer { + name: "Mconv5_stage4_L1" + type: "Convolution" + bottom: "Mconv4_stage4_L1" + top: "Mconv5_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage4_L1" + type: "ReLU" + bottom: "Mconv5_stage4_L1" + top: "Mconv5_stage4_L1" +} +layer { + name: "Mconv5_stage4_L2" + type: "Convolution" + bottom: "Mconv4_stage4_L2" + top: "Mconv5_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 3 + kernel_size: 7 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu5_stage4_L2" + type: "ReLU" + bottom: "Mconv5_stage4_L2" + top: "Mconv5_stage4_L2" +} +layer { + name: "Mconv6_stage4_L1" + type: "Convolution" + bottom: "Mconv5_stage4_L1" + top: "Mconv6_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage4_L1" + type: "ReLU" + bottom: "Mconv6_stage4_L1" + top: "Mconv6_stage4_L1" +} +layer { + name: "Mconv6_stage4_L2" + type: "Convolution" + bottom: "Mconv5_stage4_L2" + top: "Mconv6_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mrelu6_stage4_L2" + type: "ReLU" + bottom: "Mconv6_stage4_L2" + top: "Mconv6_stage4_L2" +} +layer { + name: "Mconv7_stage4_L1" + type: "Convolution" + bottom: "Mconv6_stage4_L1" + top: "Mconv7_stage4_L1" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 28 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "Mconv7_stage4_L2" + type: "Convolution" + bottom: "Mconv6_stage4_L2" + top: "Mconv7_stage4_L2" + param { + lr_mult: 4.0 + decay_mult: 1 + } + param { + lr_mult: 8.0 + decay_mult: 0 + } + convolution_param { + num_output: 16 + pad: 0 + kernel_size: 1 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + } + } +} +layer { + name: "concat_stage7" + type: "Concat" + bottom: "Mconv7_stage4_L2" + bottom: "Mconv7_stage4_L1" + top: "net_output" + concat_param { + axis: 1 + } +} diff --git a/openpose/python/CMakeLists.txt b/openpose/python/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c59c40b4c883576d1df7b947f86449dbbc85d325 --- /dev/null +++ b/openpose/python/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(openpose) diff --git a/openpose/python/openpose/CMakeLists.txt b/openpose/python/openpose/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..587a049fdb2335aeb68f7b754e199d75673ea8d0 --- /dev/null +++ b/openpose/python/openpose/CMakeLists.txt @@ -0,0 +1,14 @@ +set(PYTHON_FILES + openpose.py + __init__.py + openpose_python.cpp) + +pybind11_add_module(pyopenpose openpose_python.cpp) + +target_link_libraries(pyopenpose PRIVATE pybind11::module openpose ${OpenPose_3rdparty_libraries}) +SET_TARGET_PROPERTIES(pyopenpose PROPERTIES PREFIX "") +configure_file(__init__.py __init__.py) + +install(TARGETS pyopenpose DESTINATION python) +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/ DESTINATION python/openpose FILES_MATCHING PATTERN "*.so") +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/ DESTINATION python/openpose FILES_MATCHING PATTERN "*.py") diff --git a/openpose/python/openpose/__init__.py b/openpose/python/openpose/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..37d1fdb86b92366a52312c20702d53398e409ab8 --- /dev/null +++ b/openpose/python/openpose/__init__.py @@ -0,0 +1 @@ +from . import pyopenpose as pyopenpose diff --git a/openpose/python/openpose/openpose_python.cpp b/openpose/python/openpose/openpose_python.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d1263b8f425d9613b36ebc0ff31cd11c5e7484fa --- /dev/null +++ b/openpose/python/openpose/openpose_python.cpp @@ -0,0 +1,635 @@ +#ifndef OPENPOSE_PYTHON_HPP +#define OPENPOSE_PYTHON_HPP +#define BOOST_DATE_TIME_NO_LIB + +#include +#include + +#include +#include +#include +#include +#include +#include + +PYBIND11_MAKE_OPAQUE(std::vector>); + +#ifdef _WIN32 + #define OP_EXPORT __declspec(dllexport) +#else + #define OP_EXPORT +#endif + +namespace op +{ + + namespace py = pybind11; + + void parse_gflags(const std::vector& argv) + { + try + { + std::vector argv_vec; + for (auto& arg : argv) + argv_vec.emplace_back((char*)arg.c_str()); + char** cast = &argv_vec[0]; + int size = (int)argv_vec.size(); + gflags::ParseCommandLineFlags(&size, &cast, true); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + void init_int(py::dict d) + { + try + { + std::vector argv; + argv.emplace_back("openpose.py"); + for (auto item : d){ + // Sanity check + std::size_t found = std::string(py::str(item.first)).find("="); + if (found != std::string::npos) + error("PyOpenPose does not support equal sign flags (e.g., " + + std::string(py::str(item.first)) + ").", __LINE__, __FUNCTION__, __FILE__); + // Add argument + argv.emplace_back("--" + std::string(py::str(item.first)) + "=" + std::string(py::str(item.second))); + } + parse_gflags(argv); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + void init_argv(std::vector argv) + { + try + { + argv.insert(argv.begin(), "openpose.py"); + parse_gflags(argv); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + class WrapperPython{ + public: + std::unique_ptr opWrapper; + bool synchronousIn; + + WrapperPython(ThreadManagerMode mode = ThreadManagerMode::Asynchronous) + { + opLog("Starting OpenPose Python Wrapper...", Priority::High); + + // Construct opWrapper + opWrapper = std::unique_ptr(new Wrapper(mode)); + + // Synchronous in + synchronousIn = ( + mode == ThreadManagerMode::AsynchronousOut || + mode == ThreadManagerMode::Synchronous + ); + } + + void configure(py::dict params = py::dict()) + { + try + { + if (params.size()) + init_int(params); + + // logging_level + checkBool( + 0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", + __LINE__, __FUNCTION__, __FILE__); + ConfigureLog::setPriorityThreshold((Priority)FLAGS_logging_level); + Profiler::setDefaultX(FLAGS_profile_speed); + + // Applying user defined configuration - GFlags to program variables + // outputSize + const auto outputSize = flagsToPoint(op::String(FLAGS_output_resolution), "-1x-1"); + // netInputSize + const auto netInputSize = flagsToPoint(op::String(FLAGS_net_resolution), "-1x368"); + // faceNetInputSize + const auto faceNetInputSize = flagsToPoint(op::String(FLAGS_face_net_resolution), "368x368 (multiples of 16)"); + // handNetInputSize + const auto handNetInputSize = flagsToPoint(op::String(FLAGS_hand_net_resolution), "368x368 (multiples of 16)"); + // poseMode + const auto poseMode = flagsToPoseMode(FLAGS_body); + // poseModel + const auto poseModel = flagsToPoseModel(op::String(FLAGS_model_pose)); + // JSON saving + if (!FLAGS_write_keypoint.empty()) + opLog("Flag `write_keypoint` is deprecated and will eventually be removed." + " Please, use `write_json` instead.", Priority::Max); + // keypointScaleMode + const auto keypointScaleMode = flagsToScaleMode(FLAGS_keypoint_scale); + // heatmaps to add + const auto heatMapTypes = flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg, + FLAGS_heatmaps_add_PAFs); + const auto heatMapScaleMode = flagsToHeatMapScaleMode(FLAGS_heatmaps_scale); + // >1 camera view? + const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1); + // Face and hand detectors + const auto faceDetector = flagsToDetector(FLAGS_face_detector); + const auto handDetector = flagsToDetector(FLAGS_hand_detector); + // Enabling Google Logging + const bool enableGoogleLogging = true; + + // Pose configuration (use WrapperStructPose{} for default and recommended configuration) + const op::WrapperStructPose wrapperStructPose{ + poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu, + FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap, + op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending, + (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder), + heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold, + FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path), + op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging}; + opWrapper->configure(wrapperStructPose); + // Face configuration (use WrapperStructFace{} to disable it) + const WrapperStructFace wrapperStructFace{ + FLAGS_face, faceDetector, faceNetInputSize, + flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose), + (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold}; + opWrapper->configure(wrapperStructFace); + // Hand configuration (use WrapperStructHand{} to disable it) + const WrapperStructHand wrapperStructHand{ + FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range, + flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose, + (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold}; + opWrapper->configure(wrapperStructHand); + // Extra functionality configuration (use WrapperStructExtra{} to disable it) + const WrapperStructExtra wrapperStructExtra{ + FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads}; + opWrapper->configure(wrapperStructExtra); + // Output (comment or use default argument to disable any output) + const WrapperStructOutput wrapperStructOutput{ + FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format), + op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants, + FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format), + op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio, + op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d), + op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host), + op::String(FLAGS_udp_port)}; + opWrapper->configure(wrapperStructOutput); + if (synchronousIn) { + // SynchronousIn => We need a producer + + // Producer (use default to disable any input) + const auto cameraSize = flagsToPoint(op::String(FLAGS_camera_resolution), "-1x-1"); + ProducerType producerType; + op::String producerString; + std::tie(producerType, producerString) = flagsToProducer( + op::String(FLAGS_image_dir), op::String(FLAGS_video), op::String(FLAGS_ip_camera), FLAGS_camera, + FLAGS_flir_camera, FLAGS_flir_camera_index); + const WrapperStructInput wrapperStructInput{ + producerType, producerString, FLAGS_frame_first, FLAGS_frame_step, FLAGS_frame_last, + FLAGS_process_real_time, FLAGS_frame_flip, FLAGS_frame_rotate, FLAGS_frames_repeat, + cameraSize, op::String(FLAGS_camera_parameter_path), FLAGS_frame_undistort, FLAGS_3d_views}; + opWrapper->configure(wrapperStructInput); + } + // No GUI. Equivalent to: opWrapper.configure(WrapperStructGui{}); + // Set to single-thread (for sequential processing and/or debugging and/or reducing latency) + if (FLAGS_disable_multi_thread) + opWrapper->disableMultiThreading(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + void start() + { + try + { + opWrapper->start(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + void stop() + { + try + { + opWrapper->stop(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + void exec() + { + try + { + // GUI (comment or use default argument to disable any visual output) + const WrapperStructGui wrapperStructGui{ + flagsToDisplayMode(FLAGS_display, FLAGS_3d), !FLAGS_no_gui_verbose, FLAGS_fullscreen}; + opWrapper->configure(wrapperStructGui); + opWrapper->exec(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + bool emplaceAndPop(std::vector>& l) + { + try + { + std::shared_ptr>> datumsPtr( + &l, + [](std::vector>*){} + ); + auto got = opWrapper->emplaceAndPop(datumsPtr); + if (got && datumsPtr.get() != &l) { + l.swap(*datumsPtr); + } + return got; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + bool waitAndEmplace(std::vector>& l) + { + try + { + std::shared_ptr>> datumsPtr(&l); + return opWrapper->waitAndEmplace(datumsPtr); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + + bool waitAndPop(std::vector>& l) + { + try + { + std::shared_ptr>> datumsPtr; + auto got = opWrapper->waitAndPop(datumsPtr); + if (got) { + l.swap(*datumsPtr); + } + return got; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return false; + } + } + }; + + std::vector getImagesFromDirectory(const std::string& directoryPath) + { + try + { + return getFilesOnDirectory(directoryPath, Extensions::Images); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return {}; + } + } + + PYBIND11_MODULE(pyopenpose, m) { + + // Functions for Init Params + m.def("init_int", &init_int, "Init Function"); + m.def("init_argv", &init_argv, "Init Function"); + m.def("get_gpu_number", &getGpuNumber, "Get Total GPU"); + m.def("get_images_on_directory", &getImagesFromDirectory, "Get Images On Directory"); + + // Pose Mapping + // Code example in doc/02_output.md, section Keypoint Ordering in C++/Python + m.def("getPoseBodyPartMapping", &getPoseBodyPartMapping, "getPoseBodyPartMapping"); + m.def("getPoseNumberBodyParts", &getPoseNumberBodyParts, "getPoseNumberBodyParts"); + m.def("getPosePartPairs", &getPosePartPairs, "getPosePartPairs"); + m.def("getPoseMapIndex", &getPoseMapIndex, "getPoseMapIndex"); + py::enum_(m, "PoseModel", py::arithmetic()) + .value("BODY_25", PoseModel::BODY_25) + .value("COCO_18", PoseModel::COCO_18) + .value("MPI_15", PoseModel::MPI_15) + .value("MPI_15_4", PoseModel::MPI_15_4) + .value("BODY_25B", PoseModel::BODY_25B) + .value("BODY_135", PoseModel::BODY_135) + .export_values(); + + // OpenposePython + py::class_(m, "WrapperPython") + .def(py::init<>()) + .def(py::init()) + .def("configure", &WrapperPython::configure) + .def("start", &WrapperPython::start) + .def("stop", &WrapperPython::stop) + .def("execute", &WrapperPython::exec) + .def("emplaceAndPop", &WrapperPython::emplaceAndPop) + .def("waitAndEmplace", &WrapperPython::waitAndEmplace) + .def("waitAndPop", &WrapperPython::waitAndPop) + ; + + // ThreadManagerMode + py::enum_(m, "ThreadManagerMode") + .value("Asynchronous", ThreadManagerMode::Asynchronous) + .value("AsynchronousIn", ThreadManagerMode::AsynchronousIn) + .value("AsynchronousOut", ThreadManagerMode::AsynchronousOut) + .value("Synchronous", ThreadManagerMode::Synchronous) + ; + + // Datum Object + py::class_>(m, "Datum") + .def(py::init<>()) + .def_readwrite("id", &Datum::id) + .def_readwrite("subId", &Datum::subId) + .def_readwrite("subIdMax", &Datum::subIdMax) + .def_readwrite("name", &Datum::name) + .def_readwrite("frameNumber", &Datum::frameNumber) + .def_readwrite("cvInputData", &Datum::cvInputData) + .def_readwrite("inputNetData", &Datum::inputNetData) + .def_readwrite("outputData", &Datum::outputData) + .def_readwrite("cvOutputData", &Datum::cvOutputData) + .def_readwrite("cvOutputData3D", &Datum::cvOutputData3D) + .def_readwrite("poseKeypoints", &Datum::poseKeypoints) + .def_readwrite("poseIds", &Datum::poseIds) + .def_readwrite("poseScores", &Datum::poseScores) + .def_readwrite("poseHeatMaps", &Datum::poseHeatMaps) + .def_readwrite("poseCandidates", &Datum::poseCandidates) + .def_readwrite("faceRectangles", &Datum::faceRectangles) + .def_readwrite("faceKeypoints", &Datum::faceKeypoints) + .def_readwrite("faceHeatMaps", &Datum::faceHeatMaps) + .def_readwrite("handRectangles", &Datum::handRectangles) + .def_readwrite("handKeypoints", &Datum::handKeypoints) + .def_readwrite("handHeatMaps", &Datum::handHeatMaps) + .def_readwrite("poseKeypoints3D", &Datum::poseKeypoints3D) + .def_readwrite("faceKeypoints3D", &Datum::faceKeypoints3D) + .def_readwrite("handKeypoints3D", &Datum::handKeypoints3D) + .def_readwrite("cameraMatrix", &Datum::cameraMatrix) + .def_readwrite("cameraExtrinsics", &Datum::cameraExtrinsics) + .def_readwrite("cameraIntrinsics", &Datum::cameraIntrinsics) + .def_readwrite("poseNetOutput", &Datum::poseNetOutput) + .def_readwrite("scaleInputToNetInputs", &Datum::scaleInputToNetInputs) + .def_readwrite("netInputSizes", &Datum::netInputSizes) + .def_readwrite("scaleInputToOutput", &Datum::scaleInputToOutput) + .def_readwrite("netOutputSize", &Datum::netOutputSize) + .def_readwrite("scaleNetToOutput", &Datum::scaleNetToOutput) + .def_readwrite("elementRendered", &Datum::elementRendered) + ; + + py::bind_vector>>(m, "VectorDatum"); + + // Rectangle + py::class_>(m, "Rectangle") + .def("__repr__", [](Rectangle &a) { return a.toString(); }) + .def(py::init<>()) + .def(py::init()) + .def_readwrite("x", &Rectangle::x) + .def_readwrite("y", &Rectangle::y) + .def_readwrite("width", &Rectangle::width) + .def_readwrite("height", &Rectangle::height) + ; + + // Point + py::class_>(m, "Point") + .def("__repr__", [](Point &a) { return a.toString(); }) + .def(py::init<>()) + .def(py::init()) + .def_readwrite("x", &Point::x) + .def_readwrite("y", &Point::y) + ; + + #ifdef VERSION_INFO + m.attr("__version__") = VERSION_INFO; + #else + m.attr("__version__") = "dev"; + #endif + } +} + +// Numpy - op::Array interop +namespace pybind11 { namespace detail { + +template <> struct type_caster> { + public: + + PYBIND11_TYPE_CASTER(op::Array, _("numpy.ndarray")); + + // Cast numpy to op::Array + bool load(handle src, bool imp) + { + try + { + UNUSED(imp); + // array b(src, true); + array b = reinterpret_borrow(src); + buffer_info info = b.request(); + + if (info.format != format_descriptor::format()) + op::error("op::Array only supports float32 now", __LINE__, __FUNCTION__, __FILE__); + + //std::vector a(info.shape); + std::vector shape(std::begin(info.shape), std::end(info.shape)); + + // No copy + value = op::Array(shape, (float*)info.ptr); + // Copy + //value = op::Array(shape); + //memcpy(value.getPtr(), info.ptr, value.getVolume()*sizeof(float)); + + return true; + } + catch (const std::exception& e) + { + op::error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return {}; + } + } + + // Cast op::Array to numpy + static handle cast(const op::Array &m, return_value_policy, handle defval) + { + UNUSED(defval); + if (m.getSize().size() == 0) { + return Py_BuildValue(""); + } + std::string format = format_descriptor::format(); + return array(buffer_info( + m.getPseudoConstPtr(),/* Pointer to buffer */ + sizeof(float), /* Size of one scalar */ + format, /* Python struct-style format descriptor */ + m.getSize().size(), /* Number of dimensions */ + m.getSize(), /* Buffer dimensions */ + m.getStride() /* Strides (in bytes) for each index */ + )).release(); + } + + }; +}} // namespace pybind11::detail + +// Numpy - op::Array interop +namespace pybind11 { namespace detail { + +template <> struct type_caster> { + public: + + PYBIND11_TYPE_CASTER(op::Array, _("numpy.ndarray")); + + // Cast numpy to op::Array + bool load(handle src, bool imp) + { + op::error("op::Array is read only now", __LINE__, __FUNCTION__, __FILE__); + return false; + } + + // Cast op::Array to numpy + static handle cast(const op::Array &m, return_value_policy, handle defval) + { + UNUSED(defval); + if (m.getSize().size() == 0) { + return Py_BuildValue(""); + } + std::string format = format_descriptor::format(); + return array(buffer_info( + m.getPseudoConstPtr(),/* Pointer to buffer */ + sizeof(long long), /* Size of one scalar */ + format, /* Python struct-style format descriptor */ + m.getSize().size(), /* Number of dimensions */ + m.getSize(), /* Buffer dimensions */ + m.getStride() /* Strides (in bytes) for each index */ + )).release(); + } + + }; +}} // namespace pybind11::detail + +// Numpy - op::Matrix interop +namespace pybind11 { namespace detail { + +template <> struct type_caster { + public: + + PYBIND11_TYPE_CASTER(op::Matrix, _("numpy.ndarray")); + + // Cast numpy to op::Matrix + bool load(handle src, bool) + { + /* Try a default converting into a Python */ + //array b(src, true); + array b = reinterpret_borrow(src); + buffer_info info = b.request(); + + const int ndims = (int)info.ndim; + + decltype(CV_32F) dtype; + size_t elemsize; + if (info.format == format_descriptor::format()) + { + if (ndims == 3) + dtype = CV_32FC3; + else + dtype = CV_32FC1; + elemsize = sizeof(float); + } + else if (info.format == format_descriptor::format()) + { + if (ndims == 3) + dtype = CV_64FC3; + else + dtype = CV_64FC1; + elemsize = sizeof(double); + } + else if (info.format == format_descriptor::format()) + { + if (ndims == 3) + dtype = CV_8UC3; + else + dtype = CV_8UC1; + elemsize = sizeof(unsigned char); + } + else + { + throw std::logic_error("Unsupported type"); + return false; + } + + std::vector shape = {(int)info.shape[0], (int)info.shape[1]}; + + value = op::Matrix(shape[0], shape[1], dtype, info.ptr); + // value = cv::Mat(cv::Size(shape[1], shape[0]), dtype, info.ptr, cv::Mat::AUTO_STEP); + return true; + } + + // Cast op::Matrix to numpy + static handle cast(const op::Matrix &matrix, return_value_policy, handle defval) + { + UNUSED(defval); + std::string format = format_descriptor::format(); + size_t elemsize = sizeof(unsigned char); + int dim; + switch(matrix.type()) { + case CV_8U: + format = format_descriptor::format(); + elemsize = sizeof(unsigned char); + dim = 2; + break; + case CV_8UC3: + format = format_descriptor::format(); + elemsize = sizeof(unsigned char); + dim = 3; + break; + case CV_32F: + format = format_descriptor::format(); + elemsize = sizeof(float); + dim = 2; + break; + case CV_64F: + format = format_descriptor::format(); + elemsize = sizeof(double); + dim = 2; + break; + default: + throw std::logic_error("Unsupported type"); + } + + std::vector bufferdim; + std::vector strides; + if (dim == 2) { + bufferdim = {(size_t) matrix.rows(), (size_t) matrix.cols()}; + strides = {elemsize * (size_t) matrix.cols(), elemsize}; + } else if (dim == 3) { + bufferdim = {(size_t) matrix.rows(), (size_t) matrix.cols(), (size_t) 3}; + strides = {(size_t) elemsize * matrix.cols() * 3, (size_t) elemsize * 3, (size_t) elemsize}; + } + return array(buffer_info( + matrix.dataPseudoConst(), /* Pointer to buffer */ + elemsize, /* Size of one scalar */ + format, /* Python struct-style format descriptor */ + dim, /* Number of dimensions */ + bufferdim, /* Buffer dimensions */ + strides /* Strides (in bytes) for each index */ + )).release(); + } + + }; +}} // namespace pybind11::detail + +#endif diff --git a/openpose/scripts/CI/configure.sh b/openpose/scripts/CI/configure.sh new file mode 100644 index 0000000000000000000000000000000000000000..5425c5527518754554e9d0acaf0549b7a2c50289 --- /dev/null +++ b/openpose/scripts/CI/configure.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# Configure the project + +BASEDIR=$(dirname $0) +source $BASEDIR/defaults.sh + +echo "WITH_CMAKE = ${WITH_CMAKE}." +if [[ $WITH_CMAKE == true ]] ; then + echo "Running CMake configuration..." + source $BASEDIR/configure_cmake.sh +else + echo "Running Makefile configuration..." + source $BASEDIR/configure_make.sh +fi diff --git a/openpose/scripts/CI/configure_cmake.sh b/openpose/scripts/CI/configure_cmake.sh new file mode 100644 index 0000000000000000000000000000000000000000..1b57e0dfee0e5000e3db87af2915cf0255ecbb73 --- /dev/null +++ b/openpose/scripts/CI/configure_cmake.sh @@ -0,0 +1,82 @@ +#!/bin/bash + +# CMake configuration + +mkdir build +cd build + +echo "RUN_EXAMPLES = ${RUN_EXAMPLES}." +if [[ $RUN_EXAMPLES == false ]] ; then + ARGS="-DDOWNLOAD_BODY_25_MODEL=OFF -DDOWNLOAD_FACE_MODEL=OFF -DDOWNLOAD_HAND_MODEL=OFF" + # ARGS="-DBUILD_CAFFE=ON -DDOWNLOAD_BODY_25_MODEL=OFF -DDOWNLOAD_BODY_COCO_MODEL=OFF -DDOWNLOAD_FACE_MODEL=OFF -DDOWNLOAD_HAND_MODEL=OFF -DDOWNLOAD_BODY_MPI_MODEL=OFF" +fi + +echo "WITH_PYTHON = ${WITH_PYTHON}." +if [[ $WITH_PYTHON == true ]] ; then + if [[ "$CI_OS_NAME" == "linux" ]] ; then + ARGS="$ARGS -DBUILD_PYTHON=On" + if [[ $PYTHON3_VERSION ]] ; then + ARGS="$ARGS -DPYTHON_EXECUTABLE=/usr/bin/${PYTHON3_VERSION} -DPYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/lib${PYTHON3_VERSION}m.so" + else + echo "No Python version defined (or unknown one used), using the default v2.7" + ARGS="$ARGS -DPYTHON_EXECUTABLE=/usr/bin/python2.7 -DPYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython2.7m.so" + fi + fi + if [[ "$CI_OS_NAME" == "osx" ]] ; then + ARGS="$ARGS -DBUILD_PYTHON=On -DPYTHON_EXECUTABLE=/usr/local/bin/python2.7 -DPYTHON_LIBRARY=/usr/local/opt/python/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7m.dylib" + fi + echo "Python arguments = $ARGS" +fi + +# CUDA version +echo "WITH_CUDA = ${WITH_CUDA}." +echo "WITH_OPEN_CL = ${WITH_OPEN_CL}." +echo "WITH_MKL = ${WITH_MKL}." +if [[ $WITH_CUDA == true ]] ; then + # Only build SM50 + ARGS="$ARGS -DGPU_MODE=CUDA -DCUDA_ARCH=Manual -DCUDA_ARCH_BIN=\"52\" -DCUDA_ARCH_PTX=\"\"" +# OpenCL version +elif [[ $WITH_OPEN_CL == true ]] ; then + ARGS="$ARGS -DGPU_MODE=OPENCL" +# CPU version +else + ARGS="$ARGS -DGPU_MODE=CPU_ONLY" + # MKL (Intel Caffe) + if [[ $WITH_MKL == true ]] ; then + ARGS="$ARGS -DUSE_MKL=On" + else + ARGS="$ARGS -DUSE_MKL=Off" + fi +fi + +echo "WITH_CUDNN = ${WITH_CUDNN}." +if [[ $WITH_CUDNN == true ]] ; then + ARGS="$ARGS -DUSE_CUDNN=On" +else + ARGS="$ARGS -DUSE_CUDNN=Off" +fi + +echo "WITH_UNITY = ${WITH_UNITY}." +if [[ $WITH_UNITY == true ]] ; then + ARGS="$ARGS -DBUILD_UNITY_SUPPORT=On" +fi + +echo "WITH_DEBUG = ${WITH_DEBUG}." +if [[ $WITH_DEBUG == true ]] ; then + ARGS="$ARGS -DCMAKE_BUILD_TYPE=Debug" +fi + +echo "ARGS = ${ARGS}." + +cmake .. $ARGS + +# Patch for OpenCL and OSX +if [[ $WITH_OPEN_CL == true && $CI_OS_NAME == "osx" ]] ; then + cd ../3rdparty/caffe; git apply ../../scripts/osx/mac_opencl_patch.txt; + cd ../../build; +fi + +# Run Cmake twice for pybind to register +if [[ $WITH_PYTHON == true ]] ; then + cmake .. $ARGS +fi diff --git a/openpose/scripts/CI/configure_make.sh b/openpose/scripts/CI/configure_make.sh new file mode 100644 index 0000000000000000000000000000000000000000..5a147c2c16a504547abc7ff27d34489a100c429f --- /dev/null +++ b/openpose/scripts/CI/configure_make.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# Raw Makefile configuration +# # All in one line +# bash scripts/ubuntu_deprecated/install_caffe_and_openpose_if_cuda8.sh + +if [[ $MAKE_CONFIG_COMPATIBLE == false ]] ; then + echo "Configuration not compatible for Makefile." + exit 99 +fi + +LINE () { + echo "$@" >> Makefile.config + echo "$@" >> 3rdparty/caffe/Makefile.config +} + +# Install Caffe +echo "Installing Caffe..." +cd ./3rdparty/caffe +bash install_caffe_if_cuda8.sh +cd ../.. + +# Generate Makefile files for OpenPose +echo "Generating Makefile files for OpenPose..." +bash scripts/ubuntu_deprecated/copy_makefile_files.sh + +echo "WITH_CUDA = ${WITH_CUDA}." +if [[ $WITH_CUDA == true ]] ; then + # Only build SM50 + LINE "CUDA_ARCH := -gencode arch=compute_50,code=sm_50" +else + LINE "CPU_ONLY := 1" +fi + +echo "WITH_CUDNN = ${WITH_CUDNN}." +if [[ $WITH_CUDNN == true ]] ; then + LINE "USE_CUDNN := 1" +fi diff --git a/openpose/scripts/CI/defaults.sh b/openpose/scripts/CI/defaults.sh new file mode 100644 index 0000000000000000000000000000000000000000..e61ed268ba90300da940b490848922f53a43cd11 --- /dev/null +++ b/openpose/scripts/CI/defaults.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# Set default environment variables +set -e +CI_OS_NAME=${CI_OS_NAME} +WITH_CMAKE=${WITH_CMAKE:-true} +WITH_PYTHON=${WITH_PYTHON:-false} +WITH_CUDA=${WITH_CUDA:-true} +WITH_CUDNN=${WITH_CUDNN:-true} +WITH_OPEN_CL=${WITH_OPEN_CL:-false} +WITH_MKL=${WITH_MKL:-false} +WITH_UNITY=${WITH_UNITY:-false} +WITH_DEBUG=${WITH_DEBUG:-false} + +if [[ $WITH_CUDA == false ]] && [[ $WITH_CUDNN == true ]] +then + echo "CUDNN only possible in combination with CUDA, setting WITH_CUDNN to false" + WITH_CUDNN=false +fi + +# Examples should be run (CI environment not compatible with GPU code) +# if [[ $WITH_CMAKE == true ]] && [[ $WITH_PYTHON == true ]] && [[ $WITH_CUDA == false ]] && [[ $WITH_OPEN_CL == false ]] && [[ $WITH_MKL == false ]]; then +if [[ $WITH_CUDA == false ]] && [[ $WITH_OPEN_CL == false ]] && [[ $WITH_UNITY == false ]]; then + RUN_EXAMPLES=true +else + RUN_EXAMPLES=false +fi +echo "RUN_EXAMPLES = ${RUN_EXAMPLES}." + +# Makefile configuration compatible +# if [[ $WITH_PYTHON == false ]] ; then +if [[ $WITH_PYTHON == false ]] && [[ $WITH_DEBUG == false ]] && [[ $WITH_UNITY == false ]]; then + MAKE_CONFIG_COMPATIBLE=true +else + MAKE_CONFIG_COMPATIBLE=false +fi +echo "MAKE_CONFIG_COMPATIBLE = ${MAKE_CONFIG_COMPATIBLE}." diff --git a/openpose/scripts/CI/install_deps_osx.sh b/openpose/scripts/CI/install_deps_osx.sh new file mode 100644 index 0000000000000000000000000000000000000000..c1430497db160653f524ed5d2df78f6ee0641e9a --- /dev/null +++ b/openpose/scripts/CI/install_deps_osx.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# Install dependencies for Mac OS +echo "Running on Mac OS." + +BASEDIR=$(dirname $0) +source $BASEDIR/defaults.sh + +# To fix linking issue in CI during install of python as dep of opencv +[[ -f /usr/local/bin/2to3 ]] && rm -f /usr/local/bin/2to3 + +source ./scripts/osx/install_brew.sh +source ./scripts/osx/install_deps.sh diff --git a/openpose/scripts/CI/install_deps_ubuntu.sh b/openpose/scripts/CI/install_deps_ubuntu.sh new file mode 100644 index 0000000000000000000000000000000000000000..e10568eea584b11be606e5fb8c11f69ea0bde78e --- /dev/null +++ b/openpose/scripts/CI/install_deps_ubuntu.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# Install dependencies for Ubuntu +echo "Running on ${CI_OS_NAME} OS." + +BASEDIR=$(dirname $0) +source $BASEDIR/defaults.sh + +if [[ $WITH_CUDA == true ]]; then + bash $BASEDIR/../ubuntu/install_cuda.sh +fi +if [[ $WITH_CUDNN == true ]]; then + bash $BASEDIR/../ubuntu/install_cudnn_up_to_Ubuntu16.sh +fi + +bash $BASEDIR/../ubuntu/install_deps.sh + +sudo apt-get -y install libatlas-base-dev +sudo apt-get -y install libopencv-dev diff --git a/openpose/scripts/CI/run_make.sh b/openpose/scripts/CI/run_make.sh new file mode 100644 index 0000000000000000000000000000000000000000..ac8554003d4271158bc7536e515d4222630887a9 --- /dev/null +++ b/openpose/scripts/CI/run_make.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# Build the project + +BASEDIR=$(dirname $0) +source $BASEDIR/defaults.sh + +if [[ $WITH_CMAKE == true ]] ; then + cd build + if [[ "$CI_OS_NAME" == "linux" ]]; then make -j`nproc` ; fi + if [[ "$CI_OS_NAME" == "osx" ]]; then make -j`sysctl -n hw.logicalcpu` ; fi +else + if [[ "$CI_OS_NAME" == "linux" ]]; then make all -j`nproc` ; fi + if [[ "$CI_OS_NAME" == "osx" ]]; then make all -j`sysctl -n hw.logicalcpu` ; fi +fi diff --git a/openpose/scripts/CI/run_tests.sh b/openpose/scripts/CI/run_tests.sh new file mode 100644 index 0000000000000000000000000000000000000000..9dc054993c32155874c3bbead42fb2d0905634ab --- /dev/null +++ b/openpose/scripts/CI/run_tests.sh @@ -0,0 +1,114 @@ +#!/bin/bash + +# Test the project + +BASEDIR=$(dirname $0) +source $BASEDIR/defaults.sh + +# Only for NAME="default-cmake-cpu" WITH_CUDA=false +if [[ $RUN_EXAMPLES == true ]] ; then + echo "Running demos and tutorials..." + echo " " + + echo "OpenPose demo..." + ./build/examples/openpose/openpose.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0 + echo " " + + echo "(Deprecated) Tutorial Add Module: Example 1..." + ./build/examples/deprecated/tutorial_add_module_custom_post_processing.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0 + echo " " + + # # Note: Examples 1-2 require the whole OpenPose resolution (too much RAM memory) and the GUI + # echo "Tutorial API C++: Examples 1-2..." + # ./build/examples/tutorial_api_cpp/01_body_from_image_default.bin + # ./build/examples/tutorial_api_cpp/02_whole_body_from_image_default.bin + # echo " " + + echo "Tutorial API C++: Example 3..." + ./build/examples/tutorial_api_cpp/03_keypoints_from_image.bin --net_resolution -1x32 --write_json output/ --write_images output/ --no_display + echo " " + + echo "Tutorial API C++: Example 4..." + ./build/examples/tutorial_api_cpp/04_keypoints_from_images.bin --net_resolution -1x32 --write_json output/ --write_images output/ --no_display + echo " " + + echo "Tutorial API C++: Example 5..." + ./build/examples/tutorial_api_cpp/05_keypoints_from_images_multi_gpu.bin --net_resolution -1x32 --write_json output/ --write_images output/ --no_display --latency_is_irrelevant_and_computer_with_lots_of_ram + # Default configuration of this demo requires getGpuNumber(), which is not implement for CPU-only mode + # ./build/examples/tutorial_api_cpp/05_keypoints_from_images_multi_gpu.bin --net_resolution -1x32 --write_json output/ --write_images output/ --no_display + echo " " + + echo "Tutorial API C++: Example 6..." + ./build/examples/tutorial_api_cpp/06_face_from_image.bin --face_net_resolution 32x32 --write_json output/ --write_images output/ --no_display + echo " " + + echo "Tutorial API C++: Example 7..." + ./build/examples/tutorial_api_cpp/07_hand_from_image.bin --hand_net_resolution 32x32 --write_json output/ --write_images output/ --no_display + echo " " + + echo "Tutorial API C++: Example 8..." + ./build/examples/tutorial_api_cpp/08_heatmaps_from_image.bin --net_resolution -1x32 --write_json output/ --write_images output/ --no_display + echo " " + + echo "Tutorial API C++: Example 9..." + ./build/examples/tutorial_api_cpp/09_keypoints_from_heatmaps.bin --net_resolution -1x32 --write_json output/ --write_images output/ --no_display + echo " " + + echo "Tutorial API C++: Example 10..." + ./build/examples/tutorial_api_cpp/10_asynchronous_custom_input.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0 + echo " " + + # # Note: Example 11 would require 3D video and camera parameters + # echo "Tutorial API C++: Example 11..." + # ./build/examples/tutorial_api_cpp/11_asynchronous_custom_input_multi_camera.bin + # echo " " + + echo "Tutorial API C++: Example 12..." + ./build/examples/tutorial_api_cpp/12_asynchronous_custom_output.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --no_display + echo " " + + echo "Tutorial API C++: Example 13..." + ./build/examples/tutorial_api_cpp/13_asynchronous_custom_input_output_and_datum.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --no_display + echo " " + + echo "Tutorial API C++: Example 14..." + ./build/examples/tutorial_api_cpp/14_synchronous_custom_input.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0 + echo " " + + echo "Tutorial API C++: Example 15..." + ./build/examples/tutorial_api_cpp/15_synchronous_custom_preprocessing.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0 + echo " " + + echo "Tutorial API C++: Example 16..." + ./build/examples/tutorial_api_cpp/16_synchronous_custom_postprocessing.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0 + echo " " + + echo "Tutorial API C++: Example 17..." + ./build/examples/tutorial_api_cpp/17_synchronous_custom_output.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --no_display + echo " " + + echo "Tutorial API C++: Example 18..." + ./build/examples/tutorial_api_cpp/18_synchronous_custom_all_and_datum.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --no_display + echo " " + + # Python examples + if [[ $WITH_PYTHON == true ]] ; then + if [[ $PYTHON3_VERSION ]] ; then + PYTHON_COMMAND=python3 + else + PYTHON_COMMAND=python + fi + echo "Tutorial API Python: OpenPose demo..." + cd build/examples/tutorial_api_python + ${PYTHON_COMMAND} openpose_python.py --image_dir ../../../examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0 + echo " " + # Note: All Python examples require GUI + fi + + echo "Demos and tutorials successfully finished!" + +# Disable examples for all other CI Build configurations +else + echo "Skipping tests for non CPU-only versions." + exit 0 +fi diff --git a/openpose/scripts/osx/install_brew.sh b/openpose/scripts/osx/install_brew.sh new file mode 100644 index 0000000000000000000000000000000000000000..b278933829b4a2704aa48528756a062559cbaa6b --- /dev/null +++ b/openpose/scripts/osx/install_brew.sh @@ -0,0 +1,4 @@ +# In case the command line have already been installed, "true" will make it return a non-zero error code to avoid stopping the scripts +xcode-select --install || true +bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" +brew update diff --git a/openpose/scripts/osx/install_deps.sh b/openpose/scripts/osx/install_deps.sh new file mode 100644 index 0000000000000000000000000000000000000000..3d53d4062d16049a5f3ccd5f5a3a82e78ce50e66 --- /dev/null +++ b/openpose/scripts/osx/install_deps.sh @@ -0,0 +1,19 @@ +#!/bin/bash +brew_packages="openblas snappy leveldb gflags glog szip lmdb hdf5 opencv protobuf boost cmake viennacl" +for pkg in $brew_packages +do + echo "brew install $pkg || brew upgrade $pkg" + brew install "$pkg" || brew upgrade "$pkg" +done + +# with Python pycaffe needs dependencies built from source +#brew install --build-from-source --with-python -vd protobuf +#brew install --build-from-source -vd boost boost-python +# without Python the usual installation suffices + +pip_packages="numpy<1.17 opencv-python<4.3" +for pkg in $pip_packages +do + echo "sudo -H python2 -m pip install $pkg" + sudo -H python2 -m pip install "$pkg" +done diff --git a/openpose/scripts/osx/mac_opencl_patch.txt b/openpose/scripts/osx/mac_opencl_patch.txt new file mode 100644 index 0000000000000000000000000000000000000000..3109873e6a68e12d5294e96968c655edef0f2cce --- /dev/null +++ b/openpose/scripts/osx/mac_opencl_patch.txt @@ -0,0 +1,37 @@ +diff --git a/cmake/Modules/FindvecLib.cmake b/cmake/Modules/FindvecLib.cmake +index 7459f623..9c5ee818 100644 +--- a/cmake/Modules/FindvecLib.cmake ++++ b/cmake/Modules/FindvecLib.cmake +@@ -12,13 +12,17 @@ endif() + + set(__veclib_include_suffix "Frameworks/vecLib.framework/Versions/Current/Headers") + +-find_path(vecLib_INCLUDE_DIR vecLibTypes.h ++exec_program(xcode-select ARGS -print-path OUTPUT_VARIABLE CMAKE_XCODE_DEVELOPER_DIR) ++find_path(vecLib_INCLUDE_DIR vecLib.h + DOC "vecLib include directory" + PATHS /System/Library/Frameworks/Accelerate.framework/Versions/Current/${__veclib_include_suffix} + /System/Library/${__veclib_include_suffix} +- /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Accelerate.framework/Versions/Current/Frameworks/vecLib.framework/Headers/ ++ ${CMAKE_XCODE_DEVELOPER_DIR}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Accelerate.framework/Versions/Current/Frameworks/vecLib.framework/Headers/ + NO_DEFAULT_PATH) + ++ ++set(vecLib_INCLUDE_DIR "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/Headers/") ++ + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(vecLib DEFAULT_MSG vecLib_INCLUDE_DIR) + +diff --git a/src/caffe/layers/malis_loss_layer.cpp b/src/caffe/layers/malis_loss_layer.cpp +index dae3c7d1..68e8323a 100644 +--- a/src/caffe/layers/malis_loss_layer.cpp ++++ b/src/caffe/layers/malis_loss_layer.cpp +@@ -1,6 +1,6 @@ + #include +-#include +-#include ++//#include ++//#include + + #include + #include diff --git a/openpose/scripts/tests/drawProtoTxt.sh b/openpose/scripts/tests/drawProtoTxt.sh new file mode 100644 index 0000000000000000000000000000000000000000..66fb0ad35b2103b5331b2d8aa096fa144889a8ef --- /dev/null +++ b/openpose/scripts/tests/drawProtoTxt.sh @@ -0,0 +1,22 @@ +#!/bin/bash + + + +# Script for internal use. We might completely change it continuously and we will not answer questions about it. + +# Required +# sudo apt-get install graphviz + +# USAGE EXAMPLE +# clear && clear && make all -j`nproc` && bash ./scripts/tests/speed_test.sh + +# # Go back to main folder +# cd ../../ + +PROTO_TXT_PATH=/mnt/DataUbuntu/openpose_train/training_results/pose/pose_training.prototxt +OUTPUT_PNG_PATH=/mnt/DataUbuntu/openpose_train/training_results/pose/pose_training.png + +# Get model speed +python ~/devel/openpose_caffe_train/python/draw_net.py $PROTO_TXT_PATH $OUTPUT_PNG_PATH +display $OUTPUT_PNG_PATH +rm $OUTPUT_PNG_PATH diff --git a/openpose/scripts/tests/hand_accuracy_test.sh b/openpose/scripts/tests/hand_accuracy_test.sh new file mode 100644 index 0000000000000000000000000000000000000000..787a6915b1b98e1c448c2d43bac86356edf252cb --- /dev/null +++ b/openpose/scripts/tests/hand_accuracy_test.sh @@ -0,0 +1,73 @@ +#!/bin/bash + + + +# Disclaimer: +# Script for internal use. We might make continuous changess on it and we will not answer questions about it. + +# Full usage description: + # Step 1 - Getting JSON output + # Running it: + # Run it from OpenPose main folder with the following command: + # clear && clear && make all -j`nproc` && bash ./scripts/tests/hand_accuracy_test.sh + + # Image paths: + # Read that script for details about all the paths and change them for your own paths. + + # Careful: + # If you are using the NAS, please do not override my files, i.e., please change the output paths (corresponding to the ones indicated by `--write_json`, which is ). + + # In order to generate the JSON output: + # Uncomment the commented lines starting by `--write_json` and `--display 0` + + # Step 2 - Running JSON output to get accuracy + # Once you have the JSON files, run them with the script Tomas prepared for it, which in my case I use: + # From Matlab, `cd /media/posefs3b/Users/gines/openpose_train/dataset/hand_testing` + # Run `b_keypointJsonToMatAndImage` to generate your new file (you can run the current code to try it, I commented everything but test 1) + # Run `c_plot_save_results` to plot and save the results. Just modify `models` and `texts` with your new model path and desired name. + +# Clear terminal screen +clear && clear + + + +# Fix paths +HAND_TESTING_FOLDER="/media/posefs3b/Users/gines/openpose_train/dataset/hand_testing/" +IMAGES_FOLDER=${HAND_TESTING_FOLDER}"0_images/" +IMAGES_BB_FOLDER=${HAND_TESTING_FOLDER}"3_images_bounding_box" +HAND_GROUND_TRUTH_FOLDER=${HAND_TESTING_FOLDER}"4_hand_detections" +PEOPLE_JSON_FOLDER=${HAND_TESTING_FOLDER}"5_keypointJson/" + +# Variable paths +SCALES=6 +SUFFIX="_${SCALES}" +HAND_RESULTS_FOLDER_BASE=${PEOPLE_JSON_FOLDER}"hand_keypoints_estimated" +HAND_RESULTS_FOLDER_NO_BB=${HAND_RESULTS_FOLDER_BASE}"_old"${SUFFIX} +HAND_RESULTS_FOLDER_BB=${HAND_RESULTS_FOLDER_BASE}"_BBox"${SUFFIX} +HAND_RESULTS_FOLDER_BODY_65=${HAND_RESULTS_FOLDER_BASE}"_BODY_65" + + + +# Given bounding box +echo "Output on ${HAND_RESULTS_FOLDER_BB}" +rm -rf $HAND_RESULTS_FOLDER_BB +# 1 scale +./build/examples/tests/handFromJsonTest.bin \ + --hand_scale_number ${SCALES} --hand_scale_range 0.4 \ + --image_dir ${IMAGES_BB_FOLDER} \ + --hand_ground_truth ${HAND_GROUND_TRUTH_FOLDER} \ + --write_json $HAND_RESULTS_FOLDER_BB \ + --display 0 + + + +# No bounding box +echo "Output on ${HAND_RESULTS_FOLDER_NO_BB}" +rm -rf $HAND_RESULTS_FOLDER_NO_BB +# 1 scale +./build/examples/openpose/openpose.bin \ + --hand \ + --hand_scale_number ${SCALES} --hand_scale_range 0.4 \ + --image_dir ${IMAGES_FOLDER} \ + --write_json $HAND_RESULTS_FOLDER_NO_BB \ + --display 0 diff --git a/openpose/scripts/tests/pose_accuracy_all_val.sh b/openpose/scripts/tests/pose_accuracy_all_val.sh new file mode 100644 index 0000000000000000000000000000000000000000..8c09a79186704c828b29a23ca48ae89be5ad3437 --- /dev/null +++ b/openpose/scripts/tests/pose_accuracy_all_val.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# Script to extract COCO JSON file for each trained model +clear && clear && make all -j`nproc` + +# Body/Foot +IMAGE_DIR="/home/gines/devel/images/val2017/" +IMAGE_DIR_FOOT="/home/gines/devel/images/val2017_foot/" +# Face +IMAGE_DIR_FRGC="/home/gines/devel/images/frgc_val/" +IMAGE_DIR_MPIE="/home/gines/devel/images/multipie_val/" +IMAGE_DIR_FACE_MASK_OUT="/home/gines/devel/images/face_mask_out_val/" +# Hand +IMAGE_DIR_HAND_DOME="/home/gines/devel/images/hand_dome_val/" +IMAGE_DIR_HAND_MPII="/home/gines/devel/images/hand_mpii_val/" + +# cd OpenPose folder +cd /home/gines/Dropbox/Perceptual_Computing_Lab/openpose/openpose/ + +temporaryJsonFile1=~/Desktop/OpenPose_1.json +temporaryJsonFile4=~/Desktop/OpenPose_4.json +OP_COMAND="./build/examples/openpose/openpose.bin --face --hand --render_pose 0 --display 0 --cli_verbose 0.2" +OP_COMAND_1SCALE="${OP_COMAND} --write_coco_json ${temporaryJsonFile1} --num_gpu_start 1" +OP_COMAND_4SCALES="${OP_COMAND} --maximize_positives --net_resolution_dynamic -1 --scale_number 4 --scale_gap 0.25 --write_coco_json ${temporaryJsonFile4} --num_gpu_start 1" + +# NOTE: Uncomment those tests you are interested into. By default, all disabled. + +# # Body/foot 1 scale +# echo "Processing bodies/feet..." +# $OP_COMAND_1SCALE --image_dir ${IMAGE_DIR} --write_coco_json_variants 3 + +# # Faces +# echo "Processing faces..." +# temporaryJsonFile1Face=~/Desktop/OpenPose_1_face.json +# # Face FRGC processing +# $OP_COMAND_1SCALE --image_dir ${IMAGE_DIR_FRGC} --write_coco_json_variants 4 +# # Face MPIE processing +# $OP_COMAND_1SCALE --image_dir ${IMAGE_DIR_MPIE} --write_coco_json_variants 4 +# # Face Mask Out processing +# $OP_COMAND_1SCALE --image_dir ${IMAGE_DIR_FACE_MASK_OUT} --write_coco_json_variants 4 + +# # Hands +# echo "Processing hands..." +# # Hand Dome processing +# $OP_COMAND_1SCALE --image_dir ${IMAGE_DIR_HAND_DOME} --write_coco_json_variants 8 +# Hand MPII processing +# $OP_COMAND_1SCALE --image_dir ${IMAGE_DIR_HAND_MPII} --write_coco_json_variants 16 + +# # Body/foot 4 scales +# $OP_COMAND_4SCALES --image_dir ${IMAGE_DIR} --write_coco_json_variants 3 --net_resolution "1312x736" + +echo " " +echo "Finished! Exiting script..." +echo " " diff --git a/openpose/scripts/tests/pose_accuracy_car_val.sh b/openpose/scripts/tests/pose_accuracy_car_val.sh new file mode 100644 index 0000000000000000000000000000000000000000..aa113e43b6a3752425dbd1c55bfc35cccabcca34 --- /dev/null +++ b/openpose/scripts/tests/pose_accuracy_car_val.sh @@ -0,0 +1,38 @@ +#!/bin/bash + + + +# Script for internal use. We might completely change it continuously and we will not answer questions about it. + +clear && clear + +# USAGE EXAMPLE +# clear && clear && make all -j`nproc` && bash ./scripts/tests/pose_accuracy_coco_test.sh + +# # Go back to main folder +# cd ../../ + + +# Write COCO-format JSON +# Last id: + # ID 20671 <--> #frames = 1471 --> ~ 1.5 min at 15fps + # ID 50006 <--> #frames = 3559 --> ~ 4 min at 15fps + +# Parameters +IMAGE_FOLDER_CF=/home/gines/devel/images/car-fusion_val/ +IMAGE_FOLDER_P3=/home/gines/devel/images/pascal3d+_val/ +IMAGE_FOLDER_V7=/home/gines/devel/images/veri-776_val/ +JSON_FOLDER=../evaluation/coco_val_jsons/ +OP_BIN=./build/examples/openpose/openpose.bin +GPUS=-1 +# GPUS=1 + + # 1 scale +$OP_BIN --image_dir $IMAGE_FOLDER_CF --write_coco_json_variant 0 --write_coco_json ${JSON_FOLDER}processed_carfusion_val_1.json --model_pose CAR_22 --display 0 --render_pose 0 --num_gpu ${GPUS} +$OP_BIN --image_dir $IMAGE_FOLDER_P3 --write_coco_json_variant 1 --write_coco_json ${JSON_FOLDER}processed_pascal3dplus_val_1.json --model_pose CAR_22 --display 0 --render_pose 0 --num_gpu ${GPUS} +$OP_BIN --image_dir $IMAGE_FOLDER_V7 --write_coco_json_variant 2 --write_coco_json ${JSON_FOLDER}processed_veri776_val_1.json --model_pose CAR_22 --display 0 --render_pose 0 --num_gpu ${GPUS} + +# # 4 scales +# $OP_BIN --image_dir $IMAGE_FOLDER_CF --write_coco_json_variant 0 --write_coco_json ${JSON_FOLDER}processed_carfusion_val_4.json --model_pose CAR_22 --display 0 --render_pose 0 --scale_number 4 --scale_gap 0.25 --net_resolution "1312x736" --num_gpu ${GPUS} +# $OP_BIN --image_dir $IMAGE_FOLDER_P3 --write_coco_json_variant 1 --write_coco_json ${JSON_FOLDER}processed_pascal3dplus_val_4.json --model_pose CAR_22 --display 0 --render_pose 0 --scale_number 4 --scale_gap 0.25 --net_resolution "1312x736" --num_gpu ${GPUS} +# $OP_BIN --image_dir $IMAGE_FOLDER_V7 --write_coco_json_variant 2 --write_coco_json ${JSON_FOLDER}processed_veri776_val_4.json --model_pose CAR_22 --display 0 --render_pose 0 --scale_number 4 --scale_gap 0.25 --net_resolution "1312x736" --num_gpu ${GPUS} diff --git a/openpose/scripts/tests/pose_accuracy_coco_test_dev.sh b/openpose/scripts/tests/pose_accuracy_coco_test_dev.sh new file mode 100644 index 0000000000000000000000000000000000000000..3c3ab0dc71af6fcb37a2feb34973051c94ed73c8 --- /dev/null +++ b/openpose/scripts/tests/pose_accuracy_coco_test_dev.sh @@ -0,0 +1,36 @@ +#!/bin/bash + + + +# USAGE EXAMPLE +# clear && clear && make all -j`nproc` && bash ./scripts/tests/pose_accuracy_coco_test_dev.sh + +# Script for internal use. We might completely change it continuously and we will not answer questions about it. + +clear && clear + +# Parameters +IMAGE_FOLDER=/media/posefs3b/Users/gines/openpose_train/dataset/COCO/cocoapi/images/test2017_dev/ +JSON_FOLDER=../evaluation/coco_val_jsons/ +# JSON_FOLDER=/media/posefs3b/Users/gines/openpose_train/training_results/2_23_51/best_702k/ +OP_BIN=./build/examples/openpose/openpose.bin + +# # 1 scale +# $OP_BIN --image_dir $IMAGE_FOLDER --display 0 --render_pose 0 --cli_verbose 0.2 --write_coco_json ${JSON_FOLDER}1_test_max.json \ +# --scale_number 1 --scale_gap 0.25 --maximize_positives --net_resolution_dynamic -1 --model_pose BODY_25B +# zip ${JSON_FOLDER}1_test_max.zip ${JSON_FOLDER}1_test_max.json + + # 4 scales +# $OP_BIN --image_dir $IMAGE_FOLDER --display 0 --render_pose 0 --cli_verbose 0.2 --write_coco_json ${JSON_FOLDER}1_4_test.json \ +# --scale_number 4 --scale_gap 0.25 --net_resolution "1312x736" +$OP_BIN --image_dir $IMAGE_FOLDER --display 0 --render_pose 0 --cli_verbose 0.2 --write_coco_json ${JSON_FOLDER}1_4_test_max.json \ + --scale_number 4 --scale_gap 0.25 --net_resolution "1312x736" --maximize_positives --net_resolution_dynamic -1 +zip ${JSON_FOLDER}1_4_test_max.zip ${JSON_FOLDER}1_4_test_max.json + + + +# Additional settings: +# 1. For maximum accuracy: +# --write_coco_json ${JSON_FOLDER}1_4_max.json --maximize_positives --net_resolution_dynamic -1 +# 2. For custom models: +# --model_pose BODY_25B/BODY_23 --model_folder ${JSON_FOLDER} diff --git a/openpose/scripts/tests/pose_accuracy_coco_val.sh b/openpose/scripts/tests/pose_accuracy_coco_val.sh new file mode 100644 index 0000000000000000000000000000000000000000..0bc17c56efac29758a317310c3231cf4d473f06d --- /dev/null +++ b/openpose/scripts/tests/pose_accuracy_coco_val.sh @@ -0,0 +1,37 @@ +#!/bin/bash + + + +# USAGE EXAMPLE +# clear && clear && make all -j`nproc` && bash ./scripts/tests/pose_accuracy_coco_val.sh + +# Script for internal use. We might completely change it continuously and we will not answer questions about it. + +clear && clear + +# Parameters +IMAGE_FOLDER=~/devel/images/val2017/ +IMAGE_FOOT_FOLDER=~/devel/images/val2017_foot/ +JSON_FOLDER=../evaluation/coco_val_jsons/ +# JSON_FOLDER=/media/posefs3b/Users/gines/openpose_train/training_results/2_23_51/best_702k/ +OP_BIN=./build/examples/openpose/openpose.bin + + # 1 scale (body) +$OP_BIN --image_dir $IMAGE_FOLDER --display 0 --render_pose 0 --cli_verbose 0.2 --write_coco_json ${JSON_FOLDER}1.json --write_coco_json_variants 1 +# $OP_BIN --image_dir $IMAGE_FOLDER --display 0 --render_pose 0 --cli_verbose 0.2 --write_coco_json ${JSON_FOLDER}1_max.json --write_coco_json_variants 3 \ +# --maximize_positives --net_resolution_dynamic -1 + + # 1 scale (foot) +$OP_BIN --image_dir $IMAGE_FOOT_FOLDER --display 0 --render_pose 0 --cli_verbose 0.2 --write_coco_json ${JSON_FOLDER}1.json --write_coco_json_variants 2 + +# # 4 scales +# $OP_BIN --image_dir $IMAGE_FOLDER --display 0 --render_pose 0 --cli_verbose 0.2 --write_coco_json ${JSON_FOLDER}1_4.json --write_coco_json_variants 1 \ +# --scale_number 4 --scale_gap 0.25 --net_resolution "1312x736" + + + +# Additional settings: +# 1. For maximum accuracy: +# --write_coco_json ${JSON_FOLDER}1_4_max.json --maximize_positives --net_resolution_dynamic -1 +# 2. For custom models: +# --model_pose BODY_25B/BODY_23 --model_folder ${JSON_FOLDER} diff --git a/openpose/scripts/tests/pose_time_Caffe_layers.sh b/openpose/scripts/tests/pose_time_Caffe_layers.sh new file mode 100644 index 0000000000000000000000000000000000000000..77d720d34cda3a093c7c661a72398f66beb2db0d --- /dev/null +++ b/openpose/scripts/tests/pose_time_Caffe_layers.sh @@ -0,0 +1,17 @@ +#!/bin/bash + + + +# Script for internal use. We might completely change it continuously and we will not answer questions about it. + +# # Go back to main folder +# cd ../../ + +# Performance results +PROTOTXT_PATH=/home/gines/Dropbox/Perceptual_Computing_Lab/openpose/openpose/models/pose/coco/pose_deploy_linevec.prototxt + +gedit $0 +# First: Add 656 x 368 as input_dim in: +gedit $PROTOTXT_PATH +./3rdparty/caffe/build/tools/caffe time -model $PROTOTXT_PATH -gpu 0 -phase TEST +gedit $PROTOTXT_PATH diff --git a/openpose/scripts/tests/pose_time_visual_GUI.sh b/openpose/scripts/tests/pose_time_visual_GUI.sh new file mode 100644 index 0000000000000000000000000000000000000000..504f1d648c0ef960ccd3068a33f8c62c46400b2d --- /dev/null +++ b/openpose/scripts/tests/pose_time_visual_GUI.sh @@ -0,0 +1,16 @@ +#!/bin/bash + + + +# Script for internal use. We might completely change it continuously and we will not answer questions about it. + +# # Go back to main folder +# cd ../../ + +# Re-build +clear && clear && make all -j`nproc` + +# Performance results (~1400) +./build/examples/openpose/openpose.bin --video soccer.mp4 --frame_last 1500 +# Including 2nd graphics card (~3500) +# ./build/examples/openpose/openpose.bin --video soccer.mp4 --frame_last 3750 diff --git a/openpose/scripts/tests/speed_test.sh b/openpose/scripts/tests/speed_test.sh new file mode 100644 index 0000000000000000000000000000000000000000..b240409ca9a4c9c16b066a75b02f7baec596efea --- /dev/null +++ b/openpose/scripts/tests/speed_test.sh @@ -0,0 +1,15 @@ +#!/bin/bash + + + +# Script for internal use. We might completely change it continuously and we will not answer questions about it. + +# USAGE EXAMPLE +# clear && clear && make all -j`nproc` && bash ./scripts/tests/speed_test.sh + +# # Go back to main folder +# cd ../../ + +# Get model speed +~/devel/openpose_caffe_train/build/tools/caffe time -gpu 0 -model /mnt/DataUbuntu/openpose_train/training_results_light/pose/pose_training.prototxt +# ./3rdparty/caffe/build/tools/caffe time -gpu 0 -model /mnt/DataUbuntu/openpose_train/training_results_light/pose/pose_training.prototxt diff --git a/openpose/scripts/ubuntu/Makefile.config.Ubuntu16_cuda8_JetsonTX2 b/openpose/scripts/ubuntu/Makefile.config.Ubuntu16_cuda8_JetsonTX2 new file mode 100644 index 0000000000000000000000000000000000000000..6f47a8487e1ad6fdff8a1af4ecc173fb0be52ae0 --- /dev/null +++ b/openpose/scripts/ubuntu/Makefile.config.Ubuntu16_cuda8_JetsonTX2 @@ -0,0 +1,95 @@ +## Refer to http://caffe.berkeleyvision.org/installation.html +# Contributions simplifying and improving our build system are welcome! + +# CPU-only switch (comment to build without GPU support). +USE_CUDA := 1 + +# uncomment to disable IO dependencies and corresponding data layers +# USE_OPENCV := 0 +# USE_LEVELDB := 0 +# USE_LMDB := 0 + +# uncomment to allow MDB_NOLOCK when reading LMDB files (only if necessary) +# You should not set this flag if you will be reading LMDBs with any +# possibility of simultaneous read and write +# ALLOW_LMDB_NOLOCK := 1 + +# Uncomment if you're using OpenCV 3 +# OPENCV_VERSION := 3 + +# To customize your choice of compiler, uncomment and set the following. +# N.B. the default for Linux is g++ and the default for OSX is clang++ +# CUSTOM_CXX := g++ + +# CUDA directory contains bin/ and lib/ directories that we need. +CUDA_DIR := /usr/local/cuda +# On Ubuntu 14.04, if cuda tools are installed via +# "sudo apt-get install nvidia-cuda-toolkit" then use this instead: +# CUDA_DIR := /usr + +# CUDA architecture setting: going with all of them. +# For CUDA < 6.0, comment the *_50 through *_61 lines for compatibility. +# For CUDA < 8.0, comment the *_60 and *_61 lines for compatibility. +CUDA_ARCH := -gencode arch=compute_30,code=sm_30 \ + -gencode arch=compute_35,code=sm_35 \ + -gencode arch=compute_50,code=sm_50 \ + -gencode arch=compute_52,code=sm_52 \ + -gencode arch=compute_60,code=sm_60 \ + -gencode arch=compute_61,code=sm_61 \ + -gencode arch=compute_61,code=compute_61 +# Deprecated +# CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \ +# -gencode arch=compute_20,code=sm_21 \ +# -gencode arch=compute_30,code=sm_30 \ +# -gencode arch=compute_35,code=sm_35 \ +# -gencode arch=compute_50,code=sm_50 \ +# -gencode arch=compute_52,code=sm_52 \ +# -gencode arch=compute_60,code=sm_60 \ +# -gencode arch=compute_61,code=sm_61 \ +# -gencode arch=compute_61,code=compute_61 + +# Uncomment to enable op::Profiler +# PROFILER_ENABLED := 1 + +# DEEP_NET choice: +# caffe for Caffe (default and only option so far) +DEEP_NET := caffe + +# Caffe directory +CAFFE_DIR := 3rdparty/caffe/distribute + +# Faster GUI display +# WITH_OPENCV_WITH_OPENGL := 1 +# OpenPose 3-D Reconstruction +# WITH_3D_RENDERER := 1 +# WITH_CERES := 1 +# WITH_FLIR_CAMERA := 1 +# Eigen directory (Ceres) +# WITH_EIGEN := 1 +EIGEN_DIR := /usr/include/eigen3/ +# Spinnaker directory +SPINNAKER_DIR := /usr/include/spinnaker + +# Whatever else you find you need goes here. +INCLUDE_DIRS := /usr/local/include /usr/include/hdf5/serial +LIBRARY_DIRS := /usr/local/lib /usr/lib /usr/lib/aarch64-linux-gnu /usr/lib/aarch64-linux-gnu/hdf5/serial + +# If Homebrew is installed at a non standard location (for example your home directory) and you use it for general dependencies +# INCLUDE_DIRS += $(shell brew --prefix)/include +# LIBRARY_DIRS += $(shell brew --prefix)/lib + +# Uncomment to use `pkg-config` to specify OpenCV library paths. +# (Usually not necessary -- OpenCV libraries are normally installed in one of the above $LIBRARY_DIRS.) +# USE_PKG_CONFIG := 1 + +BUILD_DIR := build +DISTRIBUTE_DIR := distribute + +# Uncomment for debugging. Does not work on OSX due to https://github.com/BVLC/caffe/issues/171 +# DEBUG := 1 + +# The ID of the GPU that 'make runtest' will use to run unit tests. +TEST_GPUID := 0 + +# enable pretty build (comment to see full commands) +Q ?= @ diff --git a/openpose/scripts/ubuntu/Makefile.config.Ubuntu16_cuda9_JetsonTX2_JetPack33 b/openpose/scripts/ubuntu/Makefile.config.Ubuntu16_cuda9_JetsonTX2_JetPack33 new file mode 100644 index 0000000000000000000000000000000000000000..ded57f37ca3f36fa2afcc52fd3d57669dc63e186 --- /dev/null +++ b/openpose/scripts/ubuntu/Makefile.config.Ubuntu16_cuda9_JetsonTX2_JetPack33 @@ -0,0 +1,95 @@ +## Refer to http://caffe.berkeleyvision.org/installation.html +# Contributions simplifying and improving our build system are welcome! + +# CPU-only switch (comment to build without GPU support). +USE_CUDA := 1 + +# uncomment to disable IO dependencies and corresponding data layers +# USE_OPENCV := 0 +# USE_LEVELDB := 0 +# USE_LMDB := 0 + +# uncomment to allow MDB_NOLOCK when reading LMDB files (only if necessary) +# You should not set this flag if you will be reading LMDBs with any +# possibility of simultaneous read and write +# ALLOW_LMDB_NOLOCK := 1 + +# Uncomment if you're using OpenCV 3 +OPENCV_VERSION := 3 + +# To customize your choice of compiler, uncomment and set the following. +# N.B. the default for Linux is g++ and the default for OSX is clang++ +# CUSTOM_CXX := g++ + +# CUDA directory contains bin/ and lib/ directories that we need. +CUDA_DIR := /usr/local/cuda +# On Ubuntu 14.04, if cuda tools are installed via +# "sudo apt-get install nvidia-cuda-toolkit" then use this instead: +# CUDA_DIR := /usr + +# CUDA architecture setting: going with all of them. +# For CUDA < 6.0, comment the *_50 through *_61 lines for compatibility. +# For CUDA < 8.0, comment the *_60 and *_61 lines for compatibility. +CUDA_ARCH := -gencode arch=compute_30,code=sm_30 \ + -gencode arch=compute_35,code=sm_35 \ + -gencode arch=compute_50,code=sm_50 \ + -gencode arch=compute_52,code=sm_52 \ + -gencode arch=compute_60,code=sm_60 \ + -gencode arch=compute_61,code=sm_61 \ + -gencode arch=compute_61,code=compute_61 +# Deprecated +# CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \ +# -gencode arch=compute_20,code=sm_21 \ +# -gencode arch=compute_30,code=sm_30 \ +# -gencode arch=compute_35,code=sm_35 \ +# -gencode arch=compute_50,code=sm_50 \ +# -gencode arch=compute_52,code=sm_52 \ +# -gencode arch=compute_60,code=sm_60 \ +# -gencode arch=compute_61,code=sm_61 \ +# -gencode arch=compute_61,code=compute_61 + +# Uncomment to enable op::Profiler +# PROFILER_ENABLED := 1 + +# DEEP_NET choice: +# caffe for Caffe (default and only option so far) +DEEP_NET := caffe + +# Caffe directory +CAFFE_DIR := 3rdparty/caffe/distribute + +# Faster GUI display +# WITH_OPENCV_WITH_OPENGL := 1 +# OpenPose 3-D Reconstruction +# WITH_3D_RENDERER := 1 +# WITH_CERES := 1 +# WITH_FLIR_CAMERA := 1 +# Eigen directory (Ceres) +# WITH_EIGEN := 1 +EIGEN_DIR := /usr/include/eigen3/ +# Spinnaker directory +SPINNAKER_DIR := /usr/include/spinnaker + +# Whatever else you find you need goes here. +INCLUDE_DIRS := /usr/local/include /usr/include/hdf5/serial +LIBRARY_DIRS := /usr/local/lib /usr/lib /usr/lib/aarch64-linux-gnu /usr/lib/aarch64-linux-gnu/hdf5/serial + +# If Homebrew is installed at a non standard location (for example your home directory) and you use it for general dependencies +# INCLUDE_DIRS += $(shell brew --prefix)/include +# LIBRARY_DIRS += $(shell brew --prefix)/lib + +# Uncomment to use `pkg-config` to specify OpenCV library paths. +# (Usually not necessary -- OpenCV libraries are normally installed in one of the above $LIBRARY_DIRS.) +# USE_PKG_CONFIG := 1 + +BUILD_DIR := build +DISTRIBUTE_DIR := distribute + +# Uncomment for debugging. Does not work on OSX due to https://github.com/BVLC/caffe/issues/171 +# DEBUG := 1 + +# The ID of the GPU that 'make runtest' will use to run unit tests. +TEST_GPUID := 0 + +# enable pretty build (comment to see full commands) +Q ?= @ diff --git a/openpose/scripts/ubuntu/Makefile.example b/openpose/scripts/ubuntu/Makefile.example new file mode 100644 index 0000000000000000000000000000000000000000..76aaaf068ce8e76feb76751291f80b9d6b0a0b5f --- /dev/null +++ b/openpose/scripts/ubuntu/Makefile.example @@ -0,0 +1,515 @@ +PROJECT := openpose + +CONFIG_FILE := Makefile.config +# Explicitly check for the config file, otherwise make -k will proceed anyway. +ifeq ($(wildcard $(CONFIG_FILE)),) +$(error $(CONFIG_FILE) not found. See $(CONFIG_FILE).example.) +endif +include $(CONFIG_FILE) + +BUILD_DIR_LINK := $(BUILD_DIR) +ifeq ($(RELEASE_BUILD_DIR),) + RELEASE_BUILD_DIR := .$(BUILD_DIR)_release +endif +ifeq ($(DEBUG_BUILD_DIR),) + DEBUG_BUILD_DIR := .$(BUILD_DIR)_debug +endif + +DEBUG ?= 0 +ifeq ($(DEBUG), 1) + BUILD_DIR := $(DEBUG_BUILD_DIR) + OTHER_BUILD_DIR := $(RELEASE_BUILD_DIR) +else + BUILD_DIR := $(RELEASE_BUILD_DIR) + OTHER_BUILD_DIR := $(DEBUG_BUILD_DIR) +endif + +# All of the directories containing code. +SRC_DIRS := $(shell find * -type d -exec bash -c "find {} -maxdepth 1 \ + -name '*.cpp' | grep -q ." \; -print) + +# The target shared library name +LIBRARY_NAME := $(PROJECT) +LIB_BUILD_DIR := $(BUILD_DIR)/lib +STATIC_NAME := $(LIB_BUILD_DIR)/lib$(LIBRARY_NAME).a +DYNAMIC_VERSION_MAJOR := 1 +DYNAMIC_VERSION_MINOR := 7 +DYNAMIC_VERSION_REVISION := 0 +DYNAMIC_NAME_SHORT := lib$(LIBRARY_NAME).so +#DYNAMIC_SONAME_SHORT := $(DYNAMIC_NAME_SHORT).$(DYNAMIC_VERSION_MAJOR) +DYNAMIC_VERSIONED_NAME_SHORT := $(DYNAMIC_NAME_SHORT).$(DYNAMIC_VERSION_MAJOR).$(DYNAMIC_VERSION_MINOR).$(DYNAMIC_VERSION_REVISION) +DYNAMIC_NAME := $(LIB_BUILD_DIR)/$(DYNAMIC_VERSIONED_NAME_SHORT) +COMMON_FLAGS += -DOPEN_POSE_VERSION=$(DYNAMIC_VERSION_MAJOR).$(DYNAMIC_VERSION_MINOR).$(DYNAMIC_VERSION_REVISION) + + +############################## +# Enable profiler +############################## +PROFILER_ENABLED ?= 0 +ifneq ($(PROFILER_ENABLED), 0) + COMMON_FLAGS += -DPROFILER_ENABLED=$(PROFILER_ENABLED) +endif + + +############################## +# Deep net selection +############################## +DEEP_NET ?= caffe +# TensorFlow +ifeq ($(DEEP_NET), tensorflow) + # COMMON_FLAGS += -DUSE_TENSOR_FLOW +# Torch +else ifeq ($(DEEP_NET), torch) + # COMMON_FLAGS += -DUSE_TORCH +# Caffe +else + COMMON_FLAGS += -DUSE_CAFFE + LIBRARIES += caffe + LDFLAGS += -Wl,-rpath=$(CAFFE_DIR)/lib + INCLUDE_DIRS += $(CAFFE_DIR)/include + LIBRARY_DIRS += $(CAFFE_DIR)/lib +endif + + +# Faster GUI display +WITH_OPENCV_WITH_OPENGL ?= 0 +ifneq ($(WITH_OPENCV_WITH_OPENGL), 0) + COMMON_FLAGS += -DUSE_OPENCV_WITH_OPENGL + # FreeGLUT + LIBRARIES += glut + # LIBRARIES += GLU GL glut +endif + +# 3-D +# 3-D renderer +WITH_3D_RENDERER ?= 0 +ifneq ($(WITH_3D_RENDERER), 0) + COMMON_FLAGS += -DUSE_3D_RENDERER + # FreeGLUT + LIBRARIES += glut + # LIBRARIES += GLU GL glut +endif +# Ceres support +WITH_CERES ?= 0 +ifneq ($(WITH_CERES), 0) + COMMON_FLAGS += -DUSE_CERES + # Ceres + LIBRARIES += ceres + INCLUDE_DIRS += $(EIGEN_DIR) + # If Ceres was built with Suitesparse: + LIBRARIES += lapack camd amd ccolamd colamd cholmod + # If Ceres was built with CXSparse: + LIBRARIES += cxsparse + # If Ceres was built with OpenMP: + LIBRARIES += pthread gomp m + CXXFLAGS += -fopenmp + LINKFLAGS += -fopenmp +endif +# Eigen support +WITH_EIGEN ?= 0 +ifneq ($(WITH_EIGEN), 0) + COMMON_FLAGS += -DUSE_EIGEN + INCLUDE_DIRS += $(EIGEN_DIR) +endif +# Spinnaker SDK +WITH_FLIR_CAMERA ?= 0 +ifneq ($(WITH_FLIR_CAMERA), 0) + COMMON_FLAGS += -DUSE_FLIR_CAMERA + # Spinnaker SDK + LIBRARIES += Spinnaker + # INCLUDE_DIRS += $(SPINNAKER_DIR) + COMMON_FLAGS += -isystem $(SPINNAKER_DIR) # Remove warnings from this library +endif + +############################## +# Get all source files +############################## +# CXX_SRCS are the source files excluding the test ones. +# CXX_SRCS := $(shell find src/$(PROJECT) ! -name "test_*.cpp" -name "*.cpp") +CXX_SRCS := $(shell find src ! -name "test_*.cpp" -name "*.cpp") +# CU_SRCS are the cuda source files +# CU_SRCS := $(shell find src/$(PROJECT) ! -name "test_*.cu" -name "*.cu") +CU_SRCS := $(shell find src ! -name "test_*.cu" -name "*.cu") +# EXAMPLE_SRCS are the source files for the example binaries +EXAMPLE_SRCS := $(shell find examples -name "*.cpp") +# BUILD_INCLUDE_DIR contains any generated header files we want to include. +BUILD_INCLUDE_DIR := $(BUILD_DIR)/src +# NONGEN_CXX_SRCS includes all source/header files except those generated +# automatically (e.g., by proto). +NONGEN_CXX_SRCS := $(shell find \ + src/$(PROJECT) \ + include/$(PROJECT) \ + examples \ + -name "*.cpp" -or -name "*.hpp" -or -name "*.cu" -or -name "*.cuh") +LINT_SCRIPT := scripts/cpp_lint.py +LINT_OUTPUT_DIR := $(BUILD_DIR)/.lint +LINT_EXT := lint.txt +LINT_OUTPUTS := $(addsuffix .$(LINT_EXT), $(addprefix $(LINT_OUTPUT_DIR)/, $(NONGEN_CXX_SRCS))) +EMPTY_LINT_REPORT := $(BUILD_DIR)/.$(LINT_EXT) +NONEMPTY_LINT_REPORT := $(BUILD_DIR)/$(LINT_EXT) + +############################## +# Derive generated files +############################## +# The objects corresponding to the source files +# These objects will be linked into the final shared library, so we +# exclude the example objects. +CXX_OBJS := $(addprefix $(BUILD_DIR)/, ${CXX_SRCS:.cpp=.o}) +CU_OBJS := $(addprefix $(BUILD_DIR)/cuda/, ${CU_SRCS:.cu=.o}) +OBJS := $(CXX_OBJS) $(CU_OBJS) +# example objects +EXAMPLE_OBJS := $(addprefix $(BUILD_DIR)/, ${EXAMPLE_SRCS:.cpp=.o}) +# Output files for automatic dependency generation +DEPS := ${EXAMPLE_OBJS:.o=.d} ${CXX_OBJS:.o=.d} ${CU_OBJS:.o=.d} +EXAMPLE_BINS := ${EXAMPLE_OBJS:.o=.bin} + +############################## +# Derive compiler warning dump locations +############################## +WARNS_EXT := warnings.txt +CXX_WARNS := $(addprefix $(BUILD_DIR)/, ${CXX_SRCS:.cpp=.o.$(WARNS_EXT)}) +CU_WARNS := $(addprefix $(BUILD_DIR)/cuda/, ${CU_SRCS:.cu=.o.$(WARNS_EXT)}) +EXAMPLE_WARNS := $(addprefix $(BUILD_DIR)/, ${EXAMPLE_SRCS:.cpp=.o.$(WARNS_EXT)}) +ALL_CXX_WARNS := $(CXX_WARNS) $(EXAMPLE_WARNS) +ALL_CU_WARNS := $(CU_WARNS) +ALL_WARNS := $(ALL_CXX_WARNS) $(ALL_CU_WARNS) + +EMPTY_WARN_REPORT := $(BUILD_DIR)/.$(WARNS_EXT) +NONEMPTY_WARN_REPORT := $(BUILD_DIR)/$(WARNS_EXT) + +############################## +# Derive include and lib directories +############################## +CUDA_INCLUDE_DIR := $(CUDA_DIR)/include + +CUDA_LIB_DIR := +# add /lib64 only if it exists +ifneq ("$(wildcard $(CUDA_DIR)/lib64)","") + CUDA_LIB_DIR += $(CUDA_DIR)/lib64 +endif +CUDA_LIB_DIR += $(CUDA_DIR)/lib + +INCLUDE_DIRS += $(BUILD_INCLUDE_DIR) ./src ./include +ifeq ($(USE_CUDA), 1) + INCLUDE_DIRS += $(CUDA_INCLUDE_DIR) + LIBRARY_DIRS += $(CUDA_LIB_DIR) + LIBRARIES += cudart cublas curand +endif + +LIBRARIES += glog gflags m hdf5_hl hdf5 + +# handle IO dependencies +USE_LEVELDB ?= 1 +USE_LMDB ?= 1 +USE_OPENCV ?= 1 + +ifeq ($(USE_LEVELDB), 1) + LIBRARIES += leveldb snappy +endif +ifeq ($(USE_LMDB), 1) + LIBRARIES += lmdb +endif +ifeq ($(USE_OPENCV), 1) + LIBRARIES += opencv_core opencv_highgui opencv_imgproc opencv_objdetect opencv_video opencv_calib3d + + ifeq ($(OPENCV_VERSION), 3) + LIBRARIES += opencv_imgcodecs opencv_videoio + # Cuda warping removed for TX2 compatibility (PR #989) + # LIBRARIES += opencv_imgcodecs opencv_videoio opencv_cudawarping + else + LIBRARIES += opencv_contrib opencv_gpu + endif + +endif +############################## +# OpenPose extra code: commented +############################## +# WARNINGS := -Wall -Wno-sign-compare + +############################## +# Set build directories +############################## + +DISTRIBUTE_DIR ?= distribute +DISTRIBUTE_SUBDIRS := $(DISTRIBUTE_DIR)/bin $(DISTRIBUTE_DIR)/lib +DIST_ALIASES := dist +ifneq ($(strip $(DISTRIBUTE_DIR)),distribute) + DIST_ALIASES += distribute +endif + +ALL_BUILD_DIRS := $(sort $(BUILD_DIR) $(addprefix $(BUILD_DIR)/, $(SRC_DIRS)) \ + $(addprefix $(BUILD_DIR)/cuda/, $(SRC_DIRS)) \ + $(LIB_BUILD_DIR) $(LINT_OUTPUT_DIR)) + +############################## +# Set directory for Doxygen-generated documentation +############################## +DOXYGEN_CONFIG_FILE ?= ./.Doxyfile +# should be the same as OUTPUT_DIRECTORY in the .Doxyfile +DOXYGEN_OUTPUT_DIR ?= ./doxygen +DOXYGEN_COMMAND ?= doxygen +# All the files that might have Doxygen documentation. +DOXYGEN_SOURCES := $(shell find \ + src/$(PROJECT) \ + include/$(PROJECT) \ + examples \ + -name "*.cpp" -or -name "*.hpp" -or -name "*.cu" -or -name "*.cuh") +DOXYGEN_SOURCES += $(DOXYGEN_CONFIG_FILE) + + +############################## +# OpenPose extra code: added flags +############################## +# Automatic dependency generation (nvcc is handled separately) +CXXFLAGS += -march=native + +# Complete build flags. +CXXFLAGS += -fopenmp -Wpedantic -Wall -Wextra +CXXFLAGS += -Wfatal-errors +COMMON_FLAGS += -std=c++11 +LINKFLAGS += -fopenmp + + +############################## +# Configure build +############################## + +# Determine platform +UNAME := $(shell uname -s) +ifeq ($(UNAME), Linux) + LINUX := 1 +else ifeq ($(UNAME), Darwin) + OSX := 1 + OSX_MAJOR_VERSION := $(shell sw_vers -productVersion | cut -f 1 -d .) + OSX_MINOR_VERSION := $(shell sw_vers -productVersion | cut -f 2 -d .) +endif + +# Linux +ifeq ($(LINUX), 1) + CXX ?= /usr/bin/g++ + GCCVERSION := $(shell $(CXX) -dumpversion | cut -f1,2 -d.) + # We will also explicitly add stdc++ to the link target. + LIBRARIES += stdc++ + VERSIONFLAGS += -Wl,-soname,$(DYNAMIC_VERSIONED_NAME_SHORT) -Wl,-rpath,$(ORIGIN)/../lib +endif + +# OS X: +# clang++ instead of g++ +# libstdc++ for NVCC compatibility on OS X >= 10.9 with CUDA < 7.0 +ifeq ($(OSX), 1) + CXX := /usr/bin/clang++ + ifeq ($(USE_CUDA), 1) + CUDA_VERSION := $(shell $(CUDA_DIR)/bin/nvcc -V | grep -o 'release [0-9.]*' | tr -d '[a-z ]') + ifeq ($(shell echo | awk '{exit $(CUDA_VERSION) < 7.0;}'), 1) + CXXFLAGS += -stdlib=libstdc++ + LINKFLAGS += -stdlib=libstdc++ + endif + # clang throws this warning for cuda headers + WARNINGS += -Wno-unneeded-internal-declaration + # 10.11 strips DYLD_* env vars so link CUDA (rpath is available on 10.5+) + OSX_10_OR_LATER := $(shell [ $(OSX_MAJOR_VERSION) -ge 10 ] && echo true) + OSX_10_5_OR_LATER := $(shell [ $(OSX_MINOR_VERSION) -ge 5 ] && echo true) + ifeq ($(OSX_10_OR_LATER),true) + ifeq ($(OSX_10_5_OR_LATER),true) + LDFLAGS += -Wl,-rpath,$(CUDA_LIB_DIR) + endif + endif + endif + # we need to explicitly ask for the rpath to be obeyed + ORIGIN := @loader_path + VERSIONFLAGS += -Wl,-install_name,@rpath/$(DYNAMIC_VERSIONED_NAME_SHORT) -Wl,-rpath,$(ORIGIN)/../../build/lib +else + ORIGIN := \$$ORIGIN +endif + +# Custom compiler +ifdef CUSTOM_CXX + CXX := $(CUSTOM_CXX) +endif + +# Static linking +ifneq (,$(findstring clang++,$(CXX))) + STATIC_LINK_COMMAND := -Wl,-force_load $(STATIC_NAME) +else ifneq (,$(findstring g++,$(CXX))) + STATIC_LINK_COMMAND := -Wl,--whole-archive $(STATIC_NAME) -Wl,--no-whole-archive +else + # The following line must not be indented with a tab, since we are not inside a target + $(error Cannot static link with the $(CXX) compiler) +endif + +# Debugging +ifeq ($(DEBUG), 1) + COMMON_FLAGS += -DDEBUG -g -O0 + NVCCFLAGS += -G +else + COMMON_FLAGS += -DNDEBUG -O3 +endif + +# configure IO libraries +ifeq ($(USE_OPENCV), 1) + COMMON_FLAGS += -DUSE_OPENCV +endif +ifeq ($(USE_LEVELDB), 1) + COMMON_FLAGS += -DUSE_LEVELDB +endif +ifeq ($(USE_LMDB), 1) + COMMON_FLAGS += -DUSE_LMDB +ifeq ($(ALLOW_LMDB_NOLOCK), 1) + COMMON_FLAGS += -DALLOW_LMDB_NOLOCK +endif +endif + +# CPU-only configuration +ifeq ($(USE_CUDA), 1) + COMMON_FLAGS += -DUSE_CUDA +else + COMMON_FLAGS += -DCPU_ONLY # For Caffe + COMMON_FLAGS += -DUSE_CPU_ONLY +endif + +LIBRARY_DIRS += $(LIB_BUILD_DIR) + +# Automatic dependency generation (nvcc is handled separately) +CXXFLAGS += -MMD -MP + +# Complete build flags. +COMMON_FLAGS += $(foreach includedir,$(INCLUDE_DIRS),-I$(includedir)) +CXXFLAGS += -pthread -fPIC $(COMMON_FLAGS) $(WARNINGS) +NVCCFLAGS += -ccbin=$(CXX) -Xcompiler -fPIC $(COMMON_FLAGS) +LINKFLAGS += -pthread -fPIC $(COMMON_FLAGS) $(WARNINGS) + +USE_PKG_CONFIG ?= 0 +ifeq ($(USE_PKG_CONFIG), 1) + PKG_CONFIG := $(shell pkg-config opencv --libs) +else + PKG_CONFIG := +endif +LDFLAGS += $(foreach librarydir,$(LIBRARY_DIRS),-L$(librarydir)) $(PKG_CONFIG) \ + $(foreach library,$(LIBRARIES),-l$(library)) + +############################## +# Define build targets +############################## +.PHONY: all lib clean docs linecount lint lintclean examples $(DIST_ALIASES) \ + warn everything + +all: lib examples + +lib: $(STATIC_NAME) $(DYNAMIC_NAME) + +everything: $(EVERYTHING_TARGETS) + +linecount: + cloc --read-lang-def=$(PROJECT).cloc \ + src/$(PROJECT) include/$(PROJECT) examples + +lint: $(EMPTY_LINT_REPORT) + +lintclean: + @ $(RM) -r $(LINT_OUTPUT_DIR) $(EMPTY_LINT_REPORT) $(NONEMPTY_LINT_REPORT) + +docs: $(DOXYGEN_OUTPUT_DIR) + @ cd ./docs ; ln -sfn ../$(DOXYGEN_OUTPUT_DIR)/html doxygen + +$(DOXYGEN_OUTPUT_DIR): $(DOXYGEN_CONFIG_FILE) $(DOXYGEN_SOURCES) + $(DOXYGEN_COMMAND) $(DOXYGEN_CONFIG_FILE) + +$(EMPTY_LINT_REPORT): $(LINT_OUTPUTS) | $(BUILD_DIR) + @ cat $(LINT_OUTPUTS) > $@ + @ if [ -s "$@" ]; then \ + cat $@; \ + mv $@ $(NONEMPTY_LINT_REPORT); \ + echo "Found one or more lint errors."; \ + exit 1; \ + fi; \ + $(RM) $(NONEMPTY_LINT_REPORT); \ + echo "No lint errors!"; + +$(LINT_OUTPUTS): $(LINT_OUTPUT_DIR)/%.lint.txt : % $(LINT_SCRIPT) | $(LINT_OUTPUT_DIR) + @ mkdir -p $(dir $@) + @ python $(LINT_SCRIPT) $< 2>&1 \ + | grep -v "^Done processing " \ + | grep -v "^Total errors found: 0" \ + > $@ \ + || true + +examples: $(EXAMPLE_BINS) + +warn: $(EMPTY_WARN_REPORT) + +$(EMPTY_WARN_REPORT): $(ALL_WARNS) | $(BUILD_DIR) + @ cat $(ALL_WARNS) > $@ + @ if [ -s "$@" ]; then \ + cat $@; \ + mv $@ $(NONEMPTY_WARN_REPORT); \ + echo "Compiler produced one or more warnings."; \ + exit 1; \ + fi; \ + $(RM) $(NONEMPTY_WARN_REPORT); \ + echo "No compiler warnings!"; + +$(ALL_WARNS): %.o.$(WARNS_EXT) : %.o + +$(BUILD_DIR_LINK): $(BUILD_DIR)/.linked + +# Create a target ".linked" in this BUILD_DIR to tell Make that the "build" link +# is currently correct, then delete the one in the OTHER_BUILD_DIR in case it +# exists and $(DEBUG) is toggled later. +$(BUILD_DIR)/.linked: + @ mkdir -p $(BUILD_DIR) + @ $(RM) $(OTHER_BUILD_DIR)/.linked + @ $(RM) -r $(BUILD_DIR_LINK) + @ ln -s $(BUILD_DIR) $(BUILD_DIR_LINK) + @ touch $@ + +$(ALL_BUILD_DIRS): | $(BUILD_DIR_LINK) + @ mkdir -p $@ + +$(DYNAMIC_NAME): $(OBJS) | $(LIB_BUILD_DIR) + @ echo LD -o $@ + $(Q)$(CXX) -shared -o $@ $(OBJS) $(VERSIONFLAGS) $(LINKFLAGS) $(LDFLAGS) + @ cd $(LIB_BUILD_DIR); rm -f $(DYNAMIC_NAME_SHORT); ln -s $(DYNAMIC_VERSIONED_NAME_SHORT) $(DYNAMIC_NAME_SHORT) + +$(STATIC_NAME): $(OBJS) | $(LIB_BUILD_DIR) + @ echo AR -o $@ + $(Q)ar rcs $@ $(OBJS) + +$(BUILD_DIR)/%.o: %.cpp | $(ALL_BUILD_DIRS) + @ echo CXX $< + $(Q)$(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \ + || (cat $@.$(WARNS_EXT); exit 1) + @ cat $@.$(WARNS_EXT) + +$(BUILD_DIR)/cuda/%.o: %.cu | $(ALL_BUILD_DIRS) + @ echo NVCC $< + $(Q)$(CUDA_DIR)/bin/nvcc $(NVCCFLAGS) $(CUDA_ARCH) -M $< -o ${@:.o=.d} \ + -odir $(@D) + $(Q)$(CUDA_DIR)/bin/nvcc $(NVCCFLAGS) $(CUDA_ARCH) -c $< -o $@ 2> $@.$(WARNS_EXT) \ + || (cat $@.$(WARNS_EXT); exit 1) + @ cat $@.$(WARNS_EXT) + +$(EXAMPLE_BINS): %.bin : %.o | $(DYNAMIC_NAME) + @ echo CXX/LD -o $@ + $(Q)$(CXX) $< -o $@ $(LINKFLAGS) -l$(LIBRARY_NAME) $(LDFLAGS) \ + -Wl,-rpath,$(ORIGIN)/../../lib + +clean: + @- $(RM) -rf $(ALL_BUILD_DIRS) + @- $(RM) -rf $(OTHER_BUILD_DIR) + @- $(RM) -rf $(BUILD_DIR_LINK) + @- $(RM) -rf $(DISTRIBUTE_DIR) + +$(DIST_ALIASES): $(DISTRIBUTE_DIR) + +$(DISTRIBUTE_DIR): all + @ mkdir -p $(DISTRIBUTE_SUBDIRS) + # add include + cp -r include $(DISTRIBUTE_DIR)/ + # add example binaries + cp $(EXAMPLE_BINS) $(DISTRIBUTE_DIR)/bin + # add libraries + cp $(STATIC_NAME) $(DISTRIBUTE_DIR)/lib + install -m 644 $(DYNAMIC_NAME) $(DISTRIBUTE_DIR)/lib + cd $(DISTRIBUTE_DIR)/lib; rm -f $(DYNAMIC_NAME_SHORT); ln -s $(DYNAMIC_VERSIONED_NAME_SHORT) $(DYNAMIC_NAME_SHORT) + +-include $(DEPS) diff --git a/openpose/scripts/ubuntu/install_caffe_and_openpose_JetsonTX2_JetPack3.1.sh b/openpose/scripts/ubuntu/install_caffe_and_openpose_JetsonTX2_JetPack3.1.sh new file mode 100644 index 0000000000000000000000000000000000000000..0f042c3ee08e0e1a96a4a68ef975a5a8ea8a6d91 --- /dev/null +++ b/openpose/scripts/ubuntu/install_caffe_and_openpose_JetsonTX2_JetPack3.1.sh @@ -0,0 +1,50 @@ +#!/bin/bash + + + +echo "------------------------- Installing Caffe and OpenPose -------------------------" +echo "NOTE: This script assumes that just flashed JetPack 3.1 : Ubuntu 16, CUDA 8, cuDNN 6 and OpenCV are already installed on your machine. Otherwise, it might fail." + + + +function exitIfError { + if [[ $? -ne 0 ]] ; then + echo "" + echo "------------------------- -------------------------" + echo "Errors detected. Exiting script. The software might have not been successfully installed." + echo "------------------------- -------------------------" + exit 1 + fi +} + + + +function executeShInItsFolder { + # $1 = sh file name + # $2 = folder where the sh file is + # $3 = folder to go back + cd $2 + exitIfError + sudo chmod +x $1 + exitIfError + bash ./$1 + exitIfError + cd $3 + exitIfError +} + + + +git submodule update --init --recursive --remote +executeShInItsFolder "install_caffe_JetsonTX2_JetPack3.1.sh" "./3rdparty/caffe" "../.." +exitIfError + + + +executeShInItsFolder "install_openpose_JetsonTX2_JetPack3.1.sh" "./scripts/ubuntu/" "./" +exitIfError + + + +echo "------------------------- Caffe and OpenPose Installed -------------------------" +echo "" diff --git a/openpose/scripts/ubuntu/install_caffe_and_openpose_JetsonTX2_JetPack3.3.sh b/openpose/scripts/ubuntu/install_caffe_and_openpose_JetsonTX2_JetPack3.3.sh new file mode 100644 index 0000000000000000000000000000000000000000..7974085ed1ce5f02121d2d2fc45ec637b28d9aa2 --- /dev/null +++ b/openpose/scripts/ubuntu/install_caffe_and_openpose_JetsonTX2_JetPack3.3.sh @@ -0,0 +1,51 @@ +#!/bin/bash + + + +echo "------------------------- Installing Caffe and OpenPose -------------------------" +echo "NOTE: This script assumes that just flashed JetPack 3.3 : Ubuntu 16, CUDA 9, cuDNN 7 and OpenCV are already installed on your machine. Otherwise, it might fail." + + + +function exitIfError { + if [[ $? -ne 0 ]] ; then + echo "" + echo "------------------------- -------------------------" + echo "Errors detected. Exiting script. The software might have not been successfully installed." + echo "------------------------- -------------------------" + exit 1 + fi +} + + + +function executeShInItsFolder { + # $1 = sh file name + # $2 = folder where the sh file is + # $3 = folder to go back + cd $2 + exitIfError + sudo chmod +x $1 + exitIfError + bash ./$1 + exitIfError + cd $3 + exitIfError +} + + + +rm -rf ./3rdparty/caffe && mkdir ./3rdparty/caffe +git submodule update --init --recursive --remote +executeShInItsFolder "install_caffe_JetsonTX2_JetPack3.3.sh" "./3rdparty/caffe" "../.." +exitIfError + + + +executeShInItsFolder "./scripts/ubuntu/install_openpose_JetsonTX2_JetPack3.3.sh" "./" "./" +exitIfError + + + +echo "------------------------- Caffe and OpenPose Installed -------------------------" +echo "" diff --git a/openpose/scripts/ubuntu/install_cuda.sh b/openpose/scripts/ubuntu/install_cuda.sh new file mode 100644 index 0000000000000000000000000000000000000000..907673e5f67301f89ebafb3dda78de551a2b1448 --- /dev/null +++ b/openpose/scripts/ubuntu/install_cuda.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +echo "NOTE: This script assumes Ubuntu 20 or 18 (Nvidia Graphics card >= 10XX), as well as 16 or 14 (card up to 10XX)." +echo "Otherwise, install it by yourself or it might fail." + +if [[ $CI == true ]]; then + WGET_VERBOSE="--no-verbose" +fi + +# Install CUDA 8.0 +UBUNTU_VERSION="$(lsb_release -r)" +sudo apt-get update && sudo apt-get install wget -y --no-install-recommends +if [[ $UBUNTU_VERSION == *"14."* ]]; then + CUDA_LINK=https://developer.nvidia.com/compute/cuda/8.0/Prod2/local_installers/cuda-repo-ubuntu1404-8-0-local-ga2_8.0.61-1_amd64-deb + echo "wget -c \"$CUDA_LINK\" ${WGET_VERBOSE}" + wget -c "$CUDA_LINK" ${WGET_VERBOSE} + sudo dpkg --install cuda-repo-ubuntu1404-8-0-local-ga2_8.0.61-1_amd64-deb + sudo apt-get update + sudo apt-get install cuda-8-0 +elif [[ $UBUNTU_VERSION == *"16."* ]]; then + CUDA_LINK=https://developer.nvidia.com/compute/cuda/8.0/Prod2/local_installers/cuda-repo-ubuntu1604-8-0-local-ga2_8.0.61-1_amd64-deb + echo "wget -c \"$CUDA_LINK\" ${WGET_VERBOSE}" + wget -c "$CUDA_LINK" ${WGET_VERBOSE} + sudo dpkg --install cuda-repo-ubuntu1604-8-0-local-ga2_8.0.61-1_amd64-deb + sudo apt-get update + sudo apt-get install cuda-8-0 +# Install CUDA 10.0 +elif [[ $UBUNTU_VERSION == *"18."* ]]; then + CUDA_PIN_LINK=https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin + CUDA_LINK=http://developer.download.nvidia.com/compute/cuda/10.2/Prod/local_installers/cuda-repo-ubuntu1804-10-2-local-10.2.89-440.33.01_1.0-1_amd64.deb + echo "wget -c \"$CUDA_PIN_LINK\" ${WGET_VERBOSE}" + wget -c "$CUDA_PIN_LINK" ${WGET_VERBOSE} + sudo mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600 + echo "wget \"$CUDA_LINK\" ${WGET_VERBOSE}" + wget "$CUDA_LINK" ${WGET_VERBOSE} + sudo dpkg -i cuda-repo-ubuntu1804-10-2-local-10.2.89-440.33.01_1.0-1_amd64.deb + sudo apt-key add /var/cuda-repo-10-2-local-10.2.89-440.33.01/7fa2af80.pub + sudo apt-get update + sudo apt-get -y install cuda +# Install CUDA 11.0 +elif [[ $UBUNTU_VERSION == *"20."* ]]; then + CUDA_PIN_LINK=https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin + CUDA_LINK=https://developer.download.nvidia.com/compute/cuda/11.0.3/local_installers/cuda-repo-ubuntu2004-11-0-local_11.0.3-450.51.06-1_amd64.deb + echo "wget -c \"$CUDA_PIN_LINK\" ${WGET_VERBOSE}" + wget -c "$CUDA_PIN_LINK" ${WGET_VERBOSE} + sudo mv cuda-ubuntu2004.pin /etc/apt/preferences.d/cuda-repository-pin-600 + echo "wget \"$CUDA_LINK\" ${WGET_VERBOSE}" + wget "$CUDA_LINK" ${WGET_VERBOSE} + sudo dpkg -i cuda-repo-ubuntu2004-11-0-local_11.0.3-450.51.06-1_amd64.deb + sudo apt-key add /var/cuda-repo-ubuntu2004-11-0-local/7fa2af80.pub + sudo apt-get update + sudo apt-get -y install cuda +fi +# sudo apt-get install cuda diff --git a/openpose/scripts/ubuntu/install_cudnn_up_to_Ubuntu16.sh b/openpose/scripts/ubuntu/install_cudnn_up_to_Ubuntu16.sh new file mode 100644 index 0000000000000000000000000000000000000000..cb44048c7b87284ff952e8d199c1970b1f478c0d --- /dev/null +++ b/openpose/scripts/ubuntu/install_cudnn_up_to_Ubuntu16.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +echo "This script assumes Ubuntu 16 or 14 and Nvidia Graphics card up to 10XX. Otherwise, it will fail." + +if [[ $CI == true ]]; then + WGET_VERBOSE="--no-verbose" +fi + +# Install cuDNN 5.1 +UBUNTU_VERSION="$(lsb_release -r)" +if [[ $UBUNTU_VERSION == *"14."* ]] || [[ $UBUNTU_VERSION == *"15."* ]] || [[ $UBUNTU_VERSION == *"16."* ]]; then + CUDNN_URL="http://developer.download.nvidia.com/compute/redist/cudnn/v5.1/cudnn-8.0-linux-x64-v5.1.tgz" + echo "wget -c ${CUDNN_URL} ${WGET_VERBOSE}" + wget -c ${CUDNN_URL} ${WGET_VERBOSE} + sudo tar -xzf cudnn-8.0-linux-x64-v5.1.tgz -C /usr/local + rm cudnn-8.0-linux-x64-v5.1.tgz && sudo ldconfig +else + echo "cuDNN NOT INSTALLED! Ubuntu 16 or 14 not found. Install cuDNN manually from 'https://developer.nvidia.com/cudnn'." +fi diff --git a/openpose/scripts/ubuntu/install_deps.sh b/openpose/scripts/ubuntu/install_deps.sh new file mode 100644 index 0000000000000000000000000000000000000000..440abfae1229567222a9a6efdb387312ee680034 --- /dev/null +++ b/openpose/scripts/ubuntu/install_deps.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +### INSTALL PREREQUISITES + +UBUNTU_VERSION="$(lsb_release -r)" + +# Basic +sudo apt-get --assume-yes update +sudo apt-get --assume-yes install build-essential +# General dependencies +sudo apt-get --assume-yes install libatlas-base-dev libprotobuf-dev libleveldb-dev libsnappy-dev libhdf5-serial-dev protobuf-compiler +sudo apt-get --assume-yes install --no-install-recommends libboost-all-dev +# Remaining dependencies +sudo apt-get --assume-yes install libgflags-dev libgoogle-glog-dev +# LMDB is needed for Caffe training, but very likely not for inference-only +sudo apt-get --assume-yes install liblmdb-dev + +# Python2 libs (Official Ubuntu support dropped after Ubuntu 20) +if [[ $UBUNTU_VERSION == *"14."* ]] || [[ $UBUNTU_VERSION == *"15."* ]] || [[ $UBUNTU_VERSION == *"16."* ]] || [[ $UBUNTU_VERSION == *"17."* ]] || [[ $UBUNTU_VERSION == *"18."* ]]; then + echo "Installing Python2 libs..." + sudo apt-get --assume-yes install python-setuptools python-dev build-essential + hash pip2 2> /dev/null || sudo apt-get --assume-yes install python-pip + sudo -H python2 -m pip install pip --upgrade + if [[ $CI == true ]]; then + sudo -H python2 -m pip install --upgrade "numpy<1.17" protobuf + python2 -m pip install --user "opencv-python<4.3" + else + sudo -H python2 -m pip install --upgrade "numpy<1.17" protobuf "opencv-python<4.3" + fi +fi +# Python3 libs +echo "Installing Python3 libs..." +sudo apt-get --assume-yes install python3-setuptools python3-dev build-essential +hash pip3 2> /dev/null || sudo apt-get --assume-yes install python3-pip +sudo -H python3 -m pip install pip --upgrade +if [[ $CI == true ]]; then + sudo -H python3 -m pip install --upgrade numpy protobuf + python3 -m pip install --user opencv-python +else + sudo -H python3 -m pip install --upgrade numpy protobuf opencv-python +fi + +# OpenCL Generic (Official OpenPose support dropped after Ubuntu 20) +if [[ $UBUNTU_VERSION == *"14."* ]] || [[ $UBUNTU_VERSION == *"15."* ]] || [[ $UBUNTU_VERSION == *"16."* ]] || [[ $UBUNTU_VERSION == *"17."* ]] || [[ $UBUNTU_VERSION == *"18."* ]]; then + sudo apt-get --assume-yes install opencl-headers ocl-icd-opencl-dev + sudo apt-get --assume-yes install libviennacl-dev +fi +# OpenCV 2.4 -> Added as option +# # sudo apt-get --assume-yes install libopencv-dev diff --git a/openpose/scripts/ubuntu/install_openpose_JetsonTX2_JetPack3.1.sh b/openpose/scripts/ubuntu/install_openpose_JetsonTX2_JetPack3.1.sh new file mode 100644 index 0000000000000000000000000000000000000000..320eab506ad2703a6a20d8fa6f21db90e21e923a --- /dev/null +++ b/openpose/scripts/ubuntu/install_openpose_JetsonTX2_JetPack3.1.sh @@ -0,0 +1,65 @@ +#!/bin/bash + + + +echo "------------------------- Installing OpenPose -------------------------" +echo "NOTE: This script assumes that just flashed JetPack 3.1 : Ubuntu 16, CUDA 8, cuDNN 6 and OpenCV are already installed on your machine. Otherwise, it might fail." + +function exitIfError { + if [[ $? -ne 0 ]] ; then + echo "" + echo "------------------------- -------------------------" + echo "Errors detected. Exiting script. The software might have not been successfully installed." + echo "------------------------- -------------------------" + exit 1 + fi +} + + + +function executeShInItsFolder { + # $1 = sh file name + # $2 = folder where the sh file is + # $3 = folder to go back + cd $2 + exitIfError + sudo chmod +x $1 + exitIfError + bash ./$1 + exitIfError + cd $3 + exitIfError +} + + + +echo "------------------------- Checking Ubuntu Version -------------------------" +# If you respected the installation assumptions, nothing to do. +echo "------------------------- Ubuntu Version Checked -------------------------" +echo "" + + + +echo "------------------------- Compiling OpenPose -------------------------" +# Copy Makefile & Makefile.config +cp scripts/ubuntu/Makefile.example Makefile +cp scripts/ubuntu/Makefile.config.Ubuntu16_cuda8_JetsonTX2 Makefile.config +# Compile OpenPose +make all -j`nproc` +exitIfError +echo "------------------------- OpenPose Compiled -------------------------" +echo "" + + + +echo "------------------------- Downloading OpenPose Models -------------------------" +executeShInItsFolder "getModels.sh" "./models" ".." +exitIfError +echo "Models downloaded" +echo "------------------------- OpenPose Models Downloaded -------------------------" +echo "" + + + +echo "------------------------- OpenPose Installed -------------------------" +echo "" diff --git a/openpose/scripts/ubuntu/install_openpose_JetsonTX2_JetPack3.3.sh b/openpose/scripts/ubuntu/install_openpose_JetsonTX2_JetPack3.3.sh new file mode 100644 index 0000000000000000000000000000000000000000..91124a7f803bf1f00768083efe8707bd1180d480 --- /dev/null +++ b/openpose/scripts/ubuntu/install_openpose_JetsonTX2_JetPack3.3.sh @@ -0,0 +1,58 @@ +#!/bin/bash + + + +echo "------------------------- Installing OpenPose -------------------------" +echo "NOTE: This script assumes that just flashed JetPack 3.3 : Ubuntu 16, CUDA 9, cuDNN 7 and OpenCV are already installed on your machine. Otherwise, it might fail." + +function exitIfError { + if [[ $? -ne 0 ]] ; then + echo "" + echo "------------------------- -------------------------" + echo "Errors detected. Exiting script. The software might have not been successfully installed." + echo "------------------------- -------------------------" + exit 1 + fi +} + + + +function executeShInItsFolder { + # $1 = sh file name + # $2 = folder where the sh file is + # $3 = folder to go back + cd $2 + exitIfError + sudo chmod +x $1 + exitIfError + bash ./$1 + exitIfError + cd $3 + exitIfError +} + + + +echo "------------------------- Compiling OpenPose -------------------------" +# Copy Makefile & Makefile.config +cp scripts/ubuntu/Makefile.example Makefile +cp scripts/ubuntu/Makefile.config.Ubuntu16_cuda9_JetsonTX2_JetPack33 Makefile.config +# Compile OpenPose +make all -j`nproc` +exitIfError +echo "------------------------- OpenPose Compiled -------------------------" +echo "" + + + +echo "------------------------- Downloading OpenPose Models -------------------------" +executeShInItsFolder "getModels.sh" "./models" ".." +exitIfError +echo "Models downloaded" +echo "------------------------- OpenPose Models Downloaded -------------------------" +echo "" + + + +echo "------------------------- OpenPose Installed -------------------------" +echo "" diff --git a/openpose/scripts/ubuntu_deprecated/Makefile.config.Ubuntu14_cuda7.example b/openpose/scripts/ubuntu_deprecated/Makefile.config.Ubuntu14_cuda7.example new file mode 100644 index 0000000000000000000000000000000000000000..0003b9863e9d7e21f22da06af57ade20873c9d10 --- /dev/null +++ b/openpose/scripts/ubuntu_deprecated/Makefile.config.Ubuntu14_cuda7.example @@ -0,0 +1,91 @@ +## Refer to http://caffe.berkeleyvision.org/installation.html +# Contributions simplifying and improving our build system are welcome! + +# CPU-only switch (comment to build without GPU support). +USE_CUDA := 1 + +# uncomment to disable IO dependencies and corresponding data layers +# USE_OPENCV := 0 +# USE_LEVELDB := 0 +# USE_LMDB := 0 + +# uncomment to allow MDB_NOLOCK when reading LMDB files (only if necessary) +# You should not set this flag if you will be reading LMDBs with any +# possibility of simultaneous read and write +# ALLOW_LMDB_NOLOCK := 1 + +# Uncomment if you're using OpenCV 3 +# OPENCV_VERSION := 3 + +# To customize your choice of compiler, uncomment and set the following. +# N.B. the default for Linux is g++ and the default for OSX is clang++ +# CUSTOM_CXX := g++ + +# CUDA directory contains bin/ and lib/ directories that we need. +CUDA_DIR := /usr/local/cuda +# On Ubuntu 14.04, if cuda tools are installed via +# "sudo apt-get install nvidia-cuda-toolkit" then use this instead: +# CUDA_DIR := /usr + +# CUDA architecture setting: going with all of them. +# For CUDA < 6.0, comment the *_50 through *_61 lines for compatibility. +# For CUDA < 8.0, comment the *_60 and *_61 lines for compatibility. +# Architectures: +# http://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/ +CUDA_ARCH := -gencode arch=compute_30,code=sm_30 \ + -gencode arch=compute_35,code=sm_35 \ + -gencode arch=compute_50,code=sm_50 \ + -gencode arch=compute_52,code=sm_52 +# Deprecated +# CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \ +# -gencode arch=compute_20,code=sm_21 \ +# -gencode arch=compute_30,code=sm_30 \ +# -gencode arch=compute_35,code=sm_35 \ +# -gencode arch=compute_50,code=sm_50 \ +# -gencode arch=compute_52,code=sm_52 + +# Uncomment to enable op::Profiler +# PROFILER_ENABLED := 1 + +# DEEP_NET choice: +# caffe for Caffe (default and only option so far) +DEEP_NET := caffe + +# Caffe directory +CAFFE_DIR := 3rdparty/caffe/distribute + +# Faster GUI display +# WITH_OPENCV_WITH_OPENGL := 1 +# OpenPose 3-D Reconstruction +# WITH_3D_RENDERER := 1 +# WITH_CERES := 1 +# WITH_FLIR_CAMERA := 1 +# Eigen directory (Ceres) +# WITH_EIGEN := 1 +EIGEN_DIR := /usr/include/eigen3/ +# Spinnaker directory +SPINNAKER_DIR := /usr/include/spinnaker + +# Whatever else you find you need goes here. +INCLUDE_DIRS := /usr/local/include +LIBRARY_DIRS := /usr/local/lib /usr/lib + +# If Homebrew is installed at a non standard location (for example your home directory) and you use it for general dependencies +# INCLUDE_DIRS += $(shell brew --prefix)/include +# LIBRARY_DIRS += $(shell brew --prefix)/lib + +# Uncomment to use `pkg-config` to specify OpenCV library paths. +# (Usually not necessary -- OpenCV libraries are normally installed in one of the above $LIBRARY_DIRS.) +# USE_PKG_CONFIG := 1 + +BUILD_DIR := build +DISTRIBUTE_DIR := distribute + +# Uncomment for debugging. Does not work on OSX due to https://github.com/BVLC/caffe/issues/171 +# DEBUG := 1 + +# The ID of the GPU that 'make runtest' will use to run unit tests. +TEST_GPUID := 0 + +# enable pretty build (comment to see full commands) +Q ?= @ diff --git a/openpose/scripts/ubuntu_deprecated/Makefile.config.Ubuntu14_cuda8.example b/openpose/scripts/ubuntu_deprecated/Makefile.config.Ubuntu14_cuda8.example new file mode 100644 index 0000000000000000000000000000000000000000..5375fa8e93f45ce1d2f8487431eaeb30e8bb2b81 --- /dev/null +++ b/openpose/scripts/ubuntu_deprecated/Makefile.config.Ubuntu14_cuda8.example @@ -0,0 +1,95 @@ +## Refer to http://caffe.berkeleyvision.org/installation.html +# Contributions simplifying and improving our build system are welcome! + +# CPU-only switch (comment to build without GPU support). +USE_CUDA := 1 + +# uncomment to disable IO dependencies and corresponding data layers +# USE_OPENCV := 0 +# USE_LEVELDB := 0 +# USE_LMDB := 0 + +# uncomment to allow MDB_NOLOCK when reading LMDB files (only if necessary) +# You should not set this flag if you will be reading LMDBs with any +# possibility of simultaneous read and write +# ALLOW_LMDB_NOLOCK := 1 + +# Uncomment if you're using OpenCV 3 +# OPENCV_VERSION := 3 + +# To customize your choice of compiler, uncomment and set the following. +# N.B. the default for Linux is g++ and the default for OSX is clang++ +# CUSTOM_CXX := g++ + +# CUDA directory contains bin/ and lib/ directories that we need. +CUDA_DIR := /usr/local/cuda +# On Ubuntu 14.04, if cuda tools are installed via +# "sudo apt-get install nvidia-cuda-toolkit" then use this instead: +# CUDA_DIR := /usr + +# CUDA architecture setting: going with all of them. +# For CUDA < 6.0, comment the *_50 through *_61 lines for compatibility. +# For CUDA < 8.0, comment the *_60 and *_61 lines for compatibility. +CUDA_ARCH := -gencode arch=compute_30,code=sm_30 \ + -gencode arch=compute_35,code=sm_35 \ + -gencode arch=compute_50,code=sm_50 \ + -gencode arch=compute_52,code=sm_52 \ + -gencode arch=compute_60,code=sm_60 \ + -gencode arch=compute_61,code=sm_61 \ + -gencode arch=compute_61,code=compute_61 +# Deprecated +# CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \ +# -gencode arch=compute_20,code=sm_21 \ +# -gencode arch=compute_30,code=sm_30 \ +# -gencode arch=compute_35,code=sm_35 \ +# -gencode arch=compute_50,code=sm_50 \ +# -gencode arch=compute_52,code=sm_52 \ +# -gencode arch=compute_60,code=sm_60 \ +# -gencode arch=compute_61,code=sm_61 \ +# -gencode arch=compute_61,code=compute_61 + +# Uncomment to enable op::Profiler +# PROFILER_ENABLED := 1 + +# DEEP_NET choice: +# caffe for Caffe (default and only option so far) +DEEP_NET := caffe + +# Caffe directory +CAFFE_DIR := 3rdparty/caffe/distribute + +# Faster GUI display +# WITH_OPENCV_WITH_OPENGL := 1 +# OpenPose 3-D Reconstruction +# WITH_3D_RENDERER := 1 +# WITH_CERES := 1 +# WITH_FLIR_CAMERA := 1 +# Eigen directory (Ceres) +# WITH_EIGEN := 1 +EIGEN_DIR := /usr/include/eigen3/ +# Spinnaker directory +SPINNAKER_DIR := /usr/include/spinnaker + +# Whatever else you find you need goes here. +INCLUDE_DIRS := /usr/local/include +LIBRARY_DIRS := /usr/local/lib /usr/lib + +# If Homebrew is installed at a non standard location (for example your home directory) and you use it for general dependencies +# INCLUDE_DIRS += $(shell brew --prefix)/include +# LIBRARY_DIRS += $(shell brew --prefix)/lib + +# Uncomment to use `pkg-config` to specify OpenCV library paths. +# (Usually not necessary -- OpenCV libraries are normally installed in one of the above $LIBRARY_DIRS.) +# USE_PKG_CONFIG := 1 + +BUILD_DIR := build +DISTRIBUTE_DIR := distribute + +# Uncomment for debugging. Does not work on OSX due to https://github.com/BVLC/caffe/issues/171 +# DEBUG := 1 + +# The ID of the GPU that 'make runtest' will use to run unit tests. +TEST_GPUID := 0 + +# enable pretty build (comment to see full commands) +Q ?= @ diff --git a/openpose/scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda10.example b/openpose/scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda10.example new file mode 100644 index 0000000000000000000000000000000000000000..9af0eb15b3cb0d134e6ab2caebd38184ba44bca9 --- /dev/null +++ b/openpose/scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda10.example @@ -0,0 +1,91 @@ +## Refer to http://caffe.berkeleyvision.org/installation.html +# Contributions simplifying and improving our build system are welcome! + +# CPU-only switch (comment to build without GPU support). +USE_CUDA := 1 + +# uncomment to disable IO dependencies and corresponding data layers +# USE_OPENCV := 0 +# USE_LEVELDB := 0 +# USE_LMDB := 0 + +# uncomment to allow MDB_NOLOCK when reading LMDB files (only if necessary) +# You should not set this flag if you will be reading LMDBs with any +# possibility of simultaneous read and write +# ALLOW_LMDB_NOLOCK := 1 + +# Uncomment if you're using OpenCV 3 +# OPENCV_VERSION := 3 + +# To customize your choice of compiler, uncomment and set the following. +# N.B. the default for Linux is g++ and the default for OSX is clang++ +# CUSTOM_CXX := g++ + +# CUDA directory contains bin/ and lib/ directories that we need. +CUDA_DIR := /usr/local/cuda +# On Ubuntu 14.04, if cuda tools are installed via +# "sudo apt-get install nvidia-cuda-toolkit" then use this instead: +# CUDA_DIR := /usr + +# CUDA architecture setting: going with all of them. +# For CUDA < 6.0, comment the *_50 through *_61 lines for compatibility. +# For CUDA < 8.0, comment the *_60 and *_61 lines for compatibility. +# Architectures: +# http://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/ +CUDA_ARCH := -gencode arch=compute_30,code=sm_30 \ + -gencode arch=compute_35,code=sm_35 \ + -gencode arch=compute_50,code=sm_50 \ + -gencode arch=compute_52,code=sm_52 \ + -gencode arch=compute_60,code=sm_60 \ + -gencode arch=compute_61,code=sm_61 \ + -gencode arch=compute_62,code=sm_62 \ + -gencode arch=compute_70,code=sm_70 \ + -gencode arch=compute_72,code=sm_72 \ + -gencode arch=compute_75,code=sm_75 \ + -gencode arch=compute_75,code=compute_75 + +# Uncomment to enable op::Profiler +# PROFILER_ENABLED := 1 + +# DEEP_NET choice: +# caffe for Caffe (default and only option so far) +DEEP_NET := caffe + +# Caffe directory +CAFFE_DIR := 3rdparty/caffe/distribute + +# Faster GUI display +# WITH_OPENCV_WITH_OPENGL := 1 +# OpenPose 3-D Reconstruction +# WITH_3D_RENDERER := 1 +# WITH_CERES := 1 +# WITH_FLIR_CAMERA := 1 +# Eigen directory (Ceres) +# WITH_EIGEN := 1 +EIGEN_DIR := /usr/include/eigen3/ +# Spinnaker directory +SPINNAKER_DIR := /usr/include/spinnaker + +# Whatever else you find you need goes here. +INCLUDE_DIRS := /usr/local/include /usr/include/hdf5/serial +LIBRARY_DIRS := /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/hdf5/serial + +# If Homebrew is installed at a non standard location (for example your home directory) and you use it for general dependencies +# INCLUDE_DIRS += $(shell brew --prefix)/include +# LIBRARY_DIRS += $(shell brew --prefix)/lib + +# Uncomment to use `pkg-config` to specify OpenCV library paths. +# (Usually not necessary -- OpenCV libraries are normally installed in one of the above $LIBRARY_DIRS.) +# USE_PKG_CONFIG := 1 + +BUILD_DIR := build +DISTRIBUTE_DIR := distribute + +# Uncomment for debugging. Does not work on OSX due to https://github.com/BVLC/caffe/issues/171 +# DEBUG := 1 + +# The ID of the GPU that 'make runtest' will use to run unit tests. +TEST_GPUID := 0 + +# enable pretty build (comment to see full commands) +Q ?= @ diff --git a/openpose/scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda7.example b/openpose/scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda7.example new file mode 100644 index 0000000000000000000000000000000000000000..4ebca9054fc96c2e262417873ae6b8c0336df974 --- /dev/null +++ b/openpose/scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda7.example @@ -0,0 +1,89 @@ +## Refer to http://caffe.berkeleyvision.org/installation.html +# Contributions simplifying and improving our build system are welcome! + +# CPU-only switch (comment to build without GPU support). +USE_CUDA := 1 + +# uncomment to disable IO dependencies and corresponding data layers +# USE_OPENCV := 0 +# USE_LEVELDB := 0 +# USE_LMDB := 0 + +# uncomment to allow MDB_NOLOCK when reading LMDB files (only if necessary) +# You should not set this flag if you will be reading LMDBs with any +# possibility of simultaneous read and write +# ALLOW_LMDB_NOLOCK := 1 + +# Uncomment if you're using OpenCV 3 +# OPENCV_VERSION := 3 + +# To customize your choice of compiler, uncomment and set the following. +# N.B. the default for Linux is g++ and the default for OSX is clang++ +# CUSTOM_CXX := g++ + +# CUDA directory contains bin/ and lib/ directories that we need. +CUDA_DIR := /usr/local/cuda +# On Ubuntu 14.04, if cuda tools are installed via +# "sudo apt-get install nvidia-cuda-toolkit" then use this instead: +# CUDA_DIR := /usr + +# CUDA architecture setting: going with all of them. +# For CUDA < 6.0, comment the *_50 through *_61 lines for compatibility. +# For CUDA < 8.0, comment the *_60 and *_61 lines for compatibility. +CUDA_ARCH := -gencode arch=compute_30,code=sm_30 \ + -gencode arch=compute_35,code=sm_35 \ + -gencode arch=compute_50,code=sm_50 \ + -gencode arch=compute_52,code=sm_52 +# Deprecated +# CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \ +# -gencode arch=compute_20,code=sm_21 \ +# -gencode arch=compute_30,code=sm_30 \ +# -gencode arch=compute_35,code=sm_35 \ +# -gencode arch=compute_50,code=sm_50 \ +# -gencode arch=compute_52,code=sm_52 + +# Uncomment to enable op::Profiler +# PROFILER_ENABLED := 1 + +# DEEP_NET choice: +# caffe for Caffe (default and only option so far) +DEEP_NET := caffe + +# Caffe directory +CAFFE_DIR := 3rdparty/caffe/distribute + +# Faster GUI display +# WITH_OPENCV_WITH_OPENGL := 1 +# OpenPose 3-D Reconstruction +# WITH_3D_RENDERER := 1 +# WITH_CERES := 1 +# WITH_FLIR_CAMERA := 1 +# Eigen directory (Ceres) +# WITH_EIGEN := 1 +EIGEN_DIR := /usr/include/eigen3/ +# Spinnaker directory +SPINNAKER_DIR := /usr/include/spinnaker + +# Whatever else you find you need goes here. +INCLUDE_DIRS := /usr/local/include /usr/include/hdf5/serial +LIBRARY_DIRS := /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/hdf5/serial + +# If Homebrew is installed at a non standard location (for example your home directory) and you use it for general dependencies +# INCLUDE_DIRS += $(shell brew --prefix)/include +# LIBRARY_DIRS += $(shell brew --prefix)/lib + +# Uncomment to use `pkg-config` to specify OpenCV library paths. +# (Usually not necessary -- OpenCV libraries are normally installed in one of the above $LIBRARY_DIRS.) +# USE_PKG_CONFIG := 1 + +BUILD_DIR := build +DISTRIBUTE_DIR := distribute + +# Uncomment for debugging. Does not work on OSX due to https://github.com/BVLC/caffe/issues/171 +# DEBUG := 1 + +# The ID of the GPU that 'make runtest' will use to run unit tests. +TEST_GPUID := 0 + +# enable pretty build (comment to see full commands) +Q ?= @ diff --git a/openpose/scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda8.example b/openpose/scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda8.example new file mode 100644 index 0000000000000000000000000000000000000000..99807db016bae4b297a299c2ce306484f00e4137 --- /dev/null +++ b/openpose/scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda8.example @@ -0,0 +1,88 @@ +## Refer to http://caffe.berkeleyvision.org/installation.html +# Contributions simplifying and improving our build system are welcome! + +# CPU-only switch (comment to build without GPU support). +USE_CUDA := 1 + +# uncomment to disable IO dependencies and corresponding data layers +# USE_OPENCV := 0 +# USE_LEVELDB := 0 +# USE_LMDB := 0 + +# uncomment to allow MDB_NOLOCK when reading LMDB files (only if necessary) +# You should not set this flag if you will be reading LMDBs with any +# possibility of simultaneous read and write +# ALLOW_LMDB_NOLOCK := 1 + +# Uncomment if you're using OpenCV 3 +# OPENCV_VERSION := 3 + +# To customize your choice of compiler, uncomment and set the following. +# N.B. the default for Linux is g++ and the default for OSX is clang++ +# CUSTOM_CXX := g++ + +# CUDA directory contains bin/ and lib/ directories that we need. +CUDA_DIR := /usr/local/cuda +# On Ubuntu 14.04, if cuda tools are installed via +# "sudo apt-get install nvidia-cuda-toolkit" then use this instead: +# CUDA_DIR := /usr + +# CUDA architecture setting: going with all of them. +# For CUDA < 6.0, comment the *_50 through *_61 lines for compatibility. +# For CUDA < 8.0, comment the *_60 and *_61 lines for compatibility. +# Architectures: +# http://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/ +CUDA_ARCH := -gencode arch=compute_30,code=sm_30 \ + -gencode arch=compute_35,code=sm_35 \ + -gencode arch=compute_50,code=sm_50 \ + -gencode arch=compute_52,code=sm_52 \ + -gencode arch=compute_60,code=sm_60 \ + -gencode arch=compute_61,code=sm_61 \ + -gencode arch=compute_62,code=sm_62 \ + -gencode arch=compute_62,code=compute_62 + +# Uncomment to enable op::Profiler +# PROFILER_ENABLED := 1 + +# DEEP_NET choice: +# caffe for Caffe (default and only option so far) +DEEP_NET := caffe + +# Caffe directory +CAFFE_DIR := 3rdparty/caffe/distribute + +# Faster GUI display +# WITH_OPENCV_WITH_OPENGL := 1 +# OpenPose 3-D Reconstruction +# WITH_3D_RENDERER := 1 +# WITH_CERES := 1 +# WITH_FLIR_CAMERA := 1 +# Eigen directory (Ceres) +# WITH_EIGEN := 1 +EIGEN_DIR := /usr/include/eigen3/ +# Spinnaker directory +SPINNAKER_DIR := /usr/include/spinnaker + +# Whatever else you find you need goes here. +INCLUDE_DIRS := /usr/local/include /usr/include/hdf5/serial +LIBRARY_DIRS := /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/hdf5/serial + +# If Homebrew is installed at a non standard location (for example your home directory) and you use it for general dependencies +# INCLUDE_DIRS += $(shell brew --prefix)/include +# LIBRARY_DIRS += $(shell brew --prefix)/lib + +# Uncomment to use `pkg-config` to specify OpenCV library paths. +# (Usually not necessary -- OpenCV libraries are normally installed in one of the above $LIBRARY_DIRS.) +# USE_PKG_CONFIG := 1 + +BUILD_DIR := build +DISTRIBUTE_DIR := distribute + +# Uncomment for debugging. Does not work on OSX due to https://github.com/BVLC/caffe/issues/171 +# DEBUG := 1 + +# The ID of the GPU that 'make runtest' will use to run unit tests. +TEST_GPUID := 0 + +# enable pretty build (comment to see full commands) +Q ?= @ diff --git a/openpose/scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda9.example b/openpose/scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda9.example new file mode 100644 index 0000000000000000000000000000000000000000..43f21b711ef0baee9cac7fb7436b5ca8f24f0dcd --- /dev/null +++ b/openpose/scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda9.example @@ -0,0 +1,90 @@ +## Refer to http://caffe.berkeleyvision.org/installation.html +# Contributions simplifying and improving our build system are welcome! + +# CPU-only switch (comment to build without GPU support). +USE_CUDA := 1 + +# uncomment to disable IO dependencies and corresponding data layers +# USE_OPENCV := 0 +# USE_LEVELDB := 0 +# USE_LMDB := 0 + +# uncomment to allow MDB_NOLOCK when reading LMDB files (only if necessary) +# You should not set this flag if you will be reading LMDBs with any +# possibility of simultaneous read and write +# ALLOW_LMDB_NOLOCK := 1 + +# Uncomment if you're using OpenCV 3 +# OPENCV_VERSION := 3 + +# To customize your choice of compiler, uncomment and set the following. +# N.B. the default for Linux is g++ and the default for OSX is clang++ +# CUSTOM_CXX := g++ + +# CUDA directory contains bin/ and lib/ directories that we need. +CUDA_DIR := /usr/local/cuda +# On Ubuntu 14.04, if cuda tools are installed via +# "sudo apt-get install nvidia-cuda-toolkit" then use this instead: +# CUDA_DIR := /usr + +# CUDA architecture setting: going with all of them. +# For CUDA < 6.0, comment the *_50 through *_61 lines for compatibility. +# For CUDA < 8.0, comment the *_60 and *_61 lines for compatibility. +# Architectures: +# http://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/ +CUDA_ARCH := -gencode arch=compute_30,code=sm_30 \ + -gencode arch=compute_35,code=sm_35 \ + -gencode arch=compute_50,code=sm_50 \ + -gencode arch=compute_52,code=sm_52 \ + -gencode arch=compute_60,code=sm_60 \ + -gencode arch=compute_61,code=sm_61 \ + -gencode arch=compute_62,code=sm_62 \ + -gencode arch=compute_70,code=sm_70 \ + -gencode arch=compute_72,code=sm_72 \ + -gencode arch=compute_72,code=compute_72 + +# Uncomment to enable op::Profiler +# PROFILER_ENABLED := 1 + +# DEEP_NET choice: +# caffe for Caffe (default and only option so far) +DEEP_NET := caffe + +# Caffe directory +CAFFE_DIR := 3rdparty/caffe/distribute + +# Faster GUI display +# WITH_OPENCV_WITH_OPENGL := 1 +# OpenPose 3-D Reconstruction +# WITH_3D_RENDERER := 1 +# WITH_CERES := 1 +# WITH_FLIR_CAMERA := 1 +# Eigen directory (Ceres) +# WITH_EIGEN := 1 +EIGEN_DIR := /usr/include/eigen3/ +# Spinnaker directory +SPINNAKER_DIR := /usr/include/spinnaker + +# Whatever else you find you need goes here. +INCLUDE_DIRS := /usr/local/include /usr/include/hdf5/serial +LIBRARY_DIRS := /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/hdf5/serial + +# If Homebrew is installed at a non standard location (for example your home directory) and you use it for general dependencies +# INCLUDE_DIRS += $(shell brew --prefix)/include +# LIBRARY_DIRS += $(shell brew --prefix)/lib + +# Uncomment to use `pkg-config` to specify OpenCV library paths. +# (Usually not necessary -- OpenCV libraries are normally installed in one of the above $LIBRARY_DIRS.) +# USE_PKG_CONFIG := 1 + +BUILD_DIR := build +DISTRIBUTE_DIR := distribute + +# Uncomment for debugging. Does not work on OSX due to https://github.com/BVLC/caffe/issues/171 +# DEBUG := 1 + +# The ID of the GPU that 'make runtest' will use to run unit tests. +TEST_GPUID := 0 + +# enable pretty build (comment to see full commands) +Q ?= @ diff --git a/openpose/scripts/ubuntu_deprecated/copy_makefile_files.sh b/openpose/scripts/ubuntu_deprecated/copy_makefile_files.sh new file mode 100644 index 0000000000000000000000000000000000000000..47e575d61cd839847aff55b249ad384da5f425b7 --- /dev/null +++ b/openpose/scripts/ubuntu_deprecated/copy_makefile_files.sh @@ -0,0 +1,53 @@ +#!/bin/bash + + + +echo "------------------------- Preprocessing -------------------------" +echo "NOTE: This script assumes that CUDA and cuDNN are already installed on your machine. Otherwise, it might fail." + + + +function exitIfError { + if [[ $? -ne 0 ]] ; then + echo "" + echo "------------------------- -------------------------" + echo "Errors detected. Exiting script. The software might have not been successfully installed." + echo "------------------------- -------------------------" + exit 1 + fi +} + + + +echo "------------------------- Checking Ubuntu Version -------------------------" +ubuntu_version="$(lsb_release -r)" +echo "Ubuntu $ubuntu_version" +if [[ $ubuntu_version == *"14."* ]]; then + ubuntu_le_14=true +elif [[ $ubuntu_version == *"16."* || $ubuntu_version == *"15."* || $ubuntu_version == *"17."* || $ubuntu_version == *"18."* ]]; then + ubuntu_le_14=false +else + echo "Ubuntu release older than version 14. This installation script might fail." + ubuntu_le_14=true +fi +exitIfError +echo "------------------------- Ubuntu Version Checked -------------------------" +echo "" + + + +echo "------------------------- Copying Required Files -------------------------" +# Copy Makefile & Makefile.config +cp scripts/ubuntu/Makefile.example Makefile +if [[ $ubuntu_le_14 == true ]]; then + cp scripts/ubuntu_deprecated/Makefile.config.Ubuntu14_cuda8.example Makefile.config +else + cp scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda8.example Makefile.config +fi +exitIfError +echo "------------------------- Required Files Copied -------------------------" + + + +echo "------------------------- Preprocessing Ready -------------------------" +echo "" diff --git a/openpose/scripts/ubuntu_deprecated/install_caffe_and_openpose_if_cuda8.sh b/openpose/scripts/ubuntu_deprecated/install_caffe_and_openpose_if_cuda8.sh new file mode 100644 index 0000000000000000000000000000000000000000..a555b7d606098f9c86c10fab385e293fbded2810 --- /dev/null +++ b/openpose/scripts/ubuntu_deprecated/install_caffe_and_openpose_if_cuda8.sh @@ -0,0 +1,50 @@ +#!/bin/bash + + + +echo "------------------------- Installing Caffe and OpenPose -------------------------" +echo "NOTE: This script assumes that CUDA and cuDNN are already installed on your machine. Otherwise, it might fail." + + + +function exitIfError { + if [[ $? -ne 0 ]] ; then + echo "" + echo "------------------------- -------------------------" + echo "Errors detected. Exiting script. The software might have not been successfully installed." + echo "------------------------- -------------------------" + exit 1 + fi +} + + + +function executeShInItsFolder { + # $1 = sh file name + # $2 = folder where the sh file is + # $3 = folder to go back + cd $2 + exitIfError + sudo chmod +x $1 + exitIfError + bash ./$1 + exitIfError + cd $3 + exitIfError +} + + + +git submodule update --init --recursive --remote +executeShInItsFolder "install_caffe_if_cuda8.sh" "./3rdparty/caffe" "../.." +exitIfError + + + +executeShInItsFolder "./scripts/ubuntu_deprecated/install_openpose_if_cuda8.sh" "./" "./" +exitIfError + + + +echo "------------------------- Caffe and OpenPose Installed -------------------------" +echo "" diff --git a/openpose/scripts/ubuntu_deprecated/install_openpose_if_cuda8.sh b/openpose/scripts/ubuntu_deprecated/install_openpose_if_cuda8.sh new file mode 100644 index 0000000000000000000000000000000000000000..5ca876ab6420dd8d1819605fc5365e49b14c3f03 --- /dev/null +++ b/openpose/scripts/ubuntu_deprecated/install_openpose_if_cuda8.sh @@ -0,0 +1,59 @@ +#!/bin/bash + + + +echo "------------------------- Installing OpenPose -------------------------" + + + +function exitIfError { + if [[ $? -ne 0 ]] ; then + echo "" + echo "------------------------- -------------------------" + echo "Errors detected. Exiting script. The software might have not been successfully installed." + echo "------------------------- -------------------------" + exit 1 + fi +} + + + +function executeShInItsFolder { + # $1 = sh file name + # $2 = folder where the sh file is + # $3 = folder to go back + cd $2 + exitIfError + sudo chmod +x $1 + exitIfError + bash ./$1 + exitIfError + cd $3 + exitIfError +} + + + +executeShInItsFolder "scripts/ubuntu_deprecated/copy_makefile_files.sh" "./" "./" + + + +echo "------------------------- Compiling OpenPose -------------------------" +make all -j`nproc` +exitIfError +echo "------------------------- OpenPose Compiled -------------------------" +echo "" + + + +echo "------------------------- Downloading OpenPose Models -------------------------" +executeShInItsFolder "getModels.sh" "./models" ".." +exitIfError +echo "Models downloaded" +echo "------------------------- OpenPose Models Downloaded -------------------------" +echo "" + + + +echo "------------------------- OpenPose Installed -------------------------" +echo ""