From f36c3dc2d4931c567d28410d233525a58154bcd1 Mon Sep 17 00:00:00 2001 From: Travis CI Date: Thu, 3 Jan 2019 21:53:23 +0000 Subject: [PATCH] Deploy code docs to GitHub Pages Travis build: 475 Commit: c783eeb616590abb4ed53067b6e6974195eda462 --- doxygen.log | 2 +- html/wrapper_auxiliary_8hpp_source.html | 1412 ++++++++++++----------- 2 files changed, 731 insertions(+), 683 deletions(-) diff --git a/doxygen.log b/doxygen.log index dfe53fd4..ab45c9dd 100644 --- a/doxygen.log +++ b/doxygen.log @@ -1269,5 +1269,5 @@ Generating file index... Generating file member index... Generating example index... finalizing index lists... -lookup cache used 5088/65536 hits=39579 misses=5461 +lookup cache used 5088/65536 hits=39717 misses=5461 finished... diff --git a/html/wrapper_auxiliary_8hpp_source.html b/html/wrapper_auxiliary_8hpp_source.html index b58da57a..661210e7 100644 --- a/html/wrapper_auxiliary_8hpp_source.html +++ b/html/wrapper_auxiliary_8hpp_source.html @@ -424,694 +424,742 @@ $(document).ready(function(){initNavTree('wrapper_auxiliary_8hpp_source.html',''
342  // wPose.emplace_back(std::make_shared<WKeepTopNPeople<TDatumsSP>>(keepTopNPeople));
343  // }
344  }
-
345 
+
345  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
346 
347  // Face extractor(s)
348  if (wrapperStructFace.enable)
349  {
-
350  // Face detector
-
351  // OpenPose face detector
-
352  if (wrapperStructPose.enable)
-
353  {
-
354  const auto faceDetector = std::make_shared<FaceDetector>(wrapperStructPose.poseModel);
-
355  for (auto& wPose : poseExtractorsWs)
-
356  wPose.emplace_back(std::make_shared<WFaceDetector<TDatumsSP>>(faceDetector));
-
357  }
-
358  // OpenCV face detector
-
359  else
-
360  {
-
361  log("Body keypoint detection is disabled. Hence, using OpenCV face detector (much less"
-
362  " accurate but faster).", Priority::High);
-
363  for (auto& wPose : poseExtractorsWs)
-
364  {
-
365  // 1 FaceDetectorOpenCV per thread, OpenCV face detector is not thread-safe
-
366  const auto faceDetectorOpenCV = std::make_shared<FaceDetectorOpenCV>(modelFolder);
-
367  wPose.emplace_back(
-
368  std::make_shared<WFaceDetectorOpenCV<TDatumsSP>>(faceDetectorOpenCV)
-
369  );
-
370  }
-
371  }
-
372  // Face keypoint extractor
-
373  for (auto gpu = 0u; gpu < poseExtractorsWs.size(); gpu++)
-
374  {
-
375  // Face keypoint extractor
-
376  const auto netOutputSize = wrapperStructFace.netInputSize;
-
377  const auto faceExtractorNet = std::make_shared<FaceExtractorCaffe>(
-
378  wrapperStructFace.netInputSize, netOutputSize, modelFolder,
-
379  gpu + gpuNumberStart, wrapperStructPose.heatMapTypes, wrapperStructPose.heatMapScale,
-
380  wrapperStructPose.enableGoogleLogging
-
381  );
-
382  faceExtractorNets.emplace_back(faceExtractorNet);
-
383  poseExtractorsWs.at(gpu).emplace_back(
-
384  std::make_shared<WFaceExtractorNet<TDatumsSP>>(faceExtractorNet));
-
385  }
-
386  }
-
387 
-
388  // Hand extractor(s)
-
389  if (wrapperStructHand.enable)
-
390  {
-
391  const auto handDetector = std::make_shared<HandDetector>(wrapperStructPose.poseModel);
-
392  for (auto gpu = 0u; gpu < poseExtractorsWs.size(); gpu++)
-
393  {
-
394  // Hand detector
-
395  // If tracking
-
396  if (wrapperStructHand.tracking)
-
397  poseExtractorsWs.at(gpu).emplace_back(
-
398  std::make_shared<WHandDetectorTracking<TDatumsSP>>(handDetector)
-
399  );
-
400  // If detection
-
401  else
-
402  poseExtractorsWs.at(gpu).emplace_back(
-
403  std::make_shared<WHandDetector<TDatumsSP>>(handDetector));
-
404  // Hand keypoint extractor
-
405  const auto netOutputSize = wrapperStructHand.netInputSize;
-
406  const auto handExtractorNet = std::make_shared<HandExtractorCaffe>(
-
407  wrapperStructHand.netInputSize, netOutputSize, modelFolder,
-
408  gpu + gpuNumberStart, wrapperStructHand.scalesNumber, wrapperStructHand.scaleRange,
-
409  wrapperStructPose.heatMapTypes, wrapperStructPose.heatMapScale,
-
410  wrapperStructPose.enableGoogleLogging
-
411  );
-
412  handExtractorNets.emplace_back(handExtractorNet);
-
413  poseExtractorsWs.at(gpu).emplace_back(
-
414  std::make_shared<WHandExtractorNet<TDatumsSP>>(handExtractorNet)
-
415  );
-
416  // If tracking
-
417  if (wrapperStructHand.tracking)
-
418  poseExtractorsWs.at(gpu).emplace_back(
-
419  std::make_shared<WHandDetectorUpdate<TDatumsSP>>(handDetector)
-
420  );
-
421  }
-
422  }
-
423 
-
424  // Pose renderer(s)
-
425  if (!poseGpuRenderers.empty())
-
426  for (auto i = 0u; i < poseExtractorsWs.size(); i++)
-
427  poseExtractorsWs.at(i).emplace_back(std::make_shared<WPoseRenderer<TDatumsSP>>(
-
428  poseGpuRenderers.at(i)
-
429  ));
-
430 
-
431  // Face renderer(s)
-
432  if (renderFace)
-
433  {
-
434  // CPU rendering
-
435  if (wrapperStructFace.renderMode == RenderMode::Cpu)
-
436  {
-
437  // Construct face renderer
-
438  const auto faceRenderer = std::make_shared<FaceCpuRenderer>(wrapperStructFace.renderThreshold,
-
439  wrapperStructFace.alphaKeypoint,
-
440  wrapperStructFace.alphaHeatMap);
-
441  // Add worker
-
442  cpuRenderers.emplace_back(std::make_shared<WFaceRenderer<TDatumsSP>>(faceRenderer));
-
443  }
-
444  // GPU rendering
-
445  else if (wrapperStructFace.renderMode == RenderMode::Gpu)
-
446  {
-
447  for (auto i = 0u; i < poseExtractorsWs.size(); i++)
-
448  {
-
449  // Construct face renderer
-
450  const auto faceRenderer = std::make_shared<FaceGpuRenderer>(
-
451  wrapperStructFace.renderThreshold, wrapperStructFace.alphaKeypoint,
-
452  wrapperStructFace.alphaHeatMap
-
453  );
-
454  // Performance boost -> share spGpuMemory for all renderers
-
455  if (!poseGpuRenderers.empty())
-
456  {
-
457  const bool isLastRenderer = !renderHandGpu;
-
458  const auto renderer = std::static_pointer_cast<PoseGpuRenderer>(
-
459  poseGpuRenderers.at(i)
-
460  );
-
461  faceRenderer->setSharedParametersAndIfLast(renderer->getSharedParameters(),
-
462  isLastRenderer);
-
463  }
-
464  // Add worker
-
465  poseExtractorsWs.at(i).emplace_back(
-
466  std::make_shared<WFaceRenderer<TDatumsSP>>(faceRenderer));
-
467  }
-
468  }
-
469  else
-
470  error("Unknown RenderMode.", __LINE__, __FUNCTION__, __FILE__);
-
471  }
-
472 
-
473  // Hand renderer(s)
-
474  if (renderHand)
-
475  {
-
476  // CPU rendering
-
477  if (wrapperStructHand.renderMode == RenderMode::Cpu)
-
478  {
-
479  // Construct hand renderer
-
480  const auto handRenderer = std::make_shared<HandCpuRenderer>(wrapperStructHand.renderThreshold,
-
481  wrapperStructHand.alphaKeypoint,
-
482  wrapperStructHand.alphaHeatMap);
-
483  // Add worker
-
484  cpuRenderers.emplace_back(std::make_shared<WHandRenderer<TDatumsSP>>(handRenderer));
-
485  }
-
486  // GPU rendering
-
487  else if (wrapperStructHand.renderMode == RenderMode::Gpu)
-
488  {
-
489  for (auto i = 0u; i < poseExtractorsWs.size(); i++)
-
490  {
-
491  // Construct hands renderer
-
492  const auto handRenderer = std::make_shared<HandGpuRenderer>(
-
493  wrapperStructHand.renderThreshold, wrapperStructHand.alphaKeypoint,
-
494  wrapperStructHand.alphaHeatMap
-
495  );
-
496  // Performance boost -> share spGpuMemory for all renderers
-
497  if (!poseGpuRenderers.empty())
-
498  {
-
499  const bool isLastRenderer = true;
-
500  const auto renderer = std::static_pointer_cast<PoseGpuRenderer>(
-
501  poseGpuRenderers.at(i)
-
502  );
-
503  handRenderer->setSharedParametersAndIfLast(renderer->getSharedParameters(),
-
504  isLastRenderer);
-
505  }
-
506  // Add worker
-
507  poseExtractorsWs.at(i).emplace_back(
-
508  std::make_shared<WHandRenderer<TDatumsSP>>(handRenderer));
-
509  }
-
510  }
-
511  else
-
512  error("Unknown RenderMode.", __LINE__, __FUNCTION__, __FILE__);
-
513  }
-
514 
-
515  // 3-D reconstruction
-
516  poseTriangulationsWs.clear();
-
517  if (wrapperStructExtra.reconstruct3d)
-
518  {
-
519  // For all (body/face/hands): PoseTriangulations ~30 msec, 8 GPUS ~30 msec for keypoint estimation
-
520  poseTriangulationsWs.resize(fastMax(1, int(poseExtractorsWs.size() / 4)));
-
521  for (auto i = 0u ; i < poseTriangulationsWs.size() ; i++)
-
522  {
-
523  const auto poseTriangulation = std::make_shared<PoseTriangulation>(
-
524  wrapperStructExtra.minViews3d);
-
525  poseTriangulationsWs.at(i) = {std::make_shared<WPoseTriangulation<TDatumsSP>>(
-
526  poseTriangulation)};
-
527  }
-
528  }
-
529  // Itermediate workers (e.g., OpenPose format to cv::Mat, json & frames recorder, ...)
-
530  postProcessingWs.clear();
-
531  // // Person ID identification (when no multi-thread and no dependency on tracking)
-
532  // if (wrapperStructExtra.identification)
-
533  // {
-
534  // const auto personIdExtractor = std::make_shared<PersonIdExtractor>();
-
535  // postProcessingWs.emplace_back(
-
536  // std::make_shared<WPersonIdExtractor<TDatumsSP>>(personIdExtractor)
-
537  // );
-
538  // }
-
539  // Frames processor (OpenPose format -> cv::Mat format)
-
540  if (renderOutput)
-
541  {
-
542  postProcessingWs = mergeVectors(postProcessingWs, cpuRenderers);
-
543  const auto opOutputToCvMat = std::make_shared<OpOutputToCvMat>();
-
544  postProcessingWs.emplace_back(std::make_shared<WOpOutputToCvMat<TDatumsSP>>(opOutputToCvMat));
-
545  }
-
546  // Re-scale pose if desired
-
547  // If desired scale is not the current input
-
548  if (wrapperStructPose.keypointScale != ScaleMode::InputResolution
-
549  // and desired scale is not output when size(input) = size(output)
-
550  && !(wrapperStructPose.keypointScale == ScaleMode::OutputResolution &&
-
551  (finalOutputSize == producerSize || finalOutputSize.x <= 0 || finalOutputSize.y <= 0))
-
552  // and desired scale is not net output when size(input) = size(net output)
-
553  && !(wrapperStructPose.keypointScale == ScaleMode::NetOutputResolution
-
554  && producerSize == wrapperStructPose.netInputSize))
+
350  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
351  // Face detector
+
352  // OpenPose face detector
+
353  if (wrapperStructPose.enable)
+
354  {
+
355  const auto faceDetector = std::make_shared<FaceDetector>(wrapperStructPose.poseModel);
+
356  for (auto& wPose : poseExtractorsWs)
+
357  wPose.emplace_back(std::make_shared<WFaceDetector<TDatumsSP>>(faceDetector));
+
358  }
+
359  // OpenCV face detector
+
360  else
+
361  {
+
362  log("Body keypoint detection is disabled. Hence, using OpenCV face detector (much less"
+
363  " accurate but faster).", Priority::High);
+
364  for (auto& wPose : poseExtractorsWs)
+
365  {
+
366  // 1 FaceDetectorOpenCV per thread, OpenCV face detector is not thread-safe
+
367  const auto faceDetectorOpenCV = std::make_shared<FaceDetectorOpenCV>(modelFolder);
+
368  wPose.emplace_back(
+
369  std::make_shared<WFaceDetectorOpenCV<TDatumsSP>>(faceDetectorOpenCV)
+
370  );
+
371  }
+
372  }
+
373  // Face keypoint extractor
+
374  for (auto gpu = 0u; gpu < poseExtractorsWs.size(); gpu++)
+
375  {
+
376  // Face keypoint extractor
+
377  const auto netOutputSize = wrapperStructFace.netInputSize;
+
378  const auto faceExtractorNet = std::make_shared<FaceExtractorCaffe>(
+
379  wrapperStructFace.netInputSize, netOutputSize, modelFolder,
+
380  gpu + gpuNumberStart, wrapperStructPose.heatMapTypes, wrapperStructPose.heatMapScale,
+
381  wrapperStructPose.enableGoogleLogging
+
382  );
+
383  faceExtractorNets.emplace_back(faceExtractorNet);
+
384  poseExtractorsWs.at(gpu).emplace_back(
+
385  std::make_shared<WFaceExtractorNet<TDatumsSP>>(faceExtractorNet));
+
386  }
+
387  }
+
388  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
389 
+
390  // Hand extractor(s)
+
391  if (wrapperStructHand.enable)
+
392  {
+
393  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
394  const auto handDetector = std::make_shared<HandDetector>(wrapperStructPose.poseModel);
+
395  for (auto gpu = 0u; gpu < poseExtractorsWs.size(); gpu++)
+
396  {
+
397  // Hand detector
+
398  // If tracking
+
399  if (wrapperStructHand.tracking)
+
400  poseExtractorsWs.at(gpu).emplace_back(
+
401  std::make_shared<WHandDetectorTracking<TDatumsSP>>(handDetector)
+
402  );
+
403  // If detection
+
404  else
+
405  poseExtractorsWs.at(gpu).emplace_back(
+
406  std::make_shared<WHandDetector<TDatumsSP>>(handDetector));
+
407  // Hand keypoint extractor
+
408  const auto netOutputSize = wrapperStructHand.netInputSize;
+
409  const auto handExtractorNet = std::make_shared<HandExtractorCaffe>(
+
410  wrapperStructHand.netInputSize, netOutputSize, modelFolder,
+
411  gpu + gpuNumberStart, wrapperStructHand.scalesNumber, wrapperStructHand.scaleRange,
+
412  wrapperStructPose.heatMapTypes, wrapperStructPose.heatMapScale,
+
413  wrapperStructPose.enableGoogleLogging
+
414  );
+
415  handExtractorNets.emplace_back(handExtractorNet);
+
416  poseExtractorsWs.at(gpu).emplace_back(
+
417  std::make_shared<WHandExtractorNet<TDatumsSP>>(handExtractorNet)
+
418  );
+
419  // If tracking
+
420  if (wrapperStructHand.tracking)
+
421  poseExtractorsWs.at(gpu).emplace_back(
+
422  std::make_shared<WHandDetectorUpdate<TDatumsSP>>(handDetector)
+
423  );
+
424  }
+
425  }
+
426  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
427 
+
428  // Pose renderer(s)
+
429  if (!poseGpuRenderers.empty())
+
430  {
+
431  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
432  for (auto i = 0u; i < poseExtractorsWs.size(); i++)
+
433  poseExtractorsWs.at(i).emplace_back(std::make_shared<WPoseRenderer<TDatumsSP>>(
+
434  poseGpuRenderers.at(i)
+
435  ));
+
436  }
+
437  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
438 
+
439  // Face renderer(s)
+
440  if (renderFace)
+
441  {
+
442  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
443  // CPU rendering
+
444  if (wrapperStructFace.renderMode == RenderMode::Cpu)
+
445  {
+
446  // Construct face renderer
+
447  const auto faceRenderer = std::make_shared<FaceCpuRenderer>(wrapperStructFace.renderThreshold,
+
448  wrapperStructFace.alphaKeypoint,
+
449  wrapperStructFace.alphaHeatMap);
+
450  // Add worker
+
451  cpuRenderers.emplace_back(std::make_shared<WFaceRenderer<TDatumsSP>>(faceRenderer));
+
452  }
+
453  // GPU rendering
+
454  else if (wrapperStructFace.renderMode == RenderMode::Gpu)
+
455  {
+
456  for (auto i = 0u; i < poseExtractorsWs.size(); i++)
+
457  {
+
458  // Construct face renderer
+
459  const auto faceRenderer = std::make_shared<FaceGpuRenderer>(
+
460  wrapperStructFace.renderThreshold, wrapperStructFace.alphaKeypoint,
+
461  wrapperStructFace.alphaHeatMap
+
462  );
+
463  // Performance boost -> share spGpuMemory for all renderers
+
464  if (!poseGpuRenderers.empty())
+
465  {
+
466  const bool isLastRenderer = !renderHandGpu;
+
467  const auto renderer = std::static_pointer_cast<PoseGpuRenderer>(
+
468  poseGpuRenderers.at(i)
+
469  );
+
470  faceRenderer->setSharedParametersAndIfLast(renderer->getSharedParameters(),
+
471  isLastRenderer);
+
472  }
+
473  // Add worker
+
474  poseExtractorsWs.at(i).emplace_back(
+
475  std::make_shared<WFaceRenderer<TDatumsSP>>(faceRenderer));
+
476  }
+
477  }
+
478  else
+
479  error("Unknown RenderMode.", __LINE__, __FUNCTION__, __FILE__);
+
480  }
+
481  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
482 
+
483  // Hand renderer(s)
+
484  if (renderHand)
+
485  {
+
486  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
487  // CPU rendering
+
488  if (wrapperStructHand.renderMode == RenderMode::Cpu)
+
489  {
+
490  // Construct hand renderer
+
491  const auto handRenderer = std::make_shared<HandCpuRenderer>(wrapperStructHand.renderThreshold,
+
492  wrapperStructHand.alphaKeypoint,
+
493  wrapperStructHand.alphaHeatMap);
+
494  // Add worker
+
495  cpuRenderers.emplace_back(std::make_shared<WHandRenderer<TDatumsSP>>(handRenderer));
+
496  }
+
497  // GPU rendering
+
498  else if (wrapperStructHand.renderMode == RenderMode::Gpu)
+
499  {
+
500  for (auto i = 0u; i < poseExtractorsWs.size(); i++)
+
501  {
+
502  // Construct hands renderer
+
503  const auto handRenderer = std::make_shared<HandGpuRenderer>(
+
504  wrapperStructHand.renderThreshold, wrapperStructHand.alphaKeypoint,
+
505  wrapperStructHand.alphaHeatMap
+
506  );
+
507  // Performance boost -> share spGpuMemory for all renderers
+
508  if (!poseGpuRenderers.empty())
+
509  {
+
510  const bool isLastRenderer = true;
+
511  const auto renderer = std::static_pointer_cast<PoseGpuRenderer>(
+
512  poseGpuRenderers.at(i)
+
513  );
+
514  handRenderer->setSharedParametersAndIfLast(renderer->getSharedParameters(),
+
515  isLastRenderer);
+
516  }
+
517  // Add worker
+
518  poseExtractorsWs.at(i).emplace_back(
+
519  std::make_shared<WHandRenderer<TDatumsSP>>(handRenderer));
+
520  }
+
521  }
+
522  else
+
523  error("Unknown RenderMode.", __LINE__, __FUNCTION__, __FILE__);
+
524  }
+
525  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
526 
+
527  // 3-D reconstruction
+
528  poseTriangulationsWs.clear();
+
529  if (wrapperStructExtra.reconstruct3d)
+
530  {
+
531  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
532  // For all (body/face/hands): PoseTriangulations ~30 msec, 8 GPUS ~30 msec for keypoint estimation
+
533  poseTriangulationsWs.resize(fastMax(1, int(poseExtractorsWs.size() / 4)));
+
534  for (auto i = 0u ; i < poseTriangulationsWs.size() ; i++)
+
535  {
+
536  const auto poseTriangulation = std::make_shared<PoseTriangulation>(
+
537  wrapperStructExtra.minViews3d);
+
538  poseTriangulationsWs.at(i) = {std::make_shared<WPoseTriangulation<TDatumsSP>>(
+
539  poseTriangulation)};
+
540  }
+
541  }
+
542  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
543  // Itermediate workers (e.g., OpenPose format to cv::Mat, json & frames recorder, ...)
+
544  postProcessingWs.clear();
+
545  // // Person ID identification (when no multi-thread and no dependency on tracking)
+
546  // if (wrapperStructExtra.identification)
+
547  // {
+
548  // const auto personIdExtractor = std::make_shared<PersonIdExtractor>();
+
549  // postProcessingWs.emplace_back(
+
550  // std::make_shared<WPersonIdExtractor<TDatumsSP>>(personIdExtractor)
+
551  // );
+
552  // }
+
553  // Frames processor (OpenPose format -> cv::Mat format)
+
554  if (renderOutput)
555  {
-
556  // Then we must rescale the keypoints
-
557  auto keypointScaler = std::make_shared<KeypointScaler>(wrapperStructPose.keypointScale);
-
558  postProcessingWs.emplace_back(std::make_shared<WKeypointScaler<TDatumsSP>>(keypointScaler));
-
559  }
-
560  }
-
561 
-
562  // IK/Adam
-
563  const auto displayAdam = wrapperStructGui.displayMode == DisplayMode::DisplayAdam
-
564  || (wrapperStructGui.displayMode == DisplayMode::DisplayAll
-
565  && wrapperStructExtra.ikThreads > 0);
-
566  jointAngleEstimationsWs.clear();
-
567 #ifdef USE_3D_ADAM_MODEL
-
568  if (wrapperStructExtra.ikThreads > 0)
-
569  {
-
570  jointAngleEstimationsWs.resize(wrapperStructExtra.ikThreads);
-
571  // Pose extractor(s)
-
572  for (auto i = 0u; i < jointAngleEstimationsWs.size(); i++)
-
573  {
-
574  const auto jointAngleEstimation = std::make_shared<JointAngleEstimation>(displayAdam);
-
575  jointAngleEstimationsWs.at(i) = {std::make_shared<WJointAngleEstimation<TDatumsSP>>(
-
576  jointAngleEstimation)};
-
577  }
-
578  }
-
579 #endif
-
580 
-
581  // Output workers
-
582  std::vector<TWorker> outputWs;
-
583  // Print verbose
-
584  if (wrapperStructOutput.verbose > 0.)
-
585  {
-
586  const auto verbosePrinter = std::make_shared<VerbosePrinter>(
-
587  wrapperStructOutput.verbose, producerSharedPtr->get(CV_CAP_PROP_FRAME_COUNT));
-
588  outputWs.emplace_back(std::make_shared<WVerbosePrinter<TDatumsSP>>(verbosePrinter));
-
589  }
-
590  // Send information (e.g., to Unity) though UDP client-server communication
-
591 
-
592 #ifdef USE_3D_ADAM_MODEL
-
593  if (!wrapperStructOutput.udpHost.empty() && !wrapperStructOutput.udpPort.empty())
-
594  {
-
595  const auto udpSender = std::make_shared<UdpSender>(wrapperStructOutput.udpHost,
-
596  wrapperStructOutput.udpPort);
-
597  outputWs.emplace_back(std::make_shared<WUdpSender<TDatumsSP>>(udpSender));
-
598  }
-
599 #endif
-
600  // Write people pose data on disk (json for OpenCV >= 3, xml, yml...)
-
601  if (!writeKeypointCleaned.empty())
-
602  {
-
603  const auto keypointSaver = std::make_shared<KeypointSaver>(writeKeypointCleaned,
-
604  wrapperStructOutput.writeKeypointFormat);
-
605  outputWs.emplace_back(std::make_shared<WPoseSaver<TDatumsSP>>(keypointSaver));
-
606  if (wrapperStructFace.enable)
-
607  outputWs.emplace_back(std::make_shared<WFaceSaver<TDatumsSP>>(keypointSaver));
-
608  if (wrapperStructHand.enable)
-
609  outputWs.emplace_back(std::make_shared<WHandSaver<TDatumsSP>>(keypointSaver));
-
610  }
-
611  // Write OpenPose output data on disk in json format (body/hand/face keypoints, body part locations if
-
612  // enabled, etc.)
-
613  if (!writeJsonCleaned.empty())
-
614  {
-
615  const auto peopleJsonSaver = std::make_shared<PeopleJsonSaver>(writeJsonCleaned);
-
616  outputWs.emplace_back(std::make_shared<WPeopleJsonSaver<TDatumsSP>>(peopleJsonSaver));
-
617  }
-
618  // Write people pose data on disk (COCO validation json format)
-
619  if (!wrapperStructOutput.writeCocoJson.empty())
-
620  {
-
621  // If humanFormat: bigger size (& maybe slower to process), but easier for user to read it
-
622  const auto humanFormat = true;
-
623  const auto cocoJsonSaver = std::make_shared<CocoJsonSaver>(
-
624  wrapperStructOutput.writeCocoJson, wrapperStructPose.poseModel, humanFormat,
-
625  (wrapperStructPose.poseModel != PoseModel::CAR_22
-
626  && wrapperStructPose.poseModel != PoseModel::CAR_12
-
627  ? CocoJsonFormat::Body : CocoJsonFormat::Car),
-
628  wrapperStructOutput.writeCocoJsonVariant);
-
629  outputWs.emplace_back(std::make_shared<WCocoJsonSaver<TDatumsSP>>(cocoJsonSaver));
-
630  }
-
631  // Write people foot pose data on disk (COCO validation json format for foot data)
-
632  if (!wrapperStructOutput.writeCocoFootJson.empty())
-
633  {
-
634  // If humanFormat: bigger size (& maybe slower to process), but easier for user to read it
-
635  const auto humanFormat = true;
-
636  const auto cocoJsonSaver = std::make_shared<CocoJsonSaver>(
-
637  wrapperStructOutput.writeCocoFootJson, wrapperStructPose.poseModel, humanFormat,
-
638  CocoJsonFormat::Foot);
-
639  outputWs.emplace_back(std::make_shared<WCocoJsonSaver<TDatumsSP>>(cocoJsonSaver));
-
640  }
-
641  // Write frames as desired image format on hard disk
-
642  if (!writeImagesCleaned.empty())
-
643  {
-
644  const auto imageSaver = std::make_shared<ImageSaver>(writeImagesCleaned,
-
645  wrapperStructOutput.writeImagesFormat);
-
646  outputWs.emplace_back(std::make_shared<WImageSaver<TDatumsSP>>(imageSaver));
-
647  }
-
648  auto originalVideoFps = 0.;
-
649  if (!wrapperStructOutput.writeVideo.empty() || !wrapperStructOutput.writeVideo3D.empty()
-
650  || !wrapperStructOutput.writeBvh.empty())
-
651  {
-
652  if (wrapperStructOutput.writeVideoFps <= 0
-
653  && (!oPProducer || producerSharedPtr->get(CV_CAP_PROP_FPS) <= 0))
-
654  error("The frame rate of the frames producer is unknown. Set `--write_video_fps` to your desired"
-
655  " FPS if you wanna record video (`--write_video`). E.g., if it is a folder of images, you"
-
656  " will have to know or guess the frame rate; if it is a webcam, you should use the OpenPose"
-
657  " displayed FPS as desired value. If you do not care, simply add `--write_video_fps 30`.",
-
658  __LINE__, __FUNCTION__, __FILE__);
-
659  originalVideoFps = (
-
660  wrapperStructOutput.writeVideoFps > 0 ?
-
661  wrapperStructOutput.writeVideoFps : producerSharedPtr->get(CV_CAP_PROP_FPS));
-
662  }
-
663  // Write frames as *.avi video on hard disk
-
664  if (!wrapperStructOutput.writeVideo.empty())
-
665  {
-
666  if (!oPProducer)
-
667  error("Video file can only be recorded inside `wrapper/wrapper.hpp` if the producer"
-
668  " is one of the default ones (e.g., video, webcam, ...).",
-
669  __LINE__, __FUNCTION__, __FILE__);
-
670  const auto videoSaver = std::make_shared<VideoSaver>(
-
671  wrapperStructOutput.writeVideo, CV_FOURCC('M','J','P','G'), originalVideoFps);
-
672  outputWs.emplace_back(std::make_shared<WVideoSaver<TDatumsSP>>(videoSaver));
-
673  }
-
674  // Write joint angles as *.bvh file on hard disk
-
675 #ifdef USE_3D_ADAM_MODEL
-
676  if (!wrapperStructOutput.writeBvh.empty())
-
677  {
-
678  const auto bvhSaver = std::make_shared<BvhSaver>(
-
679  wrapperStructOutput.writeBvh, JointAngleEstimation::getTotalModel(), originalVideoFps
-
680  );
-
681  outputWs.emplace_back(std::make_shared<WBvhSaver<TDatumsSP>>(bvhSaver));
-
682  }
-
683 #endif
-
684  // Write heat maps as desired image format on hard disk
-
685  if (!writeHeatMapsCleaned.empty())
-
686  {
-
687  const auto heatMapSaver = std::make_shared<HeatMapSaver>(
-
688  writeHeatMapsCleaned, wrapperStructOutput.writeHeatMapsFormat);
-
689  outputWs.emplace_back(std::make_shared<WHeatMapSaver<TDatumsSP>>(heatMapSaver));
-
690  }
-
691  // Add frame information for GUI
-
692  const bool guiEnabled = (wrapperStructGui.displayMode != DisplayMode::NoDisplay);
-
693  // If this WGuiInfoAdder instance is placed before the WImageSaver or WVideoSaver, then the resulting
-
694  // recorded frames will look exactly as the final displayed image by the GUI
-
695  if (wrapperStructGui.guiVerbose && (guiEnabled || !userOutputWs.empty()
-
696  || threadManagerMode == ThreadManagerMode::Asynchronous
-
697  || threadManagerMode == ThreadManagerMode::AsynchronousOut))
-
698  {
-
699  const auto guiInfoAdder = std::make_shared<GuiInfoAdder>(numberThreads, guiEnabled);
-
700  outputWs.emplace_back(std::make_shared<WGuiInfoAdder<TDatumsSP>>(guiInfoAdder));
-
701  }
-
702  // Minimal graphical user interface (GUI)
-
703  TWorker guiW;
-
704  TWorker videoSaver3DW;
-
705  if (guiEnabled)
-
706  {
-
707  // PoseRenderers to Renderers
-
708  std::vector<std::shared_ptr<Renderer>> renderers;
-
709  if (wrapperStructPose.renderMode == RenderMode::Cpu)
-
710  renderers.emplace_back(std::static_pointer_cast<Renderer>(poseCpuRenderer));
-
711  else
-
712  for (const auto& poseGpuRenderer : poseGpuRenderers)
-
713  renderers.emplace_back(std::static_pointer_cast<Renderer>(poseGpuRenderer));
-
714  // Display
-
715  const auto numberViews = (intRound(producerSharedPtr->get(ProducerProperty::NumberViews)));
-
716  auto finalOutputSizeGui = finalOutputSize;
-
717  if (numberViews > 1 && finalOutputSizeGui.x > 0)
-
718  finalOutputSizeGui.x *= numberViews;
-
719  // Adam (+3-D/2-D) display
-
720  if (displayAdam)
-
721  {
-
722 #ifdef USE_3D_ADAM_MODEL
-
723  // Gui
-
724  const auto gui = std::make_shared<GuiAdam>(
-
725  finalOutputSizeGui, wrapperStructGui.fullScreen, threadManager.getIsRunningSharedPtr(),
-
726  spVideoSeek, poseExtractorNets, faceExtractorNets, handExtractorNets, renderers,
-
727  wrapperStructGui.displayMode, JointAngleEstimation::getTotalModel(),
-
728  wrapperStructOutput.writeVideoAdam
-
729  );
-
730  // WGui
-
731  guiW = {std::make_shared<WGuiAdam<TDatumsSP>>(gui)};
-
732  // Write 3D frames as *.avi video on hard disk
-
733  if (!wrapperStructOutput.writeVideo3D.empty())
-
734  error("3D video can only be recorded if 3D render is enabled.",
-
735  __LINE__, __FUNCTION__, __FILE__);
-
736 #endif
-
737  }
-
738  // 3-D (+2-D) display
-
739  else if (wrapperStructGui.displayMode == DisplayMode::Display3D
-
740  || wrapperStructGui.displayMode == DisplayMode::DisplayAll)
-
741  {
-
742  // Gui
-
743  const auto gui = std::make_shared<Gui3D>(
-
744  finalOutputSizeGui, wrapperStructGui.fullScreen, threadManager.getIsRunningSharedPtr(),
-
745  spVideoSeek, poseExtractorNets, faceExtractorNets, handExtractorNets, renderers,
-
746  wrapperStructPose.poseModel, wrapperStructGui.displayMode,
-
747  !wrapperStructOutput.writeVideo3D.empty()
-
748  );
-
749  // WGui
-
750  guiW = {std::make_shared<WGui3D<TDatumsSP>>(gui)};
-
751  // Write 3D frames as *.avi video on hard disk
-
752  if (!wrapperStructOutput.writeVideo3D.empty())
-
753  {
-
754  const auto videoSaver = std::make_shared<VideoSaver>(
-
755  wrapperStructOutput.writeVideo3D, CV_FOURCC('M','J','P','G'), originalVideoFps);
-
756  videoSaver3DW = std::make_shared<WVideoSaver3D<TDatumsSP>>(videoSaver);
-
757  }
-
758  }
-
759  // 2-D display
-
760  else if (wrapperStructGui.displayMode == DisplayMode::Display2D)
-
761  {
-
762  // Gui
-
763  const auto gui = std::make_shared<Gui>(
-
764  finalOutputSizeGui, wrapperStructGui.fullScreen, threadManager.getIsRunningSharedPtr(),
-
765  spVideoSeek, poseExtractorNets, faceExtractorNets, handExtractorNets, renderers
-
766  );
-
767  // WGui
-
768  guiW = {std::make_shared<WGui<TDatumsSP>>(gui)};
-
769  // Write 3D frames as *.avi video on hard disk
-
770  if (!wrapperStructOutput.writeVideo3D.empty())
-
771  error("3D video can only be recorded if 3D render is enabled.",
-
772  __LINE__, __FUNCTION__, __FILE__);
-
773  }
-
774  else
-
775  error("Unknown DisplayMode.", __LINE__, __FUNCTION__, __FILE__);
-
776  }
-
777  // Set FpsMax
-
778  TWorker wFpsMax;
-
779  if (wrapperStructPose.fpsMax > 0.)
-
780  wFpsMax = std::make_shared<WFpsMax<TDatumsSP>>(wrapperStructPose.fpsMax);
-
781  // Set wrapper as configured
-
782  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
783 
-
784 
-
785 
-
786 
-
787 
-
788  // The less number of queues -> the less threads opened, and potentially the less lag
-
789 
-
790  // Sanity checks
-
791  if ((datumProducerW == nullptr) == (userInputWs.empty())
-
792  && threadManagerMode != ThreadManagerMode::Asynchronous
-
793  && threadManagerMode != ThreadManagerMode::AsynchronousIn)
-
794  {
-
795  const auto message = "You need to have 1 and only 1 producer selected. You can introduce your own"
-
796  " producer by using setWorker(WorkerType::Input, ...) or use the OpenPose"
-
797  " default producer by configuring it in the configure function) or use the"
-
798  " ThreadManagerMode::Asynchronous(In) mode.";
-
799  error(message, __LINE__, __FUNCTION__, __FILE__);
-
800  }
-
801  if (outputWs.empty() && userOutputWs.empty() && guiW == nullptr
-
802  && threadManagerMode != ThreadManagerMode::Asynchronous
-
803  && threadManagerMode != ThreadManagerMode::AsynchronousOut)
-
804  {
-
805  error("No output selected.", __LINE__, __FUNCTION__, __FILE__);
-
806  }
-
807 
-
808  // Thread Manager
-
809  // Clean previous thread manager (avoid configure to crash the program if used more than once)
-
810  threadManager.reset();
-
811  unsigned long long threadId = 0ull;
-
812  auto queueIn = 0ull;
-
813  auto queueOut = 1ull;
-
814  // After producer
-
815  // ID generator (before any multi-threading or any function that requires the ID)
-
816  const auto wIdGenerator = std::make_shared<WIdGenerator<TDatumsSP>>();
-
817  std::vector<TWorker> workersAux{wIdGenerator};
-
818  // Scale & cv::Mat to OP format
-
819  if (scaleAndSizeExtractorW != nullptr)
-
820  workersAux = mergeVectors(workersAux, {scaleAndSizeExtractorW});
-
821  if (cvMatToOpInputW != nullptr)
-
822  workersAux = mergeVectors(workersAux, {cvMatToOpInputW});
-
823  // cv::Mat to output format
-
824  if (cvMatToOpOutputW != nullptr)
-
825  workersAux = mergeVectors(workersAux, {cvMatToOpOutputW});
-
826 
-
827  // Producer
-
828  // If custom user Worker and uses its own thread
-
829  if (!userInputWs.empty() && userInputWsOnNewThread)
-
830  {
-
831  // Thread 0, queues 0 -> 1
-
832  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
833  threadManager.add(threadId, userInputWs, queueIn++, queueOut++);
-
834  threadIdPP(threadId, multiThreadEnabled);
-
835  }
-
836  // If custom user Worker in same thread
-
837  else if (!userInputWs.empty())
-
838  workersAux = mergeVectors(userInputWs, workersAux);
-
839  // If OpenPose producer (same thread)
-
840  else if (datumProducerW != nullptr)
-
841  workersAux = mergeVectors({datumProducerW}, workersAux);
-
842  // Otherwise
-
843  else if (threadManagerMode != ThreadManagerMode::Asynchronous
-
844  && threadManagerMode != ThreadManagerMode::AsynchronousIn)
-
845  error("No input selected.", __LINE__, __FUNCTION__, __FILE__);
-
846  // Thread 0 or 1, queues 0 -> 1
-
847  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
848  threadManager.add(threadId, workersAux, queueIn++, queueOut++);
-
849  // Increase thread
-
850  threadIdPP(threadId, multiThreadEnabled);
-
851 
-
852  // Pose estimation & rendering
-
853  // Thread 1 or 2...X, queues 1 -> 2, X = 2 + #GPUs
-
854  if (!poseExtractorsWs.empty())
-
855  {
-
856  if (multiThreadEnabled)
-
857  {
-
858  for (auto& wPose : poseExtractorsWs)
-
859  {
-
860  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
861  threadManager.add(threadId, wPose, queueIn, queueOut);
-
862  threadIdPP(threadId, multiThreadEnabled);
-
863  }
-
864  queueIn++;
-
865  queueOut++;
-
866  // Sort frames - Required own thread
-
867  if (poseExtractorsWs.size() > 1u)
-
868  {
-
869  const auto wQueueOrderer = std::make_shared<WQueueOrderer<TDatumsSP>>();
-
870  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
871  threadManager.add(threadId, wQueueOrderer, queueIn++, queueOut++);
-
872  threadIdPP(threadId, multiThreadEnabled);
-
873  }
-
874  }
-
875  else
-
876  {
-
877  if (poseExtractorsWs.size() > 1)
-
878  log("Multi-threading disabled, only 1 thread running. All GPUs have been disabled but the"
-
879  " first one, which is defined by gpuNumberStart (e.g., in the OpenPose demo, it is set"
-
880  " with the `--num_gpu_start` flag).", Priority::High);
-
881  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
882  threadManager.add(threadId, poseExtractorsWs.at(0), queueIn++, queueOut++);
-
883  }
-
884  }
-
885  // Assemble all frames from same time instant (3-D module)
-
886  const auto wQueueAssembler = std::make_shared<WQueueAssembler<TDatumsSP, TDatums>>();
-
887  // 3-D reconstruction
-
888  if (!poseTriangulationsWs.empty())
-
889  {
-
890  // Assemble frames
-
891  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
892  threadManager.add(threadId, wQueueAssembler, queueIn++, queueOut++);
-
893  threadIdPP(threadId, multiThreadEnabled);
-
894  // 3-D reconstruction
-
895  if (multiThreadEnabled)
-
896  {
-
897  for (auto& wPoseTriangulations : poseTriangulationsWs)
-
898  {
-
899  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
900  threadManager.add(threadId, wPoseTriangulations, queueIn, queueOut);
-
901  threadIdPP(threadId, multiThreadEnabled);
-
902  }
-
903  queueIn++;
-
904  queueOut++;
-
905  // Sort frames
-
906  if (poseTriangulationsWs.size() > 1u)
+
556  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
557  postProcessingWs = mergeVectors(postProcessingWs, cpuRenderers);
+
558  const auto opOutputToCvMat = std::make_shared<OpOutputToCvMat>();
+
559  postProcessingWs.emplace_back(std::make_shared<WOpOutputToCvMat<TDatumsSP>>(opOutputToCvMat));
+
560  }
+
561  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
562  // Re-scale pose if desired
+
563  // If desired scale is not the current input
+
564  if (wrapperStructPose.keypointScale != ScaleMode::InputResolution
+
565  // and desired scale is not output when size(input) = size(output)
+
566  && !(wrapperStructPose.keypointScale == ScaleMode::OutputResolution &&
+
567  (finalOutputSize == producerSize || finalOutputSize.x <= 0 || finalOutputSize.y <= 0))
+
568  // and desired scale is not net output when size(input) = size(net output)
+
569  && !(wrapperStructPose.keypointScale == ScaleMode::NetOutputResolution
+
570  && producerSize == wrapperStructPose.netInputSize))
+
571  {
+
572  // Then we must rescale the keypoints
+
573  auto keypointScaler = std::make_shared<KeypointScaler>(wrapperStructPose.keypointScale);
+
574  postProcessingWs.emplace_back(std::make_shared<WKeypointScaler<TDatumsSP>>(keypointScaler));
+
575  }
+
576  }
+
577  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
578 
+
579  // IK/Adam
+
580  const auto displayAdam = wrapperStructGui.displayMode == DisplayMode::DisplayAdam
+
581  || (wrapperStructGui.displayMode == DisplayMode::DisplayAll
+
582  && wrapperStructExtra.ikThreads > 0);
+
583  jointAngleEstimationsWs.clear();
+
584 #ifdef USE_3D_ADAM_MODEL
+
585  if (wrapperStructExtra.ikThreads > 0)
+
586  {
+
587  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
588  jointAngleEstimationsWs.resize(wrapperStructExtra.ikThreads);
+
589  // Pose extractor(s)
+
590  for (auto i = 0u; i < jointAngleEstimationsWs.size(); i++)
+
591  {
+
592  const auto jointAngleEstimation = std::make_shared<JointAngleEstimation>(displayAdam);
+
593  jointAngleEstimationsWs.at(i) = {std::make_shared<WJointAngleEstimation<TDatumsSP>>(
+
594  jointAngleEstimation)};
+
595  }
+
596  }
+
597  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
598 #endif
+
599 
+
600  // Output workers
+
601  std::vector<TWorker> outputWs;
+
602  // Print verbose
+
603  if (wrapperStructOutput.verbose > 0.)
+
604  {
+
605  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
606  const auto verbosePrinter = std::make_shared<VerbosePrinter>(
+
607  wrapperStructOutput.verbose, producerSharedPtr->get(CV_CAP_PROP_FRAME_COUNT));
+
608  outputWs.emplace_back(std::make_shared<WVerbosePrinter<TDatumsSP>>(verbosePrinter));
+
609  }
+
610  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
611  // Send information (e.g., to Unity) though UDP client-server communication
+
612 
+
613 #ifdef USE_3D_ADAM_MODEL
+
614  if (!wrapperStructOutput.udpHost.empty() && !wrapperStructOutput.udpPort.empty())
+
615  {
+
616  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
617  const auto udpSender = std::make_shared<UdpSender>(wrapperStructOutput.udpHost,
+
618  wrapperStructOutput.udpPort);
+
619  outputWs.emplace_back(std::make_shared<WUdpSender<TDatumsSP>>(udpSender));
+
620  }
+
621  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
622 #endif
+
623  // Write people pose data on disk (json for OpenCV >= 3, xml, yml...)
+
624  if (!writeKeypointCleaned.empty())
+
625  {
+
626  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
627  const auto keypointSaver = std::make_shared<KeypointSaver>(writeKeypointCleaned,
+
628  wrapperStructOutput.writeKeypointFormat);
+
629  outputWs.emplace_back(std::make_shared<WPoseSaver<TDatumsSP>>(keypointSaver));
+
630  if (wrapperStructFace.enable)
+
631  outputWs.emplace_back(std::make_shared<WFaceSaver<TDatumsSP>>(keypointSaver));
+
632  if (wrapperStructHand.enable)
+
633  outputWs.emplace_back(std::make_shared<WHandSaver<TDatumsSP>>(keypointSaver));
+
634  }
+
635  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
636  // Write OpenPose output data on disk in json format (body/hand/face keypoints, body part locations if
+
637  // enabled, etc.)
+
638  if (!writeJsonCleaned.empty())
+
639  {
+
640  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
641  const auto peopleJsonSaver = std::make_shared<PeopleJsonSaver>(writeJsonCleaned);
+
642  outputWs.emplace_back(std::make_shared<WPeopleJsonSaver<TDatumsSP>>(peopleJsonSaver));
+
643  }
+
644  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
645  // Write people pose data on disk (COCO validation json format)
+
646  if (!wrapperStructOutput.writeCocoJson.empty())
+
647  {
+
648  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
649  // If humanFormat: bigger size (& maybe slower to process), but easier for user to read it
+
650  const auto humanFormat = true;
+
651  const auto cocoJsonSaver = std::make_shared<CocoJsonSaver>(
+
652  wrapperStructOutput.writeCocoJson, wrapperStructPose.poseModel, humanFormat,
+
653  (wrapperStructPose.poseModel != PoseModel::CAR_22
+
654  && wrapperStructPose.poseModel != PoseModel::CAR_12
+
655  ? CocoJsonFormat::Body : CocoJsonFormat::Car),
+
656  wrapperStructOutput.writeCocoJsonVariant);
+
657  outputWs.emplace_back(std::make_shared<WCocoJsonSaver<TDatumsSP>>(cocoJsonSaver));
+
658  }
+
659  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
660  // Write people foot pose data on disk (COCO validation json format for foot data)
+
661  if (!wrapperStructOutput.writeCocoFootJson.empty())
+
662  {
+
663  // If humanFormat: bigger size (& maybe slower to process), but easier for user to read it
+
664  const auto humanFormat = true;
+
665  const auto cocoJsonSaver = std::make_shared<CocoJsonSaver>(
+
666  wrapperStructOutput.writeCocoFootJson, wrapperStructPose.poseModel, humanFormat,
+
667  CocoJsonFormat::Foot);
+
668  outputWs.emplace_back(std::make_shared<WCocoJsonSaver<TDatumsSP>>(cocoJsonSaver));
+
669  }
+
670  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
671  // Write frames as desired image format on hard disk
+
672  if (!writeImagesCleaned.empty())
+
673  {
+
674  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
675  const auto imageSaver = std::make_shared<ImageSaver>(writeImagesCleaned,
+
676  wrapperStructOutput.writeImagesFormat);
+
677  outputWs.emplace_back(std::make_shared<WImageSaver<TDatumsSP>>(imageSaver));
+
678  }
+
679  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
680  auto originalVideoFps = 0.;
+
681  if (!wrapperStructOutput.writeVideo.empty() || !wrapperStructOutput.writeVideo3D.empty()
+
682  || !wrapperStructOutput.writeBvh.empty())
+
683  {
+
684  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
685  if (wrapperStructOutput.writeVideoFps <= 0
+
686  && (!oPProducer || producerSharedPtr->get(CV_CAP_PROP_FPS) <= 0))
+
687  error("The frame rate of the frames producer is unknown. Set `--write_video_fps` to your desired"
+
688  " FPS if you wanna record video (`--write_video`). E.g., if it is a folder of images, you"
+
689  " will have to know or guess the frame rate; if it is a webcam, you should use the OpenPose"
+
690  " displayed FPS as desired value. If you do not care, simply add `--write_video_fps 30`.",
+
691  __LINE__, __FUNCTION__, __FILE__);
+
692  originalVideoFps = (
+
693  wrapperStructOutput.writeVideoFps > 0 ?
+
694  wrapperStructOutput.writeVideoFps : producerSharedPtr->get(CV_CAP_PROP_FPS));
+
695  }
+
696  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
697  // Write frames as *.avi video on hard disk
+
698  if (!wrapperStructOutput.writeVideo.empty())
+
699  {
+
700  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
701  if (!oPProducer)
+
702  error("Video file can only be recorded inside `wrapper/wrapper.hpp` if the producer"
+
703  " is one of the default ones (e.g., video, webcam, ...).",
+
704  __LINE__, __FUNCTION__, __FILE__);
+
705  const auto videoSaver = std::make_shared<VideoSaver>(
+
706  wrapperStructOutput.writeVideo, CV_FOURCC('M','J','P','G'), originalVideoFps);
+
707  outputWs.emplace_back(std::make_shared<WVideoSaver<TDatumsSP>>(videoSaver));
+
708  }
+
709  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
710  // Write joint angles as *.bvh file on hard disk
+
711 #ifdef USE_3D_ADAM_MODEL
+
712  if (!wrapperStructOutput.writeBvh.empty())
+
713  {
+
714  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
715  const auto bvhSaver = std::make_shared<BvhSaver>(
+
716  wrapperStructOutput.writeBvh, JointAngleEstimation::getTotalModel(), originalVideoFps
+
717  );
+
718  outputWs.emplace_back(std::make_shared<WBvhSaver<TDatumsSP>>(bvhSaver));
+
719  }
+
720  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
721 #endif
+
722  // Write heat maps as desired image format on hard disk
+
723  if (!writeHeatMapsCleaned.empty())
+
724  {
+
725  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
726  const auto heatMapSaver = std::make_shared<HeatMapSaver>(
+
727  writeHeatMapsCleaned, wrapperStructOutput.writeHeatMapsFormat);
+
728  outputWs.emplace_back(std::make_shared<WHeatMapSaver<TDatumsSP>>(heatMapSaver));
+
729  }
+
730  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
731  // Add frame information for GUI
+
732  const bool guiEnabled = (wrapperStructGui.displayMode != DisplayMode::NoDisplay);
+
733  // If this WGuiInfoAdder instance is placed before the WImageSaver or WVideoSaver, then the resulting
+
734  // recorded frames will look exactly as the final displayed image by the GUI
+
735  if (wrapperStructGui.guiVerbose && (guiEnabled || !userOutputWs.empty()
+
736  || threadManagerMode == ThreadManagerMode::Asynchronous
+
737  || threadManagerMode == ThreadManagerMode::AsynchronousOut))
+
738  {
+
739  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
740  const auto guiInfoAdder = std::make_shared<GuiInfoAdder>(numberThreads, guiEnabled);
+
741  outputWs.emplace_back(std::make_shared<WGuiInfoAdder<TDatumsSP>>(guiInfoAdder));
+
742  }
+
743  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
744  // Minimal graphical user interface (GUI)
+
745  TWorker guiW;
+
746  TWorker videoSaver3DW;
+
747  if (guiEnabled)
+
748  {
+
749  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
750  // PoseRenderers to Renderers
+
751  std::vector<std::shared_ptr<Renderer>> renderers;
+
752  if (wrapperStructPose.renderMode == RenderMode::Cpu)
+
753  renderers.emplace_back(std::static_pointer_cast<Renderer>(poseCpuRenderer));
+
754  else
+
755  for (const auto& poseGpuRenderer : poseGpuRenderers)
+
756  renderers.emplace_back(std::static_pointer_cast<Renderer>(poseGpuRenderer));
+
757  // Display
+
758  const auto numberViews = (producerSharedPtr != nullptr
+
759  ? intRound(producerSharedPtr->get(ProducerProperty::NumberViews)) : 1);
+
760  auto finalOutputSizeGui = finalOutputSize;
+
761  if (numberViews > 1 && finalOutputSizeGui.x > 0)
+
762  finalOutputSizeGui.x *= numberViews;
+
763  // Adam (+3-D/2-D) display
+
764  if (displayAdam)
+
765  {
+
766 #ifdef USE_3D_ADAM_MODEL
+
767  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
768  // Gui
+
769  const auto gui = std::make_shared<GuiAdam>(
+
770  finalOutputSizeGui, wrapperStructGui.fullScreen, threadManager.getIsRunningSharedPtr(),
+
771  spVideoSeek, poseExtractorNets, faceExtractorNets, handExtractorNets, renderers,
+
772  wrapperStructGui.displayMode, JointAngleEstimation::getTotalModel(),
+
773  wrapperStructOutput.writeVideoAdam
+
774  );
+
775  // WGui
+
776  guiW = {std::make_shared<WGuiAdam<TDatumsSP>>(gui)};
+
777  // Write 3D frames as *.avi video on hard disk
+
778  if (!wrapperStructOutput.writeVideo3D.empty())
+
779  error("3D video can only be recorded if 3D render is enabled.",
+
780  __LINE__, __FUNCTION__, __FILE__);
+
781 #endif
+
782  }
+
783  // 3-D (+2-D) display
+
784  else if (wrapperStructGui.displayMode == DisplayMode::Display3D
+
785  || wrapperStructGui.displayMode == DisplayMode::DisplayAll)
+
786  {
+
787  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
788  // Gui
+
789  const auto gui = std::make_shared<Gui3D>(
+
790  finalOutputSizeGui, wrapperStructGui.fullScreen, threadManager.getIsRunningSharedPtr(),
+
791  spVideoSeek, poseExtractorNets, faceExtractorNets, handExtractorNets, renderers,
+
792  wrapperStructPose.poseModel, wrapperStructGui.displayMode,
+
793  !wrapperStructOutput.writeVideo3D.empty()
+
794  );
+
795  // WGui
+
796  guiW = {std::make_shared<WGui3D<TDatumsSP>>(gui)};
+
797  // Write 3D frames as *.avi video on hard disk
+
798  if (!wrapperStructOutput.writeVideo3D.empty())
+
799  {
+
800  const auto videoSaver = std::make_shared<VideoSaver>(
+
801  wrapperStructOutput.writeVideo3D, CV_FOURCC('M','J','P','G'), originalVideoFps);
+
802  videoSaver3DW = std::make_shared<WVideoSaver3D<TDatumsSP>>(videoSaver);
+
803  }
+
804  }
+
805  // 2-D display
+
806  else if (wrapperStructGui.displayMode == DisplayMode::Display2D)
+
807  {
+
808  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
809  // Gui
+
810  const auto gui = std::make_shared<Gui>(
+
811  finalOutputSizeGui, wrapperStructGui.fullScreen, threadManager.getIsRunningSharedPtr(),
+
812  spVideoSeek, poseExtractorNets, faceExtractorNets, handExtractorNets, renderers
+
813  );
+
814  // WGui
+
815  guiW = {std::make_shared<WGui<TDatumsSP>>(gui)};
+
816  // Write 3D frames as *.avi video on hard disk
+
817  if (!wrapperStructOutput.writeVideo3D.empty())
+
818  error("3D video can only be recorded if 3D render is enabled.",
+
819  __LINE__, __FUNCTION__, __FILE__);
+
820  }
+
821  else
+
822  error("Unknown DisplayMode.", __LINE__, __FUNCTION__, __FILE__);
+
823  }
+
824  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
825  // Set FpsMax
+
826  TWorker wFpsMax;
+
827  if (wrapperStructPose.fpsMax > 0.)
+
828  wFpsMax = std::make_shared<WFpsMax<TDatumsSP>>(wrapperStructPose.fpsMax);
+
829  // Set wrapper as configured
+
830  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
831 
+
832 
+
833 
+
834 
+
835 
+
836  // The less number of queues -> the less threads opened, and potentially the less lag
+
837 
+
838  // Sanity checks
+
839  if ((datumProducerW == nullptr) == (userInputWs.empty())
+
840  && threadManagerMode != ThreadManagerMode::Asynchronous
+
841  && threadManagerMode != ThreadManagerMode::AsynchronousIn)
+
842  {
+
843  const auto message = "You need to have 1 and only 1 producer selected. You can introduce your own"
+
844  " producer by using setWorker(WorkerType::Input, ...) or use the OpenPose"
+
845  " default producer by configuring it in the configure function) or use the"
+
846  " ThreadManagerMode::Asynchronous(In) mode.";
+
847  error(message, __LINE__, __FUNCTION__, __FILE__);
+
848  }
+
849  if (outputWs.empty() && userOutputWs.empty() && guiW == nullptr
+
850  && threadManagerMode != ThreadManagerMode::Asynchronous
+
851  && threadManagerMode != ThreadManagerMode::AsynchronousOut)
+
852  {
+
853  error("No output selected.", __LINE__, __FUNCTION__, __FILE__);
+
854  }
+
855 
+
856  // Thread Manager
+
857  // Clean previous thread manager (avoid configure to crash the program if used more than once)
+
858  threadManager.reset();
+
859  unsigned long long threadId = 0ull;
+
860  auto queueIn = 0ull;
+
861  auto queueOut = 1ull;
+
862  // After producer
+
863  // ID generator (before any multi-threading or any function that requires the ID)
+
864  const auto wIdGenerator = std::make_shared<WIdGenerator<TDatumsSP>>();
+
865  std::vector<TWorker> workersAux{wIdGenerator};
+
866  // Scale & cv::Mat to OP format
+
867  if (scaleAndSizeExtractorW != nullptr)
+
868  workersAux = mergeVectors(workersAux, {scaleAndSizeExtractorW});
+
869  if (cvMatToOpInputW != nullptr)
+
870  workersAux = mergeVectors(workersAux, {cvMatToOpInputW});
+
871  // cv::Mat to output format
+
872  if (cvMatToOpOutputW != nullptr)
+
873  workersAux = mergeVectors(workersAux, {cvMatToOpOutputW});
+
874 
+
875  // Producer
+
876  // If custom user Worker and uses its own thread
+
877  if (!userInputWs.empty() && userInputWsOnNewThread)
+
878  {
+
879  // Thread 0, queues 0 -> 1
+
880  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
881  threadManager.add(threadId, userInputWs, queueIn++, queueOut++);
+
882  threadIdPP(threadId, multiThreadEnabled);
+
883  }
+
884  // If custom user Worker in same thread
+
885  else if (!userInputWs.empty())
+
886  workersAux = mergeVectors(userInputWs, workersAux);
+
887  // If OpenPose producer (same thread)
+
888  else if (datumProducerW != nullptr)
+
889  workersAux = mergeVectors({datumProducerW}, workersAux);
+
890  // Otherwise
+
891  else if (threadManagerMode != ThreadManagerMode::Asynchronous
+
892  && threadManagerMode != ThreadManagerMode::AsynchronousIn)
+
893  error("No input selected.", __LINE__, __FUNCTION__, __FILE__);
+
894  // Thread 0 or 1, queues 0 -> 1
+
895  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
896  threadManager.add(threadId, workersAux, queueIn++, queueOut++);
+
897  // Increase thread
+
898  threadIdPP(threadId, multiThreadEnabled);
+
899 
+
900  // Pose estimation & rendering
+
901  // Thread 1 or 2...X, queues 1 -> 2, X = 2 + #GPUs
+
902  if (!poseExtractorsWs.empty())
+
903  {
+
904  if (multiThreadEnabled)
+
905  {
+
906  for (auto& wPose : poseExtractorsWs)
907  {
-
908  const auto wQueueOrderer = std::make_shared<WQueueOrderer<TDatumsSP>>();
-
909  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
910  threadManager.add(threadId, wQueueOrderer, queueIn++, queueOut++);
-
911  threadIdPP(threadId, multiThreadEnabled);
-
912  }
-
913  }
-
914  else
-
915  {
-
916  if (poseTriangulationsWs.size() > 1)
-
917  log("Multi-threading disabled, only 1 thread running for 3-D triangulation.",
-
918  Priority::High);
-
919  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
920  threadManager.add(threadId, poseTriangulationsWs.at(0), queueIn++, queueOut++);
-
921  }
-
922  }
-
923  else
-
924  postProcessingWs = mergeVectors({wQueueAssembler}, postProcessingWs);
-
925  // Adam/IK step
-
926  if (!jointAngleEstimationsWs.empty())
-
927  {
-
928  if (multiThreadEnabled)
-
929  {
-
930  for (auto& wJointAngleEstimator : jointAngleEstimationsWs)
-
931  {
-
932  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
933  threadManager.add(threadId, wJointAngleEstimator, queueIn, queueOut);
-
934  threadIdPP(threadId, multiThreadEnabled);
-
935  }
-
936  queueIn++;
-
937  queueOut++;
-
938  // Sort frames
-
939  if (jointAngleEstimationsWs.size() > 1)
-
940  {
-
941  const auto wQueueOrderer = std::make_shared<WQueueOrderer<TDatumsSP>>();
-
942  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
943  threadManager.add(threadId, wQueueOrderer, queueIn++, queueOut++);
-
944  threadIdPP(threadId, multiThreadEnabled);
-
945  }
-
946  }
-
947  else
-
948  {
-
949  if (jointAngleEstimationsWs.size() > 1)
-
950  log("Multi-threading disabled, only 1 thread running for joint angle estimation.",
-
951  Priority::High);
-
952  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
953  threadManager.add(threadId, jointAngleEstimationsWs.at(0), queueIn++, queueOut++);
-
954  }
-
955  }
-
956  // Post processing workers
-
957  if (!postProcessingWs.empty())
-
958  {
-
959  // Combining postProcessingWs and outputWs
-
960  outputWs = mergeVectors(postProcessingWs, outputWs);
-
961  // // If I wanna split them
-
962  // log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
963  // threadManager.add(threadId, postProcessingWs, queueIn++, queueOut++);
-
964  // threadIdPP(threadId, multiThreadEnabled);
-
965  }
-
966  // If custom user Worker and uses its own thread
-
967  if (!userPostProcessingWs.empty())
-
968  {
-
969  // If custom user Worker in its own thread
-
970  if (userPostProcessingWsOnNewThread)
-
971  {
-
972  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
973  threadManager.add(threadId, userPostProcessingWs, queueIn++, queueOut++);
-
974  threadIdPP(threadId, multiThreadEnabled);
-
975  }
-
976  // If custom user Worker in same thread
-
977  // Merge with outputWs
-
978  else
-
979  outputWs = mergeVectors(outputWs, userPostProcessingWs);
-
980  }
-
981  // Output workers
-
982  if (!outputWs.empty())
-
983  {
-
984  // Thread 4 or 5, queues 4 -> 5
-
985  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
986  threadManager.add(threadId, outputWs, queueIn++, queueOut++);
-
987  threadIdPP(threadId, multiThreadEnabled);
-
988  }
-
989  // User output worker
-
990  // Thread Y, queues Q -> Q+1
-
991  if (!userOutputWs.empty())
-
992  {
-
993  if (userOutputWsOnNewThread)
-
994  {
-
995  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
996  threadManager.add(threadId, userOutputWs, queueIn++, queueOut++);
-
997  threadIdPP(threadId, multiThreadEnabled);
-
998  }
-
999  else
-
1000  {
-
1001  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
1002  threadManager.add(threadId-1, userOutputWs, queueIn++, queueOut++);
-
1003  }
-
1004  }
-
1005  // OpenPose GUI
-
1006  if (guiW != nullptr)
-
1007  {
-
1008  // Thread Y+1, queues Q+1 -> Q+2
-
1009  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
1010  threadManager.add(threadId, guiW, queueIn++, queueOut++);
-
1011  // Saving 3D output
-
1012  if (videoSaver3DW != nullptr)
-
1013  threadManager.add(threadId, videoSaver3DW, queueIn++, queueOut++);
-
1014  threadIdPP(threadId, multiThreadEnabled);
-
1015  }
-
1016  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
1017  // Setting maximum speed
-
1018  if (wFpsMax != nullptr)
-
1019  {
-
1020  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
-
1021  threadManager.add(threadId, wFpsMax, queueIn++, queueOut++);
-
1022  threadIdPP(threadId, multiThreadEnabled);
-
1023  }
-
1024  }
-
1025  catch (const std::exception& e)
-
1026  {
-
1027  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
-
1028  }
-
1029  }
-
1030 }
-
1031 
-
1032 #endif // OPENPOSE_WRAPPER_WRAPPER_AUXILIARY_HPP
+
908  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
909  threadManager.add(threadId, wPose, queueIn, queueOut);
+
910  threadIdPP(threadId, multiThreadEnabled);
+
911  }
+
912  queueIn++;
+
913  queueOut++;
+
914  // Sort frames - Required own thread
+
915  if (poseExtractorsWs.size() > 1u)
+
916  {
+
917  const auto wQueueOrderer = std::make_shared<WQueueOrderer<TDatumsSP>>();
+
918  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
919  threadManager.add(threadId, wQueueOrderer, queueIn++, queueOut++);
+
920  threadIdPP(threadId, multiThreadEnabled);
+
921  }
+
922  }
+
923  else
+
924  {
+
925  if (poseExtractorsWs.size() > 1)
+
926  log("Multi-threading disabled, only 1 thread running. All GPUs have been disabled but the"
+
927  " first one, which is defined by gpuNumberStart (e.g., in the OpenPose demo, it is set"
+
928  " with the `--num_gpu_start` flag).", Priority::High);
+
929  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
930  threadManager.add(threadId, poseExtractorsWs.at(0), queueIn++, queueOut++);
+
931  }
+
932  }
+
933  // Assemble all frames from same time instant (3-D module)
+
934  const auto wQueueAssembler = std::make_shared<WQueueAssembler<TDatumsSP, TDatums>>();
+
935  // 3-D reconstruction
+
936  if (!poseTriangulationsWs.empty())
+
937  {
+
938  // Assemble frames
+
939  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
940  threadManager.add(threadId, wQueueAssembler, queueIn++, queueOut++);
+
941  threadIdPP(threadId, multiThreadEnabled);
+
942  // 3-D reconstruction
+
943  if (multiThreadEnabled)
+
944  {
+
945  for (auto& wPoseTriangulations : poseTriangulationsWs)
+
946  {
+
947  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
948  threadManager.add(threadId, wPoseTriangulations, queueIn, queueOut);
+
949  threadIdPP(threadId, multiThreadEnabled);
+
950  }
+
951  queueIn++;
+
952  queueOut++;
+
953  // Sort frames
+
954  if (poseTriangulationsWs.size() > 1u)
+
955  {
+
956  const auto wQueueOrderer = std::make_shared<WQueueOrderer<TDatumsSP>>();
+
957  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
958  threadManager.add(threadId, wQueueOrderer, queueIn++, queueOut++);
+
959  threadIdPP(threadId, multiThreadEnabled);
+
960  }
+
961  }
+
962  else
+
963  {
+
964  if (poseTriangulationsWs.size() > 1)
+
965  log("Multi-threading disabled, only 1 thread running for 3-D triangulation.",
+
966  Priority::High);
+
967  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
968  threadManager.add(threadId, poseTriangulationsWs.at(0), queueIn++, queueOut++);
+
969  }
+
970  }
+
971  else
+
972  postProcessingWs = mergeVectors({wQueueAssembler}, postProcessingWs);
+
973  // Adam/IK step
+
974  if (!jointAngleEstimationsWs.empty())
+
975  {
+
976  if (multiThreadEnabled)
+
977  {
+
978  for (auto& wJointAngleEstimator : jointAngleEstimationsWs)
+
979  {
+
980  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
981  threadManager.add(threadId, wJointAngleEstimator, queueIn, queueOut);
+
982  threadIdPP(threadId, multiThreadEnabled);
+
983  }
+
984  queueIn++;
+
985  queueOut++;
+
986  // Sort frames
+
987  if (jointAngleEstimationsWs.size() > 1)
+
988  {
+
989  const auto wQueueOrderer = std::make_shared<WQueueOrderer<TDatumsSP>>();
+
990  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
991  threadManager.add(threadId, wQueueOrderer, queueIn++, queueOut++);
+
992  threadIdPP(threadId, multiThreadEnabled);
+
993  }
+
994  }
+
995  else
+
996  {
+
997  if (jointAngleEstimationsWs.size() > 1)
+
998  log("Multi-threading disabled, only 1 thread running for joint angle estimation.",
+
999  Priority::High);
+
1000  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
1001  threadManager.add(threadId, jointAngleEstimationsWs.at(0), queueIn++, queueOut++);
+
1002  }
+
1003  }
+
1004  // Post processing workers
+
1005  if (!postProcessingWs.empty())
+
1006  {
+
1007  // Combining postProcessingWs and outputWs
+
1008  outputWs = mergeVectors(postProcessingWs, outputWs);
+
1009  // // If I wanna split them
+
1010  // log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
1011  // threadManager.add(threadId, postProcessingWs, queueIn++, queueOut++);
+
1012  // threadIdPP(threadId, multiThreadEnabled);
+
1013  }
+
1014  // If custom user Worker and uses its own thread
+
1015  if (!userPostProcessingWs.empty())
+
1016  {
+
1017  // If custom user Worker in its own thread
+
1018  if (userPostProcessingWsOnNewThread)
+
1019  {
+
1020  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
1021  threadManager.add(threadId, userPostProcessingWs, queueIn++, queueOut++);
+
1022  threadIdPP(threadId, multiThreadEnabled);
+
1023  }
+
1024  // If custom user Worker in same thread
+
1025  // Merge with outputWs
+
1026  else
+
1027  outputWs = mergeVectors(outputWs, userPostProcessingWs);
+
1028  }
+
1029  // Output workers
+
1030  if (!outputWs.empty())
+
1031  {
+
1032  // Thread 4 or 5, queues 4 -> 5
+
1033  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
1034  threadManager.add(threadId, outputWs, queueIn++, queueOut++);
+
1035  threadIdPP(threadId, multiThreadEnabled);
+
1036  }
+
1037  // User output worker
+
1038  // Thread Y, queues Q -> Q+1
+
1039  if (!userOutputWs.empty())
+
1040  {
+
1041  if (userOutputWsOnNewThread)
+
1042  {
+
1043  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
1044  threadManager.add(threadId, userOutputWs, queueIn++, queueOut++);
+
1045  threadIdPP(threadId, multiThreadEnabled);
+
1046  }
+
1047  else
+
1048  {
+
1049  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
1050  threadManager.add(threadId-1, userOutputWs, queueIn++, queueOut++);
+
1051  }
+
1052  }
+
1053  // OpenPose GUI
+
1054  if (guiW != nullptr)
+
1055  {
+
1056  // Thread Y+1, queues Q+1 -> Q+2
+
1057  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
1058  threadManager.add(threadId, guiW, queueIn++, queueOut++);
+
1059  // Saving 3D output
+
1060  if (videoSaver3DW != nullptr)
+
1061  threadManager.add(threadId, videoSaver3DW, queueIn++, queueOut++);
+
1062  threadIdPP(threadId, multiThreadEnabled);
+
1063  }
+
1064  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
1065  // Setting maximum speed
+
1066  if (wFpsMax != nullptr)
+
1067  {
+
1068  log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
+
1069  threadManager.add(threadId, wFpsMax, queueIn++, queueOut++);
+
1070  threadIdPP(threadId, multiThreadEnabled);
+
1071  }
+
1072  }
+
1073  catch (const std::exception& e)
+
1074  {
+
1075  error(e.what(), __LINE__, __FUNCTION__, __FILE__);
+
1076  }
+
1077  }
+
1078 }
+
1079 
+
1080 #endif // OPENPOSE_WRAPPER_WRAPPER_AUXILIARY_HPP
OP_API void threadIdPP(unsigned long long &threadId, const bool multiThreadEnabled)
-- GitLab