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

Replaced Nms by Maximum in Face

上级 91e466fe
......@@ -118,6 +118,4 @@ html/
*.mov
######################### Validation Scripts & Testing #########################
*validation.sh
validation*.sh
output*/
......@@ -18,7 +18,7 @@ OpenPose is a **library for real-time multi-person keypoint detection and multi-
OpenPose represents the **first real-time system to jointly detect human body, hand and facial keypoints (in total 130 keypoints) on single images**. In addition, the system computational performance on body keypoint estimation is invariant to the number of detected people in the image.
OpenPose is freely available for free non-commercial use, and may be redistributed under these conditions. Please, see the [license](LICENSE) for further details. Contact us for commercial purposes.
OpenPose is freely available for free non-commercial use, and may be redistributed under these conditions. Please, see the [license](LICENSE) for further details. Contact [Yaser Sheikh](http://www.cs.cmu.edu/~yaser/) for commercial purposes.
......@@ -77,7 +77,7 @@ The pose estimation work is based on the C++ code from [the ECCV 2016 demo](http
2. [OpenPose Wrapper](#openpose-wrapper)
3. [OpenPose Library](#openpose-library)
4. [Output](#output)
5. [OpenPose Benchmark](#openpose-benchmark)
5. [Speed Up Openpose And Benchmark](#speed-up-openpose-and-benchmark)
6. [Send Us Your Feedback!](#send-us-your-feedback)
7. [Citation](#citation)
8. [Other Contributors](#other-contributors)
......@@ -191,6 +191,4 @@ Please cite the papers in your publications if it helps your research:
## Other Contributors
We would like to thank the following people who also contributed to OpenPose:
1. [Helen Medina](https://github.com/helen-medina): For moving OpenPose to Windows (Visual Studio), making it work there and creating the Windows branch.
We would like to thank all the people who helped OpenPose in any way. The main contributors are listed in [doc/contributors.md](doc/contributors.md).
......@@ -44,18 +44,30 @@ OpenPose Library - Release Notes
## Current version (future OpenPose 1.0.0rc4)
## OpenPose 1.0.0
1. Main improvements:
1. Increased accuracy on multi-scale (added `Datum::scaleRatios` to save the relative scale ratio when multi-scale).
2. Increased speed ~3-5% by adding CPU rendering and setting it as default rendering.
3. Check() functions give more feedback.
4. WCocoJsonSaver finished and removed its 3599-image limit.
5. Added `camera_fps` so generated video will use that frame rate.
6. Improved documentation.
1. Hands and face now use `Maximum` instead of `Nms`, since there is only 1 person / detection.
2. Increased accuracy on multi-scale (added `Datum::scaleRatios` to save the relative scale ratio when multi-scale).
3. Increased speed ~5% by adding CPU rendering (but GPU is the default rendering).
4. Rendering colors modified, visually better results.
5. Check() functions give more feedback.
6. WCocoJsonSaver finished and removed its 3599-image limit.
7. Added `camera_fps` so generated video will use that frame rate.
8. Reduced the number of printed information messages. Default logging priority threshold increased to Priority::Max.
9. Google flags to OpenPose configuration parameters reader moved from each demo to utilities/flagsToOpenPose.
10. Nms classes do not use `numberParts` for `Reshape`, they deduce the value.
11. Improved documentation.
2. Functions or parameters renamed:
1. Render flags renamed in the demo in order to incorporate the CPU/GPU rendering.
2. Keypoints saved in JSON files (`write_keypoint_json`) are now saved as `pose_keypoints`, `face_keypoints`, `hand_left_keypoints`, and `hand_right_keypoints`. They all were previously saved as `body_parts`.
3. Main bugs fixed:
1. Fixed bug in Array::getConstCvMat() if mVolume=0, now returning empty cv::Mat.
2. Fixed bug: `--process_real_time` threw error with webcam.
3. Fixed bug: Face not working when input and output resolutions are different.
4. Fixed some bugs that prevented debug version to run.
5. Face saved in JSON files were called `body_parts`. Now they are called `face_keypoints`.
## Current version (future OpenPose 1.0.1)
1. No changes yet.
......@@ -16,7 +16,6 @@
// This file should only be used for the user to take specific examples.
// C++ std library dependencies
#include <atomic>
#include <chrono> // `std::chrono::` functions and classes, e.g. std::chrono::milliseconds
#include <string>
#include <thread> // std::this_thread
......@@ -187,10 +186,12 @@ int openPoseDemo()
op::log("Configuring OpenPose wrapper.", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__);
op::Wrapper<std::vector<op::Datum>> opWrapper;
// Pose configuration (use WrapperStructPose{} for default and recommended configuration)
const op::WrapperStructPose wrapperStructPose{netInputSize, outputSize, keypointScale, FLAGS_num_gpu, FLAGS_num_gpu_start,
FLAGS_num_scales, (float)FLAGS_scale_gap, op::flagsToRenderMode(FLAGS_render_pose), poseModel,
!FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap,
FLAGS_part_to_show, FLAGS_model_folder, heatMapTypes, op::ScaleMode::UnsignedChar};
const op::WrapperStructPose wrapperStructPose{netInputSize, outputSize, keypointScale, FLAGS_num_gpu,
FLAGS_num_gpu_start, FLAGS_num_scales, (float)FLAGS_scale_gap,
op::flagsToRenderMode(FLAGS_render_pose), poseModel,
!FLAGS_disable_blending, (float)FLAGS_alpha_pose,
(float)FLAGS_alpha_heatmap, FLAGS_part_to_show, FLAGS_model_folder,
heatMapTypes, op::ScaleMode::UnsignedChar};
// Face configuration (use op::WrapperStructFace{} to disable it)
const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, op::flagsToRenderMode(FLAGS_render_face, FLAGS_render_pose),
(float)FLAGS_alpha_face, (float)FLAGS_alpha_heatmap_face};
......
......@@ -259,10 +259,12 @@ int openPoseTutorialWrapper1()
// Configure OpenPose
op::Wrapper<std::vector<UserDatum>> opWrapper{op::ThreadManagerMode::Asynchronous};
// Pose configuration (use WrapperStructPose{} for default and recommended configuration)
const op::WrapperStructPose wrapperStructPose{netInputSize, outputSize, keypointScale, FLAGS_num_gpu, FLAGS_num_gpu_start,
FLAGS_num_scales, (float)FLAGS_scale_gap, op::flagsToRenderMode(FLAGS_render_pose), poseModel,
!FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap,
FLAGS_part_to_show, FLAGS_model_folder, heatMapTypes, heatMapScale};
const op::WrapperStructPose wrapperStructPose{netInputSize, outputSize, keypointScale, FLAGS_num_gpu,
FLAGS_num_gpu_start, FLAGS_num_scales, (float)FLAGS_scale_gap,
op::flagsToRenderMode(FLAGS_render_pose), poseModel,
!FLAGS_disable_blending, (float)FLAGS_alpha_pose,
(float)FLAGS_alpha_heatmap, FLAGS_part_to_show, FLAGS_model_folder,
heatMapTypes, heatMapScale};
// Face configuration (use op::WrapperStructFace{} to disable it)
const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, op::flagsToRenderMode(FLAGS_render_face, FLAGS_render_pose),
(float)FLAGS_alpha_face, (float)FLAGS_alpha_heatmap_face};
......
......@@ -320,10 +320,12 @@ int openPoseTutorialWrapper2()
const auto workerOutputOnNewThread = true;
opWrapper.setWorkerOutput(wUserOutput, workerOutputOnNewThread);
// Configure OpenPose
const op::WrapperStructPose wrapperStructPose{netInputSize, outputSize, keypointScale, FLAGS_num_gpu, FLAGS_num_gpu_start,
FLAGS_num_scales, (float)FLAGS_scale_gap, op::flagsToRenderMode(FLAGS_render_pose), poseModel,
!FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap,
FLAGS_part_to_show, FLAGS_model_folder, heatMapTypes, heatMapScale};
const op::WrapperStructPose wrapperStructPose{netInputSize, outputSize, keypointScale, FLAGS_num_gpu,
FLAGS_num_gpu_start, FLAGS_num_scales, (float)FLAGS_scale_gap,
op::flagsToRenderMode(FLAGS_render_pose), poseModel,
!FLAGS_disable_blending, (float)FLAGS_alpha_pose,
(float)FLAGS_alpha_heatmap, FLAGS_part_to_show, FLAGS_model_folder,
heatMapTypes, heatMapScale};
// Face configuration (use op::WrapperStructFace{} to disable it)
const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, op::flagsToRenderMode(FLAGS_render_face, FLAGS_render_pose),
(float)FLAGS_alpha_face, (float)FLAGS_alpha_heatmap_face};
......
#ifndef OPENPOSE_CORE_MAXIMUM_BASE_HPP
#define OPENPOSE_CORE_MAXIMUM_BASE_HPP
#include <array>
namespace op
{
template <typename T>
void maximumCpu(T* targetPtr, const T* const sourcePtr, const std::array<int, 4>& targetSize, const std::array<int, 4>& sourceSize);
template <typename T>
void maximumGpu(T* targetPtr, const T* const sourcePtr, const std::array<int, 4>& targetSize, const std::array<int, 4>& sourceSize);
}
#endif // OPENPOSE_CORE_MAXIMUM_BASE_HPP
#ifdef USE_CAFFE
#ifndef OPENPOSE_CORE_MAXIMUM_CAFFE_HPP
#define OPENPOSE_CORE_MAXIMUM_CAFFE_HPP
#include <array>
#include "caffe/blob.hpp"
namespace op
{
// It mostly follows the Caffe::layer implementation, so Caffe users can easily use it. However, in order to keep the compatibility with any generic Caffe version,
// we keep this 'layer' inside our library rather than in the Caffe code.
template <typename T>
class MaximumCaffe
{
public:
explicit MaximumCaffe();
virtual void LayerSetUp(const std::vector<caffe::Blob<T>*>& bottom, const std::vector<caffe::Blob<T>*>& top);
virtual void Reshape(const std::vector<caffe::Blob<T>*>& bottom, const std::vector<caffe::Blob<T>*>& top);
virtual inline const char* type() const { return "Maximum"; }
virtual void Forward_cpu(const std::vector<caffe::Blob<T>*>& bottom, const std::vector<caffe::Blob<T>*>& top);
virtual void Forward_gpu(const std::vector<caffe::Blob<T>*>& bottom, const std::vector<caffe::Blob<T>*>& top);
virtual void Backward_cpu(const std::vector<caffe::Blob<T>*>& top, const std::vector<bool>& propagate_down, const std::vector<caffe::Blob<T>*>& bottom);
virtual void Backward_gpu(const std::vector<caffe::Blob<T>*>& top, const std::vector<bool>& propagate_down, const std::vector<caffe::Blob<T>*>& bottom);
private:
std::array<int, 4> mBottomSize;
std::array<int, 4> mTopSize;
};
}
#endif // OPENPOSE_CORE_MAXIMUM_CAFFE_HPP
#endif
......@@ -17,7 +17,7 @@ namespace op
virtual void LayerSetUp(const std::vector<caffe::Blob<T>*>& bottom, const std::vector<caffe::Blob<T>*>& top);
virtual void Reshape(const std::vector<caffe::Blob<T>*>& bottom, const std::vector<caffe::Blob<T>*>& top, const int maxPeaks, const int numberParts);
virtual void Reshape(const std::vector<caffe::Blob<T>*>& bottom, const std::vector<caffe::Blob<T>*>& top, const int maxPeaks);
virtual inline const char* type() const { return "Nms"; }
......
#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
......@@ -6,7 +6,6 @@
#include <openpose/core/rectangle.hpp>
#include <openpose/pose/enumClasses.hpp>
#include <openpose/utilities/macros.hpp>
#include "enumClasses.hpp"
namespace op
{
......
......@@ -7,11 +7,10 @@
#include <thread>
#include <opencv2/core/core.hpp> // cv::Mat
#include <openpose/core/array.hpp>
#include <openpose/core/maximumCaffe.hpp>
#include <openpose/core/net.hpp>
#include <openpose/core/nmsCaffe.hpp>
#include <openpose/core/rectangle.hpp>
#include <openpose/core/resizeAndMergeCaffe.hpp>
#include "enumClasses.hpp"
namespace op
{
......@@ -26,19 +25,12 @@ namespace op
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 Point<int> mNetOutputSize;
const Point<int> mOutputSize;
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;
std::shared_ptr<MaximumCaffe<float>> spMaximumCaffe;
Array<float> mFaceImageCrop;
Array<float> mFaceKeypoints;
// Init with thread
......
#ifndef OPENPOSE_FACE_FACE_PARAMETERS_HPP
#define OPENPOSE_FACE_FACE_PARAMETERS_HPP
#include "enumClasses.hpp"
#include <openpose/pose/poseParameters.hpp>
namespace op
......@@ -18,14 +17,9 @@ namespace op
// Constant parameters
const auto FACE_CCN_DECREASE_FACTOR = 8.f;
const auto 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 parameters
const auto FACE_DEFAULT_ALPHA_KEYPOINT = POSE_DEFAULT_ALPHA_KEYPOINT;
const auto FACE_DEFAULT_ALPHA_HEAT_MAP = POSE_DEFAULT_ALPHA_HEAT_MAP;
......
......@@ -2,7 +2,6 @@
#define OPENPOSE_FACE_HEADERS_HPP
// face module
#include "enumClasses.hpp"
#include "faceDetector.hpp"
#include "faceExtractor.hpp"
#include "faceParameters.hpp"
......
#ifndef OPENPOSE_FILESTREAM_FILE_STREAM_HPP
#define OPENPOSE_FILESTREAM_FILE_STREAM_HPP
#include <array>
#include <string>
#include <vector>
#include <opencv2/core/core.hpp> // cv::Mat
#include <opencv2/highgui/highgui.hpp> // CV_LOAD_IMAGE_ANYDEPTH, CV_IMWRITE_PNG_COMPRESSION
#include <openpose/core/array.hpp>
#include <openpose/core/rectangle.hpp>
#include "enumClasses.hpp"
namespace op
......@@ -31,6 +33,8 @@ namespace op
void saveImage(const cv::Mat& cvMat, const std::string& fullFilePath, const std::vector<int>& openCvCompressionParams = {CV_IMWRITE_JPEG_QUALITY, 100, CV_IMWRITE_PNG_COMPRESSION, 9});
cv::Mat loadImage(const std::string& fullFilePath, const int openCvFlags = CV_LOAD_IMAGE_ANYDEPTH);
std::vector<std::array<Rectangle<float>, 2>> loadHandDetectorTxt(const std::string& txtFilePath);
}
#endif // OPENPOSE_FILESTREAM_FILE_STREAM_HPP
#ifndef OPENPOSE_HAND_ENUM_CLASSES_HPP
#define OPENPOSE_HAND_ENUM_CLASSES_HPP
namespace op
{
enum class HandProperty : bool
{
NMSThreshold = 0,
Size,
};
}
#endif // OPENPOSE_HAND_ENUM_CLASSES_HPP
......@@ -9,7 +9,6 @@
#include <openpose/core/rectangle.hpp>
#include <openpose/pose/enumClasses.hpp>
#include <openpose/utilities/macros.hpp>
#include "enumClasses.hpp"
namespace op
{
......
#ifndef OPENPOSE_HAND_HAND_DETECTOR_FROM_TXT_HPP
#define OPENPOSE_HAND_HAND_DETECTOR_FROM_TXT_HPP
#include <array>
#include <string>
#include <vector>
#include <openpose/core/array.hpp>
#include <openpose/pose/enumClasses.hpp>
#include <openpose/utilities/macros.hpp>
namespace op
{
class HandDetectorFromTxt
{
public:
explicit HandDetectorFromTxt(const std::string& txtDirectoryPath);
std::vector<std::array<Rectangle<float>, 2>> detectHands();
private:
const std::string mTxtDirectoryPath;
const std::vector<std::string> mFilePaths;
long long mFrameNameCounter;
DELETE_COPY(HandDetectorFromTxt);
};
}
#endif // OPENPOSE_HAND_HAND_DETECTOR_FROM_TXT_HPP
......@@ -8,12 +8,11 @@
#include <opencv2/core/core.hpp> // cv::Mat
#include <openpose/core/array.hpp>
#include <openpose/core/point.hpp>
#include <openpose/core/maximumCaffe.hpp>
#include <openpose/core/net.hpp>
#include <openpose/core/nmsCaffe.hpp>
#include <openpose/core/rectangle.hpp>
#include <openpose/core/resizeAndMergeCaffe.hpp>
#include <openpose/utilities/macros.hpp>
#include "enumClasses.hpp"
namespace op
{
......@@ -30,19 +29,12 @@ namespace op
std::array<Array<float>, 2> getHandKeypoints() const;
double get(const HandProperty property) const;
void set(const HandProperty property, const double value);
void increase(const HandProperty property, const double value);
private:
const bool mIterativeDetection;
const Point<int> mNetOutputSize;
std::array<std::atomic<double>, (int)HandProperty::Size> mProperties;
std::shared_ptr<Net> spNet;
std::shared_ptr<ResizeAndMergeCaffe<float>> spResizeAndMergeCaffe;
std::shared_ptr<NmsCaffe<float>> spNmsCaffe;
std::shared_ptr<MaximumCaffe<float>> spMaximumCaffe;
Array<float> mHandImageCrop;
std::array<Array<float>, 2> mHandKeypoints;
// Init with thread
......@@ -53,8 +45,7 @@ namespace op
void checkThread() const;
void detectHandKeypoints(Array<float>& handCurrent, const float scaleInputToOutput, const int person, const cv::Mat& affineMatrix,
const unsigned int handPeaksOffset);
void detectHandKeypoints(Array<float>& handCurrent, const float scaleInputToOutput, const int person, const cv::Mat& affineMatrix);
DELETE_COPY(HandExtractor);
};
......
#ifndef OPENPOSE_HAND_HAND_PARAMETERS_HPP
#define OPENPOSE_HAND_HAND_PARAMETERS_HPP
#include "enumClasses.hpp"
#include <openpose/pose/poseParameters.hpp>
namespace op
......@@ -36,14 +35,9 @@ namespace op
// Constant parameters
const auto HAND_CCN_DECREASE_FACTOR = 8.f;
const auto 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 parameters
const auto HAND_DEFAULT_ALPHA_KEYPOINT = POSE_DEFAULT_ALPHA_KEYPOINT;
const auto HAND_DEFAULT_ALPHA_HEAT_MAP = POSE_DEFAULT_ALPHA_HEAT_MAP;
......
......@@ -2,13 +2,14 @@
#define OPENPOSE_HAND_HEADERS_HPP
// hand module
#include "enumClasses.hpp"
#include "handDetector.hpp"
#include "handDetectorFromTxt.hpp"
#include "handExtractor.hpp"
#include "handParameters.hpp"
#include "handRenderer.hpp"
#include "renderHand.hpp"
#include "wHandDetector.hpp"
#include "wHandDetectorFromTxt.hpp"
#include "wHandDetectorTracking.hpp"
#include "wHandDetectorUpdate.hpp"
#include "wHandExtractor.hpp"
......
......@@ -3,7 +3,7 @@
#include <memory> // std::shared_ptr
#include <openpose/thread/worker.hpp>
#include "handRenderer.hpp"
#include "handDetector.hpp"
namespace op
{
......
#ifndef OPENPOSE_HAND_W_HAND_DETECTOR_FROM_JSON_HPP
#define OPENPOSE_HAND_W_HAND_DETECTOR_FROM_JSON_HPP
#include <memory> // std::shared_ptr
#include <openpose/thread/worker.hpp>
#include "handDetectorFromTxt.hpp"
namespace op
{
template<typename TDatums>
class WHandDetectorFromTxt : public Worker<TDatums>
{
public:
explicit WHandDetectorFromTxt(const std::shared_ptr<HandDetectorFromTxt>& handDetectorFromTxt);
void initializationOnThread();
void work(TDatums& tDatums);
private:
std::shared_ptr<HandDetectorFromTxt> spHandDetectorFromTxt;
DELETE_COPY(WHandDetectorFromTxt);
};
}
// Implementation
#include <openpose/utilities/errorAndLog.hpp>
#include <openpose/utilities/macros.hpp>
#include <openpose/utilities/pointerContainer.hpp>
#include <openpose/utilities/profiler.hpp>
namespace op
{
template<typename TDatums>
WHandDetectorFromTxt<TDatums>::WHandDetectorFromTxt(const std::shared_ptr<HandDetectorFromTxt>& handDetectorFromTxt) :
spHandDetectorFromTxt{handDetectorFromTxt}
{
}
template<typename TDatums>
void WHandDetectorFromTxt<TDatums>::initializationOnThread()
{
}
template<typename TDatums>
void WHandDetectorFromTxt<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__);
// Detect people hand
for (auto& tDatum : *tDatums)
tDatum.handRectangles = spHandDetectorFromTxt->detectHands();
// Profiling speed
Profiler::timerEnd(profilerKey);
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, Profiler::DEFAULT_X);
// 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(WHandDetectorFromTxt);
}
#endif // OPENPOSE_HAND_W_HAND_DETECTOR_FROM_JSON_HPP
......@@ -2,6 +2,7 @@
#define OPENPOSE_UTILITIES_FILE_SYSTEM_HPP
#include <string>
#include <vector>
namespace op
{
......
#ifndef OPENPOSE_UTILITIES_G_FLAGS_TO_OPEN_POSE_HPP
#define OPENPOSE_UTILITIES_G_FLAGS_TO_OPEN_POSE_HPP
#ifndef OPENPOSE_UTILITIES_FLAGS_TO_OPEN_POSE_HPP
#define OPENPOSE_UTILITIES_FLAGS_TO_OPEN_POSE_HPP
#include <memory> // std::shared_ptr
#include <string>
......@@ -19,9 +19,11 @@ namespace op
ProducerType flagsToProducerType(const std::string& imageDirectory, const std::string& videoPath, const int webcamIndex);
std::shared_ptr<Producer> flagsToProducer(const std::string& imageDirectory, const std::string& videoPath,
const int webcamIndex, const std::string& webcamResolution, const double webcamFps);
const int webcamIndex, const std::string& webcamResolution = "1280x720",
const double webcamFps = 30.);
std::vector<HeatMapType> flagsToHeatMaps(const bool heatMapsAddParts, const bool heatMapsAddBkg, const bool heatMapsAddPAFs);
std::vector<HeatMapType> flagsToHeatMaps(const bool heatMapsAddParts = false, const bool heatMapsAddBkg = false,
const bool heatMapsAddPAFs = false);
DetectionMode flagsToDetectionMode(const int handDetectionModeFlag, const std::shared_ptr<Producer>& producer = nullptr);
......@@ -30,4 +32,4 @@ namespace op
Point<int> flagsToPoint(const std::string& pointString, const std::string& pointExample = "1280x720");
}
#endif // OPENPOSE_UTILITIES_G_FLAGS_TO_OPEN_POSE_HPP
#endif // OPENPOSE_UTILITIES_FLAGS_TO_OPEN_POSE_HPP
......@@ -2,6 +2,7 @@
#define OPENPOSE_UTILITIES_STRING_HPP
#include <string>
#include <vector>
namespace op
{
......@@ -14,6 +15,8 @@ namespace op
*/
template<typename T>
std::string toFixedLengthString(const T number, const unsigned long long stringLength = 0);
std::vector<std::string> splitString(const std::string& stringToSplit, const std::string& delimiter);
}
#endif // OPENPOSE_UTILITIES_STRING_HPP
......@@ -24,7 +24,9 @@ namespace op
* - Asynchronous input + synchronous output: call the constructor
* Wrapper(ThreadManagerMode::Synchronous, nullptr, workersOutput, irrelevantBoolean, true)
*/
template<typename TDatums, typename TWorker = std::shared_ptr<Worker<std::shared_ptr<TDatums>>>, typename TQueue = Queue<std::shared_ptr<TDatums>>>
template<typename TDatums,
typename TWorker = std::shared_ptr<Worker<std::shared_ptr<TDatums>>>,
typename TQueue = Queue<std::shared_ptr<TDatums>>>
class Wrapper
{
public:
......@@ -201,7 +203,7 @@ namespace op
bool mUserInputWsOnNewThread;
bool mUserPostProcessingWsOnNewThread;
bool mUserOutputWsOnNewThread;
unsigned int mThreadId;
unsigned long long mThreadId;
bool mMultiThreadEnabled;
// Workers
std::vector<TWorker> mUserInputWs;
......@@ -535,7 +537,7 @@ namespace op
wrapperStructInput.producerSharedPtr->set(ProducerProperty::AutoRepeat, wrapperStructInput.framesRepeat);
// 2. Set finalOutputSize
producerSize = Point<int>{(int)wrapperStructInput.producerSharedPtr->get(CV_CAP_PROP_FRAME_WIDTH),
(int)wrapperStructInput.producerSharedPtr->get(CV_CAP_PROP_FRAME_HEIGHT)};
(int)wrapperStructInput.producerSharedPtr->get(CV_CAP_PROP_FRAME_HEIGHT)};
if (wrapperStructPose.outputSize.x == -1 || wrapperStructPose.outputSize.y == -1)
{
if (producerSize.area() > 0)
......
......@@ -123,13 +123,17 @@ 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.
*/
WrapperStructPose(const Point<int>& netInputSize = Point<int>{656, 368}, const Point<int>& outputSize = Point<int>{1280, 720},
const ScaleMode keypointScale = ScaleMode::InputResolution, const int gpuNumber = 1, const int gpuNumberStart = 0,
const int scalesNumber = 1, const float scaleGap = 0.15f, const RenderMode renderMode = RenderMode::None,
WrapperStructPose(const Point<int>& netInputSize = Point<int>{656, 368},
const Point<int>& outputSize = Point<int>{1280, 720},
const ScaleMode keypointScale = ScaleMode::InputResolution,
const int gpuNumber = 1, const int gpuNumberStart = 0, const int scalesNumber = 1,
const float scaleGap = 0.15f, const RenderMode renderMode = RenderMode::None,
const PoseModel poseModel = PoseModel::COCO_18, const bool blendOriginalFrame = true,
const float alphaKeypoint = POSE_DEFAULT_ALPHA_KEYPOINT, const float alphaHeatMap = POSE_DEFAULT_ALPHA_HEAT_MAP,
const float alphaKeypoint = POSE_DEFAULT_ALPHA_KEYPOINT,
const float alphaHeatMap = POSE_DEFAULT_ALPHA_HEAT_MAP,
const int defaultPartToRender = 0, const std::string& modelFolder = "models/",
const std::vector<HeatMapType>& heatMapTypes = {}, const ScaleMode heatMapScale = ScaleMode::ZeroToOne);
const std::vector<HeatMapType>& heatMapTypes = {},
const ScaleMode heatMapScale = ScaleMode::ZeroToOne);
};
}
......
#include <openpose/utilities/errorAndLog.hpp>
#include <openpose/utilities/macros.hpp>
#include <openpose/core/maximumBase.hpp>
namespace op
{
template <typename T>
void maximumCpu(T* targetPtr, int* kernelPtr, const T* const sourcePtr, const std::array<int, 4>& targetSize, const std::array<int, 4>& sourceSize)
{
try
{
UNUSED(targetPtr);
UNUSED(kernelPtr);
UNUSED(sourcePtr);
UNUSED(targetSize);
UNUSED(sourceSize);
error("CPU version not completely implemented.", __LINE__, __FUNCTION__, __FILE__);
}
catch (const std::exception& e)
{
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
}
}
template void maximumCpu(float* targetPtr, int* kernelPtr, const float* const sourcePtr, const std::array<int, 4>& targetSize, const std::array<int, 4>& sourceSize);
template void maximumCpu(double* targetPtr, int* kernelPtr, const double* const sourcePtr, const std::array<int, 4>& targetSize, const std::array<int, 4>& sourceSize);
}
#include <thrust/device_ptr.h>
#include <thrust/extrema.h>
#include <openpose/utilities/cuda.hpp>
#include <openpose/utilities/errorAndLog.hpp>
#include <openpose/utilities/cuda.hpp>
#include <openpose/core/maximumBase.hpp>
namespace op
{
template <typename T>
__global__ void fillTargetPtrPart(T* targetPtrOffsetted, const T* sourcePtrOffsetted, const int sourceIndex, const int x, const int y)
{
targetPtrOffsetted[0] = x;
targetPtrOffsetted[1] = y;
targetPtrOffsetted[2] = sourcePtrOffsetted[sourceIndex];
}
// template <typename T>
// __global__ void fillTargetPtrChannel(T* targetPtrOffsetted, const T* sourcePtrOffsetted, const int width, const int imageOffset)
// {
// const auto sourceThrustPtr = thrust::device_pointer_cast(sourcePtrOffsetted);
// const auto sourceIndexIterator = thrust::max_element(thrust::device, sourceThrustPtr, sourceThrustPtr + imageOffset);
// const auto sourceIndex = sourceIndexIterator - sourceThrustPtr;
// targetPtrOffsetted[0] = sourceIndex % width;
// targetPtrOffsetted[1] = sourceIndex / width;
// targetPtrOffsetted[2] = sourcePtrOffsetted[sourceIndex];
// }
// template <typename T>
// __global__ void fillTargetPtr(T* targetPtr, const T* sourcePtr, const int width, const int imageOffset, const int numberSubparts, const int offsetChannel)
// {
// // get pixel location (x,y)
// const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;
// const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;
// const auto part = y*width + x;
// // if (0 < x && x < (w-1) && 0 < y && y < (h-1))
// {
// auto* targetPtrOffsetted = targetPtr + (offsetChannel + part) * numberSubparts;
// 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;
// targetPtrOffsetted[0] = sourceIndex % width;
// targetPtrOffsetted[1] = sourceIndex / width;
// targetPtrOffsetted[2] = sourcePtrOffsetted[sourceIndex];
// }
// }
template <typename T>
void maximumGpu(T* targetPtr, const T* const sourcePtr, const std::array<int, 4>& targetSize, const std::array<int, 4>& sourceSize)
{
try
{
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 sourceThrustPtr = thrust::device_pointer_cast(sourcePtrOffsetted);
const auto sourceIndexIterator = thrust::max_element(thrust::device, sourceThrustPtr, sourceThrustPtr + imageOffset);
const auto sourceIndex = sourceIndexIterator - sourceThrustPtr;
fillTargetPtrPart<<<1, 1>>>(targetPtrOffsetted, sourcePtrOffsetted, sourceIndex, sourceIndex % width, sourceIndex / width);
// // Option b - <1 fps
// fillTargetPtrChannel<<<1, 1>>>(targetPtrOffsetted, sourcePtrOffsetted, width, imageOffset);
}
// Option c - 4.9 fps
// fillTargetPtr<<<1, numberParts>>>(targetPtr, sourcePtr, width, imageOffset, numberSubparts, offsetChannel);
}
}
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
}
catch (const std::exception& e)
{
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
}
}
template void maximumGpu(float* targetPtr, const float* const sourcePtr, const std::array<int, 4>& targetSize, const std::array<int, 4>& sourceSize);
template void maximumGpu(double* targetPtr, const double* const sourcePtr, const std::array<int, 4>& targetSize, const std::array<int, 4>& sourceSize);
}
#ifdef USE_CAFFE
#include <openpose/core/maximumBase.hpp>
#include <openpose/utilities/errorAndLog.hpp>
#include <openpose/utilities/macros.hpp>
#include <openpose/core/maximumCaffe.hpp>
namespace op
{
template <typename T>
MaximumCaffe<T>::MaximumCaffe()
{
}
template <typename T>
void MaximumCaffe<T>::LayerSetUp(const std::vector<caffe::Blob<T>*>& bottom, const std::vector<caffe::Blob<T>*>& top)
{
try
{
if (top.size() != 1)
error("top.size() != 1", __LINE__, __FUNCTION__, __FILE__);
if (bottom.size() != 1)
error("bottom.size() != 1", __LINE__, __FUNCTION__, __FILE__);
}
catch (const std::exception& e)
{
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
}
}
template <typename T>
void MaximumCaffe<T>::Reshape(const std::vector<caffe::Blob<T>*>& bottom, const std::vector<caffe::Blob<T>*>& top)
{
try
{
auto bottomBlob = bottom.at(0);
auto topBlob = top.at(0);
// Bottom shape
std::vector<int> bottomShape = bottomBlob->shape();
// Top shape
std::vector<int> topShape{bottomShape};
topShape[1] = 1; // Unnecessary
topShape[2] = bottomShape[1]-1; // Number parts + bck - 1
topShape[3] = 3; // X, Y, score
topBlob->Reshape(topShape);
// Array sizes
mTopSize = std::array<int, 4>{topBlob->shape(0), topBlob->shape(1), topBlob->shape(2), topBlob->shape(3)};
mBottomSize = std::array<int, 4>{bottomBlob->shape(0), bottomBlob->shape(1), bottomBlob->shape(2), bottomBlob->shape(3)};
}
catch (const std::exception& e)
{
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
}
}
template <typename T>
void MaximumCaffe<T>::Forward_cpu(const std::vector<caffe::Blob<T>*>& bottom, const std::vector<caffe::Blob<T>*>& top)
{
try
{
maximumGpu(top.at(0)->mutable_cpu_data(), bottom.at(0)->cpu_data(), mTopSize, mBottomSize);
}
catch (const std::exception& e)
{
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
}
}
template <typename T>
void MaximumCaffe<T>::Forward_gpu(const std::vector<caffe::Blob<T>*>& bottom, const std::vector<caffe::Blob<T>*>& top)
{
try
{
maximumGpu(top.at(0)->mutable_gpu_data(), bottom.at(0)->gpu_data(), mTopSize, mBottomSize);
}
catch (const std::exception& e)
{
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
}
}
template <typename T>
void MaximumCaffe<T>::Backward_cpu(const std::vector<caffe::Blob<T>*>& top, const std::vector<bool>& propagate_down, const std::vector<caffe::Blob<T>*>& bottom)
{
try
{
UNUSED(top);
UNUSED(propagate_down);
UNUSED(bottom);
NOT_IMPLEMENTED;
}
catch (const std::exception& e)
{
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
}
}
template <typename T>
void MaximumCaffe<T>::Backward_gpu(const std::vector<caffe::Blob<T>*>& top, const std::vector<bool>& propagate_down, const std::vector<caffe::Blob<T>*>& bottom)
{
try
{
UNUSED(top);
UNUSED(propagate_down);
UNUSED(bottom);
NOT_IMPLEMENTED;
}
catch (const std::exception& e)
{
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
}
}
INSTANTIATE_CLASS(MaximumCaffe);
}
#endif
#include <thrust/scan.h>
#include <thrust/device_ptr.h>
#include <thrust/scan.h>
#include <openpose/utilities/cuda.hpp>
#include <openpose/utilities/errorAndLog.hpp>
#include <openpose/utilities/cuda.hpp>
......
......@@ -28,7 +28,7 @@ namespace op
}
template <typename T>
void NmsCaffe<T>::Reshape(const std::vector<caffe::Blob<T>*>& bottom, const std::vector<caffe::Blob<T>*>& top, const int maxPeaks, const int numberParts)
void NmsCaffe<T>::Reshape(const std::vector<caffe::Blob<T>*>& bottom, const std::vector<caffe::Blob<T>*>& top, const int maxPeaks)
{
try
{
......@@ -39,11 +39,11 @@ namespace op
std::vector<int> bottomShape = bottomBlob->shape();
// Top shape
std::vector<int> top_shape{bottomShape};
top_shape[1] = numberParts;
top_shape[2] = maxPeaks+1; // # maxPeaks + 1
top_shape[3] = 3; // X, Y, score
topBlob->Reshape(top_shape);
std::vector<int> topShape{bottomShape};
topShape[1] = bottomShape[1]-1; // Number parts + bck - 1
topShape[2] = maxPeaks+1; // # maxPeaks + 1
topShape[3] = 3; // X, Y, score
topBlob->Reshape(topShape);
mKernelBlob.Reshape(bottomShape);
// Array sizes
......
......@@ -16,7 +16,7 @@ namespace op
spNet{std::make_shared<NetCaffe>(std::array<int,4>{1, 3, mNetOutputSize.y, mNetOutputSize.x}, modelFolder + FACE_PROTOTXT,
modelFolder + FACE_TRAINED_MODEL, gpuId)},
spResizeAndMergeCaffe{std::make_shared<ResizeAndMergeCaffe<float>>()},
spNmsCaffe{std::make_shared<NmsCaffe<float>>()},
spMaximumCaffe{std::make_shared<MaximumCaffe<float>>()},
mFaceImageCrop{mNetOutputSize.area()*3}
{
try
......@@ -24,10 +24,6 @@ namespace op
checkE(netOutputSize.x, netInputSize.x, "Net input and output size must be equal.", __LINE__, __FUNCTION__, __FILE__);
checkE(netOutputSize.y, netInputSize.y, "Net input and output size must be equal.", __LINE__, __FUNCTION__, __FILE__);
checkE(netInputSize.x, netInputSize.y, "Net input size must be squared.", __LINE__, __FUNCTION__, __FILE__);
// Properties
for (auto& property : mProperties)
property = 0.;
mProperties[(int)FaceProperty::NMSThreshold] = FACE_DEFAULT_NMS_THRESHOLD;
}
catch (const std::exception& e)
{
......@@ -57,7 +53,7 @@ namespace op
// 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+1);
spMaximumCaffe->Reshape({spHeatMapsBlob.get()}, {spPeaksBlob.get()});
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
log("Finished initialization on thread.", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
......@@ -142,49 +138,28 @@ namespace op
#endif
// 3. Get peaks by Non-Maximum Suppression
spNmsCaffe->setThreshold((float)get(FaceProperty::NMSThreshold));
#ifndef CPU_ONLY
spNmsCaffe->Forward_gpu({spHeatMapsBlob.get()}, {spPeaksBlob.get()});
spMaximumCaffe->Forward_gpu({spHeatMapsBlob.get()}, {spPeaksBlob.get()});
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
#else
spNmsCaffe->Forward_cpu({spHeatMapsBlob.get()}, {spPeaksBlob.get()});
spMaximumCaffe->Forward_cpu({spHeatMapsBlob.get()}, {spPeaksBlob.get()});
#endif
const auto* facePeaksPtr = spPeaksBlob->mutable_cpu_data();
const auto facePeaksOffset = (FACE_MAX_PEAKS+1) * 3;
for (auto part = 0 ; part < mFaceKeypoints.getSize(1) ; part++)
{
// Get max peak
const int numPeaks = intRound(facePeaksPtr[facePeaksOffset*part]);
auto maxScore = -1.f;
auto maxPeak = -1;
for (auto peak = 0 ; peak < numPeaks ; peak++)
{
const auto xyIndex = facePeaksOffset * part + (1 + peak) * 3;
const auto score = facePeaksPtr[xyIndex + 2];
if (score > maxScore)
{
maxScore = score;
maxPeak = peak;
}
}
// Fill face keypoints
if (maxPeak >= 0)
{
const auto xyIndex = facePeaksOffset * part + (1 + maxPeak) * 3;
const auto x = facePeaksPtr[xyIndex];
const auto y = facePeaksPtr[xyIndex + 1];
const auto score = facePeaksPtr[xyIndex + 2];
const auto baseIndex = mFaceKeypoints.getSize(2) * (person * mFaceKeypoints.getSize(1) + part);
mFaceKeypoints[baseIndex] = (float)(scaleInputToOutput * (Mscaling.at<double>(0,0) * x
+ Mscaling.at<double>(0,1) * y
+ Mscaling.at<double>(0,2)));
mFaceKeypoints[baseIndex+1] = (float)(scaleInputToOutput * (Mscaling.at<double>(1,0) * x
+ Mscaling.at<double>(1,1) * y
+ Mscaling.at<double>(1,2)));
mFaceKeypoints[baseIndex+2] = score;
}
const auto xyIndex = part * mFaceKeypoints.getSize(2);
const auto x = facePeaksPtr[xyIndex];
const auto y = facePeaksPtr[xyIndex + 1];
const auto score = facePeaksPtr[xyIndex + 2];
const auto baseIndex = mFaceKeypoints.getSize(2) * (part + person * mFaceKeypoints.getSize(1));
mFaceKeypoints[baseIndex] = (float)(scaleInputToOutput * (Mscaling.at<double>(0,0) * x
+ Mscaling.at<double>(0,1) * y
+ Mscaling.at<double>(0,2)));
mFaceKeypoints[baseIndex+1] = (float)(scaleInputToOutput * (Mscaling.at<double>(1,0) * x
+ Mscaling.at<double>(1,1) * y
+ Mscaling.at<double>(1,2)));
mFaceKeypoints[baseIndex+2] = score;
}
}
}
......@@ -214,43 +189,6 @@ namespace op
}
}
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
......
#include <fstream> // std::ifstream
#include <opencv2/highgui/highgui.hpp> // cv::imread
#include <openpose/utilities/errorAndLog.hpp>
#include <openpose/utilities/fastMath.hpp>
#include <openpose/utilities/fileSystem.hpp>
#include <openpose/utilities/string.hpp>
#include <openpose/filestream/jsonOfstream.hpp>
#include <openpose/filestream/fileStream.hpp>
......@@ -154,21 +158,20 @@ namespace op
for (const auto& keypointPair : keypointVector)
if (!keypointPair.first.empty() && keypointPair.first.getNumberDimensions() != 3 )
error("keypointVector.getNumberDimensions() != 3.", __LINE__, __FUNCTION__, __FILE__);
// Record frame on desired path
JsonOfstream jsonOfstream{fileName, humanReadable};
jsonOfstream.objectOpen();
// Version
jsonOfstream.key("version");
jsonOfstream.plainText("1.0");
jsonOfstream.comma();
// Bodies
jsonOfstream.key("people");
jsonOfstream.arrayOpen();
const auto numberPeople = (keypointVector.size() > 0 ? keypointVector[0].first.getSize(0) : 0);
// Ger max numberPeople
auto numberPeople = 0;
for (auto vectorIndex = 0 ; vectorIndex < keypointVector.size() ; vectorIndex++)
numberPeople = fastMax(numberPeople, keypointVector[vectorIndex].first.getSize(0));
for (auto person = 0 ; person < numberPeople ; person++)
{
jsonOfstream.objectOpen();
......@@ -202,8 +205,9 @@ namespace op
jsonOfstream.enter();
}
}
// Close array
jsonOfstream.arrayClose();
// Close object
jsonOfstream.objectClose();
}
catch (const std::exception& e)
......@@ -240,4 +244,44 @@ namespace op
return cv::Mat{};
}
}
std::vector<std::array<Rectangle<float>, 2>> loadHandDetectorTxt(const std::string& txtFilePath)
{
try
{
std::vector<std::array<Rectangle<float>, 2>> handRectangles;
std::string line;
std::ifstream jsonFile{txtFilePath};
if (jsonFile.is_open())
{
while (std::getline(jsonFile, line))
{
const auto splittedStrings = splitString(line, " ");
std::vector<float> splittedInts;
for (auto splittedString : splittedStrings)
splittedInts.emplace_back(std::stof(splittedString));
if (splittedInts.size() != 4)
error("splittedInts.size() != 4, but splittedInts.size() = "
+ std::to_string(splittedInts.size()) + ".", __LINE__, __FUNCTION__, __FILE__);
const Rectangle<float> handRectangleZero;
const Rectangle<float> handRectangle{splittedInts[0], splittedInts[1], splittedInts[2], splittedInts[3]};
if (getFileNameNoExtension(txtFilePath).back() == 'l')
handRectangles.emplace_back(std::array<Rectangle<float>, 2>{handRectangle, handRectangleZero});
else
handRectangles.emplace_back(std::array<Rectangle<float>, 2>{handRectangleZero, handRectangle});
}
jsonFile.close();
}
else
error("Unable to open file " + txtFilePath + ".", __LINE__, __FUNCTION__, __FILE__);
return handRectangles;
}
catch (const std::exception& e)
{
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
return {};
}
}
}
......@@ -3,6 +3,7 @@
namespace op
{
DEFINE_TEMPLATE_DATUM(WHandDetector);
DEFINE_TEMPLATE_DATUM(WHandDetectorFromTxt);
DEFINE_TEMPLATE_DATUM(WHandDetectorTracking);
DEFINE_TEMPLATE_DATUM(WHandDetectorUpdate);
DEFINE_TEMPLATE_DATUM(WHandExtractor);
......
#include <openpose/filestream/fileStream.hpp>
#include <openpose/utilities/fileSystem.hpp>
#include <openpose/utilities/errorAndLog.hpp>
#include <openpose/hand/handDetectorFromTxt.hpp>
namespace op
{
std::vector<std::string> getTxtPathsOnDirectory(const std::string& txtDirectoryPath)
{
try
{
// Get files on directory with JSON extension
const auto txtPaths = getFilesOnDirectory(txtDirectoryPath, ".txt");
// Check #files > 0
if (txtPaths.empty())
error("No txt files were found on " + txtDirectoryPath, __LINE__, __FUNCTION__, __FILE__);
// Return file names
return txtPaths;
}
catch (const std::exception& e)
{
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
return {};
}
}
HandDetectorFromTxt::HandDetectorFromTxt(const std::string& txtDirectoryPath) :
mTxtDirectoryPath{txtDirectoryPath},
mFilePaths{getTxtPathsOnDirectory(txtDirectoryPath)},
mFrameNameCounter{0}
{
}
std::vector<std::array<Rectangle<float>, 2>> HandDetectorFromTxt::detectHands()
{
try
{
return loadHandDetectorTxt(mFilePaths.at(mFrameNameCounter++));
}
catch (const std::exception& e)
{
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
return std::vector<std::array<Rectangle<float>, 2>>{};
}
}
}
......@@ -56,7 +56,7 @@ namespace op
// Pose extractor blob and layer
spPeaksBlob = {std::make_shared<caffe::Blob<float>>(1,1,1,1)};
spNmsCaffe->Reshape({spHeatMapsBlob.get()}, {spPeaksBlob.get()}, POSE_MAX_PEAKS[(int)mPoseModel], POSE_NUMBER_BODY_PARTS[(int)mPoseModel]);
spNmsCaffe->Reshape({spHeatMapsBlob.get()}, {spPeaksBlob.get()}, POSE_MAX_PEAKS[(int)mPoseModel]);
cudaCheck(__LINE__, __FUNCTION__, __FILE__);
// Pose extractor blob and layer
......
......@@ -34,6 +34,29 @@ namespace op
}
}
std::vector<std::string> splitString(const std::string& stringToSplit, const std::string& delimiter)
{
try
{
std::vector<std::string> result;
size_t pos = 0;
auto stringToSplitAux = stringToSplit;
while ((pos = stringToSplitAux.find(delimiter)) != std::string::npos)
{
result.emplace_back(stringToSplitAux.substr(0, pos));
stringToSplitAux.erase(0, pos + delimiter.length());
}
result.emplace_back(stringToSplitAux);
return result;
}
catch (const std::exception& e)
{
error(e.what(), __LINE__, __FUNCTION__, __FILE__);
return {};
}
}
// Signed
template std::string toFixedLengthString<char>(const char number, const unsigned long long stringLength);
template std::string toFixedLengthString<signed char>(const signed char number, const unsigned long long stringLength);
......
......@@ -2,10 +2,14 @@
namespace op
{
WrapperStructPose::WrapperStructPose(const Point<int>& netInputSize_, const Point<int>& outputSize_, const ScaleMode keypointScale_, const int gpuNumber_,
const int gpuNumberStart_, const int scalesNumber_, const float scaleGap_, const RenderMode renderMode_,
const PoseModel poseModel_, const bool blendOriginalFrame_, const float alphaKeypoint_, const float alphaHeatMap_,
const int defaultPartToRender_, const std::string& modelFolder_, const std::vector<HeatMapType>& heatMapTypes_,
WrapperStructPose::WrapperStructPose(const Point<int>& netInputSize_, const Point<int>& outputSize_,
const ScaleMode keypointScale_, const int gpuNumber_,
const int gpuNumberStart_, const int scalesNumber_, const float scaleGap_,
const RenderMode renderMode_, const PoseModel poseModel_,
const bool blendOriginalFrame_, const float alphaKeypoint_,
const float alphaHeatMap_, const int defaultPartToRender_,
const std::string& modelFolder_,
const std::vector<HeatMapType>& heatMapTypes_,
const ScaleMode heatMapScale_) :
netInputSize{netInputSize_},
outputSize{outputSize_},
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册