From c652ab8b97a0cba6c678b1d2bbdd02c27a6013a8 Mon Sep 17 00:00:00 2001 From: gineshidalgo99 Date: Fri, 7 Jul 2017 11:15:49 -0400 Subject: [PATCH] Keypoints functions same format, better handDetector tracking --- include/openpose/core/rectangle.hpp | 6 ++ include/openpose/hand/handDetector.hpp | 2 +- include/openpose/hand/wHandDetectorUpdate.hpp | 2 +- include/openpose/utilities/keypoint.hpp | 18 +++-- include/openpose/wrapper/wrapper.hpp | 5 +- src/openpose/core/maximumBase.cpp | 40 ++++++++++ src/openpose/core/maximumBase.cu | 6 +- src/openpose/core/rectangle.cpp | 55 ++++++++++++++ src/openpose/face/faceDetector.cpp | 12 +-- src/openpose/hand/handDetector.cpp | 59 ++++++++------- src/openpose/utilities/keypoint.cpp | 73 ++++++++++++++++--- 11 files changed, 222 insertions(+), 56 deletions(-) diff --git a/include/openpose/core/rectangle.hpp b/include/openpose/core/rectangle.hpp index 7caf9e34..b5f34b37 100644 --- a/include/openpose/core/rectangle.hpp +++ b/include/openpose/core/rectangle.hpp @@ -62,6 +62,8 @@ namespace op return width * height; } + void recenter(const T newWidth, const T newHeight); + /** * It returns a string with the whole Rectangle data. Useful for debugging. * The format is: `[x, y, width, height]` @@ -78,6 +80,10 @@ namespace op Rectangle operator/(const T value) const; }; + + // Static methods + template + Rectangle recenter(const Rectangle& rectangle, const T newWidth, const T newHeight); } #endif // OPENPOSE_CORE_RECTANGLE_HPP diff --git a/include/openpose/hand/handDetector.hpp b/include/openpose/hand/handDetector.hpp index 353aacc8..40a71aba 100644 --- a/include/openpose/hand/handDetector.hpp +++ b/include/openpose/hand/handDetector.hpp @@ -23,7 +23,7 @@ namespace op std::vector, 2>> trackHands(const Array& poseKeypoints, const float scaleInputToOutput); - void updateTracker(const Array& poseKeypoints, const std::array, 2>& handKeypoints); + void updateTracker(const std::array, 2>& handKeypoints, const unsigned long long id); private: enum class PosePart : unsigned int diff --git a/include/openpose/hand/wHandDetectorUpdate.hpp b/include/openpose/hand/wHandDetectorUpdate.hpp index cf297e3e..1fd4d918 100644 --- a/include/openpose/hand/wHandDetectorUpdate.hpp +++ b/include/openpose/hand/wHandDetectorUpdate.hpp @@ -59,7 +59,7 @@ namespace op const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); // Detect people hand for (auto& tDatum : *tDatums) - spHandDetector->updateTracker(tDatum.poseKeypoints, tDatum.handKeypoints); + spHandDetector->updateTracker(tDatum.handKeypoints, tDatum.id); // Profiling speed Profiler::timerEnd(profilerKey); Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, Profiler::DEFAULT_X); diff --git a/include/openpose/utilities/keypoint.hpp b/include/openpose/utilities/keypoint.hpp index 95d022cb..98980f71 100644 --- a/include/openpose/utilities/keypoint.hpp +++ b/include/openpose/utilities/keypoint.hpp @@ -7,21 +7,27 @@ namespace op { - float getDistance(const float* keypointPtr, const int elementA, const int elementB); + float getDistance(const Array& keypoints, const int person, const int elementA, const int elementB); + + void averageKeypoints(Array& keypointsA, const Array& keypointsB, const int personA); void scaleKeypoints(Array& keypoints, const float scale); void scaleKeypoints(Array& keypoints, const float scaleX, const float scaleY); - void scaleKeypoints(Array& keypoints, const float scaleX, const float scaleY, const float offsetX, const float offsetY); + void scaleKeypoints(Array& keypoints, const float scaleX, const float scaleY, const float offsetX, + const float offsetY); - void renderKeypointsCpu(Array& frameArray, const Array& keypoints, const std::vector& pairs, - const std::vector colors, const float thicknessCircleRatio, const float thicknessLineRatioWRTCircle, + void renderKeypointsCpu(Array& frameArray, const Array& keypoints, + const std::vector& pairs, const std::vector colors, + const float thicknessCircleRatio, const float thicknessLineRatioWRTCircle, const float threshold); - Rectangle getKeypointsRectangle(const float* keypointPtr, const int numberKeypoints, const float threshold); + Rectangle getKeypointsRectangle(const Array& keypoints, const int person, const int numberKeypoints, const float threshold); + + float getAverageScore(const Array& keypoints, const int person); - float getKeypointsArea(const float* keypointPtr, const int numberKeypoints, const float threshold); + float getKeypointsArea(const Array& keypoints, const int person, const int numberKeypoints, const float threshold); int getBiggestPerson(const Array& keypoints, const float threshold); } diff --git a/include/openpose/wrapper/wrapper.hpp b/include/openpose/wrapper/wrapper.hpp index 704e72c7..bab9f94a 100644 --- a/include/openpose/wrapper/wrapper.hpp +++ b/include/openpose/wrapper/wrapper.hpp @@ -239,7 +239,7 @@ namespace op * Note that mThreadId must be re-initialized to 0 before starting a new Wrapper configuration. * @return unsigned int with the next thread id value. */ - unsigned int threadIdPP(); + unsigned long long threadIdPP(); /** * TWorker concatenator (private internal function). @@ -1151,7 +1151,7 @@ namespace op } template - unsigned int Wrapper::threadIdPP() + unsigned long long Wrapper::threadIdPP() { try { @@ -1162,6 +1162,7 @@ namespace op catch (const std::exception& e) { error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return 0ull; } } diff --git a/src/openpose/core/maximumBase.cpp b/src/openpose/core/maximumBase.cpp index bf864e49..a4f1ce58 100644 --- a/src/openpose/core/maximumBase.cpp +++ b/src/openpose/core/maximumBase.cpp @@ -1,3 +1,4 @@ +// #include #include #include #include @@ -15,6 +16,45 @@ namespace op UNUSED(targetSize); UNUSED(sourceSize); error("CPU version not completely implemented.", __LINE__, __FUNCTION__, __FILE__); + + // // TODO: ideally done, try, debug & compare to *.cu + // TODO: (maybe): remove thrust dependencies for computers without CUDA? + // const auto height = sourceSize[2]; + // const auto width = sourceSize[3]; + // const auto imageOffset = height * width; + // const auto num = targetSize[0]; + // const auto channels = targetSize[1]; + // const auto numberParts = targetSize[2]; + // const auto numberSubparts = targetSize[3]; + + // // log("sourceSize[0]: " + std::to_string(sourceSize[0])); // = 1 + // // log("sourceSize[1]: " + std::to_string(sourceSize[1])); // = #body parts + bck = 22 (hands) or 71 (face) + // // log("sourceSize[2]: " + std::to_string(sourceSize[2])); // = 368 = height + // // log("sourceSize[3]: " + std::to_string(sourceSize[3])); // = 368 = width + // // log("targetSize[0]: " + std::to_string(targetSize[0])); // = 1 + // // log("targetSize[1]: " + std::to_string(targetSize[1])); // = 1 + // // log("targetSize[2]: " + std::to_string(targetSize[2])); // = 21(hands) or 70 (face) + // // log("targetSize[3]: " + std::to_string(targetSize[3])); // = 3 = [x, y, score] + // // log(" "); + // for (auto n = 0; n < num; n++) + // { + // for (auto c = 0; c < channels; c++) + // { + // // // Parameters + // const auto offsetChannel = (n * channels + c); + // for (auto part = 0; part < numberParts; part++) + // { + // auto* targetPtrOffsetted = targetPtr + (offsetChannel + part) * numberSubparts; + // const auto* const sourcePtrOffsetted = sourcePtr + (offsetChannel + part) * imageOffset; + // // Option a - 6.3 fps + // const auto sourceIndexIterator = thrust::max_element(thrust::host, sourcePtrOffsetted, sourcePtrOffsetted + imageOffset); + // const auto sourceIndex = (int)(sourceIndexIterator - sourcePtrOffsetted); + // targetPtrOffsetted[0] = sourceIndex % width; + // targetPtrOffsetted[1] = sourceIndex / width; + // targetPtrOffsetted[2] = sourcePtrOffsetted[sourceIndex]; + // } + // } + // } } catch (const std::exception& e) { diff --git a/src/openpose/core/maximumBase.cu b/src/openpose/core/maximumBase.cu index 6d81abd5..ba2d5491 100644 --- a/src/openpose/core/maximumBase.cu +++ b/src/openpose/core/maximumBase.cu @@ -20,7 +20,7 @@ namespace op // { // const auto sourceThrustPtr = thrust::device_pointer_cast(sourcePtrOffsetted); // const auto sourceIndexIterator = thrust::max_element(thrust::device, sourceThrustPtr, sourceThrustPtr + imageOffset); - // const auto sourceIndex = sourceIndexIterator - sourceThrustPtr; + // const auto sourceIndex = (int)(sourceIndexIterator - sourceThrustPtr); // targetPtrOffsetted[0] = sourceIndex % width; // targetPtrOffsetted[1] = sourceIndex / width; // targetPtrOffsetted[2] = sourcePtrOffsetted[sourceIndex]; @@ -40,7 +40,7 @@ namespace op // const auto* const sourcePtrOffsetted = sourcePtr + (offsetChannel + part) * imageOffset; // auto sourceThrustPtr = thrust::device_pointer_cast(sourcePtrOffsetted); // const auto sourceIndexIterator = thrust::max_element(thrust::device, sourceThrustPtr, sourceThrustPtr + imageOffset); - // const auto sourceIndex = sourceIndexIterator - sourceThrustPtr; + // const auto sourceIndex = (int)(sourceIndexIterator - sourceThrustPtr); // targetPtrOffsetted[0] = sourceIndex % width; // targetPtrOffsetted[1] = sourceIndex / width; // targetPtrOffsetted[2] = sourcePtrOffsetted[sourceIndex]; @@ -82,7 +82,7 @@ namespace op // Option a - 6.3 fps const auto sourceThrustPtr = thrust::device_pointer_cast(sourcePtrOffsetted); const auto sourceIndexIterator = thrust::max_element(thrust::device, sourceThrustPtr, sourceThrustPtr + imageOffset); - const auto sourceIndex = sourceIndexIterator - sourceThrustPtr; + const auto sourceIndex = (int)(sourceIndexIterator - sourceThrustPtr); fillTargetPtrPart<<<1, 1>>>(targetPtrOffsetted, sourcePtrOffsetted, sourceIndex, sourceIndex % width, sourceIndex / width); // // Option b - <1 fps // fillTargetPtrChannel<<<1, 1>>>(targetPtrOffsetted, sourcePtrOffsetted, width, imageOffset); diff --git a/src/openpose/core/rectangle.cpp b/src/openpose/core/rectangle.cpp index 44d34585..88856514 100644 --- a/src/openpose/core/rectangle.cpp +++ b/src/openpose/core/rectangle.cpp @@ -111,6 +111,23 @@ namespace op } } + template + void Rectangle::recenter(const T newWidth, const T newHeight) + { + try + { + const auto centerPoint = center(); + x = centerPoint.x - T(newWidth / 2.f); + y = centerPoint.y - T(newHeight / 2.f); + width = newWidth; + height = newHeight; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + template std::string Rectangle::toString() const { @@ -192,4 +209,42 @@ namespace op } COMPILE_TEMPLATE_BASIC_TYPES_STRUCT(Rectangle); + + + + // Static methods + template + Rectangle recenter(const Rectangle& rectangle, const T newWidth, const T newHeight) + { + try + { + Rectangle result; + const auto centerPoint = rectangle.center(); + result.x = centerPoint.x - T(newWidth / 2.f); + result.y = centerPoint.y - T(newHeight / 2.f); + result.width = newWidth; + result.height = newHeight; + return result; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return Rectangle{}; + } + } + + template Rectangle recenter(const Rectangle& rectangle, const char newWidth, const char newHeight); + template Rectangle recenter(const Rectangle& rectangle, const signed char newWidth, const signed char newHeight); + template Rectangle recenter(const Rectangle& rectangle, const short newWidth, const short newHeight); + template Rectangle recenter(const Rectangle& rectangle, const int newWidth, const int newHeight); + template Rectangle recenter(const Rectangle& rectangle, const long newWidth, const long newHeight); + template Rectangle recenter(const Rectangle& rectangle, const long long newWidth, const long long newHeight); + template Rectangle recenter(const Rectangle& rectangle, const unsigned char newWidth, const unsigned char newHeight); + template Rectangle recenter(const Rectangle& rectangle, const unsigned short newWidth, const unsigned short newHeight); + template Rectangle recenter(const Rectangle& rectangle, const unsigned int newWidth, const unsigned int newHeight); + template Rectangle recenter(const Rectangle& rectangle, const unsigned long newWidth, const unsigned long newHeight); + template Rectangle recenter(const Rectangle& rectangle, const unsigned long long newWidth, const unsigned long long newHeight); + template Rectangle recenter(const Rectangle& rectangle, const float newWidth, const float newHeight); + template Rectangle recenter(const Rectangle& rectangle, const double newWidth, const double newHeight); + template Rectangle recenter(const Rectangle& rectangle, const long double newWidth, const long double newHeight); } diff --git a/src/openpose/face/faceDetector.cpp b/src/openpose/face/faceDetector.cpp index f852352f..769001ba 100644 --- a/src/openpose/face/faceDetector.cpp +++ b/src/openpose/face/faceDetector.cpp @@ -41,7 +41,7 @@ namespace op { pointTopLeft.x = posePtr[headNose*3]; pointTopLeft.y = posePtr[headNose*3+1]; - faceSize = 1.33f * getDistance(posePtr, neck, headNose); + faceSize = 1.33f * getDistance(poseKeypoints, personIndex, neck, headNose); } } // Face as average between different body keypoints (e.g. COCO) @@ -59,13 +59,13 @@ namespace op { pointTopLeft.x += (posePtr[lEye*3] + posePtr[lEar*3] + posePtr[headNose*3]) / 3.f; pointTopLeft.y += (posePtr[lEye*3+1] + posePtr[lEar*3+1] + posePtr[headNose*3+1]) / 3.f; - faceSize += 0.85f * (getDistance(posePtr, headNose, lEye) + getDistance(posePtr, headNose, lEar) + getDistance(posePtr, neck, headNose)); + faceSize += 0.85f * (getDistance(poseKeypoints, personIndex, headNose, lEye) + getDistance(poseKeypoints, personIndex, headNose, lEar) + getDistance(poseKeypoints, personIndex, neck, headNose)); } else // if(lEyeScoreAbove) { pointTopLeft.x += (posePtr[rEye*3] + posePtr[rEar*3] + posePtr[headNose*3]) / 3.f; pointTopLeft.y += (posePtr[rEye*3+1] + posePtr[rEar*3+1] + posePtr[headNose*3+1]) / 3.f; - faceSize += 0.85f * (getDistance(posePtr, headNose, rEye) + getDistance(posePtr, headNose, rEar) + getDistance(posePtr, neck, headNose)); + faceSize += 0.85f * (getDistance(poseKeypoints, personIndex, headNose, rEye) + getDistance(poseKeypoints, personIndex, headNose, rEar) + getDistance(poseKeypoints, personIndex, neck, headNose)); } } // else --> 2 * dist(neck, headNose) @@ -73,7 +73,7 @@ namespace op { pointTopLeft.x += (posePtr[neck*3] + posePtr[headNose*3]) / 2.f; pointTopLeft.y += (posePtr[neck*3+1] + posePtr[headNose*3+1]) / 2.f; - faceSize += 2.f * getDistance(posePtr, neck, headNose); + faceSize += 2.f * getDistance(poseKeypoints, personIndex, neck, headNose); } counter++; } @@ -82,7 +82,7 @@ namespace op { pointTopLeft.x += (posePtr[lEye*3] + posePtr[rEye*3]) / 2.f; pointTopLeft.y += (posePtr[lEye*3+1] + posePtr[rEye*3+1]) / 2.f; - faceSize += 3.f * getDistance(posePtr, lEye, rEye); + faceSize += 3.f * getDistance(poseKeypoints, personIndex, lEye, rEye); counter++; } // 2 * dist(lEar, rEar) @@ -90,7 +90,7 @@ namespace op { pointTopLeft.x += (posePtr[lEar*3] + posePtr[rEar*3]) / 2.f; pointTopLeft.y += (posePtr[lEar*3+1] + posePtr[rEar*3+1]) / 2.f; - faceSize += 2.f * getDistance(posePtr, lEar, rEar); + faceSize += 2.f * getDistance(poseKeypoints, personIndex, lEar, rEar); counter++; } // Average (if counter > 0) diff --git a/src/openpose/hand/handDetector.cpp b/src/openpose/hand/handDetector.cpp index 2ffcc39a..f81210da 100644 --- a/src/openpose/hand/handDetector.cpp +++ b/src/openpose/hand/handDetector.cpp @@ -25,8 +25,8 @@ namespace op // pos_hand = pos_wrist + ratio * (pos_wrist - pos_elbox) = (1 + ratio) * pos_wrist - ratio * pos_elbox handRectangle.x = posePtr[wrist*3] + ratioWristElbow * (posePtr[wrist*3] - posePtr[elbow*3]); handRectangle.y = posePtr[wrist*3+1] + ratioWristElbow * (posePtr[wrist*3+1] - posePtr[elbow*3+1]); - const auto distanceWristElbow = getDistance(posePtr, wrist, elbow); - const auto distanceElbowShoulder = getDistance(posePtr, elbow, shoulder); + const auto distanceWristElbow = getDistance(poseKeypoints, person, wrist, elbow); + const auto distanceElbowShoulder = getDistance(poseKeypoints, person, elbow, shoulder); handRectangle.width = 1.5f * fastMax(distanceWristElbow, 0.9f * distanceElbowShoulder); } // height = width @@ -188,37 +188,40 @@ namespace op } } - void HandDetector::updateTracker(const Array& poseKeypoints, const std::array, 2>& handKeypoints) + void HandDetector::updateTracker(const std::array, 2>& handKeypoints, const unsigned long long id) { try { std::lock_guard lock{mMutex}; - // Security checks - if (poseKeypoints.getSize(0) != handKeypoints[0].getSize(0) || poseKeypoints.getSize(0) != handKeypoints[1].getSize(0)) - error("Number people on poseKeypoints different than in handKeypoints.", __LINE__, __FUNCTION__, __FILE__); - // Parameters - const auto numberPeople = poseKeypoints.getSize(0); - // const auto poseNumberParts = poseKeypoints.getSize(1); - const auto handNumberParts = handKeypoints[0].getSize(1); - const auto numberChannels = poseKeypoints.getSize(2); - const auto thresholdRectangle = 0.25f; - // Update pose keypoints and hand rectangles - mPoseTrack.resize(numberPeople); - mHandLeftPrevious.clear(); - mHandRightPrevious.clear(); - for (auto person = 0 ; person < mPoseTrack.size() ; person++) + if (mCurrentId < id) { - const auto offset = person * handNumberParts * numberChannels; - // Left hand - const auto* handLeftPtr = handKeypoints[0].getConstPtr() + offset; - const auto handLeftRectangle = getKeypointsRectangle(handLeftPtr, handNumberParts, thresholdRectangle); - if (handLeftRectangle.area() > 0) - mHandLeftPrevious.emplace_back(handLeftRectangle); - const auto* handRightPtr = handKeypoints[1].getConstPtr() + offset; - // Right hand - const auto handRightRectangle = getKeypointsRectangle(handRightPtr, handNumberParts, thresholdRectangle); - if (handRightRectangle.area() > 0) - mHandRightPrevious.emplace_back(handRightRectangle); + mCurrentId = id; + // Parameters + const auto numberPeople = handKeypoints.at(0).getSize(0); + const auto handNumberParts = handKeypoints[0].getSize(1); + const auto thresholdRectangle = 0.25f; + // Update pose keypoints and hand rectangles + mPoseTrack.resize(numberPeople); + mHandLeftPrevious.clear(); + mHandRightPrevious.clear(); + for (auto person = 0 ; person < mPoseTrack.size() ; person++) + { + const auto scoreThreshold = 0.66667f; + // Left hand + if (getAverageScore(handKeypoints[0], person) > scoreThreshold) + { + const auto handLeftRectangle = getKeypointsRectangle(handKeypoints[0], person, handNumberParts, thresholdRectangle); + if (handLeftRectangle.area() > 0) + mHandLeftPrevious.emplace_back(handLeftRectangle); + } + // Right hand + if (getAverageScore(handKeypoints[1], person) > scoreThreshold) + { + const auto handRightRectangle = getKeypointsRectangle(handKeypoints[1], person, handNumberParts, thresholdRectangle); + if (handRightRectangle.area() > 0) + mHandRightPrevious.emplace_back(handRightRectangle); + } + } } } catch (const std::exception& e) diff --git a/src/openpose/utilities/keypoint.cpp b/src/openpose/utilities/keypoint.cpp index f48f5c51..b7c96285 100644 --- a/src/openpose/utilities/keypoint.cpp +++ b/src/openpose/utilities/keypoint.cpp @@ -8,10 +8,11 @@ namespace op { const std::string errorMessage = "The Array is not a RGB image. This function is only for array of dimension: [sizeA x sizeB x 3]."; - float getDistance(const float* keypointPtr, const int elementA, const int elementB) + float getDistance(const Array& keypoints, const int person, const int elementA, const int elementB) { try { + const auto keypointPtr = keypoints.getConstPtr() + person * keypoints.getSize(1) * keypoints.getSize(2); const auto pixelX = keypointPtr[elementA*3] - keypointPtr[elementB*3]; const auto pixelY = keypointPtr[elementA*3+1] - keypointPtr[elementB*3+1]; return std::sqrt(pixelX*pixelX+pixelY*pixelY); @@ -23,6 +24,36 @@ namespace op } } + void averageKeypoints(Array& keypointsA, const Array& keypointsB, const int personA) + { + try + { + // Security checks + if (keypointsA.getNumberDimensions() != keypointsB.getNumberDimensions()) + error("keypointsA.getNumberDimensions() != keypointsB.getNumberDimensions().", __LINE__, __FUNCTION__, __FILE__); + for (auto dimension = 1 ; dimension < keypointsA.getNumberDimensions() ; dimension++) + if (keypointsA.getSize(dimension) != keypointsB.getSize(dimension)) + error("keypointsA.getSize() != keypointsB.getSize().", __LINE__, __FUNCTION__, __FILE__); + // For each body part + const auto numberParts = keypointsA.getSize(1); + for (auto part = 0 ; part < numberParts ; part++) + { + const auto finalIndexA = keypointsA.getSize(2)*(personA*numberParts + part); + const auto finalIndexB = keypointsA.getSize(2)*part; + if (keypointsB[finalIndexB+2] - keypointsA[finalIndexA+2] > 0.05f) + { + keypointsA[finalIndexA] = keypointsB[finalIndexB]; + keypointsA[finalIndexA+1] = keypointsB[finalIndexB+1]; + keypointsA[finalIndexA+2] = keypointsB[finalIndexB+2]; + } + } + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + void scaleKeypoints(Array& keypoints, const float scale) { try @@ -126,12 +157,11 @@ namespace op const auto numberColors = colors.size(); const auto thresholdRectangle = 0.1f; const auto numberKeypoints = keypoints.getSize(1); - const auto areaKeypoints = numberKeypoints * keypoints.getSize(2); // Keypoints for (auto person = 0 ; person < keypoints.getSize(0) ; person++) { - const auto personRectangle = getKeypointsRectangle(&keypoints[person*areaKeypoints], numberKeypoints, thresholdRectangle); + const auto personRectangle = getKeypointsRectangle(keypoints, person, numberKeypoints, thresholdRectangle); if (personRectangle.area() > 0) { const auto ratioAreas = fastMin(1.f, fastMax(personRectangle.width/(float)width, personRectangle.height/(float)height)); @@ -187,13 +217,15 @@ namespace op } } - Rectangle getKeypointsRectangle(const float* keypointPtr, const int numberKeypoints, const float threshold) + Rectangle getKeypointsRectangle(const Array& keypoints, const int person, const int numberKeypoints, const float threshold) { try { + // Security checks if (numberKeypoints < 1) error("Number body parts must be > 0", __LINE__, __FUNCTION__, __FILE__); - + // Define keypointPtr + const auto keypointPtr = keypoints.getConstPtr() + person * keypoints.getSize(1) * keypoints.getSize(2); float minX = std::numeric_limits::max(); float maxX = 0.f; float minY = minX; @@ -229,11 +261,35 @@ namespace op } } - float getKeypointsArea(const float* keypointPtr, const int numberKeypoints, const float threshold) + float getAverageScore(const Array& keypoints, const int person) + { + try + { + // Security checks + if (person >= keypoints.getSize(0)) + error("Person index out of bounds.", __LINE__, __FUNCTION__, __FILE__); + // Get average score + auto score = 0.f; + const auto numberKeypoints = keypoints.getSize(1); + const auto area = numberKeypoints * keypoints.getSize(2); + const auto personOffset = person * area; + for (auto part = 0 ; part < numberKeypoints ; part++) + score += keypoints[personOffset + part*keypoints.getSize(2) + 2]; + return score / numberKeypoints; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return 0.f; + } + } + + float getKeypointsArea(const Array& keypoints, const int person, const int numberKeypoints, + const float threshold) { try { - return getKeypointsRectangle(keypointPtr, numberKeypoints, threshold).area(); + return getKeypointsRectangle(keypoints, person, numberKeypoints, threshold).area(); } catch (const std::exception& e) { @@ -250,12 +306,11 @@ namespace op { const auto numberPeople = keypoints.getSize(0); const auto numberKeypoints = keypoints.getSize(1); - const auto area = numberKeypoints * keypoints.getSize(2); auto biggestPoseIndex = -1; auto biggestArea = -1.f; for (auto person = 0 ; person < numberPeople ; person++) { - const auto newPersonArea = getKeypointsArea(&keypoints[person*area], numberKeypoints, threshold); + const auto newPersonArea = getKeypointsArea(keypoints, person, numberKeypoints, threshold); if (newPersonArea > biggestArea) { biggestArea = newPersonArea; -- GitLab