提交 44398bd6 编写于 作者: G gineshidalgo99

1.0.0rc3: Face+Debug+MPI render improved+minor bugs fixed (see release_notes)

上级 cc4082b4
......@@ -34,7 +34,7 @@ LIB_BUILD_DIR := $(BUILD_DIR)/lib
STATIC_NAME := $(LIB_BUILD_DIR)/lib$(LIBRARY_NAME).a
DYNAMIC_VERSION_MAJOR := 1
DYNAMIC_VERSION_MINOR := 0
DYNAMIC_VERSION_REVISION := 0-rc2
DYNAMIC_VERSION_REVISION := 0-rc3
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)
......
OpenPose
====================================
## Latest News
- Apr 2017: Body released!
- May 2017: Windows version released!
- Jun 2017: Face released!
- Check all the [release notes](doc/release_notes.md).
## Introduction
OpenPose is a **library for real-time multi-person keypoint 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), [Hanbyul Joo](http://www.cs.cmu.edu/~hanbyulj/) and [Yaser Sheikh](http://www.cs.cmu.edu/~yaser/).
* It uses Caffe, but the code is ready to be ported to other frameworks (e.g., Tensorflow or Torch). If you implement any of those, please, make a pull request and we will add it!
\* It uses Caffe, but the code is ready to be ported to other frameworks (Tensorflow, Torch, etc.). If you implement any of those, feel free to make a pull request!
OpenPose represents the **first real-time system to jointly detect human body, hand and facial keypoints (in total 130 keypoints) on single images**. In addition, the system computational performance on body keypoint estimation is invariant to the number of detected people in the image.
......@@ -15,11 +23,11 @@ OpenPose is freely available for free non-commercial use, and may be redistribut
Library main functionality:
* Multi-person 15 or **18-keypoint body pose** estimation and rendering.
* Multi-person 15 or **18-keypoint body pose** estimation and rendering. **Running time invariant of number of people** on the image.
* Multi-person **2x21-keypoint hand** estimation and rendering (coming soon in around 1-2 months!).
* Multi-person **2x21-keypoint hand** estimation and rendering. Note: In this initial version, **running time** linearly **depends** on the **number of people** on the image. **Coming soon (in around 1-5 weeks)!**
* Multi-person **70-keypoint face** estimation and rendering (coming soon in around 2-3 months!).
* Multi-person **70-keypoint face** estimation and rendering. Note: In this initial version, **running time** linearly **depends** on the **number of people** on the image.
* Flexible and easy-to-configure **multi-threading** module.
......@@ -42,6 +50,11 @@ The pose estimation work is based on the C++ code from [the ECCV 2016 demo](http
<img src="doc/media/dance.gif", width="480">
</p>
### Body + Face Estimation
<p align="center">
<img src="doc/media/pose_face.gif", width="480">
</p>
## Coming Soon (But Already Working!)
### Body + Hands + Face Estimation
......@@ -49,11 +62,6 @@ The pose estimation work is based on the C++ code from [the ECCV 2016 demo](http
<img src="doc/media/pose_face_hands.gif", width="480">
</p>
### Body + Face Estimation
<p align="center">
<img src="doc/media/pose_face.gif", width="480">
</p>
### Body + Hands
<p align="center">
<img src="doc/media/pose_hands.gif", width="480">
......@@ -132,7 +140,7 @@ doxygen doc_autogeneration.doxygen
## Output
#### Output Format
There are 2 alternatives to save the **(x,y,score) body part locations**. The `write_pose` flag uses the OpenCV cv::FileStorage default formats (JSON, XML and YML). However, the JSON format is only available after OpenCV 3.0. Hence, `write_pose_json` saves the people pose data using a custom JSON writer. For the latter, each JSON file has a `people` array of objects, where each object has an array `body_parts` containing the body part locations and detection confidence formatted as `x1,y1,c1,x2,y2,c2,...`. The coordinates `x` and `y` can be normalized to the range [0,1], [-1,1], [0, source size], [0, output size], etc., depending on the flag `scale_mode`. In addition, `c` is the confidence in the range [0,1].
There are 2 alternatives to save the **(x,y,score) body part locations**. The `write_keypoint` flag uses the OpenCV cv::FileStorage default formats (JSON, XML and YML). However, the JSON format is only available after OpenCV 3.0. Hence, `write_keypoint_json` saves the people pose data using a custom JSON writer. For the latter, each JSON file has a `people` array of objects, where each object has an array `body_parts` containing the body part locations and detection confidence formatted as `x1,y1,c1,x2,y2,c2,...`. The coordinates `x` and `y` can be normalized to the range [0,1], [-1,1], [0, source size], [0, output size], etc., depending on the flag `keypoint_scale`. In addition, `c` is the confidence in the range [0,1].
```
{
......@@ -181,6 +189,16 @@ Where each index is the key value corresponding to each body part in `POSE_COCO_
#### Reading Saved Results
We use standard formats (JSON, XML, PNG, JPG, ...) to save our results, so there will be lots of frameworks to read them later, but you might also directly use our functions in [include/openpose/filestream.hpp](include/openpose/filestream.hpp). In particular, `loadData` (for JSON, XML and YML files) and `loadImage` (for image formats such as PNG or JPG) to load the data into cv::Mat format.
#### Pose Output Format
<p align="center">
<img src="doc/media/keypoints_body.gif", width="480">
</p>
#### Face Output Format
<p align="center">
<img src="doc/media/keypoints_face.gif", width="480">
</p>
## OpenPose Benchmark
......
......@@ -7,38 +7,65 @@ In order to learn how to use it, run `./build/examples/openpose/openpose.bin --h
## Other Important Options
Please, in order to check all the real time pose demo options and their details, run `./build/examples/openpose/openpose.bin --help`. We describe here some of the most important ones.
`--video input.mp4`: Input video. If omitted, it will use the webcam.
`--camera 3`: Choose webcam number (default: 0). If `--camera`, `--image_dir` and `--write_video` are omitted, it is equivalent to use `--camera 0`.
`--image_dir path_to_images/`: Run on all images (jpg, png, bmp, etc.) in `path_to_images/`. You can test the program with the image directory `examples/media/`.
`--write_video path.avi`: Render images with this prefix: `path.avi`. You can test the program with the example video `examples/media/video.avi`.
`--write_pose path/`: Output JSON, XML or YML files with the people pose data on the `path/` folder.
`--process_real_time`: It might skip frames in order to keep the final output displaying frames on real time.
`--disable_blending`: If selected, it will only render the pose skeleton or desired heat maps, while blocking the original background. Also related: `part_to_show`, `alpha_pose`, and `alpha_pose`.
`--part_to_show`: Select the prediction channel to visualize (default: 0). 0 to visualize all the body parts, 1-18 for each body part heat map, 19 for the background heat map, 20 for all the body part heat maps together, 21 for all the PAFs, 22-69 for each body part pair PAF.
`--no_display`: Display window not opened. Useful if there is no X server and/or to slightly speed up the processing if visual output is not required.
`--num_gpu 2 --num_gpu_start 0`: Parallelize over this number of GPUs starting by the desired device id. Default is 1 and 0, respectively.
`--num_scales 3 --scale_gap 0.15`: Use 3 scales, 1, (1-0.15), (1-0.15*2). Default is one scale. If you want to change the initial scale, you actually want to multiply your desired initial scale by the `net_resolution`.
`--net_resolution 656x368 --resolution 1280x720`: For HD images and video (default values).
`--net_resolution 496x368 --resolution 640x480`: For VGA images and video.
`--model_pose MPI`: It will use MPI (15 body keypoints). Default: COCO (18 body keypoints). MPI is slightly faster. The variation `MPI_4_layers` sacrifies accuracy in order to further increase speed.
`--logging_level 3`: Logging messages threshold, range [0,255]: 0 will output any message & 255 will output none. Current messages in the range [1-4], 1 for low priority messages and 4 for important ones.
## All Flags
Each flag is divided into flag name, default value, and description.
1. Debugging
- DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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.");
2. Producer
- DEFINE_int32(camera, 0, "The camera index for cv::VideoCapture. Integer in the range [0, 9].");
- DEFINE_string(camera_resolution, "1280x720", "Size of the camera frames to ask for.");
- 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.");
- DEFINE_uint64(frame_first, 0, "Start on desired frame number.");
- DEFINE_uint64(frame_last, -1, "Finish on desired frame number. Select -1 to disable this option.");
- 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.");
3. OpenPose
- DEFINE_string(model_folder, "models/", "Folder where the pose models (COCO and MPI) are located.");
- DEFINE_string(resolution, "1280x720", "The image resolution (display and output). Use \"-1x-1\" to force the program to use the default images 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_keypoint` & `write_keypoint_json` 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], and 4 for range [-1,1]. Non related with `num_scales` and `scale_gap`.");
4. OpenPose Body Pose
- DEFINE_string(model_pose, "COCO", "Model to be used (e.g. COCO, MPI, MPI_4_layers).");
- DEFINE_string(net_resolution, "656x368", "Multiples of 16. If it is increased, the accuracy usually increases. If it is decreased, the speed increases.");
- DEFINE_int32(num_scales, 1, "Number of scales to average.");
- DEFINE_double(scale_gap, 0.3, "Scale gap between scales. No effect unless num_scales>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.");
- DEFINE_bool(heatmaps_add_parts, false, "If true, it will add the body part heatmaps to the final op::Datum::poseHeatMaps array (program speed will decrease). Not required for our library, enable it only if you intend to process this information later. 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 `include/openpose/pose/poseParameters.hpp`.");
- 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.");
5. OpenPose Face
- DEFINE_bool(face, false, "Enables face keypoint detection. It will share some parameters from the body pose, e.g. `model_folder`.");
- DEFINE_string(face_net_resolution, "368x368", "Multiples of 16. 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.");
6. OpenPose Hand
7. OpenPose Rendering
- DEFINE_int32(part_to_show, 0, "Part to show from the start.");
- DEFINE_bool(disable_blending, false, "If blending is enabled, it will merge the results with the original frame. If disabled, it will only display the results.");
8. OpenPose Rendering Pose
- DEFINE_bool(no_render_pose, false, "If false, it will fill both `outputData` and `cvOutputData` with the original image + desired part to be shown. If true, it will leave them empty.");
- 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.");
- 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.");
9. OpenPose Rendering Face
- DEFINE_bool(no_render_face, false, "Analogous to `no_render_pose` but applied to the face keypoints and heat maps.");
- DEFINE_double(alpha_face, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will hide it.");
- DEFINE_double(alpha_heatmap_face, 0.7, "Blending factor (range 0-1) between heatmap and original frame. 1 will only show the heatmap, 0 will only show the frame.");
10. Display
- DEFINE_bool(fullscreen, false, "Run in full-screen mode (press f during runtime to toggle).");
- 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_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_bool(no_display, false, "Do not open a display window.");
11. 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.");
- DEFINE_string(write_keypoint, "", "Directory to write the people body pose keypoint data. Desired format on `write_keypoint_format`.");
- DEFINE_string(write_keypoint_format, "yml", "File extension and format for `write_keypoint`: json, xml, yaml and yml. Json not available for OpenCV < 3.0, use `write_keypoint_json` instead.");
- DEFINE_string(write_keypoint_json, "", "Directory to write people pose data with *.json format, compatible with any OpenCV version.");
- DEFINE_string(write_coco_json, "", "Full file path to write people pose data with *.json COCO validation format.");
- DEFINE_string(write_heatmaps, "", "Directory to write heatmaps with *.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`. Recommended `png` or any compressed and lossless format.");
## Multiple Scales
Running at multiple scales might drastically slow down the speed, but it will increase the accuracy. Given the CNN input size (set with `net_resolution`), `num_scales` and `scale_gap` configure the number of scales to use and the gap between them, respectively. For instance, `--num_scales 3 --scale_gap 0.15` means using 3 scales at resolution: (1), (1-0.15) and (1-2*0.15) times the `net_resolution`.
......@@ -51,6 +78,36 @@ The following command will save all the body part heat maps, background heat map
## Some Important Configuration Flags
Please, in order to check all the real time pose demo options and their details, run `./build/examples/openpose/openpose.bin --help`. We describe here some of the most important ones.
- `--face`: If enabled, it will also detect the faces on the image. Note that this will considerable slow down the performance and increse the required GPU memory. In addition, the greater number of people on the image, the slower OpenPose will be.
- `--video input.mp4`: Input video. If omitted, it will use the webcam.
- `--camera 3`: Choose webcam number (default: 0). If `--camera`, `--image_dir` and `--write_video` are omitted, it is equivalent to use `--camera 0`.
- `--image_dir path_to_images/`: Run on all images (jpg, png, bmp, etc.) in `path_to_images/`. You can test the program with the image directory `examples/media/`.
- `--write_video path.avi`: Render images with this prefix: `path.avi`. You can test the program with the example video `examples/media/video.avi`.
- `--write_images folder_path`: Render images on the folder `folder_path`.
- `--write_keypoint path/`: Output JSON, XML or YML files with the people pose data on the `path/` folder.
- `--process_real_time`: It might skip frames in order to keep the final output displaying frames on real time.
- `--disable_blending`: If selected, it will only render the pose skeleton or desired heat maps, while blocking the original background. Also related: `part_to_show`, `alpha_pose`, and `alpha_pose`.
- `--part_to_show`: Select the prediction channel to visualize (default: 0). 0 to visualize all the body parts, 1-18 for each body part heat map, 19 for the background heat map, 20 for all the body part heat maps together, 21 for all the PAFs, 22-69 for each body part pair PAF.
- `--no_display`: Display window not opened. Useful if there is no X server and/or to slightly speed up the processing if visual output is not required.
- `--num_gpu 2 --num_gpu_start 0`: Parallelize over this number of GPUs starting by the desired device id. Default is 1 and 0, respectively.
- `--num_scales 3 --scale_gap 0.15`: Use 3 scales, 1, (1-0.15), (1-0.15*2). Default is one scale. If you want to change the initial scale, you actually want to multiply your desired initial scale by the `net_resolution`.
- `--net_resolution 656x368 --resolution 1280x720`: For HD images and video (default values).
- `--net_resolution 496x368 --resolution 640x480`: For VGA images and video.
- `--model_pose MPI`: It will use MPI (15 body keypoints). Default: COCO (18 body keypoints). MPI is slightly faster. The variation `MPI_4_layers` sacrifies accuracy in order to further increase speed.
- `--logging_level 3`: Logging messages threshold, range [0,255]: 0 will output any message & 255 will output none. Current messages in the range [1-4], 1 for low priority messages and 4 for important ones.
## Rendering Face without Pose
```
./build/examples/openpose/openpose.bin --face --no_render_pose
```
## Example
The following example runs the video `vid.mp4`, renders image frames on `output/result.avi`, and outputs JSON files as `output/%12d.json`, parallelizing over 2 GPUs:
```
......
......@@ -181,6 +181,20 @@ bin\OpenPoseDemo.exe --image_dir examples/media/
windows_project\x64\Release\OpenPoseDemo.exe --image_dir examples/media/
```
**4. Body Pose and Face Keypoint Detector (e.g. on Video)**
```
# Ubuntu
./build/examples/openpose/openpose.bin --video examples/media/video.avi --face
```
```
:: Windows - Demo
bin\OpenPoseDemo.exe --video examples/media/video.avi --face
```
```
:: Windows - Library
windows_project\x64\Release\OpenPoseDemo.exe --video examples/media/video.avi --face
```
The visual GUI should show the original image with the poses blended on it, similarly to the pose of this gif:
<p align="center">
<img src="media/shake.gif", width="720">
......
......@@ -180,7 +180,7 @@ The human body pose detection is wrapped into the `WPoseExtractor<T>` worker and
Currently, only `PoseExtractorCaffe` is implemented, which uses the Caffe framework. We might add other famous frameworks later (e.g. Torch or TensorFlow). If you compile our library with any other framework, please email us or make a pull request! We are really interested in adding any other Deep Net framework, and the code is mostly prepared for it. Just create the equivalent `PoseExtractorDesiredFramework` and make the pull request!
#### Constructor
In order to be initialized, `PoseExtractorCaffe` has the following constructor and parameters: `PoseExtractorCaffe(const cv::Size& netInputSize, const cv::Size& netOutputSize, const cv::Size& outputSize, const int scaleNumber, const double scaleGap, const PoseModel poseModel, const std::string& modelsFolder, const int gpuId)`.
In order to be initialized, `PoseExtractorCaffe` has the following constructor and parameters: `PoseExtractorCaffe(const Point<int>& netInputSize, const Point<int>& netOutputSize, const Point<int>& outputSize, const int scaleNumber, const double scaleGap, const PoseModel poseModel, const std::string& modelsFolder, const int gpuId)`.
1. `netInputSize` is the resolution of the first layer of the deep net. I.e., the frames given to this class must have that size.
......@@ -199,7 +199,7 @@ In order to be initialized, `PoseExtractorCaffe` has the following constructor a
#### Detect Human Pose
In order to detect the human pose:
1. First run the deep net over the desired target image, by using `forwardPass(const Array<float>& inputNetData, const cv::Size& inputDataSize)`. `inputNetData` is the input image scaled to `netInputSize`, while `inputDataSize` indicates the original frame resolution before being rescaled to `netInputSize` (this is required given that we resize the images keeping the original aspect ratio).
1. First run the deep net over the desired target image, by using `forwardPass(const Array<float>& inputNetData, const Point<int>& inputDataSize)`. `inputNetData` is the input image scaled to `netInputSize`, while `inputDataSize` indicates the original frame resolution before being rescaled to `netInputSize` (this is required given that we resize the images keeping the original aspect ratio).
2. After, you can choose either to get:
1. The people pose as a op::Array<float>: `Array<float> getPose()`.
......@@ -213,13 +213,13 @@ Due to performance reasons, we only copy the people pose data given by `getPose(
After estimating the pose, you usually desired to visualize it. `PoseRenderer` does this work for you.
#### Constructor
In order to be initialized, `PoseRenderer` has the following constructor and parameters: `PoseRenderer(const cv::Size& netOutputSize, const cv::Size& outputSize, const PoseModel poseModel, const std::shared_ptr<PoseExtractor>& poseExtractor, const float alphaPose, const float alphaHeatmap)`.
In order to be initialized, `PoseRenderer` has the following constructor and parameters: `PoseRenderer(const Point<int>& netOutputSize, const Point<int>& outputSize, const PoseModel poseModel, const std::shared_ptr<PoseExtractor>& poseExtractor, const float alphaKeypoint, const float alphaHeatMap)`.
1. `netOutputSize`, `outputSize` and `poseModel` are the same as the ones used for `PoseExtractorCaffe`.
2. `poseExtractor` is the pose extractor used previously. It is only used for heatmap and PAFs rendering, since the GPU data is not copied to `op::Datum` for performance purposes. If any of the heatmaps are gonna be rendered, `PoseRenderer` must be placed in the same thread as `PoseExtractor`. Otherwise, it will throw a runtime exception.
3. `alphaPose` and `alphaHeatMap` controls the blending coefficient between original frame and rendered pose or heatmap/PAF respectively. A value `alphaPose = 1` will render the pose with no transparency at all, while `alphaPose = 0` will not be visible. In addition, `alphaHeatMap = 1` would only show the heatmap, while `alphaHeatMap = 0` would only show the original frame.
3. `alphaKeypoint` and `alphaHeatMap` controls the blending coefficient between original frame and rendered pose or heatmap/PAF respectively. A value `alphaKeypoint = 1` will render the pose with no transparency at all, while `alphaKeypoint = 0` will not be visible. In addition, `alphaHeatMap = 1` would only show the heatmap, while `alphaHeatMap = 0` would only show the original frame.
#### Render Human Pose
In order to render the detected human pose, run `std::pair<int, std::string> renderPose(Array<float>& outputData, const Array<float>& pose, const double scaleNetToOutput)`.
......
doc/media/paf_heat_maps.png

177.8 KB | W: | H:

doc/media/paf_heat_maps.png

1.8 MB | W: | H:

doc/media/paf_heat_maps.png
doc/media/paf_heat_maps.png
doc/media/paf_heat_maps.png
doc/media/paf_heat_maps.png
  • 2-up
  • Swipe
  • Onion skin
OpenPose Library - Release Notes
====================================
## OpenPose 1.0.0rc1
1. Initial version, main functionality:
1. Body keypoint detection and rendering on Ubuntu 14 and 16.
2. It can read an image directory, video or webcam.
3. It can display the results or storing them on disk.
## OpenPose 1.0.0rc2
1. Main improvements:
1. Rendering max resolution from 720p to >32k images.
2. Highly improved documentation.
2. Functions or paremeters renamed:
1. Demo renamed from rtpose to openpose.
3. Main bugs fixed:
1. Demo uses exec instead of start, so it works with more OpenCV custom compiled versions.
## OpenPose 1.0.0rc3
1. Main improvements:
1. Added face keypoint detection.
2. Added Windows 10 compatibily.
3. Auto-detection of the number of GPUs.
4. MPI visualization more similar to COCO one.
5. Rendering max resolution from 720p to >32k images.
6. GUI info adder working when the worker TDatum has more than 1 Datum.
7. It prints out the error description before throwing the exception (so that it is writen on the Windows cmd).
8. Highly improved documentation.
2. Functions or paremeters renamed:
1. Flag `write_pose` renamed as `write_keypoint` and it also applies to face and/or hands.
2. Flag `write_pose_json` renamed as `write_keypoint_json` and it also applies to face and/or hands.
3. Flag `write_pose_format` renamed as `write_keypoint_format` and it also applies to face and/or hands.
4. PoseSaver and its JSON variant renamed as KeypointSaver.
5. PoseJsonCocoSaver renamed as CocoJsonSaver.
3. Main bugs fixed:
1. All visualization functions moved to same thread, so it works with most OpenCV custom compiled versions.
2. Fixed error on debug mode: `Too many resources requested for launch`.
此差异已折叠。
......@@ -10,7 +10,7 @@
// 3rdpary depencencies
#include <gflags/gflags.h> // DEFINE_bool, DEFINE_int32, DEFINE_int64, DEFINE_uint64, DEFINE_double, DEFINE_string
#include <glog/logging.h> // google::InitGoogleLogging, CHECK, CHECK_EQ, LOG, VLOG, ...
#include <glog/logging.h> // google::InitGoogleLogging
// OpenPose dependencies
#include <openpose/core/headers.hpp>
#include <openpose/filestream/headers.hpp>
......@@ -18,8 +18,9 @@
#include <openpose/pose/headers.hpp>
#include <openpose/utilities/headers.hpp>
// Gflags in the command line terminal. Check all the options by adding the flag `--help`, e.g. `openpose.bin --help`.
// Note: This command will show you flags for several files. Check only the flags for the file you are checking. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`.
// See all the available parameter options withe 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
DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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.");
......@@ -28,7 +29,7 @@ DEFINE_string(image_path, "examples/media/COCO_val2014_00000000019
// OpenPose
DEFINE_string(model_pose, "COCO", "Model to be used (e.g. COCO, MPI, MPI_4_layers).");
DEFINE_string(model_folder, "models/", "Folder where the pose models (COCO and MPI) are located.");
DEFINE_string(net_resolution, "656x368", "Multiples of 16.");
DEFINE_string(net_resolution, "656x368", "Multiples of 16. If it is increased, the accuracy usually increases. If it is decreased, the speed increases.");
DEFINE_string(resolution, "1280x720", "The image resolution (display). Use \"-1x-1\" to force the program to use the default images resolution.");
DEFINE_int32(num_gpu_start, 0, "GPU device start number.");
DEFINE_double(scale_gap, 0.3, "Scale gap between scales. No effect unless num_scales>1. Initial scale is always 1. If you want to change the initial scale, "
......@@ -54,16 +55,16 @@ op::PoseModel gflagToPoseModel(const std::string& poseModeString)
}
// Google flags into program variables
std::tuple<cv::Size, cv::Size, cv::Size, op::PoseModel> gflagsToOpParameters()
std::tuple<op::Point<int>, op::Point<int>, op::Point<int>, op::PoseModel> gflagsToOpParameters()
{
op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__);
// outputSize
cv::Size outputSize;
auto nRead = sscanf(FLAGS_resolution.c_str(), "%dx%d", &outputSize.width, &outputSize.height);
op::Point<int> outputSize;
auto nRead = sscanf(FLAGS_resolution.c_str(), "%dx%d", &outputSize.x, &outputSize.y);
op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ", __LINE__, __FUNCTION__, __FILE__);
// netInputSize
cv::Size netInputSize;
nRead = sscanf(FLAGS_net_resolution.c_str(), "%dx%d", &netInputSize.width, &netInputSize.height);
op::Point<int> netInputSize;
nRead = sscanf(FLAGS_net_resolution.c_str(), "%dx%d", &netInputSize.x, &netInputSize.y);
op::checkE(nRead, 2, "Error, net resolution format (" + FLAGS_net_resolution + ") invalid, should be e.g., 656x368 (multiples of 16)", __LINE__, __FUNCTION__, __FILE__);
// netOutputSize
const auto netOutputSize = netInputSize;
......@@ -89,9 +90,9 @@ int openPoseTutorialPose1()
op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", __LINE__, __FUNCTION__, __FILE__);
op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);
// Step 2 - Read Google flags (user defined configuration)
cv::Size outputSize;
cv::Size netInputSize;
cv::Size netOutputSize;
op::Point<int> outputSize;
op::Point<int> netInputSize;
op::Point<int> netOutputSize;
op::PoseModel poseModel;
std::tie(outputSize, netInputSize, netOutputSize, poseModel) = gflagsToOpParameters();
// Step 3 - Initialize all required classes
......@@ -101,7 +102,7 @@ int openPoseTutorialPose1()
FLAGS_model_folder, FLAGS_num_gpu_start};
op::PoseRenderer poseRenderer{netOutputSize, outputSize, poseModel, nullptr, (float)FLAGS_alpha_pose};
op::OpOutputToCvMat opOutputToCvMat{outputSize};
const cv::Size windowedSize = outputSize;
const op::Point<int> windowedSize = outputSize;
op::FrameDisplayer frameDisplayer{windowedSize, "OpenPose Tutorial - Example 1"};
// Step 4 - Initialize resources on desired thread (in this case single thread, i.e. we init resources here)
poseExtractorCaffe.initializationOnThread();
......@@ -117,11 +118,11 @@ int openPoseTutorialPose1()
double scaleInputToOutput;
op::Array<float> outputArray;
std::tie(scaleInputToOutput, outputArray) = cvMatToOpOutput.format(inputImage);
// Step 3 - Estimate poseKeyPoints
poseExtractorCaffe.forwardPass(netInputArray, inputImage.size());
const auto poseKeyPoints = poseExtractorCaffe.getPoseKeyPoints();
// Step 4 - Render poseKeyPoints
poseRenderer.renderPose(outputArray, poseKeyPoints);
// Step 3 - Estimate poseKeypoints
poseExtractorCaffe.forwardPass(netInputArray, {inputImage.cols, inputImage.rows});
const auto poseKeypoints = poseExtractorCaffe.getPoseKeypoints();
// Step 4 - Render poseKeypoints
poseRenderer.renderPose(outputArray, poseKeypoints);
// Step 5 - OpenPose output format to cv::Mat
auto outputImage = opOutputToCvMat.formatToCvMat(outputArray);
......
......@@ -10,7 +10,7 @@
// 3rdpary depencencies
#include <gflags/gflags.h> // DEFINE_bool, DEFINE_int32, DEFINE_int64, DEFINE_uint64, DEFINE_double, DEFINE_string
#include <glog/logging.h> // google::InitGoogleLogging, CHECK, CHECK_EQ, LOG, VLOG, ...
#include <glog/logging.h> // google::InitGoogleLogging
// OpenPose dependencies
#include <openpose/core/headers.hpp>
#include <openpose/filestream/headers.hpp>
......@@ -18,8 +18,9 @@
#include <openpose/pose/headers.hpp>
#include <openpose/utilities/headers.hpp>
// Gflags in the command line terminal. Check all the options by adding the flag `--help`, e.g. `openpose.bin --help`.
// Note: This command will show you flags for several files. Check only the flags for the file you are checking. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`.
// See all the available parameter options withe 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
DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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.");
......@@ -28,7 +29,7 @@ DEFINE_string(image_path, "examples/media/COCO_val2014_00000000019
// OpenPose
DEFINE_string(model_pose, "COCO", "Model to be used (e.g. COCO, MPI, MPI_4_layers).");
DEFINE_string(model_folder, "models/", "Folder where the pose models (COCO and MPI) are located.");
DEFINE_string(net_resolution, "656x368", "Multiples of 16.");
DEFINE_string(net_resolution, "656x368", "Multiples of 16. If it is increased, the accuracy usually increases. If it is decreased, the speed increases.");
DEFINE_string(resolution, "1280x720", "The image resolution (display). Use \"-1x-1\" to force the program to use the default images resolution.");
DEFINE_int32(num_gpu_start, 0, "GPU device start number.");
DEFINE_double(scale_gap, 0.3, "Scale gap between scales. No effect unless num_scales>1. Initial scale is always 1. If you want to change the initial scale, "
......@@ -56,16 +57,16 @@ op::PoseModel gflagToPoseModel(const std::string& poseModeString)
}
// Google flags into program variables
std::tuple<cv::Size, cv::Size, cv::Size, op::PoseModel> gflagsToOpParameters()
std::tuple<op::Point<int>, op::Point<int>, op::Point<int>, op::PoseModel> gflagsToOpParameters()
{
op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__);
// outputSize
cv::Size outputSize;
auto nRead = sscanf(FLAGS_resolution.c_str(), "%dx%d", &outputSize.width, &outputSize.height);
op::Point<int> outputSize;
auto nRead = sscanf(FLAGS_resolution.c_str(), "%dx%d", &outputSize.x, &outputSize.y);
op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ", __LINE__, __FUNCTION__, __FILE__);
// netInputSize
cv::Size netInputSize;
nRead = sscanf(FLAGS_net_resolution.c_str(), "%dx%d", &netInputSize.width, &netInputSize.height);
op::Point<int> netInputSize;
nRead = sscanf(FLAGS_net_resolution.c_str(), "%dx%d", &netInputSize.x, &netInputSize.y);
op::checkE(nRead, 2, "Error, net resolution format (" + FLAGS_net_resolution + ") invalid, should be e.g., 656x368 (multiples of 16)", __LINE__, __FUNCTION__, __FILE__);
// netOutputSize
const auto netOutputSize = netInputSize;
......@@ -91,9 +92,9 @@ int openPoseTutorialPose2()
op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", __LINE__, __FUNCTION__, __FILE__);
op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);
// Step 2 - Read Google flags (user defined configuration)
cv::Size outputSize;
cv::Size netInputSize;
cv::Size netOutputSize;
op::Point<int> outputSize;
op::Point<int> netInputSize;
op::Point<int> netOutputSize;
op::PoseModel poseModel;
std::tie(outputSize, netInputSize, netOutputSize, poseModel) = gflagsToOpParameters();
// Step 3 - Initialize all required classes
......@@ -105,7 +106,7 @@ int openPoseTutorialPose2()
op::PoseRenderer poseRenderer{netOutputSize, outputSize, poseModel, poseExtractorPtr, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap};
poseRenderer.setElementToRender(FLAGS_part_to_show);
op::OpOutputToCvMat opOutputToCvMat{outputSize};
const cv::Size windowedSize = outputSize;
const op::Point<int> windowedSize = outputSize;
op::FrameDisplayer frameDisplayer{windowedSize, "OpenPose Tutorial - Example 2"};
// Step 4 - Initialize resources on desired thread (in this case single thread, i.e. we init resources here)
poseExtractorPtr->initializationOnThread();
......@@ -121,12 +122,12 @@ int openPoseTutorialPose2()
double scaleInputToOutput;
op::Array<float> outputArray;
std::tie(scaleInputToOutput, outputArray) = cvMatToOpOutput.format(inputImage);
// Step 3 - Estimate poseKeyPoints
poseExtractorPtr->forwardPass(netInputArray, inputImage.size());
const auto poseKeyPoints = poseExtractorPtr->getPoseKeyPoints();
// Step 3 - Estimate poseKeypoints
poseExtractorPtr->forwardPass(netInputArray, {inputImage.cols, inputImage.rows});
const auto poseKeypoints = poseExtractorPtr->getPoseKeypoints();
const auto scaleNetToOutput = poseExtractorPtr->getScaleNetToOutput();
// Step 4 - Render pose
poseRenderer.renderPose(outputArray, poseKeyPoints, scaleNetToOutput);
poseRenderer.renderPose(outputArray, poseKeypoints, scaleNetToOutput);
// Step 5 - OpenPose output format to cv::Mat
auto outputImage = opOutputToCvMat.formatToCvMat(outputArray);
......
......@@ -9,7 +9,7 @@
// 3rdpary depencencies
#include <gflags/gflags.h> // DEFINE_bool, DEFINE_int32, DEFINE_int64, DEFINE_uint64, DEFINE_double, DEFINE_string
#include <glog/logging.h> // google::InitGoogleLogging, CHECK, CHECK_EQ, LOG, VLOG, ...
#include <glog/logging.h> // google::InitGoogleLogging
// OpenPose dependencies
#include <openpose/core/headers.hpp>
#include <openpose/gui/headers.hpp>
......@@ -17,8 +17,9 @@
#include <openpose/thread/headers.hpp>
#include <openpose/utilities/headers.hpp>
// Gflags in the command line terminal. Check all the options by adding the flag `--help`, e.g. `openpose.bin --help`.
// Note: This command will show you flags for several files. Check only the flags for the file you are checking. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`.
// See all the available parameter options withe 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
DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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.");
......@@ -55,7 +56,7 @@ op::ProducerType gflagsToProducerType(const std::string& imageDirectory, const s
return op::ProducerType::Webcam;
}
std::shared_ptr<op::Producer> gflagsToProducer(const std::string& imageDirectory, const std::string& videoPath, const int webcamIndex, const cv::Size webcamResolution)
std::shared_ptr<op::Producer> gflagsToProducer(const std::string& imageDirectory, const std::string& videoPath, const int webcamIndex, const op::Point<int> webcamResolution)
{
op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__);
const auto type = gflagsToProducerType(imageDirectory, videoPath, webcamIndex);
......@@ -74,16 +75,16 @@ std::shared_ptr<op::Producer> gflagsToProducer(const std::string& imageDirectory
}
// Google flags into program variables
std::tuple<cv::Size, cv::Size, std::shared_ptr<op::Producer>> gflagsToOpParameters()
std::tuple<op::Point<int>, op::Point<int>, std::shared_ptr<op::Producer>> gflagsToOpParameters()
{
op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__);
// cameraFrameSize
cv::Size cameraFrameSize;
auto nRead = sscanf(FLAGS_camera_resolution.c_str(), "%dx%d", &cameraFrameSize.width, &cameraFrameSize.height);
op::Point<int> cameraFrameSize;
auto nRead = sscanf(FLAGS_camera_resolution.c_str(), "%dx%d", &cameraFrameSize.x, &cameraFrameSize.y);
op::checkE(nRead, 2, "Error, camera resolution format (" + FLAGS_camera_resolution + ") invalid, should be e.g., 1280x720", __LINE__, __FUNCTION__, __FILE__);
// outputSize
cv::Size outputSize;
nRead = sscanf(FLAGS_resolution.c_str(), "%dx%d", &outputSize.width, &outputSize.height);
op::Point<int> outputSize;
nRead = sscanf(FLAGS_resolution.c_str(), "%dx%d", &outputSize.x, &outputSize.y);
op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ", __LINE__, __FUNCTION__, __FILE__);
// producerType
......@@ -105,17 +106,17 @@ int openPoseTutorialThread1()
op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", __LINE__, __FUNCTION__, __FILE__);
op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);
// Step 2 - Read Google flags (user defined configuration)
cv::Size cameraFrameSize;
cv::Size outputSize;
op::Point<int> cameraFrameSize;
op::Point<int> outputSize;
std::shared_ptr<op::Producer> producerSharedPtr;
std::tie(cameraFrameSize, outputSize, producerSharedPtr) = gflagsToOpParameters();
// Step 3 - Setting producer
auto videoSeekSharedPtr = std::make_shared<std::pair<std::atomic<bool>, std::atomic<int>>>();
videoSeekSharedPtr->first = false;
videoSeekSharedPtr->second = 0;
const cv::Size producerSize{(int)producerSharedPtr->get(CV_CAP_PROP_FRAME_WIDTH),
const op::Point<int> producerSize{(int)producerSharedPtr->get(CV_CAP_PROP_FRAME_WIDTH),
(int)producerSharedPtr->get(CV_CAP_PROP_FRAME_HEIGHT)};
if (outputSize.width == -1 || outputSize.height == -1)
if (outputSize.x == -1 || outputSize.y == -1)
{
if (producerSize.area() > 0)
outputSize = producerSize;
......@@ -162,7 +163,7 @@ int openPoseTutorialThread1()
// ------------------------- STARTING AND STOPPING THREADING -------------------------
op::log("Starting thread(s)", op::Priority::Max);
// Two different ways of running the program on multithread enviroment
// Two different ways of running the program on multithread environment
// Option a) Using the main thread (this thread) for processing (it saves 1 thread, recommended)
threadManager.exec(); // It blocks this thread until all threads have finished
// Option b) Giving to the user the control of this thread
......
......@@ -10,7 +10,7 @@
// 3rdpary depencencies
#include <gflags/gflags.h> // DEFINE_bool, DEFINE_int32, DEFINE_int64, DEFINE_uint64, DEFINE_double, DEFINE_string
#include <glog/logging.h> // google::InitGoogleLogging, CHECK, CHECK_EQ, LOG, VLOG, ...
#include <glog/logging.h> // google::InitGoogleLogging
// OpenPose dependencies
#include <openpose/core/headers.hpp>
#include <openpose/gui/headers.hpp>
......@@ -18,8 +18,9 @@
#include <openpose/thread/headers.hpp>
#include <openpose/utilities/headers.hpp>
// Gflags in the command line terminal. Check all the options by adding the flag `--help`, e.g. `openpose.bin --help`.
// Note: This command will show you flags for several files. Check only the flags for the file you are checking. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`.
// See all the available parameter options withe 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
DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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.");
......@@ -89,7 +90,7 @@ op::ProducerType gflagsToProducerType(const std::string& imageDirectory, const s
return op::ProducerType::Webcam;
}
std::shared_ptr<op::Producer> gflagsToProducer(const std::string& imageDirectory, const std::string& videoPath, const int webcamIndex, const cv::Size webcamResolution)
std::shared_ptr<op::Producer> gflagsToProducer(const std::string& imageDirectory, const std::string& videoPath, const int webcamIndex, const op::Point<int> webcamResolution)
{
op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__);
const auto type = gflagsToProducerType(imageDirectory, videoPath, webcamIndex);
......@@ -108,16 +109,16 @@ std::shared_ptr<op::Producer> gflagsToProducer(const std::string& imageDirectory
}
// Google flags into program variables
std::tuple<cv::Size, cv::Size, std::shared_ptr<op::Producer>> gflagsToOpParameters()
std::tuple<op::Point<int>, op::Point<int>, std::shared_ptr<op::Producer>> gflagsToOpParameters()
{
op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__);
// cameraFrameSize
cv::Size cameraFrameSize;
auto nRead = sscanf(FLAGS_camera_resolution.c_str(), "%dx%d", &cameraFrameSize.width, &cameraFrameSize.height);
op::Point<int> cameraFrameSize;
auto nRead = sscanf(FLAGS_camera_resolution.c_str(), "%dx%d", &cameraFrameSize.x, &cameraFrameSize.y);
op::checkE(nRead, 2, "Error, camera resolution format (" + FLAGS_camera_resolution + ") invalid, should be e.g., 1280x720", __LINE__, __FUNCTION__, __FILE__);
// outputSize
cv::Size outputSize;
nRead = sscanf(FLAGS_resolution.c_str(), "%dx%d", &outputSize.width, &outputSize.height);
op::Point<int> outputSize;
nRead = sscanf(FLAGS_resolution.c_str(), "%dx%d", &outputSize.x, &outputSize.y);
op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ", __LINE__, __FUNCTION__, __FILE__);
// producerType
......@@ -139,17 +140,17 @@ int openPoseTutorialThread2()
op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", __LINE__, __FUNCTION__, __FILE__);
op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);
// Step 2 - Read Google flags (user defined configuration)
cv::Size cameraFrameSize;
cv::Size outputSize;
op::Point<int> cameraFrameSize;
op::Point<int> outputSize;
std::shared_ptr<op::Producer> producerSharedPtr;
std::tie(cameraFrameSize, outputSize, producerSharedPtr) = gflagsToOpParameters();
// Step 3 - Setting producer
auto videoSeekSharedPtr = std::make_shared<std::pair<std::atomic<bool>, std::atomic<int>>>();
videoSeekSharedPtr->first = false;
videoSeekSharedPtr->second = 0;
const cv::Size producerSize{(int)producerSharedPtr->get(CV_CAP_PROP_FRAME_WIDTH),
const op::Point<int> producerSize{(int)producerSharedPtr->get(CV_CAP_PROP_FRAME_WIDTH),
(int)producerSharedPtr->get(CV_CAP_PROP_FRAME_HEIGHT)};
if (outputSize.width == -1 || outputSize.height == -1)
if (outputSize.x == -1 || outputSize.y == -1)
{
if (producerSize.area() > 0)
outputSize = producerSize;
......@@ -204,7 +205,7 @@ int openPoseTutorialThread2()
// ------------------------- STARTING AND STOPPING THREADING -------------------------
op::log("Starting thread(s)", op::Priority::Max);
// Two different ways of running the program on multithread enviroment
// Two different ways of running the program on multithread environment
// Option a) Using the main thread (this thread) for processing (it saves 1 thread, recommended)
threadManager.exec(); // It blocks this thread until all threads have finished
// Option b) Giving to the user the control of this thread
......
......@@ -10,7 +10,7 @@
// 3rdpary depencencies
#include <gflags/gflags.h> // DEFINE_bool, DEFINE_int32, DEFINE_int64, DEFINE_uint64, DEFINE_double, DEFINE_string
#include <glog/logging.h> // google::InitGoogleLogging, CHECK, CHECK_EQ, LOG, VLOG, ...
#include <glog/logging.h> // google::InitGoogleLogging
// OpenPose dependencies
// Option a) Importing all modules
#include <openpose/headers.hpp>
......@@ -23,8 +23,9 @@
// #include <openpose/thread/headers.hpp>
// #include <openpose/utilities/headers.hpp>
// Gflags in the command line terminal. Check all the options by adding the flag `--help`, e.g. `openpose.bin --help`.
// Note: This command will show you flags for several files. Check only the flags for the file you are checking. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`.
// See all the available parameter options withe 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
DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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.");
......@@ -114,7 +115,7 @@ public:
{
// User's post-processing (after OpenPose processing & before OpenPose outputs) here
// datum.cvOutputData: rendered frame with pose or heatmaps
// datum.poseKeyPoints: Array<float> with the estimated pose
// datum.poseKeypoints: Array<float> with the estimated pose
try
{
if (datumsPtr != nullptr && !datumsPtr->empty())
......@@ -142,7 +143,7 @@ public:
{
// User's displaying/saving/other processing here
// datum.cvOutputData: rendered frame with pose or heatmaps
// datum.poseKeyPoints: Array<float> with the estimated pose
// datum.poseKeypoints: Array<float> with the estimated pose
if (datumsPtr != nullptr && !datumsPtr->empty())
{
cv::imshow("User worker GUI", datumsPtr->at(0).cvOutputData);
......@@ -195,7 +196,7 @@ int openPoseTutorialThread3()
// ------------------------- STARTING AND STOPPING THREADING -------------------------
op::log("Starting thread(s)", op::Priority::Max);
// Two different ways of running the program on multithread enviroment
// Two different ways of running the program on multithread environment
// Option a) Using the main thread (this thread) for processing (it saves 1 thread, recommended)
threadManager.exec(); // It blocks this thread until all threads have finished
// Option b) Giving to the user the control of this thread
......
......@@ -10,7 +10,7 @@
// 3rdpary depencencies
#include <gflags/gflags.h> // DEFINE_bool, DEFINE_int32, DEFINE_int64, DEFINE_uint64, DEFINE_double, DEFINE_string
#include <glog/logging.h> // google::InitGoogleLogging, CHECK, CHECK_EQ, LOG, VLOG, ...
#include <glog/logging.h> // google::InitGoogleLogging
// OpenPose dependencies
// Option a) Importing all modules
#include <openpose/headers.hpp>
......@@ -23,8 +23,9 @@
// #include <openpose/thread/headers.hpp>
// #include <openpose/utilities/headers.hpp>
// Gflags in the command line terminal. Check all the options by adding the flag `--help`, e.g. `openpose.bin --help`.
// Note: This command will show you flags for several files. Check only the flags for the file you are checking. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`.
// See all the available parameter options withe 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
DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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.");
......@@ -126,7 +127,7 @@ public:
{
// User's post-processing (after OpenPose processing & before OpenPose outputs) here
// datum.cvOutputData: rendered frame with pose or heatmaps
// datum.poseKeyPoints: Array<float> with the estimated pose
// datum.poseKeypoints: Array<float> with the estimated pose
try
{
if (datumsPtr != nullptr && !datumsPtr->empty())
......@@ -154,7 +155,7 @@ public:
{
// User's displaying/saving/other processing here
// datum.cvOutputData: rendered frame with pose or heatmaps
// datum.poseKeyPoints: Array<float> with the estimated pose
// datum.poseKeypoints: Array<float> with the estimated pose
if (datumsPtr != nullptr && !datumsPtr->empty())
{
cv::imshow("User worker GUI", datumsPtr->at(0).cvOutputData);
......@@ -207,7 +208,7 @@ int openPoseTutorialThread4()
// ------------------------- STARTING AND STOPPING THREADING -------------------------
op::log("Starting thread(s)", op::Priority::Max);
// Two different ways of running the program on multithread enviroment
// Two different ways of running the program on multithread environment
// Option a) Using the main thread (this thread) for processing (it saves 1 thread, recommended)
threadManager.exec(); // It blocks this thread until all threads have finished
// Option b) Giving to the user the control of this thread
......
......@@ -2,7 +2,7 @@
// Asynchronous mode: ideal for fast prototyping when performance is not an issue. The user emplaces/pushes and pops frames from the OpenPose wrapper when he desires to.
// This example shows the user how to use the OpenPose wrapper class:
// 1. Extract and render pose / heatmap / PAF of that image
// 1. Extract and render keypoint / heatmap / PAF of that image
// 2. Save the results on disc
// 3. Display the rendered pose
// Everything in a multi-thread scenario
......@@ -20,11 +20,9 @@
#include <string> // std::string
#include <thread> // std::this_thread
#include <vector> // std::vector
// OpenCV dependencies
#include <opencv2/core/core.hpp> // cv::Mat & cv::Size
// Other 3rdpary depencencies
#include <gflags/gflags.h> // DEFINE_bool, DEFINE_int32, DEFINE_int64, DEFINE_uint64, DEFINE_double, DEFINE_string
#include <glog/logging.h> // google::InitGoogleLogging, CHECK, CHECK_EQ, LOG, VLOG, ...
#include <glog/logging.h> // google::InitGoogleLogging
// OpenPose dependencies
// Option a) Importing all modules
......@@ -32,6 +30,7 @@
// Option b) Manually importing the desired modules. Recommended if you only intend to use a few modules.
// #include <openpose/core/headers.hpp>
// #include <openpose/experimental/headers.hpp>
// #include <openpose/face/headers.hpp>
// #include <openpose/filestream/headers.hpp>
// #include <openpose/gui/headers.hpp>
// #include <openpose/pose/headers.hpp>
......@@ -40,56 +39,63 @@
// #include <openpose/utilities/headers.hpp>
// #include <openpose/wrapper/headers.hpp>
// Uncomment to avoid needing `op::` before each class and function of the OpenPose library. Analogously for OpenCV and the standard C++ library
// using namespace op;
// using namespace cv;
// using namespace std;
// Gflags in the command line terminal. Check all the options by adding the flag `--help`, e.g. `openpose.bin --help`.
// Note: This command will show you flags for several files. Check only the flags for the file you are checking. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`.
// See all the available parameter options withe 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
DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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.");
// Producer
DEFINE_string(image_dir, "examples/media/", "Process a directory of images.");
// OpenPose
DEFINE_string(model_pose, "COCO", "Model to be used (e.g. COCO, MPI, MPI_4_layers).");
DEFINE_string(model_folder, "models/", "Folder where the pose models (COCO and MPI) are located.");
DEFINE_string(net_resolution, "656x368", "Multiples of 16.");
DEFINE_string(resolution, "1280x720", "The image resolution (display and output).");
DEFINE_int32(num_gpu, 1, "The number of GPU devices to use.");
DEFINE_string(resolution, "1280x720", "The image resolution (display and output). Use \"-1x-1\" to force the program to use the default images 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_keypoint` & `write_keypoint_json` 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], and 4 for range [-1,1]. Non related with `num_scales` and `scale_gap`.");
// OpenPose Body Pose
DEFINE_string(model_pose, "COCO", "Model to be used (e.g. COCO, MPI, MPI_4_layers).");
DEFINE_string(net_resolution, "656x368", "Multiples of 16. If it is increased, the accuracy usually increases. If it is decreased, the speed increases.");
DEFINE_int32(num_scales, 1, "Number of scales to average.");
DEFINE_double(scale_gap, 0.3, "Scale gap between scales. No effect unless num_scales>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.");
DEFINE_int32(scale_mode, 0, "Scaling of the (x,y) coordinates of the final pose data array (op::Datum::pose), i.e. the scale of the (x,y) coordinates that"
" will be saved with the `write_pose` & `write_pose_json` 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], and 4 for range [-1,1]. Non related with `num_scales` and `scale_gap`.");
DEFINE_bool(heatmaps_add_parts, false, "If true, it will add the body part heatmaps to the final op::Datum::poseHeatMaps array (program speed will decrease). Not"
" required for our library, enable it only if you intend to process this information later. 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 `include/openpose/pose/poseParameters.hpp`.");
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_mode, 2, "Set 0 to scale op::Datum::poseHeatMaps in the range [0,1], 1 for [-1,1]; and 2 for integer rounded [0,255].");
DEFINE_int32(heatmaps_scale, 2, "Set 0 to scale op::Datum::poseHeatMaps in the range [0,1], 1 for [-1,1]; and 2 for integer rounded [0,255].");
// OpenPose Face
DEFINE_bool(face, false, "Enables face keypoint detection. It will share some parameters from the body pose, e.g. `model_folder`.");
DEFINE_string(face_net_resolution, "368x368", "Multiples of 16. 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
// OpenPose Rendering
DEFINE_bool(no_render_output, false, "If false, it will fill both `outputData` and `cvOutputData` with the original image + desired part to be shown."
" If true, it will leave them empty.");
DEFINE_int32(part_to_show, 0, "Part to show from the start.");
DEFINE_bool(disable_blending, false, "If false, it will blend the results with the original frame. If true, it will only display the results.");
DEFINE_bool(disable_blending, false, "If blending is enabled, it will merge the results with the original frame. If disabled, it will only display the results.");
// OpenPose Rendering Pose
DEFINE_bool(no_render_pose, false, "If false, it will fill both `outputData` and `cvOutputData` with the original image + desired part to be shown."
" If true, it will leave them empty.");
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.");
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.");
// Consumer
// OpenPose Rendering Face
DEFINE_bool(no_render_face, false, "Analogous to `no_render_pose` but applied to the face keypoints and heat maps.");
DEFINE_double(alpha_face, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will hide it.");
DEFINE_double(alpha_heatmap_face, 0.7, "Blending factor (range 0-1) between heatmap and original frame. 1 will only show the heatmap, 0 will only show the frame.");
// 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.");
DEFINE_string(write_pose, "", "Directory to write the people pose data. Desired format on `write_pose_format`.");
DEFINE_string(write_pose_format, "yml", "File extension and format for `write_pose`: json, xml, yaml and yml. Json not available for OpenCV < 3.0,"
" use `write_pose_json` instead.");
DEFINE_string(write_pose_json, "", "Directory to write people pose data with *.json format, compatible with any OpenCV version.");
DEFINE_string(write_keypoint, "", "Directory to write the people body pose keypoint data. Desired format on `write_keypoint_format`.");
DEFINE_string(write_keypoint_format, "yml", "File extension and format for `write_keypoint`: json, xml, yaml and yml. Json not available for OpenCV < 3.0,"
" use `write_keypoint_json` instead.");
DEFINE_string(write_keypoint_json, "", "Directory to write people pose data with *.json format, compatible with any OpenCV version.");
DEFINE_string(write_coco_json, "", "Full file path to write people pose data with *.json COCO validation format.");
DEFINE_string(write_heatmaps, "", "Directory to write heatmaps with *.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`. Recommended `png` or any compressed and"
......@@ -176,7 +182,7 @@ public:
{
// User's displaying/saving/other processing here
// datum.cvOutputData: rendered frame with pose or heatmaps
// datum.poseKeyPoints: Array<float> with the estimated pose
// datum.poseKeypoints: Array<float> with the estimated pose
if (datumsPtr != nullptr && !datumsPtr->empty())
{
cv::imshow("User worker GUI", datumsPtr->at(0).cvOutputData);
......@@ -203,18 +209,18 @@ op::PoseModel gflagToPoseModel(const std::string& poseModeString)
}
}
op::ScaleMode gflagToScaleMode(const int scaleMode)
op::ScaleMode gflagToScaleMode(const int keypointScale)
{
op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__);
if (scaleMode == 0)
if (keypointScale == 0)
return op::ScaleMode::InputResolution;
else if (scaleMode == 1)
else if (keypointScale == 1)
return op::ScaleMode::NetOutputResolution;
else if (scaleMode == 2)
else if (keypointScale == 2)
return op::ScaleMode::OutputResolution;
else if (scaleMode == 3)
else if (keypointScale == 3)
return op::ScaleMode::ZeroToOne;
else if (scaleMode == 4)
else if (keypointScale == 4)
return op::ScaleMode::PlusMinusOne;
else
{
......@@ -238,27 +244,31 @@ std::vector<op::HeatMapType> gflagToHeatMaps(const bool heatmaps_add_parts, cons
}
// Google flags into program variables
std::tuple<cv::Size, cv::Size, op::PoseModel, op::ScaleMode, std::vector<op::HeatMapType>, op::ScaleMode> gflagsToOpParameters()
std::tuple<op::Point<int>, op::Point<int>, op::Point<int>, op::PoseModel, op::ScaleMode, std::vector<op::HeatMapType>, op::ScaleMode> gflagsToOpParameters()
{
op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__);
// outputSize
cv::Size outputSize;
auto nRead = sscanf(FLAGS_resolution.c_str(), "%dx%d", &outputSize.width, &outputSize.height);
op::Point<int> outputSize;
auto nRead = sscanf(FLAGS_resolution.c_str(), "%dx%d", &outputSize.x, &outputSize.y);
op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ", __LINE__, __FUNCTION__, __FILE__);
// netInputSize
cv::Size netInputSize;
nRead = sscanf(FLAGS_net_resolution.c_str(), "%dx%d", &netInputSize.width, &netInputSize.height);
op::Point<int> netInputSize;
nRead = sscanf(FLAGS_net_resolution.c_str(), "%dx%d", &netInputSize.x, &netInputSize.y);
op::checkE(nRead, 2, "Error, net resolution format (" + FLAGS_net_resolution + ") invalid, should be e.g., 656x368 (multiples of 16)", __LINE__, __FUNCTION__, __FILE__);
// faceNetInputSize
op::Point<int> faceNetInputSize;
nRead = sscanf(FLAGS_face_net_resolution.c_str(), "%dx%d", &faceNetInputSize.x, &faceNetInputSize.y);
op::checkE(nRead, 2, "Error, face net resolution format (" + FLAGS_face_net_resolution + ") invalid, should be e.g., 368x368 (multiples of 16)", __LINE__, __FUNCTION__, __FILE__);
// poseModel
const auto poseModel = gflagToPoseModel(FLAGS_model_pose);
// scaleMode
const auto scaleMode = gflagToScaleMode(FLAGS_scale_mode);
// keypointScale
const auto keypointScale = gflagToScaleMode(FLAGS_keypoint_scale);
// heatmaps to add
const auto heatMapTypes = gflagToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg, FLAGS_heatmaps_add_PAFs);
op::check(FLAGS_heatmaps_scale_mode >= 0 && FLAGS_heatmaps_scale_mode <= 2, "Non valid `heatmaps_scale_mode`.", __LINE__, __FUNCTION__, __FILE__);
const auto heatMapsScaleMode = (FLAGS_heatmaps_scale_mode == 0 ? op::ScaleMode::PlusMinusOne : (FLAGS_heatmaps_scale_mode == 1 ? op::ScaleMode::ZeroToOne : op::ScaleMode::UnsignedChar ));
op::check(FLAGS_heatmaps_scale >= 0 && FLAGS_heatmaps_scale <= 2, "Non valid `heatmaps_scale`.", __LINE__, __FUNCTION__, __FILE__);
const auto heatMapScale = (FLAGS_heatmaps_scale == 0 ? op::ScaleMode::PlusMinusOne : (FLAGS_heatmaps_scale == 1 ? op::ScaleMode::ZeroToOne : op::ScaleMode::UnsignedChar ));
// return
return std::make_tuple(outputSize, netInputSize, poseModel, scaleMode, heatMapTypes, heatMapsScaleMode);
return std::make_tuple(outputSize, netInputSize, faceNetInputSize, poseModel, keypointScale, heatMapTypes, heatMapScale);
}
int openPoseTutorialWrapper1()
......@@ -272,13 +282,14 @@ int openPoseTutorialWrapper1()
const auto timerBegin = std::chrono::high_resolution_clock::now();
// Applying user defined configuration
cv::Size outputSize;
cv::Size netInputSize;
op::Point<int> outputSize;
op::Point<int> netInputSize;
op::Point<int> faceNetInputSize;
op::PoseModel poseModel;
op::ScaleMode scaleMode;
op::ScaleMode keypointScale;
std::vector<op::HeatMapType> heatMapTypes;
op::ScaleMode heatMapsScaleMode;
std::tie(outputSize, netInputSize, poseModel, scaleMode, heatMapTypes, heatMapsScaleMode) = gflagsToOpParameters();
op::ScaleMode heatMapScale;
std::tie(outputSize, netInputSize, faceNetInputSize, poseModel, keypointScale, heatMapTypes, heatMapScale) = gflagsToOpParameters();
op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__);
// Configure OpenPose
......@@ -286,16 +297,19 @@ int openPoseTutorialWrapper1()
const bool displayGui = false;
const bool guiVerbose = false;
const bool fullScreen = false;
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::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 WrapperStructPose{} for default and recommended configuration)
// Producer (use default to disable any input)
const op::WrapperStructPose wrapperStructPose{netInputSize, outputSize, keypointScale, FLAGS_num_gpu, FLAGS_num_gpu_start, FLAGS_num_scales, (float)FLAGS_scale_gap,
!FLAGS_no_render_pose, poseModel, !FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap,
FLAGS_part_to_show, FLAGS_model_folder, heatMapTypes, heatMapScale};
// (Experimental, function and class names might change in next versions) Face configuration (use op::WrapperStructFace{} to disable it)
const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, !FLAGS_no_render_face, (float)FLAGS_alpha_face, (float)FLAGS_alpha_heatmap_face};
// (Experimental, function and class names might change in next versions) Hand configuration (use op::WrapperStructFace{} to disable it)
const op::experimental::WrapperStructHand wrapperStructHand{false};
// Consumer (comment or use default argument to disable any output)
opWrapper.configure(wrapperStructPose, op::WrapperStructInput{}, wrapperStructOutput);
const op::WrapperStructOutput wrapperStructOutput{displayGui, guiVerbose, fullScreen, FLAGS_write_keypoint, op::stringToDataFormat(FLAGS_write_keypoint_format),
FLAGS_write_keypoint_json, FLAGS_write_coco_json, FLAGS_write_images, FLAGS_write_images_format, FLAGS_write_video,
FLAGS_write_heatmaps, FLAGS_write_heatmaps_format};
// Configure wrapper
opWrapper.configure(wrapperStructPose, wrapperStructFace, wrapperStructHand, op::WrapperStructInput{}, wrapperStructOutput);
// Set to single-thread running (e.g. for debugging purposes)
// opWrapper.disableMultiThreading();
......
#ifndef OPENPOSE__CORE__ARRAY_HPP
#define OPENPOSE__CORE__ARRAY_HPP
#ifndef OPENPOSE_CORE_ARRAY_HPP
#define OPENPOSE_CORE_ARRAY_HPP
#include <vector>
#include <opencv2/core/core.hpp>
#include <opencv2/core/core.hpp> // cv::Mat
#include <boost/shared_ptr.hpp> // Note: std::shared_ptr not (fully) supported for array pointers: http://stackoverflow.com/questions/8947579/
namespace op
......@@ -327,6 +327,20 @@ namespace op
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<T>::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<int> mSize;
size_t mVolume;
......@@ -363,4 +377,4 @@ namespace op
};
}
#endif // OPENPOSE__CORE__ARRAY_HPP
#endif // OPENPOSE_CORE_ARRAY_HPP
#ifndef OPENPOSE__CORE__CV_MAT_TO_OP_INPUT_HPP
#define OPENPOSE__CORE__CV_MAT_TO_OP_INPUT_HPP
#ifndef OPENPOSE_CORE_CV_MAT_TO_OP_INPUT_HPP
#define OPENPOSE_CORE_CV_MAT_TO_OP_INPUT_HPP
#include <vector>
#include <opencv2/core/core.hpp>
#include <opencv2/core/core.hpp> // cv::Mat
#include "array.hpp"
#include "point.hpp"
namespace op
{
class CvMatToOpInput
{
public:
CvMatToOpInput(const cv::Size& netInputResolution, const int scaleNumber = 1, const float scaleGap = 0.25);
CvMatToOpInput(const Point<int>& netInputResolution, const int scaleNumber = 1, const float scaleGap = 0.25);
Array<float> format(const cv::Mat& cvInputData) const;
......@@ -21,4 +22,4 @@ namespace op
};
}
#endif // OPENPOSE__CORE__CV_MAT_TO_OP_INPUT_HPP
#endif // OPENPOSE_CORE_CV_MAT_TO_OP_INPUT_HPP
#ifndef OPENPOSE__CORE__CV_MAT_TO_OP_OUTPUT_HPP
#define OPENPOSE__CORE__CV_MAT_TO_OP_OUTPUT_HPP
#ifndef OPENPOSE_CORE_CV_MAT_TO_OP_OUTPUT_HPP
#define OPENPOSE_CORE_CV_MAT_TO_OP_OUTPUT_HPP
#include <vector>
#include <opencv2/core/core.hpp>
#include <opencv2/core/core.hpp> // cv::Mat
#include "array.hpp"
#include "point.hpp"
namespace op
{
class CvMatToOpOutput
{
public:
CvMatToOpOutput(const cv::Size& outputResolution, const bool generateOutput = true);
CvMatToOpOutput(const Point<int>& outputResolution, const bool generateOutput = true);
std::tuple<double, Array<float>> format(const cv::Mat& cvInputData) const;
......@@ -20,4 +21,4 @@ namespace op
};
}
#endif // OPENPOSE__CORE__CV_MAT_TO_OP_OUTPUT_HPP
#endif // OPENPOSE_CORE_CV_MAT_TO_OP_OUTPUT_HPP
#ifndef OPENPOSE__CORE__DATUM_HPP
#define OPENPOSE__CORE__DATUM_HPP
#ifndef OPENPOSE_CORE_DATUM_HPP
#define OPENPOSE_CORE_DATUM_HPP
#include <memory> // std::shared_ptr
#include <string> // std::string
#include <opencv2/core/core.hpp> // cv::Mat
#include "array.hpp"
#include "point.hpp"
#include "rectangle.hpp"
namespace op
{
......@@ -17,7 +20,7 @@ namespace op
// -------------------------------------------------- ID parameters -------------------------------------------------- //
unsigned long long id; /**< Datum ID. Internally used to sort the Datums if multi-threading is used. */
std::string name; /**< Name used when saving the data to disk (e.g. `write_images` or `write_pose` flags in the demo). */
std::string name; /**< Name used when saving the data to disk (e.g. `write_images` or `write_keypoint` flags in the demo). */
// -------------------------------------------------- Input image and rendered version parameters -------------------------------------------------- //
/**
......@@ -37,7 +40,7 @@ namespace op
/**
* Rendered image in Array<float> format.
* It consists of a blending of the inputNetData and the pose/body part(s) heatmap/PAF(s).
* If rendering is disabled (e.g. `no_render_output` flag in the demo), then outputData will be empty.
* If rendering is disabled (e.g. `no_render_pose` flag in the demo), then outputData will be empty.
* Size: 3 x output_net_height x output_net_width
*/
Array<float> outputData;
......@@ -57,31 +60,38 @@ namespace op
* If outputData is empty, then cvOutputData will also be empty.
* Size: #people x #body parts (e.g. 18 for COCO or 15 for MPI) x 3 ((x,y) coordinates + score)
*/
Array<float> poseKeyPoints;
Array<float> poseKeypoints;
/**
* Body pose heatmaps (body parts, background and/or PAFs) for the whole image.
* This parameters 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_mode` flag in the examples/tutorial_wrapper/ for more details.
* The user can choose the heatmaps normalization: ranges [0, 1], [-1, 1] or [0, 255]. Check the `heatmaps_scale` flag in the examples/tutorial_wrapper/ for more details.
* Size: #heatmaps x output_net_height x output_net_width
*/
Array<float> poseHeatMaps;
/**
* Experimental (NOT IMPLEMENTED YET)
* Face code is in development phase. Not included in this version.
* Size: #people's faces to render x #face parts (71) x 3 ((x,y) coordinates + score)
* Face detection locations (x,y,width,height) for each person in the image.
* It has been resized to the same resolution as `poseKeypoints`.
* Size: #people
*/
std::vector<Rectangle<float>> 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<float> faceKeyPoints;
Array<float> faceKeypoints;
/**
* Experimental (NOT IMPLEMENTED YET)
* Hands code is in development phase. Not included in this version.
* Size: #people's hands to render x 2 (right and left hand) x #hand parts (21) x 3 ((x,y) coordinates + score)
*/
Array<float> handKeyPoints;
Array<float> handKeypoints;
// -------------------------------------------------- Other parameters -------------------------------------------------- //
double scaleInputToOutput; /**< Scale ratio between the input Datum::cvInputData and the output Datum::cvOutputData. */
......@@ -209,4 +219,4 @@ namespace op
};
}
#endif // OPENPOSE__CORE__DATUM_HPP
#endif // OPENPOSE_CORE_DATUM_HPP
#ifndef OPENPOSE__CORE__ENUM_CLASSES_HPP
#define OPENPOSE__CORE__ENUM_CLASSES_HPP
#ifndef OPENPOSE_CORE_ENUM_CLASSES_HPP
#define OPENPOSE_CORE_ENUM_CLASSES_HPP
namespace op
{
......@@ -21,4 +21,4 @@ namespace op
};
}
#endif // OPENPOSE__CORE__ENUM_CLASSES_HPP
#endif // OPENPOSE_CORE_ENUM_CLASSES_HPP
#ifndef OPENPOSE__CORE__HEADERS_HPP
#define OPENPOSE__CORE__HEADERS_HPP
#ifndef OPENPOSE_CORE_HEADERS_HPP
#define OPENPOSE_CORE_HEADERS_HPP
// core module
#include "array.hpp"
......@@ -7,19 +7,21 @@
#include "cvMatToOpOutput.hpp"
#include "datum.hpp"
#include "enumClasses.hpp"
#include "keyPointScaler.hpp"
#include "keypointScaler.hpp"
#include "net.hpp"
#include "netCaffe.hpp"
#include "nmsBase.hpp"
#include "nmsCaffe.hpp"
#include "opOutputToCvMat.hpp"
#include "point.hpp"
#include "rectangle.hpp"
#include "renderer.hpp"
#include "resizeAndMergeBase.hpp"
#include "resizeAndMergeCaffe.hpp"
#include "scaleKeyPoints.hpp"
#include "scaleKeypoints.hpp"
#include "wCvMatToOpInput.hpp"
#include "wCvMatToOpOutput.hpp"
#include "wKeyPointScaler.hpp"
#include "wKeypointScaler.hpp"
#include "wOpOutputToCvMat.hpp"
#endif // OPENPOSE__CORE__HEADERS_HPP
#endif // OPENPOSE_CORE_HEADERS_HPP
#ifndef OPENPOSE__CORE__KEY_POINT_SCALER_HPP
#define OPENPOSE__CORE__KEY_POINT_SCALER_HPP
#ifndef OPENPOSE_CORE_KEYPOINT_SCALER_HPP
#define OPENPOSE_CORE_KEYPOINT_SCALER_HPP
#include <vector>
#include "array.hpp"
#include "point.hpp"
#include "enumClasses.hpp"
namespace op
{
class KeyPointScaler
class KeypointScaler
{
public:
explicit KeyPointScaler(const ScaleMode scaleMode);
explicit KeypointScaler(const ScaleMode scaleMode);
void scale(Array<float>& arrayToScale, const float scaleInputToOutput, const float scaleNetToOutput, const cv::Size& producerSize) const;
void scale(Array<float>& arrayToScale, const float scaleInputToOutput, const float scaleNetToOutput, const Point<int>& producerSize) const;
void scale(std::vector<Array<float>>& arraysToScale, const float scaleInputToOutput, const float scaleNetToOutput, const cv::Size& producerSize) const;
void scale(std::vector<Array<float>>& arraysToScale, const float scaleInputToOutput, const float scaleNetToOutput, const Point<int>& producerSize) const;
private:
const ScaleMode mScaleMode;
};
}
#endif // OPENPOSE__CORE__KEY_POINT_SCALER_HPP
#endif // OPENPOSE_CORE_KEYPOINT_SCALER_HPP
#ifndef OPENPOSE__CORE__NET_HPP
#define OPENPOSE__CORE__NET_HPP
#ifndef OPENPOSE_CORE_NET_HPP
#define OPENPOSE_CORE_NET_HPP
namespace op
{
......@@ -18,4 +18,4 @@ namespace op
};
}
#endif // OPENPOSE__CORE__NET_HPP
#endif // OPENPOSE_CORE_NET_HPP
#ifdef USE_CAFFE
#ifndef OPENPOSE__CORE__NET_CAFFE_HPP
#define OPENPOSE__CORE__NET_CAFFE_HPP
#ifndef OPENPOSE_CORE_NET_CAFFE_HPP
#define OPENPOSE_CORE_NET_CAFFE_HPP
#include <array>
#include <memory> // std::shared_ptr
......@@ -47,5 +47,5 @@ namespace op
};
}
#endif // OPENPOSE__CORE__NET_CAFFE_HPP
#endif // OPENPOSE_CORE_NET_CAFFE_HPP
#endif
#ifndef OPENPOSE__CORE__NMS_BASE_HPP
#define OPENPOSE__CORE__NMS_BASE_HPP
#ifndef OPENPOSE_CORE_NMS_BASE_HPP
#define OPENPOSE_CORE_NMS_BASE_HPP
#include <array>
......@@ -12,4 +12,4 @@ namespace op
void nmsGpu(T* targetPtr, int* kernelPtr, const T* const sourcePtr, const T threshold, const std::array<int, 4>& targetSize, const std::array<int, 4>& sourceSize);
}
#endif // OPENPOSE__CORE__NMS_BASE_HPP
#endif // OPENPOSE_CORE_NMS_BASE_HPP
#ifdef USE_CAFFE
#ifndef OPENPOSE__CORE__NMS_CAFFE_HPP
#define OPENPOSE__CORE__NMS_CAFFE_HPP
#ifndef OPENPOSE_CORE_NMS_CAFFE_HPP
#define OPENPOSE_CORE_NMS_CAFFE_HPP
#include <array>
#include "caffe/blob.hpp"
......@@ -39,5 +39,5 @@ namespace op
};
}
#endif // OPENPOSE__CORE__NMS_CAFFE_HPP
#endif // OPENPOSE_CORE_NMS_CAFFE_HPP
#endif
#ifndef OPENPOSE__CORE__OP_OUTPUT_TO_CV_MAT_HPP
#define OPENPOSE__CORE__OP_OUTPUT_TO_CV_MAT_HPP
#ifndef OPENPOSE_CORE_OP_OUTPUT_TO_CV_MAT_HPP
#define OPENPOSE_CORE_OP_OUTPUT_TO_CV_MAT_HPP
#include <opencv2/core/core.hpp>
#include <opencv2/core/core.hpp> // cv::Mat
#include "array.hpp"
#include "point.hpp"
namespace op
{
class OpOutputToCvMat
{
public:
explicit OpOutputToCvMat(const cv::Size& outputResolution);
explicit OpOutputToCvMat(const Point<int>& outputResolution);
cv::Mat formatToCvMat(const Array<float>& outputData) const;
private:
const cv::Size mOutputResolution;
const Point<int> mOutputResolution;
};
}
#endif // OPENPOSE__CORE__OP_OUTPUT_TO_CV_MAT_HPP
#endif // OPENPOSE_CORE_OP_OUTPUT_TO_CV_MAT_HPP
#ifndef OPENPOSE_CORE_POINT_HPP
#define OPENPOSE_CORE_POINT_HPP
namespace op
{
template<typename T>
struct Point
{
T x;
T y;
Point(const T x = -1, const T y = -1);
/**
* Copy constructor.
* It performs `fast copy`: For performance purpose, copying a Point<T> or Point<T> 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<T>.
* @param point Point to be copied.
*/
Point<T>(const Point<T>& point);
/**
* Copy assignment.
* Similar to Point<T>(const Point<T>& point).
* @param point Point to be copied.
* @return The resulting Point.
*/
Point<T>& operator=(const Point<T>& point);
/**
* Move constructor.
* It destroys the original Point to be moved.
* @param point Point to be moved.
*/
Point<T>(Point<T>&& point);
/**
* Move assignment.
* Similar to Point<T>(Point<T>&& point).
* @param point Point to be moved.
* @return The resulting Point.
*/
Point<T>& operator=(Point<T>&& point);
inline T area() const
{
return x * y;
}
// -------------------------------------------------- Comparison operators -------------------------------------------------- //
/**
* Less comparison operator.
* @param point Point<T> to be compared.
* @result Whether the instance satisfies the condition with respect to point.
*/
inline bool operator<(const Point<T>& point) const
{
return area() < point.area();
}
/**
* Greater comparison operator.
* @param point Point<T> to be compared.
* @result Whether the instance satisfies the condition with respect to point.
*/
inline bool operator>(const Point<T>& point) const
{
return area() > point.area();
}
/**
* Less or equal comparison operator.
* @param point Point<T> to be compared.
* @result Whether the instance satisfies the condition with respect to point.
*/
inline bool operator<=(const Point<T>& point) const
{
return area() <= point.area();
}
/**
* Greater or equal comparison operator.
* @param point Point<T> to be compared.
* @result Whether the instance satisfies the condition with respect to point.
*/
inline bool operator>=(const Point<T>& point) const
{
return area() >= point.area();
}
/**
* Equal comparison operator.
* @param point Point<T> to be compared.
* @result Whether the instance satisfies the condition with respect to point.
*/
inline bool operator==(const Point<T>& point) const
{
return area() == point.area();
}
/**
* Not equal comparison operator.
* @param point Point<T> to be compared.
* @result Whether the instance satisfies the condition with respect to point.
*/
inline bool operator!=(const Point<T>& point) const
{
return area() != point.area();
}
// -------------------------------------------------- Basic Operators -------------------------------------------------- //
Point<T>& operator+=(const Point<T>& point);
Point<T>& operator+=(const T value);
Point<T>& operator-=(const Point<T>& point);
Point<T>& operator-=(const T value);
Point<T>& operator*=(const T value);
Point<T>& operator/=(const T value);
};
}
#endif // OPENPOSE_CORE_POINT_HPP
#ifndef OPENPOSE_CORE_RECTANGLE_HPP
#define OPENPOSE_CORE_RECTANGLE_HPP
#include "point.hpp"
namespace op
{
template<typename T>
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<T> 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<T>.
* @param rectangle Rectangle to be copied.
*/
Rectangle<T>(const Rectangle<T>& rectangle);
/**
* Copy assignment.
* Similar to Rectangle<T>(const Rectangle<T>& rectangle).
* @param rectangle Rectangle to be copied.
* @return The resulting Rectangle.
*/
Rectangle<T>& operator=(const Rectangle<T>& rectangle);
/**
* Move constructor.
* It destroys the original Rectangle to be moved.
* @param rectangle Rectangle to be moved.
*/
Rectangle<T>(Rectangle<T>&& rectangle);
/**
* Move assignment.
* Similar to Rectangle<T>(Rectangle<T>&& rectangle).
* @param rectangle Rectangle to be moved.
* @return The resulting Rectangle.
*/
Rectangle<T>& operator=(Rectangle<T>&& rectangle);
Point<T> center() const;
inline Point<T> topLeft() const
{
return Point<T>{x, y};
}
Point<T> bottomRight() const;
inline T area() const
{
return width * height;
}
};
}
#endif // OPENPOSE_CORE_RECTANGLE_HPP
#ifndef OPENPOSE__CORE__RENDERER_HPP
#define OPENPOSE__CORE__RENDERER_HPP
#ifndef OPENPOSE_CORE_RENDERER_HPP
#define OPENPOSE_CORE_RENDERER_HPP
#include <tuple>
#include <memory> // std::shared_ptr
#include <openpose/utilities/macros.hpp>
......@@ -9,18 +10,34 @@ namespace op
class Renderer
{
public:
explicit Renderer(const unsigned long long volume);
explicit Renderer(const unsigned long long volume, const float alphaKeypoint, const float alphaHeatMap, const unsigned int elementToRender = 0u,
const unsigned int numberElementsToRender = 0u);
~Renderer();
void initializationOnThread();
std::pair<std::shared_ptr<float*>, std::shared_ptr<bool>> getGpuMemoryAndSetAsFirst();
void increaseElementToRender(const int increment);
void setGpuMemoryAndSetIfLast(const std::pair<std::shared_ptr<float*>, std::shared_ptr<bool>>& gpuMemory, const bool isLast);
void setElementToRender(const int elementToRender);
std::tuple<std::shared_ptr<float*>, std::shared_ptr<bool>, std::shared_ptr<std::atomic<unsigned int>>, std::shared_ptr<const unsigned int>> getSharedParameters();
void setSharedParametersAndIfLast(const std::tuple<std::shared_ptr<float*>, std::shared_ptr<bool>, std::shared_ptr<std::atomic<unsigned int>>,
std::shared_ptr<const unsigned int>>& tuple, const bool isLast);
float getAlphaKeypoint() const;
void setAlphaKeypoint(const float alphaKeypoint);
float getAlphaHeatMap() const;
void setAlphaHeatMap(const float alphaHeatMap);
protected:
std::shared_ptr<float*> spGpuMemoryPtr;
std::shared_ptr<std::atomic<unsigned int>> spElementToRender;
std::shared_ptr<const unsigned int> spNumberElementsToRender;
void cpuToGpuMemoryIfNotCopiedYet(const float* const cpuMemory);
......@@ -28,6 +45,8 @@ namespace op
private:
const unsigned long long mVolume;
float mAlphaKeypoint;
float mAlphaHeatMap;
bool mIsFirstRenderer;
bool mIsLastRenderer;
std::shared_ptr<bool> spGpuMemoryAllocated;
......@@ -36,4 +55,4 @@ namespace op
};
}
#endif // OPENPOSE__CORE__RENDERER_HPP
#endif // OPENPOSE_CORE_RENDERER_HPP
#ifndef OPENPOSE__CORE__RESIZE_AND_MERGE_BASE_HPP
#define OPENPOSE__CORE__RESIZE_AND_MERGE_BASE_HPP
#ifndef OPENPOSE_CORE_RESIZE_AND_MERGE_BASE_HPP
#define OPENPOSE_CORE_RESIZE_AND_MERGE_BASE_HPP
#include <array>
......@@ -12,4 +12,4 @@ namespace op
void resizeAndMergeGpu(T* targetPtr, const T* const sourcePtr, const std::array<int, 4>& targetSize, const std::array<int, 4>& sourceSize, const T scaleGap = 0.f);
}
#endif // OPENPOSE__CORE__RESIZE_AND_MERGE_BASE_HPP
#endif // OPENPOSE_CORE_RESIZE_AND_MERGE_BASE_HPP
#ifdef USE_CAFFE
#ifndef OPENPOSE__CORE__RESIZE_AND_MERGE_CAFFE_HPP
#define OPENPOSE__CORE__RESIZE_AND_MERGE_CAFFE_HPP
#ifndef OPENPOSE_CORE_RESIZE_AND_MERGE_CAFFE_HPP
#define OPENPOSE_CORE_RESIZE_AND_MERGE_CAFFE_HPP
#include <array>
#include <caffe/blob.hpp>
......@@ -41,5 +41,5 @@ namespace op
};
}
#endif // OPENPOSE__CORE__RESIZE_AND_MERGE_CAFFE_HPP
#endif // OPENPOSE_CORE_RESIZE_AND_MERGE_CAFFE_HPP
#endif
#ifndef OPENPOSE__CORE__SCALE_KEY_POINTS_HPP
#define OPENPOSE__CORE__SCALE_KEY_POINTS_HPP
#ifndef OPENPOSE_CORE_SCALE_KEYPOINTS_HPP
#define OPENPOSE_CORE_SCALE_KEYPOINTS_HPP
#include "array.hpp"
namespace op
{
void scaleKeyPoints(Array<float>& keyPoints, const float scale);
void scaleKeypoints(Array<float>& keypoints, const float scale);
void scaleKeyPoints(Array<float>& keyPoints, const float scaleX, const float scaleY);
void scaleKeypoints(Array<float>& keypoints, const float scaleX, const float scaleY);
void scaleKeyPoints(Array<float>& keyPoints, const float scaleX, const float scaleY, const float offsetX, const float offsetY);
void scaleKeypoints(Array<float>& keypoints, const float scaleX, const float scaleY, const float offsetX, const float offsetY);
}
#endif // OPENPOSE__CORE__SCALE_KEY_POINTS_HPP
#endif // OPENPOSE_CORE_SCALE_KEYPOINTS_HPP
#ifndef OPENPOSE__CORE__W_CV_MAT_TO_OP_INPUT_HPP
#define OPENPOSE__CORE__W_CV_MAT_TO_OP_INPUT_HPP
#ifndef OPENPOSE_CORE_W_CV_MAT_TO_OP_INPUT_HPP
#define OPENPOSE_CORE_W_CV_MAT_TO_OP_INPUT_HPP
#include <memory> // std::shared_ptr
#include <opencv2/core/core.hpp>
#include <openpose/thread/worker.hpp>
#include "cvMatToOpInput.hpp"
......@@ -80,4 +79,4 @@ namespace op
COMPILE_TEMPLATE_DATUM(WCvMatToOpInput);
}
#endif // OPENPOSE__CORE__W_CV_MAT_TO_OP_INPUT_HPP
#endif // OPENPOSE_CORE_W_CV_MAT_TO_OP_INPUT_HPP
#ifndef OPENPOSE__CORE__W_CV_MAT_TO_OP_OUTPUT_HPP
#define OPENPOSE__CORE__W_CV_MAT_TO_OP_OUTPUT_HPP
#ifndef OPENPOSE_CORE_W_CV_MAT_TO_OP_OUTPUT_HPP
#define OPENPOSE_CORE_W_CV_MAT_TO_OP_OUTPUT_HPP
#include <memory> // std::shared_ptr
#include <opencv2/core/core.hpp>
#include <openpose/thread/worker.hpp>
#include "cvMatToOpOutput.hpp"
......@@ -82,4 +81,4 @@ namespace op
COMPILE_TEMPLATE_DATUM(WCvMatToOpOutput);
}
#endif // OPENPOSE__CORE__W_CV_MAT_TO_OP_OUTPUT_HPP
#endif // OPENPOSE_CORE_W_CV_MAT_TO_OP_OUTPUT_HPP
#ifndef OPENPOSE__CORE__W_KEY_POINT_SCALER_HPP
#define OPENPOSE__CORE__W_KEY_POINT_SCALER_HPP
#ifndef OPENPOSE_CORE_W_KEYPOINT_SCALER_HPP
#define OPENPOSE_CORE_W_KEYPOINT_SCALER_HPP
#include <openpose/thread/worker.hpp>
#include "keyPointScaler.hpp"
#include "scaleKeyPoints.hpp"
#include "keypointScaler.hpp"
#include "scaleKeypoints.hpp"
namespace op
{
template<typename TDatums>
class WKeyPointScaler : public Worker<TDatums>
class WKeypointScaler : public Worker<TDatums>
{
public:
explicit WKeyPointScaler(const std::shared_ptr<KeyPointScaler>& keyPointScaler);
explicit WKeypointScaler(const std::shared_ptr<KeypointScaler>& keypointScaler);
void initializationOnThread();
void work(TDatums& tDatums);
private:
std::shared_ptr<KeyPointScaler> spKeyPointScaler;
std::shared_ptr<KeypointScaler> spKeypointScaler;
};
}
......@@ -34,18 +34,18 @@ namespace op
namespace op
{
template<typename TDatums>
WKeyPointScaler<TDatums>::WKeyPointScaler(const std::shared_ptr<KeyPointScaler>& keyPointScaler) :
spKeyPointScaler{keyPointScaler}
WKeypointScaler<TDatums>::WKeypointScaler(const std::shared_ptr<KeypointScaler>& keypointScaler) :
spKeypointScaler{keypointScaler}
{
}
template<typename TDatums>
void WKeyPointScaler<TDatums>::initializationOnThread()
void WKeypointScaler<TDatums>::initializationOnThread()
{
}
template<typename TDatums>
void WKeyPointScaler<TDatums>::work(TDatums& tDatums)
void WKeypointScaler<TDatums>::work(TDatums& tDatums)
{
try
{
......@@ -58,8 +58,8 @@ namespace op
// Rescale pose data
for (auto& tDatum : *tDatums)
{
std::vector<Array<float>> arraysToScale{tDatum.poseKeyPoints, tDatum.handKeyPoints, tDatum.faceKeyPoints};
spKeyPointScaler->scale(arraysToScale, (float)tDatum.scaleInputToOutput, (float)tDatum.scaleNetToOutput, tDatum.cvInputData.size());
std::vector<Array<float>> arraysToScale{tDatum.poseKeypoints, tDatum.handKeypoints, tDatum.faceKeypoints};
spKeypointScaler->scale(arraysToScale, (float)tDatum.scaleInputToOutput, (float)tDatum.scaleNetToOutput, Point<int>{tDatum.cvInputData.cols, tDatum.cvInputData.rows});
}
// Profiling speed
Profiler::timerEnd(profilerKey);
......@@ -76,7 +76,7 @@ namespace op
}
}
COMPILE_TEMPLATE_DATUM(WKeyPointScaler);
COMPILE_TEMPLATE_DATUM(WKeypointScaler);
}
#endif // OPENPOSE__CORE__W_KEY_POINT_SCALER_HPP
#endif // OPENPOSE_CORE_W_KEYPOINT_SCALER_HPP
#ifndef OPENPOSE__CORE__W_OP_OUTPUT_TO_CV_MAT_HPP
#define OPENPOSE__CORE__W_OP_OUTPUT_TO_CV_MAT_HPP
#ifndef OPENPOSE_CORE_W_OP_OUTPUT_TO_CV_MAT_HPP
#define OPENPOSE_CORE_W_OP_OUTPUT_TO_CV_MAT_HPP
#include <memory> // std::shared_ptr
#include <opencv2/core/core.hpp>
#include <openpose/thread/worker.hpp>
#include "opOutputToCvMat.hpp"
......@@ -80,4 +79,4 @@ namespace op
COMPILE_TEMPLATE_DATUM(WOpOutputToCvMat);
}
#endif // OPENPOSE__CORE__W_OP_OUTPUT_TO_CV_MAT_HPP
#endif // OPENPOSE_CORE_W_OP_OUTPUT_TO_CV_MAT_HPP
#ifndef OPENPOSE__FACE__FACE_EXTRACTOR_HPP
#define OPENPOSE__FACE__FACE_EXTRACTOR_HPP
#include <array>
#include <atomic>
#include <memory> // std::shared_ptr
#include <thread>
#include <opencv2/core/core.hpp>
#include <openpose/core/array.hpp>
#include <openpose/core/net.hpp>
#include <openpose/core/nmsCaffe.hpp>
#include <openpose/core/resizeAndMergeCaffe.hpp>
#include <openpose/pose/enumClasses.hpp>
#include "enumClasses.hpp"
namespace op
{
namespace experimental
{
class FaceExtractor
{
public:
explicit FaceExtractor(const std::string& modelFolder, const int gpuId, const PoseModel poseModel);
void initializationOnThread();
void forwardPass(const Array<float>& poseKeyPoints, const cv::Mat& cvInputData);
Array<float> getFaceKeyPoints() const;
double get(const FaceProperty property) const;
void set(const FaceProperty property, const double value);
void increase(const FaceProperty property, const double value);
private:
const cv::Size mNetOutputSize;
const cv::Size mOutputSize;
const unsigned int mNeck;
const unsigned int mNose;
const unsigned int mLEar;
const unsigned int mREar;
const unsigned int mLEye;
const unsigned int mREye;
std::array<std::atomic<double>, (int)FaceProperty::Size> mProperties;
std::shared_ptr<Net> spNet;
std::shared_ptr<ResizeAndMergeCaffe<float>> spResizeAndMergeCaffe;
std::shared_ptr<NmsCaffe<float>> spNmsCaffe;
Array<float> mFaceImageCrop;
Array<float> mFaceKeyPoints;
float mScaleFace;
// Init with thread
boost::shared_ptr<caffe::Blob<float>> spCaffeNetOutputBlob;
std::shared_ptr<caffe::Blob<float>> spHeatMapsBlob;
std::shared_ptr<caffe::Blob<float>> spPeaksBlob;
std::thread::id mThreadId;
void checkThread() const;
DELETE_COPY(FaceExtractor);
};
}
}
#endif // OPENPOSE__FACE__FACE_EXTRACTOR_HPP
#ifndef OPENPOSE__FACE__GPU_FACE_RENDER_HPP
#define OPENPOSE__FACE__GPU_FACE_RENDER_HPP
#include <opencv2/core/core.hpp>
#include "faceParameters.hpp"
namespace op
{
void renderFaceGpu(float* framePtr, const cv::Size& frameSize, const float* const facePtr, const int numberFace, const float alphaColorToAdd = FACE_DEFAULT_ALPHA_FACE);
}
#endif // OPENPOSE__FACE__GPU_FACE_RENDER_HPP
#ifndef OPENPOSE__FACE__FACE_RENDERER_HPP
#define OPENPOSE__FACE__FACE_RENDERER_HPP
#include <opencv2/core/core.hpp>
#include <openpose/core/array.hpp>
#include <openpose/core/renderer.hpp>
#include <openpose/thread/worker.hpp>
namespace op
{
namespace experimental
{
class FaceRenderer : public Renderer
{
public:
explicit FaceRenderer(const cv::Size& frameSize);
~FaceRenderer();
void initializationOnThread();
void renderFace(Array<float>& outputData, const Array<float>& faceKeyPoints);
private:
const cv::Size mFrameSize;
float* pGpuFace; // GPU aux memory
DELETE_COPY(FaceRenderer);
};
}
}
#endif // OPENPOSE__FACE__FACE_RENDERER_HPP
#ifndef OPENPOSE__FACE__W_FACE_EXTRACTOR_HPP
#define OPENPOSE__FACE__W_FACE_EXTRACTOR_HPP
#include <memory> // std::shared_ptr
#include <openpose/thread/worker.hpp>
#include "faceRenderer.hpp"
namespace op
{
namespace experimental
{
template<typename TDatums>
class WFaceExtractor : public Worker<TDatums>
{
public:
explicit WFaceExtractor(const std::shared_ptr<FaceExtractor>& faceExtractor);
void initializationOnThread();
void work(TDatums& tDatums);
private:
std::shared_ptr<FaceExtractor> spFaceExtractor;
DELETE_COPY(WFaceExtractor);
};
}
}
// Implementation
#include <openpose/utilities/errorAndLog.hpp>
#include <openpose/utilities/macros.hpp>
#include <openpose/utilities/pointerContainer.hpp>
#include <openpose/utilities/profiler.hpp>
namespace op
{
namespace experimental
{
template<typename TDatums>
WFaceExtractor<TDatums>::WFaceExtractor(const std::shared_ptr<FaceExtractor>& faceExtractor) :
spFaceExtractor{faceExtractor}
{
}
template<typename TDatums>
void WFaceExtractor<TDatums>::initializationOnThread()
{
spFaceExtractor->initializationOnThread();
}
template<typename TDatums>
void WFaceExtractor<TDatums>::work(TDatums& tDatums)
{
try
{
if (checkNoNullNorEmpty(tDatums))
{
// Debugging log
dLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
// Profiling speed
const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);
// Extract people face
for (auto& tDatum : *tDatums)
{
spFaceExtractor->forwardPass(tDatum.poseKeyPoints, tDatum.cvInputData);
tDatum.faceKeyPoints = spFaceExtractor->getFaceKeyPoints();
}
// Profiling speed
Profiler::timerEnd(profilerKey);
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, Profiler::DEFAULT_X);
// Debugging log
dLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
}
}
catch (const std::exception& e)
{
this->stop();
tDatums = nullptr;
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
}
}
COMPILE_TEMPLATE_DATUM(WFaceExtractor);
}
}
#endif // OPENPOSE__FACE__W_FACE_EXTRACTOR_HPP
#ifndef OPENPOSE__FACE__W_FACE_RENDERER_HPP
#define OPENPOSE__FACE__W_FACE_RENDERER_HPP
#include <memory> // std::shared_ptr
#include <openpose/thread/worker.hpp>
#include "faceRenderer.hpp"
namespace op
{
namespace experimental
{
template<typename TDatums>
class WFaceRenderer : public Worker<TDatums>
{
public:
explicit WFaceRenderer(const std::shared_ptr<FaceRenderer>& faceRenderer);
void initializationOnThread();
void work(TDatums& tDatums);
private:
std::shared_ptr<FaceRenderer> spFaceRenderer;
DELETE_COPY(WFaceRenderer);
};
}
}
// Implementation
#include <openpose/utilities/errorAndLog.hpp>
#include <openpose/utilities/macros.hpp>
#include <openpose/utilities/pointerContainer.hpp>
#include <openpose/utilities/profiler.hpp>
namespace op
{
namespace experimental
{
template<typename TDatums>
WFaceRenderer<TDatums>::WFaceRenderer(const std::shared_ptr<FaceRenderer>& faceRenderer) :
spFaceRenderer{faceRenderer}
{
}
template<typename TDatums>
void WFaceRenderer<TDatums>::initializationOnThread()
{
spFaceRenderer->initializationOnThread();
}
template<typename TDatums>
void WFaceRenderer<TDatums>::work(TDatums& tDatums)
{
try
{
if (checkNoNullNorEmpty(tDatums))
{
// Debugging log
dLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
// Profiling speed
const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);
// Render people face
for (auto& tDatum : *tDatums)
spFaceRenderer->renderFace(tDatum.outputData, tDatum.faceKeyPoints);
// Profiling speed
Profiler::timerEnd(profilerKey);
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, Profiler::DEFAULT_X);
// Debugging log
dLog("", 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
#ifndef OPENPOSE__EXPERIMENTAL__FILESTREAM__HEADERS_HPP
#define OPENPOSE__EXPERIMENTAL__FILESTREAM__HEADERS_HPP
#ifndef OPENPOSE_EXPERIMENTAL_FILESTREAM_HEADERS_HPP
#define OPENPOSE_EXPERIMENTAL_FILESTREAM_HEADERS_HPP
// storage module
#include "wPoseJsonCocoSaver.hpp"
#include "wCocoJsonSaver.hpp"
#endif // OPENPOSE__EXPERIMENTAL__FILESTREAM__HEADERS_HPP
#endif // OPENPOSE_EXPERIMENTAL_FILESTREAM_HEADERS_HPP
// THE CLASSES INSIDE THE experimental NAMESPACE ARE STILL BEING DEVELOPED, WE HIGHLY RECOMMEND NOT TO USE THEM
// The results are not the same as the one obtained with Matlab, so there is a bug somewhere in this class or in PoseJsonCocoSaver.
// The results are not the same as the one obtained with Matlab, so there is a bug somewhere in this class or in CocoJsonSaver.
#ifndef OPENPOSE__EXPERIMENTAL__FILESTREAM__W_POSE_JSON_COCO_SAVER_HPP
#define OPENPOSE__EXPERIMENTAL__FILESTREAM__W_POSE_JSON_COCO_SAVER_HPP
#ifndef OPENPOSE_FILESTREAM_W_COCO_JSON_SAVER_HPP
#define OPENPOSE_FILESTREAM_W_COCO_JSON_SAVER_HPP
#include <memory> // std::shared_ptr
#include <openpose/filestream/poseJsonCocoSaver.hpp>
#include <openpose/filestream/cocoJsonSaver.hpp>
#include <openpose/thread/workerConsumer.hpp>
namespace op
......@@ -13,19 +13,19 @@ namespace op
namespace experimental
{
template<typename TDatums>
class WPoseJsonCocoSaver : public WorkerConsumer<TDatums>
class WCocoJsonSaver : public WorkerConsumer<TDatums>
{
public:
explicit WPoseJsonCocoSaver(const std::shared_ptr<PoseJsonCocoSaver>& poseJsonCocoSaver);
explicit WCocoJsonSaver(const std::shared_ptr<CocoJsonSaver>& cocoJsonSaver);
void initializationOnThread();
void workConsumer(const TDatums& tDatums);
private:
std::shared_ptr<PoseJsonCocoSaver> spPoseJsonCocoSaver;
std::shared_ptr<CocoJsonSaver> spCocoJsonSaver;
DELETE_COPY(WPoseJsonCocoSaver);
DELETE_COPY(WCocoJsonSaver);
};
}
}
......@@ -44,18 +44,18 @@ namespace op
namespace experimental
{
template<typename TDatums>
WPoseJsonCocoSaver<TDatums>::WPoseJsonCocoSaver(const std::shared_ptr<PoseJsonCocoSaver>& poseJsonCocoSaver) :
spPoseJsonCocoSaver{poseJsonCocoSaver}
WCocoJsonSaver<TDatums>::WCocoJsonSaver(const std::shared_ptr<CocoJsonSaver>& cocoJsonSaver) :
spCocoJsonSaver{cocoJsonSaver}
{
}
template<typename TDatums>
void WPoseJsonCocoSaver<TDatums>::initializationOnThread()
void WCocoJsonSaver<TDatums>::initializationOnThread()
{
}
template<typename TDatums>
void WPoseJsonCocoSaver<TDatums>::workConsumer(const TDatums& tDatums)
void WCocoJsonSaver<TDatums>::workConsumer(const TDatums& tDatums)
{
try
{
......@@ -78,7 +78,7 @@ namespace op
if (imageId <= 50006) // 3559 images ~ 4 min at 15fps // move this to producer as --frame_last 50006
{
// Record json in COCO format if file within desired range of images
spPoseJsonCocoSaver->record(tDatum.poseKeyPoints, imageId);
spCocoJsonSaver->record(tDatum.poseKeypoints, imageId);
// Profiling speed
Profiler::timerEnd(profilerKey);
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, Profiler::DEFAULT_X);
......@@ -101,8 +101,8 @@ namespace op
}
}
COMPILE_TEMPLATE_DATUM(WPoseJsonCocoSaver);
COMPILE_TEMPLATE_DATUM(WCocoJsonSaver);
}
}
#endif // OPENPOSE__EXPERIMENTAL__FILESTREAM__W_POSE_JSON_COCO_SAVER_HPP
#endif // OPENPOSE_FILESTREAM_W_COCO_JSON_SAVER_HPP
#ifndef OPENPOSE__HAND__ENUM_CLASSES_HPP
#define OPENPOSE__HAND__ENUM_CLASSES_HPP
#ifndef OPENPOSE_HAND_ENUM_CLASSES_HPP
#define OPENPOSE_HAND_ENUM_CLASSES_HPP
namespace op
{
......@@ -10,4 +10,4 @@ namespace op
};
}
#endif // OPENPOSE__HAND__ENUM_CLASSES_HPP
#endif // OPENPOSE_HAND_ENUM_CLASSES_HPP
#ifndef OPENPOSE__HAND__HAND_EXTRACTOR_HPP
#define OPENPOSE__HAND__HAND_EXTRACTOR_HPP
#ifndef OPENPOSE_HAND_HAND_EXTRACTOR_HPP
#define OPENPOSE_HAND_HAND_EXTRACTOR_HPP
#include <array>
#include <atomic>
#include <memory> // std::shared_ptr
#include <thread>
#include <opencv2/core/core.hpp>
#include <opencv2/core/core.hpp> // cv::Mat
#include <openpose/core/array.hpp>
#include <openpose/core/point.hpp>
#include <openpose/core/net.hpp>
#include <openpose/core/nmsCaffe.hpp>
#include <openpose/core/resizeAndMergeCaffe.hpp>
......@@ -24,9 +25,9 @@ namespace op
void initializationOnThread();
void forwardPass(const Array<float>& poseKeyPoints, const cv::Mat& cvInputData);
void forwardPass(const Array<float>& poseKeypoints, const cv::Mat& cvInputData);
Array<float> getHandKeyPoints() const;
Array<float> getHandKeypoints() const;
double get(const HandsProperty property) const;
......@@ -35,8 +36,8 @@ namespace op
void increase(const HandsProperty property, const double value);
private:
const cv::Size mNetOutputSize;
const cv::Size mOutputSize;
const Point<int> mNetOutputSize;
const Point<int> mOutputSize;
const unsigned int mRWrist;
const unsigned int mRElbow;
const unsigned int mLWrist;
......@@ -65,4 +66,4 @@ namespace op
}
}
#endif // OPENPOSE__HAND__HAND_EXTRACTOR_HPP
#endif // OPENPOSE_HAND_HAND_EXTRACTOR_HPP
#ifndef OPENPOSE__HAND__HAND_PARAMETERS_HPP
#define OPENPOSE__HAND__HAND_PARAMETERS_HPP
#ifndef OPENPOSE_HAND_HAND_PARAMETERS_HPP
#define OPENPOSE_HAND_HAND_PARAMETERS_HPP
#include "enumClasses.hpp"
#include <openpose/pose/poseParameters.hpp>
namespace op
{
const unsigned char HAND_MAX_NUMBER_HANDS = 2;
const auto HAND_MAX_HANDS = 2*POSE_MAX_PEOPLE;
const unsigned char HAND_NUMBER_PARTS = 21;
const auto HAND_NUMBER_PARTS = 21u;
#define HAND_PAIRS_TO_RENDER {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}
// Constant Global Parameters
// const unsigned char HAND_MAX_PEOPLE = 1;
// Constant parameters
const auto HAND_CCN_DECREASE_FACTOR = 8.f;
const unsigned int HAND_MAX_PEAKS = 64u;
const auto HAND_MAX_PEAKS = 64u;
const std::string HAND_PROTOTXT{"hand/pose_deploy.prototxt"};
const std::string HAND_TRAINED_MODEL{"hand/pose_iter_120000.caffemodel"};
......@@ -25,8 +22,8 @@ namespace op
const auto HAND_DEFAULT_NMS_THRESHOLD = 0.1f;
// Rendering default parameters
const auto HAND_DEFAULT_ALPHA_HANDS = POSE_DEFAULT_ALPHA_POSE;
// const auto HAND_DEFAULT_ALPHA_HEATMAP = POSE_DEFAULT_ALPHA_HEATMAP;
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
#endif // OPENPOSE_HAND_HAND_PARAMETERS_HPP
#ifndef OPENPOSE__HAND__GPU_HAND_RENDER_HPP
#define OPENPOSE__HAND__GPU_HAND_RENDER_HPP
#ifndef OPENPOSE_HAND_GPU_HAND_RENDER_HPP
#define OPENPOSE_HAND_GPU_HAND_RENDER_HPP
#include <opencv2/core/core.hpp>
#include <openpose/core/point.hpp>
#include "handParameters.hpp"
namespace op
{
void renderHandsGpu(float* framePtr, const cv::Size& frameSize, const float* const handsPtr, const int numberHands, const float alphaColorToAdd = HAND_DEFAULT_ALPHA_HANDS);
void renderHandsGpu(float* framePtr, const Point<int>& frameSize, const float* const handsPtr, const int numberHands, const float alphaColorToAdd = HAND_DEFAULT_ALPHA_KEYPOINT);
}
#endif // OPENPOSE__HAND__GPU_HAND_RENDER_HPP
#endif // OPENPOSE_HAND_GPU_HAND_RENDER_HPP
#ifndef OPENPOSE__HAND__HAND_RENDERER_HPP
#define OPENPOSE__HAND__HAND_RENDERER_HPP
#ifndef OPENPOSE_HAND_HAND_RENDERER_HPP
#define OPENPOSE_HAND_HAND_RENDERER_HPP
#include <opencv2/core/core.hpp>
#include <openpose/core/array.hpp>
#include <openpose/core/point.hpp>
#include <openpose/core/renderer.hpp>
#include <openpose/thread/worker.hpp>
......@@ -13,16 +13,16 @@ namespace op
class HandRenderer : public Renderer
{
public:
explicit HandRenderer(const cv::Size& frameSize);
explicit HandRenderer(const Point<int>& frameSize);
~HandRenderer();
void initializationOnThread();
void renderHands(Array<float>& outputData, const Array<float>& handKeyPoints);
void renderHands(Array<float>& outputData, const Array<float>& handKeypoints);
private:
const cv::Size mFrameSize;
const Point<int> mFrameSize;
float* pGpuHands; // GPU aux memory
DELETE_COPY(HandRenderer);
......@@ -30,4 +30,4 @@ namespace op
}
}
#endif // OPENPOSE__HAND__HAND_RENDERER_HPP
#endif // OPENPOSE_HAND_HAND_RENDERER_HPP
#ifndef OPENPOSE__HAND__HEADERS_HPP
#define OPENPOSE__HAND__HEADERS_HPP
#ifndef OPENPOSE_HAND_HEADERS_HPP
#define OPENPOSE_HAND_HEADERS_HPP
// hand module
#include "enumClasses.hpp"
......@@ -10,4 +10,4 @@
#include "wHandExtractor.hpp"
#include "wHandRenderer.hpp"
#endif // OPENPOSE__HAND__HEADERS_HPP
#endif // OPENPOSE_HAND_HEADERS_HPP
#ifndef OPENPOSE__HAND__W_HAND_EXTRACTOR_HPP
#define OPENPOSE__HAND__W_HAND_EXTRACTOR_HPP
#ifndef OPENPOSE_HAND_W_HAND_EXTRACTOR_HPP
#define OPENPOSE_HAND_W_HAND_EXTRACTOR_HPP
#include <memory> // std::shared_ptr
#include <openpose/thread/worker.hpp>
......@@ -66,8 +66,8 @@ namespace op
// Extract people hands
for (auto& tDatum : *tDatums)
{
spHandExtractor->forwardPass(tDatum.poseKeyPoints, tDatum.cvInputData);
tDatum.handKeyPoints = spHandExtractor->getHandKeyPoints();
spHandExtractor->forwardPass(tDatum.poseKeypoints, tDatum.cvInputData);
tDatum.handKeypoints = spHandExtractor->getHandKeypoints();
}
// Profiling speed
Profiler::timerEnd(profilerKey);
......@@ -88,4 +88,4 @@ namespace op
}
}
#endif // OPENPOSE__HAND__W_HAND_EXTRACTOR_HPP
#endif // OPENPOSE_HAND_W_HAND_EXTRACTOR_HPP
#ifndef OPENPOSE__HAND__W_HAND_RENDERER_HPP
#define OPENPOSE__HAND__W_HAND_RENDERER_HPP
#ifndef OPENPOSE_HAND_W_HAND_RENDERER_HPP
#define OPENPOSE_HAND_W_HAND_RENDERER_HPP
#include <memory> // std::shared_ptr
#include <openpose/thread/worker.hpp>
......@@ -65,7 +65,7 @@ namespace op
const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);
// Render people hands
for (auto& tDatum : *tDatums)
spHandRenderer->renderHands(tDatum.outputData, tDatum.handKeyPoints);
spHandRenderer->renderHands(tDatum.outputData, tDatum.handKeypoints);
// Profiling speed
Profiler::timerEnd(profilerKey);
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, Profiler::DEFAULT_X);
......@@ -85,4 +85,4 @@ namespace op
}
}
#endif // OPENPOSE__HAND__W_HAND_RENDERER_HPP
#endif // OPENPOSE_HAND_W_HAND_RENDERER_HPP
#ifndef OPENPOSE__EXPERIMENTAL__HEADERS_HPP
#define OPENPOSE__EXPERIMENTAL__HEADERS_HPP
// face module
#include "face/headers.hpp"
#ifndef OPENPOSE_EXPERIMENTAL_HEADERS_HPP
#define OPENPOSE_EXPERIMENTAL_HEADERS_HPP
// filestream module
#include "filestream/headers.hpp"
......@@ -13,4 +10,4 @@
// producer module
// #include "producer/headers.hpp"
#endif // OPENPOSE__EXPERIMENTAL__HEADERS_HPP
#endif // OPENPOSE_EXPERIMENTAL_HEADERS_HPP
#ifndef OPENPOSE__EXPERIMENTAL__PRODUCER__HEADERS_HPP
#define OPENPOSE__EXPERIMENTAL__PRODUCER__HEADERS_HPP
#ifndef OPENPOSE_EXPERIMENTAL_PRODUCER_HEADERS_HPP
#define OPENPOSE_EXPERIMENTAL_PRODUCER_HEADERS_HPP
// producer module
// #include "wPoseLoader.hpp"
#endif // OPENPOSE__EXPERIMENTAL__PRODUCER__HEADERS_HPP
#endif // OPENPOSE_EXPERIMENTAL_PRODUCER_HEADERS_HPP
......@@ -2,8 +2,8 @@
// 1. Pre-process whole video and save people pose
// 2. Real-time showing it by loading this + original video
// #ifndef OPENPOSE__PRODUCER__W_POSE_LOADER_HPP
// #define OPENPOSE__PRODUCER__W_POSE_LOADER_HPP
// #ifndef OPENPOSE_PRODUCER_W_POSE_LOADER_HPP
// #define OPENPOSE_PRODUCER_W_POSE_LOADER_HPP
// namespace op
// {
......@@ -25,4 +25,4 @@
// COMPILE_TEMPLATE_DATUM(WPoseLoader);
// }
// #endif // OPENPOSE__PRODUCER__W_POSE_LOADER_HPP
// #endif // OPENPOSE_PRODUCER_W_POSE_LOADER_HPP
#ifndef OPENPOSE__FACE__ENUM_CLASSES_HPP
#define OPENPOSE__FACE__ENUM_CLASSES_HPP
#ifndef OPENPOSE_FACE_ENUM_CLASSES_HPP
#define OPENPOSE_FACE_ENUM_CLASSES_HPP
namespace op
{
......@@ -10,5 +10,5 @@ namespace op
};
}
#endif // OPENPOSE__FACE__ENUM_CLASSES_HPP
#endif // OPENPOSE_FACE_ENUM_CLASSES_HPP
#ifndef OPENPOSE_FACE_FACE_DETECTOR_HPP
#define OPENPOSE_FACE_FACE_DETECTOR_HPP
#include <vector>
#include <openpose/core/array.hpp>
#include <openpose/core/rectangle.hpp>
#include <openpose/pose/enumClasses.hpp>
#include <openpose/utilities/macros.hpp>
#include "enumClasses.hpp"
namespace op
{
class FaceDetector
{
public:
explicit FaceDetector(const PoseModel poseModel);
std::vector<Rectangle<float>> detectFaces(const Array<float>& poseKeypoints);
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
#ifndef OPENPOSE_FACE_FACE_EXTRACTOR_HPP
#define OPENPOSE_FACE_FACE_EXTRACTOR_HPP
#include <array>
#include <atomic>
#include <memory> // std::shared_ptr
#include <thread>
#include <opencv2/core/core.hpp> // cv::Mat
#include <openpose/core/array.hpp>
#include <openpose/core/net.hpp>
#include <openpose/core/nmsCaffe.hpp>
#include <openpose/core/rectangle.hpp>
#include <openpose/core/resizeAndMergeCaffe.hpp>
#include "enumClasses.hpp"
namespace op
{
class FaceExtractor
{
public:
explicit FaceExtractor(const Point<int>& netInputSize, const Point<int>& netOutputSize, const std::string& modelFolder, const int gpuId);
void initializationOnThread();
void forwardPass(const std::vector<Rectangle<float>>& faceRectangles, const cv::Mat& cvInputData);
Array<float> getFaceKeypoints() const;
double get(const FaceProperty property) const;
void set(const FaceProperty property, const double value);
void increase(const FaceProperty property, const double value);
private:
const Point<int> mNetOutputSize;
const Point<int> mOutputSize;
std::array<std::atomic<double>, (int)FaceProperty::Size> mProperties;
std::shared_ptr<Net> spNet;
std::shared_ptr<ResizeAndMergeCaffe<float>> spResizeAndMergeCaffe;
std::shared_ptr<NmsCaffe<float>> spNmsCaffe;
Array<float> mFaceImageCrop;
Array<float> mFaceKeypoints;
// Init with thread
boost::shared_ptr<caffe::Blob<float>> spCaffeNetOutputBlob;
std::shared_ptr<caffe::Blob<float>> spHeatMapsBlob;
std::shared_ptr<caffe::Blob<float>> spPeaksBlob;
std::thread::id mThreadId;
void checkThread() const;
DELETE_COPY(FaceExtractor);
};
}
#endif // OPENPOSE_FACE_FACE_EXTRACTOR_HPP
#ifndef OPENPOSE__FACE__FACE_PARAMETERS_HPP
#define OPENPOSE__FACE__FACE_PARAMETERS_HPP
#ifndef OPENPOSE_FACE_FACE_PARAMETERS_HPP
#define OPENPOSE_FACE_FACE_PARAMETERS_HPP
#include "enumClasses.hpp"
#include <openpose/pose/poseParameters.hpp>
namespace op
{
const unsigned char FACE_MAX_NUMBER_FACE = 1;
const auto FACE_MAX_FACES = POSE_MAX_PEOPLE;
const unsigned char FACE_NUMBER_PARTS = 71;
const auto FACE_NUMBER_PARTS = 70u;
#define FACE_PAIRS_TO_RENDER {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}
// Constant Global Parameters
// const unsigned char FACE_MAX_PEOPLE = 1;
// Constant parameters
const auto FACE_CCN_DECREASE_FACTOR = 8.f;
const unsigned int FACE_MAX_PEAKS = 64u;
const auto FACE_MAX_PEAKS = 64u;
const std::string FACE_PROTOTXT{"face/pose_deploy.prototxt"};
const std::string FACE_TRAINED_MODEL{"face/pose_iter_116000.caffemodel"};
......@@ -28,8 +25,8 @@ namespace op
const auto FACE_DEFAULT_NMS_THRESHOLD = 0.1f;
// Rendering default parameters
const auto FACE_DEFAULT_ALPHA_FACE = POSE_DEFAULT_ALPHA_POSE;
// const auto FACE_DEFAULT_ALPHA_HEATMAP = POSE_DEFAULT_ALPHA_HEATMAP;
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
#endif // OPENPOSE_FACE_FACE_PARAMETERS_HPP
#ifndef OPENPOSE_FACE_GPU_FACE_RENDER_HPP
#define OPENPOSE_FACE_GPU_FACE_RENDER_HPP
#include <openpose/core/point.hpp>
#include "faceParameters.hpp"
namespace op
{
void renderFaceGpu(float* framePtr, const Point<int>& frameSize, const float* const facePtr, const int numberFace, const float alphaColorToAdd = FACE_DEFAULT_ALPHA_KEYPOINT);
}
#endif // OPENPOSE_FACE_GPU_FACE_RENDER_HPP
#ifndef OPENPOSE_FACE_FACE_RENDERER_HPP
#define OPENPOSE_FACE_FACE_RENDERER_HPP
#include <openpose/core/array.hpp>
#include <openpose/core/point.hpp>
#include <openpose/core/renderer.hpp>
#include <openpose/thread/worker.hpp>
namespace op
{
class FaceRenderer : public Renderer
{
public:
explicit FaceRenderer(const Point<int>& frameSize, const float alphaKeypoint = FACE_DEFAULT_ALPHA_KEYPOINT,
const float alphaHeatMap = FACE_DEFAULT_ALPHA_HEAT_MAP);
~FaceRenderer();
void initializationOnThread();
void renderFace(Array<float>& outputData, const Array<float>& faceKeypoints);
private:
const Point<int> mFrameSize;
float* pGpuFace; // GPU aux memory
DELETE_COPY(FaceRenderer);
};
}
#endif // OPENPOSE_FACE_FACE_RENDERER_HPP
#ifndef OPENPOSE__FACE__HEADERS_HPP
#define OPENPOSE__FACE__HEADERS_HPP
#ifndef OPENPOSE_FACE_HEADERS_HPP
#define OPENPOSE_FACE_HEADERS_HPP
// face module
#include "enumClasses.hpp"
#include "faceDetector.hpp"
#include "faceExtractor.hpp"
#include "faceParameters.hpp"
#include "faceRenderer.hpp"
#include "faceRenderGpu.hpp"
#include "wFaceDetector.hpp"
#include "wFaceExtractor.hpp"
#include "wFaceRenderer.hpp"
#endif // OPENPOSE__FACE__HEADERS_HPP
#endif // OPENPOSE_FACE_HEADERS_HPP
#ifndef OPENPOSE_FACE_W_FACE_EXTRACTOR_HPP
#define OPENPOSE_FACE_W_FACE_EXTRACTOR_HPP
#include <memory> // std::shared_ptr
#include <openpose/thread/worker.hpp>
#include "faceRenderer.hpp"
namespace op
{
template<typename TDatums>
class WFaceDetector : public Worker<TDatums>
{
public:
explicit WFaceDetector(const std::shared_ptr<FaceDetector>& faceDetector);
void initializationOnThread();
void work(TDatums& tDatums);
private:
std::shared_ptr<FaceDetector> spFaceDetector;
DELETE_COPY(WFaceDetector);
};
}
// Implementation
#include <openpose/utilities/errorAndLog.hpp>
#include <openpose/utilities/macros.hpp>
#include <openpose/utilities/pointerContainer.hpp>
#include <openpose/utilities/profiler.hpp>
namespace op
{
template<typename TDatums>
WFaceDetector<TDatums>::WFaceDetector(const std::shared_ptr<FaceDetector>& faceDetector) :
spFaceDetector{faceDetector}
{
}
template<typename TDatums>
void WFaceDetector<TDatums>::initializationOnThread()
{
}
template<typename TDatums>
void WFaceDetector<TDatums>::work(TDatums& tDatums)
{
try
{
if (checkNoNullNorEmpty(tDatums))
{
// Debugging log
dLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
// Profiling speed
const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);
// Detect people face
for (auto& tDatum : *tDatums)
tDatum.faceRectangles = spFaceDetector->detectFaces(tDatum.poseKeypoints);
// Profiling speed
Profiler::timerEnd(profilerKey);
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, Profiler::DEFAULT_X);
// Debugging log
dLog("", 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
此差异已折叠。
此差异已折叠。
#ifndef OPENPOSE__FILESTREAM__POSE_JSON_COCO_SAVER_HPP
#define OPENPOSE__FILESTREAM__POSE_JSON_COCO_SAVER_HPP
#ifndef OPENPOSE_FILESTREAM_POSE_JSON_COCO_SAVER_HPP
#define OPENPOSE_FILESTREAM_POSE_JSON_COCO_SAVER_HPP
#include <string>
#include <openpose/core/array.hpp>
......@@ -9,27 +9,27 @@
namespace op
{
/**
* The PoseJsonCocoSaver class creates a COCO validation json file with details about the processed images. It inherits from Recorder.
* The CocoJsonSaver class creates a COCO validation json file with details about the processed images. It inherits from Recorder.
*/
class PoseJsonCocoSaver
class CocoJsonSaver
{
public:
/**
* This constructor of PoseJsonCocoSaver extends the Recorder::Recorder(const std::string & filePathToSave) constructor.
* 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 PoseJsonCocoSaver(const std::string& filePathToSave, const bool humanReadable = true);
explicit CocoJsonSaver(const std::string& filePathToSave, const bool humanReadable = true);
~PoseJsonCocoSaver();
~CocoJsonSaver();
void record(const Array<float>& poseKeyPoints, const unsigned long long imageId);
void record(const Array<float>& poseKeypoints, const unsigned long long imageId);
private:
JsonOfstream mJsonOfstream;
bool mFirstElementAdded;
DELETE_COPY(PoseJsonCocoSaver);
DELETE_COPY(CocoJsonSaver);
};
}
#endif // OPENPOSE__FILESTREAM__POSE_JSON_COCO_SAVER_HPP
#endif // OPENPOSE_FILESTREAM_POSE_JSON_COCO_SAVER_HPP
#ifndef OPENPOSE__FILESTREAM__ENUM_CLASSES_HPP
#define OPENPOSE__FILESTREAM__ENUM_CLASSES_HPP
#ifndef OPENPOSE_FILESTREAM_ENUM_CLASSES_HPP
#define OPENPOSE_FILESTREAM_ENUM_CLASSES_HPP
namespace op
{
......@@ -12,4 +12,4 @@ namespace op
};
}
#endif // OPENPOSE__FILESTREAM__ENUM_CLASSES_HPP
#endif // OPENPOSE_FILESTREAM_ENUM_CLASSES_HPP
#ifndef OPENPOSE__FILESTREAM__DATA_SAVER_HPP
#define OPENPOSE__FILESTREAM__DATA_SAVER_HPP
#ifndef OPENPOSE_FILESTREAM_DATA_SAVER_HPP
#define OPENPOSE_FILESTREAM_DATA_SAVER_HPP
#include <string>
#include <openpose/utilities/string.hpp>
......@@ -20,4 +20,4 @@ namespace op
};
}
#endif // OPENPOSE__FILESTREAM__DATA_SAVER_HPP
#endif // OPENPOSE_FILESTREAM_DATA_SAVER_HPP
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册