mirror of
https://github.com/gosticks/openpose.git
synced 2026-08-12 12:20:22 +00:00
Added face-hands hpp & render (no extraction code nor models)
This commit is contained in:
@@ -5917,7 +5917,7 @@
|
||||
"_parent": {
|
||||
"$ref": "AAAAAAFbHDZmRV10zeE="
|
||||
},
|
||||
"name": "scalePose",
|
||||
"name": "scaleKeyPoints",
|
||||
"ownedElements": [
|
||||
{
|
||||
"_type": "UMLDependency",
|
||||
@@ -6005,7 +6005,7 @@
|
||||
"_parent": {
|
||||
"$ref": "AAAAAAFbHDZmRV10zeE="
|
||||
},
|
||||
"name": "wArrayScaler.hpp",
|
||||
"name": "wKeyPointScaler.hpp",
|
||||
"ownedElements": [
|
||||
{
|
||||
"_type": "UMLDependency",
|
||||
@@ -6076,7 +6076,7 @@
|
||||
"_parent": {
|
||||
"$ref": "AAAAAAFbHDZmRV10zeE="
|
||||
},
|
||||
"name": "ArrayScaler",
|
||||
"name": "KeyPointScaler",
|
||||
"ownedElements": [
|
||||
{
|
||||
"_type": "UMLDependency",
|
||||
@@ -13344,7 +13344,7 @@
|
||||
"height": 13,
|
||||
"autoResize": false,
|
||||
"underline": false,
|
||||
"text": "scalePose",
|
||||
"text": "scaleKeyPoints",
|
||||
"horizontalAlignment": 2,
|
||||
"verticalAlignment": 5,
|
||||
"wordWrap": false
|
||||
@@ -13635,7 +13635,7 @@
|
||||
"height": 13,
|
||||
"autoResize": false,
|
||||
"underline": false,
|
||||
"text": "wArrayScaler.hpp",
|
||||
"text": "wKeyPointScaler.hpp",
|
||||
"horizontalAlignment": 2,
|
||||
"verticalAlignment": 5,
|
||||
"wordWrap": false
|
||||
@@ -14633,7 +14633,7 @@
|
||||
"height": 13,
|
||||
"autoResize": false,
|
||||
"underline": false,
|
||||
"text": "ArrayScaler",
|
||||
"text": "KeyPointScaler",
|
||||
"horizontalAlignment": 2,
|
||||
"verticalAlignment": 5,
|
||||
"wordWrap": false
|
||||
|
||||
Binary file not shown.
@@ -117,11 +117,11 @@ int openPoseTutorialPose1()
|
||||
double scaleInputToOutput;
|
||||
op::Array<float> outputArray;
|
||||
std::tie(scaleInputToOutput, outputArray) = cvMatToOpOutput.format(inputImage);
|
||||
// Step 3 - Estimate pose
|
||||
// Step 3 - Estimate poseKeyPoints
|
||||
poseExtractorCaffe.forwardPass(netInputArray, inputImage.size());
|
||||
const auto pose = poseExtractorCaffe.getPose();
|
||||
// Step 4 - Render pose
|
||||
poseRenderer.renderPose(outputArray, pose);
|
||||
const auto poseKeyPoints = poseExtractorCaffe.getPoseKeyPoints();
|
||||
// Step 4 - Render poseKeyPoints
|
||||
poseRenderer.renderPose(outputArray, poseKeyPoints);
|
||||
// Step 5 - OpenPose output format to cv::Mat
|
||||
auto outputImage = opOutputToCvMat.formatToCvMat(outputArray);
|
||||
|
||||
|
||||
@@ -121,12 +121,12 @@ int openPoseTutorialPose2()
|
||||
double scaleInputToOutput;
|
||||
op::Array<float> outputArray;
|
||||
std::tie(scaleInputToOutput, outputArray) = cvMatToOpOutput.format(inputImage);
|
||||
// Step 3 - Estimate pose
|
||||
// Step 3 - Estimate poseKeyPoints
|
||||
poseExtractorPtr->forwardPass(netInputArray, inputImage.size());
|
||||
const auto pose = poseExtractorPtr->getPose();
|
||||
const auto poseKeyPoints = poseExtractorPtr->getPoseKeyPoints();
|
||||
const auto scaleNetToOutput = poseExtractorPtr->getScaleNetToOutput();
|
||||
// Step 4 - Render pose
|
||||
poseRenderer.renderPose(outputArray, pose, scaleNetToOutput);
|
||||
poseRenderer.renderPose(outputArray, poseKeyPoints, scaleNetToOutput);
|
||||
// Step 5 - OpenPose output format to cv::Mat
|
||||
auto outputImage = opOutputToCvMat.formatToCvMat(outputArray);
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ public:
|
||||
{
|
||||
// User's post-processing (after OpenPose processing & before OpenPose outputs) here
|
||||
// datum.cvOutputData: rendered frame with pose or heatmaps
|
||||
// datum.pose: Array<float> with the estimated pose
|
||||
// datum.poseKeyPoints: Array<float> with the estimated pose
|
||||
try
|
||||
{
|
||||
if (datumsPtr != nullptr && !datumsPtr->empty())
|
||||
@@ -142,7 +142,7 @@ public:
|
||||
{
|
||||
// User's displaying/saving/other processing here
|
||||
// datum.cvOutputData: rendered frame with pose or heatmaps
|
||||
// datum.pose: Array<float> with the estimated pose
|
||||
// datum.poseKeyPoints: Array<float> with the estimated pose
|
||||
if (datumsPtr != nullptr && !datumsPtr->empty())
|
||||
{
|
||||
cv::imshow("User worker GUI", datumsPtr->at(0).cvOutputData);
|
||||
|
||||
@@ -126,7 +126,7 @@ public:
|
||||
{
|
||||
// User's post-processing (after OpenPose processing & before OpenPose outputs) here
|
||||
// datum.cvOutputData: rendered frame with pose or heatmaps
|
||||
// datum.pose: Array<float> with the estimated pose
|
||||
// datum.poseKeyPoints: Array<float> with the estimated pose
|
||||
try
|
||||
{
|
||||
if (datumsPtr != nullptr && !datumsPtr->empty())
|
||||
@@ -154,7 +154,7 @@ public:
|
||||
{
|
||||
// User's displaying/saving/other processing here
|
||||
// datum.cvOutputData: rendered frame with pose or heatmaps
|
||||
// datum.pose: Array<float> with the estimated pose
|
||||
// datum.poseKeyPoints: Array<float> with the estimated pose
|
||||
if (datumsPtr != nullptr && !datumsPtr->empty())
|
||||
{
|
||||
cv::imshow("User worker GUI", datumsPtr->at(0).cvOutputData);
|
||||
|
||||
@@ -176,7 +176,7 @@ public:
|
||||
{
|
||||
// User's displaying/saving/other processing here
|
||||
// datum.cvOutputData: rendered frame with pose or heatmaps
|
||||
// datum.pose: Array<float> with the estimated pose
|
||||
// datum.poseKeyPoints: Array<float> with the estimated pose
|
||||
if (datumsPtr != nullptr && !datumsPtr->empty())
|
||||
{
|
||||
cv::imshow("User worker GUI", datumsPtr->at(0).cvOutputData);
|
||||
|
||||
@@ -188,7 +188,7 @@ public:
|
||||
{
|
||||
// User's post-processing (after OpenPose processing & before OpenPose outputs) here
|
||||
// datum.cvOutputData: rendered frame with pose or heatmaps
|
||||
// datum.pose: Array<float> with the estimated pose
|
||||
// datum.poseKeyPoints: Array<float> with the estimated pose
|
||||
try
|
||||
{
|
||||
if (datumsPtr != nullptr && !datumsPtr->empty())
|
||||
@@ -216,7 +216,7 @@ public:
|
||||
{
|
||||
// User's displaying/saving/other processing here
|
||||
// datum.cvOutputData: rendered frame with pose or heatmaps
|
||||
// datum.pose: Array<float> with the estimated pose
|
||||
// datum.poseKeyPoints: Array<float> with the estimated pose
|
||||
if (datumsPtr != nullptr && !datumsPtr->empty())
|
||||
{
|
||||
cv::imshow("User worker GUI", datumsPtr->at(0).cvOutputData);
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
#ifndef OPENPOSE__CORE__ARRAYS_SCALER_HPP
|
||||
#define OPENPOSE__CORE__ARRAYS_SCALER_HPP
|
||||
|
||||
#include <vector>
|
||||
#include "array.hpp"
|
||||
#include "enumClasses.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
class ArrayScaler
|
||||
{
|
||||
public:
|
||||
explicit ArrayScaler(const ScaleMode scalePose);
|
||||
|
||||
void scale(Array<float>& array, const double scaleInputToOutput, const double scaleNetToOutput, const cv::Size& producerSize) const;
|
||||
|
||||
void scale(std::vector<Array<float>>& arrays, const double scaleInputToOutput, const double scaleNetToOutput, const cv::Size& producerSize) const;
|
||||
|
||||
private:
|
||||
const ScaleMode mScaleMode;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__CORE__ARRAYS_SCALER_HPP
|
||||
@@ -52,15 +52,15 @@ namespace op
|
||||
|
||||
// -------------------------------------------------- Resulting Array<float> data parameters -------------------------------------------------- //
|
||||
/**
|
||||
* Pose (x,y,score) locations for each person in the image.
|
||||
* Body pose (x,y,score) locations for each person in the image.
|
||||
* It has been resized to the desired output resolution (e.g. `resolution` flag in the demo).
|
||||
* If outputData is empty, then cvOutputData will also be empty.
|
||||
* Size: #people x #body parts (e.g. 18 for COCO or 15 for MPI) x 3 ((x,y) coordinates + score)
|
||||
*/
|
||||
Array<float> poseKeyPoints;
|
||||
|
||||
Array<float> pose;
|
||||
/**
|
||||
* Pose heatmaps (body parts, background and PAFs) for the whole image.
|
||||
* Body pose heatmaps (body parts, background and/or PAFs) for the whole image.
|
||||
* This parameters is by default empty and disabled for performance. Each group (body parts, background and PAFs) can be individually enabled.
|
||||
* #heatmaps = #body parts (if enabled) + 1 (if background enabled) + 2 x #PAFs (if enabled). Each PAF has 2 consecutive channels, one for x- and one for y-coordinates.
|
||||
* Order heatmaps: body parts + background (as appears in POSE_BODY_PART_MAPPING) + (x,y) channel of each PAF (sorted as appears in POSE_BODY_PART_PAIRS). See `pose/poseParameters.hpp`.
|
||||
@@ -71,10 +71,17 @@ namespace op
|
||||
|
||||
/**
|
||||
* Experimental (NOT IMPLEMENTED YET)
|
||||
* Hands code is in development phase. Not included in this version.
|
||||
* Size: 2 (right and left hand) x #hand parts (21) x 3 ((x,y) coordinates + score)
|
||||
* Face code is in development phase. Not included in this version.
|
||||
* Size: #people's faces to render x #face parts (71) x 3 ((x,y) coordinates + score)
|
||||
*/
|
||||
Array<float> hands;
|
||||
Array<float> faceKeyPoints;
|
||||
|
||||
/**
|
||||
* Experimental (NOT IMPLEMENTED YET)
|
||||
* Hands code is in development phase. Not included in this version.
|
||||
* Size: #people's hands to render x 2 (right and left hand) x #hand parts (21) x 3 ((x,y) coordinates + score)
|
||||
*/
|
||||
Array<float> handKeyPoints;
|
||||
|
||||
// -------------------------------------------------- Other parameters -------------------------------------------------- //
|
||||
double scaleInputToOutput; /**< Scale ratio between the input Datum::cvInputData and the output Datum::cvOutputData. */
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
|
||||
// core module
|
||||
#include "array.hpp"
|
||||
#include "arrayScaler.hpp"
|
||||
#include "cvMatToOpInput.hpp"
|
||||
#include "cvMatToOpOutput.hpp"
|
||||
#include "datum.hpp"
|
||||
#include "enumClasses.hpp"
|
||||
#include "keyPointScaler.hpp"
|
||||
#include "net.hpp"
|
||||
#include "netCaffe.hpp"
|
||||
#include "nmsBase.hpp"
|
||||
@@ -16,10 +16,10 @@
|
||||
#include "renderer.hpp"
|
||||
#include "resizeAndMergeBase.hpp"
|
||||
#include "resizeAndMergeCaffe.hpp"
|
||||
#include "scalePose.hpp"
|
||||
#include "wArrayScaler.hpp"
|
||||
#include "scaleKeyPoints.hpp"
|
||||
#include "wCvMatToOpInput.hpp"
|
||||
#include "wCvMatToOpOutput.hpp"
|
||||
#include "wKeyPointScaler.hpp"
|
||||
#include "wOpOutputToCvMat.hpp"
|
||||
|
||||
#endif // OPENPOSE__CORE__HEADERS_HPP
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef OPENPOSE__CORE__KEY_POINT_SCALER_HPP
|
||||
#define OPENPOSE__CORE__KEY_POINT_SCALER_HPP
|
||||
|
||||
#include <vector>
|
||||
#include "array.hpp"
|
||||
#include "enumClasses.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
class KeyPointScaler
|
||||
{
|
||||
public:
|
||||
explicit KeyPointScaler(const ScaleMode scaleMode);
|
||||
|
||||
void scale(Array<float>& arrayToScale, const double scaleInputToOutput, const double scaleNetToOutput, const cv::Size& producerSize) const;
|
||||
|
||||
void scale(std::vector<Array<float>>& arraysToScale, const double scaleInputToOutput, const double scaleNetToOutput, const cv::Size& producerSize) const;
|
||||
|
||||
private:
|
||||
const ScaleMode mScaleMode;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__CORE__KEY_POINT_SCALER_HPP
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef OPENPOSE__CORE__SCALE_KEY_POINTS_HPP
|
||||
#define OPENPOSE__CORE__SCALE_KEY_POINTS_HPP
|
||||
|
||||
#include "array.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
void scaleKeyPoints(Array<float>& keyPoints, const double scale);
|
||||
|
||||
void scaleKeyPoints(Array<float>& keyPoints, const double scaleX, const double scaleY);
|
||||
|
||||
void scaleKeyPoints(Array<float>& keyPoints, const double scaleX, const double scaleY, const double offsetX, const double offsetY);
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__CORE__SCALE_KEY_POINTS_HPP
|
||||
@@ -1,15 +0,0 @@
|
||||
#ifndef OPENPOSE__CORE__SCALE_POSE_HPP
|
||||
#define OPENPOSE__CORE__SCALE_POSE_HPP
|
||||
|
||||
#include "array.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
void scalePose(Array<float>& pose, const double scale);
|
||||
|
||||
void scalePose(Array<float>& pose, const double scaleX, const double scaleY);
|
||||
|
||||
void scalePose(Array<float>& pose, const double scaleX, const double scaleY, const double offsetX, const double offsetY);
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__CORE__SCALE_POSE_HPP
|
||||
+15
-15
@@ -1,24 +1,24 @@
|
||||
#ifndef OPENPOSE__CORE__W_ARRAYS_SCALER_HPP
|
||||
#define OPENPOSE__CORE__W_ARRAYS_SCALER_HPP
|
||||
#ifndef OPENPOSE__CORE__W_KEY_POINT_SCALER_HPP
|
||||
#define OPENPOSE__CORE__W_KEY_POINT_SCALER_HPP
|
||||
|
||||
#include "../thread/worker.hpp"
|
||||
#include "arrayScaler.hpp"
|
||||
#include "scalePose.hpp"
|
||||
#include "keyPointScaler.hpp"
|
||||
#include "scaleKeyPoints.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
template<typename TDatums>
|
||||
class WArrayScaler : public Worker<TDatums>
|
||||
class WKeyPointScaler : public Worker<TDatums>
|
||||
{
|
||||
public:
|
||||
explicit WArrayScaler(const std::shared_ptr<ArrayScaler>& arrayScaler);
|
||||
explicit WKeyPointScaler(const std::shared_ptr<KeyPointScaler>& keyPointScaler);
|
||||
|
||||
void initializationOnThread();
|
||||
|
||||
void work(TDatums& tDatums);
|
||||
|
||||
private:
|
||||
std::shared_ptr<ArrayScaler> spArrayScaler;
|
||||
std::shared_ptr<KeyPointScaler> spKeyPointScaler;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -34,18 +34,18 @@ namespace op
|
||||
namespace op
|
||||
{
|
||||
template<typename TDatums>
|
||||
WArrayScaler<TDatums>::WArrayScaler(const std::shared_ptr<ArrayScaler>& arrayScaler) :
|
||||
spArrayScaler{arrayScaler}
|
||||
WKeyPointScaler<TDatums>::WKeyPointScaler(const std::shared_ptr<KeyPointScaler>& keyPointScaler) :
|
||||
spKeyPointScaler{keyPointScaler}
|
||||
{
|
||||
}
|
||||
|
||||
template<typename TDatums>
|
||||
void WArrayScaler<TDatums>::initializationOnThread()
|
||||
void WKeyPointScaler<TDatums>::initializationOnThread()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename TDatums>
|
||||
void WArrayScaler<TDatums>::work(TDatums& tDatums)
|
||||
void WKeyPointScaler<TDatums>::work(TDatums& tDatums)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -58,8 +58,8 @@ namespace op
|
||||
// Rescale pose data
|
||||
for (auto& tDatum : *tDatums)
|
||||
{
|
||||
std::vector<Array<float>> arrays{tDatum.pose, tDatum.hands};
|
||||
spArrayScaler->scale(arrays, tDatum.scaleInputToOutput, tDatum.scaleNetToOutput, tDatum.cvInputData.size());
|
||||
std::vector<Array<float>> arraysToScale{tDatum.poseKeyPoints, tDatum.handKeyPoints, tDatum.faceKeyPoints};
|
||||
spKeyPointScaler->scale(arraysToScale, tDatum.scaleInputToOutput, tDatum.scaleNetToOutput, tDatum.cvInputData.size());
|
||||
}
|
||||
// Profiling speed
|
||||
Profiler::timerEnd(profilerKey);
|
||||
@@ -76,7 +76,7 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
COMPILE_TEMPLATE_DATUM(WArrayScaler);
|
||||
COMPILE_TEMPLATE_DATUM(WKeyPointScaler);
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__CORE__W_ARRAYS_SCALER_HPP
|
||||
#endif // OPENPOSE__CORE__W_KEY_POINT_SCALER_HPP
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef OPENPOSE__FACE__ENUM_CLASSES_HPP
|
||||
#define OPENPOSE__FACE__ENUM_CLASSES_HPP
|
||||
|
||||
namespace op
|
||||
{
|
||||
enum class FaceProperty : bool
|
||||
{
|
||||
NMSThreshold = 0,
|
||||
Size,
|
||||
};
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__FACE__ENUM_CLASSES_HPP
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
#ifndef OPENPOSE__FACE__FACE_EXTRACTOR_HPP
|
||||
#define OPENPOSE__FACE__FACE_EXTRACTOR_HPP
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <memory> // std::shared_ptr
|
||||
#include <thread>
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include "../../core/array.hpp"
|
||||
#include "../../core/net.hpp"
|
||||
#include "../../core/nmsCaffe.hpp"
|
||||
#include "../../core/resizeAndMergeCaffe.hpp"
|
||||
#include "../../pose/enumClasses.hpp"
|
||||
#include "enumClasses.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
class FaceExtractor
|
||||
{
|
||||
public:
|
||||
explicit FaceExtractor(const std::string& modelFolder, const int gpuId, const PoseModel poseModel);
|
||||
|
||||
void initializationOnThread();
|
||||
|
||||
void forwardPass(const Array<float>& poseKeyPoints, const cv::Mat& cvInputData);
|
||||
|
||||
Array<float> getFaceKeyPoints() const;
|
||||
|
||||
double get(const FaceProperty property) const;
|
||||
|
||||
void set(const FaceProperty property, const double value);
|
||||
|
||||
void increase(const FaceProperty property, const double value);
|
||||
|
||||
private:
|
||||
const cv::Size mNetOutputSize;
|
||||
const cv::Size mOutputSize;
|
||||
const unsigned char mNeck;
|
||||
const unsigned char mNose;
|
||||
const unsigned char mLEar;
|
||||
const unsigned char mREar;
|
||||
const unsigned char mLEye;
|
||||
const unsigned char mREye;
|
||||
std::array<std::atomic<double>, (int)FaceProperty::Size> mProperties;
|
||||
std::shared_ptr<Net> spNet;
|
||||
std::shared_ptr<ResizeAndMergeCaffe<float>> spResizeAndMergeCaffe;
|
||||
std::shared_ptr<NmsCaffe<float>> spNmsCaffe;
|
||||
Array<float> mFaceImageCrop;
|
||||
Array<float> mFaceKeyPoints;
|
||||
float mScaleFace;
|
||||
// Init with thread
|
||||
boost::shared_ptr<caffe::Blob<float>> spCaffeNetOutputBlob;
|
||||
std::shared_ptr<caffe::Blob<float>> spHeatMapsBlob;
|
||||
std::shared_ptr<caffe::Blob<float>> spPeaksBlob;
|
||||
std::thread::id mThreadId;
|
||||
|
||||
void checkThread() const;
|
||||
|
||||
DELETE_COPY(FaceExtractor);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__FACE__FACE_EXTRACTOR_HPP
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef OPENPOSE__FACE__FACE_PARAMETERS_HPP
|
||||
#define OPENPOSE__FACE__FACE_PARAMETERS_HPP
|
||||
|
||||
#include "enumClasses.hpp"
|
||||
#include "../../pose/poseParameters.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
const unsigned char FACE_MAX_NUMBER_FACE = 1;
|
||||
|
||||
const unsigned char FACE_NUMBER_PARTS = 71;
|
||||
#define FACE_PAIRS_TO_RENDER {0,1, 1,2, 2,3, 3,4, 4,5, 5,6, 6,7, 7,8, 8,9, 9,10, 10,11, 11,12, 12,13, 13,14, 14,15, 15,16, 17,18, 18,19, 19,20, \
|
||||
20,21, 22,23, 23,24, 24,25, 25,26, 27,28, 28,29, 29,30, 31,32, 32,33, 33,34, 34,35, 36,37, 37,38, 38,39, 39,40, 40,41, \
|
||||
41,36, 42,43, 43,44, 44,45, 45,46, 46,47, 47,42, 48,49, 49,50, 50,51, 51,52, 52,53, 53,54, 54,55, 55,56, 56,57, 57,58, \
|
||||
58,59, 59,48, 60,61, 61,62, 62,63, 63,64, 64,65, 65,66, 66,67, 67,60}
|
||||
|
||||
// Constant Global Parameters
|
||||
// const unsigned char FACE_MAX_PEOPLE = 1;
|
||||
|
||||
// Constant parameters
|
||||
const auto FACE_CCN_DECREASE_FACTOR = 8.f;
|
||||
const unsigned int FACE_MAX_PEAKS = 64u;
|
||||
const std::string FACE_PROTOTXT{"face/pose_deploy.prototxt"};
|
||||
const std::string FACE_TRAINED_MODEL{"face/pose_iter_116000.caffemodel"};
|
||||
|
||||
// Default Model Parameters
|
||||
// They might be modified on running time
|
||||
const auto FACE_DEFAULT_NMS_THRESHOLD = 0.1f;
|
||||
|
||||
// Rendering default parameters
|
||||
const auto FACE_DEFAULT_ALPHA_FACE = POSE_DEFAULT_ALPHA_POSE;
|
||||
// const auto FACE_DEFAULT_ALPHA_HEATMAP = POSE_DEFAULT_ALPHA_HEATMAP;
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__FACE__FACE_PARAMETERS_HPP
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef OPENPOSE__FACE__GPU_FACE_RENDER_HPP
|
||||
#define OPENPOSE__FACE__GPU_FACE_RENDER_HPP
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include "faceParameters.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
void renderFaceGpu(float* framePtr, const cv::Size& frameSize, const float* const facePtr, const int numberFace, const float alphaColorToAdd = FACE_DEFAULT_ALPHA_FACE);
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__FACE__GPU_FACE_RENDER_HPP
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef OPENPOSE__FACE__FACE_RENDERER_HPP
|
||||
#define OPENPOSE__FACE__FACE_RENDERER_HPP
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include "../../core/array.hpp"
|
||||
#include "../../core/renderer.hpp"
|
||||
#include "../../thread/worker.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
class FaceRenderer : public Renderer
|
||||
{
|
||||
public:
|
||||
explicit FaceRenderer(const cv::Size& frameSize);
|
||||
|
||||
~FaceRenderer();
|
||||
|
||||
void initializationOnThread();
|
||||
|
||||
void renderFace(Array<float>& outputData, const Array<float>& faceKeyPoints);
|
||||
|
||||
private:
|
||||
const cv::Size mFrameSize;
|
||||
float* pGpuFace; // GPU aux memory
|
||||
|
||||
DELETE_COPY(FaceRenderer);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__FACE__FACE_RENDERER_HPP
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef OPENPOSE__FACE__HEADERS_HPP
|
||||
#define OPENPOSE__FACE__HEADERS_HPP
|
||||
|
||||
// face module
|
||||
#include "enumClasses.hpp"
|
||||
#include "faceExtractor.hpp"
|
||||
#include "faceParameters.hpp"
|
||||
#include "faceRenderer.hpp"
|
||||
#include "faceRenderGpu.hpp"
|
||||
#include "wFaceExtractor.hpp"
|
||||
#include "wFaceRenderer.hpp"
|
||||
|
||||
#endif // OPENPOSE__FACE__HEADERS_HPP
|
||||
@@ -0,0 +1,91 @@
|
||||
#ifndef OPENPOSE__FACE__W_FACE_EXTRACTOR_HPP
|
||||
#define OPENPOSE__FACE__W_FACE_EXTRACTOR_HPP
|
||||
|
||||
#include <memory> // std::shared_ptr
|
||||
#include "../../thread/worker.hpp"
|
||||
#include "faceRenderer.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
template<typename TDatums>
|
||||
class WFaceExtractor : public Worker<TDatums>
|
||||
{
|
||||
public:
|
||||
explicit WFaceExtractor(const std::shared_ptr<FaceExtractor>& faceExtractor);
|
||||
|
||||
void initializationOnThread();
|
||||
|
||||
void work(TDatums& tDatums);
|
||||
|
||||
private:
|
||||
std::shared_ptr<FaceExtractor> spFaceExtractor;
|
||||
|
||||
DELETE_COPY(WFaceExtractor);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Implementation
|
||||
#include "../../utilities/errorAndLog.hpp"
|
||||
#include "../../utilities/macros.hpp"
|
||||
#include "../../utilities/pointerContainer.hpp"
|
||||
#include "../../utilities/profiler.hpp"
|
||||
namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
template<typename TDatums>
|
||||
WFaceExtractor<TDatums>::WFaceExtractor(const std::shared_ptr<FaceExtractor>& faceExtractor) :
|
||||
spFaceExtractor{faceExtractor}
|
||||
{
|
||||
}
|
||||
|
||||
template<typename TDatums>
|
||||
void WFaceExtractor<TDatums>::initializationOnThread()
|
||||
{
|
||||
spFaceExtractor->initializationOnThread();
|
||||
}
|
||||
|
||||
template<typename TDatums>
|
||||
void WFaceExtractor<TDatums>::work(TDatums& tDatums)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (checkNoNullNorEmpty(tDatums))
|
||||
{
|
||||
// Debugging log
|
||||
dLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
// Profiling speed
|
||||
const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);
|
||||
// Extract people face
|
||||
for (auto& tDatum : *tDatums)
|
||||
{
|
||||
spFaceExtractor->forwardPass(tDatum.poseKeyPoints, tDatum.cvInputData);
|
||||
tDatum.faceKeyPoints = spFaceExtractor->getFaceKeyPoints();
|
||||
}
|
||||
// Profiling speed
|
||||
Profiler::timerEnd(profilerKey);
|
||||
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, 1000);
|
||||
// Debugging log
|
||||
dLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
this->stop();
|
||||
tDatums = nullptr;
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
COMPILE_TEMPLATE_DATUM(WFaceExtractor);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__FACE__W_FACE_EXTRACTOR_HPP
|
||||
@@ -0,0 +1,88 @@
|
||||
#ifndef OPENPOSE__FACE__W_FACE_RENDERER_HPP
|
||||
#define OPENPOSE__FACE__W_FACE_RENDERER_HPP
|
||||
|
||||
#include <memory> // std::shared_ptr
|
||||
#include "../../thread/worker.hpp"
|
||||
#include "faceRenderer.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
template<typename TDatums>
|
||||
class WFaceRenderer : public Worker<TDatums>
|
||||
{
|
||||
public:
|
||||
explicit WFaceRenderer(const std::shared_ptr<FaceRenderer>& faceRenderer);
|
||||
|
||||
void initializationOnThread();
|
||||
|
||||
void work(TDatums& tDatums);
|
||||
|
||||
private:
|
||||
std::shared_ptr<FaceRenderer> spFaceRenderer;
|
||||
|
||||
DELETE_COPY(WFaceRenderer);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Implementation
|
||||
#include "../../utilities/errorAndLog.hpp"
|
||||
#include "../../utilities/macros.hpp"
|
||||
#include "../../utilities/pointerContainer.hpp"
|
||||
#include "../../utilities/profiler.hpp"
|
||||
namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
template<typename TDatums>
|
||||
WFaceRenderer<TDatums>::WFaceRenderer(const std::shared_ptr<FaceRenderer>& faceRenderer) :
|
||||
spFaceRenderer{faceRenderer}
|
||||
{
|
||||
}
|
||||
|
||||
template<typename TDatums>
|
||||
void WFaceRenderer<TDatums>::initializationOnThread()
|
||||
{
|
||||
spFaceRenderer->initializationOnThread();
|
||||
}
|
||||
|
||||
template<typename TDatums>
|
||||
void WFaceRenderer<TDatums>::work(TDatums& tDatums)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (checkNoNullNorEmpty(tDatums))
|
||||
{
|
||||
// Debugging log
|
||||
dLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
// Profiling speed
|
||||
const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);
|
||||
// Render people face
|
||||
for (auto& tDatum : *tDatums)
|
||||
spFaceRenderer->renderFace(tDatum.outputData, tDatum.faceKeyPoints);
|
||||
// Profiling speed
|
||||
Profiler::timerEnd(profilerKey);
|
||||
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, 1000);
|
||||
// Debugging log
|
||||
dLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
this->stop();
|
||||
tDatums = nullptr;
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
COMPILE_TEMPLATE_DATUM(WFaceRenderer);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__FACE__W_FACE_RENDERER_HPP
|
||||
@@ -78,7 +78,7 @@ namespace op
|
||||
if (imageId <= 50006) // 3559 images ~ 4 min at 15fps // move this to producer as --frame_last 50006
|
||||
{
|
||||
// Record json in COCO format if file within desired range of images
|
||||
spPoseJsonCocoSaver->record(tDatum.pose, imageId);
|
||||
spPoseJsonCocoSaver->record(tDatum.poseKeyPoints, imageId);
|
||||
// Profiling speed
|
||||
Profiler::timerEnd(profilerKey);
|
||||
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, 1000);
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef OPENPOSE__HAND__ENUM_CLASSES_HPP
|
||||
#define OPENPOSE__HAND__ENUM_CLASSES_HPP
|
||||
|
||||
namespace op
|
||||
{
|
||||
enum class HandsProperty : bool
|
||||
{
|
||||
NMSThreshold = 0,
|
||||
Size,
|
||||
};
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__HAND__ENUM_CLASSES_HPP
|
||||
|
||||
+8
-8
@@ -1,5 +1,5 @@
|
||||
#ifndef OPENPOSE__HANDS__HANDS_EXTRACTOR_HPP
|
||||
#define OPENPOSE__HANDS__HANDS_EXTRACTOR_HPP
|
||||
#ifndef OPENPOSE__HAND__HAND_EXTRACTOR_HPP
|
||||
#define OPENPOSE__HAND__HAND_EXTRACTOR_HPP
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
@@ -17,16 +17,16 @@ namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
class HandsExtractor
|
||||
class HandExtractor
|
||||
{
|
||||
public:
|
||||
explicit HandsExtractor(const std::string& modelFolder, const int gpuId, const PoseModel poseModel);
|
||||
explicit HandExtractor(const std::string& modelFolder, const int gpuId, const PoseModel poseModel);
|
||||
|
||||
void initializationOnThread();
|
||||
|
||||
void forwardPass(const Array<float>& pose, const cv::Mat& cvInputData);
|
||||
void forwardPass(const Array<float>& poseKeyPoints, const cv::Mat& cvInputData);
|
||||
|
||||
Array<float> getHands() const;
|
||||
Array<float> getHandKeyPoints() const;
|
||||
|
||||
double get(const HandsProperty property) const;
|
||||
|
||||
@@ -60,9 +60,9 @@ namespace op
|
||||
|
||||
void checkThread() const;
|
||||
|
||||
DELETE_COPY(HandsExtractor);
|
||||
DELETE_COPY(HandExtractor);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__HANDS__HANDS_EXTRACTOR_HPP
|
||||
#endif // OPENPOSE__HAND__HAND_EXTRACTOR_HPP
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef OPENPOSE__HAND__HAND_PARAMETERS_HPP
|
||||
#define OPENPOSE__HAND__HAND_PARAMETERS_HPP
|
||||
|
||||
#include "enumClasses.hpp"
|
||||
#include "../../pose/poseParameters.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
const unsigned char HAND_MAX_NUMBER_HANDS = 2;
|
||||
|
||||
const unsigned char HAND_NUMBER_PARTS = 21;
|
||||
#define HAND_PAIRS_TO_RENDER {0,1, 1,2, 2,3, 3,4, 0,5, 5,6, 6,7, 7,8, 0,9, 9,10, 10,11, 11,12, 0,13, 13,14, 14,15, 15,16, 0,17, 17,18, 18,19, 19,20}
|
||||
|
||||
// Constant Global Parameters
|
||||
// const unsigned char HAND_MAX_PEOPLE = 1;
|
||||
|
||||
// Constant parameters
|
||||
const auto HAND_CCN_DECREASE_FACTOR = 8.f;
|
||||
const unsigned int HAND_MAX_PEAKS = 64u;
|
||||
const std::string HAND_PROTOTXT{"hand/pose_deploy.prototxt"};
|
||||
const std::string HAND_TRAINED_MODEL{"hand/pose_iter_120000.caffemodel"};
|
||||
|
||||
// Default Model Parameters
|
||||
// They might be modified on running time
|
||||
const auto HAND_DEFAULT_NMS_THRESHOLD = 0.1f;
|
||||
|
||||
// Rendering default parameters
|
||||
const auto HAND_DEFAULT_ALPHA_HANDS = POSE_DEFAULT_ALPHA_POSE;
|
||||
// const auto HAND_DEFAULT_ALPHA_HEATMAP = POSE_DEFAULT_ALPHA_HEATMAP;
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__HAND__HAND_PARAMETERS_HPP
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef OPENPOSE__HAND__GPU_HAND_RENDER_HPP
|
||||
#define OPENPOSE__HAND__GPU_HAND_RENDER_HPP
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include "handParameters.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
void renderHandsGpu(float* framePtr, const cv::Size& frameSize, const float* const handsPtr, const int numberHands, const float alphaColorToAdd = HAND_DEFAULT_ALPHA_HANDS);
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__HAND__GPU_HAND_RENDER_HPP
|
||||
+8
-8
@@ -1,5 +1,5 @@
|
||||
#ifndef OPENPOSE__HANDS__HANDS_RENDERER_HPP
|
||||
#define OPENPOSE__HANDS__HANDS_RENDERER_HPP
|
||||
#ifndef OPENPOSE__HAND__HAND_RENDERER_HPP
|
||||
#define OPENPOSE__HAND__HAND_RENDERER_HPP
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include "../../core/array.hpp"
|
||||
@@ -10,24 +10,24 @@ namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
class HandsRenderer : public Renderer
|
||||
class HandRenderer : public Renderer
|
||||
{
|
||||
public:
|
||||
explicit HandsRenderer(const cv::Size& frameSize);
|
||||
explicit HandRenderer(const cv::Size& frameSize);
|
||||
|
||||
~HandsRenderer();
|
||||
~HandRenderer();
|
||||
|
||||
void initializationOnThread();
|
||||
|
||||
void renderHands(Array<float>& outputData, const Array<float>& hands);
|
||||
void renderHands(Array<float>& outputData, const Array<float>& handKeyPoints);
|
||||
|
||||
private:
|
||||
const cv::Size mFrameSize;
|
||||
float* pGpuHands; // GPU aux memory
|
||||
|
||||
DELETE_COPY(HandsRenderer);
|
||||
DELETE_COPY(HandRenderer);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__HANDS__HANDS_RENDERER_HPP
|
||||
#endif // OPENPOSE__HAND__HAND_RENDERER_HPP
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef OPENPOSE__HAND__HEADERS_HPP
|
||||
#define OPENPOSE__HAND__HEADERS_HPP
|
||||
|
||||
// hand module
|
||||
#include "enumClasses.hpp"
|
||||
#include "handExtractor.hpp"
|
||||
#include "handParameters.hpp"
|
||||
#include "handRenderer.hpp"
|
||||
#include "handRenderGpu.hpp"
|
||||
#include "wHandExtractor.hpp"
|
||||
#include "wHandRenderer.hpp"
|
||||
|
||||
#endif // OPENPOSE__HAND__HEADERS_HPP
|
||||
+16
-16
@@ -1,28 +1,28 @@
|
||||
#ifndef OPENPOSE__HANDS__W_HANDS_EXTRACTOR_HPP
|
||||
#define OPENPOSE__HANDS__W_HANDS_EXTRACTOR_HPP
|
||||
#ifndef OPENPOSE__HAND__W_HAND_EXTRACTOR_HPP
|
||||
#define OPENPOSE__HAND__W_HAND_EXTRACTOR_HPP
|
||||
|
||||
#include <memory> // std::shared_ptr
|
||||
#include "../../thread/worker.hpp"
|
||||
#include "handsRenderer.hpp"
|
||||
#include "handRenderer.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
template<typename TDatums>
|
||||
class WHandsExtractor : public Worker<TDatums>
|
||||
class WHandExtractor : public Worker<TDatums>
|
||||
{
|
||||
public:
|
||||
explicit WHandsExtractor(const std::shared_ptr<HandsExtractor>& handsExtractor);
|
||||
explicit WHandExtractor(const std::shared_ptr<HandExtractor>& handExtractor);
|
||||
|
||||
void initializationOnThread();
|
||||
|
||||
void work(TDatums& tDatums);
|
||||
|
||||
private:
|
||||
std::shared_ptr<HandsExtractor> spHandsExtractor;
|
||||
std::shared_ptr<HandExtractor> spHandExtractor;
|
||||
|
||||
DELETE_COPY(WHandsExtractor);
|
||||
DELETE_COPY(WHandExtractor);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -41,19 +41,19 @@ namespace op
|
||||
namespace experimental
|
||||
{
|
||||
template<typename TDatums>
|
||||
WHandsExtractor<TDatums>::WHandsExtractor(const std::shared_ptr<HandsExtractor>& handsExtractor) :
|
||||
spHandsExtractor{handsExtractor}
|
||||
WHandExtractor<TDatums>::WHandExtractor(const std::shared_ptr<HandExtractor>& handExtractor) :
|
||||
spHandExtractor{handExtractor}
|
||||
{
|
||||
}
|
||||
|
||||
template<typename TDatums>
|
||||
void WHandsExtractor<TDatums>::initializationOnThread()
|
||||
void WHandExtractor<TDatums>::initializationOnThread()
|
||||
{
|
||||
spHandsExtractor->initializationOnThread();
|
||||
spHandExtractor->initializationOnThread();
|
||||
}
|
||||
|
||||
template<typename TDatums>
|
||||
void WHandsExtractor<TDatums>::work(TDatums& tDatums)
|
||||
void WHandExtractor<TDatums>::work(TDatums& tDatums)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -66,8 +66,8 @@ namespace op
|
||||
// Extract people hands
|
||||
for (auto& tDatum : *tDatums)
|
||||
{
|
||||
spHandsExtractor->forwardPass(tDatum.pose, tDatum.cvInputData);
|
||||
tDatum.hands = spHandsExtractor->getHands();
|
||||
spHandExtractor->forwardPass(tDatum.poseKeyPoints, tDatum.cvInputData);
|
||||
tDatum.handKeyPoints = spHandExtractor->getHandKeyPoints();
|
||||
}
|
||||
// Profiling speed
|
||||
Profiler::timerEnd(profilerKey);
|
||||
@@ -84,8 +84,8 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
COMPILE_TEMPLATE_DATUM(WHandsExtractor);
|
||||
COMPILE_TEMPLATE_DATUM(WHandExtractor);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__HANDS__W_HANDS_EXTRACTOR_HPP
|
||||
#endif // OPENPOSE__HAND__W_HAND_EXTRACTOR_HPP
|
||||
+15
-15
@@ -1,28 +1,28 @@
|
||||
#ifndef OPENPOSE__HANDS__W_HANDS_RENDERER_HPP
|
||||
#define OPENPOSE__HANDS__W_HANDS_RENDERER_HPP
|
||||
#ifndef OPENPOSE__HAND__W_HAND_RENDERER_HPP
|
||||
#define OPENPOSE__HAND__W_HAND_RENDERER_HPP
|
||||
|
||||
#include <memory> // std::shared_ptr
|
||||
#include "../../thread/worker.hpp"
|
||||
#include "handsRenderer.hpp"
|
||||
#include "handRenderer.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
template<typename TDatums>
|
||||
class WHandsRenderer : public Worker<TDatums>
|
||||
class WHandRenderer : public Worker<TDatums>
|
||||
{
|
||||
public:
|
||||
explicit WHandsRenderer(const std::shared_ptr<HandsRenderer>& handsRenderer);
|
||||
explicit WHandRenderer(const std::shared_ptr<HandRenderer>& handRenderer);
|
||||
|
||||
void initializationOnThread();
|
||||
|
||||
void work(TDatums& tDatums);
|
||||
|
||||
private:
|
||||
std::shared_ptr<HandsRenderer> spHandsRenderer;
|
||||
std::shared_ptr<HandRenderer> spHandRenderer;
|
||||
|
||||
DELETE_COPY(WHandsRenderer);
|
||||
DELETE_COPY(WHandRenderer);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -41,19 +41,19 @@ namespace op
|
||||
namespace experimental
|
||||
{
|
||||
template<typename TDatums>
|
||||
WHandsRenderer<TDatums>::WHandsRenderer(const std::shared_ptr<HandsRenderer>& handsRenderer) :
|
||||
spHandsRenderer{handsRenderer}
|
||||
WHandRenderer<TDatums>::WHandRenderer(const std::shared_ptr<HandRenderer>& handRenderer) :
|
||||
spHandRenderer{handRenderer}
|
||||
{
|
||||
}
|
||||
|
||||
template<typename TDatums>
|
||||
void WHandsRenderer<TDatums>::initializationOnThread()
|
||||
void WHandRenderer<TDatums>::initializationOnThread()
|
||||
{
|
||||
spHandsRenderer->initializationOnThread();
|
||||
spHandRenderer->initializationOnThread();
|
||||
}
|
||||
|
||||
template<typename TDatums>
|
||||
void WHandsRenderer<TDatums>::work(TDatums& tDatums)
|
||||
void WHandRenderer<TDatums>::work(TDatums& tDatums)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -65,7 +65,7 @@ namespace op
|
||||
const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);
|
||||
// Render people hands
|
||||
for (auto& tDatum : *tDatums)
|
||||
spHandsRenderer->renderHands(tDatum.outputData, tDatum.hands);
|
||||
spHandRenderer->renderHands(tDatum.outputData, tDatum.handKeyPoints);
|
||||
// Profiling speed
|
||||
Profiler::timerEnd(profilerKey);
|
||||
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, 1000);
|
||||
@@ -81,8 +81,8 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
COMPILE_TEMPLATE_DATUM(WHandsRenderer);
|
||||
COMPILE_TEMPLATE_DATUM(WHandRenderer);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__HANDS__W_HANDS_RENDERER_HPP
|
||||
#endif // OPENPOSE__HAND__W_HAND_RENDERER_HPP
|
||||
@@ -1,14 +0,0 @@
|
||||
#ifndef OPENPOSE__HANDS__ENUM_CLASSES_HPP
|
||||
#define OPENPOSE__HANDS__ENUM_CLASSES_HPP
|
||||
|
||||
namespace op
|
||||
{
|
||||
enum class HandsProperty : bool
|
||||
{
|
||||
NMSThreshold = 0,
|
||||
Size,
|
||||
};
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__HANDS__ENUM_CLASSES_HPP
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#ifndef OPENPOSE__HANDS__HANDS_PARAMETERS_HPP
|
||||
#define OPENPOSE__HANDS__HANDS_PARAMETERS_HPP
|
||||
|
||||
#include "enumClasses.hpp"
|
||||
#include "../../pose/poseParameters.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
const unsigned char HANDS_MAX_NUMBER_HANDS = 2;
|
||||
|
||||
const unsigned char HANDS_NUMBER_PARTS = 21;
|
||||
#define HANDS_PAIRS_TO_RENDER {0,1, 1,2, 2,3, 3,4, 0,5, 5,6, 6,7, 7,8, 0,9, 9,10, 10,11, 11,12, 0,13, 13,14, 14,15, 15,16, 0,17, 17,18, 18,19, 19,20}
|
||||
|
||||
// Constant Global Parameters
|
||||
// const unsigned char HANDS_MAX_PEOPLE = 1;
|
||||
|
||||
// Constant parameters
|
||||
const auto HANDS_CCN_DECREASE_FACTOR = 8.f;
|
||||
const unsigned int HANDS_MAX_PEAKS = 64u;
|
||||
const std::string HANDS_PROTOTXT{"hand/pose_deploy.prototxt"};
|
||||
const std::string HANDS_TRAINED_MODEL{"hand/pose_iter_120000.caffemodel"};
|
||||
|
||||
// Default Model Parameters
|
||||
// They might be modified on running time
|
||||
const auto HANDS_DEFAULT_NMS_THRESHOLD = 0.1f;
|
||||
|
||||
// Rendering default parameters
|
||||
const auto HANDS_DEFAULT_ALPHA_HANDS = POSE_DEFAULT_ALPHA_POSE;
|
||||
// const auto HANDS_DEFAULT_ALPHA_HEATMAP = POSE_DEFAULT_ALPHA_HEATMAP;
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__HANDS__HANDS_PARAMETERS_HPP
|
||||
@@ -1,12 +0,0 @@
|
||||
#ifndef OPENPOSE__HANDS__GPU_HANDS_RENDER_HPP
|
||||
#define OPENPOSE__HANDS__GPU_HANDS_RENDER_HPP
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include "handsParameters.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
void renderHandsGpu(float* framePtr, const cv::Size& frameSize, const float* const handsPtr, const int numberHands, const float alphaColorToAdd = HANDS_DEFAULT_ALPHA_HANDS);
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__HANDS__GPU_HANDS_RENDER_HPP
|
||||
@@ -1,13 +0,0 @@
|
||||
#ifndef OPENPOSE__HANDS__HEADERS_HPP
|
||||
#define OPENPOSE__HANDS__HEADERS_HPP
|
||||
|
||||
// hands module
|
||||
#include "enumClasses.hpp"
|
||||
#include "handsExtractor.hpp"
|
||||
#include "handsParameters.hpp"
|
||||
#include "handsRenderer.hpp"
|
||||
#include "handsRenderGpu.hpp"
|
||||
#include "wHandsExtractor.hpp"
|
||||
#include "wHandsRenderer.hpp"
|
||||
|
||||
#endif // OPENPOSE__HANDS__HEADERS_HPP
|
||||
@@ -1,11 +1,14 @@
|
||||
#ifndef OPENPOSE__EXPERIMENTAL__HEADERS_HPP
|
||||
#define OPENPOSE__EXPERIMENTAL__HEADERS_HPP
|
||||
|
||||
// face module
|
||||
#include "face/headers.hpp"
|
||||
|
||||
// filestream module
|
||||
#include "filestream/headers.hpp"
|
||||
|
||||
// hands module
|
||||
#include "hands/headers.hpp"
|
||||
#include "hand/headers.hpp"
|
||||
|
||||
// producer module
|
||||
// #include "producer/headers.hpp"
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace op
|
||||
|
||||
~PoseJsonCocoSaver();
|
||||
|
||||
void record(const Array<float>& pose, const int imageId);
|
||||
void record(const Array<float>& poseKeyPoints, const int imageId);
|
||||
|
||||
private:
|
||||
JsonOfstream mJsonOfstream;
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace op
|
||||
public:
|
||||
explicit PoseJsonSaver(const std::string& directoryPath);
|
||||
|
||||
void savePoseVector(const std::vector<Array<float>>& poseVector, const std::string& fileName) const;
|
||||
void savePoseKeyPoints(const std::vector<Array<float>>& poseKeyPointsVector, const std::string& fileName) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace op
|
||||
public:
|
||||
PoseSaver(const std::string& directoryPath, const DataFormat format);
|
||||
|
||||
void savePoseVector(const std::vector<Array<float>>& poseVector, const std::string& fileName) const;
|
||||
void savePoseKeyPoints(const std::vector<Array<float>>& poseKeyPointsVector, const std::string& fileName) const;
|
||||
|
||||
private:
|
||||
const DataFormat mFormat;
|
||||
|
||||
@@ -61,11 +61,11 @@ namespace op
|
||||
// T* to T
|
||||
auto& tDatumsNoPtr = *tDatums;
|
||||
// Record people pose data in json format
|
||||
std::vector<Array<float>> poseVector(tDatumsNoPtr.size());
|
||||
std::vector<Array<float>> poseKeyPointsVector(tDatumsNoPtr.size());
|
||||
for (auto i = 0; i < tDatumsNoPtr.size(); i++)
|
||||
poseVector[i] = tDatumsNoPtr[i].pose;
|
||||
poseKeyPointsVector[i] = tDatumsNoPtr[i].poseKeyPoints;
|
||||
const auto fileName = (!tDatumsNoPtr[0].name.empty() ? tDatumsNoPtr[0].name : std::to_string(tDatumsNoPtr[0].id));
|
||||
spPoseJsonSaver->savePoseVector(poseVector, fileName);
|
||||
spPoseJsonSaver->savePoseKeyPoints(poseKeyPointsVector, fileName);
|
||||
// Profiling speed
|
||||
Profiler::timerEnd(profilerKey);
|
||||
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, 1000);
|
||||
|
||||
@@ -62,11 +62,11 @@ namespace op
|
||||
// T* to T
|
||||
auto& tDatumsNoPtr = *tDatums;
|
||||
// Record people pose data
|
||||
std::vector<Array<float>> poseVector(tDatumsNoPtr.size());
|
||||
std::vector<Array<float>> poseKeyPointsVector(tDatumsNoPtr.size());
|
||||
for (auto i = 0; i < tDatumsNoPtr.size(); i++)
|
||||
poseVector[i] = tDatumsNoPtr[i].pose;
|
||||
poseKeyPointsVector[i] = tDatumsNoPtr[i].poseKeyPoints;
|
||||
const auto fileName = (!tDatumsNoPtr[0].name.empty() ? tDatumsNoPtr[0].name : std::to_string(tDatumsNoPtr[0].id));
|
||||
spPoseSaver->savePoseVector(poseVector, fileName);
|
||||
spPoseSaver->savePoseKeyPoints(poseKeyPointsVector, fileName);
|
||||
// Profiling speed
|
||||
Profiler::timerEnd(profilerKey);
|
||||
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, 1000);
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace op
|
||||
public:
|
||||
GuiInfoAdder(const cv::Size& outputSize, const int numberGpus);
|
||||
|
||||
void addInfo(cv::Mat& cvOutputData, const Array<float>& pose, const unsigned long long id, const std::string& elementRenderedName);
|
||||
void addInfo(cv::Mat& cvOutputData, const Array<float>& poseKeyPoints, const unsigned long long id, const std::string& elementRenderedName);
|
||||
|
||||
private:
|
||||
// Const variables
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace op
|
||||
const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);
|
||||
// Add GUI components to frame
|
||||
for (auto& tDatum : *tDatums)
|
||||
spGuiInfoAdder->addInfo(tDatum.cvOutputData, tDatum.pose, tDatum.id, tDatum.elementRendered.second);
|
||||
spGuiInfoAdder->addInfo(tDatum.cvOutputData, tDatum.poseKeyPoints, tDatum.id, tDatum.elementRendered.second);
|
||||
// Profiling speed
|
||||
Profiler::timerEnd(profilerKey);
|
||||
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, 1000);
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
namespace op
|
||||
{
|
||||
template <typename T>
|
||||
void connectBodyPartsCpu(Array<T>& pose, const T* const heatMapPtr, const T* const peaksPtr, const PoseModel poseModel, const cv::Size& heatMapSize, const int maxPeaks,
|
||||
void connectBodyPartsCpu(Array<T>& poseKeyPoints, const T* const heatMapPtr, const T* const peaksPtr, const PoseModel poseModel, const cv::Size& heatMapSize, const int maxPeaks,
|
||||
const int interMinAboveThreshold, const T interThreshold, const int minSubsetCnt, const T minSubsetScore, const T scaleFactor = 1.f);
|
||||
|
||||
template <typename T>
|
||||
void connectBodyPartsGpu(Array<T>& pose, T* posePtr, const T* const heatMapPtr, const T* const peaksPtr, const PoseModel poseModel, const cv::Size& heatMapSize,
|
||||
void connectBodyPartsGpu(Array<T>& poseKeyPoints, T* posePtr, const T* const heatMapPtr, const T* const peaksPtr, const PoseModel poseModel, const cv::Size& heatMapSize,
|
||||
const int maxPeaks, const int interMinAboveThreshold, const T interThreshold, const int minSubsetCnt, const T minSubsetScore, const T scaleFactor = 1.f);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,9 +36,9 @@ namespace op
|
||||
|
||||
void setScaleNetToOutput(const T scaleNetToOutput);
|
||||
|
||||
virtual void Forward_cpu(const std::vector<caffe::Blob<T>*>& bottom, Array<T>& pose);
|
||||
virtual void Forward_cpu(const std::vector<caffe::Blob<T>*>& bottom, Array<T>& poseKeyPoints);
|
||||
|
||||
virtual void Forward_gpu(const std::vector<caffe::Blob<T>*>& bottom, const std::vector<caffe::Blob<T>*>& top, Array<T>& pose);
|
||||
virtual void Forward_gpu(const std::vector<caffe::Blob<T>*>& bottom, const std::vector<caffe::Blob<T>*>& top, Array<T>& poseKeyPoints);
|
||||
|
||||
virtual void Backward_cpu(const std::vector<caffe::Blob<T>*>& top, const std::vector<bool>& propagate_down, const std::vector<caffe::Blob<T>*>& bottom);
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace op
|
||||
|
||||
virtual const float* getPoseGpuConstPtr() const = 0;
|
||||
|
||||
Array<float> getPose() const;
|
||||
Array<float> getPoseKeyPoints() const;
|
||||
|
||||
double getScaleNetToOutput() const;
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace op
|
||||
const PoseModel mPoseModel;
|
||||
const cv::Size mNetOutputSize;
|
||||
const cv::Size mOutputSize;
|
||||
Array<float> mPose;
|
||||
Array<float> mPoseKeyPoints;
|
||||
double mScaleNetToOutput;
|
||||
|
||||
void checkThread() const;
|
||||
|
||||
@@ -87,6 +87,10 @@ namespace op
|
||||
// Rendering default parameters
|
||||
const auto POSE_DEFAULT_ALPHA_POSE = 0.6f;
|
||||
const auto POSE_DEFAULT_ALPHA_HEATMAP = 0.7f;
|
||||
|
||||
// Auxiliary functions
|
||||
unsigned char poseBodyPartMapStringToKey(const PoseModel poseModel, const std::string& string);
|
||||
unsigned char poseBodyPartMapStringToKey(const PoseModel poseModel, const std::vector<std::string>& strings);
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__POSE__POSE_PARAMETERS_HPP
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace op
|
||||
|
||||
void setShowGooglyEyes(const bool showGooglyEyes);
|
||||
|
||||
std::pair<int, std::string> renderPose(Array<float>& outputData, const Array<float>& pose, const double scaleNetToOutput = -1.);
|
||||
std::pair<int, std::string> renderPose(Array<float>& outputData, const Array<float>& poseKeyPoints, const double scaleNetToOutput = -1.);
|
||||
|
||||
private:
|
||||
const cv::Size mHeatMapsSize;
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace op
|
||||
{
|
||||
spPoseExtractor->forwardPass(tDatum.inputNetData, tDatum.cvInputData.size());
|
||||
tDatum.poseHeatMaps = spPoseExtractor->getHeatMaps();
|
||||
tDatum.pose = spPoseExtractor->getPose();
|
||||
tDatum.poseKeyPoints = spPoseExtractor->getPoseKeyPoints();
|
||||
tDatum.scaleNetToOutput = spPoseExtractor->getScaleNetToOutput();
|
||||
}
|
||||
// Profiling speed
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace op
|
||||
const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);
|
||||
// Render people pose
|
||||
for (auto& tDatum : *tDatums)
|
||||
tDatum.elementRendered = spPoseRenderer->renderPose(tDatum.outputData, tDatum.pose, tDatum.scaleNetToOutput);
|
||||
tDatum.elementRendered = spPoseRenderer->renderPose(tDatum.outputData, tDatum.poseKeyPoints, tDatum.scaleNetToOutput);
|
||||
// Profiling speed
|
||||
Profiler::timerEnd(profilerKey);
|
||||
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, 1000);
|
||||
|
||||
@@ -140,7 +140,7 @@ namespace op
|
||||
colorR = addWeighted(colorR, colorToAdd[0], alphaColorToAdd);
|
||||
colorG = addWeighted(colorG, colorToAdd[1], alphaColorToAdd);
|
||||
colorB = addWeighted(colorB, colorToAdd[2], alphaColorToAdd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__UTILITIES_CUDA_HU
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
#ifndef OPENPOSE__UTILITIES_RENDER_HU
|
||||
#define OPENPOSE__UTILITIES_RENDER_HU
|
||||
|
||||
namespace op
|
||||
{
|
||||
inline __device__ void renderKeyPoints(float* targetPtr, float2* sharedMaxs, float2* sharedMins, float* sharedScaleF,
|
||||
const int globalIdx, const int x, const int y, const int targetWidth, const int targetHeight,
|
||||
const float* const facePtr, const unsigned char* const partPairsPtr,
|
||||
const int numberFaces, const int numberParts, const int numberPartPairs,
|
||||
const float* const rgbColorsPtr, const int numberColors,
|
||||
const float radius, const float stickwidth, const float threshold, const float alphaColorToAdd)
|
||||
{
|
||||
// Fill shared parameters
|
||||
if (globalIdx < numberFaces)
|
||||
{
|
||||
sharedMins[globalIdx].x = targetWidth;
|
||||
sharedMins[globalIdx].y = targetHeight;
|
||||
sharedMaxs[globalIdx].x = 0.f;
|
||||
sharedMaxs[globalIdx].y = 0.f;
|
||||
for (auto part = 0 ; part < numberParts ; part++)
|
||||
{
|
||||
const auto index = 3 * (globalIdx*numberParts + part);
|
||||
const auto x = facePtr[index];
|
||||
const auto y = facePtr[index+1];
|
||||
const auto score = facePtr[index+2];
|
||||
if (score > threshold)
|
||||
{
|
||||
if (x < sharedMins[globalIdx].x)
|
||||
sharedMins[globalIdx].x = x;
|
||||
if (x > sharedMaxs[globalIdx].x)
|
||||
sharedMaxs[globalIdx].x = x;
|
||||
if (y < sharedMins[globalIdx].y)
|
||||
sharedMins[globalIdx].y = y;
|
||||
if (y > sharedMaxs[globalIdx].y)
|
||||
sharedMaxs[globalIdx].y = y;
|
||||
}
|
||||
}
|
||||
const auto averageX = sharedMaxs[globalIdx].x-sharedMins[globalIdx].x;
|
||||
const auto averageY = sharedMaxs[globalIdx].y-sharedMins[globalIdx].y;
|
||||
sharedScaleF[globalIdx] = fastTruncate((averageX + averageY) / 400.f, 0.33f, 1.f); // (averageX + averageY) / 2.f / 400.f
|
||||
const auto constantToAdd = 50.f;
|
||||
sharedMaxs[globalIdx].x += constantToAdd;
|
||||
sharedMaxs[globalIdx].y += constantToAdd;
|
||||
sharedMins[globalIdx].x -= constantToAdd;
|
||||
sharedMins[globalIdx].y -= constantToAdd;
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
// Fill each (x,y) target pixel
|
||||
if (x < targetWidth && y < targetHeight)
|
||||
{
|
||||
const auto baseIndex = y * targetWidth + x;
|
||||
auto& b = targetPtr[ baseIndex];
|
||||
auto& g = targetPtr[ targetWidth * targetHeight + baseIndex];
|
||||
auto& r = targetPtr[2 * targetWidth * targetHeight + baseIndex];
|
||||
|
||||
for (auto person = 0; person < numberFaces; person++)
|
||||
{
|
||||
if (x <= sharedMaxs[person].x && x >= sharedMins[person].x && y <= sharedMaxs[person].y && y >= sharedMins[person].y)
|
||||
{
|
||||
// Hand part connections
|
||||
for (auto facePart = 0; facePart < numberPartPairs; facePart++)
|
||||
{
|
||||
const auto bSqrt = sharedScaleF[person] * sharedScaleF[person] * stickwidth * stickwidth;
|
||||
const auto partA = partPairsPtr[2*facePart];
|
||||
const auto partB = partPairsPtr[2*facePart+1];
|
||||
const auto indexA = person*numberParts*3 + partA*3;
|
||||
const auto xA = facePtr[indexA];
|
||||
const auto yA = facePtr[indexA + 1];
|
||||
const auto scoreA = facePtr[indexA + 2];
|
||||
const auto indexB = person*numberParts*3 + partB*3;
|
||||
const auto xB = facePtr[indexB];
|
||||
const auto yB = facePtr[indexB + 1];
|
||||
const auto scoreB = facePtr[indexB + 2];
|
||||
|
||||
if (scoreA > threshold && scoreB > threshold)
|
||||
{
|
||||
const auto xP = (xA + xB) / 2.f;
|
||||
const auto yP = (yA + yB) / 2.f;
|
||||
const auto aSqrt = (xA - xP) * (xA - xP) + (yA - yP) * (yA - yP);
|
||||
|
||||
const auto angle = atan2f(yB - yA, xB - xA);
|
||||
const auto sine = sinf(angle);
|
||||
const auto cosine = cosf(angle);
|
||||
const auto A = cosine * (x - xP) + sine * (y - yP);
|
||||
const auto B = sine * (x - xP) - cosine * (y - yP);
|
||||
|
||||
const auto judge = A * A / aSqrt + B * B / bSqrt;
|
||||
const auto minV = 0.f;
|
||||
const auto maxV = 1.f;
|
||||
if (minV <= judge && judge <= maxV)
|
||||
addColorWeighted(r, g, b, &rgbColorsPtr[(facePart%numberColors)*3], alphaColorToAdd);
|
||||
}
|
||||
}
|
||||
|
||||
// Hand part circles
|
||||
for (unsigned char i = 0; i < numberParts; i++)
|
||||
{
|
||||
const auto index = 3 * (person*numberParts + i);
|
||||
const auto localX = facePtr[index];
|
||||
const auto localY = facePtr[index + 1];
|
||||
const auto score = facePtr[index + 2];
|
||||
|
||||
if (score > threshold)
|
||||
{
|
||||
const auto dist2 = (x - localX) * (x - localX) + (y - localY) * (y - localY);
|
||||
const auto minr2 = 0.f;
|
||||
const auto maxr2 = sharedScaleF[person]*sharedScaleF[person]*radius * radius;
|
||||
if (minr2 <= dist2 && dist2 <= maxr2)
|
||||
addColorWeighted(r, g, b, &rgbColorsPtr[(i%numberColors)*3], alphaColorToAdd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__UTILITIES_RENDER_HU
|
||||
@@ -3,7 +3,8 @@
|
||||
|
||||
// wrapper module
|
||||
#include "wrapper.hpp"
|
||||
#include "wrapperStructHands.hpp"
|
||||
#include "wrapperStructFace.hpp"
|
||||
#include "wrapperStructHand.hpp"
|
||||
#include "wrapperStructInput.hpp"
|
||||
#include "wrapperStructOutput.hpp"
|
||||
#include "wrapperStructPose.hpp"
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
#define OPENPOSE__WRAPPER__WRAPPER_HPP
|
||||
|
||||
#include "../thread/headers.hpp"
|
||||
#include "wrapperStructPose.hpp"
|
||||
#include "wrapperStructHands.hpp"
|
||||
#include "wrapperStructFace.hpp"
|
||||
#include "wrapperStructHand.hpp"
|
||||
#include "wrapperStructInput.hpp"
|
||||
#include "wrapperStructOutput.hpp"
|
||||
#include "wrapperStructPose.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
@@ -72,18 +73,40 @@ namespace op
|
||||
*/
|
||||
void setWorkerOutput(const TWorker& worker, const bool workerOnNewThread = true);
|
||||
|
||||
// If output is not required, just use this function until the renderOutput argument. Keep the default values for the other parameters
|
||||
// in order not to display/save any output.
|
||||
// If output is not required, just use this function until the renderOutput argument. Keep the default values for the other parameters in order not to display/save any output.
|
||||
void configure(const WrapperStructPose& wrapperStructPose,
|
||||
// Producer (set producerSharedPtr = nullptr or use the default WrapperStructInput{} to disable any input)
|
||||
const WrapperStructInput& wrapperStructInput = WrapperStructInput{},
|
||||
const WrapperStructInput& wrapperStructInput,
|
||||
// Consumer (keep default values to disable any output)
|
||||
const WrapperStructOutput& wrapperStructOutput = WrapperStructOutput{});
|
||||
|
||||
// THIS FUNCTION IS NOT IMPLEMENTED YET -> COMING SOON
|
||||
// Similar to the previos configure, but it includes hand extraction and rendering
|
||||
void configure(const WrapperStructPose& wrapperStructPose,
|
||||
// Hand (use the default WrapperStructHand{} to disable any hand detector)
|
||||
const experimental::WrapperStructHand& wrapperHandStruct,
|
||||
// Producer (set producerSharedPtr = nullptr or use the default WrapperStructInput{} to disable any input)
|
||||
const WrapperStructInput& wrapperStructInput,
|
||||
// Consumer (keep default values to disable any output)
|
||||
const WrapperStructOutput& wrapperStructOutput = WrapperStructOutput{});
|
||||
|
||||
// THIS FUNCTION IS NOT IMPLEMENTED YET -> COMING SOON
|
||||
// Similar to the previos configure, but it includes hand extraction and rendering
|
||||
void configure(const WrapperStructPose& wrapperStructPose,
|
||||
// Face (use the default WrapperStructFace{} to disable any face detector)
|
||||
const experimental::WrapperStructFace& wrapperStructFace,
|
||||
// Producer (set producerSharedPtr = nullptr or use the default WrapperStructInput{} to disable any input)
|
||||
const WrapperStructInput& wrapperStructInput,
|
||||
// Consumer (keep default values to disable any output)
|
||||
const WrapperStructOutput& wrapperStructOutput = WrapperStructOutput{});
|
||||
|
||||
// THIS FUNCTION IS NOT IMPLEMENTED YET -> COMING SOON
|
||||
// Similar to the previos configure, but it includes hand extraction and rendering
|
||||
void configure(const WrapperStructPose& wrapperStructPose = WrapperStructPose{},
|
||||
// Hand (use the default WrapperStructHands{} to disable any hand detector)
|
||||
const experimental::WrapperStructHands& wrapperHandStruct = experimental::WrapperStructHands{},
|
||||
// Face (use the default WrapperStructFace{} to disable any face detector)
|
||||
const experimental::WrapperStructFace& wrapperStructFace = experimental::WrapperStructFace{},
|
||||
// Hand (use the default WrapperStructHand{} to disable any hand detector)
|
||||
const experimental::WrapperStructHand& wrapperHandStruct = experimental::WrapperStructHand{},
|
||||
// Producer (set producerSharedPtr = nullptr or use the default WrapperStructInput{} to disable any input)
|
||||
const WrapperStructInput& wrapperStructInput = WrapperStructInput{},
|
||||
// Consumer (keep default values to disable any output)
|
||||
@@ -349,7 +372,7 @@ namespace op
|
||||
{
|
||||
try
|
||||
{
|
||||
configure(wrapperStructPose, experimental::WrapperStructHands{}, wrapperStructInput, wrapperStructOutput);
|
||||
configure(wrapperStructPose, experimental::WrapperStructFace{}, experimental::WrapperStructHand{}, wrapperStructInput, wrapperStructOutput);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -358,8 +381,37 @@ namespace op
|
||||
}
|
||||
|
||||
template<typename TDatums, typename TWorker, typename TQueue>
|
||||
void Wrapper<TDatums, TWorker, TQueue>::configure(const WrapperStructPose& wrapperStructPose, const experimental::WrapperStructHands& wrapperHandStruct,
|
||||
void Wrapper<TDatums, TWorker, TQueue>::configure(const WrapperStructPose& wrapperStructPose, const experimental::WrapperStructFace& wrapperStructFace,
|
||||
const WrapperStructInput& wrapperStructInput, const WrapperStructOutput& wrapperStructOutput)
|
||||
{
|
||||
try
|
||||
{
|
||||
configure(wrapperStructPose, wrapperStructFace, experimental::WrapperStructHand{}, wrapperStructInput, wrapperStructOutput);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TDatums, typename TWorker, typename TQueue>
|
||||
void Wrapper<TDatums, TWorker, TQueue>::configure(const WrapperStructPose& wrapperStructPose, const experimental::WrapperStructHand& wrapperHandStruct,
|
||||
const WrapperStructInput& wrapperStructInput, const WrapperStructOutput& wrapperStructOutput)
|
||||
{
|
||||
try
|
||||
{
|
||||
configure(wrapperStructPose, experimental::WrapperStructFace{}, wrapperHandStruct, wrapperStructInput, wrapperStructOutput);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TDatums, typename TWorker, typename TQueue>
|
||||
void Wrapper<TDatums, TWorker, TQueue>::configure(const WrapperStructPose& wrapperStructPose, const experimental::WrapperStructFace& wrapperStructFace,
|
||||
const experimental::WrapperStructHand& wrapperHandStruct, const WrapperStructInput& wrapperStructInput,
|
||||
const WrapperStructOutput& wrapperStructOutput)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -393,8 +445,8 @@ namespace op
|
||||
}
|
||||
if (mUserOutputWs.empty() && mThreadManagerMode != ThreadManagerMode::Asynchronous && mThreadManagerMode != ThreadManagerMode::AsynchronousOut)
|
||||
{
|
||||
const std::string additionalMessage = " You could also set mThreadManagerMode = mThreadManagerMode::Asynchronous(Out) and/or add your own output worker"
|
||||
" class before calling this function.";
|
||||
const std::string additionalMessage = " You could also set mThreadManagerMode = mThreadManagerMode::Asynchronous(Out) and/or add your own"
|
||||
" output worker class before calling this function.";
|
||||
const auto savingSomething = (!wrapperStructOutput.writeImages.empty() || !wrapperStructOutput.writeVideo.empty()
|
||||
|| !wrapperStructOutput.writePose.empty() || !wrapperStructOutput.writePoseJson.empty()
|
||||
|| !wrapperStructOutput.writeCocoJson.empty() || !wrapperStructOutput.writeHeatMaps.empty());
|
||||
@@ -516,15 +568,27 @@ namespace op
|
||||
for (auto i = 0; i < spWPoses.size(); i++)
|
||||
spWPoses.at(i) = {std::make_shared<WPoseExtractor<TDatumsPtr>>(poseExtractors.at(i))};
|
||||
|
||||
// Face extractor(s)
|
||||
if (wrapperStructFace.extractAndRenderFace)
|
||||
{
|
||||
for (auto gpuId = 0; gpuId < spWPoses.size(); gpuId++)
|
||||
{
|
||||
const auto faceExtractor = std::make_shared<experimental::FaceExtractor>(
|
||||
wrapperStructPose.modelFolder, gpuId + wrapperStructPose.gpuNumberStart, wrapperStructPose.poseModel
|
||||
);
|
||||
spWPoses.at(gpuId).emplace_back(std::make_shared<experimental::WFaceExtractor<TDatumsPtr>>(faceExtractor));
|
||||
}
|
||||
}
|
||||
|
||||
// Hand extractor(s)
|
||||
if (wrapperHandStruct.extractAndRenderHands)
|
||||
{
|
||||
for (auto gpuId = 0; gpuId < spWPoses.size(); gpuId++)
|
||||
{
|
||||
const auto handsExtractor = std::make_shared<experimental::HandsExtractor>(
|
||||
const auto handExtractor = std::make_shared<experimental::HandExtractor>(
|
||||
wrapperStructPose.modelFolder, gpuId + wrapperStructPose.gpuNumberStart, wrapperStructPose.poseModel
|
||||
);
|
||||
spWPoses.at(gpuId).emplace_back(std::make_shared<experimental::WHandsExtractor<TDatumsPtr>>(handsExtractor));
|
||||
spWPoses.at(gpuId).emplace_back(std::make_shared<experimental::WHandExtractor<TDatumsPtr>>(handExtractor));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -539,15 +603,33 @@ namespace op
|
||||
for (auto i = 0; i < spWPoses.size(); i++)
|
||||
{
|
||||
// Construct hands renderer
|
||||
const auto handsRenderer = std::make_shared<experimental::HandsRenderer>(finalOutputSize);
|
||||
const auto handRenderer = std::make_shared<experimental::HandRenderer>(finalOutputSize);
|
||||
// Performance boost -> share spGpuMemoryPtr for all renderers
|
||||
if (!poseRenderers.empty())
|
||||
{
|
||||
const bool isLastRenderer = (!wrapperStructFace.extractAndRenderFace);
|
||||
handRenderer->setGpuMemoryAndSetIfLast(poseRenderers.at(i)->getGpuMemoryAndSetAsFirst(), isLastRenderer);
|
||||
}
|
||||
// Add worker
|
||||
spWPoses.at(i).emplace_back(std::make_shared<experimental::WHandRenderer<TDatumsPtr>>(handRenderer));
|
||||
}
|
||||
}
|
||||
|
||||
// Face renderer(s)
|
||||
if (wrapperStructFace.extractAndRenderFace)
|
||||
{
|
||||
for (auto i = 0; i < spWPoses.size(); i++)
|
||||
{
|
||||
// Construct face renderer
|
||||
const auto faceRenderer = std::make_shared<experimental::FaceRenderer>(finalOutputSize);
|
||||
// Performance boost -> share spGpuMemoryPtr for all renderers
|
||||
if (!poseRenderers.empty())
|
||||
{
|
||||
const bool isLastRenderer = true;
|
||||
handsRenderer->setGpuMemoryAndSetIfLast(poseRenderers.at(i)->getGpuMemoryAndSetAsFirst(), isLastRenderer);
|
||||
faceRenderer->setGpuMemoryAndSetIfLast(poseRenderers.at(i)->getGpuMemoryAndSetAsFirst(), isLastRenderer);
|
||||
}
|
||||
// Add worker
|
||||
spWPoses.at(i).emplace_back(std::make_shared<experimental::WHandsRenderer<TDatumsPtr>>(handsRenderer));
|
||||
spWPoses.at(i).emplace_back(std::make_shared<experimental::WFaceRenderer<TDatumsPtr>>(faceRenderer));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -567,8 +649,8 @@ namespace op
|
||||
&& (wrapperStructPose.poseScaleMode != ScaleMode::InputResolution || (finalOutputSize != producerSize))
|
||||
&& (wrapperStructPose.poseScaleMode != ScaleMode::NetOutputResolution || (finalOutputSize != netOutputSize)))
|
||||
{
|
||||
auto arrayScaler = std::make_shared<ArrayScaler>(wrapperStructPose.poseScaleMode);
|
||||
mPostProcessingWs.emplace_back(std::make_shared<WArrayScaler<TDatumsPtr>>(arrayScaler));
|
||||
auto keyPointScaler = std::make_shared<KeyPointScaler>(wrapperStructPose.poseScaleMode);
|
||||
mPostProcessingWs.emplace_back(std::make_shared<WKeyPointScaler<TDatumsPtr>>(keyPointScaler));
|
||||
}
|
||||
|
||||
mOutputWs.clear();
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef OPENPOSE__WRAPPER__WRAPPER_STRUCT_FACE_HPP
|
||||
#define OPENPOSE__WRAPPER__WRAPPER_STRUCT_FACE_HPP
|
||||
|
||||
namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
/**
|
||||
* WrapperStructFace: Face estimation and rendering configuration struct.
|
||||
* DO NOT USE. CODE TO BE FINISHED.
|
||||
* WrapperStructFace allows the user to set up the face estimation and rendering parameters that will be used for the OpenPose Wrapper
|
||||
* class.
|
||||
*/
|
||||
struct WrapperStructFace
|
||||
{
|
||||
/**
|
||||
* PROVISIONAL PARAMETER. IT WILL BE CHANGED.
|
||||
* Whether to extract and render face.
|
||||
*/
|
||||
bool extractAndRenderFace;
|
||||
|
||||
/**
|
||||
* Constructor of the struct.
|
||||
* It has the recommended and default values we recommend for each element of the struct.
|
||||
* Since all the elements of the struct are public, they can also be manually filled.
|
||||
*/
|
||||
WrapperStructFace(const bool extractAndRenderFace = false);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__WRAPPER__WRAPPER_STRUCT_FACE_HPP
|
||||
+7
-7
@@ -1,17 +1,17 @@
|
||||
#ifndef OPENPOSE__WRAPPER__WRAPPER_STRUCT_HANDS_HPP
|
||||
#define OPENPOSE__WRAPPER__WRAPPER_STRUCT_HANDS_HPP
|
||||
#ifndef OPENPOSE__WRAPPER__WRAPPER_STRUCT_HAND_HPP
|
||||
#define OPENPOSE__WRAPPER__WRAPPER_STRUCT_HAND_HPP
|
||||
|
||||
namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
/**
|
||||
* WrapperStructHands: Hands estimation and rendering configuration struct.
|
||||
* WrapperStructHand: Hands estimation and rendering configuration struct.
|
||||
* DO NOT USE. CODE TO BE FINISHED.
|
||||
* WrapperStructHands allows the user to set up the hands estimation and rendering parameters that will be used for the OpenPose Wrapper
|
||||
* WrapperStructHand allows the user to set up the hands estimation and rendering parameters that will be used for the OpenPose Wrapper
|
||||
* class.
|
||||
*/
|
||||
struct WrapperStructHands
|
||||
struct WrapperStructHand
|
||||
{
|
||||
/**
|
||||
* PROVISIONAL PARAMETER. IT WILL BE CHANGED.
|
||||
@@ -24,9 +24,9 @@ namespace op
|
||||
* It has the recommended and default values we recommend for each element of the struct.
|
||||
* Since all the elements of the struct are public, they can also be manually filled.
|
||||
*/
|
||||
WrapperStructHands(const bool extractAndRenderHands = false);
|
||||
WrapperStructHand(const bool extractAndRenderHands = false);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENPOSE__WRAPPER__WRAPPER_STRUCT_HANDS_HPP
|
||||
#endif // OPENPOSE__WRAPPER__WRAPPER_STRUCT_HAND_HPP
|
||||
@@ -25,14 +25,14 @@ namespace op
|
||||
/**
|
||||
* Output size of the final rendered image.
|
||||
* It barely affects performance compared to netInputSize.
|
||||
* The final Datum.pose can be scaled with respect to outputSize if `poseScaleMode` is set to ScaleMode::OutputResolution, even if the
|
||||
* The final Datum.poseKeyPoints can be scaled with respect to outputSize if `poseScaleMode` is set to ScaleMode::OutputResolution, even if the
|
||||
* rendering is disabled.
|
||||
*/
|
||||
cv::Size outputSize;
|
||||
|
||||
/**
|
||||
* Final scale of the Array<float> Datum.pose and the writen pose data.
|
||||
* The final Datum.pose can be scaled with respect to input size (ScaleMode::InputResolution), net output size (ScaleMode::NetOutputResolution),
|
||||
* Final scale of the Array<float> Datum.poseKeyPoints and the writen pose data.
|
||||
* The final Datum.poseKeyPoints can be scaled with respect to input size (ScaleMode::InputResolution), net output size (ScaleMode::NetOutputResolution),
|
||||
* output rendering size (ScaleMode::OutputResolution), from 0 to 1 (ScaleMode::ZeroToOne), and -1 to 1 (ScaleMode::PlusMinusOne).
|
||||
*/
|
||||
ScaleMode poseScaleMode;
|
||||
|
||||
+15
-10
@@ -18,9 +18,10 @@ namespace op
|
||||
outputData{datum.outputData},
|
||||
cvOutputData{datum.cvOutputData},
|
||||
// Resulting Array<float> data
|
||||
pose{datum.pose},
|
||||
poseKeyPoints{datum.poseKeyPoints},
|
||||
poseHeatMaps{datum.poseHeatMaps},
|
||||
hands{datum.hands},
|
||||
faceKeyPoints{datum.faceKeyPoints},
|
||||
handKeyPoints{datum.handKeyPoints},
|
||||
// Other parameters
|
||||
scaleInputToOutput{datum.scaleInputToOutput},
|
||||
scaleNetToOutput{datum.scaleNetToOutput},
|
||||
@@ -42,9 +43,10 @@ namespace op
|
||||
outputData = datum.outputData;
|
||||
cvOutputData = datum.cvOutputData;
|
||||
// Resulting Array<float> data
|
||||
pose = datum.pose;
|
||||
poseKeyPoints = datum.poseKeyPoints;
|
||||
poseHeatMaps = datum.poseHeatMaps,
|
||||
hands = datum.hands,
|
||||
faceKeyPoints = datum.faceKeyPoints,
|
||||
handKeyPoints = datum.handKeyPoints,
|
||||
// Other parameters
|
||||
scaleInputToOutput = datum.scaleInputToOutput;
|
||||
scaleNetToOutput = datum.scaleNetToOutput;
|
||||
@@ -77,9 +79,10 @@ namespace op
|
||||
std::swap(outputData, datum.outputData);
|
||||
std::swap(cvOutputData, datum.cvOutputData);
|
||||
// Resulting Array<float> data
|
||||
std::swap(pose, datum.pose);
|
||||
std::swap(poseKeyPoints, datum.poseKeyPoints);
|
||||
std::swap(poseHeatMaps, datum.poseHeatMaps);
|
||||
std::swap(hands, datum.hands);
|
||||
std::swap(faceKeyPoints, datum.faceKeyPoints);
|
||||
std::swap(handKeyPoints, datum.handKeyPoints);
|
||||
// Other parameters
|
||||
std::swap(elementRendered, datum.elementRendered);
|
||||
}
|
||||
@@ -103,9 +106,10 @@ namespace op
|
||||
std::swap(outputData, datum.outputData);
|
||||
std::swap(cvOutputData, datum.cvOutputData);
|
||||
// Resulting Array<float> data
|
||||
std::swap(pose, datum.pose);
|
||||
std::swap(poseKeyPoints, datum.poseKeyPoints);
|
||||
std::swap(poseHeatMaps, datum.poseHeatMaps);
|
||||
std::swap(hands, datum.hands);
|
||||
std::swap(faceKeyPoints, datum.faceKeyPoints);
|
||||
std::swap(handKeyPoints, datum.handKeyPoints);
|
||||
// Other parameters
|
||||
scaleInputToOutput = datum.scaleInputToOutput;
|
||||
scaleNetToOutput = datum.scaleNetToOutput;
|
||||
@@ -139,9 +143,10 @@ namespace op
|
||||
datum.outputData = outputData.clone();
|
||||
datum.cvOutputData = cvOutputData.clone();
|
||||
// Resulting Array<float> data
|
||||
datum.pose = pose.clone();
|
||||
datum.poseKeyPoints = poseKeyPoints.clone();
|
||||
datum.poseHeatMaps = poseHeatMaps.clone();
|
||||
datum.hands = hands.clone();
|
||||
datum.faceKeyPoints = faceKeyPoints.clone();
|
||||
datum.handKeyPoints = handKeyPoints.clone();
|
||||
// Other parameters
|
||||
datum.scaleInputToOutput = scaleInputToOutput;
|
||||
datum.scaleNetToOutput = scaleNetToOutput;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace op
|
||||
{
|
||||
DEFINE_TEMPLATE_DATUM(WArrayScaler);
|
||||
DEFINE_TEMPLATE_DATUM(WCvMatToOpInput);
|
||||
DEFINE_TEMPLATE_DATUM(WCvMatToOpOutput);
|
||||
DEFINE_TEMPLATE_DATUM(WKeyPointScaler);
|
||||
DEFINE_TEMPLATE_DATUM(WOpOutputToCvMat);
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
#include "openpose/core/scalePose.hpp"
|
||||
#include "openpose/core/scaleKeyPoints.hpp"
|
||||
#include "openpose/utilities/errorAndLog.hpp"
|
||||
#include "openpose/core/arrayScaler.hpp"
|
||||
#include "openpose/core/keyPointScaler.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
ArrayScaler::ArrayScaler(const ScaleMode scalePose) :
|
||||
mScaleMode{scalePose}
|
||||
KeyPointScaler::KeyPointScaler(const ScaleMode scaleMode) :
|
||||
mScaleMode{scaleMode}
|
||||
{
|
||||
}
|
||||
|
||||
void ArrayScaler::scale(Array<float>& array, const double scaleInputToOutput, const double scaleNetToOutput, const cv::Size& producerSize) const
|
||||
void KeyPointScaler::scale(Array<float>& arrayToScale, const double scaleInputToOutput, const double scaleNetToOutput, const cv::Size& producerSize) const
|
||||
{
|
||||
try
|
||||
{
|
||||
std::vector<Array<float>> arrays{array};
|
||||
scale(arrays, scaleInputToOutput, scaleNetToOutput, producerSize);
|
||||
std::vector<Array<float>> arrayToScalesToScale{arrayToScale};
|
||||
scale(arrayToScalesToScale, scaleInputToOutput, scaleNetToOutput, producerSize);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -22,7 +22,7 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayScaler::scale(std::vector<Array<float>>& arrays, const double scaleInputToOutput, const double scaleNetToOutput, const cv::Size& producerSize) const
|
||||
void KeyPointScaler::scale(std::vector<Array<float>>& arrayToScalesToScale, const double scaleInputToOutput, const double scaleNetToOutput, const cv::Size& producerSize) const
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -30,20 +30,20 @@ namespace op
|
||||
{
|
||||
// InputResolution
|
||||
if (mScaleMode == ScaleMode::InputResolution)
|
||||
for (auto& array : arrays)
|
||||
scalePose(array, 1./scaleInputToOutput);
|
||||
for (auto& arrayToScale : arrayToScalesToScale)
|
||||
scaleKeyPoints(arrayToScale, 1./scaleInputToOutput);
|
||||
// NetOutputResolution
|
||||
else if (mScaleMode == ScaleMode::NetOutputResolution)
|
||||
for (auto& array : arrays)
|
||||
scalePose(array, 1./scaleNetToOutput);
|
||||
for (auto& arrayToScale : arrayToScalesToScale)
|
||||
scaleKeyPoints(arrayToScale, 1./scaleNetToOutput);
|
||||
// [0,1]
|
||||
else if (mScaleMode == ScaleMode::ZeroToOne)
|
||||
{
|
||||
const auto scale = 1./scaleInputToOutput;
|
||||
const auto scaleX = scale / ((double)producerSize.width - 1.);
|
||||
const auto scaleY = scale / ((double)producerSize.height - 1.);
|
||||
for (auto& array : arrays)
|
||||
scalePose(array, scaleX, scaleY);
|
||||
for (auto& arrayToScale : arrayToScalesToScale)
|
||||
scaleKeyPoints(arrayToScale, scaleX, scaleY);
|
||||
}
|
||||
// [-1,1]
|
||||
else if (mScaleMode == ScaleMode::PlusMinusOne)
|
||||
@@ -52,8 +52,8 @@ namespace op
|
||||
const auto scaleX = (scale / ((double)producerSize.width - 1.));
|
||||
const auto scaleY = (scale / ((double)producerSize.height - 1.));
|
||||
const auto offset = -1.;
|
||||
for (auto& array : arrays)
|
||||
scalePose(array, scaleX, scaleY, offset, offset);
|
||||
for (auto& arrayToScale : arrayToScalesToScale)
|
||||
scaleKeyPoints(arrayToScale, scaleX, scaleY, offset, offset);
|
||||
}
|
||||
// Unknown
|
||||
else
|
||||
@@ -82,7 +82,7 @@ namespace op
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scaleGap <= 0.f)
|
||||
if (scaleGap <= 0.f && num != targetSize[0])
|
||||
error("The scale gap must be greater than 0.", __LINE__, __FUNCTION__, __FILE__);
|
||||
const auto sourceNumOffset = channels * sourceChannelOffset;
|
||||
for (auto c = 0; c < channels; c++)
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
#include "openpose/utilities/errorAndLog.hpp"
|
||||
#include "openpose/core/scalePose.hpp"
|
||||
#include "openpose/core/scaleKeyPoints.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
const std::string errorMessage = "This function is only for array of dimension: [sizeA x sizeB x 3].";
|
||||
|
||||
void scalePose(Array<float>& pose, const double scale)
|
||||
void scaleKeyPoints(Array<float>& keyPoints, const double scale)
|
||||
{
|
||||
try
|
||||
{
|
||||
scalePose(pose, scale, scale);
|
||||
scaleKeyPoints(keyPoints, scale, scale);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -17,18 +17,18 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
void scalePose(Array<float>& pose, const double scaleX, const double scaleY)
|
||||
void scaleKeyPoints(Array<float>& keyPoints, const double scaleX, const double scaleY)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (scaleX != 1. && scaleY != 1.)
|
||||
{
|
||||
// Error check
|
||||
if (!pose.empty() && pose.getSize(2) != 3)
|
||||
if (!keyPoints.empty() && keyPoints.getSize(2) != 3)
|
||||
error(errorMessage, __LINE__, __FUNCTION__, __FILE__);
|
||||
// Get #people and #parts
|
||||
const auto numberPeople = pose.getSize(0);
|
||||
const auto numberParts = pose.getSize(1);
|
||||
const auto numberPeople = keyPoints.getSize(0);
|
||||
const auto numberParts = keyPoints.getSize(1);
|
||||
// For each person
|
||||
for (auto person = 0 ; person < numberPeople ; person++)
|
||||
{
|
||||
@@ -36,8 +36,8 @@ namespace op
|
||||
for (auto part = 0 ; part < numberParts ; part++)
|
||||
{
|
||||
const auto finalIndex = 3*(person*numberParts + part);
|
||||
pose[finalIndex] *= scaleX;
|
||||
pose[finalIndex+1] *= scaleY;
|
||||
keyPoints[finalIndex] *= scaleX;
|
||||
keyPoints[finalIndex+1] *= scaleY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,18 +48,18 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
void scalePose(Array<float>& pose, const double scaleX, const double scaleY, const double offsetX, const double offsetY)
|
||||
void scaleKeyPoints(Array<float>& keyPoints, const double scaleX, const double scaleY, const double offsetX, const double offsetY)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (scaleX != 1. && scaleY != 1.)
|
||||
{
|
||||
// Error check
|
||||
if (!pose.empty() && pose.getSize(2) != 3)
|
||||
if (!keyPoints.empty() && keyPoints.getSize(2) != 3)
|
||||
error(errorMessage, __LINE__, __FUNCTION__, __FILE__);
|
||||
// Get #people and #parts
|
||||
const auto numberPeople = pose.getSize(0);
|
||||
const auto numberParts = pose.getSize(1);
|
||||
const auto numberPeople = keyPoints.getSize(0);
|
||||
const auto numberParts = keyPoints.getSize(1);
|
||||
// For each person
|
||||
for (auto person = 0 ; person < numberPeople ; person++)
|
||||
{
|
||||
@@ -67,8 +67,8 @@ namespace op
|
||||
for (auto part = 0 ; part < numberParts ; part++)
|
||||
{
|
||||
const auto finalIndex = 3*(person*numberParts + part);
|
||||
pose[finalIndex] = pose[finalIndex] * scaleX + offsetX;
|
||||
pose[finalIndex+1] = pose[finalIndex+1] * scaleY + offsetY;
|
||||
keyPoints[finalIndex] = keyPoints[finalIndex] * scaleX + offsetX;
|
||||
keyPoints[finalIndex+1] = keyPoints[finalIndex+1] * scaleY + offsetY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "openpose/experimental/face/headers.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
DEFINE_TEMPLATE_DATUM(experimental::WFaceExtractor);
|
||||
DEFINE_TEMPLATE_DATUM(experimental::WFaceRenderer);
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
#include <opencv2/opencv.hpp> // CV_WARP_INVERSE_MAP, CV_INTER_LINEAR
|
||||
#include "openpose/core/netCaffe.hpp"
|
||||
#include "openpose/experimental/face/faceParameters.hpp"
|
||||
#include "openpose/pose/poseParameters.hpp"
|
||||
#include "openpose/utilities/cuda.hpp"
|
||||
#include "openpose/utilities/errorAndLog.hpp"
|
||||
#include "openpose/utilities/fastMath.hpp"
|
||||
#include "openpose/utilities/openCv.hpp"
|
||||
#include "openpose/experimental/face/faceExtractor.hpp"
|
||||
#include "openpose/experimental/face/faceRenderGpu.hpp" // For commented debugging section
|
||||
|
||||
namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
FaceExtractor::FaceExtractor(const std::string& modelFolder, const int gpuId, const PoseModel poseModel) :
|
||||
mNetOutputSize{368, 368},
|
||||
mOutputSize{1280, 720},
|
||||
mNeck{poseBodyPartMapStringToKey(poseModel, "Neck")},
|
||||
mNose{poseBodyPartMapStringToKey(poseModel, std::vector<std::string>{"Nose", "Head"})},
|
||||
mLEar{poseBodyPartMapStringToKey(poseModel, std::vector<std::string>{"LEar", "Head"})},
|
||||
mREar{poseBodyPartMapStringToKey(poseModel, std::vector<std::string>{"REar", "Head"})},
|
||||
mLEye{poseBodyPartMapStringToKey(poseModel, std::vector<std::string>{"LEye", "Head"})},
|
||||
mREye{poseBodyPartMapStringToKey(poseModel, std::vector<std::string>{"REye", "Head"})},
|
||||
spNet{std::make_shared<NetCaffe>(std::array<int,4>{1, 3, mNetOutputSize.height, mNetOutputSize.width}, modelFolder + FACE_PROTOTXT, modelFolder + FACE_TRAINED_MODEL, gpuId)},
|
||||
spResizeAndMergeCaffe{std::make_shared<ResizeAndMergeCaffe<float>>()},
|
||||
spNmsCaffe{std::make_shared<NmsCaffe<float>>()},
|
||||
mFaceImageCrop{mNetOutputSize.area()*3}
|
||||
{
|
||||
try
|
||||
{
|
||||
error("Hands and face extraction is not implemented yet. COMING SOON!", __LINE__, __FUNCTION__, __FILE__);
|
||||
// Properties
|
||||
for (auto& property : mProperties)
|
||||
property = 0.;
|
||||
mProperties[(int)FaceProperty::NMSThreshold] = FACE_DEFAULT_NMS_THRESHOLD;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void FaceExtractor::initializationOnThread()
|
||||
{
|
||||
try
|
||||
{
|
||||
log("Starting initialization on thread.", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// Get thread id
|
||||
mThreadId = {std::this_thread::get_id()};
|
||||
|
||||
// Caffe net
|
||||
spNet->initializationOnThread();
|
||||
spCaffeNetOutputBlob = ((NetCaffe*)spNet.get())->getOutputBlob();
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// HeatMaps extractor blob and layer
|
||||
spHeatMapsBlob = {std::make_shared<caffe::Blob<float>>(1,1,1,1)};
|
||||
const bool mergeFirstDimension = true;
|
||||
spResizeAndMergeCaffe->Reshape({spCaffeNetOutputBlob.get()}, {spHeatMapsBlob.get()}, FACE_CCN_DECREASE_FACTOR, mergeFirstDimension);
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// Pose extractor blob and layer
|
||||
spPeaksBlob = {std::make_shared<caffe::Blob<float>>(1,1,1,1)};
|
||||
spNmsCaffe->Reshape({spHeatMapsBlob.get()}, {spPeaksBlob.get()}, FACE_MAX_PEAKS, FACE_NUMBER_PARTS);
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
log("Finished initialization on thread.", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void FaceExtractor::forwardPass(const Array<float>& poseKeyPoints, const cv::Mat& cvInputData)
|
||||
{
|
||||
try
|
||||
{
|
||||
UNUSED(poseKeyPoints);
|
||||
UNUSED(cvInputData);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
Array<float> FaceExtractor::getFaceKeyPoints() const
|
||||
{
|
||||
try
|
||||
{
|
||||
checkThread();
|
||||
return mFaceKeyPoints;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return Array<float>{};
|
||||
}
|
||||
}
|
||||
|
||||
double FaceExtractor::get(const FaceProperty property) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return mProperties.at((int)property);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return 0.;
|
||||
}
|
||||
}
|
||||
|
||||
void FaceExtractor::set(const FaceProperty property, const double value)
|
||||
{
|
||||
try
|
||||
{
|
||||
mProperties.at((int)property) = {value};
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void FaceExtractor::increase(const FaceProperty property, const double value)
|
||||
{
|
||||
try
|
||||
{
|
||||
mProperties[(int)property] = mProperties.at((int)property) + value;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void FaceExtractor::checkThread() const
|
||||
{
|
||||
try
|
||||
{
|
||||
if(mThreadId != std::this_thread::get_id())
|
||||
error("The CPU/GPU pointer data cannot be accessed from a different thread.", __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#include "openpose/experimental/face/faceParameters.hpp"
|
||||
#include "openpose/utilities/errorAndLog.hpp"
|
||||
#include "openpose/utilities/cuda.hpp"
|
||||
#include "openpose/utilities/cuda.hu"
|
||||
#include "openpose/utilities/render.hu"
|
||||
#include "openpose/experimental/face/faceRenderGpu.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
const auto THREADS_PER_BLOCK_1D = 32;
|
||||
|
||||
__constant__ const unsigned char PART_PAIRS_GPU[] = FACE_PAIRS_TO_RENDER;
|
||||
__constant__ const float RGB_COLORS[] = {
|
||||
255.f, 255.f, 255.f,
|
||||
};
|
||||
|
||||
|
||||
|
||||
__global__ void renderFaceParts(float* targetPtr, const int targetWidth, const int targetHeight, const float* const facePtr,
|
||||
const int numberFaces, const float threshold, const float alphaColorToAdd)
|
||||
{
|
||||
const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;
|
||||
const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;
|
||||
const auto globalIdx = threadIdx.y * blockDim.x + threadIdx.x;
|
||||
|
||||
// Shared parameters
|
||||
__shared__ float2 sharedMins[FACE_MAX_NUMBER_FACE];
|
||||
__shared__ float2 sharedMaxs[FACE_MAX_NUMBER_FACE];
|
||||
__shared__ float sharedScaleF[FACE_MAX_NUMBER_FACE];
|
||||
|
||||
// Other parameters
|
||||
const auto numberPartPairs = sizeof(PART_PAIRS_GPU) / (2*sizeof(PART_PAIRS_GPU[0]));
|
||||
const auto numberColors = sizeof(RGB_COLORS) / (3*sizeof(RGB_COLORS[0]));
|
||||
const auto radius = fastMin(targetWidth, targetHeight) / 120.f;
|
||||
const auto stickwidth = fastMin(targetWidth, targetHeight) / 250.f;
|
||||
|
||||
// Render key points
|
||||
renderKeyPoints(targetPtr, sharedMaxs, sharedMins, sharedScaleF,
|
||||
globalIdx, x, y, targetWidth, targetHeight, facePtr, PART_PAIRS_GPU, numberFaces,
|
||||
FACE_NUMBER_PARTS, numberPartPairs, RGB_COLORS, numberColors,
|
||||
radius, stickwidth, threshold, alphaColorToAdd);
|
||||
}
|
||||
|
||||
void renderFaceGpu(float* framePtr, const cv::Size& frameSize, const float* const facePtr, const int numberFaces, const float alphaColorToAdd)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (numberFaces > 0)
|
||||
{
|
||||
//framePtr = width * height * 3
|
||||
//facePtr = 3 (x,y,score) * #Hand parts * # face
|
||||
const auto threshold = 0.4f;
|
||||
dim3 threadsPerBlock = dim3{THREADS_PER_BLOCK_1D, THREADS_PER_BLOCK_1D};
|
||||
dim3 numBlocks = dim3{getNumberCudaBlocks(frameSize.width, threadsPerBlock.x), getNumberCudaBlocks(frameSize.height, threadsPerBlock.y)};
|
||||
// log("numberFaces: " + std::to_string(numberFaces), Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
renderFaceParts<<<threadsPerBlock, numBlocks>>>(framePtr, frameSize.width, frameSize.height, facePtr, numberFaces, threshold, alphaColorToAdd);
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#include <cuda.h>
|
||||
#include <cuda_runtime_api.h>
|
||||
#include "openpose/experimental/face/faceParameters.hpp"
|
||||
#include "openpose/experimental/face/faceRenderGpu.hpp"
|
||||
#include "openpose/utilities/cuda.hpp"
|
||||
#include "openpose/utilities/errorAndLog.hpp"
|
||||
#include "openpose/experimental/face/faceRenderer.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
FaceRenderer::FaceRenderer(const cv::Size& frameSize) :
|
||||
Renderer{(unsigned long long)(frameSize.area() * 3)},
|
||||
mFrameSize{frameSize}
|
||||
{
|
||||
}
|
||||
|
||||
FaceRenderer::~FaceRenderer()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Free CUDA pointers - Note that if pointers are 0 (i.e. nullptr), no operation is performed.
|
||||
cudaFree(pGpuFace);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void FaceRenderer::initializationOnThread()
|
||||
{
|
||||
try
|
||||
{
|
||||
Renderer::initializationOnThread();
|
||||
cudaMalloc((void**)(&pGpuFace), FACE_NUMBER_PARTS * 3 * sizeof(float) );
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void FaceRenderer::renderFace(Array<float>& outputData, const Array<float>& faceKeyPoints)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!faceKeyPoints.empty())
|
||||
{
|
||||
cpuToGpuMemoryIfNotCopiedYet(outputData.getPtr());
|
||||
cudaMemcpy(pGpuFace, faceKeyPoints.getConstPtr(), FACE_NUMBER_PARTS*3 * sizeof(float), cudaMemcpyHostToDevice);
|
||||
renderFaceGpu(*spGpuMemoryPtr, mFrameSize, pGpuFace, faceKeyPoints.getSize(0));
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
// GPU memory to CPU if last renderer
|
||||
gpuToCpuMemoryIfLastRenderer(outputData.getPtr());
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "openpose/experimental/hand/headers.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
DEFINE_TEMPLATE_DATUM(experimental::WHandExtractor);
|
||||
DEFINE_TEMPLATE_DATUM(experimental::WHandRenderer);
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
#include <opencv2/opencv.hpp> // CV_WARP_INVERSE_MAP, CV_INTER_LINEAR
|
||||
#include "openpose/core/netCaffe.hpp"
|
||||
#include "openpose/experimental/hand/handParameters.hpp"
|
||||
#include "openpose/pose/poseParameters.hpp"
|
||||
#include "openpose/utilities/cuda.hpp"
|
||||
#include "openpose/utilities/errorAndLog.hpp"
|
||||
#include "openpose/utilities/fastMath.hpp"
|
||||
#include "openpose/utilities/openCv.hpp"
|
||||
#include "openpose/experimental/hand/handExtractor.hpp"
|
||||
// #include "openpose/experimental/hand/handRenderGpu.hpp" // For commented debugging section
|
||||
|
||||
namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
HandExtractor::HandExtractor(const std::string& modelFolder, const int gpuId, const PoseModel poseModel) :
|
||||
mNetOutputSize{368, 368},
|
||||
mOutputSize{1280, 720},
|
||||
mRWrist{poseBodyPartMapStringToKey(poseModel, "RWrist")},
|
||||
mRElbow{poseBodyPartMapStringToKey(poseModel, "RElbow")},
|
||||
mLWrist{poseBodyPartMapStringToKey(poseModel, "LWrist")},
|
||||
mLElbow{poseBodyPartMapStringToKey(poseModel, "LElbow")},
|
||||
mNeck{poseBodyPartMapStringToKey(poseModel, "Neck")},
|
||||
mHeadNose{poseBodyPartMapStringToKey(poseModel, std::vector<std::string>{"Nose", "Head"})},
|
||||
spNet{std::make_shared<NetCaffe>(std::array<int,4>{2, 3, mNetOutputSize.height, mNetOutputSize.width}, modelFolder + HAND_PROTOTXT, modelFolder + HAND_TRAINED_MODEL, gpuId)},
|
||||
spResizeAndMergeCaffe{std::make_shared<ResizeAndMergeCaffe<float>>()},
|
||||
spNmsCaffe{std::make_shared<NmsCaffe<float>>()},
|
||||
mLeftHandCrop{mNetOutputSize.area()*3},
|
||||
mRightHandCrop{mLeftHandCrop.getSize()},
|
||||
mScaleLeftHand{100.f},
|
||||
mScaleRightHand{mScaleLeftHand}
|
||||
{
|
||||
try
|
||||
{
|
||||
error("Hands and face extraction is not implemented yet. COMING SOON!", __LINE__, __FUNCTION__, __FILE__);
|
||||
// Properties
|
||||
for (auto& property : mProperties)
|
||||
property = 0.;
|
||||
mProperties[(int)HandsProperty::NMSThreshold] = HAND_DEFAULT_NMS_THRESHOLD;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void HandExtractor::initializationOnThread()
|
||||
{
|
||||
try
|
||||
{
|
||||
log("Starting initialization on thread.", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// Get thread id
|
||||
mThreadId = {std::this_thread::get_id()};
|
||||
|
||||
// Caffe net
|
||||
spNet->initializationOnThread();
|
||||
spCaffeNetOutputBlob = ((NetCaffe*)spNet.get())->getOutputBlob();
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// HeatMaps extractor blob and layer
|
||||
spHeatMapsBlob = {std::make_shared<caffe::Blob<float>>(1,1,1,1)};
|
||||
const bool mergeFirstDimension = false;
|
||||
spResizeAndMergeCaffe->Reshape({spCaffeNetOutputBlob.get()}, {spHeatMapsBlob.get()}, HAND_CCN_DECREASE_FACTOR, mergeFirstDimension);
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
// Pose extractor blob and layer
|
||||
spPeaksBlob = {std::make_shared<caffe::Blob<float>>(1,1,1,1)};
|
||||
spNmsCaffe->Reshape({spHeatMapsBlob.get()}, {spPeaksBlob.get()}, HAND_MAX_PEAKS, HAND_NUMBER_PARTS);
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
log("Finished initialization on thread.", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void HandExtractor::forwardPass(const Array<float>& poseKeyPoints, const cv::Mat& cvInputData)
|
||||
{
|
||||
try
|
||||
{
|
||||
UNUSED(poseKeyPoints);
|
||||
UNUSED(cvInputData);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
Array<float> HandExtractor::getHandKeyPoints() const
|
||||
{
|
||||
try
|
||||
{
|
||||
checkThread();
|
||||
return mHands;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return Array<float>{};
|
||||
}
|
||||
}
|
||||
|
||||
double HandExtractor::get(const HandsProperty property) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return mProperties.at((int)property);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return 0.;
|
||||
}
|
||||
}
|
||||
|
||||
void HandExtractor::set(const HandsProperty property, const double value)
|
||||
{
|
||||
try
|
||||
{
|
||||
mProperties.at((int)property) = {value};
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void HandExtractor::increase(const HandsProperty property, const double value)
|
||||
{
|
||||
try
|
||||
{
|
||||
mProperties[(int)property] = mProperties.at((int)property) + value;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void HandExtractor::checkThread() const
|
||||
{
|
||||
try
|
||||
{
|
||||
if(mThreadId != std::this_thread::get_id())
|
||||
error("The CPU/GPU pointer data cannot be accessed from a different thread.", __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "openpose/experimental/hand/handParameters.hpp"
|
||||
#include "openpose/utilities/errorAndLog.hpp"
|
||||
#include "openpose/utilities/cuda.hpp"
|
||||
#include "openpose/utilities/cuda.hu"
|
||||
#include "openpose/utilities/render.hu"
|
||||
#include "openpose/experimental/hand/handRenderGpu.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
const auto THREADS_PER_BLOCK_1D = 32;
|
||||
|
||||
__constant__ const unsigned char PART_PAIRS_GPU[] = HAND_PAIRS_TO_RENDER;
|
||||
__constant__ const float RGB_COLORS[] = {
|
||||
179.f, 0.f, 0.f,
|
||||
204.f, 0.f, 0.f,
|
||||
230.f, 0.f, 0.f,
|
||||
255.f, 0.f, 0.f,
|
||||
143.f, 179.f, 0.f,
|
||||
163.f, 204.f, 0.f,
|
||||
184.f, 230.f, 0.f,
|
||||
204.f, 255.f, 0.f,
|
||||
0.f, 179.f, 71.f,
|
||||
0.f, 204.f, 82.f,
|
||||
0.f, 230.f, 92.f,
|
||||
0.f, 255.f, 102.f,
|
||||
0.f, 71.f, 179.f,
|
||||
0.f, 82.f, 204.f,
|
||||
0.f, 92.f, 230.f,
|
||||
0.f, 102.f, 255.f,
|
||||
143.f, 0.f, 179.f,
|
||||
163.f, 0.f, 204.f,
|
||||
184.f, 0.f, 230.f,
|
||||
204.f, 0.f, 255.f,
|
||||
179.f, 179.f, 179.f,
|
||||
179.f, 179.f, 179.f,
|
||||
179.f, 179.f, 179.f,
|
||||
179.f, 179.f, 179.f
|
||||
};
|
||||
|
||||
|
||||
|
||||
__global__ void renderHandsParts(float* targetPtr, const int targetWidth, const int targetHeight, const float* const handsPtr,
|
||||
const int numberHands, const float threshold, const float alphaColorToAdd)
|
||||
{
|
||||
const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;
|
||||
const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;
|
||||
const auto globalIdx = threadIdx.y * blockDim.x + threadIdx.x;
|
||||
|
||||
// Shared parameters
|
||||
__shared__ float2 sharedMins[HAND_MAX_NUMBER_HANDS];
|
||||
__shared__ float2 sharedMaxs[HAND_MAX_NUMBER_HANDS];
|
||||
__shared__ float sharedScaleF[HAND_MAX_NUMBER_HANDS];
|
||||
|
||||
// Other parameters
|
||||
const auto numberPartPairs = sizeof(PART_PAIRS_GPU) / (2*sizeof(PART_PAIRS_GPU[0]));
|
||||
const auto numberColors = sizeof(RGB_COLORS) / (3*sizeof(RGB_COLORS[0]));
|
||||
const auto radius = fastMin(targetWidth, targetHeight) / 100.f;
|
||||
const auto stickwidth = fastMin(targetWidth, targetHeight) / 80.f;
|
||||
|
||||
// Render key points
|
||||
renderKeyPoints(targetPtr, sharedMaxs, sharedMins, sharedScaleF,
|
||||
globalIdx, x, y, targetWidth, targetHeight, handsPtr, PART_PAIRS_GPU, numberHands,
|
||||
HAND_NUMBER_PARTS, numberPartPairs, RGB_COLORS, numberColors,
|
||||
radius, stickwidth, threshold, alphaColorToAdd);
|
||||
}
|
||||
|
||||
void renderHandsGpu(float* framePtr, const cv::Size& frameSize, const float* const handsPtr, const int numberHands, const float alphaColorToAdd)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (numberHands > 0)
|
||||
{
|
||||
//framePtr = width * height * 3
|
||||
//handsPtr = 3 (x,y,score) * #Hand parts * # hands
|
||||
const auto threshold = 0.05f;
|
||||
dim3 threadsPerBlock = dim3{THREADS_PER_BLOCK_1D, THREADS_PER_BLOCK_1D};
|
||||
dim3 numBlocks = dim3{getNumberCudaBlocks(frameSize.width, threadsPerBlock.x), getNumberCudaBlocks(frameSize.height, threadsPerBlock.y)};
|
||||
// log("numberHands: " + std::to_string(numberHands), Priority::Low, __LINE__, __FUNCTION__, __FILE__);
|
||||
renderHandsParts<<<threadsPerBlock, numBlocks>>>(framePtr, frameSize.width, frameSize.height, handsPtr, numberHands, threshold, alphaColorToAdd);
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#include <cuda.h>
|
||||
#include <cuda_runtime_api.h>
|
||||
#include "openpose/experimental/hand/handParameters.hpp"
|
||||
#include "openpose/experimental/hand/handRenderGpu.hpp"
|
||||
#include "openpose/utilities/cuda.hpp"
|
||||
#include "openpose/utilities/errorAndLog.hpp"
|
||||
#include "openpose/experimental/hand/handRenderer.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
HandRenderer::HandRenderer(const cv::Size& frameSize) :
|
||||
Renderer{(unsigned long long)(frameSize.area() * 3)},
|
||||
mFrameSize{frameSize}
|
||||
{
|
||||
}
|
||||
|
||||
HandRenderer::~HandRenderer()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Free CUDA pointers - Note that if pointers are 0 (i.e. nullptr), no operation is performed.
|
||||
cudaFree(pGpuHands);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void HandRenderer::initializationOnThread()
|
||||
{
|
||||
try
|
||||
{
|
||||
Renderer::initializationOnThread();
|
||||
cudaMalloc((void**)(&pGpuHands), 2*HAND_NUMBER_PARTS * 3 * sizeof(float) );
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void HandRenderer::renderHands(Array<float>& outputData, const Array<float>& handKeyPoints)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!handKeyPoints.empty())
|
||||
{
|
||||
cpuToGpuMemoryIfNotCopiedYet(outputData.getPtr());
|
||||
cudaMemcpy(pGpuHands, handKeyPoints.getConstPtr(), 2*HAND_NUMBER_PARTS*3 * sizeof(float), cudaMemcpyHostToDevice);
|
||||
renderHandsGpu(*spGpuMemoryPtr, mFrameSize, pGpuHands, handKeyPoints.getSize(0));
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
// GPU memory to CPU if last renderer
|
||||
gpuToCpuMemoryIfLastRenderer(outputData.getPtr());
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#include "openpose/experimental/hands/headers.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
DEFINE_TEMPLATE_DATUM(experimental::WHandsExtractor);
|
||||
DEFINE_TEMPLATE_DATUM(experimental::WHandsRenderer);
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
#include "openpose/utilities/errorAndLog.hpp"
|
||||
#include "openpose/experimental/hands/handsExtractor.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
HandsExtractor::HandsExtractor(const std::string& modelFolder, const int gpuId, const PoseModel poseModel) :
|
||||
mNetOutputSize{368, 368},
|
||||
mOutputSize{1280, 720},
|
||||
mRWrist{0},
|
||||
mRElbow{0},
|
||||
mLWrist{0},
|
||||
mLElbow{0},
|
||||
mNeck{0},
|
||||
mHeadNose{0},
|
||||
spNet{},
|
||||
spResizeAndMergeCaffe{},
|
||||
spNmsCaffe{},
|
||||
mLeftHandCrop{mNetOutputSize.area()*3},
|
||||
mRightHandCrop{mLeftHandCrop.getSize()},
|
||||
mScaleLeftHand{0.f},
|
||||
mScaleRightHand{0.f}
|
||||
{
|
||||
UNUSED(modelFolder);
|
||||
UNUSED(gpuId);
|
||||
UNUSED(poseModel);
|
||||
error("Hands code is not ready yet. A first beta version will be included in around 1-2 months. Please, set extractAndRenderHands = false in the OpenPose wrapper.",
|
||||
__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
|
||||
void HandsExtractor::initializationOnThread()
|
||||
{
|
||||
error("Hands code is not ready yet. A first beta version will be included in around 1-2 months. Please, set extractAndRenderHands = false in the OpenPose wrapper.",
|
||||
__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
|
||||
void HandsExtractor::forwardPass(const Array<float>& pose, const cv::Mat& cvInputData)
|
||||
{
|
||||
try
|
||||
{
|
||||
UNUSED(pose);
|
||||
UNUSED(cvInputData);
|
||||
error("Hands code is not ready yet. A first beta version will be included in around 1-2 months. Please, set extractAndRenderHands = false in the OpenPose wrapper.",
|
||||
__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
Array<float> HandsExtractor::getHands() const
|
||||
{
|
||||
try
|
||||
{
|
||||
checkThread();
|
||||
return mHands;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return Array<float>{};
|
||||
}
|
||||
}
|
||||
|
||||
double HandsExtractor::get(const HandsProperty property) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return mProperties.at((int)property);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return 0.;
|
||||
}
|
||||
}
|
||||
|
||||
void HandsExtractor::set(const HandsProperty property, const double value)
|
||||
{
|
||||
try
|
||||
{
|
||||
mProperties.at((int)property) = {value};
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void HandsExtractor::increase(const HandsProperty property, const double value)
|
||||
{
|
||||
try
|
||||
{
|
||||
mProperties[(int)property] = mProperties.at((int)property) + value;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void HandsExtractor::checkThread() const
|
||||
{
|
||||
try
|
||||
{
|
||||
if(mThreadId != std::this_thread::get_id())
|
||||
error("The CPU/GPU pointer data cannot be accessed from a different thread.", __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#include "openpose/utilities/errorAndLog.hpp"
|
||||
#include "openpose/experimental/hands/handsRenderGpu.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
void renderHandsGpu(float* framePtr, const cv::Size& frameSize, const float* const handsPtr, const int numberHands, const float alphaColorToAdd)
|
||||
{
|
||||
try
|
||||
{
|
||||
error("Hands code is not ready yet. A first beta version will be included in around 1-2 months. Please, set extractAndRenderHands = false in the OpenPose wrapper.",
|
||||
__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
#include "openpose/utilities/errorAndLog.hpp"
|
||||
#include "openpose/experimental/hands/handsRenderer.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
HandsRenderer::HandsRenderer(const cv::Size& frameSize) :
|
||||
Renderer{(unsigned long long)(frameSize.area() * 3)},
|
||||
mFrameSize{frameSize}
|
||||
{
|
||||
error("Hands code is not ready yet. A first beta version will be included in around 1-2 months. Please, set extractAndRenderHands = false in the OpenPose wrapper.",
|
||||
__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
|
||||
HandsRenderer::~HandsRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
void HandsRenderer::initializationOnThread()
|
||||
{
|
||||
try
|
||||
{
|
||||
error("Hands code is not ready yet. A first beta version will be included in around 1-2 months. Please, set extractAndRenderHands = false in the OpenPose wrapper.",
|
||||
__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
void HandsRenderer::renderHands(Array<float>& outputData, const Array<float>& hands)
|
||||
{
|
||||
try
|
||||
{
|
||||
UNUSED(outputData);
|
||||
UNUSED(hands);
|
||||
error("Hands code is not ready yet. A first beta version will be included in around 1-2 months. Please, set extractAndRenderHands = false in the OpenPose wrapper.",
|
||||
__LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,12 +28,12 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
void PoseJsonCocoSaver::record(const Array<float>& pose, const int imageId)
|
||||
void PoseJsonCocoSaver::record(const Array<float>& poseKeyPoints, const int imageId)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto numberPeople = pose.getSize(0);
|
||||
const auto numberBodyParts = pose.getSize(1);
|
||||
const auto numberPeople = poseKeyPoints.getSize(0);
|
||||
const auto numberBodyParts = poseKeyPoints.getSize(1);
|
||||
for (auto person = 0 ; person < numberPeople ; person++)
|
||||
{
|
||||
// Comma at any moment but first element
|
||||
@@ -58,16 +58,16 @@ namespace op
|
||||
mJsonOfstream.plainText("1");
|
||||
mJsonOfstream.comma();
|
||||
|
||||
// keypoints - i.e. pose
|
||||
// keypoints - i.e. poseKeyPoints
|
||||
mJsonOfstream.key("keypoints");
|
||||
mJsonOfstream.arrayOpen();
|
||||
const std::vector<int> indexesInCocoOrder{0, 15, 14, 17, 16, 5, 2, 6, 3, 7, 4, 11, 8, 12, 9, 13, 10};
|
||||
for (auto bodyPart = 0 ; bodyPart < indexesInCocoOrder.size() ; bodyPart++)
|
||||
{
|
||||
const auto finalIndex = 3*(person*numberBodyParts + indexesInCocoOrder.at(bodyPart));
|
||||
mJsonOfstream.plainText(pose[finalIndex]);
|
||||
mJsonOfstream.plainText(poseKeyPoints[finalIndex]);
|
||||
mJsonOfstream.comma();
|
||||
mJsonOfstream.plainText(pose[finalIndex+1]);
|
||||
mJsonOfstream.plainText(poseKeyPoints[finalIndex+1]);
|
||||
mJsonOfstream.comma();
|
||||
mJsonOfstream.plainText(1);
|
||||
if (bodyPart < numberBodyParts-1)
|
||||
|
||||
@@ -9,21 +9,21 @@ namespace op
|
||||
{
|
||||
}
|
||||
|
||||
void PoseJsonSaver::savePoseVector(const std::vector<Array<float>>& poseVector, const std::string& fileName) const
|
||||
void PoseJsonSaver::savePoseKeyPoints(const std::vector<Array<float>>& poseKeyPointsVector, const std::string& fileName) const
|
||||
{
|
||||
try
|
||||
{
|
||||
// Record json
|
||||
if (!poseVector.empty())
|
||||
if (!poseKeyPointsVector.empty())
|
||||
{
|
||||
// File path (no extension)
|
||||
const auto fileNameNoExtension = getNextFileName(fileName) + "_pose";
|
||||
|
||||
const bool humanReadable = true;
|
||||
for (auto i = 0; i < poseVector.size(); i++)
|
||||
for (auto i = 0; i < poseKeyPointsVector.size(); i++)
|
||||
{
|
||||
const auto fileName = fileNameNoExtension + (i != 0 ? "_" + std::to_string(i) : "") + ".json";
|
||||
savePoseJson(poseVector[i], fileName, humanReadable);
|
||||
savePoseJson(poseKeyPointsVector[i], fileName, humanReadable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,27 +11,27 @@ namespace op
|
||||
{
|
||||
}
|
||||
|
||||
void PoseSaver::savePoseVector(const std::vector<Array<float>>& poseVector, const std::string& fileName) const
|
||||
void PoseSaver::savePoseKeyPoints(const std::vector<Array<float>>& poseKeyPointsVector, const std::string& fileName) const
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!poseVector.empty())
|
||||
if (!poseKeyPointsVector.empty())
|
||||
{
|
||||
// File path (no extension)
|
||||
const auto fileNameNoExtension = getNextFileName(fileName) + "_pose";
|
||||
|
||||
// Get vector of people poses
|
||||
std::vector<cv::Mat> cvMatPoses(poseVector.size());
|
||||
for (auto i = 0; i < poseVector.size(); i++)
|
||||
cvMatPoses[i] = poseVector[i].getConstCvMat();
|
||||
std::vector<cv::Mat> cvMatPoses(poseKeyPointsVector.size());
|
||||
for (auto i = 0; i < poseKeyPointsVector.size(); i++)
|
||||
cvMatPoses[i] = poseKeyPointsVector[i].getConstCvMat();
|
||||
|
||||
// Get names inside file
|
||||
std::vector<std::string> poseVectorNames(cvMatPoses.size());
|
||||
std::vector<std::string> poseKeyPointsVectorNames(cvMatPoses.size());
|
||||
for (auto i = 0; i < cvMatPoses.size(); i++)
|
||||
poseVectorNames[i] = {"pose_" + std::to_string(i)};
|
||||
poseKeyPointsVectorNames[i] = {"pose_" + std::to_string(i)};
|
||||
|
||||
// Record people poses in desired format
|
||||
saveData(cvMatPoses, poseVectorNames, fileNameNoExtension, mFormat);
|
||||
saveData(cvMatPoses, poseKeyPointsVectorNames, fileNameNoExtension, mFormat);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace op
|
||||
{
|
||||
}
|
||||
|
||||
void GuiInfoAdder::addInfo(cv::Mat& cvOutputData, const Array<float>& pose, const unsigned long long id, const std::string& elementRenderedName)
|
||||
void GuiInfoAdder::addInfo(cv::Mat& cvOutputData, const Array<float>& poseKeyPoints, const unsigned long long id, const std::string& elementRenderedName)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -83,7 +83,7 @@ namespace op
|
||||
// Frame number
|
||||
putTextOnCvMat(cvOutputData, "Frame " + std::to_string(id), {mBorderMargin, (int)(mOutputSize.height - mBorderMargin)}, white, false);
|
||||
// Number people
|
||||
const auto textToDisplay = std::to_string(pose.getSize(0)) + " people";
|
||||
const auto textToDisplay = std::to_string(poseKeyPoints.getSize(0)) + " people";
|
||||
putTextOnCvMat(cvOutputData, textToDisplay, {(int)(mOutputSize.width - mBorderMargin), (int)(mOutputSize.height - mBorderMargin)}, white, true);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
namespace op
|
||||
{
|
||||
template <typename T>
|
||||
void connectBodyPartsCpu(Array<T>& pose, const T* const heatMapPtr, const T* const peaksPtr, const PoseModel poseModel, const cv::Size& heatMapSize, const int maxPeaks,
|
||||
void connectBodyPartsCpu(Array<T>& poseKeyPoints, const T* const heatMapPtr, const T* const peaksPtr, const PoseModel poseModel, const cv::Size& heatMapSize, const int maxPeaks,
|
||||
const int interMinAboveThreshold, const T interThreshold, const int minSubsetCnt, const T minSubsetScore, const T scaleFactor)
|
||||
{
|
||||
try
|
||||
@@ -290,11 +290,11 @@ namespace op
|
||||
error("Bad subsetCounter. Bug in in this function if this happens.", __LINE__, __FUNCTION__, __FILE__);
|
||||
}
|
||||
|
||||
// Fill and return pose
|
||||
// Fill and return poseKeyPoints
|
||||
if (numberPeople > 0)
|
||||
pose.reset({numberPeople, numberBodyParts, 3});
|
||||
poseKeyPoints.reset({numberPeople, numberBodyParts, 3});
|
||||
else
|
||||
pose.reset();
|
||||
poseKeyPoints.reset();
|
||||
for (auto person = 0 ; person < validSubsetIndexes.size() ; person++)
|
||||
{
|
||||
const auto& subsetI = subset[validSubsetIndexes[person]].first;
|
||||
@@ -304,15 +304,15 @@ namespace op
|
||||
const auto bodyPartIndex = subsetI[bodyPart];
|
||||
if (bodyPartIndex > 0)
|
||||
{
|
||||
pose[baseOffset] = peaksPtr[bodyPartIndex-2] * scaleFactor;
|
||||
pose[baseOffset + 1] = peaksPtr[bodyPartIndex-1] * scaleFactor;
|
||||
pose[baseOffset + 2] = peaksPtr[bodyPartIndex];
|
||||
poseKeyPoints[baseOffset] = peaksPtr[bodyPartIndex-2] * scaleFactor;
|
||||
poseKeyPoints[baseOffset + 1] = peaksPtr[bodyPartIndex-1] * scaleFactor;
|
||||
poseKeyPoints[baseOffset + 2] = peaksPtr[bodyPartIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
pose[baseOffset] = 0.f;
|
||||
pose[baseOffset + 1] = 0.f;
|
||||
pose[baseOffset + 2] = 0.f;
|
||||
poseKeyPoints[baseOffset] = 0.f;
|
||||
poseKeyPoints[baseOffset + 1] = 0.f;
|
||||
poseKeyPoints[baseOffset + 2] = 0.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -323,10 +323,10 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
template void connectBodyPartsCpu(Array<float>& pose, const float* const heatMapPtr, const float* const peaksPtr, const PoseModel poseModel, const cv::Size& heatMapSize,
|
||||
template void connectBodyPartsCpu(Array<float>& poseKeyPoints, const float* const heatMapPtr, const float* const peaksPtr, const PoseModel poseModel, const cv::Size& heatMapSize,
|
||||
const int maxPeaks, const int interMinAboveThreshold, const float interThreshold, const int minSubsetCnt,
|
||||
const float minSubsetScore, const float scaleFactor);
|
||||
template void connectBodyPartsCpu(Array<double>& pose, const double* const heatMapPtr, const double* const peaksPtr, const PoseModel poseModel, const cv::Size& heatMapSize,
|
||||
template void connectBodyPartsCpu(Array<double>& poseKeyPoints, const double* const heatMapPtr, const double* const peaksPtr, const PoseModel poseModel, const cv::Size& heatMapSize,
|
||||
const int maxPeaks, const int interMinAboveThreshold, const double interThreshold, const int minSubsetCnt,
|
||||
const double minSubsetScore, const double scaleFactor);
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
namespace op
|
||||
{
|
||||
template <typename T>
|
||||
void connectBodyPartsGpu(Array<T>& pose, T* posePtr, const T* const heatMapPtr, const T* const peaksPtr, const PoseModel poseModel, const cv::Size& heatMapSize,
|
||||
void connectBodyPartsGpu(Array<T>& poseKeyPoints, T* posePtr, const T* const heatMapPtr, const T* const peaksPtr, const PoseModel poseModel, const cv::Size& heatMapSize,
|
||||
const int maxPeaks, const int interMinAboveThreshold, const T interThreshold, const int minSubsetCnt, const T minSubsetScore, const T scaleFactor)
|
||||
{
|
||||
try
|
||||
{
|
||||
UNUSED(pose);
|
||||
UNUSED(poseKeyPoints);
|
||||
UNUSED(posePtr);
|
||||
UNUSED(heatMapPtr);
|
||||
UNUSED(peaksPtr);
|
||||
@@ -31,10 +31,10 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
template void connectBodyPartsGpu(Array<float>& pose, float* posePtr, const float* const heatMapPtr, const float* const peaksPtr, const PoseModel poseModel,
|
||||
template void connectBodyPartsGpu(Array<float>& poseKeyPoints, float* posePtr, const float* const heatMapPtr, const float* const peaksPtr, const PoseModel poseModel,
|
||||
const cv::Size& heatMapSize, const int maxPeaks, const int interMinAboveThreshold, const float interThreshold, const int minSubsetCnt,
|
||||
const float minSubsetScore, const float scaleFactor);
|
||||
template void connectBodyPartsGpu(Array<double>& pose, double* posePtr, const double* const heatMapPtr, const double* const peaksPtr, const PoseModel poseModel,
|
||||
template void connectBodyPartsGpu(Array<double>& poseKeyPoints, double* posePtr, const double* const heatMapPtr, const double* const peaksPtr, const PoseModel poseModel,
|
||||
const cv::Size& heatMapSize, const int maxPeaks, const int interMinAboveThreshold, const double interThreshold, const int minSubsetCnt,
|
||||
const double minSubsetScore, const double scaleFactor);
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ namespace op
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BodyPartConnectorCaffe<T>::Forward_cpu(const std::vector<caffe::Blob<T>*>& bottom, Array<T>& pose)
|
||||
void BodyPartConnectorCaffe<T>::Forward_cpu(const std::vector<caffe::Blob<T>*>& bottom, Array<T>& poseKeyPoints)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -139,7 +139,7 @@ namespace op
|
||||
const auto* const heatMapsPtr = heatMapsBlob->cpu_data(); // ~8.5ms / 114
|
||||
const auto* const peaksPtr = bottom.at(1)->cpu_data(); // ~0.02ms
|
||||
const auto maxPeaks = mTopSize[1];
|
||||
connectBodyPartsCpu(pose, heatMapsPtr, peaksPtr, mPoseModel, cv::Size{heatMapsBlob->shape(3), heatMapsBlob->shape(2)}, maxPeaks,
|
||||
connectBodyPartsCpu(poseKeyPoints, heatMapsPtr, peaksPtr, mPoseModel, cv::Size{heatMapsBlob->shape(3), heatMapsBlob->shape(2)}, maxPeaks,
|
||||
mInterMinAboveThreshold, mInterThreshold, mMinSubsetCnt, mMinSubsetScore, mScaleNetToOutput);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
@@ -149,7 +149,7 @@ namespace op
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BodyPartConnectorCaffe<T>::Forward_gpu(const std::vector<caffe::Blob<T>*>& bottom, const std::vector<caffe::Blob<T>*>& top, Array<T>& pose)
|
||||
void BodyPartConnectorCaffe<T>::Forward_gpu(const std::vector<caffe::Blob<T>*>& bottom, const std::vector<caffe::Blob<T>*>& top, Array<T>& poseKeyPoints)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -157,7 +157,7 @@ namespace op
|
||||
const auto* const heatMapsPtr = heatMapsBlob->gpu_data();
|
||||
const auto* const peaksPtr = bottom.at(1)->gpu_data();
|
||||
const auto maxPeaks = mTopSize[1];
|
||||
connectBodyPartsGpu(pose, top.at(0)->mutable_gpu_data(), heatMapsPtr, peaksPtr, mPoseModel, cv::Size{heatMapsBlob->shape(3), heatMapsBlob->shape(2)}, maxPeaks,
|
||||
connectBodyPartsGpu(poseKeyPoints, top.at(0)->mutable_gpu_data(), heatMapsPtr, peaksPtr, mPoseModel, cv::Size{heatMapsBlob->shape(3), heatMapsBlob->shape(2)}, maxPeaks,
|
||||
mInterMinAboveThreshold, mInterThreshold, mMinSubsetCnt, mMinSubsetScore, mScaleNetToOutput);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
|
||||
@@ -163,12 +163,12 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
Array<float> PoseExtractor::getPose() const
|
||||
Array<float> PoseExtractor::getPoseKeyPoints() const
|
||||
{
|
||||
try
|
||||
{
|
||||
checkThread();
|
||||
return mPose;
|
||||
return mPoseKeyPoints;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
||||
@@ -107,8 +107,8 @@ namespace op
|
||||
spBodyPartConnectorCaffe->setMinSubsetScore((float)get(PoseProperty::ConnectMinSubsetScore));
|
||||
|
||||
// GPU version not implemented yet
|
||||
spBodyPartConnectorCaffe->Forward_cpu({spHeatMapsBlob.get(), spPeaksBlob.get()}, mPose);
|
||||
// spBodyPartConnectorCaffe->Forward_gpu({spHeatMapsBlob.get(), spPeaksBlob.get()}, {spPoseBlob.get()}, mPose);
|
||||
spBodyPartConnectorCaffe->Forward_cpu({spHeatMapsBlob.get(), spPeaksBlob.get()}, mPoseKeyPoints);
|
||||
// spBodyPartConnectorCaffe->Forward_gpu({spHeatMapsBlob.get(), spPeaksBlob.get()}, {spPoseBlob.get()}, mPoseKeyPoints);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
#include "openpose/utilities/errorAndLog.hpp"
|
||||
#include "openpose/pose/poseParameters.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
unsigned char poseBodyPartMapStringToKey(const PoseModel poseModel, const std::vector<std::string>& strings)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto& poseBodyPartMapping = POSE_BODY_PART_MAPPING[(int)poseModel];
|
||||
for (auto& string : strings)
|
||||
for (auto& pair : poseBodyPartMapping)
|
||||
if (pair.second == string)
|
||||
return pair.first;
|
||||
error("String(s) could not be found.", __LINE__, __FUNCTION__, __FILE__);
|
||||
return 0;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char poseBodyPartMapStringToKey(const PoseModel poseModel, const std::string& string)
|
||||
{
|
||||
try
|
||||
{
|
||||
return poseBodyPartMapStringToKey(poseModel, std::vector<std::string>{string});
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "openpose/utilities/errorAndLog.hpp"
|
||||
#include "openpose/utilities/cuda.hpp"
|
||||
#include "openpose/utilities/cuda.hu"
|
||||
#include "openpose/utilities/render.hu"
|
||||
#include "openpose/pose/poseRenderGpu.hpp"
|
||||
|
||||
namespace op
|
||||
@@ -141,162 +142,29 @@ namespace op
|
||||
colorPtr.z *= rad;
|
||||
}
|
||||
|
||||
__global__ void renderPoseCoco(float* targetPtr, const int targetWidth, const int targetHeight, const float* const posePtr,
|
||||
const int numberPeople, const float threshold, const bool googlyEyes, const float blendOriginalFrame, const float alphaColorToAdd)
|
||||
__global__ void renderPoseCoco(float* targetPtr, const int targetWidth, const int targetHeight, const float* const posePtr, const int numberPeople,
|
||||
const float threshold, const bool googlyEyes, const float blendOriginalFrame, const float alphaColorToAdd)
|
||||
{
|
||||
//posePtr has length 3 * 18 * numberPeople
|
||||
const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;
|
||||
const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;
|
||||
const auto globalIdx = threadIdx.y * blockDim.x + threadIdx.x;
|
||||
|
||||
__shared__ float sharedPoses[POSE_COCO_NUMBER_PARTS*3*POSE_MAX_PEOPLE];
|
||||
// Shared parameters
|
||||
__shared__ float2 sharedMins[POSE_MAX_PEOPLE];
|
||||
__shared__ float2 sharedMaxs[POSE_MAX_PEOPLE];
|
||||
__shared__ float sharedScaleF[POSE_MAX_PEOPLE];
|
||||
if (globalIdx < numberPeople)
|
||||
{
|
||||
sharedMins[globalIdx].x = targetWidth;
|
||||
sharedMins[globalIdx].y = targetHeight;
|
||||
sharedMaxs[globalIdx].x = 0.f;
|
||||
sharedMaxs[globalIdx].y = 0.f;
|
||||
for (auto part = 0 ; part < POSE_COCO_NUMBER_PARTS ; part++)
|
||||
{
|
||||
const auto index = 3 * (globalIdx*POSE_COCO_NUMBER_PARTS + part);
|
||||
const auto x = posePtr[index];
|
||||
const auto y = posePtr[index+1];
|
||||
const auto score = posePtr[index+2];
|
||||
sharedPoses[index] = x;
|
||||
sharedPoses[index+1] = y;
|
||||
sharedPoses[index+2] = score;
|
||||
if (score > threshold)
|
||||
{
|
||||
if (x < sharedMins[globalIdx].x)
|
||||
sharedMins[globalIdx].x = x;
|
||||
if (x > sharedMaxs[globalIdx].x)
|
||||
sharedMaxs[globalIdx].x = x;
|
||||
if (y < sharedMins[globalIdx].y)
|
||||
sharedMins[globalIdx].y = y;
|
||||
if (y > sharedMaxs[globalIdx].y)
|
||||
sharedMaxs[globalIdx].y = y;
|
||||
}
|
||||
}
|
||||
const auto averageX = sharedMaxs[globalIdx].x-sharedMins[globalIdx].x;
|
||||
const auto averageY = sharedMaxs[globalIdx].y-sharedMins[globalIdx].y;
|
||||
sharedScaleF[globalIdx] = fastTruncate((averageX + averageY) / 400.f, 0.33f, 1.f); // (averageX + averageY) / 2.f / 400.f
|
||||
const auto constantToAdd = 50.f;
|
||||
sharedMaxs[globalIdx].x += constantToAdd;
|
||||
sharedMaxs[globalIdx].y += constantToAdd;
|
||||
sharedMins[globalIdx].x -= constantToAdd;
|
||||
sharedMins[globalIdx].y -= constantToAdd;
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
// Other parameters
|
||||
const auto numberPartPairs = sizeof(COCO_PAIRS_GPU) / (2*sizeof(COCO_PAIRS_GPU[0]));
|
||||
const auto numberColors = sizeof(COCO_RGB_COLORS) / (3*sizeof(COCO_RGB_COLORS[0]));
|
||||
const auto radius = fastMin(targetWidth, targetHeight) / 100.f;
|
||||
const auto stickwidth = fastMin(targetWidth, targetHeight) / 120.f;
|
||||
|
||||
const auto numberBodyParts = sizeof(COCO_PAIRS_GPU)/(2*sizeof(COCO_PAIRS_GPU[0]));
|
||||
const auto numberColors = sizeof(COCO_RGB_COLORS)/(3*sizeof(COCO_RGB_COLORS[0]));
|
||||
const auto radius = targetHeight / 100.f;
|
||||
const auto stickwidth = targetHeight / 120.f;
|
||||
|
||||
if (x < targetWidth && y < targetHeight)
|
||||
{
|
||||
const auto baseIndex = y * targetWidth + x;
|
||||
auto& b = targetPtr[ baseIndex];
|
||||
auto& g = targetPtr[ targetWidth * targetHeight + baseIndex];
|
||||
auto& r = targetPtr[2 * targetWidth * targetHeight + baseIndex];
|
||||
if (!blendOriginalFrame)
|
||||
{
|
||||
b = 0.f;
|
||||
g = 0.f;
|
||||
r = 0.f;
|
||||
}
|
||||
|
||||
for (auto person = 0; person < numberPeople; person++)
|
||||
{
|
||||
if (x <= sharedMaxs[person].x && x >= sharedMins[person].x && y <= sharedMaxs[person].y && y >= sharedMins[person].y)
|
||||
{
|
||||
// Body part connections
|
||||
for (auto bodyPart = 0; bodyPart < numberBodyParts; bodyPart++)
|
||||
{
|
||||
const auto bSqrt = sharedScaleF[person] * sharedScaleF[person] * stickwidth * stickwidth;
|
||||
const auto partA = COCO_PAIRS_GPU[2*bodyPart];
|
||||
const auto partB = COCO_PAIRS_GPU[2*bodyPart+1];
|
||||
const auto indexA = person*POSE_COCO_NUMBER_PARTS*3 + partA*3;
|
||||
const auto xA = sharedPoses[indexA];
|
||||
const auto yA = sharedPoses[indexA + 1];
|
||||
const auto valueA = sharedPoses[indexA + 2];
|
||||
const auto indexB = person*POSE_COCO_NUMBER_PARTS*3 + partB*3;
|
||||
const auto xB = sharedPoses[indexB];
|
||||
const auto yB = sharedPoses[indexB + 1];
|
||||
const auto valueB = sharedPoses[indexB + 2];
|
||||
|
||||
if (valueA > threshold && valueB > threshold)
|
||||
{
|
||||
const auto xP = (xA + xB) / 2.f;
|
||||
const auto yP = (yA + yB) / 2.f;
|
||||
const auto aSqrt = (xA - xP) * (xA - xP) + (yA - yP) * (yA - yP);
|
||||
|
||||
const auto angle = atan2f(yB - yA, xB - xA);
|
||||
const auto sine = sinf(angle);
|
||||
const auto cosine = cosf(angle);
|
||||
const auto A = cosine * (x - xP) + sine * (y - yP);
|
||||
const auto B = sine * (x - xP) - cosine * (y - yP);
|
||||
|
||||
const auto judge = A * A / aSqrt + B * B / bSqrt;
|
||||
const auto minV = 0.f;
|
||||
const auto maxV = 1.f;
|
||||
if (minV <= judge && judge <= maxV)
|
||||
{
|
||||
const auto index = (bodyPart%numberColors)*3;
|
||||
addColorWeighted(r, g, b, &COCO_RGB_COLORS[index], alphaColorToAdd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Body part circles
|
||||
for (unsigned char i = 0; i < POSE_COCO_NUMBER_PARTS; i++)
|
||||
{
|
||||
const auto index = 3 * (person*POSE_COCO_NUMBER_PARTS + i);
|
||||
const auto localX = sharedPoses[index];
|
||||
const auto localY = sharedPoses[index + 1];
|
||||
const auto value = sharedPoses[index + 2];
|
||||
|
||||
if (value > threshold)
|
||||
{
|
||||
const auto dist2 = (x - localX) * (x - localX) + (y - localY) * (y - localY);
|
||||
|
||||
if (googlyEyes && (i==14 || i==15))
|
||||
{
|
||||
const auto minr2 = sharedScaleF[person]*sharedScaleF[person]*(2.5*radius-2)*(2.5*radius-2);
|
||||
const auto maxr2 = sharedScaleF[person]*sharedScaleF[person]*2.5*2.5*radius*radius;
|
||||
if (dist2 <= maxr2)
|
||||
{
|
||||
float colorToAdd [3] = {0., 0., 0.};
|
||||
if (dist2 <= minr2)
|
||||
for (auto& color : colorToAdd)
|
||||
color = {255.f};
|
||||
if (dist2 <= minr2*0.6)
|
||||
{
|
||||
const auto dist3 = (x-4 - localX) * (x-4 - localX) + (y - localY+4) * (y - localY+4);
|
||||
if (dist3 > 3.75f*3.75f)
|
||||
for (auto& color : colorToAdd)
|
||||
color = {0.f};
|
||||
}
|
||||
const auto alphaColorToAdd = 0.9f;
|
||||
addColorWeighted(r, g, b, colorToAdd, alphaColorToAdd);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto minr2 = 0.f;
|
||||
const auto maxr2 = sharedScaleF[person]*sharedScaleF[person]*radius * radius;
|
||||
if (minr2 <= dist2 && dist2 <= maxr2)
|
||||
addColorWeighted(r, g, b, &COCO_RGB_COLORS[(i%numberColors)*3], alphaColorToAdd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Render key points
|
||||
renderKeyPoints(targetPtr, sharedMaxs, sharedMins, sharedScaleF,
|
||||
globalIdx, x, y, targetWidth, targetHeight, posePtr, COCO_PAIRS_GPU, numberPeople,
|
||||
POSE_COCO_NUMBER_PARTS, numberPartPairs, COCO_RGB_COLORS, numberColors,
|
||||
radius, stickwidth, threshold, alphaColorToAdd);
|
||||
}
|
||||
|
||||
__global__ void renderPoseMpi29Parts(float* targetPtr, const int targetWidth, const int targetHeight, const float* const posePtr,
|
||||
@@ -305,25 +173,13 @@ namespace op
|
||||
//posePtr has length 3 * 15 * numberPeople
|
||||
const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;
|
||||
const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;
|
||||
const auto globalIdx = threadIdx.y * blockDim.x + threadIdx.x;
|
||||
|
||||
__shared__ float sharedPoses[POSE_MPI_NUMBER_PARTS*3*POSE_MAX_PEOPLE];
|
||||
if (globalIdx < numberPeople * POSE_MPI_NUMBER_PARTS)
|
||||
{
|
||||
const auto index = 3*globalIdx;
|
||||
sharedPoses[index] = posePtr[index];
|
||||
sharedPoses[index+1] = posePtr[index+1];
|
||||
sharedPoses[index+2] = posePtr[index+2];
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
const auto numberBodyParts = sizeof(MPI_PAIRS_GPU)/(2*sizeof(MPI_PAIRS_GPU[0]));
|
||||
const auto radius = 3.f*targetHeight / 200.0f;
|
||||
const auto stickwidth = targetHeight / 60.0f;
|
||||
|
||||
if (x < targetWidth && y < targetHeight)
|
||||
{
|
||||
const auto numberBodyParts = sizeof(MPI_PAIRS_GPU)/(2*sizeof(MPI_PAIRS_GPU[0]));
|
||||
const auto radius = 3.f*targetHeight / 200.0f;
|
||||
const auto stickwidth = targetHeight / 60.0f;
|
||||
|
||||
const auto blueIndex = y * targetWidth + x;
|
||||
auto& b = targetPtr[ blueIndex];
|
||||
auto& g = targetPtr[ targetWidth * targetHeight + blueIndex];
|
||||
@@ -343,12 +199,12 @@ namespace op
|
||||
auto bSqrt = stickwidth * stickwidth; //fixed
|
||||
const auto partA = MPI_PAIRS_GPU[2*bodyPart];
|
||||
const auto partB = MPI_PAIRS_GPU[2*bodyPart+1];
|
||||
const auto xA = sharedPoses[person*POSE_MPI_NUMBER_PARTS*3 + partA*3];
|
||||
const auto yA = sharedPoses[person*POSE_MPI_NUMBER_PARTS*3 + partA*3 + 1];
|
||||
const auto valueA = sharedPoses[person*POSE_MPI_NUMBER_PARTS*3 + partA*3 + 2];
|
||||
const auto xB = sharedPoses[person*POSE_MPI_NUMBER_PARTS*3 + partB*3];
|
||||
const auto yB = sharedPoses[person*POSE_MPI_NUMBER_PARTS*3 + partB*3 + 1];
|
||||
const auto valueB = sharedPoses[person*POSE_MPI_NUMBER_PARTS*3 + partB*3 + 2];
|
||||
const auto xA = posePtr[person*POSE_MPI_NUMBER_PARTS*3 + partA*3];
|
||||
const auto yA = posePtr[person*POSE_MPI_NUMBER_PARTS*3 + partA*3 + 1];
|
||||
const auto valueA = posePtr[person*POSE_MPI_NUMBER_PARTS*3 + partA*3 + 2];
|
||||
const auto xB = posePtr[person*POSE_MPI_NUMBER_PARTS*3 + partB*3];
|
||||
const auto yB = posePtr[person*POSE_MPI_NUMBER_PARTS*3 + partB*3 + 1];
|
||||
const auto valueB = posePtr[person*POSE_MPI_NUMBER_PARTS*3 + partB*3 + 2];
|
||||
if (valueA > threshold && valueB > threshold)
|
||||
{
|
||||
const auto xP = (xA + xB) / 2.f;
|
||||
@@ -379,9 +235,9 @@ namespace op
|
||||
for (unsigned char i = 0; i < POSE_MPI_NUMBER_PARTS; i++) //for every point
|
||||
{
|
||||
const auto index = 3 * (person*POSE_MPI_NUMBER_PARTS + i);
|
||||
const auto localX = sharedPoses[index];
|
||||
const auto localY = sharedPoses[index + 1];
|
||||
const auto value = sharedPoses[index + 2];
|
||||
const auto localX = posePtr[index];
|
||||
const auto localY = posePtr[index + 1];
|
||||
const auto value = posePtr[index + 2];
|
||||
|
||||
if (value > threshold)
|
||||
if ((x - localX) * (x - localX) + (y - localY) * (y - localY) <= radius * radius)
|
||||
@@ -548,7 +404,7 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
inline void gpuRenderPartAffinityAux(float* framePtr, const PoseModel poseModel, const cv::Size& frameSize, const float* const heatMapPtr,
|
||||
inline void renderKeyPointsPartAffinityAux(float* framePtr, const PoseModel poseModel, const cv::Size& frameSize, const float* const heatMapPtr,
|
||||
const cv::Size& heatMapSize, const float scaleToKeepRatio, const int part, const int partsToRender, const float alphaBlending)
|
||||
{
|
||||
try
|
||||
@@ -656,7 +512,7 @@ namespace op
|
||||
{
|
||||
try
|
||||
{
|
||||
gpuRenderPartAffinityAux(framePtr, poseModel, frameSize, heatMapPtr, heatMapSize, scaleToKeepRatio, part, 1, alphaBlending);
|
||||
renderKeyPointsPartAffinityAux(framePtr, poseModel, frameSize, heatMapPtr, heatMapSize, scaleToKeepRatio, part, 1, alphaBlending);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -670,7 +526,7 @@ namespace op
|
||||
try
|
||||
{
|
||||
const auto numberBodyPartPairs = POSE_BODY_PART_PAIRS[(int)poseModel].size()/2;
|
||||
gpuRenderPartAffinityAux(framePtr, poseModel, frameSize, heatMapPtr, heatMapSize, scaleToKeepRatio, POSE_NUMBER_BODY_PARTS[(int)poseModel]+1,
|
||||
renderKeyPointsPartAffinityAux(framePtr, poseModel, frameSize, heatMapPtr, heatMapSize, scaleToKeepRatio, POSE_NUMBER_BODY_PARTS[(int)poseModel]+1,
|
||||
numberBodyPartPairs, alphaBlending);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
|
||||
@@ -211,7 +211,7 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<int, std::string> PoseRenderer::renderPose(Array<float>& outputData, const Array<float>& pose, const double scaleNetToOutput)
|
||||
std::pair<int, std::string> PoseRenderer::renderPose(Array<float>& outputData, const Array<float>& poseKeyPoints, const double scaleNetToOutput)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -221,7 +221,7 @@ namespace op
|
||||
|
||||
const auto elementRendered = mElementToRender.load(); // I prefer std::round(T&) over intRound(T) for std::atomic
|
||||
std::string elementRenderedName;
|
||||
const auto numberPeople = pose.getSize(0);
|
||||
const auto numberPeople = poseKeyPoints.getSize(0);
|
||||
|
||||
// GPU rendering
|
||||
if (numberPeople > 0 || elementRendered != 0 || !mBlendOriginalFrame)
|
||||
@@ -230,11 +230,11 @@ namespace op
|
||||
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
|
||||
const auto numberBodyParts = POSE_NUMBER_BODY_PARTS[(int)mPoseModel];
|
||||
const auto numberBodyPartsPlusBkg = numberBodyParts+1;
|
||||
// Draw pose
|
||||
// Draw poseKeyPoints
|
||||
if (elementRendered == 0)
|
||||
{
|
||||
if (!pose.empty())
|
||||
cudaMemcpy(pGpuPose, pose.getConstPtr(), numberPeople * numberBodyParts * 3 * sizeof(float), cudaMemcpyHostToDevice);
|
||||
if (!poseKeyPoints.empty())
|
||||
cudaMemcpy(pGpuPose, poseKeyPoints.getConstPtr(), numberPeople * numberBodyParts * 3 * sizeof(float), cudaMemcpyHostToDevice);
|
||||
renderPoseGpu(*spGpuMemoryPtr, mPoseModel, numberPeople, mOutputSize, pGpuPose, mShowGooglyEyes, mBlendOriginalFrame, mAlphaPose);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "openpose/wrapper/wrapperStructFace.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
WrapperStructFace::WrapperStructFace(const bool extractAndRenderFace_) :
|
||||
extractAndRenderFace{extractAndRenderFace_}
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
#include "openpose/wrapper/wrapperStructHands.hpp"
|
||||
#include "openpose/wrapper/wrapperStructHand.hpp"
|
||||
|
||||
namespace op
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
WrapperStructHands::WrapperStructHands(const bool extractAndRenderHands_) :
|
||||
WrapperStructHand::WrapperStructHand(const bool extractAndRenderHands_) :
|
||||
extractAndRenderHands{extractAndRenderHands_}
|
||||
{
|
||||
}
|
||||
Reference in New Issue
Block a user