mediapipe获取人体3d姿态 c++
时间: 2023-08-03 22:04:31 浏览: 221
使用MediaPipe获取人体3D姿态需要进行以下步骤:
1. 下载和设置MediaPipe的C++ SDK。
2. 安装CUDA和cuDNN。这是为了支持GPU加速。
3. 下载并解压预训练的模型。
4. 编写C++代码来读取摄像头输入并运行MediaPipe的姿态估计模型。
下面是一个示例代码,可以读取实时摄像头输入并显示估计的3D姿态:
```cpp
#include <iostream>
#include <string>
#include "mediapipe/framework/formats/image_frame.h"
#include "mediapipe/framework/formats/image_frame_opencv.h"
#include "mediapipe/framework/port/opencv_highgui_inc.h"
#include "mediapipe/framework/port/opencv_imgproc_inc.h"
#include "mediapipe/framework/port/status.h"
#include "mediapipe/framework/port/ret_check.h"
#include "mediapipe/framework/port/opencv_video_inc.h"
#include "mediapipe/framework/tool/options_util.h"
#include "mediapipe/framework/deps/file_path.h"
#include "mediapipe/framework/deps/compatibility.h"
#include "mediapipe/framework/calculator_framework.h"
#include "mediapipe/framework/formats/landmark.pb.h"
#include "mediapipe/framework/formats/landmark_list.pb.h"
#include "mediapipe/framework/formats/rect.pb.h"
namespace mediapipe {
constexpr char kInputStream[] = "input_video";
constexpr char kOutputStream[] = "output_video";
constexpr char kLandmarksStream[] = "pose_landmarks";
class PoseTrackingCalculator : public CalculatorBase {
public:
static ::mediapipe::Status GetContract(CalculatorContract* cc) {
RET_CHECK(cc->Inputs().HasTag(kInputStream));
RET_CHECK(cc->Outputs().HasTag(kOutputStream));
cc->Inputs().Tag(kInputStream).Set<ImageFrame>();
cc->Outputs().Tag(kOutputStream).Set<ImageFrame>();
cc->Outputs().Tag(kLandmarksStream).Set<std::vector<NormalizedLandmark>>();
return ::mediapipe::OkStatus();
}
::mediapipe::Status Open(CalculatorContext* cc) override {
cc->SetOffset(TimestampDiff(0));
return ::mediapipe::OkStatus();
}
::mediapipe::Status Process(CalculatorContext* cc) override {
const auto& input_frame = cc->Inputs().Tag(kInputStream).Get<ImageFrame>();
auto output_frame = absl::make_unique<ImageFrame>(
ImageFormat::SRGB, input_frame.Width(), input_frame.Height(),
ImageFrame::kDefaultAlignmentBoundary);
cv::Mat input_mat = formats::MatView(&input_frame);
cv::Mat output_mat = formats::MatView(output_frame.get());
// Create an instance of the pose detection calculator.
mediapipe::PoseDetectionCalculatorOptions pose_detection_options;
pose_detection_options.set_static_image_mode(false);
pose_detection_options.set_model_complexity(1);
pose_detection_options.set_smooth_landmarks(true);
pose_detection_options.set_enable_segmentation(false);
pose_detection_options.set_smooth_landmarks(true);
CalculatorGraphConfig::Node pose_detection_node_config;
pose_detection_node_config.set_calculator("PoseDetectionCalculator");
pose_detection_node_config.add_input_side_packet("image_size_side_packet");
pose_detection_node_config.add_input_side_packet("model_complexity_side_packet");
pose_detection_node_config.add_input_side_packet("static_image_mode_side_packet");
pose_detection_node_config.add_input_side_packet("smooth_landmarks_side_packet");
pose_detection_node_config.add_input_side_packet("enable_segmentation_side_packet");
pose_detection_node_config.add_input_side_packet("input_image_side_packet");
pose_detection_node_config.add_output_tag(kLandmarksStream);
pose_detection_node_config.mutable_options()->PackFrom(pose_detection_options);
CalculatorGraph graph;
ASSIGN_OR_RETURN(auto pose_detection_node, graph.AddNode(pose_detection_node_config));
// Run the pose detection calculator.
MP_RETURN_IF_ERROR(graph.StartRun({}));
MP_RETURN_IF_ERROR(graph.AddPacketToInputStream(
"image_size_side_packet", MakePacket<std::pair<int, int>>(std::make_pair(input_mat.cols, input_mat.rows))));
MP_RETURN_IF_ERROR(graph.AddPacketToInputStream("model_complexity_side_packet", MakePacket<int>(1)));
MP_RETURN_IF_ERROR(graph.AddPacketToInputStream("static_image_mode_side_packet", MakePacket<bool>(false)));
MP_RETURN_IF_ERROR(graph.AddPacketToInputStream("smooth_landmarks_side_packet", MakePacket<bool>(true)));
MP_RETURN_IF_ERROR(graph.AddPacketToInputStream("enable_segmentation_side_packet", MakePacket<bool>(false)));
MP_RETURN_IF_ERROR(graph.AddPacketToInputStream("input_image_side_packet", mediapipe::Adopt(input_frame.release()).At(Timestamp(0))));
MP_RETURN_IF_ERROR(graph.WaitUntilIdle());
mediapipe::Packet landmarks_packet;
if (graph.GetOutputLandmarkListPacket(kLandmarksStream).ValidateAsType<std::vector<NormalizedLandmark>>().ok()) {
landmarks_packet = graph.GetOutputLandmarkListPacket(kLandmarksStream);
}
MP_RETURN_IF_ERROR(graph.CloseAllPacketSources());
MP_RETURN_IF_ERROR(graph.WaitUntilDone());
// Draw the landmarks on the output frame.
auto landmarks = landmarks_packet.Get<std::vector<NormalizedLandmark>>();
for (const auto& landmark : landmarks) {
const int landmark_x = landmark.x() * input_mat.cols;
const int landmark_y = landmark.y() * input_mat.rows;
cv::circle(output_mat, cv::Point(landmark_x, landmark_y), 3, cv::Scalar(0, 255, 0), -1);
}
cc->Outputs().Tag(kOutputStream).Add(output_frame.release(), cc->InputTimestamp());
cc->Outputs().Tag(kLandmarksStream).Add(landmarks_packet, cc->InputTimestamp());
return ::mediapipe::OkStatus();
}
};
REGISTER_CALCULATOR(PoseTrackingCalculator);
} // namespace mediapipe
int main(int argc, char** argv) {
absl::ParseCommandLine(argc, argv);
mediapipe::CalculatorGraphConfig config =
mediapipe::ParseTextProtoOrDie<mediapipe::CalculatorGraphConfig>(R"pb(
input_stream: "input_video"
output_stream: "output_video"
output_stream: "pose_landmarks"
node {
calculator: "PoseTrackingCalculator"
input_stream: "input_video"
output_stream: "output_video"
output_stream: "pose_landmarks"
}
)pb");
mediapipe::CalculatorGraph graph;
MP_RETURN_IF_ERROR(graph.Initialize(config));
MP_RETURN_IF_ERROR(graph.StartRun({}));
cv::VideoCapture capture(0);
CHECK(capture.isOpened());
while (capture.isOpened()) {
cv::Mat frame;
capture >> frame;
if (frame.empty()) break;
// Convert the OpenCV Mat to a MediaPipe ImageFrame.
auto input_frame = absl::make_unique<mediapipe::ImageFrame>(
mediapipe::ImageFormat::SRGB, frame.cols, frame.rows,
mediapipe::ImageFrame::kDefaultAlignmentBoundary);
cv::Mat input_mat = mediapipe::formats::MatView(input_frame.get());
frame.copyTo(input_mat);
// Run the MediaPipe graph to estimate the pose and display the results.
mediapipe::Packet packet = mediapipe::Adopt(input_frame.release()).At(mediapipe::Timestamp(0));
MP_RETURN_IF_ERROR(graph.AddPacketToInputStream(mediapipe::kInputStream, packet));
MP_RETURN_IF_ERROR(graph.WaitUntilIdle());
auto output_frame = graph.GetOutputStreamPacket(mediapipe::kOutputStream).Get<mediapipe::ImageFrame>();
auto landmarks_packet = graph.GetOutputStreamPacket(mediapipe::kLandmarksStream);
auto landmarks = landmarks_packet.Get<std::vector<mediapipe::NormalizedLandmark>>();
for (const auto& landmark : landmarks) {
const int landmark_x = landmark.x() * frame.cols;
const int landmark_y = landmark.y() * frame.rows;
cv::circle(frame, cv::Point(landmark_x, landmark_y), 3, cv::Scalar(0, 255, 0), -1);
}
cv::imshow("Pose Tracking", mediapipe::formats::MatView(&output_frame));
if (cv::waitKey(5) == 27) break;
}
MP_RETURN_IF_ERROR(graph.CloseAllPacketSources());
return graph.WaitUntilDone().ok() ? EXIT_SUCCESS : EXIT_FAILURE;
}
```
请注意,此示例代码仅显示了如何使用MediaPipe获取人体3D姿态。如果需要更多功能(例如记录姿态数据或将其传输到其他设备),则需要进行更多的自定义编程。
阅读全文