提交 1ed09805 编写于 作者: G gineshidalgo99

CPU render: improved small face/hand render

上级 72a1f5f6
### Posting rules ### Posting rules
1. **No duplicated** posts. 1. **No duplicated** posts.
2. **No** posts about **questions already answered in** the **documentation** (e.g. **no more low-speed nor out-of-memory questions**). 2. **No** posts about **questions already answered / clearly explained in** the **documentation** (e.g. **no more low-speed nor out-of-memory questions**).
3. **Add** the **system configuration (all of it!), command and output** if you have some kind of error or performance question. 3. **Add** the **system configuration (all of it!), command and output** if you have some kind of error or performance question.
4. Set a **proper issue title**: add the Ubuntu/Windows word and be specific (e.g. do not simple call it: `Compile error`). 4. Set a **proper issue title**: add the Ubuntu/Windows word and be specific (e.g. do not simple call it: `Compile error`).
5. Only English comments. 5. Only English comments.
......
...@@ -164,6 +164,8 @@ op::PoseModel gflagToPoseModel(const std::string& poseModeString) ...@@ -164,6 +164,8 @@ op::PoseModel gflagToPoseModel(const std::string& poseModeString)
return op::PoseModel::MPI_15; return op::PoseModel::MPI_15;
else if (poseModeString == "MPI_4_layers") else if (poseModeString == "MPI_4_layers")
return op::PoseModel::MPI_15_4; return op::PoseModel::MPI_15_4;
else if (poseModeString == "BODY_22")
return op::PoseModel::BODY_22;
else else
{ {
op::error("String does not correspond to any model (COCO, MPI, MPI_4_layers)", __LINE__, __FUNCTION__, __FILE__); op::error("String does not correspond to any model (COCO, MPI, MPI_4_layers)", __LINE__, __FUNCTION__, __FILE__);
......
...@@ -9,8 +9,9 @@ namespace op ...@@ -9,8 +9,9 @@ namespace op
enum class PoseModel : unsigned char enum class PoseModel : unsigned char
{ {
COCO_18 = 0, /**< COCO model, with 18+1 components (see poseParameters.hpp for details). */ COCO_18 = 0, /**< COCO model, with 18+1 components (see poseParameters.hpp for details). */
MPI_15, /**< MPI model, with 15+1 components (see poseParameters.hpp for details). */ MPI_15 = 1, /**< MPI model, with 15+1 components (see poseParameters.hpp for details). */
MPI_15_4, /**< Same MPI model, but reducing the number of CNN stages to 4 (see poseModel.cpp for details). It should increase speed and reduce accuracy.*/ MPI_15_4 = 2, /**< Variation of the MPI model, reduced number of CNN stages to 4: faster but less accurate.*/
BODY_22 = 3, /**< Experimental. Do not use. */
Size, Size,
}; };
......
...@@ -8,8 +8,13 @@ ...@@ -8,8 +8,13 @@
namespace op namespace op
{ {
// Model-Dependent Parameters
// #define when needed in CUDA code // #define when needed in CUDA code
// Constant Global Parameters
const unsigned int POSE_MAX_PEOPLE = 96u;
// Model-Dependent Parameters
// COCO
const std::map<unsigned int, std::string> POSE_COCO_BODY_PARTS { const std::map<unsigned int, std::string> POSE_COCO_BODY_PARTS {
{0, "Nose"}, {0, "Nose"},
{1, "Neck"}, {1, "Neck"},
...@@ -33,9 +38,9 @@ namespace op ...@@ -33,9 +38,9 @@ namespace op
}; };
const unsigned int POSE_COCO_NUMBER_PARTS = 18u; // Equivalent to size of std::map POSE_COCO_BODY_PARTS - 1 (removing background) const unsigned int POSE_COCO_NUMBER_PARTS = 18u; // Equivalent to size of std::map POSE_COCO_BODY_PARTS - 1 (removing background)
const std::vector<unsigned int> POSE_COCO_MAP_IDX {31,32, 39,40, 33,34, 35,36, 41,42, 43,44, 19,20, 21,22, 23,24, 25,26, 27,28, 29,30, 47,48, 49,50, 53,54, 51,52, 55,56, 37,38, 45,46}; const std::vector<unsigned int> POSE_COCO_MAP_IDX {31,32, 39,40, 33,34, 35,36, 41,42, 43,44, 19,20, 21,22, 23,24, 25,26, 27,28, 29,30, 47,48, 49,50, 53,54, 51,52, 55,56, 37,38, 45,46};
#define POSE_COCO_PAIRS_RENDER_GPU {1,2, 1,5, 2,3, 3,4, 5,6, 6,7, 1,8, 8,9, 9,10, 1,11, 11,12, 12,13, 1,0, 0,14, 14,16, 0,15, 15,17} #define POSE_COCO_PAIRS_RENDER_GPU {1,2, 1,5, 2,3, 3,4, 5,6, 6,7, 1,8, 8,9, 9,10, 1,11, 11,12, 12,13, 1,0, 0,14, 14,16, 0,15, 15,17}
const std::vector<unsigned int> POSE_COCO_PAIRS_RENDER {POSE_COCO_PAIRS_RENDER_GPU}; const std::vector<unsigned int> POSE_COCO_PAIRS_RENDER {POSE_COCO_PAIRS_RENDER_GPU};
const std::vector<unsigned int> POSE_COCO_PAIRS {1,2, 1,5, 2,3, 3,4, 5,6, 6,7, 1,8, 8,9, 9,10, 1,11, 11,12, 12,13, 1,0, 0,14, 14,16, 0,15, 15,17, 2,16, 5,17}; const std::vector<unsigned int> POSE_COCO_PAIRS {1,2, 1,5, 2,3, 3,4, 5,6, 6,7, 1,8, 8,9, 9,10, 1,11, 11,12, 12,13, 1,0, 0,14, 14,16, 0,15, 15,17, 2,16, 5,17};
#define POSE_COCO_COLORS_RENDER \ #define POSE_COCO_COLORS_RENDER \
255.f, 0.f, 0.f, \ 255.f, 0.f, 0.f, \
255.f, 85.f, 0.f, \ 255.f, 85.f, 0.f, \
...@@ -55,7 +60,7 @@ namespace op ...@@ -55,7 +60,7 @@ namespace op
255.f, 0.f, 255.f, \ 255.f, 0.f, 255.f, \
255.f, 0.f, 170.f, \ 255.f, 0.f, 170.f, \
255.f, 0.f, 85.f 255.f, 0.f, 85.f
// MPI
const std::map<unsigned int, std::string> POSE_MPI_BODY_PARTS{ const std::map<unsigned int, std::string> POSE_MPI_BODY_PARTS{
{0, "Head"}, {0, "Head"},
{1, "Neck"}, {1, "Neck"},
...@@ -75,8 +80,8 @@ namespace op ...@@ -75,8 +80,8 @@ namespace op
{15, "Background"} {15, "Background"}
}; };
const unsigned int POSE_MPI_NUMBER_PARTS = 15; // Equivalent to size of std::map POSE_MPI_NUMBER_PARTS - 1 (removing background) const unsigned int POSE_MPI_NUMBER_PARTS = 15; // Equivalent to size of std::map POSE_MPI_NUMBER_PARTS - 1 (removing background)
const std::vector<unsigned int> POSE_MPI_MAP_IDX {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43}; const std::vector<unsigned int> POSE_MPI_MAP_IDX {16,17, 18,19, 20,21, 22,23, 24,25, 26,27, 28,29, 30,31, 32,33, 34,35, 36,37, 38,39, 40,41, 42,43};
#define POSE_MPI_PAIRS_RENDER_GPU { 0,1, 1,2, 2,3, 3,4, 1,5, 5,6, 6,7, 1,14, 14,8, 8,9, 9,10, 14,11, 11,12, 12,13} #define POSE_MPI_PAIRS_RENDER_GPU { 0,1, 1,2, 2,3, 3,4, 1,5, 5,6, 6,7, 1,14, 14,8, 8,9, 9,10, 14,11, 11,12, 12,13}
const std::vector<unsigned int> POSE_MPI_PAIRS POSE_MPI_PAIRS_RENDER_GPU; const std::vector<unsigned int> POSE_MPI_PAIRS POSE_MPI_PAIRS_RENDER_GPU;
// MPI colors chosen such that they are closed to COCO colors // MPI colors chosen such that they are closed to COCO colors
#define POSE_MPI_COLORS_RENDER \ #define POSE_MPI_COLORS_RENDER \
...@@ -95,35 +100,108 @@ namespace op ...@@ -95,35 +100,108 @@ namespace op
0.f, 170.f, 255.f, \ 0.f, 170.f, 255.f, \
0.f, 85.f, 255.f, \ 0.f, 85.f, 255.f, \
0.f, 0.f, 255.f 0.f, 0.f, 255.f
// BODY_22 (experimental, do not use)
// Constant Global Parameters const std::map<unsigned int, std::string> POSE_BODY_22_BODY_PARTS {
const unsigned int POSE_MAX_PEOPLE = 96u; {0, "Nose"},
{1, "Neck"},
{2, "RShoulder"},
{3, "RElbow"},
{4, "RWrist"},
{5, "LShoulder"},
{6, "LElbow"},
{7, "LWrist"},
{8, "RHip"},
{9, "RKnee"},
{10, "RAnkle"},
{11, "LHip"},
{12, "LKnee"},
{13, "LAnkle"},
{14, "REye"},
{15, "LEye"},
{16, "REar"},
{17, "LEar"},
{22, "Background"},
};
const unsigned int POSE_BODY_22_NUMBER_PARTS = 2u; // Equivalent to size of std::map POSE_BODY_22_BODY_PARTS - 1 (removing background)
const std::vector<unsigned int> POSE_BODY_22_MAP_IDX {35,36, 43,45};
#define POSE_BODY_22_PAIRS_RENDER_GPU {1,2, 1,5}
const std::vector<unsigned int> POSE_BODY_22_PAIRS_RENDER {POSE_BODY_22_PAIRS_RENDER_GPU};
const std::vector<unsigned int> POSE_BODY_22_PAIRS {1,2};
#define POSE_BODY_22_COLORS_RENDER \
255.f, 0.f, 0.f, \
255.f, 85.f, 0.f, \
255.f, 170.f, 0.f, \
255.f, 255.f, 0.f, \
170.f, 255.f, 0.f, \
85.f, 255.f, 0.f, \
0.f, 255.f, 0.f, \
0.f, 255.f, 85.f, \
0.f, 255.f, 170.f, \
0.f, 255.f, 255.f, \
0.f, 170.f, 255.f, \
0.f, 85.f, 255.f, \
0.f, 0.f, 255.f, \
85.f, 0.f, 255.f, \
170.f, 0.f, 255.f, \
255.f, 0.f, 255.f, \
255.f, 0.f, 170.f, \
255.f, 0.f, 85.f
// Constant Array Parameters // Constant Array Parameters
const std::array<float, (int)PoseModel::Size> POSE_CCN_DECREASE_FACTOR{ 8.f, 8.f, 8.f}; const std::array<float, (int)PoseModel::Size> POSE_CCN_DECREASE_FACTOR{
const std::array<unsigned int, (int)PoseModel::Size> POSE_MAX_PEAKS{ POSE_MAX_PEOPLE, POSE_MAX_PEOPLE, POSE_MAX_PEOPLE}; 8.f, 8.f, 8.f, 8.f
const std::array<unsigned int, (int)PoseModel::Size> POSE_NUMBER_BODY_PARTS{ POSE_COCO_NUMBER_PARTS, POSE_MPI_NUMBER_PARTS, POSE_MPI_NUMBER_PARTS}; };
const std::array<std::vector<unsigned int>, 3> POSE_BODY_PART_PAIRS{ POSE_COCO_PAIRS, POSE_MPI_PAIRS, POSE_MPI_PAIRS}; const std::array<unsigned int, (int)PoseModel::Size> POSE_MAX_PEAKS{
const std::array<std::vector<unsigned int>, 3> POSE_BODY_PART_PAIRS_RENDER{POSE_COCO_PAIRS_RENDER, POSE_MPI_PAIRS, POSE_MPI_PAIRS}; POSE_MAX_PEOPLE, POSE_MAX_PEOPLE, POSE_MAX_PEOPLE, POSE_MAX_PEOPLE
const std::array<std::vector<unsigned int>, 3> POSE_MAP_IDX{ POSE_COCO_MAP_IDX, POSE_MPI_MAP_IDX, POSE_MPI_MAP_IDX}; };
const std::array<std::string, (int)PoseModel::Size> POSE_PROTOTXT{ "pose/coco/pose_deploy_linevec.prototxt", const std::array<unsigned int, (int)PoseModel::Size> POSE_NUMBER_BODY_PARTS{
"pose/mpi/pose_deploy_linevec.prototxt", POSE_COCO_NUMBER_PARTS, POSE_MPI_NUMBER_PARTS, POSE_MPI_NUMBER_PARTS, POSE_BODY_22_NUMBER_PARTS
"pose/mpi/pose_deploy_linevec_faster_4_stages.prototxt"}; };
const std::array<std::string, (int)PoseModel::Size> POSE_TRAINED_MODEL{ "pose/coco/pose_iter_440000.caffemodel", const std::array<std::vector<unsigned int>, (int)PoseModel::Size> POSE_BODY_PART_PAIRS{
"pose/mpi/pose_iter_160000.caffemodel", POSE_COCO_PAIRS, POSE_MPI_PAIRS, POSE_MPI_PAIRS, POSE_BODY_22_PAIRS
"pose/mpi/pose_iter_160000.caffemodel"}; };
const std::array<std::vector<unsigned int>, (int)PoseModel::Size> POSE_BODY_PART_PAIRS_RENDER{
POSE_COCO_PAIRS_RENDER, POSE_MPI_PAIRS, POSE_MPI_PAIRS, POSE_BODY_22_PAIRS_RENDER
};
const std::array<std::vector<unsigned int>, (int)PoseModel::Size> POSE_MAP_IDX{
POSE_COCO_MAP_IDX, POSE_MPI_MAP_IDX, POSE_MPI_MAP_IDX, POSE_BODY_22_MAP_IDX
};
const std::array<std::string, (int)PoseModel::Size> POSE_PROTOTXT{
"pose/coco/pose_deploy_linevec.prototxt",
"pose/mpi/pose_deploy_linevec.prototxt",
"pose/mpi/pose_deploy_linevec_faster_4_stages.prototxt",
"pose/body_22/pose_deploy.prototxt"
};
const std::array<std::string, (int)PoseModel::Size> POSE_TRAINED_MODEL{
"pose/coco/pose_iter_440000.caffemodel",
"pose/mpi/pose_iter_160000.caffemodel",
"pose/mpi/pose_iter_160000.caffemodel",
"pose/body_22/pose_iter_40000.caffemodel"
};
// POSE_BODY_PART_MAPPING crashes on Windows at dynamic initialization, to avoid this crash: // POSE_BODY_PART_MAPPING crashes on Windows at dynamic initialization, to avoid this crash:
// POSE_BODY_PART_MAPPING has been moved to poseParameters.cpp and getPoseBodyPartMapping() wraps it // POSE_BODY_PART_MAPPING has been moved to poseParameters.cpp and getPoseBodyPartMapping() wraps it
//const std::array<std::map<unsigned int, std::string>, 3> POSE_BODY_PART_MAPPING{ POSE_COCO_BODY_PARTS, POSE_MPI_BODY_PARTS, POSE_MPI_BODY_PARTS}; // const std::array<std::map<unsigned int, std::string>, (int)PoseModel::Size> POSE_BODY_PART_MAPPING{
// POSE_COCO_BODY_PARTS, POSE_MPI_BODY_PARTS, POSE_MPI_BODY_PARTS
// };
const std::map<unsigned int, std::string>& getPoseBodyPartMapping(const PoseModel poseModel); const std::map<unsigned int, std::string>& getPoseBodyPartMapping(const PoseModel poseModel);
// Default Model Parameters // Default Model Parameters
// They might be modified on running time // They might be modified on running time
const std::array<float, (int)PoseModel::Size> POSE_DEFAULT_NMS_THRESHOLD{ 0.05f, 0.6f, 0.3f}; const std::array<float, (int)PoseModel::Size> POSE_DEFAULT_NMS_THRESHOLD{
const std::array<unsigned int, (int)PoseModel::Size> POSE_DEFAULT_CONNECT_INTER_MIN_ABOVE_THRESHOLD{ 9, 8, 8}; 0.05f, 0.6f, 0.3f, 0.05f
const std::array<float, (int)PoseModel::Size> POSE_DEFAULT_CONNECT_INTER_THRESHOLD{ 0.05f, 0.01f, 0.01f}; };
const std::array<unsigned int, (int)PoseModel::Size> POSE_DEFAULT_CONNECT_MIN_SUBSET_CNT{ 3, 3, 3}; const std::array<unsigned int, (int)PoseModel::Size> POSE_DEFAULT_CONNECT_INTER_MIN_ABOVE_THRESHOLD{
const std::array<float, (int)PoseModel::Size> POSE_DEFAULT_CONNECT_MIN_SUBSET_SCORE{ 0.4f, 0.4f, 0.4f}; 9, 8, 8, 9
};
const std::array<float, (int)PoseModel::Size> POSE_DEFAULT_CONNECT_INTER_THRESHOLD{
0.05f, 0.01f, 0.01f, 0.05f
};
const std::array<unsigned int, (int)PoseModel::Size> POSE_DEFAULT_CONNECT_MIN_SUBSET_CNT{
3, 3, 3, 3
};
const std::array<float, (int)PoseModel::Size> POSE_DEFAULT_CONNECT_MIN_SUBSET_SCORE{
0.4f, 0.4f, 0.4f, 0.4f
};
// Rendering parameters // Rendering parameters
const auto POSE_DEFAULT_ALPHA_KEYPOINT = 0.6f; const auto POSE_DEFAULT_ALPHA_KEYPOINT = 0.6f;
......
...@@ -3,7 +3,9 @@ ...@@ -3,7 +3,9 @@
namespace op namespace op
{ {
const std::array<std::map<unsigned int, std::string>, 3> POSE_BODY_PART_MAPPING{ POSE_COCO_BODY_PARTS, POSE_MPI_BODY_PARTS, POSE_MPI_BODY_PARTS }; const std::array<std::map<unsigned int, std::string>, (int)PoseModel::Size> POSE_BODY_PART_MAPPING{
POSE_COCO_BODY_PARTS, POSE_MPI_BODY_PARTS, POSE_MPI_BODY_PARTS, POSE_BODY_22_BODY_PARTS
};
unsigned int poseBodyPartMapStringToKey(const PoseModel poseModel, const std::vector<std::string>& strings) unsigned int poseBodyPartMapStringToKey(const PoseModel poseModel, const std::vector<std::string>& strings)
{ {
......
...@@ -10,8 +10,10 @@ namespace op ...@@ -10,8 +10,10 @@ namespace op
// PI digits: http://www.piday.org/million/ // PI digits: http://www.piday.org/million/
__constant__ const float PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745f; __constant__ const float PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745f;
__constant__ const unsigned int COCO_PAIRS_GPU[] = POSE_COCO_PAIRS_RENDER_GPU; __constant__ const unsigned int COCO_PAIRS_GPU[] = POSE_COCO_PAIRS_RENDER_GPU;
__constant__ const unsigned int BODY_22_PAIRS_GPU[] = POSE_BODY_22_PAIRS_RENDER_GPU;
__constant__ const unsigned int MPI_PAIRS_GPU[] = POSE_MPI_PAIRS_RENDER_GPU; __constant__ const unsigned int MPI_PAIRS_GPU[] = POSE_MPI_PAIRS_RENDER_GPU;
__constant__ const float COCO_COLORS[] = {POSE_COCO_COLORS_RENDER}; __constant__ const float COCO_COLORS[] = {POSE_COCO_COLORS_RENDER};
__constant__ const float BODY_22_COLORS[] = {POSE_BODY_22_COLORS_RENDER};
__constant__ const float MPI_COLORS[] = {POSE_MPI_COLORS_RENDER}; __constant__ const float MPI_COLORS[] = {POSE_MPI_COLORS_RENDER};
...@@ -93,8 +95,9 @@ namespace op ...@@ -93,8 +95,9 @@ namespace op
colorPtr.z *= rad; colorPtr.z *= rad;
} }
__global__ void renderPoseCoco(float* targetPtr, const int targetWidth, const int targetHeight, const float* const posePtr, const int numberPeople, __global__ void renderPoseCoco(float* targetPtr, const int targetWidth, const int targetHeight, const float* const posePtr,
const float threshold, const bool googlyEyes, const bool blendOriginalFrame, const float alphaColorToAdd) const int numberPeople, const float threshold, const bool googlyEyes, const bool blendOriginalFrame,
const float alphaColorToAdd)
{ {
const auto x = (blockIdx.x * blockDim.x) + threadIdx.x; const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;
const auto y = (blockIdx.y * blockDim.y) + threadIdx.y; const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;
...@@ -118,6 +121,32 @@ namespace op ...@@ -118,6 +121,32 @@ namespace op
radius, stickwidth, threshold, alphaColorToAdd, blendOriginalFrame, (googlyEyes ? 14 : -1), (googlyEyes ? 15 : -1)); radius, stickwidth, threshold, alphaColorToAdd, blendOriginalFrame, (googlyEyes ? 14 : -1), (googlyEyes ? 15 : -1));
} }
__global__ void renderPoseBody22(float* targetPtr, const int targetWidth, const int targetHeight, const float* const posePtr,
const int numberPeople, const float threshold, const bool googlyEyes, const bool blendOriginalFrame,
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[POSE_MAX_PEOPLE];
__shared__ float2 sharedMaxs[POSE_MAX_PEOPLE];
__shared__ float sharedScaleF[POSE_MAX_PEOPLE];
// Other parameters
const auto numberPartPairs = sizeof(BODY_22_PAIRS_GPU) / (2*sizeof(BODY_22_PAIRS_GPU[0]));
const auto numberColors = sizeof(BODY_22_COLORS) / (3*sizeof(BODY_22_COLORS[0]));
const auto radius = fastMin(targetWidth, targetHeight) / 100.f;
const auto stickwidth = fastMin(targetWidth, targetHeight) / 120.f;
// Render key points
renderKeypoints(targetPtr, sharedMaxs, sharedMins, sharedScaleF,
globalIdx, x, y, targetWidth, targetHeight, posePtr, BODY_22_PAIRS_GPU, numberPeople,
POSE_BODY_22_NUMBER_PARTS, numberPartPairs, BODY_22_COLORS, numberColors,
radius, stickwidth, threshold, alphaColorToAdd, blendOriginalFrame, (googlyEyes ? 14 : -1), (googlyEyes ? 15 : -1));
}
__global__ void renderPoseMpi29Parts(float* targetPtr, const int targetWidth, const int targetHeight, const float* const posePtr, __global__ void renderPoseMpi29Parts(float* targetPtr, const int targetWidth, const int targetHeight, const float* const posePtr,
const int numberPeople, const float threshold, const bool blendOriginalFrame, const float alphaColorToAdd) const int numberPeople, const float threshold, const bool blendOriginalFrame, const float alphaColorToAdd)
{ {
...@@ -306,11 +335,14 @@ namespace op ...@@ -306,11 +335,14 @@ namespace op
if (poseModel == PoseModel::COCO_18) if (poseModel == PoseModel::COCO_18)
renderPoseCoco<<<threadsPerBlock, numBlocks>>>(framePtr, frameSize.x, frameSize.y, posePtr, numberPeople, renderPoseCoco<<<threadsPerBlock, numBlocks>>>(framePtr, frameSize.x, frameSize.y, posePtr, numberPeople,
POSE_RENDER_THRESHOLD, googlyEyes, blendOriginalFrame, alphaBlending); POSE_RENDER_THRESHOLD, googlyEyes, blendOriginalFrame, alphaBlending);
else if (poseModel == PoseModel::BODY_22)
renderPoseBody22<<<threadsPerBlock, numBlocks>>>(framePtr, frameSize.x, frameSize.y, posePtr, numberPeople,
POSE_RENDER_THRESHOLD, googlyEyes, blendOriginalFrame, alphaBlending);
else if (poseModel == PoseModel::MPI_15 || poseModel == PoseModel::MPI_15_4) else if (poseModel == PoseModel::MPI_15 || poseModel == PoseModel::MPI_15_4)
renderPoseMpi29Parts<<<threadsPerBlock, numBlocks>>>(framePtr, frameSize.x, frameSize.y, posePtr, renderPoseMpi29Parts<<<threadsPerBlock, numBlocks>>>(framePtr, frameSize.x, frameSize.y, posePtr,
numberPeople, POSE_RENDER_THRESHOLD, blendOriginalFrame, alphaBlending); numberPeople, POSE_RENDER_THRESHOLD, blendOriginalFrame, alphaBlending);
else else
error("Unvalid Model.", __LINE__, __FUNCTION__, __FILE__); error("Invalid Model.", __LINE__, __FUNCTION__, __FILE__);
cudaCheck(__LINE__, __FUNCTION__, __FILE__); cudaCheck(__LINE__, __FUNCTION__, __FILE__);
} }
} }
......
...@@ -123,54 +123,59 @@ namespace op ...@@ -123,54 +123,59 @@ namespace op
// Parameters // Parameters
const auto lineType = 8; const auto lineType = 8;
const auto shift = 0; const auto shift = 0;
const auto thresholdRectangle = 0.1f;
const auto numberColors = colors.size(); const auto numberColors = colors.size();
const auto thresholdRectangle = 0.1f;
const auto numberKeypoints = keypoints.getSize(1); const auto numberKeypoints = keypoints.getSize(1);
const auto areaKeypoints = numberKeypoints * keypoints.getSize(2); const auto areaKeypoints = numberKeypoints * keypoints.getSize(2);
// Keypoints // Keypoints
for (auto person = 0 ; person < keypoints.getSize(0) ; person++) for (auto person = 0 ; person < keypoints.getSize(0) ; person++)
{ {
const auto personRectangle = getKeypointsRectangle(&keypoints[person*areaKeypoints], keypoints.getSize(1), thresholdRectangle); const auto personRectangle = getKeypointsRectangle(&keypoints[person*areaKeypoints], numberKeypoints, thresholdRectangle);
const auto ratioAreas = fastMin(1.f, fastMax(personRectangle.width/(float)width, personRectangle.height/(float)height)); if (personRectangle.area() > 0)
// Size-dependent variables
const auto thicknessCircle = fastMax(intRound(std::sqrt(area)*thicknessCircleRatio * ratioAreas), 2);
const auto thicknessLine = intRound(thicknessCircle * thicknessLineRatioWRTCircle);
const auto radius = thicknessCircle / 2;
// Draw lines
for (auto pair = 0 ; pair < pairs.size() ; pair+=2)
{ {
const auto index1 = (person * keypoints.getSize(1) + pairs[pair]) * keypoints.getSize(2); const auto ratioAreas = fastMin(1.f, fastMax(personRectangle.width/(float)width, personRectangle.height/(float)height));
const auto index2 = (person * keypoints.getSize(1) + pairs[pair+1]) * keypoints.getSize(2); // Size-dependent variables
if (keypoints[index1+2] > threshold && keypoints[index2+2] > threshold) const auto thicknessRatio = fastMax(intRound(std::sqrt(area)*thicknessCircleRatio * ratioAreas), 2);
// Negative thickness in cv::circle means that a filled circle is to be drawn.
const auto thicknessCircle = (ratioAreas > 0.05 ? thicknessRatio : -1);
const auto thicknessLine = intRound(thicknessRatio * thicknessLineRatioWRTCircle);
const auto radius = thicknessRatio / 2;
// Draw lines
for (auto pair = 0 ; pair < pairs.size() ; pair+=2)
{ {
const auto colorIndex = pair/2*3; const auto index1 = (person * numberKeypoints + pairs[pair]) * keypoints.getSize(2);
const cv::Scalar color{colors[colorIndex % numberColors], const auto index2 = (person * numberKeypoints + pairs[pair+1]) * keypoints.getSize(2);
colors[(colorIndex+1) % numberColors], if (keypoints[index1+2] > threshold && keypoints[index2+2] > threshold)
colors[(colorIndex+2) % numberColors]}; {
const cv::Point keypoint1{intRound(keypoints[index1]), intRound(keypoints[index1+1])}; const auto colorIndex = pair/2*3;
const cv::Point keypoint2{intRound(keypoints[index2]), intRound(keypoints[index2+1])}; const cv::Scalar color{colors[colorIndex % numberColors],
cv::line(frameR, keypoint1, keypoint2, color[0], thicknessLine, lineType, shift); colors[(colorIndex+1) % numberColors],
cv::line(frameG, keypoint1, keypoint2, color[1], thicknessLine, lineType, shift); colors[(colorIndex+2) % numberColors]};
cv::line(frameB, keypoint1, keypoint2, color[2], thicknessLine, lineType, shift); const cv::Point keypoint1{intRound(keypoints[index1]), intRound(keypoints[index1+1])};
const cv::Point keypoint2{intRound(keypoints[index2]), intRound(keypoints[index2+1])};
cv::line(frameR, keypoint1, keypoint2, color[0], thicknessLine, lineType, shift);
cv::line(frameG, keypoint1, keypoint2, color[1], thicknessLine, lineType, shift);
cv::line(frameB, keypoint1, keypoint2, color[2], thicknessLine, lineType, shift);
}
} }
}
// Draw circles // Draw circles
for (auto part = 0 ; part < keypoints.getSize(1) ; part++) for (auto part = 0 ; part < numberKeypoints ; part++)
{
const auto faceIndex = (person * keypoints.getSize(1) + part) * keypoints.getSize(2);
if (keypoints[faceIndex+2] > threshold)
{ {
const auto colorIndex = part*3; const auto faceIndex = (person * numberKeypoints + part) * keypoints.getSize(2);
const cv::Scalar color{colors[colorIndex % numberColors], if (keypoints[faceIndex+2] > threshold)
colors[(colorIndex+1) % numberColors], {
colors[(colorIndex+2) % numberColors]}; const auto colorIndex = part*3;
const cv::Point center{intRound(keypoints[faceIndex]), intRound(keypoints[faceIndex+1])}; const cv::Scalar color{colors[colorIndex % numberColors],
cv::circle(frameR, center, radius, color[0], thicknessCircle, lineType, shift); colors[(colorIndex+1) % numberColors],
cv::circle(frameG, center, radius, color[1], thicknessCircle, lineType, shift); colors[(colorIndex+2) % numberColors]};
cv::circle(frameB, center, radius, color[2], thicknessCircle, lineType, shift); const cv::Point center{intRound(keypoints[faceIndex]), intRound(keypoints[faceIndex+1])};
cv::circle(frameR, center, radius, color[0], thicknessCircle, lineType, shift);
cv::circle(frameG, center, radius, color[1], thicknessCircle, lineType, shift);
cv::circle(frameB, center, radius, color[2], thicknessCircle, lineType, shift);
}
} }
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册