|
#ifndef OPENPOSE_WRAPPER_WRAPPER_HAND_FROM_JSON_TEST_HPP |
|
#define OPENPOSE_WRAPPER_WRAPPER_HAND_FROM_JSON_TEST_HPP |
|
|
|
|
|
#include <opencv2/opencv.hpp> |
|
|
|
#include <openpose/headers.hpp> |
|
|
|
namespace op |
|
{ |
|
template<typename TDatum, |
|
typename TDatums = std::vector<std::shared_ptr<TDatum>>, |
|
typename TWorker = std::shared_ptr<Worker<std::shared_ptr<TDatums>>>, |
|
typename TQueue = Queue<std::shared_ptr<TDatums>>> |
|
class WrapperHandFromJsonTest |
|
{ |
|
public: |
|
|
|
|
|
|
|
explicit WrapperHandFromJsonTest(); |
|
|
|
|
|
|
|
|
|
|
|
~WrapperHandFromJsonTest(); |
|
|
|
void configure(const WrapperStructPose& wrapperStructPose, |
|
const WrapperStructHand& wrapperStructHand, |
|
const std::shared_ptr<Producer>& producerSharedPtr, |
|
const std::string& handGroundTruth, |
|
const std::string& writeJson, |
|
const DisplayMode displayMode = DisplayMode::NoDisplay); |
|
|
|
|
|
|
|
|
|
|
|
|
|
void exec(); |
|
|
|
private: |
|
ThreadManager<std::shared_ptr<TDatums>> mThreadManager; |
|
|
|
TWorker wDatumProducer; |
|
TWorker spWIdGenerator; |
|
TWorker spWScaleAndSizeExtractor; |
|
TWorker spWCvMatToOpInput; |
|
TWorker spWCvMatToOpOutput; |
|
std::vector<std::vector<TWorker>> spWPoses; |
|
std::vector<TWorker> mPostProcessingWs; |
|
std::vector<TWorker> mOutputWs; |
|
TWorker spWGui; |
|
|
|
|
|
|
|
|
|
|
|
|
|
void reset(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
void configureThreadManager(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<TWorker> mergeWorkers(const std::vector<TWorker>& workersA, const std::vector<TWorker>& workersB); |
|
|
|
DELETE_COPY(WrapperHandFromJsonTest); |
|
}; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <openpose/core/headers.hpp> |
|
#include <openpose/face/headers.hpp> |
|
#include <openpose/filestream/headers.hpp> |
|
#include <openpose/gui/headers.hpp> |
|
#include <openpose/gpu/gpu.hpp> |
|
#include <openpose/hand/headers.hpp> |
|
#include <openpose/pose/headers.hpp> |
|
#include <openpose/producer/headers.hpp> |
|
#include <openpose/utilities/errorAndLog.hpp> |
|
#include <openpose/utilities/fileSystem.hpp> |
|
namespace op |
|
{ |
|
template<typename TDatum, typename TDatums, typename TWorker, typename TQueue> |
|
WrapperHandFromJsonTest<TDatum, TDatums, TWorker, TQueue>::WrapperHandFromJsonTest() |
|
{ |
|
} |
|
|
|
template<typename TDatum, typename TDatums, typename TWorker, typename TQueue> |
|
WrapperHandFromJsonTest<TDatum, TDatums, TWorker, TQueue>::~WrapperHandFromJsonTest() |
|
{ |
|
try |
|
{ |
|
mThreadManager.stop(); |
|
reset(); |
|
} |
|
catch (const std::exception& e) |
|
{ |
|
errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__); |
|
} |
|
} |
|
|
|
template<typename TDatum, typename TDatums, typename TWorker, typename TQueue> |
|
void WrapperHandFromJsonTest<TDatum, TDatums, TWorker, TQueue>::configure( |
|
const WrapperStructPose& wrapperStructPose, |
|
const WrapperStructHand& wrapperStructHand, |
|
const std::shared_ptr<Producer>& producerSharedPtr, |
|
const std::string& handGroundTruth, |
|
const std::string& writeJson, |
|
const DisplayMode displayMode) |
|
{ |
|
try |
|
{ |
|
opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); |
|
|
|
|
|
typedef std::shared_ptr<TDatums> TDatumsPtr; |
|
|
|
|
|
if (wrapperStructPose.scaleGap <= 0.f && wrapperStructPose.scalesNumber > 1) |
|
error("The scale gap must be greater than 0 (it has no effect if the number of scales is 1).", |
|
__LINE__, __FUNCTION__, __FILE__); |
|
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 = !writeJson.empty(); |
|
const auto displayGui = (displayMode != DisplayMode::NoDisplay); |
|
if (!displayGui && !savingSomething) |
|
{ |
|
const auto message = "No output is selected (`--display 0`) and no results are generated (no `write_X` flags enabled). Thus," |
|
" no output would be generated." + additionalMessage; |
|
error(message, __LINE__, __FUNCTION__, __FILE__); |
|
} |
|
|
|
|
|
auto gpuNumber = wrapperStructPose.gpuNumber; |
|
auto gpuNumberStart = wrapperStructPose.gpuNumberStart; |
|
|
|
if (gpuNumber < 0) |
|
{ |
|
|
|
gpuNumber = getGpuNumber(); |
|
|
|
gpuNumberStart = 0; |
|
|
|
opLog("Auto-detecting GPUs... Detected " + std::to_string(gpuNumber) + " GPU(s), using them all.", Priority::High); |
|
} |
|
|
|
|
|
const auto writeJsonCleaned = formatAsDirectory(writeJson); |
|
|
|
|
|
const auto finalOutputSize = wrapperStructPose.outputSize; |
|
const Point<int> producerSize{ |
|
(int)producerSharedPtr->get(getCvCapPropFrameWidth()), |
|
(int)producerSharedPtr->get(getCvCapPropFrameHeight())}; |
|
if (finalOutputSize.x == -1 || finalOutputSize.y == -1) |
|
{ |
|
const auto message = "Output resolution cannot be (-1 x -1) unless producerSharedPtr is also set."; |
|
error(message, __LINE__, __FUNCTION__, __FILE__); |
|
} |
|
|
|
|
|
const auto datumProducer = std::make_shared<DatumProducer<TDatum>>(producerSharedPtr); |
|
wDatumProducer = std::make_shared<WDatumProducer<TDatum>>(datumProducer); |
|
|
|
|
|
const auto scaleAndSizeExtractor = std::make_shared<ScaleAndSizeExtractor>( |
|
wrapperStructPose.netInputSize, (float)wrapperStructPose.netInputSizeDynamicBehavior, finalOutputSize, |
|
wrapperStructPose.scalesNumber, wrapperStructPose.scaleGap); |
|
spWScaleAndSizeExtractor = std::make_shared<WScaleAndSizeExtractor<TDatumsPtr>>(scaleAndSizeExtractor); |
|
|
|
|
|
const auto cvMatToOpInput = std::make_shared<CvMatToOpInput>(wrapperStructPose.poseModel); |
|
spWCvMatToOpInput = std::make_shared<WCvMatToOpInput<TDatumsPtr>>(cvMatToOpInput); |
|
if (displayGui) |
|
{ |
|
const auto cvMatToOpOutput = std::make_shared<CvMatToOpOutput>(); |
|
spWCvMatToOpOutput = std::make_shared<WCvMatToOpOutput<TDatumsPtr>>(cvMatToOpOutput); |
|
} |
|
|
|
|
|
if (wrapperStructHand.enable) |
|
{ |
|
spWPoses.resize(gpuNumber); |
|
const auto handDetector = std::make_shared<HandDetectorFromTxt>(handGroundTruth); |
|
for (auto gpuId = 0u; gpuId < spWPoses.size(); gpuId++) |
|
{ |
|
|
|
|
|
if (wrapperStructHand.detector == Detector::BodyWithTracking) |
|
error("Tracking not valid for hand detector from JSON files.", __LINE__, __FUNCTION__, __FILE__); |
|
|
|
else |
|
spWPoses.at(gpuId) = {std::make_shared<WHandDetectorFromTxt<TDatumsPtr>>(handDetector)}; |
|
|
|
const auto netOutputSize = wrapperStructHand.netInputSize; |
|
const auto handExtractor = std::make_shared<HandExtractorCaffe>( |
|
wrapperStructHand.netInputSize, netOutputSize, wrapperStructPose.modelFolder.getStdString(), |
|
gpuId + gpuNumberStart, wrapperStructHand.scalesNumber, wrapperStructHand.scaleRange |
|
); |
|
spWPoses.at(gpuId).emplace_back(std::make_shared<WHandExtractorNet<TDatumsPtr>>(handExtractor)); |
|
} |
|
} |
|
|
|
|
|
std::vector<TWorker> cpuRenderers; |
|
if (displayGui) |
|
{ |
|
|
|
const auto handRenderer = std::make_shared<HandCpuRenderer>(wrapperStructHand.renderThreshold, |
|
wrapperStructHand.alphaKeypoint, |
|
wrapperStructHand.alphaHeatMap); |
|
|
|
cpuRenderers.emplace_back(std::make_shared<WHandRenderer<TDatumsPtr>>(handRenderer)); |
|
} |
|
|
|
|
|
mPostProcessingWs.clear(); |
|
|
|
if (spWPoses.size() > 1) |
|
mPostProcessingWs.emplace_back(std::make_shared<WQueueOrderer<TDatumsPtr>>()); |
|
|
|
if (displayGui) |
|
{ |
|
mPostProcessingWs = mergeWorkers(mPostProcessingWs, cpuRenderers); |
|
const auto opOutputToCvMat = std::make_shared<OpOutputToCvMat>(); |
|
mPostProcessingWs.emplace_back(std::make_shared<WOpOutputToCvMat<TDatumsPtr>>(opOutputToCvMat)); |
|
} |
|
|
|
if (wrapperStructPose.keypointScaleMode != ScaleMode::InputResolution) |
|
error("Only wrapperStructPose.keypointScaleMode == ScaleMode::InputResolution.", |
|
__LINE__, __FUNCTION__, __FILE__); |
|
|
|
mOutputWs.clear(); |
|
|
|
if (!writeJsonCleaned.empty()) |
|
{ |
|
const auto jsonSaver = std::make_shared<PeopleJsonSaver>(writeJsonCleaned); |
|
mOutputWs.emplace_back(std::make_shared<WPeopleJsonSaver<TDatumsPtr>>(jsonSaver)); |
|
} |
|
|
|
spWGui = nullptr; |
|
if (displayGui) |
|
{ |
|
const auto guiInfoAdder = std::make_shared<GuiInfoAdder>(gpuNumber, displayGui); |
|
mOutputWs.emplace_back(std::make_shared<WGuiInfoAdder<TDatumsPtr>>(guiInfoAdder)); |
|
const auto gui = std::make_shared<Gui>( |
|
finalOutputSize, false, mThreadManager.getIsRunningSharedPtr() |
|
); |
|
spWGui = {std::make_shared<WGui<TDatumsPtr>>(gui)}; |
|
} |
|
opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); |
|
} |
|
catch (const std::exception& e) |
|
{ |
|
error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
|
} |
|
} |
|
|
|
template<typename TDatum, typename TDatums, typename TWorker, typename TQueue> |
|
void WrapperHandFromJsonTest<TDatum, TDatums, TWorker, TQueue>::exec() |
|
{ |
|
try |
|
{ |
|
configureThreadManager(); |
|
mThreadManager.exec(); |
|
} |
|
catch (const std::exception& e) |
|
{ |
|
error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
|
} |
|
} |
|
|
|
template<typename TDatum, typename TDatums, typename TWorker, typename TQueue> |
|
void WrapperHandFromJsonTest<TDatum, TDatums, TWorker, TQueue>::reset() |
|
{ |
|
try |
|
{ |
|
mThreadManager.reset(); |
|
|
|
wDatumProducer = nullptr; |
|
spWScaleAndSizeExtractor = nullptr; |
|
spWCvMatToOpInput = nullptr; |
|
spWCvMatToOpOutput = nullptr; |
|
spWPoses.clear(); |
|
mPostProcessingWs.clear(); |
|
mOutputWs.clear(); |
|
spWGui = nullptr; |
|
} |
|
catch (const std::exception& e) |
|
{ |
|
error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
|
} |
|
} |
|
|
|
template<typename TDatum, typename TDatums, typename TWorker, typename TQueue> |
|
void WrapperHandFromJsonTest<TDatum, TDatums, TWorker, TQueue>::configureThreadManager() |
|
{ |
|
try |
|
{ |
|
|
|
if (spWCvMatToOpInput == nullptr) |
|
error("Configure the WrapperHandFromJsonTest class before calling `start()`.", |
|
__LINE__, __FUNCTION__, __FILE__); |
|
if (wDatumProducer == nullptr) |
|
{ |
|
const auto message = "You need to use the OpenPose default producer."; |
|
error(message, __LINE__, __FUNCTION__, __FILE__); |
|
} |
|
if (mOutputWs.empty() && spWGui == nullptr) |
|
{ |
|
error("No output selected.", __LINE__, __FUNCTION__, __FILE__); |
|
} |
|
|
|
|
|
|
|
mThreadManager.reset(); |
|
auto threadId = 0ull; |
|
auto queueIn = 0ull; |
|
auto queueOut = 1ull; |
|
|
|
spWIdGenerator = std::make_shared<WIdGenerator<std::shared_ptr<TDatums>>>(); |
|
|
|
|
|
if (spWCvMatToOpOutput == nullptr) |
|
mThreadManager.add(threadId++, {wDatumProducer, spWIdGenerator, spWScaleAndSizeExtractor, |
|
spWCvMatToOpInput}, queueIn++, queueOut++); |
|
else |
|
mThreadManager.add(threadId++, {wDatumProducer, spWIdGenerator, spWScaleAndSizeExtractor, |
|
spWCvMatToOpInput, spWCvMatToOpOutput}, queueIn++, queueOut++); |
|
|
|
|
|
if (!spWPoses.empty()) |
|
{ |
|
for (auto& wPose : spWPoses) |
|
mThreadManager.add(threadId++, wPose, queueIn, queueOut); |
|
queueIn++; |
|
queueOut++; |
|
} |
|
|
|
|
|
|
|
mThreadManager.add(threadId++, mergeWorkers(mPostProcessingWs, mOutputWs), queueIn++, queueOut++); |
|
|
|
|
|
if (spWGui != nullptr) |
|
mThreadManager.add(threadId++, spWGui, queueIn++, queueOut++); |
|
opLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); |
|
} |
|
catch (const std::exception& e) |
|
{ |
|
error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
|
} |
|
} |
|
|
|
template<typename TDatum, typename TDatums, typename TWorker, typename TQueue> |
|
std::vector<TWorker> WrapperHandFromJsonTest<TDatum, TDatums, TWorker, TQueue>::mergeWorkers(const std::vector<TWorker>& workersA, const std::vector<TWorker>& workersB) |
|
{ |
|
try |
|
{ |
|
auto workersToReturn(workersA); |
|
for (auto& worker : workersB) |
|
workersToReturn.emplace_back(worker); |
|
return workersToReturn; |
|
} |
|
catch (const std::exception& e) |
|
{ |
|
error(e.what(), __LINE__, __FUNCTION__, __FILE__); |
|
return std::vector<TWorker>{}; |
|
} |
|
} |
|
} |
|
|
|
#endif |
|
|