From e8a4223d27ca951d73abbeafce34d75ff08f05f2 Mon Sep 17 00:00:00 2001 From: Gines Hidalgo Date: Thu, 25 May 2017 14:41:55 -0400 Subject: [PATCH] Ubuntu code compatible with Windows one --- doc/demo_overview.md | 32 ----------------- doc/installation.md | 42 ++++++++++++++++++++++- include/openpose/pose/poseParameters.hpp | 5 ++- include/openpose/producer/producer.hpp | 1 + include/openpose/thread/queueBase.hpp | 2 +- include/openpose/thread/threadManager.hpp | 8 ++--- src/openpose/core/nmsBase.cu | 4 +-- src/openpose/gui/guiInfoAdder.cpp | 3 +- src/openpose/pose/poseParameters.cpp | 15 ++++++++ src/openpose/pose/poseRenderGpu.cu | 4 ++- src/openpose/pose/poseRenderer.cpp | 7 ++-- src/openpose/utilities/profiler.cpp | 2 +- 12 files changed, 79 insertions(+), 46 deletions(-) diff --git a/doc/demo_overview.md b/doc/demo_overview.md index 34f431c8..eb1fe058 100644 --- a/doc/demo_overview.md +++ b/doc/demo_overview.md @@ -5,38 +5,6 @@ Forget about the OpenPose library code, just compile the library and use the dem In order to learn how to use it, run `./build/examples/openpose/openpose.bin --help` in your bash and read all the available flags (check only the flags for `examples/openpose/openpose.cpp` itself, i.e. the section `Flags from examples/openpose/openpose.cpp:`). We detail some of them in the following sections. -## Quick Start -Check that the library is working properly by using any of the following commands. Note that `examples/media/video.avi` and `examples/media` exist, so you do not need to change the paths. - -1. Running on Video -``` -./build/examples/openpose/openpose.bin --video examples/media/video.avi -``` - -2. Running on Webcam -``` -./build/examples/openpose/openpose.bin -``` - -3. Running on Images -``` -./build/examples/openpose/openpose.bin --image_dir examples/media/ -``` - -The visual GUI should show the original image with the poses blended on it, similarly to the pose of this gif: -

- -

- -If you choose to visualize a body part or a PAF (Part Affinity Field) heat map with the command option `--part_to_show`, the result should be similar to one of the following images: -

- -

- -

- -

- ## Other Important Options diff --git a/doc/installation.md b/doc/installation.md index aae4c6a1..075a5923 100644 --- a/doc/installation.md +++ b/doc/installation.md @@ -5,7 +5,7 @@ OpenPose Library - Compilation and Installation ## Requirements - Ubuntu (tested on 14 and 16) -- GPU with at least 2 GB and 1.5 GB available (the `nvidia-smi` command checks the available GPU memory in Ubuntu). +- GPU with at least 1.5 GB available (the `nvidia-smi` command checks the available GPU memory in Ubuntu). - CUDA and cuDNN installed. - At least 2 GB of free RAM memory. - Highly recommended: A CPU with at least 8 cores. @@ -80,3 +80,43 @@ make clean && cd 3rdparty/caffe && make clean ## Uninstallation You just need to remove the OpenPose folder, by default called `openpose/`. E.g. `rm -rf openpose/`. + + + +## Quick Start +Check that the library is working properly by using any of the following commands. Note that `examples/media/video.avi` and `examples/media` exist, so you do not need to change the paths. + +1. Running on Video +``` +./build/examples/openpose/openpose.bin --video examples/media/video.avi +``` + +2. Running on Webcam +``` +./build/examples/openpose/openpose.bin +``` + +3. Running on Images +``` +./build/examples/openpose/openpose.bin --image_dir examples/media/ +``` + +The visual GUI should show the original image with the poses blended on it, similarly to the pose of this gif: +

+ +

+ +If you choose to visualize a body part or a PAF (Part Affinity Field) heat map with the command option `--part_to_show`, the result should be similar to one of the following images: +

+ +

+ +

+ +

