Skip to content

Commit 3356336

Browse files
Added pre-processing worker to Wrapper (CMU-Perceptual-Computing-Lab#608)
1 parent 084d169 commit 3356336

File tree

9 files changed

+209
-11
lines changed

9 files changed

+209
-11
lines changed

doc/release_notes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ OpenPose Library - Release Notes
315315
32. Function getFilesOnDirectory() can extra all basic image file types at once without requiring to manually enumerate them.
316316
33. Added the flags `--face_detector` and `--hand_detector`, that enable the user to select the face/hand rectangle detector that is used for the later face/hand keypoint detection. It includes OpenCV (for face), and also allows the user to provide its own input. Flag `--hand_tracking` is removed and integrated into this flag too.
317317
34. Maximum queue size per OpenPose thread is configurable through the Wrapper class.
318+
35. Added pre-processing capabilities to Wrapper (WorkerType::PreProcessing), which will be run right after the image has been read.
318319
2. Functions or parameters renamed:
319320
1. By default, python example `tutorial_developer/python_2_pose_from_heatmaps.py` was using 2 scales starting at -1x736, changed to 1 scale at -1x368.
320321
2. WrapperStructPose default parameters changed to match those of the OpenPose demo binary.
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
// ------------------------- OpenPose C++ API Tutorial - Example 13 - Custom Pre-processing -------------------------
2+
// Synchronous mode: ideal for production integration. It provides the fastest results with respect to runtime
3+
// performance.
4+
// In this function, the user can implement its own pre-processing, i.e., his function will be called after the image
5+
// has been read by OpenPose but before OpenPose processes the frames.
6+
7+
// Command-line user intraface
8+
#include <openpose/flags.hpp>
9+
// OpenPose dependencies
10+
#include <openpose/headers.hpp>
11+
12+
// This worker will just invert the image
13+
class WUserPreProcessing : public op::Worker<std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>>
14+
{
15+
public:
16+
WUserPreProcessing()
17+
{
18+
// User's constructor here
19+
}
20+
21+
void initializationOnThread() {}
22+
23+
void work(std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)
24+
{
25+
// User's pre-processing (after OpenPose read the input image & before OpenPose processing) here
26+
// datumPtr->cvInputData: input frame
27+
try
28+
{
29+
if (datumsPtr != nullptr && !datumsPtr->empty())
30+
for (auto& datumPtr : *datumsPtr)
31+
cv::bitwise_not(datumPtr->cvOutputData, datumPtr->cvOutputData);
32+
}
33+
catch (const std::exception& e)
34+
{
35+
this->stop();
36+
op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
37+
}
38+
}
39+
};
40+
41+
void configureWrapper(op::Wrapper& opWrapper)
42+
{
43+
try
44+
{
45+
// Configuring OpenPose
46+
47+
// logging_level
48+
op::check(0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.",
49+
__LINE__, __FUNCTION__, __FILE__);
50+
op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);
51+
op::Profiler::setDefaultX(FLAGS_profile_speed);
52+
53+
// Applying user defined configuration - GFlags to program variables
54+
// producerType
55+
op::ProducerType producerType;
56+
std::string producerString;
57+
std::tie(producerType, producerString) = op::flagsToProducer(
58+
FLAGS_image_dir, FLAGS_video, FLAGS_ip_camera, FLAGS_camera, FLAGS_flir_camera, FLAGS_flir_camera_index);
59+
// cameraSize
60+
const auto cameraSize = op::flagsToPoint(FLAGS_camera_resolution, "-1x-1");
61+
// outputSize
62+
const auto outputSize = op::flagsToPoint(FLAGS_output_resolution, "-1x-1");
63+
// netInputSize
64+
const auto netInputSize = op::flagsToPoint(FLAGS_net_resolution, "-1x368");
65+
// faceNetInputSize
66+
const auto faceNetInputSize = op::flagsToPoint(FLAGS_face_net_resolution, "368x368 (multiples of 16)");
67+
// handNetInputSize
68+
const auto handNetInputSize = op::flagsToPoint(FLAGS_hand_net_resolution, "368x368 (multiples of 16)");
69+
// poseModel
70+
const auto poseModel = op::flagsToPoseModel(FLAGS_model_pose);
71+
// JSON saving
72+
if (!FLAGS_write_keypoint.empty())
73+
op::log("Flag `write_keypoint` is deprecated and will eventually be removed."
74+
" Please, use `write_json` instead.", op::Priority::Max);
75+
// keypointScaleMode
76+
const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);
77+
// heatmaps to add
78+
const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,
79+
FLAGS_heatmaps_add_PAFs);
80+
const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);
81+
// >1 camera view?
82+
const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1 || FLAGS_flir_camera);
83+
// Face and hand detectors
84+
const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);
85+
const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);
86+
// Enabling Google Logging
87+
const bool enableGoogleLogging = true;
88+
89+
// Initializing the user custom classes
90+
// Processing
91+
auto wUserPreProcessing = std::make_shared<WUserPreProcessing>();
92+
// Add custom processing
93+
const auto workerProcessingOnNewThread = true;
94+
opWrapper.setWorker(op::WorkerType::PreProcessing, wUserPreProcessing, workerProcessingOnNewThread);
95+
96+
// Pose configuration (use WrapperStructPose{} for default and recommended configuration)
97+
const op::WrapperStructPose wrapperStructPose{
98+
!FLAGS_body_disable, netInputSize, outputSize, keypointScaleMode, FLAGS_num_gpu, FLAGS_num_gpu_start,
99+
FLAGS_scale_number, (float)FLAGS_scale_gap, op::flagsToRenderMode(FLAGS_render_pose, multipleView),
100+
poseModel, !FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap,
101+
FLAGS_part_to_show, FLAGS_model_folder, heatMapTypes, heatMapScaleMode, FLAGS_part_candidates,
102+
(float)FLAGS_render_threshold, FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max,
103+
FLAGS_prototxt_path, FLAGS_caffemodel_path, enableGoogleLogging};
104+
opWrapper.configure(wrapperStructPose);
105+
// Face configuration (use op::WrapperStructFace{} to disable it)
106+
const op::WrapperStructFace wrapperStructFace{
107+
FLAGS_face, faceDetector, faceNetInputSize,
108+
op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),
109+
(float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};
110+
opWrapper.configure(wrapperStructFace);
111+
// Hand configuration (use op::WrapperStructHand{} to disable it)
112+
const op::WrapperStructHand wrapperStructHand{
113+
FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,
114+
op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,
115+
(float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};
116+
opWrapper.configure(wrapperStructHand);
117+
// Extra functionality configuration (use op::WrapperStructExtra{} to disable it)
118+
const op::WrapperStructExtra wrapperStructExtra{
119+
FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};
120+
opWrapper.configure(wrapperStructExtra);
121+
// Producer (use default to disable any input)
122+
const op::WrapperStructInput wrapperStructInput{
123+
producerType, producerString, FLAGS_frame_first, FLAGS_frame_step, FLAGS_frame_last,
124+
FLAGS_process_real_time, FLAGS_frame_flip, FLAGS_frame_rotate, FLAGS_frames_repeat,
125+
cameraSize, FLAGS_camera_parameter_path, FLAGS_frame_undistort, FLAGS_3d_views};
126+
opWrapper.configure(wrapperStructInput);
127+
// Output (comment or use default argument to disable any output)
128+
const op::WrapperStructOutput wrapperStructOutput{
129+
FLAGS_cli_verbose, FLAGS_write_keypoint, op::stringToDataFormat(FLAGS_write_keypoint_format),
130+
FLAGS_write_json, FLAGS_write_coco_json, FLAGS_write_coco_foot_json, FLAGS_write_coco_json_variant,
131+
FLAGS_write_images, FLAGS_write_images_format, FLAGS_write_video, FLAGS_write_video_fps,
132+
FLAGS_write_video_with_audio, FLAGS_write_heatmaps, FLAGS_write_heatmaps_format, FLAGS_write_video_3d,
133+
FLAGS_write_video_adam, FLAGS_write_bvh, FLAGS_udp_host, FLAGS_udp_port};
134+
opWrapper.configure(wrapperStructOutput);
135+
// GUI (comment or use default argument to disable any visual output)
136+
const op::WrapperStructGui wrapperStructGui{
137+
op::flagsToDisplayMode(FLAGS_display, FLAGS_3d), !FLAGS_no_gui_verbose, FLAGS_fullscreen};
138+
opWrapper.configure(wrapperStructGui);
139+
// Set to single-thread (for sequential processing and/or debugging and/or reducing latency)
140+
if (FLAGS_disable_multi_thread)
141+
opWrapper.disableMultiThreading();
142+
}
143+
catch (const std::exception& e)
144+
{
145+
op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
146+
}
147+
}
148+
149+
int tutorialApiCpp()
150+
{
151+
try
152+
{
153+
op::log("Starting OpenPose demo...", op::Priority::High);
154+
const auto opTimer = op::getTimerInit();
155+
156+
// OpenPose wrapper
157+
op::log("Configuring OpenPose...", op::Priority::High);
158+
op::Wrapper opWrapper;
159+
configureWrapper(opWrapper);
160+
161+
// Start, run, and stop processing - exec() blocks this thread until OpenPose wrapper has finished
162+
op::log("Starting thread(s)...", op::Priority::High);
163+
opWrapper.exec();
164+
165+
// Measuring total time
166+
op::printTime(opTimer, "OpenPose demo successfully finished. Total time: ", " seconds.", op::Priority::High);
167+
168+
// Return
169+
return 0;
170+
}
171+
catch (const std::exception& e)
172+
{
173+
return -1;
174+
}
175+
}
176+
177+
int main(int argc, char *argv[])
178+
{
179+
// Parsing command line flags
180+
gflags::ParseCommandLineFlags(&argc, &argv, true);
181+
182+
// Running tutorialApiCpp
183+
return tutorialApiCpp();
184+
}

