mirror of
https://github.com/gosticks/openpose.git
synced 2026-08-12 12:20:22 +00:00
CPU rendering added
This commit is contained in:
@@ -1,12 +1,25 @@
|
||||
### Posting rules
|
||||
1. **No duplicated** posts.
|
||||
2. **No** posts about **questions already answered in** the **documentation** (e.g. **no more low-speed nor out-of-memory questions**).
|
||||
3. **Add** the **system configuration (all of it!), command and output** if you have some kind of error or performance question.
|
||||
4. Set a **proper issue title**: add the Ubuntu/Windows word and be specific (e.g. do not simple call it: `Compile error`).
|
||||
5. Only English comments.
|
||||
Issues/comments that do not follow this will be **ignored or removed** with no further clarification.
|
||||
|
||||
|
||||
|
||||
### Issue summary
|
||||
|
||||
|
||||
|
||||
### Executed command (if any)
|
||||
|
||||
|
||||
|
||||
### OpenPose output (if any)
|
||||
|
||||
|
||||
|
||||
### Type of issue
|
||||
You might select multiple topics, delete the rest:
|
||||
- Compilation/installation error
|
||||
@@ -16,6 +29,8 @@ You might select multiple topics, delete the rest:
|
||||
- Enhancement / offering possible extensions / pull request / etc
|
||||
- Other (type your own type)
|
||||
|
||||
|
||||
|
||||
### Your system configuration
|
||||
**Operating system** (`lsb_release -a` on Ubuntu):
|
||||
**CUDA version** (`cat /usr/local/cuda/version.txt` in most cases):
|
||||
|
||||
@@ -6,6 +6,7 @@ OpenPose
|
||||
- May 2017: Windows version released!
|
||||
- Jun 2017: Face released!
|
||||
- Check all the [release notes](doc/release_notes.md).
|
||||
- Interested in an internship on CMU as OpenPose programmer? See [this link](https://docs.google.com/document/d/14SygG39NjIRZfx08clewTdFMGwVdtRu2acyCi3TYcHs/edit?usp=sharing) for details.
|
||||
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 82 KiB |
+5209
-1741
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+10
-10
@@ -44,13 +44,13 @@ Each flag is divided into flag name, default value, and description.
|
||||
- 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.");
|
||||
- DEFINE_int32(render_pose, 1, "Set to 0 for no rendering, 1 for CPU rendering (slightly faster), and 2 for GPU rendering (slower but greater functionality, e.g. `alpha_X` flags). If rendering is enabled, it will render both `outputData` and `cvOutputData` with the original image and desired body part to be shown (i.e. keypoints, heat maps or PAFs).");
|
||||
- DEFINE_double(alpha_pose, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will hide it. Only valid for GPU rendering.");
|
||||
- DEFINE_double(alpha_heatmap, 0.7, "Blending factor (range 0-1) between heatmap and original frame. 1 will only show the heatmap, 0 will only show the frame. Only valid for GPU rendering.");
|
||||
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.");
|
||||
- DEFINE_int32(render_face, -1, "Analogous to `render_pose` but applied to the face. Extra option: -1 to use the same configuration that `render_pose` is using.");
|
||||
- DEFINE_double(alpha_face, 0.6, "Analogous to `alpha_pose` but applied to face.");
|
||||
- DEFINE_double(alpha_heatmap_face, 0.7, "Analogous to `alpha_heatmap` but applied to face.");
|
||||
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.");
|
||||
@@ -60,11 +60,11 @@ Each flag is divided into flag name, default value, and description.
|
||||
- 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_keypoint, "", "Directory to write the people pose keypoint data. Format with `write_keypoint_format`.");
|
||||
- DEFINE_string(write_keypoint_format, "yml", "File extension and format for `write_keypoint`: json, xml, yaml & yml. Json not available for OpenCV < 3.0, use `write_keypoint_json` instead.");
|
||||
- DEFINE_string(write_keypoint_json, "", "Directory to write people pose data in *.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, "", "Directory to write heatmaps in *.png format. At least 1 `add_heatmaps_X` flag must be enabled.");
|
||||
- DEFINE_string(write_heatmaps_format, "png", "File extension and format for `write_heatmaps`, analogous to `write_images_format`. Recommended `png` or any compressed and lossless format.");
|
||||
|
||||
## Multiple Scales
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 181 KiB |
+13
-9
@@ -15,7 +15,7 @@ OpenPose Library - Release Notes
|
||||
1. Main improvements:
|
||||
1. Rendering max resolution from 720p to >32k images.
|
||||
2. Highly improved documentation.
|
||||
2. Functions or paremeters renamed:
|
||||
2. Functions or parameters 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.
|
||||
@@ -25,14 +25,14 @@ OpenPose Library - Release Notes
|
||||
## OpenPose 1.0.0rc3
|
||||
1. Main improvements:
|
||||
1. Added face keypoint detection.
|
||||
2. Added Windows 10 compatibily.
|
||||
2. Added Windows 10 compatibility.
|
||||
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).
|
||||
7. It prints out the error description before throwing the exception (so that it is written on the Windows cmd).
|
||||
8. Highly improved documentation.
|
||||
2. Functions or paremeters renamed:
|
||||
2. Functions or parameters 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.
|
||||
@@ -46,11 +46,15 @@ OpenPose Library - Release Notes
|
||||
|
||||
## Current version (future OpenPose 1.0.0rc4)
|
||||
1. Main improvements:
|
||||
1. Check() functions give more feedback.
|
||||
2. Improved documentation.
|
||||
2. Functions or paremeters renamed:
|
||||
1. `Datum::scaleRatios` to save the relative scale ratio when multi-scale.
|
||||
1. Increased accuracy on multi-scale (added `Datum::scaleRatios` to save the relative scale ratio when multi-scale).
|
||||
2. Increased speed ~3-5% by adding CPU rendering and setting it as default rendering.
|
||||
3. Check() functions give more feedback.
|
||||
4. WCocoJsonSaver finished and removed its 3599-image limit.
|
||||
5. Improved documentation.
|
||||
2. Functions or parameters renamed:
|
||||
1. Render flags renamed in the demo in order to incorporate the CPU/GPU rendering.
|
||||
3. Main bugs fixed:
|
||||
1. Fixed bug in Array::getConstCvMat() if mVolume=0, now returning empty cv::Mat.
|
||||
2. Fixed bug: `--process_real_time` threw error with webcam.
|
||||
3. Fixed bug: Face not working with output resolution different to input.
|
||||
3. Fixed bug: Face not working when input and output resolutions are different.
|
||||
4. Fixed some bugs that prevented debug version to run.
|
||||
|
||||
+120
-71
@@ -16,12 +16,12 @@
|
||||
// This file should only be used for the user to take specific examples.
|
||||
|
||||
// C++ std library dependencies
|
||||
#include <atomic> // std::atomic
|
||||
#include <atomic>
|
||||
#include <chrono> // `std::chrono::` functions and classes, e.g. std::chrono::milliseconds
|
||||
#include <cstdio> // sscanf
|
||||
#include <string> // std::string
|
||||
#include <string>
|
||||
#include <thread> // std::this_thread
|
||||
#include <vector> // std::vector
|
||||
#include <vector>
|
||||
// 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
|
||||
@@ -45,77 +45,98 @@
|
||||
// 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.");
|
||||
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_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_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. Indexes are 0-based, i.e. the first frame has index 0.");
|
||||
DEFINE_uint64(frame_last, -1, "Finish on desired frame number. Select -1 to disable. Indexes are 0-based, e.g. if set to 10, it will process"
|
||||
" 11 frames (0-10).");
|
||||
DEFINE_uint64(frame_last, -1, "Finish on desired frame number. Select -1 to disable. Indexes are 0-based, e.g. if set to"
|
||||
" 10, it will process 11 frames (0-10).");
|
||||
DEFINE_bool(frame_flip, false, "Flip/mirror each frame (e.g. for real time webcam demonstrations).");
|
||||
DEFINE_int32(frame_rotate, 0, "Rotate each frame, 4 possible values: 0, 90, 180, 270.");
|
||||
DEFINE_bool(frames_repeat, false, "Repeat frames when finished.");
|
||||
// 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_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`.");
|
||||
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_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_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.");
|
||||
// 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.");
|
||||
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_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.");
|
||||
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.");
|
||||
DEFINE_int32(render_pose, 1, "Set to 0 for no rendering, 1 for CPU rendering (slightly faster), and 2 for GPU rendering"
|
||||
" (slower but greater functionality, e.g. `alpha_X` flags). If rendering is enabled, it will"
|
||||
" render both `outputData` and `cvOutputData` with the original image and desired body part"
|
||||
" to be shown (i.e. keypoints, heat maps or PAFs).");
|
||||
DEFINE_double(alpha_pose, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will"
|
||||
" hide it. Only valid for GPU rendering.");
|
||||
DEFINE_double(alpha_heatmap, 0.7, "Blending factor (range 0-1) between heatmap and original frame. 1 will only show the"
|
||||
" heatmap, 0 will only show the frame. Only valid for GPU rendering.");
|
||||
// OpenPose Rendering Face
|
||||
DEFINE_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.");
|
||||
DEFINE_int32(render_face, -1, "Analogous to `render_pose` but applied to the face. Extra option: -1 to use the same"
|
||||
" configuration that `render_pose` is using.");
|
||||
DEFINE_double(alpha_face, 0.6, "Analogous to `alpha_pose` but applied to face.");
|
||||
DEFINE_double(alpha_heatmap_face, 0.7, "Analogous to `alpha_heatmap` but applied to face.");
|
||||
// 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(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.");
|
||||
// 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_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 pose keypoint data. Format with `write_keypoint_format`.");
|
||||
DEFINE_string(write_keypoint_format, "yml", "File extension and format for `write_keypoint`: json, xml, yaml & yml. Json not available"
|
||||
" for OpenCV < 3.0, use `write_keypoint_json` instead.");
|
||||
DEFINE_string(write_keypoint_json, "", "Directory to write people pose data in *.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.");
|
||||
DEFINE_string(write_heatmaps, "", "Directory to write heatmaps in *.png format. At least 1 `add_heatmaps_X` flag must be"
|
||||
" enabled.");
|
||||
DEFINE_string(write_heatmaps_format, "png", "File extension and format for `write_heatmaps`, analogous to `write_images_format`."
|
||||
" Recommended `png` or any compressed and lossless format.");
|
||||
|
||||
op::PoseModel gflagToPoseModel(const std::string& poseModeString)
|
||||
{
|
||||
@@ -148,7 +169,8 @@ op::ScaleMode gflagToScaleMode(const int keypointScale)
|
||||
return op::ScaleMode::PlusMinusOne;
|
||||
else
|
||||
{
|
||||
const std::string message = "String does not correspond to any scale mode: (0, 1, 2, 3, 4) for (InputResolution, NetOutputResolution, OutputResolution, ZeroToOne, PlusMinusOne).";
|
||||
const std::string message = "String does not correspond to any scale mode: (0, 1, 2, 3, 4) for (InputResolution,"
|
||||
" NetOutputResolution, OutputResolution, ZeroToOne, PlusMinusOne).";
|
||||
op::error(message, __LINE__, __FUNCTION__, __FILE__);
|
||||
return op::ScaleMode::InputResolution;
|
||||
}
|
||||
@@ -175,7 +197,8 @@ 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 op::Point<int> 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);
|
||||
@@ -193,39 +216,60 @@ std::shared_ptr<op::Producer> gflagsToProducer(const std::string& imageDirectory
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<op::HeatMapType> gflagToHeatMaps(const bool heatmaps_add_parts, const bool heatmaps_add_bkg, const bool heatmaps_add_PAFs)
|
||||
std::vector<op::HeatMapType> gflagToHeatMaps(const bool heatMapsAddParts, const bool heatMapsAddBkg, const bool heatMapsAddPAFs)
|
||||
{
|
||||
|
||||
std::vector<op::HeatMapType> heatMapTypes;
|
||||
if (heatmaps_add_parts)
|
||||
if (heatMapsAddParts)
|
||||
heatMapTypes.emplace_back(op::HeatMapType::Parts);
|
||||
if (heatmaps_add_bkg)
|
||||
if (heatMapsAddBkg)
|
||||
heatMapTypes.emplace_back(op::HeatMapType::Background);
|
||||
if (heatmaps_add_PAFs)
|
||||
if (heatMapsAddPAFs)
|
||||
heatMapTypes.emplace_back(op::HeatMapType::PAFs);
|
||||
return heatMapTypes;
|
||||
}
|
||||
|
||||
op::RenderMode gflagToRenderMode(const int renderFlag, const int renderPoseFlag = -2)
|
||||
{
|
||||
if (renderFlag == -1 && renderPoseFlag != -2)
|
||||
return gflagToRenderMode(renderPoseFlag, -2);
|
||||
else if (renderFlag == 0)
|
||||
return op::RenderMode::None;
|
||||
else if (renderFlag == 1)
|
||||
return op::RenderMode::Cpu;
|
||||
else if (renderFlag == 2)
|
||||
return op::RenderMode::Gpu;
|
||||
else
|
||||
{
|
||||
op::error("Undefined RenderMode selected.", __LINE__, __FUNCTION__, __FILE__);
|
||||
return op::RenderMode::None;
|
||||
}
|
||||
}
|
||||
|
||||
// Google flags into program variables
|
||||
std::tuple<op::Point<int>, op::Point<int>, op::Point<int>, op::Point<int>, std::shared_ptr<op::Producer>, op::PoseModel, op::ScaleMode, std::vector<op::HeatMapType>> gflagsToOpParameters()
|
||||
std::tuple<op::Point<int>, op::Point<int>, op::Point<int>, op::Point<int>, std::shared_ptr<op::Producer>, op::PoseModel,
|
||||
op::ScaleMode, std::vector<op::HeatMapType>> gflagsToOpParameters()
|
||||
{
|
||||
op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
// cameraFrameSize
|
||||
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__);
|
||||
op::checkE(nRead, 2, "Error, camera resolution format (" + FLAGS_camera_resolution + ") invalid, should be e.g., 1280x720",
|
||||
__LINE__, __FUNCTION__, __FILE__);
|
||||
// outputSize
|
||||
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__);
|
||||
op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ",
|
||||
__LINE__, __FUNCTION__, __FILE__);
|
||||
// netInputSize
|
||||
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__);
|
||||
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__);
|
||||
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__);
|
||||
// producerType
|
||||
const auto producerSharedPtr = gflagsToProducer(FLAGS_image_dir, FLAGS_video, FLAGS_camera, cameraFrameSize);
|
||||
// poseModel
|
||||
@@ -257,25 +301,29 @@ int opRealTimePoseDemo()
|
||||
op::PoseModel poseModel;
|
||||
op::ScaleMode keypointScale;
|
||||
std::vector<op::HeatMapType> heatMapTypes;
|
||||
std::tie(cameraFrameSize, outputSize, netInputSize, faceNetInputSize, producerSharedPtr, poseModel, keypointScale, heatMapTypes) = gflagsToOpParameters();
|
||||
std::tie(cameraFrameSize, outputSize, netInputSize, faceNetInputSize, producerSharedPtr, poseModel, keypointScale,
|
||||
heatMapTypes) = gflagsToOpParameters();
|
||||
|
||||
// OpenPose wrapper
|
||||
op::log("Configuring OpenPose wrapper.", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
op::Wrapper<std::vector<op::Datum>> opWrapper;
|
||||
// Pose configuration (use WrapperStructPose{} for default and recommended configuration)
|
||||
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,
|
||||
const op::WrapperStructPose wrapperStructPose{netInputSize, outputSize, keypointScale, FLAGS_num_gpu, FLAGS_num_gpu_start,
|
||||
FLAGS_num_scales, (float)FLAGS_scale_gap, gflagToRenderMode(FLAGS_render_pose), poseModel,
|
||||
!FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap,
|
||||
FLAGS_part_to_show, FLAGS_model_folder, heatMapTypes, op::ScaleMode::UnsignedChar};
|
||||
// (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)
|
||||
// Face configuration (use op::WrapperStructFace{} to disable it)
|
||||
const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, gflagToRenderMode(FLAGS_render_face, FLAGS_render_pose),
|
||||
(float)FLAGS_alpha_face, (float)FLAGS_alpha_heatmap_face};
|
||||
// Hand configuration (use op::WrapperStructHand{} to disable it)
|
||||
const op::experimental::WrapperStructHand wrapperStructHand{false};
|
||||
// Producer (use default to disable any input)
|
||||
const op::WrapperStructInput wrapperStructInput{producerSharedPtr, FLAGS_frame_first, FLAGS_frame_last, FLAGS_process_real_time, FLAGS_frame_flip,
|
||||
FLAGS_frame_rotate, FLAGS_frames_repeat};
|
||||
const op::WrapperStructInput wrapperStructInput{producerSharedPtr, FLAGS_frame_first, FLAGS_frame_last, FLAGS_process_real_time,
|
||||
FLAGS_frame_flip, FLAGS_frame_rotate, FLAGS_frames_repeat};
|
||||
// Consumer (comment or use default argument to disable any output)
|
||||
const op::WrapperStructOutput wrapperStructOutput{!FLAGS_no_display, !FLAGS_no_gui_verbose, FLAGS_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,
|
||||
const op::WrapperStructOutput wrapperStructOutput{!FLAGS_no_display, !FLAGS_no_gui_verbose, FLAGS_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, wrapperStructInput, wrapperStructOutput);
|
||||
@@ -310,7 +358,8 @@ int opRealTimePoseDemo()
|
||||
// opWrapper.stop();
|
||||
|
||||
// Measuring total time
|
||||
const auto totalTimeSec = (double)std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now()-timerBegin).count() * 1e-9;
|
||||
const auto now = std::chrono::high_resolution_clock::now();
|
||||
const auto totalTimeSec = (double)std::chrono::duration_cast<std::chrono::nanoseconds>(now-timerBegin).count() * 1e-9;
|
||||
const auto message = "Real-time pose estimation demo successfully finished. Total time: " + std::to_string(totalTimeSec) + " seconds.";
|
||||
op::log(message, op::Priority::Max);
|
||||
|
||||
|
||||
@@ -22,21 +22,26 @@
|
||||
// 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.");
|
||||
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_path, "examples/media/COCO_val2014_000000000192.jpg", "Process the desired image.");
|
||||
// OpenPose
|
||||
DEFINE_string(model_pose, "COCO", "Model to be used (e.g. COCO, MPI, MPI_4_layers).");
|
||||
DEFINE_string(model_folder, "models/", "Folder path (absolute or relative) where the models (pose, face, ...) are located.");
|
||||
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_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 and output). 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, "
|
||||
"you actually want to multiply the `net_resolution` by your desired initial scale.");
|
||||
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(num_scales, 1, "Number of scales to average.");
|
||||
// OpenPose Rendering
|
||||
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_pose, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will"
|
||||
" hide it. Only valid for GPU rendering.");
|
||||
|
||||
op::PoseModel gflagToPoseModel(const std::string& poseModeString)
|
||||
{
|
||||
@@ -61,11 +66,13 @@ std::tuple<op::Point<int>, op::Point<int>, op::Point<int>, op::PoseModel> gflags
|
||||
// outputSize
|
||||
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__);
|
||||
op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ",
|
||||
__LINE__, __FUNCTION__, __FILE__);
|
||||
// netInputSize
|
||||
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__);
|
||||
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;
|
||||
// poseModel
|
||||
|
||||
@@ -22,23 +22,29 @@
|
||||
// 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.");
|
||||
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_path, "examples/media/COCO_val2014_000000000192.jpg", "Process the desired image.");
|
||||
// OpenPose
|
||||
DEFINE_string(model_pose, "COCO", "Model to be used (e.g. COCO, MPI, MPI_4_layers).");
|
||||
DEFINE_string(model_folder, "models/", "Folder path (absolute or relative) where the models (pose, face, ...) are located.");
|
||||
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_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 and output). 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, "
|
||||
"you actually want to multiply the `net_resolution` by your desired initial scale.");
|
||||
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(num_scales, 1, "Number of scales to average.");
|
||||
// OpenPose Rendering
|
||||
DEFINE_int32(part_to_show, 19, "Part to show from the start.");
|
||||
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.");
|
||||
DEFINE_double(alpha_pose, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will"
|
||||
" hide it. Only valid for GPU rendering.");
|
||||
DEFINE_double(alpha_heatmap, 0.7, "Blending factor (range 0-1) between heatmap and original frame. 1 will only show the"
|
||||
" heatmap, 0 will only show the frame. Only valid for GPU rendering.");
|
||||
|
||||
op::PoseModel gflagToPoseModel(const std::string& poseModeString)
|
||||
{
|
||||
@@ -63,11 +69,13 @@ std::tuple<op::Point<int>, op::Point<int>, op::Point<int>, op::PoseModel> gflags
|
||||
// outputSize
|
||||
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__);
|
||||
op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ",
|
||||
__LINE__, __FUNCTION__, __FILE__);
|
||||
// netInputSize
|
||||
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__);
|
||||
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;
|
||||
// poseModel
|
||||
@@ -100,8 +108,9 @@ int openPoseTutorialPose2()
|
||||
// Step 3 - Initialize all required classes
|
||||
op::CvMatToOpInput cvMatToOpInput{netInputSize, FLAGS_num_scales, (float)FLAGS_scale_gap};
|
||||
op::CvMatToOpOutput cvMatToOpOutput{outputSize};
|
||||
std::shared_ptr<op::PoseExtractor> poseExtractorPtr = std::make_shared<op::PoseExtractorCaffe>(netInputSize, netOutputSize, outputSize, FLAGS_num_scales,
|
||||
poseModel, FLAGS_model_folder, FLAGS_num_gpu_start);
|
||||
std::shared_ptr<op::PoseExtractor> poseExtractorPtr = std::make_shared<op::PoseExtractorCaffe>(netInputSize, netOutputSize, outputSize,
|
||||
FLAGS_num_scales, poseModel,
|
||||
FLAGS_model_folder, FLAGS_num_gpu_start);
|
||||
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};
|
||||
|
||||
@@ -21,19 +21,23 @@
|
||||
// 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.");
|
||||
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_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_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.");
|
||||
// OpenPose
|
||||
DEFINE_string(resolution, "1280x720", "The image resolution (display). Use \"-1x-1\" to force the program to use the default images resolution.");
|
||||
DEFINE_string(resolution, "1280x720", "The image resolution (display and output). Use \"-1x-1\" to force the program to use the"
|
||||
" default images resolution.");
|
||||
// Consumer
|
||||
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(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.");
|
||||
|
||||
// Determine type of frame source
|
||||
op::ProducerType gflagsToProducerType(const std::string& imageDirectory, const std::string& videoPath, const int webcamIndex)
|
||||
@@ -56,7 +60,8 @@ 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 op::Point<int> 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);
|
||||
@@ -81,11 +86,13 @@ std::tuple<op::Point<int>, op::Point<int>, std::shared_ptr<op::Producer>> gflags
|
||||
// cameraFrameSize
|
||||
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__);
|
||||
op::checkE(nRead, 2, "Error, camera resolution format (" + FLAGS_camera_resolution + ") invalid, should be e.g., 1280x720",
|
||||
__LINE__, __FUNCTION__, __FILE__);
|
||||
// outputSize
|
||||
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__);
|
||||
op::checkE(nRead, 2, "Error, camera resolution format (" + FLAGS_camera_resolution + ") invalid, should be e.g., 1280x720",
|
||||
__LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// producerType
|
||||
const auto producerSharedPtr = gflagsToProducer(FLAGS_image_dir, FLAGS_video, FLAGS_camera, cameraFrameSize);
|
||||
@@ -121,7 +128,8 @@ int openPoseTutorialThread1()
|
||||
if (producerSize.area() > 0)
|
||||
outputSize = producerSize;
|
||||
else
|
||||
op::error("Output resolution = input resolution not valid for image reading (size might change between images).", __LINE__, __FUNCTION__, __FILE__);
|
||||
op::error("Output resolution = input resolution not valid for image reading (size might change between images).",
|
||||
__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
// Step 4 - Setting thread workers && manager
|
||||
typedef std::vector<op::Datum> TypedefDatumsNoPtr;
|
||||
@@ -138,7 +146,8 @@ int openPoseTutorialThread1()
|
||||
// ------------------------- CONFIGURING THREADING -------------------------
|
||||
// In this simple multi-thread example, we will do the following:
|
||||
// 3 (virtual) queues: 0, 1, 2
|
||||
// 1 real queue: 1. The first and last queue ids (in this case 0 and 2) are not actual queues, but the beginning and end of the processing sequence
|
||||
// 1 real queue: 1. The first and last queue ids (in this case 0 and 2) are not actual queues, but the beginning and end of the processing
|
||||
// sequence
|
||||
// 2 threads: 0, 1
|
||||
// wDatumProducer will generate frames (there is no real queue 0) and push them on queue 1
|
||||
// wGui will pop frames from queue 1 and process them (there is no real queue 2)
|
||||
|
||||
@@ -22,19 +22,23 @@
|
||||
// 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.");
|
||||
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_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_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.");
|
||||
// OpenPose
|
||||
DEFINE_string(resolution, "1280x720", "The image resolution (display). Use \"-1x-1\" to force the program to use the default images resolution.");
|
||||
DEFINE_string(resolution, "1280x720", "The image resolution (display and output). Use \"-1x-1\" to force the program to use the"
|
||||
" default images resolution.");
|
||||
// Consumer
|
||||
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(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.");
|
||||
|
||||
// This class can be implemented either as a template or as a simple class given
|
||||
// that the user usually knows which kind of data he will move between the queues,
|
||||
@@ -90,7 +94,8 @@ 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 op::Point<int> 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);
|
||||
@@ -115,11 +120,13 @@ std::tuple<op::Point<int>, op::Point<int>, std::shared_ptr<op::Producer>> gflags
|
||||
// cameraFrameSize
|
||||
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__);
|
||||
op::checkE(nRead, 2, "Error, camera resolution format (" + FLAGS_camera_resolution + ") invalid, should be e.g., 1280x720",
|
||||
__LINE__, __FUNCTION__, __FILE__);
|
||||
// outputSize
|
||||
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__);
|
||||
op::checkE(nRead, 2, "Error, camera resolution format (" + FLAGS_camera_resolution + ") invalid, should be e.g., 1280x720",
|
||||
__LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// producerType
|
||||
const auto producerSharedPtr = gflagsToProducer(FLAGS_image_dir, FLAGS_video, FLAGS_camera, cameraFrameSize);
|
||||
@@ -155,7 +162,8 @@ int openPoseTutorialThread2()
|
||||
if (producerSize.area() > 0)
|
||||
outputSize = producerSize;
|
||||
else
|
||||
op::error("Output resolution = input resolution not valid for image reading (size might change between images).", __LINE__, __FUNCTION__, __FILE__);
|
||||
op::error("Output resolution = input resolution not valid for image reading (size might change between images).",
|
||||
__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
// Step 4 - Setting thread workers && manager
|
||||
typedef std::vector<op::Datum> TypedefDatumsNoPtr;
|
||||
@@ -174,7 +182,8 @@ int openPoseTutorialThread2()
|
||||
// ------------------------- CONFIGURING THREADING -------------------------
|
||||
// In this simple multi-thread example, we will do the following:
|
||||
// 3 (virtual) queues: 0, 1, 2
|
||||
// 1 real queue: 1. The first and last queue ids (in this case 0 and 2) are not actual queues, but the beginning and end of the processing sequence
|
||||
// 1 real queue: 1. The first and last queue ids (in this case 0 and 2) are not actual queues, but the beginning and end of the processing
|
||||
// sequence
|
||||
// 2 threads: 0, 1
|
||||
// wDatumProducer will generate frames (there is no real queue 0) and push them on queue 1
|
||||
// wGui will pop frames from queue 1 and process them (there is no real queue 2)
|
||||
|
||||
@@ -27,8 +27,9 @@
|
||||
// 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.");
|
||||
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.");
|
||||
// Consumer
|
||||
@@ -183,7 +184,8 @@ int openPoseTutorialThread3()
|
||||
// ------------------------- CONFIGURING THREADING -------------------------
|
||||
// In this simple multi-thread example, we will do the following:
|
||||
// 3 (virtual) queues: 0, 1, 2
|
||||
// 1 real queue: 1. The first and last queue ids (in this case 0 and 2) are not actual queues, but the beginning and end of the processing sequence
|
||||
// 1 real queue: 1. The first and last queue ids (in this case 0 and 2) are not actual queues, but the beginning and end of the processing
|
||||
// sequence
|
||||
// 2 threads: 0, 1
|
||||
// wUserInput will generate frames (there is no real queue 0) and push them on queue 1
|
||||
// wGui will pop frames from queue 1 and process them (there is no real queue 2)
|
||||
|
||||
@@ -27,8 +27,9 @@
|
||||
// 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.");
|
||||
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.");
|
||||
// Consumer
|
||||
@@ -36,7 +37,8 @@ DEFINE_bool(fullscreen, false, "Run in full-screen mode
|
||||
|
||||
|
||||
// If the user needs his own variables, he can inherit the op::Datum struct and add them
|
||||
// UserDatum can be directly used by the OpenPose wrapper because it inherits from op::Datum, just define Wrapper<UserDatum> instead of Wrapper<op::Datum>
|
||||
// UserDatum can be directly used by the OpenPose wrapper because it inherits from op::Datum, just define Wrapper<UserDatum> instead of
|
||||
// Wrapper<op::Datum>
|
||||
struct UserDatum : public op::Datum
|
||||
{
|
||||
bool boolThatUserNeedsForSomeReason;
|
||||
@@ -195,7 +197,8 @@ int openPoseTutorialThread4()
|
||||
// ------------------------- CONFIGURING THREADING -------------------------
|
||||
// In this simple multi-thread example, we will do the following:
|
||||
// 3 (virtual) queues: 0, 1, 2
|
||||
// 1 real queue: 1. The first and last queue ids (in this case 0 and 2) are not actual queues, but the beginning and end of the processing sequence
|
||||
// 1 real queue: 1. The first and last queue ids (in this case 0 and 2) are not actual queues, but the beginning and end of the processing
|
||||
// sequence
|
||||
// 2 threads: 0, 1
|
||||
// wUserInput will generate frames (there is no real queue 0) and push them on queue 1
|
||||
// wGui will pop frames from queue 1 and process them (there is no real queue 2)
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
// This file should only be used for the user to take specific examples.
|
||||
|
||||
// C++ std library dependencies
|
||||
#include <atomic> // std::atomic
|
||||
#include <atomic>
|
||||
#include <chrono> // `std::chrono::` functions and classes, e.g. std::chrono::milliseconds
|
||||
#include <cstdio> // sscanf
|
||||
#include <string> // std::string
|
||||
#include <string>
|
||||
#include <thread> // std::this_thread
|
||||
#include <vector> // std::vector
|
||||
#include <vector>
|
||||
// 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
|
||||
@@ -43,67 +43,87 @@
|
||||
// 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.");
|
||||
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_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_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`.");
|
||||
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_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_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.");
|
||||
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].");
|
||||
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.");
|
||||
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_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.");
|
||||
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.");
|
||||
DEFINE_int32(render_pose, 1, "Set to 0 for no rendering, 1 for CPU rendering (slightly faster), and 2 for GPU rendering"
|
||||
" (slower but greater functionality, e.g. `alpha_X` flags). If rendering is enabled, it will"
|
||||
" render both `outputData` and `cvOutputData` with the original image and desired body part"
|
||||
" to be shown (i.e. keypoints, heat maps or PAFs).");
|
||||
DEFINE_double(alpha_pose, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will"
|
||||
" hide it. Only valid for GPU rendering.");
|
||||
DEFINE_double(alpha_heatmap, 0.7, "Blending factor (range 0-1) between heatmap and original frame. 1 will only show the"
|
||||
" heatmap, 0 will only show the frame. Only valid for GPU rendering.");
|
||||
// OpenPose Rendering Face
|
||||
DEFINE_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.");
|
||||
DEFINE_int32(render_face, -1, "Analogous to `render_pose` but applied to the face. Extra option: -1 to use the same"
|
||||
" configuration that `render_pose` is using.");
|
||||
DEFINE_double(alpha_face, 0.6, "Analogous to `alpha_pose` but applied to face.");
|
||||
DEFINE_double(alpha_heatmap_face, 0.7, "Analogous to `alpha_heatmap` but applied to face.");
|
||||
// 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_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 pose keypoint data. Format with `write_keypoint_format`.");
|
||||
DEFINE_string(write_keypoint_format, "yml", "File extension and format for `write_keypoint`: json, xml, yaml & yml. Json not available"
|
||||
" for OpenCV < 3.0, use `write_keypoint_json` instead.");
|
||||
DEFINE_string(write_keypoint_json, "", "Directory to write people pose data in *.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.");
|
||||
DEFINE_string(write_heatmaps, "", "Directory to write heatmaps in *.png format. At least 1 `add_heatmaps_X` flag must be"
|
||||
" enabled.");
|
||||
DEFINE_string(write_heatmaps_format, "png", "File extension and format for `write_heatmaps`, analogous to `write_images_format`."
|
||||
" Recommended `png` or any compressed and lossless format.");
|
||||
|
||||
|
||||
// If the user needs his own variables, he can inherit the op::Datum struct and add them
|
||||
// UserDatum can be directly used by the OpenPose wrapper because it inherits from op::Datum, just define Wrapper<UserDatum> instead of Wrapper<op::Datum>
|
||||
// UserDatum can be directly used by the OpenPose wrapper because it inherits from op::Datum, just define Wrapper<UserDatum> instead of
|
||||
// Wrapper<op::Datum>
|
||||
struct UserDatum : public op::Datum
|
||||
{
|
||||
bool boolThatUserNeedsForSomeReason;
|
||||
@@ -224,41 +244,62 @@ op::ScaleMode gflagToScaleMode(const int keypointScale)
|
||||
return op::ScaleMode::PlusMinusOne;
|
||||
else
|
||||
{
|
||||
const std::string message = "String does not correspond to any scale mode: (0, 1, 2, 3, 4) for (InputResolution, NetOutputResolution, OutputResolution, ZeroToOne, PlusMinusOne).";
|
||||
const std::string message = "String does not correspond to any scale mode: (0, 1, 2, 3, 4) for (InputResolution,"
|
||||
" NetOutputResolution, OutputResolution, ZeroToOne, PlusMinusOne).";
|
||||
op::error(message, __LINE__, __FUNCTION__, __FILE__);
|
||||
return op::ScaleMode::InputResolution;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<op::HeatMapType> gflagToHeatMaps(const bool heatmaps_add_parts, const bool heatmaps_add_bkg, const bool heatmaps_add_PAFs)
|
||||
std::vector<op::HeatMapType> gflagToHeatMaps(const bool heatMapsAddParts, const bool heatMapsAddBkg, const bool heatMapsAddPAFs)
|
||||
{
|
||||
|
||||
std::vector<op::HeatMapType> heatMapTypes;
|
||||
if (heatmaps_add_parts)
|
||||
if (heatMapsAddParts)
|
||||
heatMapTypes.emplace_back(op::HeatMapType::Parts);
|
||||
if (heatmaps_add_bkg)
|
||||
if (heatMapsAddBkg)
|
||||
heatMapTypes.emplace_back(op::HeatMapType::Background);
|
||||
if (heatmaps_add_PAFs)
|
||||
if (heatMapsAddPAFs)
|
||||
heatMapTypes.emplace_back(op::HeatMapType::PAFs);
|
||||
return heatMapTypes;
|
||||
}
|
||||
|
||||
op::RenderMode gflagToRenderMode(const int renderFlag, const int renderPoseFlag = -2)
|
||||
{
|
||||
if (renderFlag == -1 && renderPoseFlag != -2)
|
||||
return gflagToRenderMode(renderPoseFlag, -2);
|
||||
else if (renderFlag == 0)
|
||||
return op::RenderMode::None;
|
||||
else if (renderFlag == 1)
|
||||
return op::RenderMode::Cpu;
|
||||
else if (renderFlag == 2)
|
||||
return op::RenderMode::Gpu;
|
||||
else
|
||||
{
|
||||
op::error("Undefined RenderMode selected.", __LINE__, __FUNCTION__, __FILE__);
|
||||
return op::RenderMode::None;
|
||||
}
|
||||
}
|
||||
|
||||
// Google flags into program variables
|
||||
std::tuple<op::Point<int>, op::Point<int>, op::Point<int>, 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
|
||||
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__);
|
||||
op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ",
|
||||
__LINE__, __FUNCTION__, __FILE__);
|
||||
// netInputSize
|
||||
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__);
|
||||
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__);
|
||||
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);
|
||||
// keypointScale
|
||||
@@ -266,7 +307,8 @@ std::tuple<op::Point<int>, op::Point<int>, op::Point<int>, op::PoseModel, op::Sc
|
||||
// heatmaps to add
|
||||
const auto heatMapTypes = gflagToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg, FLAGS_heatmaps_add_PAFs);
|
||||
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 ));
|
||||
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, faceNetInputSize, poseModel, keypointScale, heatMapTypes, heatMapScale);
|
||||
}
|
||||
@@ -297,16 +339,19 @@ int openPoseTutorialWrapper1()
|
||||
const bool displayGui = false;
|
||||
const bool guiVerbose = false;
|
||||
const bool fullScreen = false;
|
||||
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,
|
||||
const op::WrapperStructPose wrapperStructPose{netInputSize, outputSize, keypointScale, FLAGS_num_gpu, FLAGS_num_gpu_start,
|
||||
FLAGS_num_scales, (float)FLAGS_scale_gap, gflagToRenderMode(FLAGS_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)
|
||||
// Face configuration (use op::WrapperStructFace{} to disable it)
|
||||
const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, gflagToRenderMode(FLAGS_render_face, FLAGS_render_pose),
|
||||
(float)FLAGS_alpha_face, (float)FLAGS_alpha_heatmap_face};
|
||||
// Hand configuration (use op::WrapperStructHand{} to disable it)
|
||||
const op::experimental::WrapperStructHand wrapperStructHand{false};
|
||||
// Consumer (comment or use default argument to disable any output)
|
||||
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,
|
||||
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);
|
||||
@@ -339,7 +384,8 @@ int openPoseTutorialWrapper1()
|
||||
opWrapper.stop();
|
||||
|
||||
// Measuring total time
|
||||
const auto totalTimeSec = (double)std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now()-timerBegin).count() * 1e-9;
|
||||
const auto now = std::chrono::high_resolution_clock::now();
|
||||
const auto totalTimeSec = (double)std::chrono::duration_cast<std::chrono::nanoseconds>(now-timerBegin).count() * 1e-9;
|
||||
const auto message = "Real-time pose estimation demo successfully finished. Total time: " + std::to_string(totalTimeSec) + " seconds.";
|
||||
op::log(message, op::Priority::Max);
|
||||
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
// This file should only be used for the user to take specific examples.
|
||||
|
||||
// C++ std library dependencies
|
||||
#include <atomic> // std::atomic
|
||||
#include <atomic>
|
||||
#include <chrono> // `std::chrono::` functions and classes, e.g. std::chrono::milliseconds
|
||||
#include <cstdio> // sscanf
|
||||
#include <string> // std::string
|
||||
#include <string>
|
||||
#include <thread> // std::this_thread
|
||||
#include <vector> // std::vector
|
||||
#include <vector>
|
||||
// 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
|
||||
@@ -43,67 +43,87 @@
|
||||
// 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.");
|
||||
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_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_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`.");
|
||||
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_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_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.");
|
||||
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].");
|
||||
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.");
|
||||
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_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.");
|
||||
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.");
|
||||
DEFINE_int32(render_pose, 1, "Set to 0 for no rendering, 1 for CPU rendering (slightly faster), and 2 for GPU rendering"
|
||||
" (slower but greater functionality, e.g. `alpha_X` flags). If rendering is enabled, it will"
|
||||
" render both `outputData` and `cvOutputData` with the original image and desired body part"
|
||||
" to be shown (i.e. keypoints, heat maps or PAFs).");
|
||||
DEFINE_double(alpha_pose, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will"
|
||||
" hide it. Only valid for GPU rendering.");
|
||||
DEFINE_double(alpha_heatmap, 0.7, "Blending factor (range 0-1) between heatmap and original frame. 1 will only show the"
|
||||
" heatmap, 0 will only show the frame. Only valid for GPU rendering.");
|
||||
// OpenPose Rendering Face
|
||||
DEFINE_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.");
|
||||
DEFINE_int32(render_face, -1, "Analogous to `render_pose` but applied to the face. Extra option: -1 to use the same"
|
||||
" configuration that `render_pose` is using.");
|
||||
DEFINE_double(alpha_face, 0.6, "Analogous to `alpha_pose` but applied to face.");
|
||||
DEFINE_double(alpha_heatmap_face, 0.7, "Analogous to `alpha_heatmap` but applied to face.");
|
||||
// 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_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 pose keypoint data. Format with `write_keypoint_format`.");
|
||||
DEFINE_string(write_keypoint_format, "yml", "File extension and format for `write_keypoint`: json, xml, yaml & yml. Json not available"
|
||||
" for OpenCV < 3.0, use `write_keypoint_json` instead.");
|
||||
DEFINE_string(write_keypoint_json, "", "Directory to write people pose data in *.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.");
|
||||
DEFINE_string(write_heatmaps, "", "Directory to write heatmaps in *.png format. At least 1 `add_heatmaps_X` flag must be"
|
||||
" enabled.");
|
||||
DEFINE_string(write_heatmaps_format, "png", "File extension and format for `write_heatmaps`, analogous to `write_images_format`."
|
||||
" Recommended `png` or any compressed and lossless format.");
|
||||
|
||||
|
||||
// If the user needs his own variables, he can inherit the op::Datum struct and add them
|
||||
// UserDatum can be directly used by the OpenPose wrapper because it inherits from op::Datum, just define Wrapper<UserDatum> instead of Wrapper<op::Datum>
|
||||
// UserDatum can be directly used by the OpenPose wrapper because it inherits from op::Datum, just define Wrapper<UserDatum> instead of
|
||||
// Wrapper<op::Datum>
|
||||
struct UserDatum : public op::Datum
|
||||
{
|
||||
bool boolThatUserNeedsForSomeReason;
|
||||
@@ -269,41 +289,62 @@ op::ScaleMode gflagToScaleMode(const int keypointScale)
|
||||
return op::ScaleMode::PlusMinusOne;
|
||||
else
|
||||
{
|
||||
const std::string message = "String does not correspond to any scale mode: (0, 1, 2, 3, 4) for (InputResolution, NetOutputResolution, OutputResolution, ZeroToOne, PlusMinusOne).";
|
||||
const std::string message = "String does not correspond to any scale mode: (0, 1, 2, 3, 4) for (InputResolution,"
|
||||
" NetOutputResolution, OutputResolution, ZeroToOne, PlusMinusOne).";
|
||||
op::error(message, __LINE__, __FUNCTION__, __FILE__);
|
||||
return op::ScaleMode::InputResolution;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<op::HeatMapType> gflagToHeatMaps(const bool heatmaps_add_parts, const bool heatmaps_add_bkg, const bool heatmaps_add_PAFs)
|
||||
std::vector<op::HeatMapType> gflagToHeatMaps(const bool heatMapsAddParts, const bool heatMapsAddBkg, const bool heatMapsAddPAFs)
|
||||
{
|
||||
|
||||
std::vector<op::HeatMapType> heatMapTypes;
|
||||
if (heatmaps_add_parts)
|
||||
if (heatMapsAddParts)
|
||||
heatMapTypes.emplace_back(op::HeatMapType::Parts);
|
||||
if (heatmaps_add_bkg)
|
||||
if (heatMapsAddBkg)
|
||||
heatMapTypes.emplace_back(op::HeatMapType::Background);
|
||||
if (heatmaps_add_PAFs)
|
||||
if (heatMapsAddPAFs)
|
||||
heatMapTypes.emplace_back(op::HeatMapType::PAFs);
|
||||
return heatMapTypes;
|
||||
}
|
||||
|
||||
op::RenderMode gflagToRenderMode(const int renderFlag, const int renderPoseFlag = -2)
|
||||
{
|
||||
if (renderFlag == -1 && renderPoseFlag != -2)
|
||||
return gflagToRenderMode(renderPoseFlag, -2);
|
||||
else if (renderFlag == 0)
|
||||
return op::RenderMode::None;
|
||||
else if (renderFlag == 1)
|
||||
return op::RenderMode::Cpu;
|
||||
else if (renderFlag == 2)
|
||||
return op::RenderMode::Gpu;
|
||||
else
|
||||
{
|
||||
op::error("Undefined RenderMode selected.", __LINE__, __FUNCTION__, __FILE__);
|
||||
return op::RenderMode::None;
|
||||
}
|
||||
}
|
||||
|
||||
// Google flags into program variables
|
||||
std::tuple<op::Point<int>, op::Point<int>, op::Point<int>, 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
|
||||
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__);
|
||||
op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ",
|
||||
__LINE__, __FUNCTION__, __FILE__);
|
||||
// netInputSize
|
||||
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__);
|
||||
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__);
|
||||
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);
|
||||
// keypointScale
|
||||
@@ -311,7 +352,8 @@ std::tuple<op::Point<int>, op::Point<int>, op::Point<int>, op::PoseModel, op::Sc
|
||||
// heatmaps to add
|
||||
const auto heatMapTypes = gflagToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg, FLAGS_heatmaps_add_PAFs);
|
||||
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 ));
|
||||
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, faceNetInputSize, poseModel, keypointScale, heatMapTypes, heatMapScale);
|
||||
}
|
||||
@@ -359,16 +401,19 @@ int openPoseTutorialWrapper2()
|
||||
const bool displayGui = false;
|
||||
const bool guiVerbose = false;
|
||||
const bool fullScreen = false;
|
||||
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,
|
||||
const op::WrapperStructPose wrapperStructPose{netInputSize, outputSize, keypointScale, FLAGS_num_gpu, FLAGS_num_gpu_start,
|
||||
FLAGS_num_scales, (float)FLAGS_scale_gap, gflagToRenderMode(FLAGS_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)
|
||||
// Face configuration (use op::WrapperStructFace{} to disable it)
|
||||
const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, gflagToRenderMode(FLAGS_render_face, FLAGS_render_pose),
|
||||
(float)FLAGS_alpha_face, (float)FLAGS_alpha_heatmap_face};
|
||||
// Hand configuration (use op::WrapperStructHand{} to disable it)
|
||||
const op::experimental::WrapperStructHand wrapperStructHand{false};
|
||||
// Consumer (comment or use default argument to disable any output)
|
||||
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,
|
||||
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);
|
||||
@@ -400,7 +445,8 @@ int openPoseTutorialWrapper2()
|
||||
// opWrapper.stop();
|
||||
|
||||
// Measuring total time
|
||||
const auto totalTimeSec = (double)std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now()-timerBegin).count() * 1e-9;
|
||||
const auto now = std::chrono::high_resolution_clock::now();
|
||||
const auto totalTimeSec = (double)std::chrono::duration_cast<std::chrono::nanoseconds>(now-timerBegin).count() * 1e-9;
|
||||
const auto message = "Real-time pose estimation demo successfully finished. Total time: " + std::to_string(totalTimeSec) + " seconds.";
|
||||
op::log(message, op::Priority::Max);
|
||||
|
||||
|
||||
@@ -211,12 +211,6 @@ namespace op
|
||||
return spData.get();
|
||||
}
|
||||
|
||||
// Disabled because people might try to modify it in illegal ways and change the allocated memory (e.g. resizing), leading to huge errors
|
||||
// inline cv::Mat& getCvMat()
|
||||
// {
|
||||
// return mCvMatData.second;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Return a cv::Mat wrapper to the data. It forbids the data to be modified.
|
||||
* OpenCV only admits unsigned char, signed char, int, float & double. If the T class is not supported by OpenCV, it will throw an error.
|
||||
@@ -229,6 +223,14 @@ namespace op
|
||||
*/
|
||||
const cv::Mat& getConstCvMat() const;
|
||||
|
||||
/**
|
||||
* Analogous to getConstCvMat, but in this case it returns a editable cv::Mat.
|
||||
* Very important: Only allowed functions which do not provoke data reallocation.
|
||||
* E.g. resizing functions will not work and they would provoke an undefined behaviour and/or execution crashes.
|
||||
* @return A cv::Mat pointing to the data.
|
||||
*/
|
||||
cv::Mat& getCvMat();
|
||||
|
||||
/**
|
||||
* [] operator
|
||||
* Similar to the [] operator for raw pointer data.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define OPENPOSE_CORE_DATUM_HPP
|
||||
|
||||
#include <memory> // std::shared_ptr
|
||||
#include <string> // std::string
|
||||
#include <string>
|
||||
#include <opencv2/core/core.hpp> // cv::Mat
|
||||
#include "array.hpp"
|
||||
#include "point.hpp"
|
||||
|
||||
@@ -19,6 +19,13 @@ namespace op
|
||||
Background,
|
||||
PAFs,
|
||||
};
|
||||
|
||||
enum class RenderMode : unsigned char
|
||||
{
|
||||
None,
|
||||
Cpu,
|
||||
Gpu,
|
||||
};
|
||||
}
|
||||
|
||||
#endif // OPENPOSE_CORE_ENUM_CLASSES_HPP
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "renderer.hpp"
|
||||
#include "resizeAndMergeBase.hpp"
|
||||
#include "resizeAndMergeCaffe.hpp"
|
||||
#include "scaleKeypoints.hpp"
|
||||
#include "wCvMatToOpInput.hpp"
|
||||
#include "wCvMatToOpOutput.hpp"
|
||||
#include "wKeypointScaler.hpp"
|
||||
|
||||
@@ -11,8 +11,8 @@ namespace op
|
||||
class Renderer
|
||||
{
|
||||
public:
|
||||
explicit Renderer(const unsigned long long volume, const float alphaKeypoint, const float alphaHeatMap, const unsigned int elementToRender = 0u,
|
||||
const unsigned int numberElementsToRender = 0u);
|
||||
explicit Renderer(const unsigned long long volume, const float alphaKeypoint, const float alphaHeatMap,
|
||||
const unsigned int elementToRender = 0u, const unsigned int numberElementsToRender = 0u);
|
||||
|
||||
~Renderer();
|
||||
|
||||
@@ -22,9 +22,11 @@ namespace op
|
||||
|
||||
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();
|
||||
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>>,
|
||||
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;
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#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 scaleX, const float scaleY);
|
||||
|
||||
void scaleKeypoints(Array<float>& keypoints, const float scaleX, const float scaleY, const float offsetX, const float offsetY);
|
||||
}
|
||||
|
||||
#endif // OPENPOSE_CORE_SCALE_KEYPOINTS_HPP
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include <openpose/thread/worker.hpp>
|
||||
#include "keypointScaler.hpp"
|
||||
#include "scaleKeypoints.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
|
||||
@@ -9,7 +9,33 @@ namespace op
|
||||
const auto HAND_MAX_HANDS = 2*POSE_MAX_PEOPLE;
|
||||
|
||||
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}
|
||||
#define HAND_PAIRS_RENDER_GPU {0,1, 1,2, 2,3, 3,4, 0,5, 5,6, 6,7, 7,8, 0,9, 9,10, 10,11, 11,12, 0,13, 13,14, 14,15, 15,16, 0,17, 17,18, 18,19, 19,20}
|
||||
const std::vector<unsigned int> HAND_PAIRS_RENDER {HAND_PAIRS_RENDER_GPU};
|
||||
#define HAND_COLORS_RENDER \
|
||||
179.f, 0.f, 0.f, \
|
||||
204.f, 0.f, 0.f, \
|
||||
230.f, 0.f, 0.f, \
|
||||
255.f, 0.f, 0.f, \
|
||||
143.f, 179.f, 0.f, \
|
||||
163.f, 204.f, 0.f, \
|
||||
184.f, 230.f, 0.f, \
|
||||
204.f, 255.f, 0.f, \
|
||||
0.f, 179.f, 71.f, \
|
||||
0.f, 204.f, 82.f, \
|
||||
0.f, 230.f, 92.f, \
|
||||
0.f, 255.f, 102.f, \
|
||||
0.f, 71.f, 179.f, \
|
||||
0.f, 82.f, 204.f, \
|
||||
0.f, 92.f, 230.f, \
|
||||
0.f, 102.f, 255.f, \
|
||||
143.f, 0.f, 179.f, \
|
||||
163.f, 0.f, 204.f, \
|
||||
184.f, 0.f, 230.f, \
|
||||
204.f, 0.f, 255.f, \
|
||||
179.f, 179.f, 179.f, \
|
||||
179.f, 179.f, 179.f, \
|
||||
179.f, 179.f, 179.f, \
|
||||
179.f, 179.f, 179.f
|
||||
|
||||
// Constant parameters
|
||||
const auto HAND_CCN_DECREASE_FACTOR = 8.f;
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#ifndef OPENPOSE_HAND_GPU_HAND_RENDER_HPP
|
||||
#define OPENPOSE_HAND_GPU_HAND_RENDER_HPP
|
||||
|
||||
#include <openpose/core/point.hpp>
|
||||
#include "handParameters.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
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
|
||||
@@ -2,9 +2,11 @@
|
||||
#define OPENPOSE_HAND_HAND_RENDERER_HPP
|
||||
|
||||
#include <openpose/core/array.hpp>
|
||||
#include <openpose/core/enumClasses.hpp>
|
||||
#include <openpose/core/point.hpp>
|
||||
#include <openpose/core/renderer.hpp>
|
||||
#include <openpose/thread/worker.hpp>
|
||||
#include "handParameters.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
@@ -13,17 +15,23 @@ namespace op
|
||||
class HandRenderer : public Renderer
|
||||
{
|
||||
public:
|
||||
explicit HandRenderer(const Point<int>& frameSize);
|
||||
HandRenderer(const Point<int>& frameSize, const float alphaKeypoint = HAND_DEFAULT_ALPHA_KEYPOINT,
|
||||
const float alphaHeatMap = HAND_DEFAULT_ALPHA_HEAT_MAP, const RenderMode renderMode = RenderMode::Cpu);
|
||||
|
||||
~HandRenderer();
|
||||
|
||||
void initializationOnThread();
|
||||
|
||||
void renderHands(Array<float>& outputData, const Array<float>& handKeypoints);
|
||||
void renderHand(Array<float>& outputData, const Array<float>& handKeypoints);
|
||||
|
||||
private:
|
||||
const Point<int> mFrameSize;
|
||||
float* pGpuHands; // GPU aux memory
|
||||
const RenderMode mRenderMode;
|
||||
float* pGpuHands; // GPU aux memory
|
||||
|
||||
void renderHandCpu(Array<float>& outputData, const Array<float>& handKeypoints);
|
||||
|
||||
void renderHandGpu(Array<float>& outputData, const Array<float>& handKeypoints);
|
||||
|
||||
DELETE_COPY(HandRenderer);
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "handExtractor.hpp"
|
||||
#include "handParameters.hpp"
|
||||
#include "handRenderer.hpp"
|
||||
#include "handRenderGpu.hpp"
|
||||
#include "renderHand.hpp"
|
||||
#include "wHandExtractor.hpp"
|
||||
#include "wHandRenderer.hpp"
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef OPENPOSE_HAND_GPU_HAND_RENDER_HPP
|
||||
#define OPENPOSE_HAND_GPU_HAND_RENDER_HPP
|
||||
|
||||
#include <openpose/core/array.hpp>
|
||||
#include <openpose/core/point.hpp>
|
||||
#include "handParameters.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
void renderHandKeypointsCpu(Array<float>& frameArray, const Array<float>& handKeypoints);
|
||||
|
||||
void renderHandKeypointsGpu(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
|
||||
@@ -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->renderHand(tDatum.outputData, tDatum.handKeypoints);
|
||||
// Profiling speed
|
||||
Profiler::timerEnd(profilerKey);
|
||||
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, Profiler::DEFAULT_X);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
// namespace op
|
||||
// {
|
||||
// template<typename TDatums>
|
||||
// template<typename TDatums>
|
||||
// class wPoseLoader : public Worker<TDatums>
|
||||
// {
|
||||
// public:
|
||||
|
||||
@@ -9,10 +9,12 @@ namespace op
|
||||
const auto FACE_MAX_FACES = POSE_MAX_PEOPLE;
|
||||
|
||||
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, \
|
||||
#define FACE_PAIRS_RENDER_GPU {0,1, 1,2, 2,3, 3,4, 4,5, 5,6, 6,7, 7,8, 8,9, 9,10, 10,11, 11,12, 12,13, 13,14, 14,15, 15,16, 17,18, 18,19, 19,20, \
|
||||
20,21, 22,23, 23,24, 24,25, 25,26, 27,28, 28,29, 29,30, 31,32, 32,33, 33,34, 34,35, 36,37, 37,38, 38,39, 39,40, 40,41, \
|
||||
41,36, 42,43, 43,44, 44,45, 45,46, 46,47, 47,42, 48,49, 49,50, 50,51, 51,52, 52,53, 53,54, 54,55, 55,56, 56,57, 57,58, \
|
||||
58,59, 59,48, 60,61, 61,62, 62,63, 63,64, 64,65, 65,66, 66,67, 67,60}
|
||||
const std::vector<unsigned int> FACE_PAIRS_RENDER {FACE_PAIRS_RENDER_GPU};
|
||||
#define FACE_COLORS_RENDER 255.f, 255.f, 255.f
|
||||
|
||||
// Constant parameters
|
||||
const auto FACE_CCN_DECREASE_FACTOR = 8.f;
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#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
|
||||
@@ -2,9 +2,11 @@
|
||||
#define OPENPOSE_FACE_FACE_RENDERER_HPP
|
||||
|
||||
#include <openpose/core/array.hpp>
|
||||
#include <openpose/core/enumClasses.hpp>
|
||||
#include <openpose/core/point.hpp>
|
||||
#include <openpose/core/renderer.hpp>
|
||||
#include <openpose/thread/worker.hpp>
|
||||
#include "faceParameters.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
@@ -12,7 +14,7 @@ namespace op
|
||||
{
|
||||
public:
|
||||
explicit FaceRenderer(const Point<int>& frameSize, const float alphaKeypoint = FACE_DEFAULT_ALPHA_KEYPOINT,
|
||||
const float alphaHeatMap = FACE_DEFAULT_ALPHA_HEAT_MAP);
|
||||
const float alphaHeatMap = FACE_DEFAULT_ALPHA_HEAT_MAP, const RenderMode renderMode = RenderMode::Cpu);
|
||||
|
||||
~FaceRenderer();
|
||||
|
||||
@@ -22,7 +24,12 @@ namespace op
|
||||
|
||||
private:
|
||||
const Point<int> mFrameSize;
|
||||
float* pGpuFace; // GPU aux memory
|
||||
const RenderMode mRenderMode;
|
||||
float* pGpuFace; // GPU aux memory
|
||||
|
||||
void renderFaceCpu(Array<float>& outputData, const Array<float>& faceKeypoints);
|
||||
|
||||
void renderFaceGpu(Array<float>& outputData, const Array<float>& faceKeypoints);
|
||||
|
||||
DELETE_COPY(FaceRenderer);
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "faceExtractor.hpp"
|
||||
#include "faceParameters.hpp"
|
||||
#include "faceRenderer.hpp"
|
||||
#include "faceRenderGpu.hpp"
|
||||
#include "renderFace.hpp"
|
||||
#include "wFaceDetector.hpp"
|
||||
#include "wFaceExtractor.hpp"
|
||||
#include "wFaceRenderer.hpp"
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef OPENPOSE_FACE_RENDER_FACE_HPP
|
||||
#define OPENPOSE_FACE_RENDER_FACE_HPP
|
||||
|
||||
#include <openpose/core/array.hpp>
|
||||
#include <openpose/core/point.hpp>
|
||||
#include "faceParameters.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
void renderFaceKeypointsCpu(Array<float>& frameArray, const Array<float>& faceKeypoints);
|
||||
|
||||
void renderFaceKeypointsGpu(float* framePtr, const Point<int>& frameSize, const float* const facePtr, const int numberFace,
|
||||
const float alphaColorToAdd = FACE_DEFAULT_ALPHA_KEYPOINT);
|
||||
}
|
||||
|
||||
#endif // OPENPOSE_FACE_RENDER_FACE_HPP
|
||||
@@ -8,8 +8,8 @@
|
||||
#include "poseExtractor.hpp"
|
||||
#include "poseExtractorCaffe.hpp"
|
||||
#include "poseRenderer.hpp"
|
||||
#include "poseRenderGpu.hpp"
|
||||
#include "poseParameters.hpp"
|
||||
#include "renderPose.hpp"
|
||||
#include "wPoseExtractor.hpp"
|
||||
#include "wPoseRenderer.hpp"
|
||||
|
||||
|
||||
@@ -31,10 +31,30 @@ namespace op
|
||||
{17, "LEar"},
|
||||
{18, "Background"}
|
||||
};
|
||||
const unsigned int POSE_COCO_NUMBER_PARTS = 18u; // Equivalent to size of std::map POSE_COCO_BODY_PARTS - 1 (removing background)
|
||||
const std::vector<unsigned int> POSE_COCO_MAP_IDX {31,32, 39,40, 33,34, 35,36, 41,42, 43,44, 19,20, 21,22, 23,24, 25,26, 27,28, 29,30, 47,48, 49,50, 53,54, 51,52, 55,56, 37,38, 45,46};
|
||||
#define POSE_COCO_PAIRS_TO_RENDER {1,2, 1,5, 2,3, 3,4, 5,6, 6,7, 1,8, 8,9, 9,10, 1,11, 11,12, 12,13, 1,0, 0,14, 14,16, 0,15, 15,17}
|
||||
const std::vector<unsigned int> POSE_COCO_PAIRS {1,2, 1,5, 2,3, 3,4, 5,6, 6,7, 1,8, 8,9, 9,10, 1,11, 11,12, 12,13, 1,0, 0,14, 14,16, 0,15, 15,17, 2,16, 5,17};
|
||||
const unsigned int POSE_COCO_NUMBER_PARTS = 18u; // Equivalent to size of std::map POSE_COCO_BODY_PARTS - 1 (removing background)
|
||||
const std::vector<unsigned int> POSE_COCO_MAP_IDX {31,32, 39,40, 33,34, 35,36, 41,42, 43,44, 19,20, 21,22, 23,24, 25,26, 27,28, 29,30, 47,48, 49,50, 53,54, 51,52, 55,56, 37,38, 45,46};
|
||||
#define POSE_COCO_PAIRS_RENDER_GPU {1,2, 1,5, 2,3, 3,4, 5,6, 6,7, 1,8, 8,9, 9,10, 1,11, 11,12, 12,13, 1,0, 0,14, 14,16, 0,15, 15,17}
|
||||
const std::vector<unsigned int> POSE_COCO_PAIRS_RENDER {POSE_COCO_PAIRS_RENDER_GPU};
|
||||
const std::vector<unsigned int> POSE_COCO_PAIRS {1,2, 1,5, 2,3, 3,4, 5,6, 6,7, 1,8, 8,9, 9,10, 1,11, 11,12, 12,13, 1,0, 0,14, 14,16, 0,15, 15,17, 2,16, 5,17};
|
||||
#define POSE_COCO_COLORS_RENDER \
|
||||
255.f, 0.f, 0.f, \
|
||||
255.f, 85.f, 0.f, \
|
||||
255.f, 170.f, 0.f, \
|
||||
255.f, 255.f, 0.f, \
|
||||
170.f, 255.f, 0.f, \
|
||||
85.f, 255.f, 0.f, \
|
||||
0.f, 255.f, 0.f, \
|
||||
0.f, 255.f, 85.f, \
|
||||
0.f, 255.f, 170.f, \
|
||||
0.f, 255.f, 255.f, \
|
||||
0.f, 170.f, 255.f, \
|
||||
0.f, 85.f, 255.f, \
|
||||
0.f, 0.f, 255.f, \
|
||||
85.f, 0.f, 255.f, \
|
||||
170.f, 0.f, 255.f, \
|
||||
255.f, 0.f, 255.f, \
|
||||
255.f, 0.f, 170.f, \
|
||||
255.f, 0.f, 85.f
|
||||
|
||||
const std::map<unsigned int, std::string> POSE_MPI_BODY_PARTS{
|
||||
{0, "Head"},
|
||||
@@ -56,8 +76,25 @@ namespace op
|
||||
};
|
||||
const unsigned int POSE_MPI_NUMBER_PARTS = 15; // Equivalent to size of std::map POSE_MPI_NUMBER_PARTS - 1 (removing background)
|
||||
const std::vector<unsigned int> POSE_MPI_MAP_IDX {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43};
|
||||
#define POSE_MPI_PAIRS_TO_RENDER { 0,1, 1,2, 2,3, 3,4, 1,5, 5,6, 6,7, 1,14, 14,8, 8,9, 9,10, 14,11, 11,12, 12,13}
|
||||
const std::vector<unsigned int> POSE_MPI_PAIRS POSE_MPI_PAIRS_TO_RENDER;
|
||||
#define POSE_MPI_PAIRS_RENDER_GPU { 0,1, 1,2, 2,3, 3,4, 1,5, 5,6, 6,7, 1,14, 14,8, 8,9, 9,10, 14,11, 11,12, 12,13}
|
||||
const std::vector<unsigned int> POSE_MPI_PAIRS POSE_MPI_PAIRS_RENDER_GPU;
|
||||
// MPI colors chosen such that they are closed to COCO colors
|
||||
#define POSE_MPI_COLORS_RENDER \
|
||||
255.f, 0.f, 85.f, \
|
||||
255.f, 0.f, 0.f, \
|
||||
255.f, 85.f, 0.f, \
|
||||
255.f, 170.f, 0.f, \
|
||||
255.f, 255.f, 0.f, \
|
||||
170.f, 255.f, 0.f, \
|
||||
85.f, 255.f, 0.f, \
|
||||
43.f, 255.f, 0.f, \
|
||||
0.f, 255.f, 0.f, \
|
||||
0.f, 255.f, 85.f, \
|
||||
0.f, 255.f, 170.f, \
|
||||
0.f, 255.f, 255.f, \
|
||||
0.f, 170.f, 255.f, \
|
||||
0.f, 85.f, 255.f, \
|
||||
0.f, 0.f, 255.f
|
||||
|
||||
// Constant Global Parameters
|
||||
const unsigned int POSE_MAX_PEOPLE = 96u;
|
||||
@@ -67,6 +104,7 @@ namespace op
|
||||
const std::array<unsigned int, (int)PoseModel::Size> POSE_MAX_PEAKS{ POSE_MAX_PEOPLE, POSE_MAX_PEOPLE, POSE_MAX_PEOPLE};
|
||||
const std::array<unsigned int, (int)PoseModel::Size> POSE_NUMBER_BODY_PARTS{ POSE_COCO_NUMBER_PARTS, POSE_MPI_NUMBER_PARTS, POSE_MPI_NUMBER_PARTS};
|
||||
const std::array<std::vector<unsigned int>, 3> POSE_BODY_PART_PAIRS{ POSE_COCO_PAIRS, POSE_MPI_PAIRS, POSE_MPI_PAIRS};
|
||||
const std::array<std::vector<unsigned int>, 3> POSE_BODY_PART_PAIRS_RENDER{POSE_COCO_PAIRS_RENDER, POSE_MPI_PAIRS, POSE_MPI_PAIRS};
|
||||
const std::array<std::vector<unsigned int>, 3> POSE_MAP_IDX{ POSE_COCO_MAP_IDX, POSE_MPI_MAP_IDX, POSE_MPI_MAP_IDX};
|
||||
const std::array<std::string, (int)PoseModel::Size> POSE_PROTOTXT{ "pose/coco/pose_deploy_linevec.prototxt",
|
||||
"pose/mpi/pose_deploy_linevec.prototxt",
|
||||
@@ -74,17 +112,17 @@ namespace op
|
||||
const std::array<std::string, (int)PoseModel::Size> POSE_TRAINED_MODEL{ "pose/coco/pose_iter_440000.caffemodel",
|
||||
"pose/mpi/pose_iter_160000.caffemodel",
|
||||
"pose/mpi/pose_iter_160000.caffemodel"};
|
||||
// POSE_BODY_PART_MAPPING crashes on Windows at dynamic initialization, to avoid this crash:
|
||||
// POSE_BODY_PART_MAPPING has been moved to poseParameters.cpp and getPoseBodyPartMapping() wraps it
|
||||
//const std::array<std::map<unsigned int, std::string>, 3> POSE_BODY_PART_MAPPING{ POSE_COCO_BODY_PARTS, POSE_MPI_BODY_PARTS, POSE_MPI_BODY_PARTS};
|
||||
const std::map<unsigned int, std::string>& getPoseBodyPartMapping(const PoseModel poseModel);
|
||||
// POSE_BODY_PART_MAPPING crashes on Windows at dynamic initialization, to avoid this crash:
|
||||
// POSE_BODY_PART_MAPPING has been moved to poseParameters.cpp and getPoseBodyPartMapping() wraps it
|
||||
//const std::array<std::map<unsigned int, std::string>, 3> POSE_BODY_PART_MAPPING{ POSE_COCO_BODY_PARTS, POSE_MPI_BODY_PARTS, POSE_MPI_BODY_PARTS};
|
||||
const std::map<unsigned int, std::string>& getPoseBodyPartMapping(const PoseModel poseModel);
|
||||
|
||||
// Default Model Parameters
|
||||
// They might be modified on running time
|
||||
const std::array<float, (int)PoseModel::Size> POSE_DEFAULT_NMS_THRESHOLD{ 0.05f, 0.6f, 0.3f};
|
||||
const std::array<unsigned int, (int)PoseModel::Size> POSE_DEFAULT_CONNECT_INTER_MIN_ABOVE_THRESHOLD{ 9, 8, 8};
|
||||
const std::array<unsigned int, (int)PoseModel::Size> POSE_DEFAULT_CONNECT_INTER_MIN_ABOVE_THRESHOLD{ 9, 8, 8};
|
||||
const std::array<float, (int)PoseModel::Size> POSE_DEFAULT_CONNECT_INTER_THRESHOLD{ 0.05f, 0.01f, 0.01f};
|
||||
const std::array<unsigned int, (int)PoseModel::Size> POSE_DEFAULT_CONNECT_MIN_SUBSET_CNT{ 3, 3, 3};
|
||||
const std::array<unsigned int, (int)PoseModel::Size> POSE_DEFAULT_CONNECT_MIN_SUBSET_CNT{ 3, 3, 3};
|
||||
const std::array<float, (int)PoseModel::Size> POSE_DEFAULT_CONNECT_MIN_SUBSET_SCORE{ 0.4f, 0.4f, 0.4f};
|
||||
|
||||
// Rendering default parameters
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
#ifndef OPENPOSE_POSE_GPU_POSE_RENDER_HPP
|
||||
#define OPENPOSE_POSE_GPU_POSE_RENDER_HPP
|
||||
|
||||
#include <openpose/core/point.hpp>
|
||||
#include "enumClasses.hpp"
|
||||
#include "poseParameters.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
void renderPoseGpu(float* framePtr, const PoseModel poseModel, const int numberPeople, const Point<int>& frameSize, const float* const posePtr,
|
||||
const bool googlyEyes = false, const bool blendOriginalFrame = true, const float alphaBlending = POSE_DEFAULT_ALPHA_KEYPOINT);
|
||||
void renderBodyPartGpu(float* frame, const PoseModel poseModel, const Point<int>& frameSize, const float* const heatmap, const Point<int>& heatmapSize,
|
||||
const float scaleToKeepRatio, const int part, const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP);
|
||||
void renderBodyPartsGpu(float* frame, const PoseModel poseModel, const Point<int>& frameSize, const float* const heatmap, const Point<int>& heatmapSize,
|
||||
const float scaleToKeepRatio, const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP);
|
||||
void renderPartAffinityFieldGpu(float* framePtr, const PoseModel poseModel, const Point<int>& frameSize, const float* const heatmapPtr,
|
||||
const Point<int>& heatmapSize, const float scaleToKeepRatio, const int part, const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP);
|
||||
void renderPartAffinityFieldsGpu(float* framePtr, const PoseModel poseModel, const Point<int>& frameSize, const float* const heatmapPtr,
|
||||
const Point<int>& heatmapSize, const float scaleToKeepRatio, const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP);
|
||||
}
|
||||
|
||||
#endif // OPENPOSE_POSE_GPU_POSE_RENDER_HPP
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <memory> // std::shared_ptr
|
||||
#include <openpose/core/array.hpp>
|
||||
#include <openpose/core/enumClasses.hpp>
|
||||
#include <openpose/core/point.hpp>
|
||||
#include <openpose/core/renderer.hpp>
|
||||
#include <openpose/utilities/macros.hpp>
|
||||
@@ -14,9 +15,10 @@ namespace op
|
||||
class PoseRenderer : public Renderer
|
||||
{
|
||||
public:
|
||||
explicit PoseRenderer(const Point<int>& heatMapsSize, const Point<int>& outputSize, const PoseModel poseModel, const std::shared_ptr<PoseExtractor>& poseExtractor,
|
||||
const bool blendOriginalFrame = true, const float alphaKeypoint = POSE_DEFAULT_ALPHA_KEYPOINT,
|
||||
const float alphaHeatMap = POSE_DEFAULT_ALPHA_HEAT_MAP, const unsigned int elementToRender = 0u);
|
||||
explicit PoseRenderer(const Point<int>& heatMapsSize, const Point<int>& outputSize, const PoseModel poseModel,
|
||||
const std::shared_ptr<PoseExtractor>& poseExtractor, const bool blendOriginalFrame = true,
|
||||
const float alphaKeypoint = POSE_DEFAULT_ALPHA_KEYPOINT, const float alphaHeatMap = POSE_DEFAULT_ALPHA_HEAT_MAP,
|
||||
const unsigned int elementToRender = 0u, const RenderMode renderMode = RenderMode::Cpu);
|
||||
|
||||
~PoseRenderer();
|
||||
|
||||
@@ -38,10 +40,15 @@ namespace op
|
||||
const PoseModel mPoseModel;
|
||||
const std::map<unsigned int, std::string> mPartIndexToName;
|
||||
const std::shared_ptr<PoseExtractor> spPoseExtractor;
|
||||
const RenderMode mRenderMode;
|
||||
std::atomic<bool> mBlendOriginalFrame;
|
||||
std::atomic<bool> mShowGooglyEyes;
|
||||
// Init with thread
|
||||
float* pGpuPose; // GPU aux memory
|
||||
float* pGpuPose; // GPU aux memory
|
||||
|
||||
std::pair<int, std::string> renderPoseCpu(Array<float>& outputData, const Array<float>& poseKeypoints, const float scaleNetToOutput = -1.f);
|
||||
|
||||
std::pair<int, std::string> renderPoseGpu(Array<float>& outputData, const Array<float>& poseKeypoints, const float scaleNetToOutput = -1.f);
|
||||
|
||||
DELETE_COPY(PoseRenderer);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef OPENPOSE_POSE_RENDER_POSE_HPP
|
||||
#define OPENPOSE_POSE_RENDER_POSE_HPP
|
||||
|
||||
#include <opencv2/core/core.hpp> // cv::Mat
|
||||
#include <openpose/core/array.hpp>
|
||||
#include <openpose/core/point.hpp>
|
||||
#include "enumClasses.hpp"
|
||||
#include "poseParameters.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
void renderPoseKeypointsCpu(Array<float>& frameArray, const Array<float>& poseKeypoints, const PoseModel poseModel,
|
||||
const bool blendOriginalFrame = true);
|
||||
|
||||
void renderPoseKeypointsGpu(float* framePtr, const PoseModel poseModel, const int numberPeople, const Point<int>& frameSize,
|
||||
const float* const posePtr, const bool googlyEyes = false, const bool blendOriginalFrame = true,
|
||||
const float alphaBlending = POSE_DEFAULT_ALPHA_KEYPOINT);
|
||||
|
||||
void renderPoseHeatMapGpu(float* frame, const PoseModel poseModel, const Point<int>& frameSize, const float* const heatmap,
|
||||
const Point<int>& heatmapSize, const float scaleToKeepRatio, const int part,
|
||||
const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP);
|
||||
|
||||
void renderPoseHeatMapsGpu(float* frame, const PoseModel poseModel, const Point<int>& frameSize, const float* const heatmap,
|
||||
const Point<int>& heatmapSize, const float scaleToKeepRatio,
|
||||
const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP);
|
||||
|
||||
void renderPosePAFGpu(float* framePtr, const PoseModel poseModel, const Point<int>& frameSize, const float* const heatmapPtr,
|
||||
const Point<int>& heatmapSize, const float scaleToKeepRatio, const int part,
|
||||
const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP);
|
||||
|
||||
void renderPosePAFsGpu(float* framePtr, const PoseModel poseModel, const Point<int>& frameSize, const float* const heatmapPtr,
|
||||
const Point<int>& heatmapSize, const float scaleToKeepRatio,
|
||||
const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP);
|
||||
}
|
||||
|
||||
#endif // OPENPOSE_POSE_RENDER_POSE_HPP
|
||||
@@ -13,7 +13,7 @@ namespace op
|
||||
|
||||
inline void work(TDatums& tDatums)
|
||||
{
|
||||
workConsumer(tDatums);
|
||||
workConsumer(tDatums);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace op
|
||||
return (totalRequired + numberCudaThreads - 1) / numberCudaThreads;
|
||||
}
|
||||
|
||||
dim3 getNumberCudaBlocks(const Point<int>& frameSize, const dim3 numberCudaThreads = dim3{ CUDA_NUM_THREADS, CUDA_NUM_THREADS, 1 });
|
||||
dim3 getNumberCudaBlocks(const Point<int>& frameSize, const dim3 numberCudaThreads = dim3{ CUDA_NUM_THREADS, CUDA_NUM_THREADS, 1 });
|
||||
|
||||
std::pair<dim3, dim3> getNumberCudaThreadsAndBlocks(const Point<int>& frameSize);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "errorAndLog.hpp"
|
||||
#include "fastMath.hpp"
|
||||
#include "fileSystem.hpp"
|
||||
#include "keypoint.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "openCv.hpp"
|
||||
#include "pointerContainer.hpp"
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef OPENPOSE_UTILITIES_KEYPOINT_HPP
|
||||
#define OPENPOSE_UTILITIES_KEYPOINT_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <openpose/core/array.hpp>
|
||||
#include <openpose/core/rectangle.hpp>
|
||||
|
||||
namespace op
|
||||
{
|
||||
float getDistance(const float* keypointPtr, const int elementA, const int elementB);
|
||||
|
||||
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, const float offsetX, const float offsetY);
|
||||
|
||||
void renderKeypointsCpu(Array<float>& frameArray, const Array<float>& keypoints, const std::vector<unsigned int>& pairs,
|
||||
const std::vector<float> colors, const float thicknessCircleRatio, const float thicknessLineRatioWRTCircle);
|
||||
|
||||
Rectangle<unsigned int> getKeypointsRectangle(const float* keypointPtr, const int numberBodyParts, const float threshold);
|
||||
|
||||
int getKeypointsArea(const float* keypointPtr, const int numberBodyParts, const float threshold);
|
||||
|
||||
int getBiggestPerson(const Array<float>& keypoints, const float threshold);
|
||||
}
|
||||
|
||||
#endif // OPENPOSE_UTILITIES_KEYPOINT_HPP
|
||||
@@ -80,17 +80,15 @@ namespace op
|
||||
// Consumer (keep default values to disable any output)
|
||||
const WrapperStructOutput& wrapperStructOutput = WrapperStructOutput{});
|
||||
|
||||
// THIS FUNCTION IS NOT IMPLEMENTED YET -> COMING SOON
|
||||
// Similar to the previos configure, but it includes hand extraction and rendering
|
||||
void configure(const WrapperStructPose& wrapperStructPose,
|
||||
// Hand (use the default WrapperStructHand{} to disable any hand detector)
|
||||
const experimental::WrapperStructHand& wrapperHandStruct,
|
||||
const experimental::WrapperStructHand& wrapperStructHand,
|
||||
// Producer (set producerSharedPtr = nullptr or use the default WrapperStructInput{} to disable any input)
|
||||
const WrapperStructInput& wrapperStructInput,
|
||||
// Consumer (keep default values to disable any output)
|
||||
const WrapperStructOutput& wrapperStructOutput = WrapperStructOutput{});
|
||||
|
||||
// THIS FUNCTION IS NOT IMPLEMENTED YET -> COMING SOON
|
||||
// Similar to the previos configure, but it includes hand extraction and rendering
|
||||
void configure(const WrapperStructPose& wrapperStructPose,
|
||||
// Face (use the default WrapperStructFace{} to disable any face detector)
|
||||
@@ -100,13 +98,12 @@ namespace op
|
||||
// Consumer (keep default values to disable any output)
|
||||
const WrapperStructOutput& wrapperStructOutput = WrapperStructOutput{});
|
||||
|
||||
// THIS FUNCTION IS NOT IMPLEMENTED YET -> COMING SOON
|
||||
// Similar to the previos configure, but it includes hand extraction and rendering
|
||||
void configure(const WrapperStructPose& wrapperStructPose = WrapperStructPose{},
|
||||
// Face (use the default WrapperStructFace{} to disable any face detector)
|
||||
const WrapperStructFace& wrapperStructFace = WrapperStructFace{},
|
||||
// Hand (use the default WrapperStructHand{} to disable any hand detector)
|
||||
const experimental::WrapperStructHand& wrapperHandStruct = experimental::WrapperStructHand{},
|
||||
const experimental::WrapperStructHand& wrapperStructHand = experimental::WrapperStructHand{},
|
||||
// Producer (set producerSharedPtr = nullptr or use the default WrapperStructInput{} to disable any input)
|
||||
const WrapperStructInput& wrapperStructInput = WrapperStructInput{},
|
||||
// Consumer (keep default values to disable any output)
|
||||
@@ -372,12 +369,14 @@ namespace op
|
||||
}
|
||||
|
||||
template<typename TDatums, typename TWorker, typename TQueue>
|
||||
void Wrapper<TDatums, TWorker, TQueue>::configure(const WrapperStructPose& wrapperStructPose, const WrapperStructInput& wrapperStructInput,
|
||||
void Wrapper<TDatums, TWorker, TQueue>::configure(const WrapperStructPose& wrapperStructPose,
|
||||
const WrapperStructInput& wrapperStructInput,
|
||||
const WrapperStructOutput& wrapperStructOutput)
|
||||
{
|
||||
try
|
||||
{
|
||||
configure(wrapperStructPose, WrapperStructFace{}, experimental::WrapperStructHand{}, wrapperStructInput, wrapperStructOutput);
|
||||
configure(wrapperStructPose, WrapperStructFace{}, experimental::WrapperStructHand{},
|
||||
wrapperStructInput, wrapperStructOutput);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -386,12 +385,15 @@ namespace op
|
||||
}
|
||||
|
||||
template<typename TDatums, typename TWorker, typename TQueue>
|
||||
void Wrapper<TDatums, TWorker, TQueue>::configure(const WrapperStructPose& wrapperStructPose, const WrapperStructFace& wrapperStructFace,
|
||||
const WrapperStructInput& wrapperStructInput, const WrapperStructOutput& wrapperStructOutput)
|
||||
void Wrapper<TDatums, TWorker, TQueue>::configure(const WrapperStructPose& wrapperStructPose,
|
||||
const WrapperStructFace& wrapperStructFace,
|
||||
const WrapperStructInput& wrapperStructInput,
|
||||
const WrapperStructOutput& wrapperStructOutput)
|
||||
{
|
||||
try
|
||||
{
|
||||
configure(wrapperStructPose, wrapperStructFace, experimental::WrapperStructHand{}, wrapperStructInput, wrapperStructOutput);
|
||||
configure(wrapperStructPose, wrapperStructFace, experimental::WrapperStructHand{},
|
||||
wrapperStructInput, wrapperStructOutput);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -400,12 +402,15 @@ namespace op
|
||||
}
|
||||
|
||||
template<typename TDatums, typename TWorker, typename TQueue>
|
||||
void Wrapper<TDatums, TWorker, TQueue>::configure(const WrapperStructPose& wrapperStructPose, const experimental::WrapperStructHand& wrapperHandStruct,
|
||||
const WrapperStructInput& wrapperStructInput, const WrapperStructOutput& wrapperStructOutput)
|
||||
void Wrapper<TDatums, TWorker, TQueue>::configure(const WrapperStructPose& wrapperStructPose,
|
||||
const experimental::WrapperStructHand& wrapperStructHand,
|
||||
const WrapperStructInput& wrapperStructInput,
|
||||
const WrapperStructOutput& wrapperStructOutput)
|
||||
{
|
||||
try
|
||||
{
|
||||
configure(wrapperStructPose, WrapperStructFace{}, wrapperHandStruct, wrapperStructInput, wrapperStructOutput);
|
||||
configure(wrapperStructPose, WrapperStructFace{}, wrapperStructHand,
|
||||
wrapperStructInput, wrapperStructOutput);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -414,8 +419,10 @@ namespace op
|
||||
}
|
||||
|
||||
template<typename TDatums, typename TWorker, typename TQueue>
|
||||
void Wrapper<TDatums, TWorker, TQueue>::configure(const WrapperStructPose& wrapperStructPose, const WrapperStructFace& wrapperStructFace,
|
||||
const experimental::WrapperStructHand& wrapperHandStruct, const WrapperStructInput& wrapperStructInput,
|
||||
void Wrapper<TDatums, TWorker, TQueue>::configure(const WrapperStructPose& wrapperStructPose,
|
||||
const WrapperStructFace& wrapperStructFace,
|
||||
const experimental::WrapperStructHand& wrapperStructHand,
|
||||
const WrapperStructInput& wrapperStructInput,
|
||||
const WrapperStructOutput& wrapperStructOutput)
|
||||
{
|
||||
try
|
||||
@@ -426,8 +433,9 @@ namespace op
|
||||
typedef std::shared_ptr<TDatums> TDatumsPtr;
|
||||
|
||||
// Required parameters
|
||||
const auto renderOutput = wrapperStructPose.renderOutput || wrapperStructFace.renderOutput;
|
||||
const auto renderFace = wrapperStructFace.enable && wrapperStructFace.renderOutput;
|
||||
const auto renderOutput = wrapperStructPose.renderMode != RenderMode::None || wrapperStructFace.renderMode != RenderMode::None;
|
||||
const auto renderOutputGpu = wrapperStructPose.renderMode == RenderMode::Gpu || wrapperStructFace.renderMode == RenderMode::Gpu;
|
||||
const auto renderFace = wrapperStructFace.enable && wrapperStructFace.renderMode != RenderMode::None;
|
||||
|
||||
// Check no wrong/contradictory flags enabled
|
||||
if (wrapperStructPose.alphaKeypoint < 0. || wrapperStructPose.alphaKeypoint > 1.
|
||||
@@ -563,22 +571,38 @@ namespace op
|
||||
|
||||
// Pose renderers
|
||||
std::vector<std::shared_ptr<PoseRenderer>> poseRenderers;
|
||||
if (wrapperStructPose.renderOutput || renderOutput)
|
||||
std::shared_ptr<PoseRenderer> poseCpuRenderer;
|
||||
std::vector<TWorker> cpuRenderers;
|
||||
if (renderOutputGpu || wrapperStructPose.renderMode == RenderMode::Cpu)
|
||||
{
|
||||
// If !wrapperStructPose.renderOutput but renderOutput, then we create an alpha = 0 pose renderer
|
||||
// If !wrapperStructPose.renderMode == RenderMode::Gpu but renderOutput, then we create an alpha = 0 pose renderer
|
||||
// in order to keep the removing background option
|
||||
const auto alphaKeypoint = (wrapperStructPose.renderOutput ? wrapperStructPose.alphaKeypoint : 0.f);
|
||||
const auto alphaHeatMap = (wrapperStructPose.renderOutput ? wrapperStructPose.alphaHeatMap : 0.f);
|
||||
for (auto gpuId = 0; gpuId < poseExtractors.size(); gpuId++)
|
||||
const auto alphaKeypoint = (wrapperStructPose.renderMode != RenderMode::None ? wrapperStructPose.alphaKeypoint : 0.f);
|
||||
const auto alphaHeatMap = (wrapperStructPose.renderMode != RenderMode::None ? wrapperStructPose.alphaHeatMap : 0.f);
|
||||
// GPU rendering
|
||||
if (renderOutputGpu)
|
||||
{
|
||||
poseRenderers.emplace_back(std::make_shared<PoseRenderer>(
|
||||
poseNetOutputSize, finalOutputSize, wrapperStructPose.poseModel, poseExtractors[gpuId],
|
||||
wrapperStructPose.blendOriginalFrame, alphaKeypoint,
|
||||
alphaHeatMap, wrapperStructPose.defaultPartToRender
|
||||
));
|
||||
for (auto gpuId = 0; gpuId < poseExtractors.size(); gpuId++)
|
||||
{
|
||||
poseRenderers.emplace_back(std::make_shared<PoseRenderer>(
|
||||
poseNetOutputSize, finalOutputSize, wrapperStructPose.poseModel, poseExtractors[gpuId],
|
||||
wrapperStructPose.blendOriginalFrame, alphaKeypoint,
|
||||
alphaHeatMap, wrapperStructPose.defaultPartToRender, wrapperStructPose.renderMode
|
||||
));
|
||||
}
|
||||
}
|
||||
// CPU rendering
|
||||
if (wrapperStructPose.renderMode == RenderMode::Cpu)
|
||||
{
|
||||
poseCpuRenderer = std::make_shared<PoseRenderer>(
|
||||
poseNetOutputSize, finalOutputSize, wrapperStructPose.poseModel, nullptr,
|
||||
wrapperStructPose.blendOriginalFrame, alphaKeypoint,
|
||||
alphaHeatMap, wrapperStructPose.defaultPartToRender, wrapperStructPose.renderMode
|
||||
);
|
||||
cpuRenderers.emplace_back(std::make_shared<WPoseRenderer<TDatumsPtr>>(poseCpuRenderer));
|
||||
}
|
||||
log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// Input cvMat to OpenPose format
|
||||
const auto cvMatToOpInput = std::make_shared<CvMatToOpInput>(
|
||||
@@ -589,7 +613,6 @@ namespace op
|
||||
spWCvMatToOpOutput = std::make_shared<WCvMatToOpOutput<TDatumsPtr>>(cvMatToOpOutput);
|
||||
|
||||
// Pose extractor(s)
|
||||
spWPoses.clear();
|
||||
spWPoses.resize(poseExtractors.size());
|
||||
for (auto i = 0; i < spWPoses.size(); i++)
|
||||
spWPoses.at(i) = {std::make_shared<WPoseExtractor<TDatumsPtr>>(poseExtractors.at(i))};
|
||||
@@ -612,7 +635,7 @@ namespace op
|
||||
}
|
||||
|
||||
// Hand extractor(s)
|
||||
if (wrapperHandStruct.extractAndRenderHands)
|
||||
if (wrapperStructHand.extractAndRenderHands)
|
||||
{
|
||||
for (auto gpuId = 0; gpuId < spWPoses.size(); gpuId++)
|
||||
{
|
||||
@@ -624,44 +647,76 @@ namespace op
|
||||
}
|
||||
|
||||
// Pose renderer(s)
|
||||
if (!poseRenderers.empty())
|
||||
if (renderOutputGpu && !poseRenderers.empty())
|
||||
for (auto i = 0; i < spWPoses.size(); i++)
|
||||
spWPoses.at(i).emplace_back(std::make_shared<WPoseRenderer<TDatumsPtr>>(poseRenderers.at(i)));
|
||||
|
||||
// Hands renderer(s)
|
||||
if (wrapperHandStruct.extractAndRenderHands)
|
||||
{
|
||||
for (auto i = 0; i < spWPoses.size(); i++)
|
||||
{
|
||||
// Construct hands renderer
|
||||
const auto handRenderer = std::make_shared<experimental::HandRenderer>(finalOutputSize);
|
||||
// Performance boost -> share spGpuMemoryPtr for all renderers
|
||||
if (!poseRenderers.empty())
|
||||
{
|
||||
const bool isLastRenderer = (!renderFace);
|
||||
handRenderer->setSharedParametersAndIfLast(poseRenderers.at(i)->getSharedParameters(), isLastRenderer);
|
||||
}
|
||||
// Add worker
|
||||
spWPoses.at(i).emplace_back(std::make_shared<experimental::WHandRenderer<TDatumsPtr>>(handRenderer));
|
||||
}
|
||||
}
|
||||
|
||||
// Face renderer(s)
|
||||
if (renderFace)
|
||||
{
|
||||
for (auto i = 0; i < spWPoses.size(); i++)
|
||||
// CPU rendering
|
||||
if (wrapperStructFace.renderMode == RenderMode::Cpu)
|
||||
{
|
||||
// Construct face renderer
|
||||
const auto faceRenderer = std::make_shared<FaceRenderer>(finalOutputSize, wrapperStructFace.alphaKeypoint, wrapperStructFace.alphaHeatMap);
|
||||
// Performance boost -> share spGpuMemoryPtr for all renderers
|
||||
if (!poseRenderers.empty())
|
||||
{
|
||||
const bool isLastRenderer = true;
|
||||
faceRenderer->setSharedParametersAndIfLast(poseRenderers.at(i)->getSharedParameters(), isLastRenderer);
|
||||
}
|
||||
const auto faceRenderer = std::make_shared<FaceRenderer>(finalOutputSize, wrapperStructFace.alphaKeypoint,
|
||||
wrapperStructFace.alphaHeatMap,
|
||||
wrapperStructFace.renderMode);
|
||||
// Add worker
|
||||
spWPoses.at(i).emplace_back(std::make_shared<WFaceRenderer<TDatumsPtr>>(faceRenderer));
|
||||
cpuRenderers.emplace_back(std::make_shared<WFaceRenderer<TDatumsPtr>>(faceRenderer));
|
||||
}
|
||||
// GPU rendering
|
||||
else if (wrapperStructFace.renderMode == RenderMode::Gpu)
|
||||
{
|
||||
for (auto i = 0; i < spWPoses.size(); i++)
|
||||
{
|
||||
// Construct face renderer
|
||||
const auto faceRenderer = std::make_shared<FaceRenderer>(finalOutputSize, wrapperStructFace.alphaKeypoint,
|
||||
wrapperStructFace.alphaHeatMap,
|
||||
wrapperStructFace.renderMode);
|
||||
// Performance boost -> share spGpuMemoryPtr for all renderers
|
||||
if (!poseRenderers.empty())
|
||||
{
|
||||
const bool isLastRenderer = (!wrapperStructHand.extractAndRenderHands);
|
||||
faceRenderer->setSharedParametersAndIfLast(poseRenderers.at(i)->getSharedParameters(), isLastRenderer);
|
||||
}
|
||||
// Add worker
|
||||
spWPoses.at(i).emplace_back(std::make_shared<WFaceRenderer<TDatumsPtr>>(faceRenderer));
|
||||
}
|
||||
}
|
||||
else
|
||||
error("Unknown RenderMode.", __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
|
||||
// Hands renderer(s)
|
||||
if (wrapperStructHand.extractAndRenderHands)
|
||||
{
|
||||
// CPU rendering
|
||||
// if (wrapperStructHand.renderMode == RenderMode::Cpu)
|
||||
{
|
||||
// Construct hand renderer
|
||||
const auto handRenderer = std::make_shared<experimental::HandRenderer>(finalOutputSize);
|
||||
// Add worker
|
||||
cpuRenderers.emplace_back(std::make_shared<experimental::WHandRenderer<TDatumsPtr>>(handRenderer));
|
||||
}
|
||||
// GPU rendering
|
||||
// else if (wrapperStructHand.renderMode == RenderMode::Gpu)
|
||||
// {
|
||||
// for (auto i = 0; i < spWPoses.size(); i++)
|
||||
// {
|
||||
// // Construct hands renderer
|
||||
// const auto handRenderer = std::make_shared<experimental::HandRenderer>(finalOutputSize);
|
||||
// // Performance boost -> share spGpuMemoryPtr for all renderers
|
||||
// if (!poseRenderers.empty())
|
||||
// {
|
||||
// const bool isLastRenderer = true;
|
||||
// handRenderer->setSharedParametersAndIfLast(poseRenderers.at(i)->getSharedParameters(), isLastRenderer);
|
||||
// }
|
||||
// // Add worker
|
||||
// spWPoses.at(i).emplace_back(std::make_shared<experimental::WHandRenderer<TDatumsPtr>>(handRenderer));
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// error("Unknown RenderMode.", __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
|
||||
// Itermediate workers (e.g. OpenPose format to cv::Mat, json & frames recorder, ...)
|
||||
@@ -672,6 +727,7 @@ namespace op
|
||||
// Frames processor (OpenPose format -> cv::Mat format)
|
||||
if (renderOutput)
|
||||
{
|
||||
mPostProcessingWs = mergeWorkers(mPostProcessingWs, cpuRenderers);
|
||||
const auto opOutputToCvMat = std::make_shared<OpOutputToCvMat>(finalOutputSize);
|
||||
mPostProcessingWs.emplace_back(std::make_shared<WOpOutputToCvMat<TDatumsPtr>>(opOutputToCvMat));
|
||||
}
|
||||
@@ -692,7 +748,7 @@ namespace op
|
||||
mOutputWs.emplace_back(std::make_shared<WPoseSaver<TDatumsPtr>>(keypointSaver));
|
||||
if (wrapperStructFace.enable)
|
||||
mOutputWs.emplace_back(std::make_shared<WFaceSaver<TDatumsPtr>>(keypointSaver));
|
||||
if (wrapperHandStruct.extractAndRenderHands)
|
||||
if (wrapperStructHand.extractAndRenderHands)
|
||||
mOutputWs.emplace_back(std::make_shared<WHandSaver<TDatumsPtr>>(keypointSaver));
|
||||
}
|
||||
// Write people pose data on disk (json format)
|
||||
@@ -702,7 +758,7 @@ namespace op
|
||||
mOutputWs.emplace_back(std::make_shared<WPoseJsonSaver<TDatumsPtr>>(keypointJsonSaver));
|
||||
if (wrapperStructFace.enable)
|
||||
mOutputWs.emplace_back(std::make_shared<WFaceJsonSaver<TDatumsPtr>>(keypointJsonSaver));
|
||||
if (wrapperHandStruct.extractAndRenderHands)
|
||||
if (wrapperStructHand.extractAndRenderHands)
|
||||
mOutputWs.emplace_back(std::make_shared<WHandJsonSaver<TDatumsPtr>>(keypointJsonSaver));
|
||||
}
|
||||
// Write people pose data on disk (COCO validation json format)
|
||||
@@ -750,7 +806,8 @@ namespace op
|
||||
if (wrapperStructOutput.displayGui)
|
||||
{
|
||||
const auto gui = std::make_shared<Gui>(
|
||||
wrapperStructOutput.fullScreen, finalOutputSize, mThreadManager.getIsRunningSharedPtr(), spVideoSeek, poseExtractors, poseRenderers
|
||||
wrapperStructOutput.fullScreen, finalOutputSize, mThreadManager.getIsRunningSharedPtr(), spVideoSeek, poseExtractors,
|
||||
(wrapperStructPose.renderMode == RenderMode::Cpu ? std::vector<std::shared_ptr<PoseRenderer>>{poseCpuRenderer} : poseRenderers)
|
||||
);
|
||||
spWGui = {std::make_shared<WGui<TDatumsPtr>>(gui)};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef OPENPOSE_WRAPPER_WRAPPER_STRUCT_FACE_HPP
|
||||
#define OPENPOSE_WRAPPER_WRAPPER_STRUCT_FACE_HPP
|
||||
|
||||
#include <openpose/core/enumClasses.hpp>
|
||||
#include <openpose/core/point.hpp>
|
||||
#include <openpose/face/faceParameters.hpp>
|
||||
|
||||
@@ -27,9 +28,10 @@ namespace op
|
||||
Point<int> netInputSize;
|
||||
|
||||
/**
|
||||
* Whether to render the output (pose locations, face, background or PAF heat maps).
|
||||
* Whether to render the output (pose locations, body, background or PAF heat maps) with CPU or GPU.
|
||||
* Select `None` for no rendering, `Cpu` or `Gpu` por CPU and GPU rendering respectively.
|
||||
*/
|
||||
bool renderOutput;
|
||||
RenderMode renderMode;
|
||||
|
||||
/**
|
||||
* Rendering blending alpha value of the pose point locations with respect to the background image.
|
||||
@@ -49,7 +51,8 @@ namespace op
|
||||
* Since all the elements of the struct are public, they can also be manually filled.
|
||||
*/
|
||||
WrapperStructFace(const bool enable = false, const Point<int>& netInputSize = Point<int>{368, 368},
|
||||
const bool renderOutput = false, const float alphaKeypoint = FACE_DEFAULT_ALPHA_KEYPOINT,
|
||||
const RenderMode renderMode = RenderMode::None,
|
||||
const float alphaKeypoint = FACE_DEFAULT_ALPHA_KEYPOINT,
|
||||
const float alphaHeatMap = FACE_DEFAULT_ALPHA_HEAT_MAP);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -63,9 +63,10 @@ namespace op
|
||||
float scaleGap;
|
||||
|
||||
/**
|
||||
* Whether to render the output (pose locations, body, background or PAF heat maps).
|
||||
* Whether to render the output (pose locations, body, background or PAF heat maps) with CPU or GPU.
|
||||
* Select `None` for no rendering, `Cpu` or `Gpu` por CPU and GPU rendering respectively.
|
||||
*/
|
||||
bool renderOutput;
|
||||
RenderMode renderMode;
|
||||
|
||||
/**
|
||||
* Pose model, it affects the number of body parts to render
|
||||
@@ -124,7 +125,7 @@ namespace op
|
||||
*/
|
||||
WrapperStructPose(const Point<int>& netInputSize = Point<int>{656, 368}, const Point<int>& outputSize = Point<int>{1280, 720},
|
||||
const ScaleMode keypointScale = ScaleMode::InputResolution, const int gpuNumber = 1, const int gpuNumberStart = 0,
|
||||
const int scalesNumber = 1, const float scaleGap = 0.15f, const bool renderOutput = false,
|
||||
const int scalesNumber = 1, const float scaleGap = 0.15f, const RenderMode renderMode = RenderMode::None,
|
||||
const PoseModel poseModel = PoseModel::COCO_18, const bool blendOriginalFrame = true,
|
||||
const float alphaKeypoint = POSE_DEFAULT_ALPHA_KEYPOINT, const float alphaHeatMap = POSE_DEFAULT_ALPHA_HEAT_MAP,
|
||||
const int defaultPartToRender = 0, const std::string& modelFolder = "models/",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
input: "image"
|
||||
input_dim: 1
|
||||
input_dim: 3
|
||||
input_dim: 1 # This value will be defined at runtime
|
||||
input_dim: 1 # This value will be defined at runtime
|
||||
input_dim: 1 # This value will be defined at runtime
|
||||
input_dim: 1 # This value will be defined at runtime
|
||||
layer {
|
||||
name: "conv1_1"
|
||||
type: "Convolution"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
input: "image"
|
||||
input_dim: 1
|
||||
input_dim: 3
|
||||
input_dim: 1 # This value will be defined at runtime
|
||||
input_dim: 1 # This value will be defined at runtime
|
||||
input_dim: 1 # This value will be defined at runtime
|
||||
input_dim: 1 # This value will be defined at runtime
|
||||
layer {
|
||||
name: "conv1_1"
|
||||
type: "Convolution"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
input: "image"
|
||||
input_dim: 1
|
||||
input_dim: 3
|
||||
input_dim: 1 # This value will be defined at runtime
|
||||
input_dim: 1 # This value will be defined at runtime
|
||||
input_dim: 1 # This value will be defined at runtime
|
||||
input_dim: 1 # This value will be defined at runtime
|
||||
layer {
|
||||
name: "conv1_1"
|
||||
type: "Convolution"
|
||||
|
||||
@@ -322,13 +322,25 @@ namespace op
|
||||
{
|
||||
try
|
||||
{
|
||||
if (mCvMatData.first)
|
||||
return mCvMatData.second;
|
||||
else
|
||||
{
|
||||
if (!mCvMatData.first)
|
||||
error("Array<T>: cv::Mat functions only valid for T types defined by OpenCV: unsigned char, signed char, int, float & double", __LINE__, __FUNCTION__, __FILE__);
|
||||
return mCvMatData.second;
|
||||
}
|
||||
return mCvMatData.second;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return mCvMatData.second;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
cv::Mat& Array<T>::getCvMat()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!mCvMatData.first)
|
||||
error("Array<T>: cv::Mat functions only valid for T types defined by OpenCV: unsigned char, signed char, int, float & double", __LINE__, __FUNCTION__, __FILE__);
|
||||
return mCvMatData.second;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <openpose/core/scaleKeypoints.hpp>
|
||||
#include <openpose/utilities/errorAndLog.hpp>
|
||||
#include <openpose/utilities/keypoint.hpp>
|
||||
#include <openpose/core/keypointScaler.hpp>
|
||||
|
||||
namespace op
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
#include <cuda.h>
|
||||
#include <cuda_runtime_api.h>
|
||||
#ifndef CPU_ONLY
|
||||
#include <cuda.h>
|
||||
#include <cuda_runtime_api.h>
|
||||
#endif
|
||||
#include <openpose/utilities/errorAndLog.hpp>
|
||||
#include <openpose/core/renderer.hpp>
|
||||
|
||||
namespace op
|
||||
{
|
||||
Renderer::Renderer(const unsigned long long volume, const float alphaKeypoint, const float alphaHeatMap, const unsigned int elementToRender,
|
||||
const unsigned int numberElementsToRender) :
|
||||
Renderer::Renderer(const unsigned long long volume, const float alphaKeypoint, const float alphaHeatMap,
|
||||
const unsigned int elementToRender, const unsigned int numberElementsToRender) :
|
||||
spGpuMemoryPtr{std::make_shared<float*>()},
|
||||
spElementToRender{std::make_shared<std::atomic<unsigned int>>(elementToRender)},
|
||||
spNumberElementsToRender{std::make_shared<const unsigned int>(numberElementsToRender)},
|
||||
@@ -23,8 +25,10 @@ namespace op
|
||||
{
|
||||
try
|
||||
{
|
||||
if (mIsLastRenderer)
|
||||
cudaFree(*spGpuMemoryPtr);
|
||||
#ifndef CPU_ONLY
|
||||
if (mIsLastRenderer)
|
||||
cudaFree(*spGpuMemoryPtr);
|
||||
#endif
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -36,8 +40,10 @@ namespace op
|
||||
{
|
||||
try
|
||||
{
|
||||
if (mIsFirstRenderer)
|
||||
cudaMalloc((void**)(spGpuMemoryPtr.get()), mVolume * sizeof(float));
|
||||
#ifndef CPU_ONLY
|
||||
if (mIsFirstRenderer)
|
||||
cudaMalloc((void**)(spGpuMemoryPtr.get()), mVolume * sizeof(float));
|
||||
#endif
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -74,7 +80,8 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
std::tuple<std::shared_ptr<float*>, std::shared_ptr<bool>, std::shared_ptr<std::atomic<unsigned int>>, std::shared_ptr<const unsigned int>> Renderer::getSharedParameters()
|
||||
std::tuple<std::shared_ptr<float*>, std::shared_ptr<bool>, std::shared_ptr<std::atomic<unsigned int>>,
|
||||
std::shared_ptr<const unsigned int>> Renderer::getSharedParameters()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -88,7 +95,8 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::setSharedParametersAndIfLast(const std::tuple<std::shared_ptr<float*>, std::shared_ptr<bool>, std::shared_ptr<std::atomic<unsigned int>>,
|
||||
void Renderer::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)
|
||||
{
|
||||
try
|
||||
@@ -160,11 +168,16 @@ namespace op
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!*spGpuMemoryAllocated)
|
||||
{
|
||||
cudaMemcpy(*spGpuMemoryPtr, cpuMemory, mVolume * sizeof(float), cudaMemcpyHostToDevice);
|
||||
*spGpuMemoryAllocated = true;
|
||||
}
|
||||
#ifndef CPU_ONLY
|
||||
if (!*spGpuMemoryAllocated)
|
||||
{
|
||||
cudaMemcpy(*spGpuMemoryPtr, cpuMemory, mVolume * sizeof(float), cudaMemcpyHostToDevice);
|
||||
*spGpuMemoryAllocated = true;
|
||||
}
|
||||
#else
|
||||
error("GPU rendering not available if `CPU_ONLY` is set.", __LINE__, __FUNCTION__, __FILE__);
|
||||
UNUSED(cpuMemory);
|
||||
#endif
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -176,11 +189,16 @@ namespace op
|
||||
{
|
||||
try
|
||||
{
|
||||
if (*spGpuMemoryAllocated && mIsLastRenderer)
|
||||
{
|
||||
cudaMemcpy(cpuMemory, *spGpuMemoryPtr, mVolume * sizeof(float), cudaMemcpyDeviceToHost);
|
||||
*spGpuMemoryAllocated = false;
|
||||
}
|
||||
#ifndef CPU_ONLY
|
||||
if (*spGpuMemoryAllocated && mIsLastRenderer)
|
||||
{
|
||||
cudaMemcpy(cpuMemory, *spGpuMemoryPtr, mVolume * sizeof(float), cudaMemcpyDeviceToHost);
|
||||
*spGpuMemoryAllocated = false;
|
||||
}
|
||||
#else
|
||||
error("GPU rendering not available if `CPU_ONLY` is set.", __LINE__, __FUNCTION__, __FILE__);
|
||||
UNUSED(cpuMemory);
|
||||
#endif
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
#include <openpose/utilities/errorAndLog.hpp>
|
||||
#include <openpose/core/scaleKeypoints.hpp>
|
||||
|
||||
namespace op
|
||||
{
|
||||
const std::string errorMessage = "This function is only for array of dimension: [sizeA x sizeB x 3].";
|
||||
|
||||
void scaleKeypoints(Array<float>& keypoints, const float scale)
|
||||
{
|
||||
try
|
||||
{
|
||||
scaleKeypoints(keypoints, scale, scale);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void scaleKeypoints(Array<float>& keypoints, const float scaleX, const float scaleY)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (scaleX != 1. && scaleY != 1.)
|
||||
{
|
||||
// Error check
|
||||
if (!keypoints.empty() && keypoints.getSize(2) != 3)
|
||||
error(errorMessage, __LINE__, __FUNCTION__, __FILE__);
|
||||
// Get #people and #parts
|
||||
const auto numberPeople = keypoints.getSize(0);
|
||||
const auto numberParts = keypoints.getSize(1);
|
||||
// For each person
|
||||
for (auto person = 0 ; person < numberPeople ; person++)
|
||||
{
|
||||
// For each body part
|
||||
for (auto part = 0 ; part < numberParts ; part++)
|
||||
{
|
||||
const auto finalIndex = 3*(person*numberParts + part);
|
||||
keypoints[finalIndex] *= scaleX;
|
||||
keypoints[finalIndex+1] *= scaleY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void scaleKeypoints(Array<float>& keypoints, const float scaleX, const float scaleY, const float offsetX, const float offsetY)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (scaleX != 1. && scaleY != 1.)
|
||||
{
|
||||
// Error check
|
||||
if (!keypoints.empty() && keypoints.getSize(2) != 3)
|
||||
error(errorMessage, __LINE__, __FUNCTION__, __FILE__);
|
||||
// Get #people and #parts
|
||||
const auto numberPeople = keypoints.getSize(0);
|
||||
const auto numberParts = keypoints.getSize(1);
|
||||
// For each person
|
||||
for (auto person = 0 ; person < numberPeople ; person++)
|
||||
{
|
||||
// For each body part
|
||||
for (auto part = 0 ; part < numberParts ; part++)
|
||||
{
|
||||
const auto finalIndex = 3*(person*numberParts + part);
|
||||
keypoints[finalIndex] = keypoints[finalIndex] * scaleX + offsetX;
|
||||
keypoints[finalIndex+1] = keypoints[finalIndex+1] * scaleY + offsetY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
#include <cuda.h>
|
||||
#include <cuda_runtime_api.h>
|
||||
#include <openpose/experimental/hand/handParameters.hpp>
|
||||
#include <openpose/experimental/hand/handRenderGpu.hpp>
|
||||
#ifndef CPU_ONLY
|
||||
#include <cuda.h>
|
||||
#include <cuda_runtime_api.h>
|
||||
#endif
|
||||
#include <openpose/experimental/hand/renderHand.hpp>
|
||||
#include <openpose/utilities/cuda.hpp>
|
||||
#include <openpose/utilities/errorAndLog.hpp>
|
||||
#include <openpose/experimental/hand/handRenderer.hpp>
|
||||
@@ -10,9 +11,10 @@ namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
HandRenderer::HandRenderer(const Point<int>& frameSize) :
|
||||
Renderer{(unsigned long long)(frameSize.area() * 3), HAND_DEFAULT_ALPHA_KEYPOINT, HAND_DEFAULT_ALPHA_HEAT_MAP},
|
||||
mFrameSize{frameSize}
|
||||
HandRenderer::HandRenderer(const Point<int>& frameSize, const float alphaKeypoint, const float alphaHeatMap, const RenderMode renderMode) :
|
||||
Renderer{(unsigned long long)(frameSize.area() * 3), alphaKeypoint, alphaHeatMap},
|
||||
mFrameSize{frameSize},
|
||||
mRenderMode{renderMode}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -21,7 +23,9 @@ namespace op
|
||||
try
|
||||
{
|
||||
// Free CUDA pointers - Note that if pointers are 0 (i.e. nullptr), no operation is performed.
|
||||
cudaFree(pGpuHands);
|
||||
#ifndef CPU_ONLY
|
||||
cudaFree(pGpuHands);
|
||||
#endif
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -33,8 +37,13 @@ namespace op
|
||||
{
|
||||
try
|
||||
{
|
||||
log("Starting initialization on thread.", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
Renderer::initializationOnThread();
|
||||
cudaMalloc((void**)(&pGpuHands), 2*HAND_NUMBER_PARTS * 3 * sizeof(float));
|
||||
// GPU memory allocation for rendering
|
||||
#ifndef CPU_ONLY
|
||||
cudaMalloc((void**)(&pGpuHands), 2*HAND_NUMBER_PARTS * 3 * sizeof(float));
|
||||
#endif
|
||||
log("Finished initialization on thread.", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -42,25 +51,67 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
void HandRenderer::renderHands(Array<float>& outputData, const Array<float>& handKeypoints)
|
||||
void HandRenderer::renderHand(Array<float>& outputData, const Array<float>& handKeypoints)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto elementRendered = spElementToRender->load(); // I prefer std::round(T&) over intRound(T) for std::atomic
|
||||
const auto numberPeople = handKeypoints.getSize(0);
|
||||
// Security checks
|
||||
if (outputData.empty())
|
||||
error("Empty Array<float> outputData.", __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// CPU rendering
|
||||
if (mRenderMode == RenderMode::Cpu)
|
||||
renderHandCpu(outputData, handKeypoints);
|
||||
|
||||
// GPU rendering
|
||||
if (numberPeople > 0 && elementRendered == 0)
|
||||
{
|
||||
cpuToGpuMemoryIfNotCopiedYet(outputData.getPtr());
|
||||
// Draw faceKeypoints
|
||||
cudaMemcpy(pGpuHands, handKeypoints.getConstPtr(), 2*HAND_NUMBER_PARTS*3 * sizeof(float), cudaMemcpyHostToDevice);
|
||||
renderHandsGpu(*spGpuMemoryPtr, mFrameSize, pGpuHands, handKeypoints.getSize(0));
|
||||
// CUDA check
|
||||
else
|
||||
renderHandGpu(outputData, handKeypoints);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void HandRenderer::renderHandCpu(Array<float>& outputData, const Array<float>& handKeypoints)
|
||||
{
|
||||
try
|
||||
{
|
||||
renderHandKeypointsCpu(outputData, handKeypoints);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void HandRenderer::renderHandGpu(Array<float>& outputData, const Array<float>& handKeypoints)
|
||||
{
|
||||
try
|
||||
{
|
||||
// GPU rendering
|
||||
#ifndef CPU_ONLY
|
||||
const auto elementRendered = spElementToRender->load(); // I prefer std::round(T&) over intRound(T) for std::atomic
|
||||
const auto numberPeople = handKeypoints.getSize(0);
|
||||
// GPU rendering
|
||||
if (numberPeople > 0 && elementRendered == 0)
|
||||
{
|
||||
cpuToGpuMemoryIfNotCopiedYet(outputData.getPtr());
|
||||
// Draw handKeypoints
|
||||
cudaMemcpy(pGpuHands, handKeypoints.getConstPtr(), 2*HAND_NUMBER_PARTS*3 * sizeof(float), cudaMemcpyHostToDevice);
|
||||
renderHandKeypointsGpu(*spGpuMemoryPtr, mFrameSize, pGpuHands, handKeypoints.getSize(0));
|
||||
// CUDA check
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
// GPU memory to CPU if last renderer
|
||||
gpuToCpuMemoryIfLastRenderer(outputData.getPtr());
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
// GPU memory to CPU if last renderer
|
||||
gpuToCpuMemoryIfLastRenderer(outputData.getPtr());
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
// CPU_ONLY mode
|
||||
#else
|
||||
error("GPU rendering not available if `CPU_ONLY` is set.", __LINE__, __FUNCTION__, __FILE__);
|
||||
UNUSED(outputData);
|
||||
UNUSED(handKeypoints);
|
||||
#endif
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#include <openpose/experimental/hand/handParameters.hpp>
|
||||
#include <openpose/utilities/errorAndLog.hpp>
|
||||
#include <openpose/utilities/fastMath.hpp>
|
||||
#include <openpose/utilities/keypoint.hpp>
|
||||
#include <openpose/experimental/hand/renderHand.hpp>
|
||||
|
||||
namespace op
|
||||
{
|
||||
const std::vector<float> COLORS{HAND_COLORS_RENDER};
|
||||
|
||||
void renderHandKeypointsCpu(Array<float>& frameArray, const Array<float>& handKeypoints)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!frameArray.empty())
|
||||
{
|
||||
// Parameters
|
||||
const auto thicknessCircleRatio = 1.f/200.f;
|
||||
const auto thicknessLineRatioWRTCircle = 0.75f;
|
||||
const auto& pairs = HAND_PAIRS_RENDER;
|
||||
|
||||
// Render keypoints
|
||||
renderKeypointsCpu(frameArray, handKeypoints, pairs, COLORS, thicknessCircleRatio, thicknessLineRatioWRTCircle);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-32
@@ -3,37 +3,12 @@
|
||||
#include <openpose/utilities/cuda.hpp>
|
||||
#include <openpose/utilities/cuda.hu>
|
||||
#include <openpose/utilities/render.hu>
|
||||
#include <openpose/experimental/hand/handRenderGpu.hpp>
|
||||
#include <openpose/experimental/hand/renderHand.hpp>
|
||||
|
||||
namespace op
|
||||
{
|
||||
__constant__ const unsigned int PART_PAIRS_GPU[] = HAND_PAIRS_TO_RENDER;
|
||||
__constant__ const float RGB_COLORS[] = {
|
||||
179.f, 0.f, 0.f,
|
||||
204.f, 0.f, 0.f,
|
||||
230.f, 0.f, 0.f,
|
||||
255.f, 0.f, 0.f,
|
||||
143.f, 179.f, 0.f,
|
||||
163.f, 204.f, 0.f,
|
||||
184.f, 230.f, 0.f,
|
||||
204.f, 255.f, 0.f,
|
||||
0.f, 179.f, 71.f,
|
||||
0.f, 204.f, 82.f,
|
||||
0.f, 230.f, 92.f,
|
||||
0.f, 255.f, 102.f,
|
||||
0.f, 71.f, 179.f,
|
||||
0.f, 82.f, 204.f,
|
||||
0.f, 92.f, 230.f,
|
||||
0.f, 102.f, 255.f,
|
||||
143.f, 0.f, 179.f,
|
||||
163.f, 0.f, 204.f,
|
||||
184.f, 0.f, 230.f,
|
||||
204.f, 0.f, 255.f,
|
||||
179.f, 179.f, 179.f,
|
||||
179.f, 179.f, 179.f,
|
||||
179.f, 179.f, 179.f,
|
||||
179.f, 179.f, 179.f
|
||||
};
|
||||
__constant__ const unsigned int PART_PAIRS_GPU[] = HAND_PAIRS_RENDER_GPU;
|
||||
__constant__ const float COLORS[] = {HAND_COLORS_RENDER};
|
||||
|
||||
|
||||
|
||||
@@ -51,18 +26,19 @@ namespace op
|
||||
|
||||
// Other parameters
|
||||
const auto numberPartPairs = sizeof(PART_PAIRS_GPU) / (2*sizeof(PART_PAIRS_GPU[0]));
|
||||
const auto numberColors = sizeof(RGB_COLORS) / (3*sizeof(RGB_COLORS[0]));
|
||||
const auto numberColors = sizeof(COLORS) / (3*sizeof(COLORS[0]));
|
||||
const auto radius = fastMin(targetWidth, targetHeight) / 100.f;
|
||||
const auto stickwidth = fastMin(targetWidth, targetHeight) / 80.f;
|
||||
|
||||
// Render key points
|
||||
renderKeypoints(targetPtr, sharedMaxs, sharedMins, sharedScaleF,
|
||||
globalIdx, x, y, targetWidth, targetHeight, handsPtr, PART_PAIRS_GPU, numberHands,
|
||||
HAND_NUMBER_PARTS, numberPartPairs, RGB_COLORS, numberColors,
|
||||
HAND_NUMBER_PARTS, numberPartPairs, COLORS, numberColors,
|
||||
radius, stickwidth, threshold, alphaColorToAdd);
|
||||
}
|
||||
|
||||
void renderHandsGpu(float* framePtr, const Point<int>& frameSize, const float* const handsPtr, const int numberHands, const float alphaColorToAdd)
|
||||
void renderHandKeypointsGpu(float* framePtr, const Point<int>& frameSize, const float* const handsPtr, const int numberHands,
|
||||
const float alphaColorToAdd)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -72,7 +48,8 @@ namespace op
|
||||
dim3 threadsPerBlock;
|
||||
dim3 numBlocks;
|
||||
std::tie(threadsPerBlock, numBlocks) = getNumberCudaThreadsAndBlocks(frameSize);
|
||||
renderHandsParts<<<threadsPerBlock, numBlocks>>>(framePtr, frameSize.x, frameSize.y, handsPtr, numberHands, threshold, alphaColorToAdd);
|
||||
renderHandsParts<<<threadsPerBlock, numBlocks>>>(framePtr, frameSize.x, frameSize.y, handsPtr, numberHands, threshold,
|
||||
alphaColorToAdd);
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <openpose/pose/poseParameters.hpp>
|
||||
#include <openpose/utilities/check.hpp>
|
||||
#include <openpose/utilities/errorAndLog.hpp>
|
||||
#include <openpose/utilities/keypoint.hpp>
|
||||
#include <openpose/face/faceDetector.hpp>
|
||||
|
||||
namespace op
|
||||
@@ -16,21 +17,6 @@ namespace op
|
||||
{
|
||||
}
|
||||
|
||||
float getDistance(const float* posePtr, const int elementA, const int elementB)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto pixelX = posePtr[elementA*3] - posePtr[elementB*3];
|
||||
const auto pixelY = posePtr[elementA*3+1] - posePtr[elementB*3+1];
|
||||
return std::sqrt(pixelX*pixelX+pixelY*pixelY);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return -1.f;
|
||||
}
|
||||
}
|
||||
|
||||
inline Rectangle<float> getFaceFromPoseKeypoints(const Array<float>& poseKeypoints, const unsigned int personIndex, const unsigned int neck,
|
||||
const unsigned int nose, const unsigned int lEar, const unsigned int rEar,
|
||||
const unsigned int lEye, const unsigned int rEye, const float threshold)
|
||||
|
||||
@@ -10,9 +10,11 @@
|
||||
|
||||
namespace op
|
||||
{
|
||||
FaceExtractor::FaceExtractor(const Point<int>& netInputSize, const Point<int>& netOutputSize, const std::string& modelFolder, const int gpuId) :
|
||||
FaceExtractor::FaceExtractor(const Point<int>& netInputSize, const Point<int>& netOutputSize, const std::string& modelFolder,
|
||||
const int gpuId) :
|
||||
mNetOutputSize{netOutputSize},
|
||||
spNet{std::make_shared<NetCaffe>(std::array<int,4>{1, 3, mNetOutputSize.y, mNetOutputSize.x}, modelFolder + FACE_PROTOTXT, modelFolder + FACE_TRAINED_MODEL, gpuId)},
|
||||
spNet{std::make_shared<NetCaffe>(std::array<int,4>{1, 3, mNetOutputSize.y, mNetOutputSize.x}, modelFolder + FACE_PROTOTXT,
|
||||
modelFolder + FACE_TRAINED_MODEL, gpuId)},
|
||||
spResizeAndMergeCaffe{std::make_shared<ResizeAndMergeCaffe<float>>()},
|
||||
spNmsCaffe{std::make_shared<NmsCaffe<float>>()},
|
||||
mFaceImageCrop{mNetOutputSize.area()*3}
|
||||
@@ -21,6 +23,7 @@ namespace op
|
||||
{
|
||||
checkE(netOutputSize.x, netInputSize.x, "Net input and output size must be equal.", __LINE__, __FUNCTION__, __FILE__);
|
||||
checkE(netOutputSize.y, netInputSize.y, "Net input and output size must be equal.", __LINE__, __FUNCTION__, __FILE__);
|
||||
checkE(netInputSize.x, netInputSize.y, "Net input size must be squared.", __LINE__, __FUNCTION__, __FILE__);
|
||||
// Properties
|
||||
for (auto& property : mProperties)
|
||||
property = 0.;
|
||||
@@ -77,24 +80,25 @@ namespace op
|
||||
|
||||
// Set face size
|
||||
const auto numberPeople = (int)faceRectangles.size();
|
||||
mFaceKeypoints.reset({numberPeople, FACE_NUMBER_PARTS, 3}, 0);
|
||||
// // Commented lines are for debugging
|
||||
// log("\nAreas:");
|
||||
// cv::Mat cvInputDataCopy = cvInputData.clone();
|
||||
mFaceKeypoints.reset({numberPeople, (int)FACE_NUMBER_PARTS, 3}, 0);
|
||||
|
||||
// // Debugging
|
||||
// cv::Mat cvInputDataCopy = cvInputData.clone();
|
||||
// Extract face keypoints for each person
|
||||
for (auto person = 0 ; person < numberPeople ; person++)
|
||||
{
|
||||
// Only consider faces with a minimum pixel area
|
||||
const auto faceAreaSquared = std::sqrt(faceRectangles.at(person).area());
|
||||
// // Debugging
|
||||
// log(std::to_string(cvInputData.cols) + " " + std::to_string(cvInputData.rows));
|
||||
// cv::rectangle(cvInputDataCopy,
|
||||
// cv::Point{(int)faceRectangle.x, (int)faceRectangle.y},
|
||||
// cv::Point{(int)faceRectangle.bottomRight().x, (int)faceRectangle.bottomRight().y},
|
||||
// cv::Scalar{0,0,255}, 2);
|
||||
// Get parts
|
||||
if (faceAreaSquared > 50)
|
||||
{
|
||||
const auto& faceRectangle = faceRectangles.at(person);
|
||||
// log(faceAreaSquared);
|
||||
// log(std::to_string(cvInputData.cols) + " " + std::to_string(cvInputData.rows));
|
||||
// cv::rectangle(cvInputDataCopy,
|
||||
// cv::Point{(int)faceRectangle.x, (int)faceRectangle.y},
|
||||
// cv::Point{(int)faceRectangle.bottomRight().x, (int)faceRectangle.bottomRight().y},
|
||||
// cv::Scalar{255,0,255}, 2);
|
||||
// Get face position(s)
|
||||
const Point<float> faceCenterPosition{faceRectangle.topLeft()};
|
||||
const auto faceSize = fastMax(faceRectangle.width, faceRectangle.height);
|
||||
@@ -112,8 +116,11 @@ namespace op
|
||||
|
||||
// cv::Mat -> float*
|
||||
uCharCvMatToFloatPtr(mFaceImageCrop.getPtr(), faceImage, true);
|
||||
// if (person < 5)
|
||||
// cv::imshow("faceImage" + std::to_string(person), faceImage);
|
||||
|
||||
// // Debugging
|
||||
// if (person < 5)
|
||||
// cv::imshow("faceImage" + std::to_string(person), faceImage);
|
||||
|
||||
// 1. Caffe deep network
|
||||
auto* inputDataGpuPtr = spNet->getInputDataGpuPtr();
|
||||
cudaMemcpy(inputDataGpuPtr, mFaceImageCrop.getPtr(), mNetOutputSize.area() * 3 * sizeof(float), cudaMemcpyHostToDevice);
|
||||
@@ -162,7 +169,7 @@ namespace op
|
||||
const auto x = facePeaksPtr[xyIndex];
|
||||
const auto y = facePeaksPtr[xyIndex + 1];
|
||||
const auto score = facePeaksPtr[xyIndex + 2];
|
||||
const auto baseIndex = (person * FACE_NUMBER_PARTS + part) * 3;
|
||||
const auto baseIndex = mFaceKeypoints.getSize(2) * (person * mFaceKeypoints.getSize(1) + part);
|
||||
mFaceKeypoints[baseIndex] = scaleInputToOutput * (Mscaling.at<double>(0,0) * x + Mscaling.at<double>(0,1) * y + Mscaling.at<double>(0,2));
|
||||
mFaceKeypoints[baseIndex+1] = scaleInputToOutput * (Mscaling.at<double>(1,0) * x + Mscaling.at<double>(1,1) * y + Mscaling.at<double>(1,2));
|
||||
mFaceKeypoints[baseIndex+2] = score;
|
||||
@@ -170,7 +177,8 @@ namespace op
|
||||
}
|
||||
}
|
||||
}
|
||||
// cv::imshow("AcvInputDataCopy", cvInputDataCopy);
|
||||
// // Debugging
|
||||
// cv::imshow("AcvInputDataCopy", cvInputDataCopy);
|
||||
}
|
||||
else
|
||||
mFaceKeypoints.reset();
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
#include <cuda.h>
|
||||
#include <cuda_runtime_api.h>
|
||||
#include <openpose/face/faceParameters.hpp>
|
||||
#include <openpose/face/faceRenderGpu.hpp>
|
||||
#ifndef CPU_ONLY
|
||||
#include <cuda.h>
|
||||
#include <cuda_runtime_api.h>
|
||||
#endif
|
||||
#include <openpose/face/renderFace.hpp>
|
||||
#include <openpose/utilities/cuda.hpp>
|
||||
#include <openpose/utilities/errorAndLog.hpp>
|
||||
#include <openpose/face/faceRenderer.hpp>
|
||||
|
||||
namespace op
|
||||
{
|
||||
FaceRenderer::FaceRenderer(const Point<int>& frameSize, const float alphaKeypoint, const float alphaHeatMap) :
|
||||
FaceRenderer::FaceRenderer(const Point<int>& frameSize, const float alphaKeypoint, const float alphaHeatMap, const RenderMode renderMode) :
|
||||
Renderer{(unsigned long long)(frameSize.area() * 3), alphaKeypoint, alphaHeatMap},
|
||||
mFrameSize{frameSize}
|
||||
mFrameSize{frameSize},
|
||||
mRenderMode{renderMode}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -19,7 +21,9 @@ namespace op
|
||||
try
|
||||
{
|
||||
// Free CUDA pointers - Note that if pointers are 0 (i.e. nullptr), no operation is performed.
|
||||
cudaFree(pGpuFace);
|
||||
#ifndef CPU_ONLY
|
||||
cudaFree(pGpuFace);
|
||||
#endif
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -31,8 +35,13 @@ namespace op
|
||||
{
|
||||
try
|
||||
{
|
||||
log("Starting initialization on thread.", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
Renderer::initializationOnThread();
|
||||
cudaMalloc((void**)(&pGpuFace), POSE_MAX_PEOPLE * FACE_NUMBER_PARTS * 3 * sizeof(float));
|
||||
// GPU memory allocation for rendering
|
||||
#ifndef CPU_ONLY
|
||||
cudaMalloc((void**)(&pGpuFace), POSE_MAX_PEOPLE * FACE_NUMBER_PARTS * 3 * sizeof(float));
|
||||
#endif
|
||||
log("Finished initialization on thread.", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -44,21 +53,63 @@ namespace op
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto elementRendered = spElementToRender->load(); // I prefer std::round(T&) over intRound(T) for std::atomic
|
||||
const auto numberPeople = faceKeypoints.getSize(0);
|
||||
// Security checks
|
||||
if (outputData.empty())
|
||||
error("Empty Array<float> outputData.", __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// CPU rendering
|
||||
if (mRenderMode == RenderMode::Cpu)
|
||||
renderFaceCpu(outputData, faceKeypoints);
|
||||
|
||||
// GPU rendering
|
||||
if (numberPeople > 0 && elementRendered == 0)
|
||||
{
|
||||
cpuToGpuMemoryIfNotCopiedYet(outputData.getPtr());
|
||||
// Draw faceKeypoints
|
||||
cudaMemcpy(pGpuFace, faceKeypoints.getConstPtr(), faceKeypoints.getSize(0) * FACE_NUMBER_PARTS * 3 * sizeof(float), cudaMemcpyHostToDevice);
|
||||
renderFaceGpu(*spGpuMemoryPtr, mFrameSize, pGpuFace, faceKeypoints.getSize(0), getAlphaKeypoint());
|
||||
// CUDA check
|
||||
else
|
||||
renderFaceGpu(outputData, faceKeypoints);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void FaceRenderer::renderFaceCpu(Array<float>& outputData, const Array<float>& faceKeypoints)
|
||||
{
|
||||
try
|
||||
{
|
||||
renderFaceKeypointsCpu(outputData, faceKeypoints);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void FaceRenderer::renderFaceGpu(Array<float>& outputData, const Array<float>& faceKeypoints)
|
||||
{
|
||||
try
|
||||
{
|
||||
// GPU rendering
|
||||
#ifndef CPU_ONLY
|
||||
const auto elementRendered = spElementToRender->load(); // I prefer std::round(T&) over intRound(T) for std::atomic
|
||||
const auto numberPeople = faceKeypoints.getSize(0);
|
||||
if (numberPeople > 0 && elementRendered == 0)
|
||||
{
|
||||
cpuToGpuMemoryIfNotCopiedYet(outputData.getPtr());
|
||||
// Draw faceKeypoints
|
||||
cudaMemcpy(pGpuFace, faceKeypoints.getConstPtr(), faceKeypoints.getSize(0) * FACE_NUMBER_PARTS * 3 * sizeof(float),
|
||||
cudaMemcpyHostToDevice);
|
||||
renderFaceKeypointsGpu(*spGpuMemoryPtr, mFrameSize, pGpuFace, faceKeypoints.getSize(0), getAlphaKeypoint());
|
||||
// CUDA check
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
// GPU memory to CPU if last renderer
|
||||
gpuToCpuMemoryIfLastRenderer(outputData.getPtr());
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
// GPU memory to CPU if last renderer
|
||||
gpuToCpuMemoryIfLastRenderer(outputData.getPtr());
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
// CPU_ONLY mode
|
||||
#else
|
||||
error("GPU rendering not available if `CPU_ONLY` is set.", __LINE__, __FUNCTION__, __FILE__);
|
||||
UNUSED(outputData);
|
||||
UNUSED(faceKeypoints);
|
||||
#endif
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#include <openpose/face/faceParameters.hpp>
|
||||
#include <openpose/utilities/errorAndLog.hpp>
|
||||
#include <openpose/utilities/fastMath.hpp>
|
||||
#include <openpose/utilities/keypoint.hpp>
|
||||
#include <openpose/face/renderFace.hpp>
|
||||
|
||||
namespace op
|
||||
{
|
||||
const std::vector<float> COLORS{FACE_COLORS_RENDER};
|
||||
|
||||
void renderFaceKeypointsCpu(Array<float>& frameArray, const Array<float>& faceKeypoints)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!frameArray.empty())
|
||||
{
|
||||
// Parameters
|
||||
const auto thicknessCircleRatio = 1.f/75.f;
|
||||
const auto thicknessLineRatioWRTCircle = 0.334f;
|
||||
const auto& pairs = FACE_PAIRS_RENDER;
|
||||
|
||||
// Render keypoints
|
||||
renderKeypointsCpu(frameArray, faceKeypoints, pairs, COLORS, thicknessCircleRatio, thicknessLineRatioWRTCircle);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,15 +3,13 @@
|
||||
#include <openpose/utilities/cuda.hpp>
|
||||
#include <openpose/utilities/cuda.hu>
|
||||
#include <openpose/utilities/render.hu>
|
||||
#include <openpose/face/faceRenderGpu.hpp>
|
||||
#include <openpose/face/renderFace.hpp>
|
||||
|
||||
namespace op
|
||||
{
|
||||
const dim3 THREADS_PER_BLOCK{128, 128, 1};
|
||||
__constant__ const unsigned int PART_PAIRS_GPU[] = FACE_PAIRS_TO_RENDER;
|
||||
__constant__ const float RGB_COLORS[] = {
|
||||
255.f, 255.f, 255.f,
|
||||
};
|
||||
__constant__ const unsigned int PART_PAIRS_GPU[] = FACE_PAIRS_RENDER_GPU;
|
||||
__constant__ const float COLORS[] = {FACE_COLORS_RENDER};
|
||||
|
||||
|
||||
|
||||
@@ -29,18 +27,19 @@ namespace op
|
||||
|
||||
// Other parameters
|
||||
const auto numberPartPairs = sizeof(PART_PAIRS_GPU) / (2*sizeof(PART_PAIRS_GPU[0]));
|
||||
const auto numberColors = sizeof(RGB_COLORS) / (3*sizeof(RGB_COLORS[0]));
|
||||
const auto numberColors = sizeof(COLORS) / (3*sizeof(COLORS[0]));
|
||||
const auto radius = fastMin(targetWidth, targetHeight) / 120.f;
|
||||
const auto stickwidth = fastMin(targetWidth, targetHeight) / 250.f;
|
||||
|
||||
// Render key points
|
||||
renderKeypoints(targetPtr, sharedMaxs, sharedMins, sharedScaleF,
|
||||
globalIdx, x, y, targetWidth, targetHeight, facePtr, PART_PAIRS_GPU, numberFaces,
|
||||
FACE_NUMBER_PARTS, numberPartPairs, RGB_COLORS, numberColors,
|
||||
FACE_NUMBER_PARTS, numberPartPairs, COLORS, numberColors,
|
||||
radius, stickwidth, threshold, alphaColorToAdd);
|
||||
}
|
||||
|
||||
void renderFaceGpu(float* framePtr, const Point<int>& frameSize, const float* const facePtr, const int numberFaces, const float alphaColorToAdd)
|
||||
void renderFaceKeypointsGpu(float* framePtr, const Point<int>& frameSize, const float* const facePtr, const int numberFaces,
|
||||
const float alphaColorToAdd)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -48,7 +47,8 @@ namespace op
|
||||
{
|
||||
const auto threshold = 0.4f;
|
||||
const auto numBlocks = getNumberCudaBlocks(frameSize, THREADS_PER_BLOCK);
|
||||
renderFaceParts<<<THREADS_PER_BLOCK, numBlocks>>>(framePtr, frameSize.x, frameSize.y, facePtr, numberFaces, threshold, alphaColorToAdd);
|
||||
renderFaceParts<<<THREADS_PER_BLOCK, numBlocks>>>(framePtr, frameSize.x, frameSize.y, facePtr, numberFaces, threshold,
|
||||
alphaColorToAdd);
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
@@ -7,78 +7,6 @@
|
||||
|
||||
namespace op
|
||||
{
|
||||
// In case I wanna order the pose keypoints by area
|
||||
// inline int getPersonArea(const float* posePtr, const int numberBodyParts, const float threshold)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// if (numberBodyParts < 1)
|
||||
// error("Number body parts must be > 0", __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// unsigned int minX = -1;
|
||||
// unsigned int maxX = 0u;
|
||||
// unsigned int minY = -1;
|
||||
// unsigned int maxY = 0u;
|
||||
// for (auto part = 0 ; part < numberBodyParts ; part++)
|
||||
// {
|
||||
// const auto score = posePtr[3*part + 2];
|
||||
// if (score > threshold)
|
||||
// {
|
||||
// const auto x = posePtr[3*part];
|
||||
// const auto y = posePtr[3*part + 1];
|
||||
// // Set X
|
||||
// if (maxX < x)
|
||||
// maxX = x;
|
||||
// if (minX > x)
|
||||
// minX = x;
|
||||
// // Set Y
|
||||
// if (maxY < y)
|
||||
// maxY = y;
|
||||
// if (minY > y)
|
||||
// minY = y;
|
||||
// }
|
||||
// }
|
||||
// return (maxX - minX) * (maxY - minY);
|
||||
// }
|
||||
// catch (const std::exception& e)
|
||||
// {
|
||||
// error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
// return 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
// inline int getPersonWithMaxArea(const Array<float>& poseKeypoints, const float threshold)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// if (!poseKeypoints.empty())
|
||||
// {
|
||||
// const auto numberPeople = poseKeypoints.getSize(0);
|
||||
// const auto numberBodyParts = poseKeypoints.getSize(1);
|
||||
// const auto area = numberBodyParts * poseKeypoints.getSize(2);
|
||||
// auto biggestPoseIndex = -1;
|
||||
// auto biggestArea = -1;
|
||||
// for (auto person = 0 ; person < numberPeople ; person++)
|
||||
// {
|
||||
// const auto newPersonArea = getPersonArea(&poseKeypoints[person*area], numberBodyParts, threshold);
|
||||
// if (newPersonArea > biggestArea)
|
||||
// {
|
||||
// biggestArea = newPersonArea;
|
||||
// biggestPoseIndex = person;
|
||||
// }
|
||||
// }
|
||||
// return biggestPoseIndex;
|
||||
// }
|
||||
// else
|
||||
// return -1;
|
||||
// }
|
||||
// catch (const std::exception& e)
|
||||
// {
|
||||
// error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
// return -1;
|
||||
// }
|
||||
// }
|
||||
|
||||
bool heatMapTypesHas(const std::vector<HeatMapType>& heatMapTypes, const HeatMapType heatMapType)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
namespace op
|
||||
{
|
||||
const std::array<std::map<unsigned int, std::string>, 3> POSE_BODY_PART_MAPPING{ POSE_COCO_BODY_PARTS, POSE_MPI_BODY_PARTS, POSE_MPI_BODY_PARTS };
|
||||
const std::array<std::map<unsigned int, std::string>, 3> POSE_BODY_PART_MAPPING{ POSE_COCO_BODY_PARTS, POSE_MPI_BODY_PARTS, POSE_MPI_BODY_PARTS };
|
||||
|
||||
unsigned int poseBodyPartMapStringToKey(const PoseModel poseModel, const std::vector<std::string>& strings)
|
||||
{
|
||||
@@ -24,29 +24,29 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int poseBodyPartMapStringToKey(const PoseModel poseModel, const std::string& string)
|
||||
{
|
||||
try
|
||||
{
|
||||
return poseBodyPartMapStringToKey(poseModel, std::vector<std::string>{string});
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
unsigned int poseBodyPartMapStringToKey(const PoseModel poseModel, const std::string& string)
|
||||
{
|
||||
try
|
||||
{
|
||||
return poseBodyPartMapStringToKey(poseModel, std::vector<std::string>{string});
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const std::map<unsigned int, std::string>& getPoseBodyPartMapping(const PoseModel poseModel)
|
||||
{
|
||||
try
|
||||
{
|
||||
return POSE_BODY_PART_MAPPING.at((int)poseModel);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return POSE_BODY_PART_MAPPING[(int)poseModel];
|
||||
}
|
||||
}
|
||||
const std::map<unsigned int, std::string>& getPoseBodyPartMapping(const PoseModel poseModel)
|
||||
{
|
||||
try
|
||||
{
|
||||
return POSE_BODY_PART_MAPPING.at((int)poseModel);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return POSE_BODY_PART_MAPPING[(int)poseModel];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include <cuda.h>
|
||||
#include <cuda_runtime_api.h>
|
||||
#ifndef CPU_ONLY
|
||||
#include <cuda.h>
|
||||
#include <cuda_runtime_api.h>
|
||||
#endif
|
||||
#include <openpose/pose/poseParameters.hpp>
|
||||
#include <openpose/pose/poseRenderGpu.hpp>
|
||||
#include <openpose/pose/renderPose.hpp>
|
||||
#include <openpose/utilities/cuda.hpp>
|
||||
#include <openpose/utilities/errorAndLog.hpp>
|
||||
#include <openpose/pose/poseRenderer.hpp>
|
||||
@@ -37,8 +39,10 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
PoseRenderer::PoseRenderer(const Point<int>& heatMapsSize, const Point<int>& outputSize, const PoseModel poseModel, const std::shared_ptr<PoseExtractor>& poseExtractor,
|
||||
const bool blendOriginalFrame, const float alphaKeypoint, const float alphaHeatMap, const unsigned int elementToRender) :
|
||||
PoseRenderer::PoseRenderer(const Point<int>& heatMapsSize, const Point<int>& outputSize, const PoseModel poseModel,
|
||||
const std::shared_ptr<PoseExtractor>& poseExtractor, const bool blendOriginalFrame,
|
||||
const float alphaKeypoint, const float alphaHeatMap, const unsigned int elementToRender,
|
||||
const RenderMode renderMode) :
|
||||
// #body elements to render = #body parts (size()) + #body part pair connections + 3 (+whole pose +whole heatmaps +PAFs)
|
||||
// POSE_BODY_PART_MAPPING crashes on Windows, replaced by getPoseBodyPartMapping
|
||||
Renderer{(unsigned long long)(outputSize.area() * 3), alphaKeypoint, alphaHeatMap, elementToRender,
|
||||
@@ -48,6 +52,7 @@ namespace op
|
||||
mPoseModel{poseModel},
|
||||
mPartIndexToName{createPartToName(poseModel)},
|
||||
spPoseExtractor{poseExtractor},
|
||||
mRenderMode{renderMode},
|
||||
mBlendOriginalFrame{blendOriginalFrame},
|
||||
mShowGooglyEyes{false},
|
||||
pGpuPose{nullptr}
|
||||
@@ -59,7 +64,9 @@ namespace op
|
||||
try
|
||||
{
|
||||
// Free CUDA pointers - Note that if pointers are 0 (i.e. nullptr), no operation is performed.
|
||||
cudaFree(pGpuPose);
|
||||
#ifndef CPU_ONLY
|
||||
cudaFree(pGpuPose);
|
||||
#endif
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -71,11 +78,13 @@ namespace op
|
||||
{
|
||||
try
|
||||
{
|
||||
// GPU memory allocation for rendering
|
||||
log("Starting initialization on thread.", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
Renderer::initializationOnThread();
|
||||
cudaMalloc((void**)(&pGpuPose), POSE_MAX_PEOPLE * POSE_NUMBER_BODY_PARTS[(int)mPoseModel] * 3 * sizeof(float));
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
// GPU memory allocation for rendering
|
||||
#ifndef CPU_ONLY
|
||||
cudaMalloc((void**)(&pGpuPose), POSE_MAX_PEOPLE * POSE_NUMBER_BODY_PARTS[(int)mPoseModel] * 3 * sizeof(float));
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
#endif
|
||||
log("Finished initialization on thread.", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
@@ -134,73 +143,135 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<int, std::string> PoseRenderer::renderPose(Array<float>& outputData, const Array<float>& poseKeypoints, const float scaleNetToOutput)
|
||||
std::pair<int, std::string> PoseRenderer::renderPose(Array<float>& outputData, const Array<float>& poseKeypoints,
|
||||
const float scaleNetToOutput)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Security checks
|
||||
if (outputData.empty())
|
||||
error("Empty outputData.", __LINE__, __FUNCTION__, __FILE__);
|
||||
error("Empty Array<float> outputData.", __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
const auto elementRendered = spElementToRender->load(); // I prefer std::round(T&) over intRound(T) for std::atomic
|
||||
const auto numberPeople = poseKeypoints.getSize(0);
|
||||
std::string elementRenderedName;
|
||||
// CPU rendering
|
||||
if (mRenderMode == RenderMode::Cpu)
|
||||
return renderPoseCpu(outputData, poseKeypoints, scaleNetToOutput);
|
||||
|
||||
// GPU rendering
|
||||
if (numberPeople > 0 || elementRendered != 0 || !mBlendOriginalFrame)
|
||||
else
|
||||
return renderPoseGpu(outputData, poseKeypoints, scaleNetToOutput);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return std::make_pair(-1, "");
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<int, std::string> PoseRenderer::renderPoseCpu(Array<float>& outputData, const Array<float>& poseKeypoints,
|
||||
const float scaleNetToOutput)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto elementRendered = spElementToRender->load();
|
||||
|
||||
std::string elementRenderedName;
|
||||
// CPU rendering
|
||||
// Draw poseKeypoints
|
||||
if (elementRendered == 0)
|
||||
renderPoseKeypointsCpu(outputData, poseKeypoints, mPoseModel, mBlendOriginalFrame);
|
||||
// Draw heat maps / PAFs
|
||||
else
|
||||
{
|
||||
cpuToGpuMemoryIfNotCopiedYet(outputData.getPtr());
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
const auto numberBodyParts = POSE_NUMBER_BODY_PARTS[(int)mPoseModel];
|
||||
const auto numberBodyPartsPlusBkg = numberBodyParts+1;
|
||||
// Draw poseKeypoints
|
||||
if (elementRendered == 0)
|
||||
UNUSED(scaleNetToOutput);
|
||||
error("CPU rendering only available for drawing keypoints, no heat maps nor PAFs.", __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
// Return result
|
||||
return std::make_pair(elementRendered, elementRenderedName);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return std::make_pair(-1, "");
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<int, std::string> PoseRenderer::renderPoseGpu(Array<float>& outputData, const Array<float>& poseKeypoints,
|
||||
const float scaleNetToOutput)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto elementRendered = spElementToRender->load();
|
||||
|
||||
std::string elementRenderedName;
|
||||
// GPU rendering
|
||||
#ifndef CPU_ONLY
|
||||
const auto numberPeople = poseKeypoints.getSize(0);
|
||||
if (numberPeople > 0 || elementRendered != 0 || !mBlendOriginalFrame)
|
||||
{
|
||||
if (!poseKeypoints.empty())
|
||||
cudaMemcpy(pGpuPose, poseKeypoints.getConstPtr(), numberPeople * numberBodyParts * 3 * sizeof(float), cudaMemcpyHostToDevice);
|
||||
renderPoseGpu(*spGpuMemoryPtr, mPoseModel, numberPeople, mOutputSize, pGpuPose, mShowGooglyEyes, mBlendOriginalFrame, getAlphaKeypoint());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scaleNetToOutput == -1.f)
|
||||
error("Non valid scaleNetToOutput.", __LINE__, __FUNCTION__, __FILE__);
|
||||
// Draw specific body part or bkg
|
||||
if (elementRendered <= numberBodyPartsPlusBkg)
|
||||
cpuToGpuMemoryIfNotCopiedYet(outputData.getPtr());
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
const auto numberBodyParts = POSE_NUMBER_BODY_PARTS[(int)mPoseModel];
|
||||
const auto numberBodyPartsPlusBkg = numberBodyParts+1;
|
||||
// Draw poseKeypoints
|
||||
if (elementRendered == 0)
|
||||
{
|
||||
elementRenderedName = mPartIndexToName.at(elementRendered-1);
|
||||
renderBodyPartGpu(*spGpuMemoryPtr, mPoseModel, mOutputSize, spPoseExtractor->getHeatMapCpuConstPtr(), mHeatMapsSize,
|
||||
scaleNetToOutput, elementRendered, (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f));
|
||||
if (!poseKeypoints.empty())
|
||||
cudaMemcpy(pGpuPose, poseKeypoints.getConstPtr(), numberPeople * numberBodyParts * 3 * sizeof(float),
|
||||
cudaMemcpyHostToDevice);
|
||||
renderPoseKeypointsGpu(*spGpuMemoryPtr, mPoseModel, numberPeople, mOutputSize, pGpuPose,
|
||||
mShowGooglyEyes, mBlendOriginalFrame, getAlphaKeypoint());
|
||||
}
|
||||
// Draw PAFs (Part Affinity Fields)
|
||||
else if (elementRendered == numberBodyPartsPlusBkg+1)
|
||||
{
|
||||
elementRenderedName = "Heatmaps";
|
||||
renderBodyPartsGpu(*spGpuMemoryPtr, mPoseModel, mOutputSize, spPoseExtractor->getHeatMapCpuConstPtr(), mHeatMapsSize, scaleNetToOutput,
|
||||
(mBlendOriginalFrame ? getAlphaHeatMap() : 1.f));
|
||||
}
|
||||
// Draw PAFs (Part Affinity Fields)
|
||||
else if (elementRendered == numberBodyPartsPlusBkg+2)
|
||||
{
|
||||
elementRenderedName = "PAFs (Part Affinity Fields)";
|
||||
renderPartAffinityFieldsGpu(*spGpuMemoryPtr, mPoseModel, mOutputSize, spPoseExtractor->getHeatMapCpuConstPtr(),
|
||||
mHeatMapsSize, scaleNetToOutput, (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f));
|
||||
}
|
||||
// Draw affinity between 2 body parts
|
||||
else
|
||||
{
|
||||
const auto affinityPart = (elementRendered-numberBodyPartsPlusBkg-3)*2;
|
||||
const auto affinityPartMapped = POSE_MAP_IDX[(int)mPoseModel].at(affinityPart);
|
||||
elementRenderedName = mPartIndexToName.at(affinityPartMapped);
|
||||
elementRenderedName = elementRenderedName.substr(0, elementRenderedName.find("("));
|
||||
renderPartAffinityFieldGpu(*spGpuMemoryPtr, mPoseModel, mOutputSize, spPoseExtractor->getHeatMapCpuConstPtr(),
|
||||
mHeatMapsSize, scaleNetToOutput, affinityPartMapped, (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f));
|
||||
}
|
||||
if (scaleNetToOutput == -1.f)
|
||||
error("Non valid scaleNetToOutput.", __LINE__, __FUNCTION__, __FILE__);
|
||||
// Draw specific body part or bkg
|
||||
if (elementRendered <= numberBodyPartsPlusBkg)
|
||||
{
|
||||
elementRenderedName = mPartIndexToName.at(elementRendered-1);
|
||||
renderPoseHeatMapGpu(*spGpuMemoryPtr, mPoseModel, mOutputSize, spPoseExtractor->getHeatMapCpuConstPtr(),
|
||||
mHeatMapsSize, scaleNetToOutput, elementRendered,
|
||||
(mBlendOriginalFrame ? getAlphaHeatMap() : 1.f));
|
||||
}
|
||||
// Draw PAFs (Part Affinity Fields)
|
||||
else if (elementRendered == numberBodyPartsPlusBkg+1)
|
||||
{
|
||||
elementRenderedName = "Heatmaps";
|
||||
renderPoseHeatMapsGpu(*spGpuMemoryPtr, mPoseModel, mOutputSize, spPoseExtractor->getHeatMapCpuConstPtr(),
|
||||
mHeatMapsSize, scaleNetToOutput, (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f));
|
||||
}
|
||||
// Draw PAFs (Part Affinity Fields)
|
||||
else if (elementRendered == numberBodyPartsPlusBkg+2)
|
||||
{
|
||||
elementRenderedName = "PAFs (Part Affinity Fields)";
|
||||
renderPosePAFsGpu(*spGpuMemoryPtr, mPoseModel, mOutputSize, spPoseExtractor->getHeatMapCpuConstPtr(),
|
||||
mHeatMapsSize, scaleNetToOutput, (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f));
|
||||
}
|
||||
// Draw affinity between 2 body parts
|
||||
else
|
||||
{
|
||||
const auto affinityPart = (elementRendered-numberBodyPartsPlusBkg-3)*2;
|
||||
const auto affinityPartMapped = POSE_MAP_IDX[(int)mPoseModel].at(affinityPart);
|
||||
elementRenderedName = mPartIndexToName.at(affinityPartMapped);
|
||||
elementRenderedName = elementRenderedName.substr(0, elementRenderedName.find("("));
|
||||
renderPosePAFGpu(*spGpuMemoryPtr, mPoseModel, mOutputSize, spPoseExtractor->getHeatMapCpuConstPtr(),
|
||||
mHeatMapsSize, scaleNetToOutput, affinityPartMapped,
|
||||
(mBlendOriginalFrame ? getAlphaHeatMap() : 1.f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// GPU memory to CPU if last renderer
|
||||
gpuToCpuMemoryIfLastRenderer(outputData.getPtr());
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// GPU memory to CPU if last renderer
|
||||
gpuToCpuMemoryIfLastRenderer(outputData.getPtr());
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
// CPU_ONLY mode
|
||||
#else
|
||||
error("GPU rendering not available if `CPU_ONLY` is set.", __LINE__, __FUNCTION__, __FILE__);
|
||||
UNUSED(elementRendered);
|
||||
UNUSED(outputData);
|
||||
UNUSED(poseKeypoints);
|
||||
UNUSED(scaleNetToOutput);
|
||||
#endif
|
||||
// Return result
|
||||
return std::make_pair(elementRendered, elementRenderedName);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#include <openpose/pose/poseParameters.hpp>
|
||||
#include <openpose/utilities/errorAndLog.hpp>
|
||||
#include <openpose/utilities/fastMath.hpp>
|
||||
#include <openpose/utilities/keypoint.hpp>
|
||||
#include <openpose/pose/renderPose.hpp>
|
||||
|
||||
namespace op
|
||||
{
|
||||
const std::vector<float> COCO_COLORS{POSE_COCO_COLORS_RENDER};
|
||||
const std::vector<float> MPI_COLORS{POSE_MPI_COLORS_RENDER};
|
||||
|
||||
void renderPoseKeypointsCpu(Array<float>& frameArray, const Array<float>& poseKeypoints, const PoseModel poseModel, const bool blendOriginalFrame)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!frameArray.empty())
|
||||
{
|
||||
// Array<float> --> cv::Mat
|
||||
auto frame = frameArray.getCvMat();
|
||||
|
||||
// Background
|
||||
if (!blendOriginalFrame)
|
||||
frame.setTo(0.f); // [0-255]
|
||||
|
||||
// Parameters
|
||||
const auto thicknessCircleRatio = 1.f/75.f;
|
||||
const auto thicknessLineRatioWRTCircle = 0.75f;
|
||||
const auto& pairs = POSE_BODY_PART_PAIRS_RENDER[(int)poseModel];
|
||||
const auto& colors = (poseModel == PoseModel::COCO_18 ? COCO_COLORS : MPI_COLORS);
|
||||
|
||||
// Render keypoints
|
||||
renderKeypointsCpu(frameArray, poseKeypoints, pairs, colors, thicknessCircleRatio, thicknessLineRatioWRTCircle);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,74 +1,18 @@
|
||||
#include <utility> // std::pair
|
||||
#include <openpose/pose/poseParameters.hpp>
|
||||
#include <openpose/utilities/errorAndLog.hpp>
|
||||
#include <openpose/utilities/cuda.hpp>
|
||||
#include <openpose/utilities/cuda.hu>
|
||||
#include <openpose/utilities/render.hu>
|
||||
#include <openpose/pose/poseRenderGpu.hpp>
|
||||
#include <openpose/pose/renderPose.hpp>
|
||||
|
||||
namespace op
|
||||
{
|
||||
// PI digits: http://www.piday.org/million/
|
||||
__constant__ const float PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745f;
|
||||
__constant__ const unsigned int COCO_PAIRS_GPU[] = POSE_COCO_PAIRS_TO_RENDER;
|
||||
__constant__ const unsigned int MPI_PAIRS_GPU[] = POSE_MPI_PAIRS_TO_RENDER;
|
||||
__constant__ const float COCO_RGB_COLORS[] = {
|
||||
255.f, 0.f, 0.f,
|
||||
255.f, 85.f, 0.f,
|
||||
255.f, 170.f, 0.f,
|
||||
255.f, 255.f, 0.f,
|
||||
170.f, 255.f, 0.f,
|
||||
85.f, 255.f, 0.f,
|
||||
0.f, 255.f, 0.f,
|
||||
0.f, 255.f, 85.f,
|
||||
0.f, 255.f, 170.f,
|
||||
0.f, 255.f, 255.f,
|
||||
0.f, 170.f, 255.f,
|
||||
0.f, 85.f, 255.f,
|
||||
0.f, 0.f, 255.f,
|
||||
85.f, 0.f, 255.f,
|
||||
170.f, 0.f, 255.f,
|
||||
255.f, 0.f, 255.f,
|
||||
255.f, 0.f, 170.f,
|
||||
255.f, 0.f, 85.f,
|
||||
};
|
||||
__constant__ const float MPI_RGB_COLORS[] = { // MPI colors chosen such that they are closed to COCO colors
|
||||
255.f, 0.f, 85.f,
|
||||
255.f, 0.f, 0.f,
|
||||
255.f, 85.f, 0.f,
|
||||
255.f, 170.f, 0.f,
|
||||
255.f, 255.f, 0.f,
|
||||
170.f, 255.f, 0.f,
|
||||
85.f, 255.f, 0.f,
|
||||
43.f, 255.f, 0.f,
|
||||
0.f, 255.f, 0.f,
|
||||
0.f, 255.f, 85.f,
|
||||
0.f, 255.f, 170.f,
|
||||
0.f, 255.f, 255.f,
|
||||
0.f, 170.f, 255.f,
|
||||
0.f, 85.f, 255.f,
|
||||
0.f, 0.f, 255.f,
|
||||
};
|
||||
__constant__ const float RGB_COLORS_BACKGROUND[] = {
|
||||
255.f, 0.f, 0.f,
|
||||
255.f, 85.f, 0.f,
|
||||
255.f, 170.f, 0.f,
|
||||
255.f, 255.f, 0.f,
|
||||
170.f, 255.f, 0.f,
|
||||
85.f, 255.f, 0.f,
|
||||
0.f, 255.f, 0.f,
|
||||
0.f, 255.f, 85.f,
|
||||
0.f, 255.f, 170.f,
|
||||
0.f, 255.f, 255.f,
|
||||
0.f, 170.f, 255.f,
|
||||
0.f, 85.f, 255.f,
|
||||
0.f, 0.f, 255.f,
|
||||
85.f, 0.f, 255.f,
|
||||
170.f, 0.f, 255.f,
|
||||
255.f, 0.f, 255.f,
|
||||
255.f, 0.f, 170.f,
|
||||
255.f, 0.f, 85.f,
|
||||
};
|
||||
// PI digits: http://www.piday.org/million/
|
||||
__constant__ const float PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745f;
|
||||
__constant__ const unsigned int COCO_PAIRS_GPU[] = POSE_COCO_PAIRS_RENDER_GPU;
|
||||
__constant__ const unsigned int MPI_PAIRS_GPU[] = POSE_MPI_PAIRS_RENDER_GPU;
|
||||
__constant__ const float COCO_COLORS[] = {POSE_COCO_COLORS_RENDER};
|
||||
__constant__ const float MPI_COLORS[] = {POSE_MPI_COLORS_RENDER};
|
||||
|
||||
|
||||
|
||||
@@ -163,14 +107,14 @@ namespace op
|
||||
|
||||
// Other parameters
|
||||
const auto numberPartPairs = sizeof(COCO_PAIRS_GPU) / (2*sizeof(COCO_PAIRS_GPU[0]));
|
||||
const auto numberColors = sizeof(COCO_RGB_COLORS) / (3*sizeof(COCO_RGB_COLORS[0]));
|
||||
const auto numberColors = sizeof(COCO_COLORS) / (3*sizeof(COCO_COLORS[0]));
|
||||
const auto radius = fastMin(targetWidth, targetHeight) / 100.f;
|
||||
const auto stickwidth = fastMin(targetWidth, targetHeight) / 120.f;
|
||||
|
||||
// Render key points
|
||||
renderKeypoints(targetPtr, sharedMaxs, sharedMins, sharedScaleF,
|
||||
globalIdx, x, y, targetWidth, targetHeight, posePtr, COCO_PAIRS_GPU, numberPeople,
|
||||
POSE_COCO_NUMBER_PARTS, numberPartPairs, COCO_RGB_COLORS, numberColors,
|
||||
POSE_COCO_NUMBER_PARTS, numberPartPairs, COCO_COLORS, numberColors,
|
||||
radius, stickwidth, threshold, alphaColorToAdd, blendOriginalFrame, (googlyEyes ? 14 : -1), (googlyEyes ? 15 : -1));
|
||||
}
|
||||
|
||||
@@ -188,14 +132,14 @@ namespace op
|
||||
|
||||
// Other parameters
|
||||
const auto numberPartPairs = sizeof(MPI_PAIRS_GPU) / (2*sizeof(MPI_PAIRS_GPU[0]));
|
||||
const auto numberColors = sizeof(MPI_RGB_COLORS) / (3*sizeof(MPI_RGB_COLORS[0]));
|
||||
const auto numberColors = sizeof(MPI_COLORS) / (3*sizeof(MPI_COLORS[0]));
|
||||
const auto radius = fastMin(targetWidth, targetHeight) / 100.f;
|
||||
const auto stickwidth = fastMin(targetWidth, targetHeight) / 120.f;
|
||||
|
||||
// Render key points
|
||||
renderKeypoints(targetPtr, sharedMaxs, sharedMins, sharedScaleF,
|
||||
globalIdx, x, y, targetWidth, targetHeight, posePtr, MPI_PAIRS_GPU, numberPeople,
|
||||
POSE_MPI_NUMBER_PARTS, numberPartPairs, MPI_RGB_COLORS, numberColors,
|
||||
POSE_MPI_NUMBER_PARTS, numberPartPairs, MPI_COLORS, numberColors,
|
||||
radius, stickwidth, threshold, alphaColorToAdd, blendOriginalFrame);
|
||||
}
|
||||
|
||||
@@ -205,7 +149,7 @@ namespace op
|
||||
const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;
|
||||
const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;
|
||||
|
||||
const auto numberColors = sizeof(RGB_COLORS_BACKGROUND)/(3*sizeof(RGB_COLORS_BACKGROUND[0]));
|
||||
const auto numberColors = sizeof(COCO_COLORS)/(3*sizeof(COCO_COLORS[0]));
|
||||
|
||||
if (x < targetWidth && y < targetHeight)
|
||||
{
|
||||
@@ -220,9 +164,9 @@ namespace op
|
||||
const auto offsetOrigin = part * heatMapArea;
|
||||
const auto value = __saturatef(heatMapPtr[offsetOrigin + yHeatMap*widthHeatMap + xHeatMap]); // __saturatef = trucate to [0,1]
|
||||
const auto rgbColorIndex = (part%numberColors)*3;
|
||||
rgbColor[0] += value*RGB_COLORS_BACKGROUND[rgbColorIndex];
|
||||
rgbColor[1] += value*RGB_COLORS_BACKGROUND[rgbColorIndex+1];
|
||||
rgbColor[2] += value*RGB_COLORS_BACKGROUND[rgbColorIndex+2];
|
||||
rgbColor[0] += value*COCO_COLORS[rgbColorIndex];
|
||||
rgbColor[1] += value*COCO_COLORS[rgbColorIndex+1];
|
||||
rgbColor[2] += value*COCO_COLORS[rgbColorIndex+2];
|
||||
}
|
||||
|
||||
const auto blueIndex = y * targetWidth + x;
|
||||
@@ -340,9 +284,9 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
inline void renderKeypointsPartAffinityAux(float* framePtr, const PoseModel poseModel, const Point<int>& frameSize,
|
||||
const float* const heatMapPtr, const Point<int>& heatMapSize, const float scaleToKeepRatio,
|
||||
const int part, const int partsToRender, const float alphaBlending)
|
||||
inline void renderPosePAFGpuAux(float* framePtr, const PoseModel poseModel, const Point<int>& frameSize,
|
||||
const float* const heatMapPtr, const Point<int>& heatMapSize, const float scaleToKeepRatio,
|
||||
const int part, const int partsToRender, const float alphaBlending)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -363,8 +307,8 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
void renderPoseGpu(float* framePtr, const PoseModel poseModel, const int numberPeople, const Point<int>& frameSize, const float* const posePtr,
|
||||
const bool googlyEyes, const bool blendOriginalFrame, const float alphaBlending)
|
||||
void renderPoseKeypointsGpu(float* framePtr, const PoseModel poseModel, const int numberPeople, const Point<int>& frameSize,
|
||||
const float* const posePtr, const bool googlyEyes, const bool blendOriginalFrame, const float alphaBlending)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -398,8 +342,8 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
void renderBodyPartGpu(float* framePtr, const PoseModel poseModel, const Point<int>& frameSize, const float* const heatMapPtr,
|
||||
const Point<int>& heatMapSize, const float scaleToKeepRatio, const int part, const float alphaBlending)
|
||||
void renderPoseHeatMapGpu(float* framePtr, const PoseModel poseModel, const Point<int>& frameSize, const float* const heatMapPtr,
|
||||
const Point<int>& heatMapSize, const float scaleToKeepRatio, const int part, const float alphaBlending)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -422,8 +366,8 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
void renderBodyPartsGpu(float* framePtr, const PoseModel poseModel, const Point<int>& frameSize, const float* const heatMapPtr,
|
||||
const Point<int>& heatMapSize, const float scaleToKeepRatio, const float alphaBlending)
|
||||
void renderPoseHeatMapsGpu(float* framePtr, const PoseModel poseModel, const Point<int>& frameSize, const float* const heatMapPtr,
|
||||
const Point<int>& heatMapSize, const float scaleToKeepRatio, const float alphaBlending)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -446,12 +390,12 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
void renderPartAffinityFieldGpu(float* framePtr, const PoseModel poseModel, const Point<int>& frameSize, const float* const heatMapPtr,
|
||||
const Point<int>& heatMapSize, const float scaleToKeepRatio, const int part, const float alphaBlending)
|
||||
void renderPosePAFGpu(float* framePtr, const PoseModel poseModel, const Point<int>& frameSize, const float* const heatMapPtr,
|
||||
const Point<int>& heatMapSize, const float scaleToKeepRatio, const int part, const float alphaBlending)
|
||||
{
|
||||
try
|
||||
{
|
||||
renderKeypointsPartAffinityAux(framePtr, poseModel, frameSize, heatMapPtr, heatMapSize, scaleToKeepRatio, part, 1, alphaBlending);
|
||||
renderPosePAFGpuAux(framePtr, poseModel, frameSize, heatMapPtr, heatMapSize, scaleToKeepRatio, part, 1, alphaBlending);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -459,14 +403,14 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
void renderPartAffinityFieldsGpu(float* framePtr, const PoseModel poseModel, const Point<int>& frameSize, const float* const heatMapPtr,
|
||||
const Point<int>& heatMapSize, const float scaleToKeepRatio, const float alphaBlending)
|
||||
void renderPosePAFsGpu(float* framePtr, const PoseModel poseModel, const Point<int>& frameSize, const float* const heatMapPtr,
|
||||
const Point<int>& heatMapSize, const float scaleToKeepRatio, const float alphaBlending)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto numberBodyPartPairs = (int)POSE_BODY_PART_PAIRS[(int)poseModel].size()/2;
|
||||
renderKeypointsPartAffinityAux(framePtr, poseModel, frameSize, heatMapPtr, heatMapSize, scaleToKeepRatio, POSE_NUMBER_BODY_PARTS[(int)poseModel]+1,
|
||||
numberBodyPartPairs, alphaBlending);
|
||||
renderPosePAFGpuAux(framePtr, poseModel, frameSize, heatMapPtr, heatMapSize, scaleToKeepRatio,
|
||||
POSE_NUMBER_BODY_PARTS[(int)poseModel]+1, numberBodyPartPairs, alphaBlending);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -2,6 +2,6 @@
|
||||
|
||||
namespace op
|
||||
{
|
||||
template class DatumProducer<DATUM_BASE_NO_PTR>;
|
||||
template class DatumProducer<DATUM_BASE_NO_PTR>;
|
||||
template class WDatumProducer<DATUM_BASE, DATUM_BASE_NO_PTR>;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace op
|
||||
{
|
||||
try
|
||||
{
|
||||
return VideoCaptureReader::getRawFrame();
|
||||
return VideoCaptureReader::getRawFrame();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
#include <openpose/utilities/errorAndLog.hpp>
|
||||
#include <openpose/utilities/fastMath.hpp>
|
||||
#include <openpose/utilities/keypoint.hpp>
|
||||
|
||||
namespace op
|
||||
{
|
||||
const std::string errorMessage = "The Array<float> is not a RGB image. This function is only for array of dimension: [sizeA x sizeB x 3].";
|
||||
|
||||
float getDistance(const float* keypointPtr, const int elementA, const int elementB)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto pixelX = keypointPtr[elementA*3] - keypointPtr[elementB*3];
|
||||
const auto pixelY = keypointPtr[elementA*3+1] - keypointPtr[elementB*3+1];
|
||||
return std::sqrt(pixelX*pixelX+pixelY*pixelY);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return -1.f;
|
||||
}
|
||||
}
|
||||
|
||||
void scaleKeypoints(Array<float>& keypoints, const float scale)
|
||||
{
|
||||
try
|
||||
{
|
||||
scaleKeypoints(keypoints, scale, scale);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void scaleKeypoints(Array<float>& keypoints, const float scaleX, const float scaleY)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (scaleX != 1. && scaleY != 1.)
|
||||
{
|
||||
// Error check
|
||||
if (!keypoints.empty() && keypoints.getSize(2) != 3)
|
||||
error(errorMessage, __LINE__, __FUNCTION__, __FILE__);
|
||||
// Get #people and #parts
|
||||
const auto numberPeople = keypoints.getSize(0);
|
||||
const auto numberParts = keypoints.getSize(1);
|
||||
// For each person
|
||||
for (auto person = 0 ; person < numberPeople ; person++)
|
||||
{
|
||||
// For each body part
|
||||
for (auto part = 0 ; part < numberParts ; part++)
|
||||
{
|
||||
const auto finalIndex = 3*(person*numberParts + part);
|
||||
keypoints[finalIndex] *= scaleX;
|
||||
keypoints[finalIndex+1] *= scaleY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void scaleKeypoints(Array<float>& keypoints, const float scaleX, const float scaleY, const float offsetX, const float offsetY)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (scaleX != 1. && scaleY != 1.)
|
||||
{
|
||||
// Error check
|
||||
if (!keypoints.empty() && keypoints.getSize(2) != 3)
|
||||
error(errorMessage, __LINE__, __FUNCTION__, __FILE__);
|
||||
// Get #people and #parts
|
||||
const auto numberPeople = keypoints.getSize(0);
|
||||
const auto numberParts = keypoints.getSize(1);
|
||||
// For each person
|
||||
for (auto person = 0 ; person < numberPeople ; person++)
|
||||
{
|
||||
// For each body part
|
||||
for (auto part = 0 ; part < numberParts ; part++)
|
||||
{
|
||||
const auto finalIndex = keypoints.getSize(2)*(person*numberParts + part);
|
||||
keypoints[finalIndex] = keypoints[finalIndex] * scaleX + offsetX;
|
||||
keypoints[finalIndex+1] = keypoints[finalIndex+1] * scaleY + offsetY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void renderKeypointsCpu(Array<float>& frameArray, const Array<float>& keypoints, const std::vector<unsigned int>& pairs,
|
||||
const std::vector<float> colors, const float thicknessCircleRatio, const float thicknessLineRatioWRTCircle)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!frameArray.empty())
|
||||
{
|
||||
// Array<float> --> cv::Mat
|
||||
auto frame = frameArray.getCvMat();
|
||||
|
||||
// Security check
|
||||
if (frame.dims != 3 || frame.size[0] != 3)
|
||||
error(errorMessage, __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// Get frame channels
|
||||
const auto width = frame.size[2];
|
||||
const auto height = frame.size[1];
|
||||
const auto area = width * height;
|
||||
cv::Mat frameB{height, width, CV_32FC1, &frame.data[0]};
|
||||
cv::Mat frameG{height, width, CV_32FC1, &frame.data[area * sizeof(float) / sizeof(uchar)]};
|
||||
cv::Mat frameR{height, width, CV_32FC1, &frame.data[2 * area * sizeof(float) / sizeof(uchar)]};
|
||||
|
||||
// Parameters
|
||||
const auto lineType = 8;
|
||||
const auto shift = 0;
|
||||
const auto threshold = 0.1;
|
||||
const auto numberColors = colors.size();
|
||||
const auto numberBodyParts = keypoints.getSize(1);
|
||||
const auto areaKeypoints = numberBodyParts * keypoints.getSize(2);
|
||||
|
||||
// Keypoints
|
||||
for (auto person = 0 ; person < keypoints.getSize(0) ; person++)
|
||||
{
|
||||
const auto personRectangle = getKeypointsRectangle(&keypoints[person*areaKeypoints], keypoints.getSize(1), threshold);
|
||||
const auto ratioAreas = fastMin(1.f, fastMax(personRectangle.width/(float)width, personRectangle.height/(float)height));
|
||||
// Size-dependent variables
|
||||
const auto thicknessCircle = fastMax(intRound(std::sqrt(area)*thicknessCircleRatio * ratioAreas), 2);
|
||||
const auto thicknessLine = intRound(thicknessCircle * thicknessLineRatioWRTCircle);
|
||||
const auto radius = thicknessCircle / 2;
|
||||
|
||||
// Draw lines
|
||||
for (auto pair = 0 ; pair < pairs.size() ; pair+=2)
|
||||
{
|
||||
const auto index1 = (person * keypoints.getSize(1) + pairs[pair]) * keypoints.getSize(2);
|
||||
const auto index2 = (person * keypoints.getSize(1) + pairs[pair+1]) * keypoints.getSize(2);
|
||||
if (keypoints[index1+2] > threshold && keypoints[index2+2] > threshold)
|
||||
{
|
||||
const auto colorIndex = pair/2*3;
|
||||
const cv::Scalar color{colors[colorIndex % numberColors],
|
||||
colors[(colorIndex+1) % numberColors],
|
||||
colors[(colorIndex+2) % numberColors]};
|
||||
const cv::Point keypoint1{intRound(keypoints[index1]), intRound(keypoints[index1+1])};
|
||||
const cv::Point keypoint2{intRound(keypoints[index2]), intRound(keypoints[index2+1])};
|
||||
cv::line(frameR, keypoint1, keypoint2, color[0], thicknessLine, lineType, shift);
|
||||
cv::line(frameG, keypoint1, keypoint2, color[1], thicknessLine, lineType, shift);
|
||||
cv::line(frameB, keypoint1, keypoint2, color[2], thicknessLine, lineType, shift);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw circles
|
||||
for (auto part = 0 ; part < keypoints.getSize(1) ; part++)
|
||||
{
|
||||
const auto faceIndex = (person * keypoints.getSize(1) + part) * keypoints.getSize(2);
|
||||
if (keypoints[faceIndex+2] > threshold)
|
||||
{
|
||||
const auto colorIndex = part*3;
|
||||
const cv::Scalar color{colors[colorIndex % numberColors],
|
||||
colors[(colorIndex+1) % numberColors],
|
||||
colors[(colorIndex+2) % numberColors]};
|
||||
const cv::Point center{intRound(keypoints[faceIndex]), intRound(keypoints[faceIndex+1])};
|
||||
cv::circle(frameR, center, radius, color[0], thicknessCircle, lineType, shift);
|
||||
cv::circle(frameG, center, radius, color[1], thicknessCircle, lineType, shift);
|
||||
cv::circle(frameB, center, radius, color[2], thicknessCircle, lineType, shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle<unsigned int> getKeypointsRectangle(const float* keypointPtr, const int numberBodyParts, const float threshold)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (numberBodyParts < 1)
|
||||
error("Number body parts must be > 0", __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
unsigned int minX = -1;
|
||||
unsigned int maxX = 0u;
|
||||
unsigned int minY = -1;
|
||||
unsigned int maxY = 0u;
|
||||
for (auto part = 0 ; part < numberBodyParts ; part++)
|
||||
{
|
||||
const auto score = keypointPtr[3*part + 2];
|
||||
if (score > threshold)
|
||||
{
|
||||
const auto x = keypointPtr[3*part];
|
||||
const auto y = keypointPtr[3*part + 1];
|
||||
// Set X
|
||||
if (maxX < x)
|
||||
maxX = x;
|
||||
if (minX > x)
|
||||
minX = x;
|
||||
// Set Y
|
||||
if (maxY < y)
|
||||
maxY = y;
|
||||
if (minY > y)
|
||||
minY = y;
|
||||
}
|
||||
}
|
||||
return Rectangle<unsigned int>{minX, minY, maxX-minX, maxY-minY};
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return Rectangle<unsigned int>{};
|
||||
}
|
||||
}
|
||||
|
||||
int getKeypointsArea(const float* keypointPtr, const int numberBodyParts, const float threshold)
|
||||
{
|
||||
try
|
||||
{
|
||||
return getKeypointsRectangle(keypointPtr, numberBodyParts, threshold).area();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int getBiggestPerson(const Array<float>& keypoints, const float threshold)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!keypoints.empty())
|
||||
{
|
||||
const auto numberPeople = keypoints.getSize(0);
|
||||
const auto numberBodyParts = keypoints.getSize(1);
|
||||
const auto area = numberBodyParts * keypoints.getSize(2);
|
||||
auto biggestPoseIndex = -1;
|
||||
auto biggestArea = -1;
|
||||
for (auto person = 0 ; person < numberPeople ; person++)
|
||||
{
|
||||
const auto newPersonArea = getKeypointsArea(&keypoints[person*area], numberBodyParts, threshold);
|
||||
if (newPersonArea > biggestArea)
|
||||
{
|
||||
biggestArea = newPersonArea;
|
||||
biggestPoseIndex = person;
|
||||
}
|
||||
}
|
||||
return biggestPoseIndex;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
namespace op
|
||||
{
|
||||
WrapperStructFace::WrapperStructFace(const bool enable_, const Point<int>& netInputSize_, const bool renderOutput_, const float alphaKeypoint_,
|
||||
const float alphaHeatMap_) :
|
||||
WrapperStructFace::WrapperStructFace(const bool enable_, const Point<int>& netInputSize_, const RenderMode renderMode_,
|
||||
const float alphaKeypoint_, const float alphaHeatMap_) :
|
||||
enable{enable_},
|
||||
netInputSize{netInputSize_},
|
||||
renderOutput{renderOutput_},
|
||||
renderMode{renderMode_},
|
||||
alphaKeypoint{alphaKeypoint_},
|
||||
alphaHeatMap{alphaHeatMap_}
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace op
|
||||
{
|
||||
WrapperStructPose::WrapperStructPose(const Point<int>& netInputSize_, const Point<int>& outputSize_, const ScaleMode keypointScale_, const int gpuNumber_,
|
||||
const int gpuNumberStart_, const int scalesNumber_, const float scaleGap_, const bool renderOutput_,
|
||||
const int gpuNumberStart_, const int scalesNumber_, const float scaleGap_, const RenderMode renderMode_,
|
||||
const PoseModel poseModel_, const bool blendOriginalFrame_, const float alphaKeypoint_, const float alphaHeatMap_,
|
||||
const int defaultPartToRender_, const std::string& modelFolder_, const std::vector<HeatMapType>& heatMapTypes_,
|
||||
const ScaleMode heatMapScale_) :
|
||||
@@ -14,7 +14,7 @@ namespace op
|
||||
gpuNumberStart{gpuNumberStart_},
|
||||
scalesNumber{scalesNumber_},
|
||||
scaleGap{scaleGap_},
|
||||
renderOutput{renderOutput_},
|
||||
renderMode{renderMode_},
|
||||
poseModel{poseModel_},
|
||||
blendOriginalFrame{blendOriginalFrame_},
|
||||
alphaKeypoint{alphaKeypoint_},
|
||||
|
||||
Reference in New Issue
Block a user