+ + + +## FAQ +Q: Out of memory error - After installing OpenPose, I get an out of memory error, similar to: `Check failed: error == cudaSuccess (2 vs. 0) out of memory`. +A: Most probably cuDNN is not installed/enabled, the default Caffe model uses >12 GB of GPU memory, cuDNN reduces it to ~1.5 GB. diff --git a/include/openpose/pose/poseParameters.hpp b/include/openpose/pose/poseParameters.hpp index 4f592350..33244cad 100644 --- a/include/openpose/pose/poseParameters.hpp +++ b/include/openpose/pose/poseParameters.hpp @@ -66,7 +66,6 @@ namespace op const std::array POSE_CCN_DECREASE_FACTOR{ 8.f, 8.f, 8.f}; const std::array POSE_MAX_PEAKS{ POSE_MAX_PEOPLE, POSE_MAX_PEOPLE, POSE_MAX_PEOPLE}; const std::array POSE_NUMBER_BODY_PARTS{ POSE_COCO_NUMBER_PARTS, POSE_MPI_NUMBER_PARTS, POSE_MPI_NUMBER_PARTS}; - const std::array, 3> POSE_BODY_PART_MAPPING{ POSE_COCO_BODY_PARTS, POSE_MPI_BODY_PARTS, POSE_MPI_BODY_PARTS}; const std::array, 3> POSE_BODY_PART_PAIRS{ POSE_COCO_PAIRS, POSE_MPI_PAIRS, POSE_MPI_PAIRS}; const std::array, 3> POSE_MAP_IDX{ POSE_COCO_MAP_IDX, POSE_MPI_MAP_IDX, POSE_MPI_MAP_IDX}; const std::array POSE_PROTOTXT{ "pose/coco/pose_deploy_linevec.prototxt", @@ -75,6 +74,10 @@ namespace op const std::array POSE_TRAINED_MODEL{ "pose/coco/pose_iter_440000.caffemodel", "pose/mpi/pose_iter_160000.caffemodel", "pose/mpi/pose_iter_160000.caffemodel"}; + // POSE_BODY_PART_MAPPING crashes on Windows at dynamic initialization, to avoid this crash: + // POSE_BODY_PART_MAPPING has been moved to poseParameters.cpp and getPoseBodyPartMapping() wraps it + //const std::array, 3> POSE_BODY_PART_MAPPING{ POSE_COCO_BODY_PARTS, POSE_MPI_BODY_PARTS, POSE_MPI_BODY_PARTS}; + const std::map& getPoseBodyPartMapping(const PoseModel poseModel); // Default Model Parameters // They might be modified on running time diff --git a/include/openpose/producer/producer.hpp b/include/openpose/producer/producer.hpp index de84ba2b..490ab48d 100644 --- a/include/openpose/producer/producer.hpp +++ b/include/openpose/producer/producer.hpp @@ -1,6 +1,7 @@ #ifndef OPENPOSE__PRODUCER__PRODUCER_HPP #define OPENPOSE__PRODUCER__PRODUCER_HPP +#include #include #include #include // capProperties of OpenCV diff --git a/include/openpose/thread/queueBase.hpp b/include/openpose/thread/queueBase.hpp index b6a77f30..e423e66a 100644 --- a/include/openpose/thread/queueBase.hpp +++ b/include/openpose/thread/queueBase.hpp @@ -1,5 +1,5 @@ #ifndef OPENPOSE__THREAD__QUEUE_BASE_HPP -#define OPENPOSE__THREAD__QUEUE_BASE_HPP +#define OPENPOSE__THREAD__QUEUE_BASE_HPP #include // std::queue & std::priority_queue #include diff --git a/include/openpose/thread/threadManager.hpp b/include/openpose/thread/threadManager.hpp index f899e7d4..fc316feb 100644 --- a/include/openpose/thread/threadManager.hpp +++ b/include/openpose/thread/threadManager.hpp @@ -442,7 +442,7 @@ namespace op // #threads = maxThreadId+1 mThreads.resize(maxThreadId); for (auto& thread : mThreads) - thread = {std::make_shared>()}; + thread = std::make_shared>(); mThreads.emplace_back(std::make_shared>(spIsRunning)); } catch (const std::exception& e) @@ -467,8 +467,8 @@ namespace op std::vector> usedQueueIds(maxQueueId + 1, {false, false}); for (const auto& threadWorkerQueue : mThreadWorkerQueues) { - usedQueueIds[std::get<2>(threadWorkerQueue)].first = true; - usedQueueIds[std::get<3>(threadWorkerQueue)].second = true; + 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; @@ -493,7 +493,7 @@ namespace op else error("Unknown ThreadManagerMode", __LINE__, __FUNCTION__, __FILE__); for (auto& tQueue : mTQueues) - tQueue = {std::make_shared(mDefaultMaxSizeQueues)}; + tQueue = std::make_shared(mDefaultMaxSizeQueues); } } catch (const std::exception& e) diff --git a/src/openpose/core/nmsBase.cu b/src/openpose/core/nmsBase.cu index 848099d0..fc5c9450 100644 --- a/src/openpose/core/nmsBase.cu +++ b/src/openpose/core/nmsBase.cu @@ -7,8 +7,8 @@ namespace op { - const auto THREADS_PER_BLOCK_1D = 16; - const auto THREADS_PER_BLOCK = 512; + const auto THREADS_PER_BLOCK_1D = 16u; + const auto THREADS_PER_BLOCK = 512u; template __global__ void nmsRegisterKernel(int* kernelPtr, const T* const sourcePtr, const int w, const int h, const T threshold) diff --git a/src/openpose/gui/guiInfoAdder.cpp b/src/openpose/gui/guiInfoAdder.cpp index 5fb8ba06..5a71449f 100644 --- a/src/openpose/gui/guiInfoAdder.cpp +++ b/src/openpose/gui/guiInfoAdder.cpp @@ -1,5 +1,6 @@ #include #include // std::snprintf +#include // std::numeric_limits #include "openpose/utilities/errorAndLog.hpp" #include "openpose/utilities/fastMath.hpp" #include "openpose/utilities/openCv.hpp" @@ -52,7 +53,7 @@ namespace op mGuiEnabled{guiEnabled}, mFpsCounter{0u}, mLastElementRenderedCounter{std::numeric_limits::max()}, - mLastId{-1u} + mLastId{std::numeric_limits::max()} { } diff --git a/src/openpose/pose/poseParameters.cpp b/src/openpose/pose/poseParameters.cpp index f89bd8ef..754bd86e 100644 --- a/src/openpose/pose/poseParameters.cpp +++ b/src/openpose/pose/poseParameters.cpp @@ -3,6 +3,8 @@ namespace op { + const std::array, 3> POSE_BODY_PART_MAPPING{ POSE_COCO_BODY_PARTS, POSE_MPI_BODY_PARTS, POSE_MPI_BODY_PARTS }; + unsigned char poseBodyPartMapStringToKey(const PoseModel poseModel, const std::vector& strings) { try @@ -34,4 +36,17 @@ namespace op return 0; } } + + const std::map& getPoseBodyPartMapping(const PoseModel poseModel) + { + try + { + return POSE_BODY_PART_MAPPING.at((int)poseModel); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return POSE_BODY_PART_MAPPING[(int)poseModel]; + } + } } diff --git a/src/openpose/pose/poseRenderGpu.cu b/src/openpose/pose/poseRenderGpu.cu index ce044498..2820a134 100644 --- a/src/openpose/pose/poseRenderGpu.cu +++ b/src/openpose/pose/poseRenderGpu.cu @@ -8,6 +8,8 @@ namespace op { + // PI digits: http://www.piday.org/million/ + __constant__ const float PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745f; __constant__ const unsigned char COCO_PAIRS_GPU[] = POSE_COCO_PAIRS_TO_RENDER; __constant__ const unsigned char MPI_PAIRS_GPU[] = POSE_MPI_PAIRS_TO_RENDER; __constant__ const float COCO_RGB_COLORS[] = { @@ -131,7 +133,7 @@ namespace op inline __device__ void getColorXYAffinity(float3& colorPtr, const float x, const float y) { const auto rad = fastMin(1.f, sqrt( x*x + y*y ) ); - const float a = atan2(-y,-x)/M_PI; + const float a = atan2(-y,-x)/PI; auto fk = (a+1.f)/2.f; // 0 to 1 if (::isnan(fk)) fk = 0.f; diff --git a/src/openpose/pose/poseRenderer.cpp b/src/openpose/pose/poseRenderer.cpp index 418102ac..cbe8b475 100644 --- a/src/openpose/pose/poseRenderer.cpp +++ b/src/openpose/pose/poseRenderer.cpp @@ -12,7 +12,9 @@ namespace op { try { - auto partToName = POSE_BODY_PART_MAPPING[(int)poseModel]; + // POSE_BODY_PART_MAPPING crashes on Windows, replaced by getPoseBodyPartMapping + // auto partToName = POSE_BODY_PART_MAPPING[(int)poseModel]; + auto partToName = getPoseBodyPartMapping(poseModel); const auto& bodyPartPairs = POSE_BODY_PART_PAIRS[(int)poseModel]; const auto& mapIdx = POSE_MAP_IDX[(int)poseModel]; @@ -43,7 +45,8 @@ namespace op mPoseModel{poseModel}, mPartIndexToName{createPartToName(poseModel)}, // #body elements to render = #body parts (size()) + #body part pair connections + 3 (+whole pose +whole heatmaps +PAFs) - mNumberElementsToRender{(int)(POSE_BODY_PART_MAPPING[(int)mPoseModel].size() + POSE_BODY_PART_PAIRS[(int)mPoseModel].size()/2 + 3)}, + // POSE_BODY_PART_MAPPING crashes on Windows, replaced by getPoseBodyPartMapping + mNumberElementsToRender{(int)(getPoseBodyPartMapping(mPoseModel).size() + POSE_BODY_PART_PAIRS[(int)mPoseModel].size()/2 + 3)}, spPoseExtractor{poseExtractor}, mAlphaPose{alphaPose}, mAlphaHeatMap{alphaHeatMap}, diff --git a/src/openpose/utilities/profiler.cpp b/src/openpose/utilities/profiler.cpp index 3852fbfd..c7677f08 100644 --- a/src/openpose/utilities/profiler.cpp +++ b/src/openpose/utilities/profiler.cpp @@ -42,7 +42,7 @@ namespace op if (sProfilerTuple.count(key) > 0) std::get<2>(sProfilerTuple[key]) = std::chrono::high_resolution_clock::now(); else - sProfilerTuple[key] = {std::make_tuple(0., 0, std::chrono::high_resolution_clock::now())}; + sProfilerTuple[key] = {std::make_tuple(0., 0ull, std::chrono::high_resolution_clock::now())}; lock.unlock(); return key; #else