mirror of
https://github.com/gosticks/openpose.git
synced 2026-10-06 15:17:00 +00:00
Face/hand working with any output resolution
This commit is contained in:
@@ -215,7 +215,9 @@ OpenPose Library - Release Notes
|
||||
1. Main improvements:
|
||||
1. Flir cameras: Added software trigger and a dedicated thread to keep reading images to remove latency (analogously to webcamReader).
|
||||
2. Functions or parameters renamed:
|
||||
1. Removed scale parameter from hand and face rectangle extractor (causing wrong results if custom `--output_resolution`).
|
||||
3. Main bugs fixed:
|
||||
1. Hand and face work properly again with any `--output_resolution`.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace op
|
||||
public:
|
||||
explicit FaceDetector(const PoseModel poseModel);
|
||||
|
||||
std::vector<Rectangle<float>> detectFaces(const Array<float>& poseKeypoints, const double scaleInputToOutput) const;
|
||||
std::vector<Rectangle<float>> detectFaces(const Array<float>& poseKeypoints) const;
|
||||
|
||||
private:
|
||||
const unsigned int mNeck;
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace op
|
||||
const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);
|
||||
// Detect people face
|
||||
for (auto& tDatum : *tDatums)
|
||||
tDatum.faceRectangles = spFaceDetector->detectFaces(tDatum.poseKeypoints, tDatum.scaleInputToOutput);
|
||||
tDatum.faceRectangles = spFaceDetector->detectFaces(tDatum.poseKeypoints);
|
||||
// Profiling speed
|
||||
Profiler::timerEnd(profilerKey);
|
||||
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
@@ -14,9 +14,9 @@ namespace op
|
||||
public:
|
||||
explicit HandDetector(const PoseModel poseModel);
|
||||
|
||||
std::vector<std::array<Rectangle<float>, 2>> detectHands(const Array<float>& poseKeypoints, const double scaleInputToOutput) const;
|
||||
std::vector<std::array<Rectangle<float>, 2>> detectHands(const Array<float>& poseKeypoints) const;
|
||||
|
||||
std::vector<std::array<Rectangle<float>, 2>> trackHands(const Array<float>& poseKeypoints, const double scaleInputToOutput);
|
||||
std::vector<std::array<Rectangle<float>, 2>> trackHands(const Array<float>& poseKeypoints);
|
||||
|
||||
void updateTracker(const std::array<Array<float>, 2>& handKeypoints, const unsigned long long id);
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace op
|
||||
const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);
|
||||
// Detect people hand
|
||||
for (auto& tDatum : *tDatums)
|
||||
tDatum.handRectangles = spHandDetector->detectHands(tDatum.poseKeypoints, tDatum.scaleInputToOutput);
|
||||
tDatum.handRectangles = spHandDetector->detectHands(tDatum.poseKeypoints);
|
||||
// Profiling speed
|
||||
Profiler::timerEnd(profilerKey);
|
||||
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace op
|
||||
const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);
|
||||
// Detect people hand
|
||||
for (auto& tDatum : *tDatums)
|
||||
tDatum.handRectangles = spHandDetector->trackHands(tDatum.poseKeypoints, tDatum.scaleInputToOutput);
|
||||
tDatum.handRectangles = spHandDetector->trackHands(tDatum.poseKeypoints);
|
||||
// Profiling speed
|
||||
Profiler::timerEnd(profilerKey);
|
||||
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);
|
||||
|
||||
@@ -15,9 +15,11 @@ namespace op
|
||||
{
|
||||
}
|
||||
|
||||
inline Rectangle<float> getFaceFromPoseKeypoints(const Array<float>& poseKeypoints, const unsigned int personIndex, const unsigned int neck,
|
||||
const unsigned int headNose, const unsigned int lEar, const unsigned int rEar,
|
||||
const unsigned int lEye, const unsigned int rEye, const float threshold)
|
||||
inline Rectangle<float> getFaceFromPoseKeypoints(const Array<float>& poseKeypoints, const unsigned int personIndex,
|
||||
const unsigned int neck, const unsigned int headNose,
|
||||
const unsigned int lEar, const unsigned int rEar,
|
||||
const unsigned int lEye, const unsigned int rEye,
|
||||
const float threshold)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -58,13 +60,17 @@ 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(poseKeypoints, personIndex, headNose, lEye) + getDistance(poseKeypoints, personIndex, headNose, lEar) + getDistance(poseKeypoints, personIndex, 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(poseKeypoints, personIndex, headNose, rEye) + getDistance(poseKeypoints, personIndex, headNose, rEar) + getDistance(poseKeypoints, personIndex, 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)
|
||||
@@ -108,7 +114,7 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Rectangle<float>> FaceDetector::detectFaces(const Array<float>& poseKeypoints, const double scaleInputToOutput) const
|
||||
std::vector<Rectangle<float>> FaceDetector::detectFaces(const Array<float>& poseKeypoints) const
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -119,7 +125,8 @@ namespace op
|
||||
// Otherwise, get face position(s)
|
||||
if (!poseKeypoints.empty())
|
||||
for (auto person = 0 ; person < numberPeople ; person++)
|
||||
faceRectangles.at(person) = getFaceFromPoseKeypoints(poseKeypoints, person, mNeck, mNose, mLEar, mREar, mLEye, mREye, threshold) / (float)scaleInputToOutput;
|
||||
faceRectangles.at(person) = getFaceFromPoseKeypoints(
|
||||
poseKeypoints, person, mNeck, mNose, mLEar, mREar, mLEye, mREye, threshold);
|
||||
return faceRectangles;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace op
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<std::array<Rectangle<float>, 2>> HandDetector::detectHands(const Array<float>& poseKeypoints, const double scaleInputToOutput) const
|
||||
std::vector<std::array<Rectangle<float>, 2>> HandDetector::detectHands(const Array<float>& poseKeypoints) const
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -148,8 +148,6 @@ namespace op
|
||||
mPoseIndexes[(int)PosePart::LShoulder], mPoseIndexes[(int)PosePart::RWrist],
|
||||
mPoseIndexes[(int)PosePart::RElbow], mPoseIndexes[(int)PosePart::RShoulder], threshold
|
||||
);
|
||||
handRectangles.at(person).at(0) /= (float) scaleInputToOutput;
|
||||
handRectangles.at(person).at(1) /= (float) scaleInputToOutput;
|
||||
}
|
||||
}
|
||||
return handRectangles;
|
||||
@@ -161,13 +159,13 @@ namespace op
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::array<Rectangle<float>, 2>> HandDetector::trackHands(const Array<float>& poseKeypoints, const double scaleInputToOutput)
|
||||
std::vector<std::array<Rectangle<float>, 2>> HandDetector::trackHands(const Array<float>& poseKeypoints)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{mMutex};
|
||||
// Baseline detectHands
|
||||
auto handRectangles = detectHands(poseKeypoints, scaleInputToOutput);
|
||||
auto handRectangles = detectHands(poseKeypoints);
|
||||
// If previous hands saved
|
||||
for (auto& handRectangle : handRectangles)
|
||||
{
|
||||
|
||||
@@ -354,8 +354,10 @@ namespace op
|
||||
}
|
||||
if (imagesExtracted)
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock{mBufferMutex};
|
||||
std::unique_lock<std::mutex> lock{mBufferMutex};
|
||||
std::swap(mBuffer, imagePtrs);
|
||||
lock.unlock();
|
||||
std::this_thread::sleep_for(std::chrono::microseconds{1});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -408,23 +410,9 @@ namespace op
|
||||
std::this_thread::sleep_for(std::chrono::microseconds{5});
|
||||
}
|
||||
}
|
||||
// Commented code was supposed to clean buffer, but `NewestFirstOverwrite` does that
|
||||
// Getting frames
|
||||
// Retrieve next received image and ensure image completion
|
||||
// Spinnaker::ImagePtr imagePtr = cameraPtrs.at(i)->GetNextImage();
|
||||
// Clean buffer + retrieve next received image + ensure image completion
|
||||
// auto durationMs = 0.;
|
||||
// // for (auto counter = 0 ; counter < 10 ; counter++)
|
||||
// while (durationMs < 1.)
|
||||
// {
|
||||
// const auto begin = std::chrono::high_resolution_clock::now();
|
||||
// for (auto i = 0u; i < cameraPtrs.size(); i++)
|
||||
// imagePtrs.at(i) = cameraPtrs.at(i)->GetNextImage();
|
||||
// durationMs = std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
// std::chrono::high_resolution_clock::now()-begin
|
||||
// ).count() * 1e-6;
|
||||
// // log("Time extraction (ms): " + std::to_string(durationMs), Priority::High);
|
||||
// }
|
||||
|
||||
// All images completed
|
||||
bool imagesExtracted = true;
|
||||
|
||||
Reference in New Issue
Block a user