OpenPose  1.0.0rc2
OpenPose: A Real-Time Multi-Person Key-Point Detection And Multi-Threading C++ Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
wrapper.hpp
Go to the documentation of this file.
1 #ifndef OPENPOSE_WRAPPER_WRAPPER_HPP
2 #define OPENPOSE_WRAPPER_WRAPPER_HPP
3 
11 
12 namespace op
13 {
29  template<typename TDatums,
30  typename TWorker = std::shared_ptr<Worker<std::shared_ptr<TDatums>>>,
31  typename TQueue = Queue<std::shared_ptr<TDatums>>>
32  class Wrapper
33  {
34  public:
42  explicit Wrapper(const ThreadManagerMode threadManagerMode = ThreadManagerMode::Synchronous);
43 
48  ~Wrapper();
49 
56  void disableMultiThreading();
57 
64  void setWorkerInput(const TWorker& worker, const bool workerOnNewThread = true);
65 
72  void setWorkerPostProcessing(const TWorker& worker, const bool workerOnNewThread = true);
73 
80  void setWorkerOutput(const TWorker& worker, const bool workerOnNewThread = true);
81 
82  // If output is not required, just use this function until the renderOutput argument. Keep the default values
83  // for the other parameters in order not to display/save any output.
84  void configure(const WrapperStructPose& wrapperStructPose,
85  // Producer: set producerSharedPtr=nullptr or use default WrapperStructInput{} to disable input
86  const WrapperStructInput& wrapperStructInput,
87  // Consumer (keep default values to disable any output)
88  const WrapperStructOutput& wrapperStructOutput = WrapperStructOutput{});
89 
90  // Similar to the previos configure, but it includes hand extraction and rendering
91  void configure(const WrapperStructPose& wrapperStructPose,
92  // Hand (use the default WrapperStructHand{} to disable any hand detector)
93  const WrapperStructHand& wrapperStructHand,
94  // Producer: set producerSharedPtr=nullptr or use default WrapperStructInput{} to disable input
95  const WrapperStructInput& wrapperStructInput,
96  // Consumer (keep default values to disable any output)
97  const WrapperStructOutput& wrapperStructOutput = WrapperStructOutput{});
98 
99  // Similar to the previos configure, but it includes hand extraction and rendering
100  void configure(const WrapperStructPose& wrapperStructPose,
101  // Face (use the default WrapperStructFace{} to disable any face detector)
102  const WrapperStructFace& wrapperStructFace,
103  // Producer: set producerSharedPtr=nullptr or use default WrapperStructInput{} to disable input
104  const WrapperStructInput& wrapperStructInput,
105  // Consumer (keep default values to disable any output)
106  const WrapperStructOutput& wrapperStructOutput = WrapperStructOutput{});
107 
108  // Similar to the previos configure, but it includes hand extraction and rendering
109  void configure(const WrapperStructPose& wrapperStructPose = WrapperStructPose{},
110  // Face (use the default WrapperStructFace{} to disable any face detector)
111  const WrapperStructFace& wrapperStructFace = WrapperStructFace{},
112  // Hand (use the default WrapperStructHand{} to disable any hand detector)
113  const WrapperStructHand& wrapperStructHand = WrapperStructHand{},
114  // Producer: set producerSharedPtr=nullptr or use default WrapperStructInput{} to disable input
115  const WrapperStructInput& wrapperStructInput = WrapperStructInput{},
116  // Consumer (keep default values to disable any output)
117  const WrapperStructOutput& wrapperStructOutput = WrapperStructOutput{});
118 
124  void exec();
125 
135  void start();
136 
141  void stop();
142 
148  bool isRunning() const;
149 
157  bool tryEmplace(std::shared_ptr<TDatums>& tDatums);
158 
167  bool waitAndEmplace(std::shared_ptr<TDatums>& tDatums);
168 
175  bool tryPush(const std::shared_ptr<TDatums>& tDatums);
176 
183  bool waitAndPush(const std::shared_ptr<TDatums>& tDatums);
184 
192  bool tryPop(std::shared_ptr<TDatums>& tDatums);
193 
202  bool waitAndPop(std::shared_ptr<TDatums>& tDatums);
203 
204  private:
205  const ThreadManagerMode mThreadManagerMode;
206  const std::shared_ptr<std::pair<std::atomic<bool>, std::atomic<int>>> spVideoSeek;
207  bool mConfigured;
209  bool mUserInputWsOnNewThread;
210  bool mUserPostProcessingWsOnNewThread;
211  bool mUserOutputWsOnNewThread;
212  unsigned long long mThreadId;
213  bool mMultiThreadEnabled;
214  // Workers
215  std::vector<TWorker> mUserInputWs;
216  TWorker wDatumProducer;
217  TWorker spWIdGenerator;
218  TWorker spWScaleAndSizeExtractor;
219  TWorker spWCvMatToOpInput;
220  TWorker spWCvMatToOpOutput;
221  std::vector<std::vector<TWorker>> spWPoses;
222  std::vector<TWorker> mPostProcessingWs;
223  std::vector<TWorker> mUserPostProcessingWs;
224  std::vector<TWorker> mOutputWs;
225  TWorker spWGui;
226  std::vector<TWorker> mUserOutputWs;
227 
234  void reset();
235 
242  void configureThreadManager();
243 
251  unsigned long long threadIdPP();
252 
253  DELETE_COPY(Wrapper);
254  };
255 }
256 
257 
258 
259 
260 
261 // Implementation
262 #include <openpose/3d/headers.hpp>
263 #include <openpose/core/headers.hpp>
265 #include <openpose/face/headers.hpp>
267 #include <openpose/gui/headers.hpp>
268 #include <openpose/gpu/gpu.hpp>
269 #include <openpose/hand/headers.hpp>
270 #include <openpose/pose/headers.hpp>
275 namespace op
276 {
277  template<typename TDatums, typename TWorker, typename TQueue>
279  mThreadManagerMode{threadManagerMode},
280  spVideoSeek{std::make_shared<std::pair<std::atomic<bool>, std::atomic<int>>>()},
281  mConfigured{false},
282  mThreadManager{threadManagerMode},
283  mMultiThreadEnabled{true}
284  {
285  try
286  {
287  // It cannot be directly included in the constructor (compiler error for copying std::atomic)
288  spVideoSeek->first = false;
289  spVideoSeek->second = 0;
290  }
291  catch (const std::exception& e)
292  {
293  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
294  }
295  }
296 
297  template<typename TDatums, typename TWorker, typename TQueue>
299  {
300  try
301  {
302  stop();
303  reset();
304  }
305  catch (const std::exception& e)
306  {
307  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
308  }
309  }
310 
311  template<typename TDatums, typename TWorker, typename TQueue>
313  {
314  try
315  {
316  mMultiThreadEnabled = false;
317  }
318  catch (const std::exception& e)
319  {
320  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
321  }
322  }
323 
324  template<typename TDatums, typename TWorker, typename TQueue>
325  void Wrapper<TDatums, TWorker, TQueue>::setWorkerInput(const TWorker& worker, const bool workerOnNewThread)
326  {
327  try
328  {
329  mUserInputWs.clear();
330  if (worker == nullptr)
331  error("Your worker is a nullptr.", __LINE__, __FILE__, __FUNCTION__);
332  mUserInputWs.emplace_back(worker);
333  mUserInputWsOnNewThread = {workerOnNewThread};
334  }
335  catch (const std::exception& e)
336  {
337  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
338  }
339  }
340 
341  template<typename TDatums, typename TWorker, typename TQueue>
343  const bool workerOnNewThread)
344  {
345  try
346  {
347  mUserPostProcessingWs.clear();
348  if (worker == nullptr)
349  error("Your worker is a nullptr.", __LINE__, __FILE__, __FUNCTION__);
350  mUserPostProcessingWs.emplace_back(worker);
351  mUserPostProcessingWsOnNewThread = {workerOnNewThread};
352  }
353  catch (const std::exception& e)
354  {
355  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
356  }
357  }
358 
359  template<typename TDatums, typename TWorker, typename TQueue>
360  void Wrapper<TDatums, TWorker, TQueue>::setWorkerOutput(const TWorker& worker, const bool workerOnNewThread)
361  {
362  try
363  {
364  mUserOutputWs.clear();
365  if (worker == nullptr)
366  error("Your worker is a nullptr.", __LINE__, __FILE__, __FUNCTION__);
367  mUserOutputWs.emplace_back(worker);
368  mUserOutputWsOnNewThread = {workerOnNewThread};
369  }
370  catch (const std::exception& e)
371  {
372  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
373  }
374  }
375 
376  template<typename TDatums, typename TWorker, typename TQueue>
378  const WrapperStructInput& wrapperStructInput,
379  const WrapperStructOutput& wrapperStructOutput)
380  {
381  try
382  {
383  configure(wrapperStructPose, WrapperStructFace{}, WrapperStructHand{},
384  wrapperStructInput, wrapperStructOutput);
385  }
386  catch (const std::exception& e)
387  {
388  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
389  }
390  }
391 
392  template<typename TDatums, typename TWorker, typename TQueue>
394  const WrapperStructFace& wrapperStructFace,
395  const WrapperStructInput& wrapperStructInput,
396  const WrapperStructOutput& wrapperStructOutput)
397  {
398  try
399  {
400  configure(wrapperStructPose, wrapperStructFace, WrapperStructHand{},
401  wrapperStructInput, wrapperStructOutput);
402  }
403  catch (const std::exception& e)
404  {
405  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
406  }
407  }
408 
409  template<typename TDatums, typename TWorker, typename TQueue>
411  const WrapperStructHand& wrapperStructHand,
412  const WrapperStructInput& wrapperStructInput,
413  const WrapperStructOutput& wrapperStructOutput)
414  {
415  try
416  {
417  configure(wrapperStructPose, WrapperStructFace{}, wrapperStructHand,
418  wrapperStructInput, wrapperStructOutput);
419  }
420  catch (const std::exception& e)
421  {
422  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
423  }
424  }
425 
426  template<typename TDatums, typename TWorker, typename TQueue>
428  const WrapperStructFace& wrapperStructFace,
429  const WrapperStructHand& wrapperStructHand,
430  const WrapperStructInput& wrapperStructInput,
431  const WrapperStructOutput& wrapperStructOutput)
432  {
433  try
434  {
435  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
436 
437  // Shortcut
438  typedef std::shared_ptr<TDatums> TDatumsPtr;
439 
440  // Required parameters
441  const auto renderOutput = wrapperStructPose.renderMode != RenderMode::None
442  || wrapperStructFace.renderMode != RenderMode::None
443  || wrapperStructHand.renderMode != RenderMode::None;
444  const auto renderOutputGpu = wrapperStructPose.renderMode == RenderMode::Gpu
445  || wrapperStructFace.renderMode == RenderMode::Gpu
446  || wrapperStructHand.renderMode == RenderMode::Gpu;
447  const auto renderFace = wrapperStructFace.enable && wrapperStructFace.renderMode != RenderMode::None;
448  const auto renderHand = wrapperStructHand.enable && wrapperStructHand.renderMode != RenderMode::None;
449  const auto renderHandGpu = wrapperStructHand.enable && wrapperStructHand.renderMode == RenderMode::Gpu;
450 
451  // Check no wrong/contradictory flags enabled
452  const auto userOutputWsEmpty = mUserOutputWs.empty();
453  wrapperConfigureSecurityChecks(wrapperStructPose, wrapperStructFace, wrapperStructHand, wrapperStructInput,
454  wrapperStructOutput, renderOutput, userOutputWsEmpty, mThreadManagerMode);
455 
456  // Get number threads
457  auto numberThreads = wrapperStructPose.gpuNumber;
458  auto gpuNumberStart = wrapperStructPose.gpuNumberStart;
459  // CPU --> 1 thread or no pose extraction
460  if (getGpuMode() == GpuMode::NoGpu)
461  {
462  numberThreads = (wrapperStructPose.gpuNumber == 0 ? 0 : 1);
463  gpuNumberStart = 0;
464  // Disabling multi-thread makes the code 400 ms faster (2.3 sec vs. 2.7 in i7-6850K)
465  // and fixes the bug that the screen was not properly displayed and only refreshed sometimes
466  // Note: The screen bug could be also fixed by using waitKey(30) rather than waitKey(1)
467  disableMultiThreading();
468  }
469  // GPU --> user picks (<= #GPUs)
470  else
471  {
472  // If number GPU < 0 --> set it to all the available GPUs
473  if (numberThreads < 0)
474  {
475  // Get total number GPUs
476  const auto totalGpuNumber = getGpuNumber();
477  if (totalGpuNumber <= gpuNumberStart)
478  error("Number of initial GPUs (`--number_gpu_start`) must be lower than the total number of used"
479  " GPUs (`--number_gpu`)", __LINE__, __FUNCTION__, __FILE__);
480  numberThreads = totalGpuNumber - gpuNumberStart;
481  // Reset initial GPU to 0 (we want them all)
482  // Logging message
483  log("Auto-detecting all available GPUs... Detected " + std::to_string(totalGpuNumber)
484  + " GPU(s), using " + std::to_string(numberThreads) + " of them starting at GPU "
485  + std::to_string(gpuNumberStart) + ".", Priority::High);
486  }
487  }
488 
489  // Proper format
490  const auto writeImagesCleaned = formatAsDirectory(wrapperStructOutput.writeImages);
491  const auto writeKeypointCleaned = formatAsDirectory(wrapperStructOutput.writeKeypoint);
492  const auto writeJsonCleaned = formatAsDirectory(wrapperStructOutput.writeJson);
493  const auto writeHeatMapsCleaned = formatAsDirectory(wrapperStructOutput.writeHeatMaps);
494  const auto modelFolder = formatAsDirectory(wrapperStructPose.modelFolder);
495 
496  // Common parameters
497  auto finalOutputSize = wrapperStructPose.outputSize;
498  Point<int> producerSize{-1,-1};
499  if (wrapperStructInput.producerSharedPtr != nullptr)
500  {
501  // 1. Set producer properties
502  const auto displayProducerFpsMode = (wrapperStructInput.realTimeProcessing
504  wrapperStructInput.producerSharedPtr->setProducerFpsMode(displayProducerFpsMode);
505  wrapperStructInput.producerSharedPtr->set(ProducerProperty::Flip, wrapperStructInput.frameFlip);
506  wrapperStructInput.producerSharedPtr->set(ProducerProperty::Rotation, wrapperStructInput.frameRotate);
507  wrapperStructInput.producerSharedPtr->set(ProducerProperty::AutoRepeat,
508  wrapperStructInput.framesRepeat);
509  // 2. Set finalOutputSize
510  producerSize = Point<int>{(int)wrapperStructInput.producerSharedPtr->get(CV_CAP_PROP_FRAME_WIDTH),
511  (int)wrapperStructInput.producerSharedPtr->get(CV_CAP_PROP_FRAME_HEIGHT)};
512  // Set finalOutputSize to input size if desired
513  if (finalOutputSize.x == -1 || finalOutputSize.y == -1)
514  finalOutputSize = producerSize;
515  }
516 
517  // Producer
518  if (wrapperStructInput.producerSharedPtr != nullptr)
519  {
520  const auto datumProducer = std::make_shared<DatumProducer<TDatums>>(
521  wrapperStructInput.producerSharedPtr, wrapperStructInput.frameFirst, wrapperStructInput.frameLast,
522  spVideoSeek
523  );
524  wDatumProducer = std::make_shared<WDatumProducer<TDatumsPtr, TDatums>>(datumProducer);
525  }
526  else
527  wDatumProducer = nullptr;
528 
529  std::vector<std::shared_ptr<PoseExtractor>> poseExtractors;
530  std::vector<std::shared_ptr<PoseGpuRenderer>> poseGpuRenderers;
531  std::shared_ptr<PoseCpuRenderer> poseCpuRenderer;
532  if (numberThreads > 0)
533  {
534  // Get input scales and sizes
535  const auto scaleAndSizeExtractor = std::make_shared<ScaleAndSizeExtractor>(
536  wrapperStructPose.netInputSize, finalOutputSize, wrapperStructPose.scalesNumber,
537  wrapperStructPose.scaleGap
538  );
539  spWScaleAndSizeExtractor = std::make_shared<WScaleAndSizeExtractor<TDatumsPtr>>(scaleAndSizeExtractor);
540 
541  // Input cvMat to OpenPose input & output format
542  const auto cvMatToOpInput = std::make_shared<CvMatToOpInput>();
543  spWCvMatToOpInput = std::make_shared<WCvMatToOpInput<TDatumsPtr>>(cvMatToOpInput);
544  if (renderOutput)
545  {
546  const auto cvMatToOpOutput = std::make_shared<CvMatToOpOutput>();
547  spWCvMatToOpOutput = std::make_shared<WCvMatToOpOutput<TDatumsPtr>>(cvMatToOpOutput);
548  }
549 
550  // Pose estimators & renderers
551  std::vector<TWorker> cpuRenderers;
552  spWPoses.clear();
553  spWPoses.resize(numberThreads);
554  if (wrapperStructPose.enable)
555  {
556  // Pose estimators
557  for (auto gpuId = 0; gpuId < numberThreads; gpuId++)
558  poseExtractors.emplace_back(std::make_shared<PoseExtractorCaffe>(
559  wrapperStructPose.poseModel, modelFolder, gpuId + gpuNumberStart,
560  wrapperStructPose.heatMapTypes, wrapperStructPose.heatMapScale,
561  wrapperStructPose.addPartCandidates, wrapperStructPose.enableGoogleLogging
562  ));
563 
564  // Pose renderers
565  if (renderOutputGpu || wrapperStructPose.renderMode == RenderMode::Cpu)
566  {
567  // If wrapperStructPose.renderMode != RenderMode::Gpu but renderOutput, then we create an
568  // alpha = 0 pose renderer in order to keep the removing background option
569  const auto alphaKeypoint = (wrapperStructPose.renderMode != RenderMode::None
570  ? wrapperStructPose.alphaKeypoint : 0.f);
571  const auto alphaHeatMap = (wrapperStructPose.renderMode != RenderMode::None
572  ? wrapperStructPose.alphaHeatMap : 0.f);
573  // GPU rendering
574  if (renderOutputGpu)
575  {
576  for (const auto& poseExtractor : poseExtractors)
577  {
578  poseGpuRenderers.emplace_back(std::make_shared<PoseGpuRenderer>(
579  wrapperStructPose.poseModel, poseExtractor, wrapperStructPose.renderThreshold,
580  wrapperStructPose.blendOriginalFrame, alphaKeypoint,
581  alphaHeatMap, wrapperStructPose.defaultPartToRender
582  ));
583  }
584  }
585  // CPU rendering
586  if (wrapperStructPose.renderMode == RenderMode::Cpu)
587  {
588  poseCpuRenderer = std::make_shared<PoseCpuRenderer>(
589  wrapperStructPose.poseModel, wrapperStructPose.renderThreshold,
590  wrapperStructPose.blendOriginalFrame, alphaKeypoint, alphaHeatMap,
591  wrapperStructPose.defaultPartToRender);
592  cpuRenderers.emplace_back(std::make_shared<WPoseRenderer<TDatumsPtr>>(poseCpuRenderer));
593  }
594  }
595  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
596 
597  // Pose extractor(s)
598  spWPoses.resize(poseExtractors.size());
599  for (auto i = 0u; i < spWPoses.size(); i++)
600  spWPoses.at(i) = {std::make_shared<WPoseExtractor<TDatumsPtr>>(poseExtractors.at(i))};
601 
602  // Added right after PoseExtractor to avoid:
603  // 1) Rendering people that are later deleted (wrong visualization).
604  // 2) Processing faces and hands on people that will be deleted (speed up).
605  if (wrapperStructPose.numberPeopleMax > 0)
606  {
607  // Add KeepTopNPeople for each PoseExtractor
608  const auto keepTopNPeople = std::make_shared<KeepTopNPeople>(wrapperStructPose.numberPeopleMax);
609  for (auto& wPose : spWPoses)
610  wPose.emplace_back(std::make_shared<WKeepTopNPeople<TDatumsPtr>>(keepTopNPeople));
611  }
612  }
613 
614 
615  // Face extractor(s)
616  if (wrapperStructFace.enable)
617  {
618  // Face detector
619  // OpenPose face detector
620  if (wrapperStructPose.enable)
621  {
622  const auto faceDetector = std::make_shared<FaceDetector>(wrapperStructPose.poseModel);
623  for (auto& wPose : spWPoses)
624  wPose.emplace_back(std::make_shared<WFaceDetector<TDatumsPtr>>(faceDetector));
625  }
626  // OpenCV face detector
627  else
628  {
629  log("Body keypoint detection is disabled. Hence, using OpenCV face detector (much less"
630  " accurate but faster).", Priority::High);
631  for (auto& wPose : spWPoses)
632  {
633  // 1 FaceDetectorOpenCV per thread, OpenCV face detector is not thread-safe
634  const auto faceDetectorOpenCV = std::make_shared<FaceDetectorOpenCV>(modelFolder);
635  wPose.emplace_back(
636  std::make_shared<WFaceDetectorOpenCV<TDatumsPtr>>(faceDetectorOpenCV)
637  );
638  }
639  }
640  // Face keypoint extractor
641  for (auto gpu = 0u; gpu < spWPoses.size(); gpu++)
642  {
643  // Face keypoint extractor
644  const auto netOutputSize = wrapperStructFace.netInputSize;
645  const auto faceExtractor = std::make_shared<FaceExtractorCaffe>(
646  wrapperStructFace.netInputSize, netOutputSize, modelFolder,
647  gpu + gpuNumberStart, wrapperStructPose.heatMapTypes, wrapperStructPose.heatMapScale,
648  wrapperStructPose.enableGoogleLogging
649  );
650  spWPoses.at(gpu).emplace_back(std::make_shared<WFaceExtractor<TDatumsPtr>>(faceExtractor));
651  }
652  }
653 
654  // Hand extractor(s)
655  if (wrapperStructHand.enable)
656  {
657  const auto handDetector = std::make_shared<HandDetector>(wrapperStructPose.poseModel);
658  for (auto gpu = 0u; gpu < spWPoses.size(); gpu++)
659  {
660  // Hand detector
661  // If tracking
662  if (wrapperStructHand.tracking)
663  spWPoses.at(gpu).emplace_back(
664  std::make_shared<WHandDetectorTracking<TDatumsPtr>>(handDetector)
665  );
666  // If detection
667  else
668  spWPoses.at(gpu).emplace_back(std::make_shared<WHandDetector<TDatumsPtr>>(handDetector));
669  // Hand keypoint extractor
670  const auto netOutputSize = wrapperStructHand.netInputSize;
671  const auto handExtractor = std::make_shared<HandExtractorCaffe>(
672  wrapperStructHand.netInputSize, netOutputSize, modelFolder,
673  gpu + gpuNumberStart, wrapperStructHand.scalesNumber, wrapperStructHand.scaleRange,
674  wrapperStructPose.heatMapTypes, wrapperStructPose.heatMapScale,
675  wrapperStructPose.enableGoogleLogging
676  );
677  spWPoses.at(gpu).emplace_back(
678  std::make_shared<WHandExtractor<TDatumsPtr>>(handExtractor)
679  );
680  // If tracking
681  if (wrapperStructHand.tracking)
682  spWPoses.at(gpu).emplace_back(
683  std::make_shared<WHandDetectorUpdate<TDatumsPtr>>(handDetector)
684  );
685  }
686  }
687 
688  // Pose renderer(s)
689  if (!poseGpuRenderers.empty())
690  for (auto i = 0u; i < spWPoses.size(); i++)
691  spWPoses.at(i).emplace_back(std::make_shared<WPoseRenderer<TDatumsPtr>>(
692  poseGpuRenderers.at(i)
693  ));
694 
695  // Face renderer(s)
696  if (renderFace)
697  {
698  // CPU rendering
699  if (wrapperStructFace.renderMode == RenderMode::Cpu)
700  {
701  // Construct face renderer
702  const auto faceRenderer = std::make_shared<FaceCpuRenderer>(wrapperStructFace.renderThreshold,
703  wrapperStructFace.alphaKeypoint,
704  wrapperStructFace.alphaHeatMap);
705  // Add worker
706  cpuRenderers.emplace_back(std::make_shared<WFaceRenderer<TDatumsPtr>>(faceRenderer));
707  }
708  // GPU rendering
709  else if (wrapperStructFace.renderMode == RenderMode::Gpu)
710  {
711  for (auto i = 0u; i < spWPoses.size(); i++)
712  {
713  // Construct face renderer
714  const auto faceRenderer = std::make_shared<FaceGpuRenderer>(
715  wrapperStructFace.renderThreshold, wrapperStructFace.alphaKeypoint,
716  wrapperStructFace.alphaHeatMap
717  );
718  // Performance boost -> share spGpuMemory for all renderers
719  if (!poseGpuRenderers.empty())
720  {
721  const bool isLastRenderer = !renderHandGpu;
722  const auto renderer = std::static_pointer_cast<PoseGpuRenderer>(
723  poseGpuRenderers.at(i)
724  );
725  faceRenderer->setSharedParametersAndIfLast(renderer->getSharedParameters(),
726  isLastRenderer);
727  }
728  // Add worker
729  spWPoses.at(i).emplace_back(std::make_shared<WFaceRenderer<TDatumsPtr>>(faceRenderer));
730  }
731  }
732  else
733  error("Unknown RenderMode.", __LINE__, __FUNCTION__, __FILE__);
734  }
735 
736  // Hand renderer(s)
737  if (renderHand)
738  {
739  // CPU rendering
740  if (wrapperStructHand.renderMode == RenderMode::Cpu)
741  {
742  // Construct hand renderer
743  const auto handRenderer = std::make_shared<HandCpuRenderer>(wrapperStructHand.renderThreshold,
744  wrapperStructHand.alphaKeypoint,
745  wrapperStructHand.alphaHeatMap);
746  // Add worker
747  cpuRenderers.emplace_back(std::make_shared<WHandRenderer<TDatumsPtr>>(handRenderer));
748  }
749  // GPU rendering
750  else if (wrapperStructHand.renderMode == RenderMode::Gpu)
751  {
752  for (auto i = 0u; i < spWPoses.size(); i++)
753  {
754  // Construct hands renderer
755  const auto handRenderer = std::make_shared<HandGpuRenderer>(
756  wrapperStructHand.renderThreshold, wrapperStructHand.alphaKeypoint,
757  wrapperStructHand.alphaHeatMap
758  );
759  // Performance boost -> share spGpuMemory for all renderers
760  if (!poseGpuRenderers.empty())
761  {
762  const bool isLastRenderer = true;
763  const auto renderer = std::static_pointer_cast<PoseGpuRenderer>(
764  poseGpuRenderers.at(i)
765  );
766  handRenderer->setSharedParametersAndIfLast(renderer->getSharedParameters(),
767  isLastRenderer);
768  }
769  // Add worker
770  spWPoses.at(i).emplace_back(std::make_shared<WHandRenderer<TDatumsPtr>>(handRenderer));
771  }
772  }
773  else
774  error("Unknown RenderMode.", __LINE__, __FUNCTION__, __FILE__);
775  }
776 
777  // Itermediate workers (e.g. OpenPose format to cv::Mat, json & frames recorder, ...)
778  mPostProcessingWs.clear();
779  // Frame buffer and ordering
780  if (spWPoses.size() > 1u)
781  mPostProcessingWs.emplace_back(std::make_shared<WQueueOrderer<TDatumsPtr>>());
782  // Person ID identification
783  if (wrapperStructPose.identification)
784  {
785  const auto personIdExtractor = std::make_shared<PersonIdExtractor>();
786  mPostProcessingWs.emplace_back(
787  std::make_shared<WPersonIdExtractor<TDatumsPtr>>(personIdExtractor)
788  );
789  }
790  // 3-D reconstruction
791  if (wrapperStructPose.reconstruct3d)
792  {
793  mPostProcessingWs.emplace_back(
794  std::make_shared<WPoseTriangulation<TDatumsPtr>>()
795  );
796  }
797  // Frames processor (OpenPose format -> cv::Mat format)
798  if (renderOutput)
799  {
800  mPostProcessingWs = mergeVectors(mPostProcessingWs, cpuRenderers);
801  const auto opOutputToCvMat = std::make_shared<OpOutputToCvMat>();
802  mPostProcessingWs.emplace_back(std::make_shared<WOpOutputToCvMat<TDatumsPtr>>(opOutputToCvMat));
803  }
804  // Re-scale pose if desired
805  // If desired scale is not the current input
806  if (wrapperStructPose.keypointScale != ScaleMode::InputResolution
807  // and desired scale is not output when size(input) = size(output)
808  && !(wrapperStructPose.keypointScale == ScaleMode::OutputResolution &&
809  (finalOutputSize == producerSize || finalOutputSize.x <= 0 || finalOutputSize.y <= 0))
810  // and desired scale is not net output when size(input) = size(net output)
811  && !(wrapperStructPose.keypointScale == ScaleMode::NetOutputResolution
812  && producerSize == wrapperStructPose.netInputSize))
813  {
814  // Then we must rescale the keypoints
815  auto keypointScaler = std::make_shared<KeypointScaler>(wrapperStructPose.keypointScale);
816  mPostProcessingWs.emplace_back(std::make_shared<WKeypointScaler<TDatumsPtr>>(keypointScaler));
817  }
818  }
819 
820  mOutputWs.clear();
821  // Write people pose data on disk (json for OpenCV >= 3, xml, yml...)
822  if (!writeKeypointCleaned.empty())
823  {
824  const auto keypointSaver = std::make_shared<KeypointSaver>(writeKeypointCleaned,
825  wrapperStructOutput.writeKeypointFormat);
826  mOutputWs.emplace_back(std::make_shared<WPoseSaver<TDatumsPtr>>(keypointSaver));
827  if (wrapperStructFace.enable)
828  mOutputWs.emplace_back(std::make_shared<WFaceSaver<TDatumsPtr>>(keypointSaver));
829  if (wrapperStructHand.enable)
830  mOutputWs.emplace_back(std::make_shared<WHandSaver<TDatumsPtr>>(keypointSaver));
831  }
832  // Write OpenPose output data on disk in json format (body/hand/face keypoints, body part locations if
833  // enabled, etc.)
834  if (!writeJsonCleaned.empty())
835  {
836  const auto peopleJsonSaver = std::make_shared<PeopleJsonSaver>(writeJsonCleaned);
837  mOutputWs.emplace_back(std::make_shared<WPeopleJsonSaver<TDatumsPtr>>(peopleJsonSaver));
838  }
839  // Write people pose data on disk (COCO validation json format)
840  if (!wrapperStructOutput.writeCocoJson.empty())
841  {
842  // If humanFormat: bigger size (& maybe slower to process), but easier for user to read it
843  const auto humanFormat = true;
844  const auto cocoJsonSaver = std::make_shared<CocoJsonSaver>(wrapperStructOutput.writeCocoJson,
845  humanFormat);
846  mOutputWs.emplace_back(std::make_shared<WCocoJsonSaver<TDatumsPtr>>(cocoJsonSaver));
847  }
848  // Write frames as desired image format on hard disk
849  if (!writeImagesCleaned.empty())
850  {
851  const auto imageSaver = std::make_shared<ImageSaver>(writeImagesCleaned,
852  wrapperStructOutput.writeImagesFormat);
853  mOutputWs.emplace_back(std::make_shared<WImageSaver<TDatumsPtr>>(imageSaver));
854  }
855  // Write frames as *.avi video on hard disk
856  if (!wrapperStructOutput.writeVideo.empty() && wrapperStructInput.producerSharedPtr != nullptr)
857  {
858  if (finalOutputSize.x <= 0 || finalOutputSize.y <= 0)
859  error("Video can only be recorded if outputSize is fixed (e.g. video, webcam, IP camera),"
860  "but not for a image directory.", __LINE__, __FUNCTION__, __FILE__);
861  const auto originalVideoFps = (wrapperStructInput.producerSharedPtr->get(CV_CAP_PROP_FPS) > 0.
862  ? wrapperStructInput.producerSharedPtr->get(CV_CAP_PROP_FPS) : 30.);
863  const auto videoSaver = std::make_shared<VideoSaver>(
864  wrapperStructOutput.writeVideo, CV_FOURCC('M','J','P','G'), originalVideoFps, finalOutputSize
865  );
866  mOutputWs.emplace_back(std::make_shared<WVideoSaver<TDatumsPtr>>(videoSaver));
867  }
868  // Write heat maps as desired image format on hard disk
869  if (!writeHeatMapsCleaned.empty())
870  {
871  const auto heatMapSaver = std::make_shared<HeatMapSaver>(writeHeatMapsCleaned,
872  wrapperStructOutput.writeHeatMapsFormat);
873  mOutputWs.emplace_back(std::make_shared<WHeatMapSaver<TDatumsPtr>>(heatMapSaver));
874  }
875  // Add frame information for GUI
876  const bool guiEnabled = (wrapperStructOutput.displayMode != DisplayMode::NoDisplay);
877  // If this WGuiInfoAdder instance is placed before the WImageSaver or WVideoSaver, then the resulting
878  // recorded frames will look exactly as the final displayed image by the GUI
879  if (wrapperStructOutput.guiVerbose && (guiEnabled || !mUserOutputWs.empty()
880  || mThreadManagerMode == ThreadManagerMode::Asynchronous
881  || mThreadManagerMode == ThreadManagerMode::AsynchronousOut))
882  {
883  const auto guiInfoAdder = std::make_shared<GuiInfoAdder>(numberThreads, guiEnabled);
884  mOutputWs.emplace_back(std::make_shared<WGuiInfoAdder<TDatumsPtr>>(guiInfoAdder));
885  }
886  // Minimal graphical user interface (GUI)
887  spWGui = nullptr;
888  if (guiEnabled)
889  {
890  // PoseRenderers to Renderers
891  std::vector<std::shared_ptr<Renderer>> renderers;
892  if (wrapperStructPose.renderMode == RenderMode::Cpu)
893  renderers.emplace_back(std::static_pointer_cast<Renderer>(poseCpuRenderer));
894  else
895  for (const auto& poseGpuRenderer : poseGpuRenderers)
896  renderers.emplace_back(std::static_pointer_cast<Renderer>(poseGpuRenderer));
897  // Display
898  // 3-D (+2-D) display
899  if (wrapperStructOutput.displayMode == DisplayMode::Display3D
900  || wrapperStructOutput.displayMode == DisplayMode::DisplayAll)
901  {
902  // Gui
903  auto gui = std::make_shared<Gui3D>(
904  finalOutputSize, wrapperStructOutput.fullScreen, mThreadManager.getIsRunningSharedPtr(),
905  spVideoSeek, poseExtractors, renderers, wrapperStructPose.poseModel,
906  wrapperStructOutput.displayMode
907  );
908  // WGui
909  spWGui = {std::make_shared<WGui3D<TDatumsPtr>>(gui)};
910  }
911  // 2-D display
912  else if (wrapperStructOutput.displayMode == DisplayMode::Display2D)
913  {
914  // Gui
915  auto gui = std::make_shared<Gui>(
916  finalOutputSize, wrapperStructOutput.fullScreen, mThreadManager.getIsRunningSharedPtr(),
917  spVideoSeek, poseExtractors, renderers
918  );
919  // WGui
920  spWGui = {std::make_shared<WGui<TDatumsPtr>>(gui)};
921  }
922  else
923  error("Unknown DisplayMode.", __LINE__, __FUNCTION__, __FILE__);
924  }
925  // Set wrapper as configured
926  mConfigured = true;
927  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
928  }
929  catch (const std::exception& e)
930  {
931  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
932  }
933  }
934 
935  template<typename TDatums, typename TWorker, typename TQueue>
937  {
938  try
939  {
940  configureThreadManager();
941  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
942  mThreadManager.exec();
943  }
944  catch (const std::exception& e)
945  {
946  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
947  }
948  }
949 
950  template<typename TDatums, typename TWorker, typename TQueue>
952  {
953  try
954  {
955  configureThreadManager();
956  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
957  mThreadManager.start();
958  }
959  catch (const std::exception& e)
960  {
961  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
962  }
963  }
964 
965  template<typename TDatums, typename TWorker, typename TQueue>
967  {
968  try
969  {
970  mThreadManager.stop();
971  }
972  catch (const std::exception& e)
973  {
974  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
975  }
976  }
977 
978  template<typename TDatums, typename TWorker, typename TQueue>
980  {
981  try
982  {
983  return mThreadManager.isRunning();
984  }
985  catch (const std::exception& e)
986  {
987  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
988  return false;
989  }
990  }
991 
992  template<typename TDatums, typename TWorker, typename TQueue>
993  bool Wrapper<TDatums, TWorker, TQueue>::tryEmplace(std::shared_ptr<TDatums>& tDatums)
994  {
995  try
996  {
997  if (!mUserInputWs.empty())
998  error("Emplace cannot be called if an input worker was already selected.",
999  __LINE__, __FUNCTION__, __FILE__);
1000  return mThreadManager.tryEmplace(tDatums);
1001  }
1002  catch (const std::exception& e)
1003  {
1004  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
1005  return false;
1006  }
1007  }
1008 
1009  template<typename TDatums, typename TWorker, typename TQueue>
1010  bool Wrapper<TDatums, TWorker, TQueue>::waitAndEmplace(std::shared_ptr<TDatums>& tDatums)
1011  {
1012  try
1013  {
1014  if (!mUserInputWs.empty())
1015  error("Emplace cannot be called if an input worker was already selected.",
1016  __LINE__, __FUNCTION__, __FILE__);
1017  return mThreadManager.waitAndEmplace(tDatums);
1018  }
1019  catch (const std::exception& e)
1020  {
1021  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
1022  return false;
1023  }
1024  }
1025 
1026  template<typename TDatums, typename TWorker, typename TQueue>
1027  bool Wrapper<TDatums, TWorker, TQueue>::tryPush(const std::shared_ptr<TDatums>& tDatums)
1028  {
1029  try
1030  {
1031  if (!mUserInputWs.empty())
1032  error("Push cannot be called if an input worker was already selected.",
1033  __LINE__, __FUNCTION__, __FILE__);
1034  return mThreadManager.tryPush(tDatums);
1035  }
1036  catch (const std::exception& e)
1037  {
1038  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
1039  return false;
1040  }
1041  }
1042 
1043  template<typename TDatums, typename TWorker, typename TQueue>
1044  bool Wrapper<TDatums, TWorker, TQueue>::waitAndPush(const std::shared_ptr<TDatums>& tDatums)
1045  {
1046  try
1047  {
1048  if (!mUserInputWs.empty())
1049  error("Push cannot be called if an input worker was already selected.",
1050  __LINE__, __FUNCTION__, __FILE__);
1051  return mThreadManager.waitAndPush(tDatums);
1052  }
1053  catch (const std::exception& e)
1054  {
1055  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
1056  return false;
1057  }
1058  }
1059 
1060  template<typename TDatums, typename TWorker, typename TQueue>
1061  bool Wrapper<TDatums, TWorker, TQueue>::tryPop(std::shared_ptr<TDatums>& tDatums)
1062  {
1063  try
1064  {
1065  if (!mUserOutputWs.empty())
1066  error("Pop cannot be called if an output worker was already selected.",
1067  __LINE__, __FUNCTION__, __FILE__);
1068  return mThreadManager.tryPop(tDatums);
1069  }
1070  catch (const std::exception& e)
1071  {
1072  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
1073  return false;
1074  }
1075  }
1076 
1077  template<typename TDatums, typename TWorker, typename TQueue>
1078  bool Wrapper<TDatums, TWorker, TQueue>::waitAndPop(std::shared_ptr<TDatums>& tDatums)
1079  {
1080  try
1081  {
1082  if (!mUserOutputWs.empty())
1083  error("Pop cannot be called if an output worker was already selected.",
1084  __LINE__, __FUNCTION__, __FILE__);
1085  return mThreadManager.waitAndPop(tDatums);
1086  }
1087  catch (const std::exception& e)
1088  {
1089  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
1090  return false;
1091  }
1092  }
1093 
1094  template<typename TDatums, typename TWorker, typename TQueue>
1096  {
1097  try
1098  {
1099  mConfigured = false;
1100  mThreadManager.reset();
1101  mThreadId = 0ull;
1102  // Reset
1103  mUserInputWs.clear();
1104  wDatumProducer = nullptr;
1105  spWScaleAndSizeExtractor = nullptr;
1106  spWCvMatToOpInput = nullptr;
1107  spWCvMatToOpOutput = nullptr;
1108  spWPoses.clear();
1109  mPostProcessingWs.clear();
1110  mUserPostProcessingWs.clear();
1111  mOutputWs.clear();
1112  spWGui = nullptr;
1113  mUserOutputWs.clear();
1114  }
1115  catch (const std::exception& e)
1116  {
1117  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
1118  }
1119  }
1120 
1121  template<typename TDatums, typename TWorker, typename TQueue>
1122  void Wrapper<TDatums, TWorker, TQueue>::configureThreadManager()
1123  {
1124  try
1125  {
1126  // The less number of queues -> the less lag
1127 
1128  // Security checks
1129  if (!mConfigured)
1130  error("Configure the Wrapper class before calling `start()`.", __LINE__, __FUNCTION__, __FILE__);
1131  if ((wDatumProducer == nullptr) == (mUserInputWs.empty())
1132  && mThreadManagerMode != ThreadManagerMode::Asynchronous
1133  && mThreadManagerMode != ThreadManagerMode::AsynchronousIn)
1134  {
1135  const auto message = "You need to have 1 and only 1 producer selected. You can introduce your own"
1136  " producer by using setWorkerInput() or use the OpenPose default producer by"
1137  " configuring it in the configure function) or use the"
1138  " ThreadManagerMode::Asynchronous(In) mode.";
1139  error(message, __LINE__, __FUNCTION__, __FILE__);
1140  }
1141  if (mOutputWs.empty() && mUserOutputWs.empty() && spWGui == nullptr
1142  && mThreadManagerMode != ThreadManagerMode::Asynchronous
1143  && mThreadManagerMode != ThreadManagerMode::AsynchronousOut)
1144  {
1145  error("No output selected.", __LINE__, __FUNCTION__, __FILE__);
1146  }
1147 
1148  // Thread Manager:
1149  // Clean previous thread manager (avoid configure to crash the program if used more than once)
1150  mThreadManager.reset();
1151  mThreadId = 0ull;
1152  auto queueIn = 0ull;
1153  auto queueOut = 1ull;
1154  // If custom user Worker and uses its own thread
1155  spWIdGenerator = std::make_shared<WIdGenerator<std::shared_ptr<TDatums>>>();
1156  if (!mUserInputWs.empty() && mUserInputWsOnNewThread)
1157  {
1158  // Thread 0, queues 0 -> 1
1159  mThreadManager.add(mThreadId, mUserInputWs, queueIn++, queueOut++);
1160  if (spWScaleAndSizeExtractor != nullptr && spWCvMatToOpInput != nullptr)
1161  {
1162  threadIdPP();
1163  // Thread 1, queues 1 -> 2
1164  if (spWCvMatToOpOutput == nullptr)
1165  mThreadManager.add(mThreadId, {spWIdGenerator, spWScaleAndSizeExtractor, spWCvMatToOpInput},
1166  queueIn++, queueOut++);
1167  else
1168  mThreadManager.add(mThreadId, {spWIdGenerator, spWScaleAndSizeExtractor, spWCvMatToOpInput,
1169  spWCvMatToOpOutput}, queueIn++, queueOut++);
1170  }
1171  else
1172  mThreadManager.add(mThreadId, spWIdGenerator, queueIn++, queueOut++);
1173  }
1174  // If custom user Worker in same thread or producer on same thread
1175  else
1176  {
1177  std::vector<TWorker> workersAux;
1178  // Custom user Worker
1179  if (!mUserInputWs.empty())
1180  workersAux = mergeVectors(workersAux, mUserInputWs);
1181  // OpenPose producer
1182  else if (wDatumProducer != nullptr)
1183  workersAux = mergeVectors(workersAux, {wDatumProducer});
1184  // Otherwise
1185  else if (mThreadManagerMode != ThreadManagerMode::Asynchronous
1186  && mThreadManagerMode != ThreadManagerMode::AsynchronousIn)
1187  error("No input selected.", __LINE__, __FUNCTION__, __FILE__);
1188  // ID generator
1189  workersAux = mergeVectors(workersAux, {spWIdGenerator});
1190  // Scale & cv::Mat to OP format
1191  if (spWScaleAndSizeExtractor != nullptr && spWCvMatToOpInput != nullptr)
1192  workersAux = mergeVectors(workersAux, {spWScaleAndSizeExtractor,
1193  spWCvMatToOpInput});
1194  // cv::Mat to output format
1195  if (spWCvMatToOpOutput != nullptr)
1196  workersAux = mergeVectors(workersAux, {spWCvMatToOpOutput});
1197  // Thread 0 or 1, queues 0 -> 1
1198  mThreadManager.add(mThreadId, workersAux, queueIn++, queueOut++);
1199  }
1200  threadIdPP();
1201  // Pose estimation & rendering
1202  // Thread 1 or 2...X, queues 1 -> 2, X = 2 + #GPUs
1203  if (!spWPoses.empty())
1204  {
1205  if (mMultiThreadEnabled)
1206  {
1207  for (auto& wPose : spWPoses)
1208  {
1209  mThreadManager.add(mThreadId, wPose, queueIn, queueOut);
1210  threadIdPP();
1211  }
1212  }
1213  else
1214  {
1215  if (spWPoses.size() > 1)
1216  log("Multi-threading disabled, only 1 thread running. All GPUs have been disabled but the"
1217  " first one, which is defined by gpuNumberStart (e.g. in the OpenPose demo, it is set"
1218  " with the `--num_gpu_start` flag).", Priority::High);
1219  mThreadManager.add(mThreadId, spWPoses.at(0), queueIn, queueOut);
1220  }
1221  queueIn++;
1222  queueOut++;
1223  }
1224  // If custom user Worker and uses its own thread
1225  if (!mUserPostProcessingWs.empty() && mUserPostProcessingWsOnNewThread)
1226  {
1227  // Post processing workers
1228  if (!mPostProcessingWs.empty())
1229  {
1230  // Thread 2 or 3, queues 2 -> 3
1231  mThreadManager.add(mThreadId, mPostProcessingWs, queueIn++, queueOut++);
1232  threadIdPP();
1233  }
1234  // User processing workers
1235  // Thread 3 or 4, queues 3 -> 4
1236  mThreadManager.add(mThreadId, mUserPostProcessingWs, queueIn++, queueOut++);
1237  threadIdPP();
1238  // Output workers
1239  if (!mOutputWs.empty())
1240  {
1241  // Thread 4 or 5, queues 4 -> 5
1242  mThreadManager.add(mThreadId, mOutputWs, queueIn++, queueOut++);
1243  threadIdPP();
1244  }
1245  }
1246  // If custom user Worker in same thread or producer on same thread
1247  else
1248  {
1249  // Post processing workers + User post processing workers + Output workers
1250  auto workersAux = mergeVectors(mPostProcessingWs, mUserPostProcessingWs);
1251  workersAux = mergeVectors(workersAux, mOutputWs);
1252  if (!workersAux.empty())
1253  {
1254  // Thread 2 or 3, queues 2 -> 3
1255  mThreadManager.add(mThreadId, workersAux, queueIn++, queueOut++);
1256  threadIdPP();
1257  }
1258  }
1259  // User output worker
1260  // Thread Y, queues Q -> Q+1
1261  if (!mUserOutputWs.empty())
1262  {
1263  if (mUserOutputWsOnNewThread)
1264  {
1265  mThreadManager.add(mThreadId, mUserOutputWs, queueIn++, queueOut++);
1266  threadIdPP();
1267  }
1268  else
1269  mThreadManager.add(mThreadId-1, mUserOutputWs, queueIn++, queueOut++);
1270  }
1271  // OpenPose GUI
1272  if (spWGui != nullptr)
1273  {
1274  // Thread Y+1, queues Q+1 -> Q+2
1275  mThreadManager.add(mThreadId, spWGui, queueIn++, queueOut++);
1276  threadIdPP();
1277  }
1278  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
1279  }
1280  catch (const std::exception& e)
1281  {
1282  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
1283  }
1284  }
1285 
1286  template<typename TDatums, typename TWorker, typename TQueue>
1287  unsigned long long Wrapper<TDatums, TWorker, TQueue>::threadIdPP()
1288  {
1289  try
1290  {
1291  if (mMultiThreadEnabled)
1292  mThreadId++;
1293  return mThreadId;
1294  }
1295  catch (const std::exception& e)
1296  {
1297  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
1298  return 0ull;
1299  }
1300  }
1301 
1302  extern template class Wrapper<DATUM_BASE_NO_PTR>;
1303 }
1304 
1305 #endif // OPENPOSE_WRAPPER_WRAPPER_HPP
PoseModel poseModel
Definition: wrapperStructPose.hpp:88
Point< int > netInputSize
Definition: wrapperStructPose.hpp:31
float alphaHeatMap
Definition: wrapperStructPose.hpp:106
Definition: wHandDetectorTracking.hpp:11
Wrapper(const ThreadManagerMode threadManagerMode=ThreadManagerMode::Synchronous)
Definition: wrapper.hpp:278
Definition: wGuiInfoAdder.hpp:11
Definition: wPersonIdExtractor.hpp:11
float alphaHeatMap
Definition: wrapperStructFace.hpp:45
ScaleMode heatMapScale
Definition: wrapperStructPose.hpp:135
bool guiVerbose
Definition: wrapperStructOutput.hpp:31
std::vector< HeatMapType > heatMapTypes
Definition: wrapperStructPose.hpp:127
std::string writeHeatMapsFormat
Definition: wrapperStructOutput.hpp:101
bool addPartCandidates
Definition: wrapperStructPose.hpp:141
OP_API void wrapperConfigureSecurityChecks(const WrapperStructPose &wrapperStructPose, const WrapperStructFace &wrapperStructFace, const WrapperStructHand &wrapperStructHand, const WrapperStructInput &wrapperStructInput, const WrapperStructOutput &wrapperStructOutput, const bool renderOutput, const bool userOutputWsEmpty, const ThreadManagerMode threadManagerMode)
Definition: wPoseSaver.hpp:12
bool identification
Definition: wrapperStructPose.hpp:181
bool tryPush(const std::shared_ptr< TDatums > &tDatums)
Definition: wrapper.hpp:1027
Definition: wrapperStructPose.hpp:17
std::string writeKeypoint
Definition: wrapperStructOutput.hpp:44
float alphaKeypoint
Definition: wrapperStructFace.hpp:39
bool frameFlip
Definition: wrapperStructInput.hpp:41
Definition: wFaceSaver.hpp:12
void stop()
Definition: wrapper.hpp:966
float alphaKeypoint
Definition: wrapperStructHand.hpp:59
bool tryPop(std::shared_ptr< TDatums > &tDatums)
Definition: wrapper.hpp:1061
void exec()
Definition: wrapper.hpp:936
Definition: wPeopleJsonSaver.hpp:11
int defaultPartToRender
Definition: wrapperStructPose.hpp:115
Definition: wHandRenderer.hpp:11
Definition: wFaceExtractor.hpp:11
void setWorkerPostProcessing(const TWorker &worker, const bool workerOnNewThread=true)
Definition: wrapper.hpp:342
Definition: wImageSaver.hpp:11
std::string writeImages
Definition: wrapperStructOutput.hpp:73
float alphaHeatMap
Definition: wrapperStructHand.hpp:65
bool framesRepeat
Definition: wrapperStructInput.hpp:52
Definition: wKeypointScaler.hpp:11
std::string writeHeatMaps
Definition: wrapperStructOutput.hpp:95
std::string writeCocoJson
Definition: wrapperStructOutput.hpp:67
Definition: wFaceDetector.hpp:11
bool enable
Definition: wrapperStructPose.hpp:24
Definition: wrapperStructFace.hpp:15
Point< int > outputSize
Definition: wrapperStructPose.hpp:39
OP_API void error(const std::string &message, const int line=-1, const std::string &function="", const std::string &file="")
bool fullScreen
Definition: wrapperStructOutput.hpp:37
Definition: wKeepTopNPeople.hpp:11
DataFormat writeKeypointFormat
Definition: wrapperStructOutput.hpp:51
float scaleGap
Definition: wrapperStructPose.hpp:75
RenderMode renderMode
Definition: wrapperStructPose.hpp:81
bool waitAndEmplace(std::shared_ptr< TDatums > &tDatums)
Definition: wrapper.hpp:1010
Definition: wrapper.hpp:32
bool tryEmplace(std::shared_ptr< TDatums > &tDatums)
Definition: wrapper.hpp:993
float scaleRange
Definition: wrapperStructHand.hpp:40
OP_API GpuMode getGpuMode()
int gpuNumberStart
Definition: wrapperStructPose.hpp:60
RenderMode renderMode
Definition: wrapperStructFace.hpp:33
bool tracking
Definition: wrapperStructHand.hpp:47
bool enable
Definition: wrapperStructFace.hpp:20
Definition: wFaceDetectorOpenCV.hpp:11
Definition: wQueueOrderer.hpp:12
Definition: wVideoSaver.hpp:11
Definition: wOpOutputToCvMat.hpp:11
bool waitAndPush(const std::shared_ptr< TDatums > &tDatums)
Definition: wrapper.hpp:1044
void start()
Definition: wrapper.hpp:951
bool realTimeProcessing
Definition: wrapperStructInput.hpp:36
OP_API std::string formatAsDirectory(const std::string &directoryPathString)
Definition: wHandExtractor.hpp:11
Definition: wHandDetectorUpdate.hpp:11
Definition: wrapperStructInput.hpp:13
std::string modelFolder
Definition: wrapperStructPose.hpp:120
int numberPeopleMax
Definition: wrapperStructPose.hpp:159
void configure(const WrapperStructPose &wrapperStructPose, const WrapperStructInput &wrapperStructInput, const WrapperStructOutput &wrapperStructOutput=WrapperStructOutput{})
Definition: wrapper.hpp:377
int scalesNumber
Definition: wrapperStructPose.hpp:68
Definition: wFaceRenderer.hpp:11
bool waitAndPop(std::shared_ptr< TDatums > &tDatums)
Definition: wrapper.hpp:1078
std::shared_ptr< Producer > producerSharedPtr
Definition: wrapperStructInput.hpp:19
Definition: threadManager.hpp:16
Definition: wPoseRenderer.hpp:11
std::string writeJson
Definition: wrapperStructOutput.hpp:61
OP_API void log(const std::string &message, const Priority priority=Priority::Max, const int line=-1, const std::string &function="", const std::string &file="")
Definition: wCocoJsonSaver.hpp:11
~Wrapper()
Definition: wrapper.hpp:298
Definition: wrapperStructHand.hpp:15
float renderThreshold
Definition: wrapperStructHand.hpp:72
Definition: poseGpuRenderer.hpp:13
Definition: wHandDetector.hpp:11
bool enableGoogleLogging
Definition: wrapperStructPose.hpp:168
std::vector< T > mergeVectors(const std::vector< T > &vectorA, const std::vector< T > &vectorB)
Definition: standard.hpp:40
Definition: wHandSaver.hpp:12
std::string writeVideo
Definition: wrapperStructOutput.hpp:88
unsigned long long frameLast
Definition: wrapperStructInput.hpp:31
DisplayMode displayMode
Definition: wrapperStructOutput.hpp:25
Point< int > netInputSize
Definition: wrapperStructFace.hpp:27
float renderThreshold
Definition: wrapperStructPose.hpp:149
void setSharedParametersAndIfLast(const std::tuple< std::shared_ptr< float * >, std::shared_ptr< bool >, std::shared_ptr< std::atomic< unsigned int >>, std::shared_ptr< std::atomic< unsigned long long >>, std::shared_ptr< const unsigned int >> &tuple, const bool isLast)
Definition: wPoseTriangulation.hpp:11
float alphaKeypoint
Definition: wrapperStructPose.hpp:99
void setWorkerOutput(const TWorker &worker, const bool workerOnNewThread=true)
Definition: wrapper.hpp:360
Definition: wHeatMapSaver.hpp:11
bool enable
Definition: wrapperStructHand.hpp:20
ScaleMode keypointScale
Definition: wrapperStructPose.hpp:47
ThreadManagerMode
Definition: enumClasses.hpp:9
int gpuNumber
Definition: wrapperStructPose.hpp:54
bool isRunning() const
Definition: wrapper.hpp:979
void setWorkerInput(const TWorker &worker, const bool workerOnNewThread=true)
Definition: wrapper.hpp:325
float renderThreshold
Definition: wrapperStructFace.hpp:52
int frameRotate
Definition: wrapperStructInput.hpp:47
std::string writeImagesFormat
Definition: wrapperStructOutput.hpp:81
unsigned long long frameFirst
Definition: wrapperStructInput.hpp:25
Definition: wrapperStructOutput.hpp:14
void disableMultiThreading()
Definition: wrapper.hpp:312
OP_API int getGpuNumber()
Point< int > netInputSize
Definition: wrapperStructHand.hpp:27
bool blendOriginalFrame
Definition: wrapperStructPose.hpp:93
bool reconstruct3d
Definition: wrapperStructPose.hpp:176
int scalesNumber
Definition: wrapperStructHand.hpp:34
RenderMode renderMode
Definition: wrapperStructHand.hpp:53