提交 fcadd274 编写于 作者: G gineshidalgo99

Flag write_json includes 3-D keypoints

上级 cb06fded
...@@ -97,7 +97,14 @@ It should be similar to the following image. ...@@ -97,7 +97,14 @@ It should be similar to the following image.
## Using a Different Camera Brand ## Using a Different Camera Brand
You can copy and modify the OpenPose 3-D demo to use any camera brand, by modifying the frames producer. For that, you would need to provide your custom code to retrieve synchronized images from your cameras, as well as their intrinsic and extrinsic camera parameters. You can copy and modify the OpenPose 3-D demo to use any camera brand by:
1. You can optionally turn off the `WITH_FLIR_CAMERA` while compiling CMake.
2. Copy any of the `examples/tutorial_wrapper/*.cpp` examples (we recommend `2_user_synchronous.cpp`).
3. Modify `WUserInput` and add your custom code there. Your code should fill `Datum::name`, `Datum::cameraMatrix`, `Datum::cvInputData`, and `Datum::cvOutputData` (fill cvOutputData = cvInputData).
4. Remove `WUserPostProcessing` and `WUserOutput` (unless you want to have your custom post-processing and/or output).
Note that your custom code should retrieve synchronized images from your cameras or any other source, as well as their intrinsic and extrinsic camera parameters.
......
...@@ -213,7 +213,7 @@ Each flag is divided into flag name, default value, and description. ...@@ -213,7 +213,7 @@ Each flag is divided into flag name, default value, and description.
- DEFINE_string(write_images, "", "Directory to write rendered frames in `write_images_format` image format."); - DEFINE_string(write_images, "", "Directory to write rendered frames in `write_images_format` image format.");
- DEFINE_string(write_images_format, "png", "File extension and format for `write_images`, e.g. png, jpg or bmp. Check the OpenCV function cv::imwrite for all compatible extensions."); - DEFINE_string(write_images_format, "png", "File extension and format for `write_images`, e.g. png, jpg or bmp. Check the OpenCV function cv::imwrite for all compatible extensions.");
- DEFINE_string(write_video, "", "Full file path to write rendered frames in motion JPEG video format. It might fail if the final path does not finish in `.avi`. It internally uses cv::VideoWriter."); - DEFINE_string(write_video, "", "Full file path to write rendered frames in motion JPEG video format. It might fail if the final path does not finish in `.avi`. It internally uses cv::VideoWriter.");
- DEFINE_string(write_json, "", "Directory to write OpenPose output in JSON format. It includes body, hand, and face pose keypoints, as well as pose candidates (if `--part_candidates` enabled)."); - DEFINE_string(write_json, "", "Directory to write OpenPose output in JSON format. It includes body, hand, and face pose keypoints (2-D and 3-D), as well as pose candidates (if `--part_candidates` enabled).");
- DEFINE_string(write_coco_json, "", "Full file path to write people pose data with JSON COCO validation format."); - DEFINE_string(write_coco_json, "", "Full file path to write people pose data with JSON COCO validation format.");
- DEFINE_string(write_heatmaps, "", "Directory to write body pose heatmaps in PNG format. At least 1 `add_heatmaps_X` flag must be enabled."); - DEFINE_string(write_heatmaps, "", "Directory to write body pose heatmaps in PNG format. At least 1 `add_heatmaps_X` flag must be enabled.");
- DEFINE_string(write_heatmaps_format, "png", "File extension and format for `write_heatmaps`, analogous to `write_images_format`. For lossless compression, recommended `png` for integer `heatmaps_scale` and `float` for floating values."); - DEFINE_string(write_heatmaps_format, "png", "File extension and format for `write_heatmaps`, analogous to `write_images_format`. For lossless compression, recommended `png` for integer `heatmaps_scale` and `float` for floating values.");
......
...@@ -125,13 +125,20 @@ build\x64\Release\OpenPoseDemo.exe --flir_camera --3d --number_people_max 1 ...@@ -125,13 +125,20 @@ build\x64\Release\OpenPoseDemo.exe --flir_camera --3d --number_people_max 1
build\x64\Release\OpenPoseDemo.exe --flir_camera --3d --number_people_max 1 --face --hand build\x64\Release\OpenPoseDemo.exe --flir_camera --3d --number_people_max 1 --face --hand
``` ```
2. Saving stereo camera images for a later post-processing: 2. Saving 3-D keypoints
``` ```
# Ubuntu (same flags for Windows version) # Ubuntu (same flags for Windows version)
./build/examples/openpose/openpose.bin --flir_camera --3d --number_people_max 1 --num_gpu 0 --write_images output_folder_path/ ./build/examples/openpose/openpose.bin --flir_camera --3d --number_people_max 1 --write_json output_folder_path/
``` ```
3. Reading previouly saved stereo camera images and processing them: 3. Saving stereo camera images fast (without keypoint detection) for later post-processing
```
# Ubuntu (same flags for Windows version)
# Note: saving in PNG rather than JPG will improve image quality, but slow down FPS (depending on hard disk writing speed and camera number)
./build/examples/openpose/openpose.bin --flir_camera --num_gpu 0 --write_images output_folder_path/
```
4. Reading and processing previouly saved stereo camera images
``` ```
# Ubuntu (same flags for Windows version) # Ubuntu (same flags for Windows version)
# Optionally add `--face` and/or `--hand` to include face and/or hands # Optionally add `--face` and/or `--hand` to include face and/or hands
......
...@@ -185,6 +185,8 @@ OpenPose Library - Release Notes ...@@ -185,6 +185,8 @@ OpenPose Library - Release Notes
13. 3-D reconstruction module forces the user to set `number_people_max 1` to avoid errors (as it assumes only 1 person per image). 13. 3-D reconstruction module forces the user to set `number_people_max 1` to avoid errors (as it assumes only 1 person per image).
14. Removed old `windows/` version. CMake is the only Windows version available. 14. Removed old `windows/` version. CMake is the only Windows version available.
15. Camera parameters (flir camera) are read from disk at runtime rather than being compiled. 15. Camera parameters (flir camera) are read from disk at runtime rather than being compiled.
16. 3-D reconstruction module can be implemented with different camera brands or custom image sources.
16. Flag `--write_json` includes 3-D keypoints.
2. Functions or parameters renamed: 2. Functions or parameters renamed:
1. Flag `no_display` renamed as `display`, able to select between `NoDisplay`, `Display2D`, `Display3D`, and `DisplayAll`. 1. Flag `no_display` renamed as `display`, able to select between `NoDisplay`, `Display2D`, `Display3D`, and `DisplayAll`.
2. 3-D reconstruction demo is now inside the OpenPose demo binary. 2. 3-D reconstruction demo is now inside the OpenPose demo binary.
......
...@@ -194,7 +194,7 @@ DEFINE_string(write_images_format, "png", "File extension and form ...@@ -194,7 +194,7 @@ DEFINE_string(write_images_format, "png", "File extension and form
DEFINE_string(write_video, "", "Full file path to write rendered frames in motion JPEG video format. It might fail if the" DEFINE_string(write_video, "", "Full file path to write rendered frames in motion JPEG video format. It might fail if the"
" final path does not finish in `.avi`. It internally uses cv::VideoWriter."); " final path does not finish in `.avi`. It internally uses cv::VideoWriter.");
DEFINE_string(write_json, "", "Directory to write OpenPose output in JSON format. It includes body, hand, and face pose" DEFINE_string(write_json, "", "Directory to write OpenPose output in JSON format. It includes body, hand, and face pose"
" keypoints, as well as pose candidates (if `--part_candidates` enabled)."); " keypoints (2-D and 3-D), as well as pose candidates (if `--part_candidates` enabled).");
DEFINE_string(write_coco_json, "", "Full file path to write people pose data with JSON COCO validation format."); DEFINE_string(write_coco_json, "", "Full file path to write people pose data with JSON COCO validation format.");
DEFINE_string(write_heatmaps, "", "Directory to write body pose heatmaps in PNG format. At least 1 `add_heatmaps_X` flag" DEFINE_string(write_heatmaps, "", "Directory to write body pose heatmaps in PNG format. At least 1 `add_heatmaps_X` flag"
" must be enabled."); " must be enabled.");
......
...@@ -201,7 +201,7 @@ DEFINE_string(write_images_format, "png", "File extension and form ...@@ -201,7 +201,7 @@ DEFINE_string(write_images_format, "png", "File extension and form
DEFINE_string(write_video, "", "Full file path to write rendered frames in motion JPEG video format. It might fail if the" DEFINE_string(write_video, "", "Full file path to write rendered frames in motion JPEG video format. It might fail if the"
" final path does not finish in `.avi`. It internally uses cv::VideoWriter."); " final path does not finish in `.avi`. It internally uses cv::VideoWriter.");
DEFINE_string(write_json, "", "Directory to write OpenPose output in JSON format. It includes body, hand, and face pose" DEFINE_string(write_json, "", "Directory to write OpenPose output in JSON format. It includes body, hand, and face pose"
" keypoints, as well as pose candidates (if `--part_candidates` enabled)."); " keypoints (2-D and 3-D), as well as pose candidates (if `--part_candidates` enabled).");
DEFINE_string(write_coco_json, "", "Full file path to write people pose data with JSON COCO validation format."); DEFINE_string(write_coco_json, "", "Full file path to write people pose data with JSON COCO validation format.");
DEFINE_string(write_heatmaps, "", "Directory to write body pose heatmaps in PNG format. At least 1 `add_heatmaps_X` flag" DEFINE_string(write_heatmaps, "", "Directory to write body pose heatmaps in PNG format. At least 1 `add_heatmaps_X` flag"
" must be enabled."); " must be enabled.");
......
...@@ -184,7 +184,7 @@ DEFINE_string(write_images_format, "png", "File extension and form ...@@ -184,7 +184,7 @@ DEFINE_string(write_images_format, "png", "File extension and form
DEFINE_string(write_video, "", "Full file path to write rendered frames in motion JPEG video format. It might fail if the" DEFINE_string(write_video, "", "Full file path to write rendered frames in motion JPEG video format. It might fail if the"
" final path does not finish in `.avi`. It internally uses cv::VideoWriter."); " final path does not finish in `.avi`. It internally uses cv::VideoWriter.");
DEFINE_string(write_json, "", "Directory to write OpenPose output in JSON format. It includes body, hand, and face pose" DEFINE_string(write_json, "", "Directory to write OpenPose output in JSON format. It includes body, hand, and face pose"
" keypoints, as well as pose candidates (if `--part_candidates` enabled)."); " keypoints (2-D and 3-D), as well as pose candidates (if `--part_candidates` enabled).");
DEFINE_string(write_coco_json, "", "Full file path to write people pose data with JSON COCO validation format."); DEFINE_string(write_coco_json, "", "Full file path to write people pose data with JSON COCO validation format.");
DEFINE_string(write_heatmaps, "", "Directory to write body pose heatmaps in PNG format. At least 1 `add_heatmaps_X` flag" DEFINE_string(write_heatmaps, "", "Directory to write body pose heatmaps in PNG format. At least 1 `add_heatmaps_X` flag"
" must be enabled."); " must be enabled.");
......
...@@ -165,7 +165,7 @@ DEFINE_string(write_images_format, "png", "File extension and form ...@@ -165,7 +165,7 @@ DEFINE_string(write_images_format, "png", "File extension and form
DEFINE_string(write_video, "", "Full file path to write rendered frames in motion JPEG video format. It might fail if the" DEFINE_string(write_video, "", "Full file path to write rendered frames in motion JPEG video format. It might fail if the"
" final path does not finish in `.avi`. It internally uses cv::VideoWriter."); " final path does not finish in `.avi`. It internally uses cv::VideoWriter.");
DEFINE_string(write_json, "", "Directory to write OpenPose output in JSON format. It includes body, hand, and face pose" DEFINE_string(write_json, "", "Directory to write OpenPose output in JSON format. It includes body, hand, and face pose"
" keypoints, as well as pose candidates (if `--part_candidates` enabled)."); " keypoints (2-D and 3-D), as well as pose candidates (if `--part_candidates` enabled).");
DEFINE_string(write_coco_json, "", "Full file path to write people pose data with JSON COCO validation format."); DEFINE_string(write_coco_json, "", "Full file path to write people pose data with JSON COCO validation format.");
DEFINE_string(write_heatmaps, "", "Directory to write body pose heatmaps in PNG format. At least 1 `add_heatmaps_X` flag" DEFINE_string(write_heatmaps, "", "Directory to write body pose heatmaps in PNG format. At least 1 `add_heatmaps_X` flag"
" must be enabled."); " must be enabled.");
......
...@@ -165,7 +165,7 @@ DEFINE_string(write_images_format, "png", "File extension and form ...@@ -165,7 +165,7 @@ DEFINE_string(write_images_format, "png", "File extension and form
DEFINE_string(write_video, "", "Full file path to write rendered frames in motion JPEG video format. It might fail if the" DEFINE_string(write_video, "", "Full file path to write rendered frames in motion JPEG video format. It might fail if the"
" final path does not finish in `.avi`. It internally uses cv::VideoWriter."); " final path does not finish in `.avi`. It internally uses cv::VideoWriter.");
DEFINE_string(write_json, "", "Directory to write OpenPose output in JSON format. It includes body, hand, and face pose" DEFINE_string(write_json, "", "Directory to write OpenPose output in JSON format. It includes body, hand, and face pose"
" keypoints, as well as pose candidates (if `--part_candidates` enabled)."); " keypoints (2-D and 3-D), as well as pose candidates (if `--part_candidates` enabled).");
DEFINE_string(write_coco_json, "", "Full file path to write people pose data with JSON COCO validation format."); DEFINE_string(write_coco_json, "", "Full file path to write people pose data with JSON COCO validation format.");
DEFINE_string(write_heatmaps, "", "Directory to write body pose heatmaps in PNG format. At least 1 `add_heatmaps_X` flag" DEFINE_string(write_heatmaps, "", "Directory to write body pose heatmaps in PNG format. At least 1 `add_heatmaps_X` flag"
" must be enabled."); " must be enabled.");
......
...@@ -66,10 +66,16 @@ namespace op ...@@ -66,10 +66,16 @@ namespace op
const auto fileName = baseFileName + (i != 0 ? "_" + std::to_string(i) : ""); const auto fileName = baseFileName + (i != 0 ? "_" + std::to_string(i) : "");
const std::vector<std::pair<Array<float>, std::string>> keypointVector{ const std::vector<std::pair<Array<float>, std::string>> keypointVector{
// 2D
std::make_pair(tDatum.poseKeypoints, "pose_keypoints"), std::make_pair(tDatum.poseKeypoints, "pose_keypoints"),
std::make_pair(tDatum.faceKeypoints, "face_keypoints"), std::make_pair(tDatum.faceKeypoints, "face_keypoints"),
std::make_pair(tDatum.handKeypoints[0], "hand_left_keypoints"), std::make_pair(tDatum.handKeypoints[0], "hand_left_keypoints"),
std::make_pair(tDatum.handKeypoints[1], "hand_right_keypoints") std::make_pair(tDatum.handKeypoints[1], "hand_right_keypoints"),
// 3D
std::make_pair(tDatum.poseKeypoints3D, "pose_keypoints_3d"),
std::make_pair(tDatum.faceKeypoints3D, "face_keypoints_3d"),
std::make_pair(tDatum.handKeypoints3D[0], "hand_left_keypoints_3d"),
std::make_pair(tDatum.handKeypoints3D[1], "hand_right_keypoints_3d")
}; };
// Save keypoints // Save keypoints
spPeopleJsonSaver->save(keypointVector, tDatum.poseCandidates, fileName, humanReadable); spPeopleJsonSaver->save(keypointVector, tDatum.poseCandidates, fileName, humanReadable);
......
...@@ -59,22 +59,22 @@ namespace op ...@@ -59,22 +59,22 @@ namespace op
// tDatums might be empty but we still wanna update the GUI // tDatums might be empty but we still wanna update the GUI
if (tDatums != nullptr) if (tDatums != nullptr)
{ {
// Check tDatums->size() == 1
if (tDatums->size() > 1)
error("Only implemented for tDatums->size() == 1", __LINE__, __FUNCTION__, __FILE__);
// Debugging log // Debugging log
dLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); dLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
// Profiling speed // Profiling speed
const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);
// T* to T // Update cvMat
auto& tDatumsNoPtr = *tDatums; if (!tDatums->empty())
// Set image {
const auto cvOutputData = (!tDatumsNoPtr.empty() ? tDatumsNoPtr[0].cvOutputData : cv::Mat()); std::vector<cv::Mat> cvOutputDatas;
spGui->setImage(cvOutputData); for (auto& tDatum : *tDatums)
cvOutputDatas.emplace_back(tDatum.cvOutputData);
spGui->setImage(cvOutputDatas);
}
// Refresh GUI // Refresh GUI
spGui->update(); spGui->update();
// Profiling speed // Profiling speed
if (!tDatumsNoPtr.empty()) if (!tDatums->empty())
{ {
Profiler::timerEnd(profilerKey); Profiler::timerEnd(profilerKey);
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);
......
...@@ -63,21 +63,24 @@ namespace op ...@@ -63,21 +63,24 @@ namespace op
dLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); dLog("", Priority::Low, __LINE__, __FUNCTION__, __FILE__);
// Profiling speed // Profiling speed
const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);
// Update cvMat & keypoints
if (!tDatums->empty()) if (!tDatums->empty())
{ {
// T* to T
auto& tDatum = (*tDatums)[0];
// Update cvMat // Update cvMat
std::vector<cv::Mat> cvOutputDatas; std::vector<cv::Mat> cvOutputDatas;
for (auto& tDatum : *tDatums) for (auto& tDatum : *tDatums)
cvOutputDatas.emplace_back(tDatum.cvOutputData); cvOutputDatas.emplace_back(tDatum.cvOutputData);
spGui3D->setImage(cvOutputDatas); spGui3D->setImage(cvOutputDatas);
// Update keypoints // Update keypoints
auto& tDatum = (*tDatums)[0];
spGui3D->setKeypoints(tDatum.poseKeypoints3D, tDatum.faceKeypoints3D, tDatum.handKeypoints3D[0], spGui3D->setKeypoints(tDatum.poseKeypoints3D, tDatum.faceKeypoints3D, tDatum.handKeypoints3D[0],
tDatum.handKeypoints3D[1]); tDatum.handKeypoints3D[1]);
// Refresh/update GUI }
spGui3D->update(); // Refresh/update GUI
// Profiling speed spGui3D->update();
// Profiling speed
if (!tDatums->empty())
{
Profiler::timerEnd(profilerKey); Profiler::timerEnd(profilerKey);
Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__); Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);
} }
......
...@@ -40,21 +40,22 @@ namespace op ...@@ -40,21 +40,22 @@ namespace op
{ {
const auto& keypoints = keypointVector[vectorIndex].first; const auto& keypoints = keypointVector[vectorIndex].first;
const auto& keypointName = keypointVector[vectorIndex].second; const auto& keypointName = keypointVector[vectorIndex].second;
const auto numberBodyParts = keypoints.getSize(1); const auto numberElementsPerRaw = keypoints.getSize(1) * keypoints.getSize(2);
jsonOfstream.key(keypointName); jsonOfstream.key(keypointName);
jsonOfstream.arrayOpen(); jsonOfstream.arrayOpen();
// Body parts // Body parts
for (auto bodyPart = 0 ; bodyPart < numberBodyParts ; bodyPart++) if (numberElementsPerRaw > 0)
{ {
const auto finalIndex = 3*(person*numberBodyParts + bodyPart); const auto finalIndex = person*numberElementsPerRaw;
jsonOfstream.plainText(keypoints[finalIndex]); for (auto element = 0 ; element < numberElementsPerRaw - 1 ; element++)
jsonOfstream.comma(); {
jsonOfstream.plainText(keypoints[finalIndex+1]); jsonOfstream.plainText(keypoints[finalIndex + element]);
jsonOfstream.comma();
jsonOfstream.plainText(keypoints[finalIndex+2]);
if (bodyPart < numberBodyParts-1)
jsonOfstream.comma(); jsonOfstream.comma();
}
// Last element (no comma)
jsonOfstream.plainText(keypoints[finalIndex + numberElementsPerRaw - 1]);
} }
// Close array
jsonOfstream.arrayClose(); jsonOfstream.arrayClose();
if (vectorIndex < keypointVector.size()-1) if (vectorIndex < keypointVector.size()-1)
jsonOfstream.comma(); jsonOfstream.comma();
...@@ -313,7 +314,11 @@ namespace op ...@@ -313,7 +314,11 @@ namespace op
JsonOfstream jsonOfstream{fileName, humanReadable}; JsonOfstream jsonOfstream{fileName, humanReadable};
jsonOfstream.objectOpen(); jsonOfstream.objectOpen();
// Add version // Add version
jsonOfstream.version("1.1"); // Version 0.1: Body keypoints (2-D)
// Version 1.0: Added face and hands (2-D)
// Version 1.1: Added candidates
// Version 1.2: Added body, face, and hands (3-D)
jsonOfstream.version("1.2");
jsonOfstream.comma(); jsonOfstream.comma();
// Add people keypoints // Add people keypoints
addKeypointsToJson(jsonOfstream, keypointVector); addKeypointsToJson(jsonOfstream, keypointVector);
......
...@@ -102,6 +102,7 @@ namespace op ...@@ -102,6 +102,7 @@ namespace op
{ {
try try
{ {
mFrameNameCounter++; // Simple counter: 0,1,2,3,...
return mSpinnakerWrapper.getRawFrames(); return mSpinnakerWrapper.getRawFrames();
} }
catch (const std::exception& e) catch (const std::exception& e)
......
...@@ -15,6 +15,7 @@ namespace op ...@@ -15,6 +15,7 @@ namespace op
{ {
if (isOpened()) if (isOpened())
{ {
mFrameNameCounter = 0;
if (webcamResolution != Point<int>{}) if (webcamResolution != Point<int>{})
{ {
set(CV_CAP_PROP_FRAME_WIDTH, webcamResolution.x); set(CV_CAP_PROP_FRAME_WIDTH, webcamResolution.x);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册