examples/tutorial_api_cpp/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ set(EXAMPLE_FILES
1111
10_asynchronous_custom_output.cpp
1212
11_asynchronous_custom_input_output_and_datum.cpp
1313
12_synchronous_custom_input.cpp
14-
# 13_synchronous_custom_preprocessing.cpp
14+
13_synchronous_custom_preprocessing.cpp
1515
14_synchronous_custom_postprocessing.cpp
1616
15_synchronous_custom_output.cpp
1717
16_synchronous_custom_all_and_datum.cpp)

include/openpose/core/macros.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ namespace boost
9797
#endif
9898
#ifdef OPEN_CV_IS_4_OR_HIGHER
9999
#define CV_BGR2GRAY cv::COLOR_BGR2GRAY
100+
#define CV_BGR2RGB cv::COLOR_BGR2RGB
100101
#define CV_CALIB_CB_ADAPTIVE_THRESH cv::CALIB_CB_ADAPTIVE_THRESH
101102
#define CV_CALIB_CB_NORMALIZE_IMAGE cv::CALIB_CB_NORMALIZE_IMAGE
102103
#define CV_CALIB_CB_FILTER_QUADS cv::CALIB_CB_FILTER_QUADS
@@ -111,6 +112,7 @@ namespace boost
111112
#define CV_INTER_CUBIC cv::INTER_CUBIC
112113
#define CV_INTER_LINEAR cv::INTER_LINEAR
113114
#define CV_L2 cv::NORM_L2
115+
#define CV_RGB2BGR cv::COLOR_RGB2BGR
114116
#define CV_TERMCRIT_EPS cv::TermCriteria::Type::EPS
115117
#define CV_TERMCRIT_ITER cv::TermCriteria::Type::MAX_ITER
116118
#define CV_WARP_INVERSE_MAP cv::WARP_INVERSE_MAP

