diff --git a/examples/openpose/openpose.cpp b/examples/openpose/openpose.cpp index c90f3d21..dd5c2648 100755 --- a/examples/openpose/openpose.cpp +++ b/examples/openpose/openpose.cpp @@ -28,7 +28,7 @@ // OpenPose dependencies #include -// See all the available parameter options withe the `--help` flag. E.g. `./build/examples/openpose/openpose.bin --help`. +// See all the available parameter options withe the `--help` flag. E.g. `build/examples/openpose/openpose.bin --help` // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging @@ -171,7 +171,8 @@ DEFINE_string(write_heatmaps_format, "png", "File extension and form int openPoseDemo() { // logging_level - op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", __LINE__, __FUNCTION__, __FILE__); + op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", + __LINE__, __FUNCTION__, __FILE__); op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level); // op::ConfigureLog::setPriorityThreshold(op::Priority::None); // To print all logging messages @@ -195,7 +196,8 @@ int openPoseDemo() // keypointScale const auto keypointScale = op::flagsToScaleMode(FLAGS_keypoint_scale); // heatmaps to add - const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg, FLAGS_heatmaps_add_PAFs); + const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg, + FLAGS_heatmaps_add_PAFs); // Enabling Google Logging const bool enableGoogleLogging = true; // Logging @@ -205,30 +207,38 @@ int openPoseDemo() op::log("Configuring OpenPose wrapper.", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__); op::Wrapper> opWrapper; // Pose configuration (use WrapperStructPose{} for default and recommended configuration) - const op::WrapperStructPose wrapperStructPose{!FLAGS_body_disable, netInputSize, outputSize, keypointScale, FLAGS_num_gpu, - FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap, - op::flagsToRenderMode(FLAGS_render_pose), poseModel, - !FLAGS_disable_blending, (float)FLAGS_alpha_pose, + const op::WrapperStructPose wrapperStructPose{!FLAGS_body_disable, netInputSize, outputSize, keypointScale, + FLAGS_num_gpu, FLAGS_num_gpu_start, FLAGS_scale_number, + (float)FLAGS_scale_gap, op::flagsToRenderMode(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, (float)FLAGS_render_threshold, - enableGoogleLogging}; + heatMapTypes, op::ScaleMode::UnsignedChar, + (float)FLAGS_render_threshold, enableGoogleLogging}; // Face configuration (use op::WrapperStructFace{} to disable it) - const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, op::flagsToRenderMode(FLAGS_face_render, FLAGS_render_pose), - (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold}; + const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, + op::flagsToRenderMode(FLAGS_face_render, FLAGS_render_pose), + (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, + (float)FLAGS_face_render_threshold}; // Hand configuration (use op::WrapperStructHand{} to disable it) - const op::WrapperStructHand wrapperStructHand{FLAGS_hand, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range, - FLAGS_hand_tracking, op::flagsToRenderMode(FLAGS_hand_render, FLAGS_render_pose), - (float)FLAGS_hand_alpha_pose, (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold}; + const op::WrapperStructHand wrapperStructHand{FLAGS_hand, handNetInputSize, FLAGS_hand_scale_number, + (float)FLAGS_hand_scale_range, FLAGS_hand_tracking, + op::flagsToRenderMode(FLAGS_hand_render, FLAGS_render_pose), + (float)FLAGS_hand_alpha_pose, (float)FLAGS_hand_alpha_heatmap, + (float)FLAGS_hand_render_threshold}; // 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); + opWrapper.configure(wrapperStructPose, wrapperStructFace, wrapperStructHand, wrapperStructInput, + wrapperStructOutput); // Set to single-thread running (e.g. for debugging purposes) // opWrapper.disableMultiThreading(); @@ -239,9 +249,10 @@ int openPoseDemo() // Start, run & stop threads opWrapper.exec(); // It blocks this thread until all threads have finished - // // Option b) Keeping this thread free in case you want to do something else meanwhile, e.g. profiling the GPU memory - // // VERY IMPORTANT NOTE: if OpenCV is compiled with Qt support, this option will not work. Qt needs the main thread to - // // plot visual results, so the final GUI (which uses OpenCV) would return an exception similar to: + // // Option b) Keeping this thread free in case you want to do something else meanwhile, e.g. profiling the GPU + // memory + // // VERY IMPORTANT NOTE: if OpenCV is compiled with Qt support, this option will not work. Qt needs the main + // // thread to plot visual results, so the final GUI (which uses OpenCV) would return an exception similar to: // // `QMetaMethod::invoke: Unable to invoke methods with return values in queued connections` // // Start threads // opWrapper.start(); @@ -261,8 +272,10 @@ int openPoseDemo() // Measuring total time const auto now = std::chrono::high_resolution_clock::now(); - const auto totalTimeSec = (double)std::chrono::duration_cast(now-timerBegin).count() * 1e-9; - const auto message = "Real-time pose estimation demo successfully finished. Total time: " + std::to_string(totalTimeSec) + " seconds."; + const auto totalTimeSec = (double)std::chrono::duration_cast(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::High); return 0; diff --git a/examples/tests/handFromJsonTest.cpp b/examples/tests/handFromJsonTest.cpp index 50996ed2..34a1dc1e 100644 --- a/examples/tests/handFromJsonTest.cpp +++ b/examples/tests/handFromJsonTest.cpp @@ -75,7 +75,8 @@ int handFromJsonTest() // Measuring total time const auto now = std::chrono::high_resolution_clock::now(); - const auto totalTimeSec = (double)std::chrono::duration_cast(now-timerBegin).count() * 1e-9; + const auto totalTimeSec = (double)std::chrono::duration_cast(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::High); diff --git a/examples/tutorial_add_module/1_custom_post_processing.cpp b/examples/tutorial_add_module/1_custom_post_processing.cpp new file mode 100644 index 00000000..d2db43e5 --- /dev/null +++ b/examples/tutorial_add_module/1_custom_post_processing.cpp @@ -0,0 +1,290 @@ +// ------------------------- OpenPose Library Tutorial - Adding Module - Example 1 - Custom Post Processing ------------------------- +// Purpose of this example +// To create a class in OpenPose format so it can be later added to the library. + +// How to use? +// 1. `userPostProcessing.hpp`: Implement your custom functionality there. +// 2. `wUserPostProcessing.hpp`: Change 1 line in `work(TDatums& tDatums)` to use your custom function from +// `userPostProcessing.hpp`. +// 3. `userDatum.hpp`: Add any required output of your post-processing class there. +// 4. `1_custom_post_processing.cpp`: Change 1 line, when creating the `UserPostProcessing` class, add any specific +// arguments/parameters than your class need. +// 5. `1_custom_post_processing.bin`: Compile and run this file (as you usually run the OpenPose demo) in order to +// test your custom functionality. + +// Syntax rules +// 1. Class/template variables start by up (unique_ptr), sp (sahred_ptr), p (pointer) or m (non-pointer), and they +// have no underscores, e.g.: mThisIsAVariable. +// 2. The internal temporary function variable equivalent would be thisIsAVariable. +// 3. Every line cannot have more than 120 characters. +// 4. If extra classes and files are required, add those extra files inside the OpenPose include and src folders, +// under a new folder (i.e. `include/newMethod/` and `src/newMethod/`), including `namespace op` on those files. + +// This example is a sub-case of `tutorial_wrapper/2_user_synchronous.cpp`, where only custom post-processing is +// considered. + +// C++ std library dependencies +#include // `std::chrono::` functions and classes, e.g. std::chrono::milliseconds +#include // std::this_thread +// Other 3rdparty dependencies +// GFlags: DEFINE_bool, _int32, _int64, _uint64, _double, _string +#include +// Allow Google Flags in Ubuntu 14 +#ifndef GFLAGS_GFLAGS_H_ + namespace gflags = google; +#endif +// OpenPose dependencies +#include +#include "userDatum.hpp" +#include "wUserPostProcessing.hpp" + +// See all the available parameter options withe the `--help` flag. E.g. `build/examples/openpose/openpose.bin --help` +// Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose +// executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. +// Debugging +DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() message, while" + " 255 will not output any. Current OpenPose library messages are in the range 0-4: 1 for" + " low priority messages and 4 for important ones."); +// Producer +DEFINE_int32(camera, -1, "The camera index for cv::VideoCapture. Integer in the range [0, 9]. Select a negative" + " number (by default), to auto-detect and open the first available camera."); +DEFINE_string(camera_resolution, "1280x720", "Size of the camera frames to ask for."); +DEFINE_double(camera_fps, 30.0, "Frame rate for the webcam (only used when saving video from webcam). Set this value to the" + " minimum value between the OpenPose displayed speed and the webcam real frame rate."); +DEFINE_string(video, "", "Use a video file instead of the camera. Use `examples/media/video.avi` for our default" + " example video."); +DEFINE_string(image_dir, "", "Process a directory of images. Use `examples/media/` for our default example folder with 20" + " images. Read all standard formats (jpg, png, bmp, etc.)."); +DEFINE_string(ip_camera, "", "String with the IP camera URL. It supports protocols like RTSP and HTTP."); +DEFINE_uint64(frame_first, 0, "Start on desired frame number. Indexes are 0-based, i.e. the first frame has index 0."); +DEFINE_uint64(frame_last, -1, "Finish on desired frame number. Select -1 to disable. Indexes are 0-based, e.g. if set to" + " 10, it will process 11 frames (0-10)."); +DEFINE_bool(frame_flip, false, "Flip/mirror each frame (e.g. for real time webcam demonstrations)."); +DEFINE_int32(frame_rotate, 0, "Rotate each frame, 4 possible values: 0, 90, 180, 270."); +DEFINE_bool(frames_repeat, false, "Repeat frames when finished."); +DEFINE_bool(process_real_time, false, "Enable to keep the original source frame rate (e.g. for video). If the processing time is" + " too long, it will skip frames. If it is too fast, it will slow it down."); +// OpenPose +DEFINE_string(model_folder, "models/", "Folder path (absolute or relative) where the models (pose, face, ...) are located."); +DEFINE_string(output_resolution, "-1x-1", "The image resolution (display and output). Use \"-1x-1\" to force the program to use the" + " input image resolution."); +DEFINE_int32(num_gpu, -1, "The number of GPU devices to use. If negative, it will use all the available GPUs in your" + " machine."); +DEFINE_int32(num_gpu_start, 0, "GPU device start number."); +DEFINE_int32(keypoint_scale, 0, "Scaling of the (x,y) coordinates of the final pose data array, i.e. the scale of the (x,y)" + " coordinates that will be saved with the `write_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 `scale_number` and `scale_gap`."); +// OpenPose Body Pose +DEFINE_bool(body_disable, false, "Disable body keypoint detection. Option only possible for faster (but less accurate) face" + " keypoint detection."); +DEFINE_string(model_pose, "COCO", "Model to be used. E.g. `COCO` (18 keypoints), `MPI` (15 keypoints, ~10% faster), " + "`MPI_4_layers` (15 keypoints, even faster but less accurate)."); +DEFINE_string(net_resolution, "656x368", "Multiples of 16. If it is increased, the accuracy potentially increases. If it is" + " decreased, the speed increases. For maximum speed-accuracy balance, it should keep the" + " closest aspect ratio possible to the images or videos to be processed. Using `-1` in" + " any of the dimensions, OP will choose the optimal aspect ratio depending on the user's" + " input value. E.g. the default `-1x368` is equivalent to `656x368` in 16:9 resolutions," + " e.g. full HD (1980x1080) and HD (1280x720) resolutions."); +DEFINE_int32(scale_number, 1, "Number of scales to average."); +DEFINE_double(scale_gap, 0.3, "Scale gap between scales. No effect unless scale_number > 1. Initial scale is always 1." + " If you want to change the initial scale, you actually want to multiply the" + " `net_resolution` by your desired initial scale."); +DEFINE_bool(heatmaps_add_parts, false, "If true, it will add the body part heatmaps to the final op::Datum::poseHeatMaps array," + " and analogously face & hand heatmaps to op::Datum::faceHeatMaps & op::Datum::handHeatMaps" + " (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]."); +// OpenPose Face +DEFINE_bool(face, false, "Enables face keypoint detection. It will share some parameters from the body pose, e.g." + " `model_folder`. Note that this will considerable slow down the performance and increse" + " the required GPU memory. In addition, the greater number of people on the image, the" + " slower OpenPose will be."); +DEFINE_string(face_net_resolution, "368x368", "Multiples of 16 and squared. Analogous to `net_resolution` but applied to the face keypoint" + " detector. 320x320 usually works fine while giving a substantial speed up when multiple" + " faces on the image."); +// OpenPose Hand +DEFINE_bool(hand, false, "Enables hand keypoint detection. It will share some parameters from the body pose, e.g." + " `model_folder`. Analogously to `--face`, it will also slow down the performance, increase" + " the required GPU memory and its speed depends on the number of people."); +DEFINE_string(hand_net_resolution, "368x368", "Multiples of 16 and squared. Analogous to `net_resolution` but applied to the hand keypoint" + " detector."); +DEFINE_int32(hand_scale_number, 1, "Analogous to `scale_number` but applied to the hand keypoint detector. Our best results" + " were found with `hand_scale_number` = 6 and `hand_scale_range` = 0.4"); +DEFINE_double(hand_scale_range, 0.4, "Analogous purpose than `scale_gap` but applied to the hand keypoint detector. Total range" + " between smallest and biggest scale. The scales will be centered in ratio 1. E.g. if" + " scaleRange = 0.4 and scalesNumber = 2, then there will be 2 scales, 0.8 and 1.2."); +DEFINE_bool(hand_tracking, false, "Adding hand tracking might improve hand keypoints detection for webcam (if the frame rate" + " is high enough, i.e. >7 FPS per GPU) and video. This is not person ID tracking, it" + " simply looks for hands in positions at which hands were located in previous frames, but" + " it does not guarantee the same person ID among frames"); +// OpenPose Rendering +DEFINE_int32(part_to_show, 0, "Prediction channel to visualize (default: 0). 0 for all the body parts, 1-18 for each body" + " part heat map, 19 for the background heat map, 20 for all the body part heat maps" + " together, 21 for all the PAFs, 22-40 for each body part pair PAF"); +DEFINE_bool(disable_blending, false, "If enabled, it will render the results (keypoint skeletons or heatmaps) on a black" + " background, instead of being rendered into the original image. Related: `part_to_show`," + " `alpha_pose`, and `alpha_pose`."); +// OpenPose Rendering Pose +DEFINE_double(render_threshold, 0.05, "Only estimated keypoints whose score confidences are higher than this threshold will be" + " rendered. Generally, a high threshold (> 0.5) will only render very clear body parts;" + " while small thresholds (~0.1) will also output guessed and occluded keypoints, but also" + " more false positives (i.e. wrong detections)."); +DEFINE_int32(render_pose, 2, "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_double(face_render_threshold, 0.4, "Analogous to `render_threshold`, but applied to the face keypoints."); +DEFINE_int32(face_render, -1, "Analogous to `render_pose` but applied to the face. Extra option: -1 to use the same" + " configuration that `render_pose` is using."); +DEFINE_double(face_alpha_pose, 0.6, "Analogous to `alpha_pose` but applied to face."); +DEFINE_double(face_alpha_heatmap, 0.7, "Analogous to `alpha_heatmap` but applied to face."); +// OpenPose Rendering Hand +DEFINE_double(hand_render_threshold, 0.2, "Analogous to `render_threshold`, but applied to the hand keypoints."); +DEFINE_int32(hand_render, -1, "Analogous to `render_pose` but applied to the hand. Extra option: -1 to use the same" + " configuration that `render_pose` is using."); +DEFINE_double(hand_alpha_pose, 0.6, "Analogous to `alpha_pose` but applied to hand."); +DEFINE_double(hand_alpha_heatmap, 0.7, "Analogous to `alpha_heatmap` but applied to hand."); +// Display +DEFINE_bool(fullscreen, false, "Run in full-screen mode (press f during runtime to toggle)."); +DEFINE_bool(no_gui_verbose, false, "Do not write text on output images on GUI (e.g. number of current frame and people). It" + " does not affect the pose rendering."); +DEFINE_bool(no_display, false, "Do not open a display window. Useful if there is no X server and/or to slightly speed up" + " the processing if visual output is not required."); +// 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. Set 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 body pose heatmaps in *.png format. At least 1 `add_heatmaps_X` flag" + " must be enabled."); +DEFINE_string(write_heatmaps_format, "png", "File extension and format for `write_heatmaps`, analogous to `write_images_format`." + " Recommended `png` or any compressed and lossless format."); + +int openPoseTutorialWrapper4() +{ + // logging_level + op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", + __LINE__, __FUNCTION__, __FILE__); + op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level); + // op::ConfigureLog::setPriorityThreshold(op::Priority::None); // To print all logging messages + + op::log("Starting pose estimation demo.", op::Priority::High); + const auto timerBegin = std::chrono::high_resolution_clock::now(); + + // Applying user defined configuration - Google flags to program variables + // outputSize + const auto outputSize = op::flagsToPoint(FLAGS_output_resolution, "-1x-1"); + // netInputSize + const auto netInputSize = op::flagsToPoint(FLAGS_net_resolution, "-1x368"); + // faceNetInputSize + const auto faceNetInputSize = op::flagsToPoint(FLAGS_face_net_resolution, "368x368 (multiples of 16)"); + // handNetInputSize + const auto handNetInputSize = op::flagsToPoint(FLAGS_hand_net_resolution, "368x368 (multiples of 16)"); + // producerType + const auto producerSharedPtr = op::flagsToProducer(FLAGS_image_dir, FLAGS_video, FLAGS_ip_camera, FLAGS_camera, + FLAGS_camera_resolution, FLAGS_camera_fps); + // poseModel + const auto poseModel = op::flagsToPoseModel(FLAGS_model_pose); + // keypointScale + const auto keypointScale = op::flagsToScaleMode(FLAGS_keypoint_scale); + // heatmaps to add + const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg, + FLAGS_heatmaps_add_PAFs); + // Enabling Google Logging + const bool enableGoogleLogging = true; + // Logging + op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__); + + // OpenPose wrapper + op::log("Configuring OpenPose wrapper.", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__); + op::Wrapper> opWrapper; + // Pose configuration (use WrapperStructPose{} for default and recommended configuration) + const op::WrapperStructPose wrapperStructPose{!FLAGS_body_disable, netInputSize, outputSize, keypointScale, + FLAGS_num_gpu, FLAGS_num_gpu_start, FLAGS_scale_number, + (float)FLAGS_scale_gap, op::flagsToRenderMode(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, + (float)FLAGS_render_threshold, enableGoogleLogging}; + // Face configuration (use op::WrapperStructFace{} to disable it) + const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, + op::flagsToRenderMode(FLAGS_face_render, FLAGS_render_pose), + (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, + (float)FLAGS_face_render_threshold}; + // Hand configuration (use op::WrapperStructHand{} to disable it) + const op::WrapperStructHand wrapperStructHand{FLAGS_hand, handNetInputSize, FLAGS_hand_scale_number, + (float)FLAGS_hand_scale_range, FLAGS_hand_tracking, + op::flagsToRenderMode(FLAGS_hand_render, FLAGS_render_pose), + (float)FLAGS_hand_alpha_pose, (float)FLAGS_hand_alpha_heatmap, + (float)FLAGS_hand_render_threshold}; + // 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}; + // 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, + FLAGS_write_heatmaps, FLAGS_write_heatmaps_format}; + + // Custom post-processing + auto userPostProcessing = std::make_shared(/* Your class arguments here */); + auto wUserPostProcessing = std::make_shared>>>( + userPostProcessing + ); + // Add custom processing + const auto workerProcessingOnNewThread = false; + opWrapper.setWorkerPostProcessing(wUserPostProcessing, workerProcessingOnNewThread); + + // Configure wrapper + opWrapper.configure(wrapperStructPose, wrapperStructFace, wrapperStructHand, wrapperStructInput, + wrapperStructOutput); + // Set to single-thread running (e.g. for debugging purposes) + // opWrapper.disableMultiThreading(); + + op::log("Starting thread(s)", op::Priority::High); + // Two different ways of running the program on multithread environment + // Start, run & stop threads + opWrapper.exec(); // It blocks this thread until all threads have finished + + // Measuring total time + const auto now = std::chrono::high_resolution_clock::now(); + const auto totalTimeSec = (double)std::chrono::duration_cast(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::High); + + return 0; +} + +int main(int argc, char *argv[]) +{ + // Parsing command line flags + gflags::ParseCommandLineFlags(&argc, &argv, true); + + // Running openPoseTutorialWrapper4 + return openPoseTutorialWrapper4(); +} diff --git a/examples/tutorial_add_module/userDatum.hpp b/examples/tutorial_add_module/userDatum.hpp new file mode 100644 index 00000000..e5857e64 --- /dev/null +++ b/examples/tutorial_add_module/userDatum.hpp @@ -0,0 +1,24 @@ +#ifndef OPENPOSE_TUTORIAL_USER_DATUM_HPP +#define OPENPOSE_TUTORIAL_USER_DATUM_HPP + +#include // cv::Mat +#include +#include + +namespace op +{ + // If the user needs his own variables to be shared accross Worker classes, he can directly add them here. + struct UserDatum : public Datum + { + /** + * Description of your variable. + */ + bool boolThatUserNeedsForSomeReason; + + UserDatum() {}; + + virtual ~UserDatum(){}; + }; +} + +#endif // OPENPOSE_TUTORIAL_USER_DATUM_HPP diff --git a/examples/tutorial_add_module/userPostProcessing.hpp b/examples/tutorial_add_module/userPostProcessing.hpp new file mode 100644 index 00000000..befabeab --- /dev/null +++ b/examples/tutorial_add_module/userPostProcessing.hpp @@ -0,0 +1,87 @@ +#ifndef OPENPOSE_EXAMPLES_TUTORIAL_USER_POST_PROCESSING_HPP +#define OPENPOSE_EXAMPLES_TUTORIAL_USER_POST_PROCESSING_HPP + +#include +#include + +namespace op +{ + /** + * Add your class description here. + */ + class UserPostProcessing + { + public: + /** + * Add your constructor description here. + */ + UserPostProcessing(); + + /** + * Add your initializationOnThread description here. + * This is equivalent to the constructor, but it is run in the thread where this function will operate + */ + void initializationOnThread(); + + /** + * Add your information about what your class does and their inputs/outputs. + * @param output is the modified cv::Mat. + * @param input is the input cv::Mat. + * @return If it is not void, add returning information here. + */ + void doSomething(cv::Mat& output, const cv::Mat& input); + + private: + /** + * Description of your variable here. + */ + // bool mSomeVariableHere; + }; +} + + + + + +// Implementation +namespace op +{ + UserPostProcessing::UserPostProcessing() + { + try + { + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + void UserPostProcessing::initializationOnThread() + { + try + { + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + void UserPostProcessing::doSomething(cv::Mat& output, const cv::Mat& input) + { + try + { + // Random operation on data + cv::bitwise_not(input, output); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + // COMPILE_TEMPLATE_DATUM(UserPostProcessing); +} + +#endif // OPENPOSE_EXAMPLES_TUTORIAL_USER_POST_PROCESSING_HPP diff --git a/examples/tutorial_add_module/wUserPostProcessing.hpp b/examples/tutorial_add_module/wUserPostProcessing.hpp new file mode 100644 index 00000000..79a62d45 --- /dev/null +++ b/examples/tutorial_add_module/wUserPostProcessing.hpp @@ -0,0 +1,80 @@ +#ifndef OPENPOSE_EXAMPLES_TUTORIAL_W_USER_POST_PROCESSING_HPP +#define OPENPOSE_EXAMPLES_TUTORIAL_W_USER_POST_PROCESSING_HPP + +#include +#include +#include +#include "userPostProcessing.hpp" + +namespace op +{ + template + class WUserPostProcessing : public Worker + { + public: + WUserPostProcessing(const std::shared_ptr& userPostProcessing); + + void initializationOnThread(); + + void work(TDatums& tDatums); + + private: + std::shared_ptr spUserPostProcessing; + + DELETE_COPY(WUserPostProcessing); + }; +} + + + + + +// Implementation +#include +namespace op +{ + template + WUserPostProcessing::WUserPostProcessing(const std::shared_ptr& userPostProcessing) : + spUserPostProcessing{userPostProcessing} + { + } + + template + void WUserPostProcessing::initializationOnThread() + { + } + + template + void WUserPostProcessing::work(TDatums& tDatums) + { + try + { + if (checkNoNullNorEmpty(tDatums)) + { + // Debugging log + dLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + // Profiling speed + const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); + for (auto& datum : *tDatums) + // THIS IS THE ONLY LINE THAT THE USER MUST MODIFY ON THIS HPP FILE, by using the proper function + // and datum elements + spUserPostProcessing->doSomething(datum.cvOutputData, datum.cvOutputData); + // Profiling speed + Profiler::timerEnd(profilerKey); + Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); + // Debugging log + dLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); + } + } + catch (const std::exception& e) + { + this->stop(); + tDatums = nullptr; + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + // COMPILE_TEMPLATE_DATUM(WUserPostProcessing); +} + +#endif // OPENPOSE_EXAMPLES_TUTORIAL_W_USER_POST_PROCESSING_HPP diff --git a/examples/tutorial_pose/1_extract_from_image.cpp b/examples/tutorial_pose/1_extract_from_image.cpp index 3c3b93b2..e2ca457a 100644 --- a/examples/tutorial_pose/1_extract_from_image.cpp +++ b/examples/tutorial_pose/1_extract_from_image.cpp @@ -22,7 +22,7 @@ #include #include -// See all the available parameter options withe the `--help` flag. E.g. `./build/examples/openpose/openpose.bin --help`. +// See all the available parameter options withe the `--help` flag. E.g. `build/examples/openpose/openpose.bin --help` // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging diff --git a/examples/tutorial_pose/2_extract_pose_or_heatmat_from_image.cpp b/examples/tutorial_pose/2_extract_pose_or_heatmat_from_image.cpp index d2712afc..2a9f684a 100644 --- a/examples/tutorial_pose/2_extract_pose_or_heatmat_from_image.cpp +++ b/examples/tutorial_pose/2_extract_pose_or_heatmat_from_image.cpp @@ -22,7 +22,7 @@ #include #include -// See all the available parameter options withe the `--help` flag. E.g. `./build/examples/openpose/openpose.bin --help`. +// See all the available parameter options withe the `--help` flag. E.g. `build/examples/openpose/openpose.bin --help` // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging diff --git a/examples/tutorial_thread/1_openpose_read_and_display.cpp b/examples/tutorial_thread/1_openpose_read_and_display.cpp index 6616ecce..29871e5b 100644 --- a/examples/tutorial_thread/1_openpose_read_and_display.cpp +++ b/examples/tutorial_thread/1_openpose_read_and_display.cpp @@ -21,7 +21,7 @@ #include #include -// See all the available parameter options withe the `--help` flag. E.g. `./build/examples/openpose/openpose.bin --help`. +// See all the available parameter options withe the `--help` flag. E.g. `build/examples/openpose/openpose.bin --help` // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging @@ -54,7 +54,8 @@ int openPoseTutorialThread1() // Step 1 - Set logging level // - 0 will output all the logging messages // - 255 will output nothing - op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", __LINE__, __FUNCTION__, __FILE__); + op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", + __LINE__, __FUNCTION__, __FILE__); op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level); // Step 2 - Read Google flags (user defined configuration) // outputSize @@ -86,8 +87,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) @@ -116,8 +117,8 @@ int openPoseTutorialThread1() // Option a) Using the main thread (this thread) for processing (it saves 1 thread, recommended) threadManager.exec(); // It blocks this thread until all threads have finished // Option b) Giving to the user the control of this thread - // // VERY IMPORTANT NOTE: if OpenCV is compiled with Qt support, this option will not work. Qt needs the main thread to - // // plot visual results, so the final GUI (which uses OpenCV) would return an exception similar to: + // // VERY IMPORTANT NOTE: if OpenCV is compiled with Qt support, this option will not work. Qt needs the main + // // thread to plot visual results, so the final GUI (which uses OpenCV) would return an exception similar to: // // `QMetaMethod::invoke: Unable to invoke methods with return values in queued connections` // // Start threads // threadManager.start(); diff --git a/examples/tutorial_thread/2_user_processing_function.cpp b/examples/tutorial_thread/2_user_processing_function.cpp index 96df72fc..2f0c0b61 100644 --- a/examples/tutorial_thread/2_user_processing_function.cpp +++ b/examples/tutorial_thread/2_user_processing_function.cpp @@ -22,7 +22,7 @@ #include #include -// See all the available parameter options withe the `--help` flag. E.g. `./build/examples/openpose/openpose.bin --help`. +// See all the available parameter options withe the `--help` flag. E.g. `build/examples/openpose/openpose.bin --help` // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging @@ -88,7 +88,8 @@ int openPoseTutorialThread2() // Step 1 - Set logging level // - 0 will output all the logging messages // - 255 will output nothing - op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", __LINE__, __FUNCTION__, __FILE__); + op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", + __LINE__, __FUNCTION__, __FILE__); op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level); // Step 2 - Read Google flags (user defined configuration) // outputSize @@ -122,8 +123,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) @@ -158,8 +159,8 @@ int openPoseTutorialThread2() // Option a) Using the main thread (this thread) for processing (it saves 1 thread, recommended) threadManager.exec(); // It blocks this thread until all threads have finished // Option b) Giving to the user the control of this thread - // // VERY IMPORTANT NOTE: if OpenCV is compiled with Qt support, this option will not work. Qt needs the main thread to - // // plot visual results, so the final GUI (which uses OpenCV) would return an exception similar to: + // // VERY IMPORTANT NOTE: if OpenCV is compiled with Qt support, this option will not work. Qt needs the main + // // thread to plot visual results, so the final GUI (which uses OpenCV) would return an exception similar to: // // `QMetaMethod::invoke: Unable to invoke methods with return values in queued connections` // // Start threads // threadManager.start(); diff --git a/examples/tutorial_thread/3_user_input_processing_and_output.cpp b/examples/tutorial_thread/3_user_input_processing_and_output.cpp index 8507de3c..60bbcf6d 100644 --- a/examples/tutorial_thread/3_user_input_processing_and_output.cpp +++ b/examples/tutorial_thread/3_user_input_processing_and_output.cpp @@ -27,7 +27,7 @@ // #include // #include -// See all the available parameter options withe the `--help` flag. E.g. `./build/examples/openpose/openpose.bin --help`. +// See all the available parameter options withe the `--help` flag. E.g. `build/examples/openpose/openpose.bin --help` // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging @@ -49,7 +49,8 @@ class WUserInput : public op::WorkerProducer{"jpg", "png"})}, // If we want "jpg" + "png" images + // If we want "jpg" + "png" images + // mImageFiles{op::getFilesOnDirectory(directoryPath, std::vector{"jpg", "png"})}, mCounter{0} { if (mImageFiles.empty()) @@ -65,8 +66,10 @@ public: // Close program when empty frame if (mImageFiles.size() <= mCounter) { - op::log("Last frame read and added to queue. Closing program after it is processed.", op::Priority::High); - // This funtion stops this worker, which will eventually stop the whole thread system once all the frames have been processed + op::log("Last frame read and added to queue. Closing program after it is processed.", + op::Priority::High); + // This funtion stops this worker, which will eventually stop the whole thread system once all the + // frames have been processed this->stop(); return nullptr; } @@ -83,7 +86,8 @@ public: // If empty frame -> return nullptr if (datum.cvInputData.empty()) { - op::log("Empty frame detected on path: " + mImageFiles.at(mCounter-1) + ". Closing program.", op::Priority::High); + op::log("Empty frame detected on path: " + mImageFiles.at(mCounter-1) + ". Closing program.", + op::Priority::High); this->stop(); datumsPtr = nullptr; } @@ -152,7 +156,8 @@ public: if (datumsPtr != nullptr && !datumsPtr->empty()) { cv::imshow("User worker GUI", datumsPtr->at(0).cvOutputData); - cv::waitKey(1); // It displays the image and sleeps at least 1 ms (it usually sleeps ~5-10 msec to display the image) + // It displays the image and sleeps at least 1 ms (it usually sleeps ~5-10 msec to display the image) + cv::waitKey(1); } } catch (const std::exception& e) @@ -171,7 +176,8 @@ int openPoseTutorialThread3() // Step 1 - Set logging level // - 0 will output all the logging messages // - 255 will output nothing - op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", __LINE__, __FUNCTION__, __FILE__); + op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", + __LINE__, __FUNCTION__, __FILE__); op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level); // Step 2 - Setting thread workers && manager typedef std::shared_ptr> TypedefDatums; @@ -188,8 +194,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) @@ -206,8 +212,8 @@ int openPoseTutorialThread3() // Option a) Using the main thread (this thread) for processing (it saves 1 thread, recommended) threadManager.exec(); // It blocks this thread until all threads have finished // Option b) Giving to the user the control of this thread - // // VERY IMPORTANT NOTE: if OpenCV is compiled with Qt support, this option will not work. Qt needs the main thread to - // // plot visual results, so the final GUI (which uses OpenCV) would return an exception similar to: + // // VERY IMPORTANT NOTE: if OpenCV is compiled with Qt support, this option will not work. Qt needs the main + // // thread to plot visual results, so the final GUI (which uses OpenCV) would return an exception similar to: // // `QMetaMethod::invoke: Unable to invoke methods with return values in queued connections` // // Start threads // threadManager.start(); diff --git a/examples/tutorial_thread/4_user_input_processing_output_and_datum.cpp b/examples/tutorial_thread/4_user_input_processing_output_and_datum.cpp index 2e6bf618..c226fc6a 100644 --- a/examples/tutorial_thread/4_user_input_processing_output_and_datum.cpp +++ b/examples/tutorial_thread/4_user_input_processing_output_and_datum.cpp @@ -27,7 +27,7 @@ // #include // #include -// See all the available parameter options withe the `--help` flag. E.g. `./build/examples/openpose/openpose.bin --help`. +// See all the available parameter options withe the `--help` flag. E.g. `build/examples/openpose/openpose.bin --help` // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging @@ -41,8 +41,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 instead of -// Wrapper +// UserDatum can be directly used by the OpenPose wrapper because it inherits from op::Datum, just define +// Wrapper instead of Wrapper struct UserDatum : public op::Datum { bool boolThatUserNeedsForSomeReason; @@ -62,7 +62,8 @@ class WUserInput : public op::WorkerProducer{"jpg", "png"})}, // If we want "jpg" + "png" images + // If we want "jpg" + "png" images + // mImageFiles{op::getFilesOnDirectory(directoryPath, std::vector{"jpg", "png"})}, mCounter{0} { if (mImageFiles.empty()) @@ -78,8 +79,10 @@ public: // Close program when empty frame if (mImageFiles.size() <= mCounter) { - op::log("Last frame read and added to queue. Closing program after it is processed.", op::Priority::High); - // This funtion stops this worker, which will eventually stop the whole thread system once all the frames have been processed + op::log("Last frame read and added to queue. Closing program after it is processed.", + op::Priority::High); + // This funtion stops this worker, which will eventually stop the whole thread system once all the + // frames have been processed this->stop(); return nullptr; } @@ -96,7 +99,8 @@ public: // If empty frame -> return nullptr if (datum.cvInputData.empty()) { - op::log("Empty frame detected on path: " + mImageFiles.at(mCounter-1) + ". Closing program.", op::Priority::High); + op::log("Empty frame detected on path: " + mImageFiles.at(mCounter-1) + ". Closing program.", + op::Priority::High); this->stop(); datumsPtr = nullptr; } @@ -165,7 +169,8 @@ public: if (datumsPtr != nullptr && !datumsPtr->empty()) { cv::imshow("User worker GUI", datumsPtr->at(0).cvOutputData); - cv::waitKey(1); // It displays the image and sleeps at least 1 ms (it usually sleeps ~5-10 msec to display the image) + // It displays the image and sleeps at least 1 ms (it usually sleeps ~5-10 msec to display the image) + cv::waitKey(1); } } catch (const std::exception& e) @@ -184,7 +189,8 @@ int openPoseTutorialThread4() // Step 1 - Set logging level // - 0 will output all the logging messages // - 255 will output nothing - op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", __LINE__, __FUNCTION__, __FILE__); + op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", + __LINE__, __FUNCTION__, __FILE__); op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level); // Step 2 - Setting thread workers && manager typedef std::shared_ptr> TypedefDatums; @@ -201,8 +207,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) @@ -219,8 +225,8 @@ int openPoseTutorialThread4() // Option a) Using the main thread (this thread) for processing (it saves 1 thread, recommended) threadManager.exec(); // It blocks this thread until all threads have finished // Option b) Giving to the user the control of this thread - // // VERY IMPORTANT NOTE: if OpenCV is compiled with Qt support, this option will not work. Qt needs the main thread to - // // plot visual results, so the final GUI (which uses OpenCV) would return an exception similar to: + // // VERY IMPORTANT NOTE: if OpenCV is compiled with Qt support, this option will not work. Qt needs the main + // // thread to plot visual results, so the final GUI (which uses OpenCV) would return an exception similar to: // // `QMetaMethod::invoke: Unable to invoke methods with return values in queued connections` // // Start threads // threadManager.start(); diff --git a/examples/tutorial_wrapper/1_user_asynchronous_output.cpp b/examples/tutorial_wrapper/1_user_asynchronous_output.cpp index 8ce9bde7..26f484d3 100644 --- a/examples/tutorial_wrapper/1_user_asynchronous_output.cpp +++ b/examples/tutorial_wrapper/1_user_asynchronous_output.cpp @@ -1,4 +1,4 @@ -// ------------------------- OpenPose Library Tutorial - Thread - Example 3 - Asynchronous Output ------------------------- +// ------------------------- OpenPose Library Tutorial - Wrapper - Example 3 - Asynchronous Output ------------------------- // Asynchronous output mode: ideal for fast prototyping when performance is not an issue and user wants to use the output OpenPose format. The user // simply gets the processed frames from the OpenPose wrapper when he desires to. @@ -28,7 +28,7 @@ // OpenPose dependencies #include -// See all the available parameter options withe the `--help` flag. E.g. `./build/examples/openpose/openpose.bin --help`. +// See all the available parameter options withe the `--help` flag. E.g. `build/examples/openpose/openpose.bin --help` // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging @@ -112,7 +112,6 @@ DEFINE_int32(hand_scale_number, 1, "Analogous to `scale_num DEFINE_double(hand_scale_range, 0.4, "Analogous purpose than `scale_gap` but applied to the hand keypoint detector. Total range" " between smallest and biggest scale. The scales will be centered in ratio 1. E.g. if" " scaleRange = 0.4 and scalesNumber = 2, then there will be 2 scales, 0.8 and 1.2."); - DEFINE_bool(hand_tracking, false, "Adding hand tracking might improve hand keypoints detection for webcam (if the frame rate" " is high enough, i.e. >7 FPS per GPU) and video. This is not person ID tracking, it" " simply looks for hands in positions at which hands were located in previous frames, but" @@ -167,8 +166,8 @@ DEFINE_string(write_heatmaps_format, "png", "File extension and form // 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 instead of -// Wrapper +// UserDatum can be directly used by the OpenPose wrapper because it inherits from op::Datum, just define +// Wrapper instead of Wrapper struct UserDatum : public op::Datum { bool boolThatUserNeedsForSomeReason; @@ -257,10 +256,11 @@ public: } }; -int openPoseTutorialWrapper3() +int openPoseTutorialWrapper1() { // logging_level - op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", __LINE__, __FUNCTION__, __FILE__); + op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", + __LINE__, __FUNCTION__, __FILE__); op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level); // op::ConfigureLog::setPriorityThreshold(op::Priority::None); // To print all logging messages @@ -284,10 +284,12 @@ int openPoseTutorialWrapper3() // keypointScale const auto keypointScale = op::flagsToScaleMode(FLAGS_keypoint_scale); // heatmaps to add - const auto heatMapTypes = op::flagsToHeatMaps(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 heatMapTypes = op::flagsToHeatMaps(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 )); + : (FLAGS_heatmaps_scale == 1 ? op::ScaleMode::ZeroToOne : op::ScaleMode::UnsignedChar )); // Enabling Google Logging const bool enableGoogleLogging = true; // Logging @@ -297,23 +299,28 @@ int openPoseTutorialWrapper3() op::log("Configuring OpenPose wrapper.", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__); op::Wrapper> opWrapper{op::ThreadManagerMode::AsynchronousOut}; // Pose configuration (use WrapperStructPose{} for default and recommended configuration) - const op::WrapperStructPose wrapperStructPose{!FLAGS_body_disable, netInputSize, outputSize, keypointScale, FLAGS_num_gpu, - FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap, - op::flagsToRenderMode(FLAGS_render_pose), poseModel, - !FLAGS_disable_blending, (float)FLAGS_alpha_pose, + const op::WrapperStructPose wrapperStructPose{!FLAGS_body_disable, netInputSize, outputSize, keypointScale, + FLAGS_num_gpu, FLAGS_num_gpu_start, FLAGS_scale_number, + (float)FLAGS_scale_gap, op::flagsToRenderMode(FLAGS_render_pose), + poseModel, !FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, FLAGS_model_folder, heatMapTypes, heatMapScale, (float)FLAGS_render_threshold, enableGoogleLogging}; // Face configuration (use op::WrapperStructFace{} to disable it) - const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, op::flagsToRenderMode(FLAGS_face_render, FLAGS_render_pose), - (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold}; + const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, + op::flagsToRenderMode(FLAGS_face_render, FLAGS_render_pose), + (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, + (float)FLAGS_face_render_threshold}; // Hand configuration (use op::WrapperStructHand{} to disable it) - const op::WrapperStructHand wrapperStructHand{FLAGS_hand, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range, - FLAGS_hand_tracking, op::flagsToRenderMode(FLAGS_hand_render, FLAGS_render_pose), - (float)FLAGS_hand_alpha_pose, (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold}; + const op::WrapperStructHand wrapperStructHand{FLAGS_hand, handNetInputSize, FLAGS_hand_scale_number, + (float)FLAGS_hand_scale_range, FLAGS_hand_tracking, + op::flagsToRenderMode(FLAGS_hand_render, FLAGS_render_pose), + (float)FLAGS_hand_alpha_pose, (float)FLAGS_hand_alpha_heatmap, + (float)FLAGS_hand_render_threshold}; // 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 bool displayGui = false; const bool guiVerbose = false; @@ -323,7 +330,8 @@ int openPoseTutorialWrapper3() 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); + opWrapper.configure(wrapperStructPose, wrapperStructFace, wrapperStructHand, wrapperStructInput, + wrapperStructOutput); // Set to single-thread running (e.g. for debugging purposes) // opWrapper.disableMultiThreading(); @@ -351,8 +359,10 @@ int openPoseTutorialWrapper3() // Measuring total time const auto now = std::chrono::high_resolution_clock::now(); - const auto totalTimeSec = (double)std::chrono::duration_cast(now-timerBegin).count() * 1e-9; - const auto message = "Real-time pose estimation demo successfully finished. Total time: " + std::to_string(totalTimeSec) + " seconds."; + const auto totalTimeSec = (double)std::chrono::duration_cast(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::High); return 0; @@ -363,6 +373,6 @@ int main(int argc, char *argv[]) // Parsing command line flags gflags::ParseCommandLineFlags(&argc, &argv, true); - // Running openPoseTutorialWrapper3 - return openPoseTutorialWrapper3(); + // Running openPoseTutorialWrapper1 + return openPoseTutorialWrapper1(); } diff --git a/examples/tutorial_wrapper/2_user_synchronous.cpp b/examples/tutorial_wrapper/2_user_synchronous.cpp index 2a2c4a31..3bd8d004 100644 --- a/examples/tutorial_wrapper/2_user_synchronous.cpp +++ b/examples/tutorial_wrapper/2_user_synchronous.cpp @@ -1,4 +1,4 @@ -// ------------------------- OpenPose Library Tutorial - Thread - Example 2 - Synchronous ------------------------- +// ------------------------- OpenPose Library Tutorial - Wrapper - Example 2 - Synchronous ------------------------- // Synchronous mode: ideal for performance. The user can add his own frames producer / post-processor / consumer to the OpenPose wrapper or use the // default ones. @@ -28,7 +28,7 @@ // OpenPose dependencies #include -// See all the available parameter options withe the `--help` flag. E.g. `./build/examples/openpose/openpose.bin --help`. +// See all the available parameter options withe the `--help` flag. E.g. `build/examples/openpose/openpose.bin --help` // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging @@ -95,7 +95,6 @@ DEFINE_int32(hand_scale_number, 1, "Analogous to `scale_num DEFINE_double(hand_scale_range, 0.4, "Analogous purpose than `scale_gap` but applied to the hand keypoint detector. Total range" " between smallest and biggest scale. The scales will be centered in ratio 1. E.g. if" " scaleRange = 0.4 and scalesNumber = 2, then there will be 2 scales, 0.8 and 1.2."); - DEFINE_bool(hand_tracking, false, "Adding hand tracking might improve hand keypoints detection for webcam (if the frame rate" " is high enough, i.e. >7 FPS per GPU) and video. This is not person ID tracking, it" " simply looks for hands in positions at which hands were located in previous frames, but" @@ -150,8 +149,8 @@ DEFINE_string(write_heatmaps_format, "png", "File extension and form // 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 instead of -// Wrapper +// UserDatum can be directly used by the OpenPose wrapper because it inherits from op::Datum, just define +// Wrapper instead of Wrapper struct UserDatum : public op::Datum { bool boolThatUserNeedsForSomeReason; @@ -171,7 +170,8 @@ class WUserInput : public op::WorkerProducer{"jpg", "png"})}, // If we want "jpg" + "png" images + // If we want "jpg" + "png" images + // mImageFiles{op::getFilesOnDirectory(directoryPath, std::vector{"jpg", "png"})}, mCounter{0} { if (mImageFiles.empty()) @@ -187,8 +187,10 @@ public: // Close program when empty frame if (mImageFiles.size() <= mCounter) { - op::log("Last frame read and added to queue. Closing program after it is processed.", op::Priority::High); - // This funtion stops this worker, which will eventually stop the whole thread system once all the frames have been processed + op::log("Last frame read and added to queue. Closing program after it is processed.", + op::Priority::High); + // This funtion stops this worker, which will eventually stop the whole thread system once all the + // frames have been processed this->stop(); return nullptr; } @@ -205,7 +207,8 @@ public: // If empty frame -> return nullptr if (datum.cvInputData.empty()) { - op::log("Empty frame detected on path: " + mImageFiles.at(mCounter-1) + ". Closing program.", op::Priority::High); + op::log("Empty frame detected on path: " + mImageFiles.at(mCounter-1) + ". Closing program.", + op::Priority::High); this->stop(); datumsPtr = nullptr; } @@ -339,7 +342,8 @@ public: int openPoseTutorialWrapper2() { // logging_level - op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", __LINE__, __FUNCTION__, __FILE__); + op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", + __LINE__, __FUNCTION__, __FILE__); op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level); // op::ConfigureLog::setPriorityThreshold(op::Priority::None); // To print all logging messages @@ -360,10 +364,12 @@ int openPoseTutorialWrapper2() // keypointScale const auto keypointScale = op::flagsToScaleMode(FLAGS_keypoint_scale); // heatmaps to add - const auto heatMapTypes = op::flagsToHeatMaps(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 heatMapTypes = op::flagsToHeatMaps(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 )); + : (FLAGS_heatmaps_scale == 1 ? op::ScaleMode::ZeroToOne : op::ScaleMode::UnsignedChar )); // Enabling Google Logging const bool enableGoogleLogging = true; // Logging @@ -389,20 +395,24 @@ int openPoseTutorialWrapper2() opWrapper.setWorkerOutput(wUserOutput, workerOutputOnNewThread); // Configure OpenPose op::log("Configuring OpenPose wrapper.", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__); - const op::WrapperStructPose wrapperStructPose{!FLAGS_body_disable, netInputSize, outputSize, keypointScale, FLAGS_num_gpu, - FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap, - op::flagsToRenderMode(FLAGS_render_pose), poseModel, - !FLAGS_disable_blending, (float)FLAGS_alpha_pose, + const op::WrapperStructPose wrapperStructPose{!FLAGS_body_disable, netInputSize, outputSize, keypointScale, + FLAGS_num_gpu, FLAGS_num_gpu_start, FLAGS_scale_number, + (float)FLAGS_scale_gap, op::flagsToRenderMode(FLAGS_render_pose), + poseModel, !FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, FLAGS_model_folder, heatMapTypes, heatMapScale, (float)FLAGS_render_threshold, enableGoogleLogging}; // Face configuration (use op::WrapperStructFace{} to disable it) - const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, op::flagsToRenderMode(FLAGS_face_render, FLAGS_render_pose), - (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold}; + const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, + op::flagsToRenderMode(FLAGS_face_render, FLAGS_render_pose), + (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, + (float)FLAGS_face_render_threshold}; // Hand configuration (use op::WrapperStructHand{} to disable it) - const op::WrapperStructHand wrapperStructHand{FLAGS_hand, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range, - FLAGS_hand_tracking, op::flagsToRenderMode(FLAGS_hand_render, FLAGS_render_pose), - (float)FLAGS_hand_alpha_pose, (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold}; + const op::WrapperStructHand wrapperStructHand{FLAGS_hand, handNetInputSize, FLAGS_hand_scale_number, + (float)FLAGS_hand_scale_range, FLAGS_hand_tracking, + op::flagsToRenderMode(FLAGS_hand_render, FLAGS_render_pose), + (float)FLAGS_hand_alpha_pose, (float)FLAGS_hand_alpha_heatmap, + (float)FLAGS_hand_render_threshold}; // Consumer (comment or use default argument to disable any output) const bool displayGui = false; const bool guiVerbose = false; @@ -412,7 +422,8 @@ int openPoseTutorialWrapper2() 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); + opWrapper.configure(wrapperStructPose, wrapperStructFace, wrapperStructHand, op::WrapperStructInput{}, + wrapperStructOutput); // Set to single-thread running (e.g. for debugging purposes) // opWrapper.disableMultiThreading(); @@ -423,8 +434,8 @@ int openPoseTutorialWrapper2() opWrapper.exec(); // It blocks this thread until all threads have finished // Option b) Keeping this thread free in case you want to do something else meanwhile, e.g. profiling the GPU memory - // // VERY IMPORTANT NOTE: if OpenCV is compiled with Qt support, this option will not work. Qt needs the main thread to - // // plot visual results, so the final GUI (which uses OpenCV) would return an exception similar to: + // // VERY IMPORTANT NOTE: if OpenCV is compiled with Qt support, this option will not work. Qt needs the main + // // thread to plot visual results, so the final GUI (which uses OpenCV) would return an exception similar to: // // `QMetaMethod::invoke: Unable to invoke methods with return values in queued connections` // // Start threads // opWrapper.start(); @@ -442,8 +453,10 @@ int openPoseTutorialWrapper2() // Measuring total time const auto now = std::chrono::high_resolution_clock::now(); - const auto totalTimeSec = (double)std::chrono::duration_cast(now-timerBegin).count() * 1e-9; - const auto message = "Real-time pose estimation demo successfully finished. Total time: " + std::to_string(totalTimeSec) + " seconds."; + const auto totalTimeSec = (double)std::chrono::duration_cast(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::High); return 0; diff --git a/examples/tutorial_wrapper/3_user_asynchronous.cpp b/examples/tutorial_wrapper/3_user_asynchronous.cpp index 596f04e8..90a2b619 100644 --- a/examples/tutorial_wrapper/3_user_asynchronous.cpp +++ b/examples/tutorial_wrapper/3_user_asynchronous.cpp @@ -1,4 +1,4 @@ -// ------------------------- OpenPose Library Tutorial - Thread - Example 1 - Asynchronous ------------------------- +// ------------------------- OpenPose Library Tutorial - Wrapper - Example 1 - Asynchronous ------------------------- // Asynchronous mode: ideal for fast prototyping when performance is not an issue. The user emplaces/pushes and pops frames from the OpenPose wrapper // when he desires to. @@ -28,7 +28,7 @@ // OpenPose dependencies #include -// See all the available parameter options withe the `--help` flag. E.g. `./build/examples/openpose/openpose.bin --help`. +// See all the available parameter options withe the `--help` flag. E.g. `build/examples/openpose/openpose.bin --help` // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging @@ -95,7 +95,6 @@ DEFINE_int32(hand_scale_number, 1, "Analogous to `scale_num DEFINE_double(hand_scale_range, 0.4, "Analogous purpose than `scale_gap` but applied to the hand keypoint detector. Total range" " between smallest and biggest scale. The scales will be centered in ratio 1. E.g. if" " scaleRange = 0.4 and scalesNumber = 2, then there will be 2 scales, 0.8 and 1.2."); - DEFINE_bool(hand_tracking, false, "Adding hand tracking might improve hand keypoints detection for webcam (if the frame rate" " is high enough, i.e. >7 FPS per GPU) and video. This is not person ID tracking, it" " simply looks for hands in positions at which hands were located in previous frames, but" @@ -171,7 +170,8 @@ class UserInputClass public: UserInputClass(const std::string& directoryPath) : mImageFiles{op::getFilesOnDirectory(directoryPath, "jpg")}, - // mImageFiles{op::getFilesOnDirectory(directoryPath, std::vector{"jpg", "png"})}, // If we want "jpg" + "png" images + // If we want "jpg" + "png" images + // mImageFiles{op::getFilesOnDirectory(directoryPath, std::vector{"jpg", "png"})}, mCounter{0}, mClosed{false} { @@ -185,7 +185,8 @@ public: if (mClosed || mImageFiles.size() <= mCounter) { op::log("Last frame read and added to queue. Closing program after it is processed.", op::Priority::High); - // This funtion stops this worker, which will eventually stop the whole thread system once all the frames have been processed + // This funtion stops this worker, which will eventually stop the whole thread system once all the frames + // have been processed mClosed = true; return nullptr; } @@ -202,7 +203,8 @@ public: // If empty frame -> return nullptr if (datum.cvInputData.empty()) { - op::log("Empty frame detected on path: " + mImageFiles.at(mCounter-1) + ". Closing program.", op::Priority::High); + op::log("Empty frame detected on path: " + mImageFiles.at(mCounter-1) + ". Closing program.", + op::Priority::High); mClosed = true; datumsPtr = nullptr; } @@ -295,10 +297,11 @@ public: } }; -int openPoseTutorialWrapper1() +int openPoseTutorialWrapper3() { // logging_level - op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", __LINE__, __FUNCTION__, __FILE__); + op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", + __LINE__, __FUNCTION__, __FILE__); op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level); // op::ConfigureLog::setPriorityThreshold(op::Priority::None); // To print all logging messages @@ -319,10 +322,12 @@ int openPoseTutorialWrapper1() // keypointScale const auto keypointScale = op::flagsToScaleMode(FLAGS_keypoint_scale); // heatmaps to add - const auto heatMapTypes = op::flagsToHeatMaps(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 heatMapTypes = op::flagsToHeatMaps(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 )); + : (FLAGS_heatmaps_scale == 1 ? op::ScaleMode::ZeroToOne : op::ScaleMode::UnsignedChar )); // Enabling Google Logging const bool enableGoogleLogging = true; // Logging @@ -331,20 +336,24 @@ int openPoseTutorialWrapper1() // Configure OpenPose op::Wrapper> opWrapper{op::ThreadManagerMode::Asynchronous}; // Pose configuration (use WrapperStructPose{} for default and recommended configuration) - const op::WrapperStructPose wrapperStructPose{!FLAGS_body_disable, netInputSize, outputSize, keypointScale, FLAGS_num_gpu, - FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap, - op::flagsToRenderMode(FLAGS_render_pose), poseModel, - !FLAGS_disable_blending, (float)FLAGS_alpha_pose, + const op::WrapperStructPose wrapperStructPose{!FLAGS_body_disable, netInputSize, outputSize, keypointScale, + FLAGS_num_gpu, FLAGS_num_gpu_start, FLAGS_scale_number, + (float)FLAGS_scale_gap, op::flagsToRenderMode(FLAGS_render_pose), + poseModel, !FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, FLAGS_model_folder, heatMapTypes, heatMapScale, (float)FLAGS_render_threshold, enableGoogleLogging}; // Face configuration (use op::WrapperStructFace{} to disable it) - const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, op::flagsToRenderMode(FLAGS_face_render, FLAGS_render_pose), - (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold}; + const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, + op::flagsToRenderMode(FLAGS_face_render, FLAGS_render_pose), + (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, + (float)FLAGS_face_render_threshold}; // Hand configuration (use op::WrapperStructHand{} to disable it) - const op::WrapperStructHand wrapperStructHand{FLAGS_hand, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range, - FLAGS_hand_tracking, op::flagsToRenderMode(FLAGS_hand_render, FLAGS_render_pose), - (float)FLAGS_hand_alpha_pose, (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold}; + const op::WrapperStructHand wrapperStructHand{FLAGS_hand, handNetInputSize, FLAGS_hand_scale_number, + (float)FLAGS_hand_scale_range, FLAGS_hand_tracking, + op::flagsToRenderMode(FLAGS_hand_render, FLAGS_render_pose), + (float)FLAGS_hand_alpha_pose, (float)FLAGS_hand_alpha_heatmap, + (float)FLAGS_hand_render_threshold}; // Consumer (comment or use default argument to disable any output) const bool displayGui = false; const bool guiVerbose = false; @@ -355,7 +364,8 @@ int openPoseTutorialWrapper1() FLAGS_write_heatmaps, FLAGS_write_heatmaps_format}; // Configure wrapper op::log("Configuring OpenPose wrapper.", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__); - opWrapper.configure(wrapperStructPose, wrapperStructFace, wrapperStructHand, op::WrapperStructInput{}, wrapperStructOutput); + opWrapper.configure(wrapperStructPose, wrapperStructFace, wrapperStructHand, op::WrapperStructInput{}, + wrapperStructOutput); // Set to single-thread running (e.g. for debugging purposes) // opWrapper.disableMultiThreading(); @@ -381,7 +391,8 @@ int openPoseTutorialWrapper1() userOutputClass.printKeypoints(datumProcessed); } else - op::log("Processed datum could not be emplaced.", op::Priority::High, __LINE__, __FUNCTION__, __FILE__); + op::log("Processed datum could not be emplaced.", op::Priority::High, + __LINE__, __FUNCTION__, __FILE__); } } @@ -390,8 +401,10 @@ int openPoseTutorialWrapper1() // Measuring total time const auto now = std::chrono::high_resolution_clock::now(); - const auto totalTimeSec = (double)std::chrono::duration_cast(now-timerBegin).count() * 1e-9; - const auto message = "Real-time pose estimation demo successfully finished. Total time: " + std::to_string(totalTimeSec) + " seconds."; + const auto totalTimeSec = (double)std::chrono::duration_cast(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::High); return 0; @@ -402,6 +415,6 @@ int main(int argc, char *argv[]) // Parsing command line flags gflags::ParseCommandLineFlags(&argc, &argv, true); - // Running openPoseTutorialWrapper1 - return openPoseTutorialWrapper1(); + // Running openPoseTutorialWrapper3 + return openPoseTutorialWrapper3(); } diff --git a/examples_beta/openpose3d/openpose3d.cpp b/examples_beta/openpose3d/openpose3d.cpp index cc9076fd..9e3d8f30 100644 --- a/examples_beta/openpose3d/openpose3d.cpp +++ b/examples_beta/openpose3d/openpose3d.cpp @@ -30,7 +30,7 @@ #include #include -// See all the available parameter options withe the `--help` flag. E.g. `./build/examples/openpose/openpose.bin --help`. +// See all the available parameter options withe the `--help` flag. E.g. `build/examples/openpose/openpose.bin --help` // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging @@ -151,7 +151,8 @@ DEFINE_string(write_heatmaps_format, "png", "File extension and form int openpose3d() { // logging_level - op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", __LINE__, __FUNCTION__, __FILE__); + op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.", + __LINE__, __FUNCTION__, __FILE__); op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level); // op::ConfigureLog::setPriorityThreshold(op::Priority::None); // To print all logging messages @@ -172,10 +173,12 @@ int openpose3d() // keypointScale const auto keypointScale = op::flagsToScaleMode(FLAGS_keypoint_scale); // heatmaps to add - const auto heatMapTypes = op::flagsToHeatMaps(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 heatMapTypes = op::flagsToHeatMaps(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 )); + : (FLAGS_heatmaps_scale == 1 ? op::ScaleMode::ZeroToOne : op::ScaleMode::UnsignedChar )); // Enabling Google Logging const bool enableGoogleLogging = true; // Logging @@ -200,20 +203,24 @@ int openpose3d() const auto workerOutputOnNewThread = true; opWrapper.setWorkerOutput(wRender3D, workerOutputOnNewThread); // Configure OpenPose - const op::WrapperStructPose wrapperStructPose{!FLAGS_body_disable, netInputSize, outputSize, keypointScale, FLAGS_num_gpu, - FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap, - op::flagsToRenderMode(FLAGS_render_pose), poseModel, - !FLAGS_disable_blending, (float)FLAGS_alpha_pose, + const op::WrapperStructPose wrapperStructPose{!FLAGS_body_disable, netInputSize, outputSize, keypointScale, + FLAGS_num_gpu, FLAGS_num_gpu_start, FLAGS_scale_number, + (float)FLAGS_scale_gap, op::flagsToRenderMode(FLAGS_render_pose), + poseModel, !FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, FLAGS_model_folder, heatMapTypes, heatMapScale, (float)FLAGS_render_threshold, enableGoogleLogging}; // Face configuration (use op::WrapperStructFace{} to disable it) - const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, op::flagsToRenderMode(FLAGS_face_render, FLAGS_render_pose), - (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold}; + const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, + op::flagsToRenderMode(FLAGS_face_render, FLAGS_render_pose), + (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, + (float)FLAGS_face_render_threshold}; // Hand configuration (use op::WrapperStructHand{} to disable it) - const op::WrapperStructHand wrapperStructHand{FLAGS_hand, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range, - FLAGS_hand_tracking, op::flagsToRenderMode(FLAGS_hand_render, FLAGS_render_pose), - (float)FLAGS_hand_alpha_pose, (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold}; + const op::WrapperStructHand wrapperStructHand{FLAGS_hand, handNetInputSize, FLAGS_hand_scale_number, + (float)FLAGS_hand_scale_range, FLAGS_hand_tracking, + op::flagsToRenderMode(FLAGS_hand_render, FLAGS_render_pose), + (float)FLAGS_hand_alpha_pose, (float)FLAGS_hand_alpha_heatmap, + (float)FLAGS_hand_render_threshold}; // Consumer (comment or use default argument to disable any output) const bool displayGui = false; const bool guiVerbose = true; @@ -223,7 +230,8 @@ int openpose3d() 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); + opWrapper.configure(wrapperStructPose, wrapperStructFace, wrapperStructHand, op::WrapperStructInput{}, + wrapperStructOutput); // Set to single-thread running (e.g. for debugging purposes) // opWrapper.disableMultiThreading(); @@ -233,8 +241,10 @@ int openpose3d() // Measuring total time const auto now = std::chrono::high_resolution_clock::now(); - const auto totalTimeSec = (double)std::chrono::duration_cast(now-timerBegin).count() * 1e-9; - const auto message = "Real-time pose estimation demo successfully finished. Total time: " + std::to_string(totalTimeSec) + " seconds."; + const auto totalTimeSec = (double)std::chrono::duration_cast(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::High); return 0; diff --git a/windows/OpenPose.sln b/windows/OpenPose.sln index abb83d74..36b90425 100644 --- a/windows/OpenPose.sln +++ b/windows/OpenPose.sln @@ -74,6 +74,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "3_user_asynchronous", "Tuto {1848F100-6EC5-4F60-9748-062590ADFE5C} = {1848F100-6EC5-4F60-9748-062590ADFE5C} EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Adding Module to OpenPose", "Adding Module to OpenPose", "{C6404144-61BC-4402-BA36-FB6BB19BD739}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "1_custom_post_processing", "TutorialAddModule\1_custom_post_processing.vcxproj", "{0CC54804-3AD3-4C81-BE71-8011C72F1E1C}" + ProjectSection(ProjectDependencies) = postProject + {1848F100-6EC5-4F60-9748-062590ADFE5C} = {1848F100-6EC5-4F60-9748-062590ADFE5C} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -152,6 +159,12 @@ Global {6669F592-6798-4F29-853A-A8C42205DE4A}.Release|x64.ActiveCfg = Release|x64 {6669F592-6798-4F29-853A-A8C42205DE4A}.Release|x64.Build.0 = Release|x64 {6669F592-6798-4F29-853A-A8C42205DE4A}.Release|x86.ActiveCfg = Release|x64 + {0CC54804-3AD3-4C81-BE71-8011C72F1E1C}.Debug|x64.ActiveCfg = Debug|x64 + {0CC54804-3AD3-4C81-BE71-8011C72F1E1C}.Debug|x64.Build.0 = Debug|x64 + {0CC54804-3AD3-4C81-BE71-8011C72F1E1C}.Debug|x86.ActiveCfg = Debug|x64 + {0CC54804-3AD3-4C81-BE71-8011C72F1E1C}.Release|x64.ActiveCfg = Release|x64 + {0CC54804-3AD3-4C81-BE71-8011C72F1E1C}.Release|x64.Build.0 = Release|x64 + {0CC54804-3AD3-4C81-BE71-8011C72F1E1C}.Release|x86.ActiveCfg = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -174,5 +187,7 @@ Global {CB5A0F6C-6DD3-4789-9E6F-9B9B51AE4F10} = {48ECEE85-ED06-42A5-8068-CBDD92BB6EF4} {F31BEEF2-37B0-4B0F-85D3-AD427C56AD72} = {CB5A0F6C-6DD3-4789-9E6F-9B9B51AE4F10} {6669F592-6798-4F29-853A-A8C42205DE4A} = {BA0F9599-8099-4A7A-99A3-ACFC7C35639C} + {C6404144-61BC-4402-BA36-FB6BB19BD739} = {48ECEE85-ED06-42A5-8068-CBDD92BB6EF4} + {0CC54804-3AD3-4C81-BE71-8011C72F1E1C} = {C6404144-61BC-4402-BA36-FB6BB19BD739} EndGlobalSection EndGlobal diff --git a/windows/TutorialAddModule/1_custom_post_processing.vcxproj b/windows/TutorialAddModule/1_custom_post_processing.vcxproj new file mode 100644 index 00000000..53674fd8 --- /dev/null +++ b/windows/TutorialAddModule/1_custom_post_processing.vcxproj @@ -0,0 +1,97 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + {0CC54804-3AD3-4C81-BE71-8011C72F1E1C} + 1_user_asynchronous + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + + + + + + + + + + + + + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64 + $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); + $(VC_ReferencesPath_x64); + $(ProjectName)\$(Platform)\$(Configuration)\ + false + + + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64 + $(ProjectName)\$(Platform)\$(Configuration)\ + + + + EnableAllWarnings + Disabled + true + true + _CRT_SECURE_NO_WARNINGS;CMAKE_WINDOWS_BUILD;GLOG_NO_ABBREVIATED_SEVERITIES;GOOGLE_GLOG_DLL_DECL=__declspec(dllimport);GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS=__declspec(dllimport);CMAKE_INTDIR="Debug" + $(IntDir)\obj\relDir\relDir\%(RelativeDir)\%(Filename)%(Extension).obj + + + + + Level4 + Full + true + true + true + ..\..\include;..\..\3rdparty\windows\opencv\include;..\..\3rdparty\windows\caffe\include;..\..\3rdparty\windows\caffe\include2;..\..\3rdparty\windows\caffe3rdparty\include;..\..\3rdparty\windows\caffe3rdparty\include\boost-1_61;$(CUDA_PATH_V8_0)\include;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;CMAKE_WINDOWS_BUILD;GLOG_NO_ABBREVIATED_SEVERITIES;GOOGLE_GLOG_DLL_DECL=__declspec(dllimport);GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS=__declspec(dllimport);CMAKE_INTDIR="Release";NDEBUG + $(IntDir)\obj\relDir\relDir\%(RelativeDir)\%(Filename)%(Extension).obj + true + Speed + OldStyle + + + true + true + $(CUDA_PATH_V8_0)\lib\x64\; + ..\..\3rdparty\windows\caffe\lib\caffe.lib;..\..\3rdparty\windows\caffe\lib\caffeproto.lib;..\..\3rdparty\windows\caffe3rdparty\lib\boost_filesystem-vc140-mt-1_61.lib;..\..\3rdparty\windows\caffe3rdparty\lib\boost_system-vc140-mt-1_61.lib;..\..\3rdparty\windows\caffe3rdparty\lib\caffehdf5.lib;..\..\3rdparty\windows\caffe3rdparty\lib\caffehdf5_hl.lib;..\..\3rdparty\windows\caffe3rdparty\lib\caffezlib.lib;..\..\3rdparty\windows\caffe3rdparty\lib\gflags.lib;..\..\3rdparty\windows\caffe3rdparty\lib\glog.lib;..\..\3rdparty\windows\caffe3rdparty\lib\leveldb.lib;..\..\3rdparty\windows\caffe3rdparty\lib\libopenblas.dll.a;..\..\3rdparty\windows\caffe3rdparty\lib\libprotobuf.lib;..\..\3rdparty\windows\caffe3rdparty\lib\lmdb.lib;..\..\3rdparty\windows\caffe3rdparty\lib\snappy.lib;..\..\3rdparty\windows\opencv\x64\vc14\lib\opencv_world310.lib;cublas.lib;cublas_device.lib;cudart.lib;cudnn.lib;curand.lib;ntdll.lib;shlwapi.lib;..\x64\Release\OpenPose.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/windows/TutorialAddModule/1_custom_post_processing.vcxproj.filters b/windows/TutorialAddModule/1_custom_post_processing.vcxproj.filters new file mode 100644 index 00000000..a99ac7b8 --- /dev/null +++ b/windows/TutorialAddModule/1_custom_post_processing.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {eeb2cc8c-beec-41a6-8ede-1cccf81f7a8d} + + + {35ac3ba9-48c9-4d62-82f0-69be0b50034c} + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/windows/TutorialAddModule/1_custom_post_processing.vcxproj.user b/windows/TutorialAddModule/1_custom_post_processing.vcxproj.user new file mode 100644 index 00000000..ebb1f573 --- /dev/null +++ b/windows/TutorialAddModule/1_custom_post_processing.vcxproj.user @@ -0,0 +1,8 @@ + + + + PATH=%PATH%;3rdparty\windows\caffe\bin\;3rdparty\windows\opencv\x64\vc14\bin + WindowsLocalDebugger + ..\.. + + \ No newline at end of file