提交 9dd78c3c 编写于 作者: G gineshidalgo99

Doxygen doc for Wrapper

上级 39f0e08c
......@@ -3,7 +3,7 @@ OpenPose
## Introduction
OpenPose is a **library for real-time multi-person key-point detection and multi-threading written in C++** using OpenCV and Caffe, authored by [Gines Hidalgo](https://www.linkedin.com/in/gineshidalgo/), [Zhe Cao](http://www.andrew.cmu.edu/user/zhecao), [Tomas Simon](http://www.cs.cmu.edu/~tsimon/), [Shih-En Wei](https://scholar.google.com/citations?user=sFQD3k4AAAAJ&hl=en), [Yaser Sheikh](http://www.cs.cmu.edu/~yaser/).
OpenPose is a **library for real-time multi-person key-point detection and multi-threading written in C++** using OpenCV and Caffe, authored by [Gines Hidalgo](https://www.linkedin.com/in/gineshidalgo/), [Zhe Cao](http://www.andrew.cmu.edu/user/zhecao), [Tomas Simon](http://www.cs.cmu.edu/~tsimon/), [Shih-En Wei](https://scholar.google.com/citations?user=sFQD3k4AAAAJ&hl=en) and [Yaser Sheikh](http://www.cs.cmu.edu/~yaser/).
OpenPose is freely available for free non-commercial use, and may be redistributed under these conditions. Please, see the [license](LICENSE) for further details. Contact us for commercial purposes.
......@@ -53,7 +53,7 @@ This work is based on the C++ code from [C++ real-time ECCV 2016 demo](https://g
## Installation
Installation steps on [installation.md](doc/installation.md).
Installation steps on [doc/installation.md](doc/installation.md).
......@@ -65,7 +65,7 @@ Most users cases should not need to dive deep into the library, they might just
#### Demo
Your case if you just want to process a folder of images or video or webcam and display or save the pose results.
Forget about the OpenPose library details and just read the [demo_overview.md](doc/demo_overview.md) 1-page section.
Forget about the OpenPose library details and just read the [doc/demo_overview.md](doc/demo_overview.md) 1-page section.
#### OpenPose Wrapper
Your case if you want to read a specific format of image source and/or add a specific post-processing function and/or implement your own display/saving.
......@@ -77,16 +77,17 @@ Note: you should not need to modify OpenPose source code or examples, so that yo
#### OpenPose Library
Your case if you want to change internal functions and/or extend its functionality. First, take a look to the [Demo](#demo) and [OpenPose Wrapper](#openpose-wrapper). Secondly, read the 2 following subsections: OpenPose Overview and Extending Functionality.
1. OpenPose Overview: Learn the basics about our library source code on [library_overview.md](doc/library_overview.md).
1. OpenPose Overview: Learn the basics about our library source code on [doc/library_overview.md](doc/library_overview.md).
2. Extending Functionality: Learn how to extend our library on [library_extend_functionality.md](doc/library_extend_functionality.md).
2. Extending Functionality: Learn how to extend our library on [doc/library_extend_functionality.md](doc/library_extend_functionality.md).
3. Adding An Extra Module: Learn how to add an extra module on [library_add_new_module.md](doc/library_add_new_module.md).
3. Adding An Extra Module: Learn how to add an extra module on [doc/library_add_new_module.md](doc/library_add_new_module.md).
#### Doxygen Documentation Autogeneration
You can generate the documentation by running the following command. The documentation will be generated on `doc/doxygen/html/index.html`. You can simply open it with double click and your favourite browser will display it.
You can generate the documentation by running the following command. The documentation will be generated on `doc/doxygen/html/index.html`. You can simply open it with double click (your default browser should automatically display it).
```
doxygen doc/doc_autogeneration.doxygen
cd doc/
doxygen doc_autogeneration.doxygen
```
......
......@@ -58,7 +58,7 @@ PROJECT_LOGO =
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
OUTPUT_DIRECTORY = /home/gines/Dropbox/Perceptual_Computing_Lab/cpm/cpm/doc/doxygen
OUTPUT_DIRECTORY = doxygen
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
......@@ -781,7 +781,7 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = /home/gines/Dropbox/Perceptual_Computing_Lab/cpm/cpm/include
INPUT = ../include/openpose/
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
......
OpenPose Library - Compilation and Installation
====================================
# Requirements
## 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).
- At least 2 GB of free RAM memory.
- Highly recommended: A CPU with at least 8 cores.
Note: This requirements assume the default configuration (i.e. `--net_resolution "656x368"` and `num_scales 1`). You might need more (with a greater net resolution and/or number of scales) or less resources (with smaller net resolution and/or using the MPI and MPI_4 models).
# How to Compile It
## How to Compile It
1. Required: CUDA, cuDNN and OpenCV installed on your machine. OpenCV can be easily installed by running `apt-get install libopencv-dev`.
2. If you have installed OpenCV 2.4 in your system, go to step 3. If you are using OpenCV 3, uncomment the line `# OPENCV_VERSION := 3` on the file `Makefile.config.Ubuntu14.example` (for Ubuntu 14) and/or `Makefile.config.Ubuntu16.example` (for Ubuntu 15 or 16). In addition, OpenCV 3 does not incorporate the `opencv_contrib` module by default. Assuming you have manually installed it and you need to use it, append `opencv_contrib` at the end of the line `LIBRARIES += opencv_core opencv_highgui opencv_imgproc` in the `Makefile` file.
3. Build Caffe & the OpenPose library + download the required Caffe models for Ubuntu 14.04 or 16.04 and cuda 8:
......@@ -49,7 +50,7 @@ make clean
make all -j$(NUM_CORES)
```
# Custom Caffe
## Custom Caffe
We slightly modified some Caffe compilation flags and minor details. In case you want to use your own Caffe distribution, these are the files we added and modified:
1. Added files: `install_caffe_and_openpose.sh`; as well as `Makefile.config.Ubuntu14.example`, `Makefile.config.Ubuntu16.example`, `Makefile.config.Ubuntu14_cuda_7.example` and `Makefile.config.Ubuntu16_cuda_7.example` (extracted from `Makefile.config.example`).
......
......@@ -16,7 +16,7 @@ In order to add a new module, these are the recommended steps in order to develo
2. Use the whole op::Datum as unique argument of your auxiliary functions.
3. Use the OpenPose Wrapper in ThreadMode::SingleThread mode (e.g. it allows you to directly use cv::imshow).
3. Use the OpenPose Wrapper in ThreadManagerMode::SingleThread mode (e.g. it allows you to directly use cv::imshow).
4. If you are using your own custom Caffe -> initially change the Caffe for your version. It should directly work.
......
......@@ -248,20 +248,20 @@ int opRealTimePoseDemo()
// OpenPose wrapper
op::log("Configuring OpenPose wrapper.", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__);
op::Wrapper<std::vector<op::Datum>> opWrapper;
const op::WrapperPoseStruct wrapperPoseStruct{netInputSize, outputSize, scaleMode, FLAGS_num_gpu, FLAGS_num_gpu_start, FLAGS_num_scales, (float)FLAGS_scale_gap,
const op::WrapperStructPose wrapperStructPose{netInputSize, outputSize, scaleMode, FLAGS_num_gpu, FLAGS_num_gpu_start, FLAGS_num_scales, (float)FLAGS_scale_gap,
!FLAGS_no_render_output, poseModel, !FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap,
FLAGS_part_to_show, FLAGS_model_folder, heatMapTypes, op::ScaleMode::UnsignedChar};
const op::WrapperInputStruct wrapperInputStruct{producerSharedPtr, FLAGS_frame_first, FLAGS_frame_last, FLAGS_process_real_time, FLAGS_frame_flip,
const op::WrapperStructInput wrapperStructInput{producerSharedPtr, FLAGS_frame_first, FLAGS_frame_last, FLAGS_process_real_time, FLAGS_frame_flip,
FLAGS_frame_rotate, FLAGS_frames_repeat};
const op::WrapperOutputStruct wrapperOutputStruct{!FLAGS_no_display, !FLAGS_no_gui_verbose, FLAGS_fullscreen, FLAGS_write_pose, op::stringToDataFormat(FLAGS_write_pose_format),
const op::WrapperStructOutput wrapperStructOutput{!FLAGS_no_display, !FLAGS_no_gui_verbose, FLAGS_fullscreen, FLAGS_write_pose, op::stringToDataFormat(FLAGS_write_pose_format),
FLAGS_write_pose_json, FLAGS_write_coco_json, FLAGS_write_images, FLAGS_write_images_format, FLAGS_write_video,
FLAGS_write_heatmaps, FLAGS_write_heatmaps_format};
// Pose configuration (use WrapperPoseStruct{} for default and recommended configuration)
// Pose configuration (use WrapperStructPose{} for default and recommended configuration)
// Producer (use default to disable any input)
// Consumer (comment or use default argument to disable any output)
opWrapper.configure(wrapperPoseStruct, wrapperInputStruct, wrapperOutputStruct);
opWrapper.configure(wrapperStructPose, wrapperStructInput, wrapperStructOutput);
// Set to single-thread running (for debugging purposes)
// opWrapper.setWrapperMode(op::WrapperMode::SingleThread);
// opWrapper.disableMultiThreading();
// Start processing
// Two different ways of running the program on multithread enviroment
......
......@@ -282,22 +282,22 @@ int openPoseTutorialWrapper1()
op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__);
// Configure OpenPose
op::Wrapper<std::vector<UserDatum>> opWrapper{op::ThreadMode::Asynchronous};
op::Wrapper<std::vector<UserDatum>> opWrapper{op::ThreadManagerMode::Asynchronous};
const bool displayGui = false;
const bool guiVerbose = false;
const bool fullScreen = false;
const op::WrapperPoseStruct wrapperPoseStruct{netInputSize, outputSize, scaleMode, FLAGS_num_gpu, FLAGS_num_gpu_start, FLAGS_num_scales, (float)FLAGS_scale_gap,
const op::WrapperStructPose wrapperStructPose{netInputSize, outputSize, scaleMode, FLAGS_num_gpu, FLAGS_num_gpu_start, FLAGS_num_scales, (float)FLAGS_scale_gap,
!FLAGS_no_render_output, poseModel, !FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap,
FLAGS_part_to_show, FLAGS_model_folder, heatMapTypes, heatMapsScaleMode};
const op::WrapperOutputStruct wrapperOutputStruct{displayGui, guiVerbose, fullScreen, FLAGS_write_pose, op::stringToDataFormat(FLAGS_write_pose_format),
const op::WrapperStructOutput wrapperStructOutput{displayGui, guiVerbose, fullScreen, FLAGS_write_pose, op::stringToDataFormat(FLAGS_write_pose_format),
FLAGS_write_pose_json, FLAGS_write_coco_json, FLAGS_write_images, FLAGS_write_images_format, FLAGS_write_video,
FLAGS_write_heatmaps, FLAGS_write_heatmaps_format};
// Pose configuration (use WrapperPoseStruct{} for default and recommended configuration)
// Pose configuration (use WrapperStructPose{} for default and recommended configuration)
// Producer (use default to disable any input)
// Consumer (comment or use default argument to disable any output)
opWrapper.configure(wrapperPoseStruct, op::WrapperInputStruct{}, wrapperOutputStruct);
opWrapper.configure(wrapperStructPose, op::WrapperStructInput{}, wrapperStructOutput);
// Set to single-thread running (for debugging purposes)
// opWrapper.setWrapperMode(op::WrapperMode::SingleThread);
// opWrapper.disableMultiThreading();
op::log("Starting thread(s)", op::Priority::Max);
opWrapper.start();
......
......@@ -348,18 +348,18 @@ int openPoseTutorialWrapper2()
const bool displayGui = false;
const bool guiVerbose = false;
const bool fullScreen = false;
const op::WrapperPoseStruct wrapperPoseStruct{netInputSize, outputSize, scaleMode, FLAGS_num_gpu, FLAGS_num_gpu_start, FLAGS_num_scales, (float)FLAGS_scale_gap,
const op::WrapperStructPose wrapperStructPose{netInputSize, outputSize, scaleMode, FLAGS_num_gpu, FLAGS_num_gpu_start, FLAGS_num_scales, (float)FLAGS_scale_gap,
!FLAGS_no_render_output, poseModel, !FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap,
FLAGS_part_to_show, FLAGS_model_folder, heatMapTypes, heatMapsScaleMode};
const op::WrapperOutputStruct wrapperOutputStruct{displayGui, guiVerbose, fullScreen, FLAGS_write_pose, op::stringToDataFormat(FLAGS_write_pose_format),
const op::WrapperStructOutput wrapperStructOutput{displayGui, guiVerbose, fullScreen, FLAGS_write_pose, op::stringToDataFormat(FLAGS_write_pose_format),
FLAGS_write_pose_json, FLAGS_write_coco_json, FLAGS_write_images, FLAGS_write_images_format, FLAGS_write_video,
FLAGS_write_heatmaps, FLAGS_write_heatmaps_format};
// Pose configuration (use WrapperPoseStruct{} for default and recommended configuration)
// Pose configuration (use WrapperStructPose{} for default and recommended configuration)
// Producer (use default to disable any input)
// Consumer (comment or use default argument to disable any output)
opWrapper.configure(wrapperPoseStruct, op::WrapperInputStruct{}, wrapperOutputStruct);
opWrapper.configure(wrapperStructPose, op::WrapperStructInput{}, wrapperStructOutput);
// Set to single-thread running (for debugging purposes)
// opWrapper.setWrapperMode(op::WrapperMode::SingleThread);
// opWrapper.disableMultiThreading();
op::log("Starting thread(s)", op::Priority::Max);
// Two different ways of running the program on multithread enviroment
......
......@@ -4,7 +4,8 @@
namespace op
{
/**
* A class enum with the different output screen options (e.g. full screen, windored or disabling the display).
* GUI display modes.
* An enum class with the different output screen options (e.g. full screen, windored or disabling the display).
*/
enum class GuiDisplayMode : bool
{
......
......@@ -18,7 +18,8 @@ namespace op
};
/**
* A class enum in which all the possible type of Producer are included. In order to add a new Producer,
* 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
......
......@@ -3,11 +3,23 @@
namespace op
{
enum class ThreadMode : unsigned char
/**
* 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,
AsynchronousOut,
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,
};
}
......
......@@ -19,7 +19,7 @@ namespace op
{
public:
// Completely customizable case
explicit ThreadManager(const ThreadMode threadMode = ThreadMode::Synchronous);
explicit ThreadManager(const ThreadManagerMode threadManagerMode = ThreadManagerMode::Synchronous);
void setDefaultMaxSizeQueues(const long long defaultMaxSizeQueues = -1);
......@@ -58,7 +58,7 @@ namespace op
bool waitAndPop(TDatums& tDatums);
private:
const ThreadMode mThreadMode;
const ThreadManagerMode mThreadManagerMode;
std::shared_ptr<std::atomic<bool>> spIsRunning;
long long mDefaultMaxSizeQueues;
std::multiset<std::tuple<unsigned long long, std::vector<TWorker>, unsigned long long, unsigned long long>> mThreadWorkerQueues;
......@@ -95,8 +95,8 @@ namespace op
namespace op
{
template<typename TDatums, typename TWorker, typename TQueue>
ThreadManager<TDatums, TWorker, TQueue>::ThreadManager(const ThreadMode threadMode) :
mThreadMode{threadMode},
ThreadManager<TDatums, TWorker, TQueue>::ThreadManager(const ThreadManagerMode threadManagerMode) :
mThreadManagerMode{threadManagerMode},
spIsRunning{std::make_shared<std::atomic<bool>>(false)},
mDefaultMaxSizeQueues{-1ll}
{
......@@ -130,7 +130,8 @@ namespace op
}
template<typename TDatums, typename TWorker, typename TQueue>
void ThreadManager<TDatums, TWorker, TQueue>::add(const unsigned long long threadId, const TWorker& tWorker, const unsigned long long queueInId, const unsigned long long queueOutId)
void ThreadManager<TDatums, TWorker, TQueue>::add(const unsigned long long threadId, const TWorker& tWorker, const unsigned long long queueInId,
const unsigned long long queueOutId)
{
try
{
......@@ -227,8 +228,8 @@ namespace op
{
try
{
if (mThreadMode != ThreadMode::Asynchronous && mThreadMode != ThreadMode::AsynchronousIn)
error("Not available for this ThreadMode.", __LINE__, __FUNCTION__, __FILE__);
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);
......@@ -245,8 +246,8 @@ namespace op
{
try
{
if (mThreadMode != ThreadMode::Asynchronous && mThreadMode != ThreadMode::AsynchronousIn)
error("Not available for this ThreadMode.", __LINE__, __FUNCTION__, __FILE__);
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);
......@@ -263,8 +264,8 @@ namespace op
{
try
{
if (mThreadMode != ThreadMode::Asynchronous && mThreadMode != ThreadMode::AsynchronousIn)
error("Not available for this ThreadMode.", __LINE__, __FUNCTION__, __FILE__);
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);
......@@ -281,8 +282,8 @@ namespace op
{
try
{
if (mThreadMode != ThreadMode::Asynchronous && mThreadMode != ThreadMode::AsynchronousIn)
error("Not available for this ThreadMode.", __LINE__, __FUNCTION__, __FILE__);
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);
......@@ -299,8 +300,8 @@ namespace op
{
try
{
if (mThreadMode != ThreadMode::Asynchronous && mThreadMode != ThreadMode::AsynchronousOut)
error("Not available for this ThreadMode.", __LINE__, __FUNCTION__, __FILE__);
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);
......@@ -317,8 +318,8 @@ namespace op
{
try
{
if (mThreadMode != ThreadMode::Asynchronous && mThreadMode != ThreadMode::AsynchronousOut)
error("Not available for this ThreadMode.", __LINE__, __FUNCTION__, __FILE__);
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);
......@@ -331,7 +332,8 @@ namespace op
}
template<typename TDatums, typename TWorker, typename TQueue>
void ThreadManager<TDatums, TWorker, TQueue>::add(const std::vector<std::tuple<unsigned long long, std::vector<TWorker>, unsigned long long, unsigned long long>>& threadWorkerQueues)
void ThreadManager<TDatums, TWorker, TQueue>::add(const std::vector<std::tuple<unsigned long long, std::vector<TWorker>,
unsigned long long, unsigned long long>>& threadWorkerQueues)
{
try
{
......@@ -345,12 +347,14 @@ namespace op
}
template<typename TDatums, typename TWorker, typename TQueue>
void ThreadManager<TDatums, TWorker, TQueue>::add(const std::vector<std::tuple<unsigned long long, TWorker, unsigned long long, unsigned long long>>& threadWorkerQueues)
void ThreadManager<TDatums, TWorker, TQueue>::add(const std::vector<std::tuple<unsigned long long, TWorker, unsigned long long,
unsigned long long>>& threadWorkerQueues)
{
try
{
for (const auto& threadWorkerQueue : threadWorkerQueues)
add({std::make_tuple(std::get<0>(threadWorkerQueue), std::vector<TWorker>{std::get<1>(threadWorkerQueue)}, std::get<2>(threadWorkerQueue), std::get<3>(threadWorkerQueue))});
add({std::make_tuple(std::get<0>(threadWorkerQueue), std::vector<TWorker>{std::get<1>(threadWorkerQueue)},
std::get<2>(threadWorkerQueue), std::get<3>(threadWorkerQueue))});
}
catch (const std::exception& e)
{
......@@ -379,32 +383,32 @@ namespace op
{
auto& thread = mThreads[std::get<0>(threadWorkerQueue)];
const auto& tWorkers = std::get<1>(threadWorkerQueue);
const auto queueInId = std::get<2>(threadWorkerQueue);
const auto queueOutId = std::get<3>(threadWorkerQueue);
const auto queueIn = std::get<2>(threadWorkerQueue);
const auto queueOut = std::get<3>(threadWorkerQueue);
std::shared_ptr<SubThread<TDatums, TWorker>> subThread;
// If AsynchronousIn -> queue indexes are OK
if (mThreadMode == ThreadMode::Asynchronous || mThreadMode == ThreadMode::AsynchronousIn)
if (mThreadManagerMode == ThreadManagerMode::Asynchronous || mThreadManagerMode == ThreadManagerMode::AsynchronousIn)
{
if (mThreadMode == ThreadMode::AsynchronousIn && queueOutId == mTQueues.size())
subThread = {std::make_shared<SubThreadQueueIn<TDatums, TWorker, TQueue>>(tWorkers, mTQueues.at(queueInId))};
if (mThreadManagerMode == ThreadManagerMode::AsynchronousIn && queueOut == mTQueues.size())
subThread = {std::make_shared<SubThreadQueueIn<TDatums, TWorker, TQueue>>(tWorkers, mTQueues.at(queueIn))};
else
subThread = {std::make_shared<SubThreadQueueInOut<TDatums, TWorker, TQueue>>(tWorkers, mTQueues.at(queueInId), mTQueues.at(queueOutId))};
subThread = {std::make_shared<SubThreadQueueInOut<TDatums, TWorker, TQueue>>(tWorkers, mTQueues.at(queueIn), mTQueues.at(queueOut))};
}
// If !AsynchronousIn -> queue indexes - 1
else if (queueOutId != maxQueueIdSynchronous || mThreadMode == ThreadMode::AsynchronousOut)
else if (queueOut != maxQueueIdSynchronous || mThreadManagerMode == ThreadManagerMode::AsynchronousOut)
{
// Queue in + out
if (queueInId != 0)
subThread = {std::make_shared<SubThreadQueueInOut<TDatums, TWorker, TQueue>>(tWorkers, mTQueues.at(queueInId-1), mTQueues.at(queueOutId-1))};
if (queueIn != 0)
subThread = {std::make_shared<SubThreadQueueInOut<TDatums, TWorker, TQueue>>(tWorkers, mTQueues.at(queueIn-1), mTQueues.at(queueOut-1))};
// Case queue out (first TWorker(s))
else
subThread = {std::make_shared<SubThreadQueueOut<TDatums, TWorker, TQueue>>(tWorkers, mTQueues.at(queueOutId-1))};
subThread = {std::make_shared<SubThreadQueueOut<TDatums, TWorker, TQueue>>(tWorkers, mTQueues.at(queueOut-1))};
}
// Case queue in (last TWorker(s))
else if (queueInId != 0) // && queueOutId == maxQueueIdSynchronous
subThread = {std::make_shared<SubThreadQueueIn<TDatums, TWorker, TQueue>>(tWorkers, mTQueues.at(queueInId-1))};
else if (queueIn != 0) // && queueOut == maxQueueIdSynchronous
subThread = {std::make_shared<SubThreadQueueIn<TDatums, TWorker, TQueue>>(tWorkers, mTQueues.at(queueIn-1))};
// Case no queue
else // if (queueInId == 0 && queueOutId == maxQueueIdSynchronous)
else // if (queueIn == 0 && queueOut == maxQueueIdSynchronous)
subThread = {std::make_shared<SubThreadNoQueue<TDatums, TWorker>>(tWorkers)};
thread->add(subThread);
}
......@@ -430,7 +434,7 @@ namespace op
{
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__);
error("Missing thread id " + std::to_string(currentThreadId) + " of " + std::to_string(maxThreadId) + ".", __LINE__, __FUNCTION__, __FILE__);
previousThreadId = currentThreadId;
}
......@@ -480,14 +484,14 @@ namespace op
}
// Create Queues
if (mThreadMode == ThreadMode::Asynchronous)
if (mThreadManagerMode == ThreadManagerMode::Asynchronous)
mTQueues.resize(maxQueueId+1); // First and last one are queues
else if (mThreadMode == ThreadMode::Synchronous)
else if (mThreadManagerMode == ThreadManagerMode::Synchronous)
mTQueues.resize(maxQueueId-1); // First and last one are not actually queues
else if (mThreadMode == ThreadMode::AsynchronousIn || mThreadMode == ThreadMode::AsynchronousOut)
else if (mThreadManagerMode == ThreadManagerMode::AsynchronousIn || mThreadManagerMode == ThreadManagerMode::AsynchronousOut)
mTQueues.resize(maxQueueId); // First or last one is queue
else
error("Unknown ThreadMode", __LINE__, __FUNCTION__, __FILE__);
error("Unknown ThreadManagerMode", __LINE__, __FUNCTION__, __FILE__);
for (auto& tQueue : mTQueues)
tQueue = {std::make_shared<TQueue>(mDefaultMaxSizeQueues)};
}
......
#ifndef OPENPOSE__WRAPPER__ENUM_CLASSES_HPP
#define OPENPOSE__WRAPPER__ENUM_CLASSES_HPP
namespace op
{
enum class WrapperMode : bool
{
SingleThread,
MultiThread,
};
}
#endif // OPENPOSE__WRAPPER__ENUM_CLASSES_HPP
......@@ -2,7 +2,10 @@
#define OPENPOSE__WRAPPER__HEADERS_HPP
// wrapper module
#include "enumClasses.hpp"
#include "wrapper.hpp"
#include "wrapperStructHands.hpp"
#include "wrapperStructInput.hpp"
#include "wrapperStructOutput.hpp"
#include "wrapperStructPose.hpp"
#endif // OPENPOSE__WRAPPER__HEADERS_HPP
#ifndef OPENPOSE__WRAPPER__WRAPPER_STRUCT_HANDS_HPP
#define OPENPOSE__WRAPPER__WRAPPER_STRUCT_HANDS_HPP
namespace op
{
namespace experimental
{
/**
* WrapperStructHands: Hands estimation and rendering configuration struct.
* DO NOT USE. CODE TO BE FINISHED.
* WrapperStructHands allows the user to set up the hands estimation and rendering parameters that will be used for the OpenPose Wrapper
* class.
*/
struct WrapperStructHands
{
/**
* PROVISIONAL PARAMETER. IT WILL BE CHANGED.
* Whether to extract and render hands.
*/
bool extractAndRenderHands;
/**
* 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.
*/
WrapperStructHands(const bool extractAndRenderHands = false);
};
}
}
#endif // OPENPOSE__WRAPPER__WRAPPER_STRUCT_HANDS_HPP
#ifndef OPENPOSE__WRAPPER__WRAPPER_STRUCT_INPUT_HPP
#define OPENPOSE__WRAPPER__WRAPPER_STRUCT_INPUT_HPP
#include <memory>
#include "../producer/producer.hpp"
namespace op
{
/**
* WrapperStructInput: Input (images, video, webcam, etc.) configuration struct.
* WrapperStructInput allows the user to set up the input frames generator.
*/
struct WrapperStructInput
{
/**
* Producer which will generate the frames.
* Set to nullptr to disable the whole input, i.e. if the user is going to use his own frames generator.
*/
std::shared_ptr<Producer> producerSharedPtr;
/**
* First image to obtain.
* Default: 0.
*/
unsigned long long frameFirst;
/**
* Last image to obtain.
* Default: -1 (i.e. obtain 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;
/**
* 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 std::shared_ptr<Producer> producerSharedPtr = nullptr, const unsigned long long frameFirst = 0,
const unsigned long long frameLast = -1, const bool realTimeProcessing = false, const bool frameFlip = false,
const int frameRotate = 0, const bool framesRepeat = false);
};
}
#endif // OPENPOSE__WRAPPER__WRAPPER_STRUCT_INPUT_HPP
#ifndef OPENPOSE__WRAPPER__WRAPPER_STRUCT_OUTPUT_HPP
#define OPENPOSE__WRAPPER__WRAPPER_STRUCT_OUTPUT_HPP
#include <string>
#include "../filestream/enumClasses.hpp"
namespace op
{
/**
* WrapperStructOutput: Output (small GUI, writing rendered results and/or pose data, etc.) configuration struct.
* WrapperStructOutput allows the user to set up the input frames generator.
*/
struct WrapperStructOutput
{
/**
* Whether to display the OpenPose small integrated GUI.
*/
bool displayGui;
/**
* 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;
/**
* Pose (x, y, score) locations saving folder location.
* If it is empty (default), it is disabled.
* Select format with writePoseDataFormat.
*/
std::string writePose;
/**
* 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 writePoseDataFormat;
/**
* Pose (x, y, score) locations saving folder location in JSON format (e.g. useful when needed JSON but using OpenCV < 3.0).
* If it is empty (default), it is disabled.
*/
std::string writePoseJson;
/**
* Pose (x, y, score) locations saving folder location in JSON COCO validation format.
* If it is empty (default), it is disabled.
*/
std::string writeCocoJson;
/**
* Rendered image saving folder.
* If it is empty (default), it is disabled.
*/
std::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.
*/
std::string writeImagesFormat;
/**
* Rendered images saving video path.
* Please, use *.avi format.
* If it is empty (default), it is disabled.
*/
std::string writeVideo;
/**
* 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.
*/
std::string writeHeatMaps;
/**
* Heat maps image saving format.
* Analogous to writeImagesFormat.
*/
std::string writeHeatMapsFormat;
/**
* 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 bool displayGui = false, const bool guiVerbose = false, const bool fullScreen = false, const std::string& writePose = "",
const DataFormat writePoseDataFormat = DataFormat::Xml, const std::string& writePoseJson = "", const std::string& writeCocoJson = "",
const std::string& writeImages = "", const std::string& writeImagesFormat = "", const std::string& writeVideo = "",
const std::string& writeHeatMaps = "", const std::string& writeHeatMapsFormat = "");
};
}
#endif // OPENPOSE__WRAPPER__WRAPPER_STRUCT_OUTPUT_HPP
#ifndef OPENPOSE__WRAPPER__WRAPPER_STRUCT_POSE_HPP
#define OPENPOSE__WRAPPER__WRAPPER_STRUCT_POSE_HPP
#include <opencv2/core/core.hpp>
#include "../core/enumClasses.hpp"
#include "../pose/enumClasses.hpp"
#include "../pose/poseParameters.hpp"
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 Wrapper
* class.
*/
struct WrapperStructPose
{
/**
* 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.
*/
cv::Size netInputSize;
/**
* Output size of the final rendered image.
* It barely affects performance compared to netInputSize.
* The final Datum.pose can be scaled with respect to outputSize if `poseScaleMode` is set to ScaleMode::OutputResolution, even if the
* rendering is disabled.
*/
cv::Size outputSize;
/**
* Final scale of the Array<float> Datum.pose and the writen pose data.
* The final Datum.pose 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), and -1 to 1 (ScaleMode::PlusMinusOne).
*/
ScaleMode poseScaleMode;
/**
* 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).
*/
bool renderOutput;
/**
* Pose model, it affects the number of body parts to render
* Select 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 alphaPose;
/**
* 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.
*/
std::string modelFolder;
/**
* Whether and which heat maps to save on the Array<float> Datum.heatmaps.
* Use HeatMapType::Parts for body parts, HeatMapType::Background for the background, and HeatMapType::PAFs for the Part Affinity Fields.
*/
std::vector<HeatMapType> heatMapTypes;
/**
* Scale of the Datum.heatmaps.
* Select ScaleMode::ZeroToOne for range [0,1], ScaleMode::PlusMinusOne for [-1,1] and ScaleMode::UnsignedChar for [0, 255]
* If heatMapTypes.empty(), then this parameters makes no effect.
*/
ScaleMode heatMapScaleMode;
/**
* 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 cv::Size& netInputSize = cv::Size{656, 368}, const cv::Size& outputSize = cv::Size{1280, 720},
const ScaleMode poseScaleMode = ScaleMode::InputResolution, const int gpuNumber = 1, const int gpuNumberStart = 0,
const int scalesNumber = 1, const float scaleGap = 0.15f, const bool renderOutput = false,
const PoseModel poseModel = PoseModel::COCO_18, const bool blendOriginalFrame = true,
const float alphaPose = POSE_DEFAULT_ALPHA_POSE, const float alphaHeatMap = POSE_DEFAULT_ALPHA_HEATMAP,
const int defaultPartToRender = 0, const std::string& modelFolder = "models/",
const std::vector<HeatMapType>& heatMapTypes = {}, const ScaleMode heatMapScaleMode = ScaleMode::ZeroToOne);
};
}
#endif // OPENPOSE__WRAPPER__WRAPPER_STRUCT_POSE_HPP
#include "openpose/wrapper/wrapper.hpp"
namespace op
{
WrapperPoseStruct::WrapperPoseStruct(const cv::Size& netInputSize_, const cv::Size& outputSize_, const ScaleMode scaleMode_, const int gpuNumber_,
const int gpuNumberStart_, const int scalesNumber_, const float scaleGap_, const bool renderOutput_, const PoseModel poseModel_,
const bool blendOriginalFrame_, const float alphaPose_, const float alphaHeatMap_, const int defaultPartToRender_,
const std::string& modelFolder_, const std::vector<HeatMapType>& heatMapTypes_, const ScaleMode heatMapScaleMode_) :
netInputSize{netInputSize_},
outputSize{outputSize_},
scaleMode{scaleMode_},
gpuNumber{gpuNumber_},
gpuNumberStart{gpuNumberStart_},
scalesNumber{scalesNumber_},
scaleGap{scaleGap_},
renderOutput{renderOutput_},
poseModel{poseModel_},
blendOriginalFrame{blendOriginalFrame_},
alphaPose{alphaPose_},
alphaHeatMap{alphaHeatMap_},
defaultPartToRender{defaultPartToRender_},
modelFolder{modelFolder_},
heatMapTypes{heatMapTypes_},
heatMapScaleMode{heatMapScaleMode_}
{
}
namespace experimental
{
WrapperHandsStruct::WrapperHandsStruct(const bool extractAndRenderHands_) :
extractAndRenderHands{extractAndRenderHands_}
{
}
}
WrapperInputStruct::WrapperInputStruct(const std::shared_ptr<Producer> producerSharedPtr_, const unsigned long long frameFirst_, const unsigned long long frameLast_,
const bool realTimeProcessing_, const bool frameFlip_, const int frameRotate_, const bool framesRepeat_) :
producerSharedPtr{producerSharedPtr_},
frameFirst{frameFirst_},
frameLast{frameLast_},
realTimeProcessing{realTimeProcessing_},
frameFlip{frameFlip_},
frameRotate{frameRotate_},
framesRepeat{framesRepeat_}
{
}
WrapperOutputStruct::WrapperOutputStruct(const bool displayGui_, const bool guiVerbose_, const bool fullScreen_, const std::string& writePose_,
const DataFormat dataFormat_, const std::string& writePoseJson_, const std::string& writeCocoJson_,
const std::string& writeImages_, const std::string& writeImagesFormat_, const std::string& writeVideo_,
const std::string& writeHeatMaps_, const std::string& writeHeatMapsFormat_) :
displayGui{displayGui_},
guiVerbose{guiVerbose_},
fullScreen{fullScreen_},
writePose{writePose_},
dataFormat{dataFormat_},
writePoseJson{writePoseJson_},
writeCocoJson{writeCocoJson_},
writeImages{writeImages_},
writeImagesFormat{writeImagesFormat_},
writeVideo{writeVideo_},
writeHeatMaps{writeHeatMaps_},
writeHeatMapsFormat{writeHeatMapsFormat_}
{
}
}
#include "openpose/wrapper/wrapperStructHands.hpp"
namespace op
{
namespace experimental
{
WrapperStructHands::WrapperStructHands(const bool extractAndRenderHands_) :
extractAndRenderHands{extractAndRenderHands_}
{
}
}
}
#include "openpose/wrapper/wrapperStructInput.hpp"
namespace op
{
WrapperStructInput::WrapperStructInput(const std::shared_ptr<Producer> producerSharedPtr_, const unsigned long long frameFirst_, const unsigned long long frameLast_,
const bool realTimeProcessing_, const bool frameFlip_, const int frameRotate_, const bool framesRepeat_) :
producerSharedPtr{producerSharedPtr_},
frameFirst{frameFirst_},
frameLast{frameLast_},
realTimeProcessing{realTimeProcessing_},
frameFlip{frameFlip_},
frameRotate{frameRotate_},
framesRepeat{framesRepeat_}
{
}
}
#include "openpose/wrapper/wrapperStructOutput.hpp"
namespace op
{
WrapperStructOutput::WrapperStructOutput(const bool displayGui_, const bool guiVerbose_, const bool fullScreen_, const std::string& writePose_,
const DataFormat writePoseDataFormat_, const std::string& writePoseJson_, const std::string& writeCocoJson_,
const std::string& writeImages_, const std::string& writeImagesFormat_, const std::string& writeVideo_,
const std::string& writeHeatMaps_, const std::string& writeHeatMapsFormat_) :
displayGui{displayGui_},
guiVerbose{guiVerbose_},
fullScreen{fullScreen_},
writePose{writePose_},
writePoseDataFormat{writePoseDataFormat_},
writePoseJson{writePoseJson_},
writeCocoJson{writeCocoJson_},
writeImages{writeImages_},
writeImagesFormat{writeImagesFormat_},
writeVideo{writeVideo_},
writeHeatMaps{writeHeatMaps_},
writeHeatMapsFormat{writeHeatMapsFormat_}
{
}
}
#include "openpose/wrapper/wrapperStructPose.hpp"
namespace op
{
WrapperStructPose::WrapperStructPose(const cv::Size& netInputSize_, const cv::Size& outputSize_, const ScaleMode poseScaleMode_, const int gpuNumber_,
const int gpuNumberStart_, const int scalesNumber_, const float scaleGap_, const bool renderOutput_,
const PoseModel poseModel_, const bool blendOriginalFrame_, const float alphaPose_, const float alphaHeatMap_,
const int defaultPartToRender_, const std::string& modelFolder_, const std::vector<HeatMapType>& heatMapTypes_,
const ScaleMode heatMapScaleMode_) :
netInputSize{netInputSize_},
outputSize{outputSize_},
poseScaleMode{poseScaleMode_},
gpuNumber{gpuNumber_},
gpuNumberStart{gpuNumberStart_},
scalesNumber{scalesNumber_},
scaleGap{scaleGap_},
renderOutput{renderOutput_},
poseModel{poseModel_},
blendOriginalFrame{blendOriginalFrame_},
alphaPose{alphaPose_},
alphaHeatMap{alphaHeatMap_},
defaultPartToRender{defaultPartToRender_},
modelFolder{modelFolder_},
heatMapTypes{heatMapTypes_},
heatMapScaleMode{heatMapScaleMode_}
{
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册