include/openpose/wrapper/enumClasses.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace op
1515
enum class WorkerType : unsigned char
1616
{
1717
Input = 0,
18-
// PreProcessing,
18+
PreProcessing,
1919
PostProcessing,
2020
Output,
2121
Size,

include/openpose/wrapper/wrapper.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ namespace op
6060

6161
/**
6262
* Add an user-defined extra Worker for a desired task (input, output, ...).
63-
* @param workerType WorkerType to configure (e.g., Input, PostProcessing, Output).
63+
* @param workerType WorkerType to configure (e.g., Input, PreProcessing, PostProcessing, Output).
6464
* @param worker TWorker to be added.
6565
* @param workerOnNewThread Whether to add this TWorker on a new thread (if it is computationally demanding) or
6666
* simply reuse existing threads (for light functions). Set to true if the performance time is unknown.

include/openpose/wrapper/wrapperAuxiliary.hpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,11 @@ namespace op
109109

110110
// User custom workers
111111
const auto& userInputWs = userWs[int(WorkerType::Input)];
112+
const auto& userPreProcessingWs = userWs[int(WorkerType::PreProcessing)];
112113
const auto& userPostProcessingWs = userWs[int(WorkerType::PostProcessing)];
113114
const auto& userOutputWs = userWs[int(WorkerType::Output)];
114115
const auto userInputWsOnNewThread = userWsOnNewThread[int(WorkerType::Input)];
116+
const auto userPreProcessingWsOnNewThread = userWsOnNewThread[int(WorkerType::PreProcessing)];
115117
const auto userPostProcessingWsOnNewThread = userWsOnNewThread[int(WorkerType::PostProcessing)];
116118
const auto userOutputWsOnNewThread = userWsOnNewThread[int(WorkerType::Output)];
117119

@@ -900,7 +902,18 @@ namespace op
900902
// After producer
901903
// ID generator (before any multi-threading or any function that requires the ID)
902904
const auto wIdGenerator = std::make_shared<WIdGenerator<TDatumsSP>>();
903-
std::vector<TWorker> workersAux{wIdGenerator};
905+
// If custom user Worker and uses its own thread
906+
std::vector<TWorker> workersAux;
907+
if (!userPreProcessingWs.empty())
908+
{
909+
// If custom user Worker in its own thread
910+
if (userPreProcessingWsOnNewThread)
911+
log("You chose to add your pre-processing function in a new thread. However, OpenPose will"
912+
" add it in the same thread than the input frame producer.",
913+
Priority::High, __LINE__, __FUNCTION__, __FILE__);
914+
workersAux = mergeVectors(workersAux, {userPreProcessingWs});
915+
}
916+
workersAux = mergeVectors(workersAux, {wIdGenerator});
904917
// Scale & cv::Mat to OP format
905918
if (scaleAndSizeExtractorW != nullptr)
906919
workersAux = mergeVectors(workersAux, {scaleAndSizeExtractorW});
@@ -927,7 +940,7 @@ namespace op
927940
workersAux = mergeVectors({datumProducerW}, workersAux);
928941
// Otherwise
929942
else if (threadManagerMode != ThreadManagerMode::Asynchronous
930-
&& threadManagerMode != ThreadManagerMode::AsynchronousIn)
943+
&& threadManagerMode != ThreadManagerMode::AsynchronousIn)
931944
error("No input selected.", __LINE__, __FUNCTION__, __FILE__);
932945
// Thread 0 or 1, queues 0 -> 1
933946
log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);

scripts/travis/configure_cmake.sh

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ mkdir build
66
cd build
77

88
echo "RUN_EXAMPLES = ${RUN_EXAMPLES}."
9-
if [[ $RUN_EXAMPLES == true ]] ; then
10-
ARGS="-DDOWNLOAD_FACE_MODEL=OFF -DDOWNLOAD_HAND_MODEL=OFF"
11-
else
9+
if [[ $RUN_EXAMPLES == false ]] ; then
1210
ARGS="-DDOWNLOAD_BODY_25_MODEL=OFF -DDOWNLOAD_FACE_MODEL=OFF -DDOWNLOAD_HAND_MODEL=OFF"
1311
# ARGS="-DBUILD_CAFFE=ON -DDOWNLOAD_BODY_25_MODEL=OFF -DDOWNLOAD_BODY_COCO_MODEL=OFF -DDOWNLOAD_FACE_MODEL=OFF -DDOWNLOAD_HAND_MODEL=OFF -DDOWNLOAD_BODY_MPI_MODEL=OFF"
1412
fi

scripts/travis/run_tests.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ if [[ $RUN_EXAMPLES == true ]] ; then
6666
./build/examples/tutorial_api_cpp/12_synchronous_custom_input.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0
6767
echo " "
6868

69-
# echo "Tutorial API C++: Example 13..."
70-
# ./build/examples/tutorial_api_cpp/13_synchronous_custom_preprocessing.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0
71-
# echo " "
69+
echo "Tutorial API C++: Example 13..."
70+
./build/examples/tutorial_api_cpp/13_synchronous_custom_preprocessing.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0
71+
echo " "
7272

7373
echo "Tutorial API C++: Example 14..."
7474
./build/examples/tutorial_api_cpp/14_synchronous_custom_postprocessing.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0

0 commit comments

Comments
 (0)