做外贸如何建网站,创建全国文明城市倡议书,目前推广平台都有哪些,十堰网站建设报价使用 C 和 OpenCV DNN 进行人体姿态估计
本文将介绍如何使用 C 和 OpenCV 的深度神经网络#xff08;DNN#xff09;模块来识别人类肢体#xff0c;即进行人体姿态估计 (Human Pose Estimation)。我们的目标是读取一张包含人物的图片#xff0c;并检测出人体的关键点…使用 C 和 OpenCV DNN 进行人体姿态估计
本文将介绍如何使用 C 和 OpenCV 的深度神经网络DNN模块来识别人类肢体即进行人体姿态估计 (Human Pose Estimation)。我们的目标是读取一张包含人物的图片并检测出人体的关键点如头部、肩膀、手腕等然后将这些关键点连接起来形成一个“骨架”。 核心概念 姿态估计: 这个任务的目标是识别人体图像中的关键关节Keypoints。这些关节的集合可以勾勒出人体的姿态和骨架。 OpenCV DNN 模块: OpenCV 提供了一个功能强大的 cv::dnn 模块它能够加载预先训练好的深度学习模型并进行推理Inference。我们不需要自己训练模型而是使用社区已经训练好的模型文件。 预训练模型: 我们将使用一个基于 OpenPose 并且适用于 MPII (Max Planck Institute for Informatics) 数据集的模型。这个模型由两个文件组成 pose/mpi/pose_deploy_linevec_faster_4_stages.prototxt: 模型的网络结构定义文件。pose/mpi/pose_iter_160000.caffemodel: 模型的预训练权重文件。 热力图 (Heatmaps): 模型在进行推理后不会直接返回关节点坐标。它会为每个关节点如左肩、右膝生成一张热力图。热力图上每个像素的亮度代表该位置是对应关节点的置信度。我们只需要在每张热力图上找到最亮的点就能确定关节点的位置。 ️ 环境准备
在开始编码之前请确保你已经准备好以下环境
C 编译器: 如 G, Clang, 或 MSVC。OpenCV 库: 确保你安装的 OpenCV 版本包含了 dnn 和 highgui 模块。你可以从 OpenCV 官网 下载。预训练模型文件: 创建一个名为 models 的文件夹。下载模型文件并将它们放入 models 文件夹。你可以从 OpenCV 的 GitHub 仓库 获取 pose_deploy_linevec_faster_4_stages.prototxt (下载后可重命名)pose_iter_160000.caffemodel 代码实现
我们将整个过程分解为加载模型、图像预处理、模型推理、解析结果和绘制骨架几个步骤。
1. 包含头文件和定义常量
首先我们需要包含必要的 OpenCV 头文件并定义一些常量比如模型的输入尺寸和关节点的配对关系。
#include iostream
#include opencv2/dnn.hpp
#include opencv2/imgproc.hpp
#include opencv2/highgui.hpp// 使用 MPII 数据集训练的模型它定义了15个关节点
const int nPoints 15;// 定义关节点之间的连接关系
// 例如 {0, 1} 表示连接第0个关节点头和第1个关节点颈
const int POSE_PAIRS[14][2] {{0, 1}, {1, 2}, {2, 3}, {3, 4}, // 右臂{1, 5}, {5, 6}, {6, 7}, // 左臂{1, 14}, {14, 8}, {8, 9}, {9, 10}, // 右腿{14, 11}, {11, 12}, {12, 13} // 左腿
};2. 主函数和模型加载
在 main 函数中我们首先加载 Caffe 模型然后读取待处理的图像。
int main(int argc, char **argv) {// ---- 模型和图像路径 ----std::string protoFile models/pose_deploy_linevec_faster_4_stages.prototxt;std::string weightsFile models/pose_iter_160000.caffemodel;std::string imageFile person.jpg; // 替换成你自己的图片路径if (argc 1) {imageFile argv[1];}// ---- 加载网络 ----cv::dnn::Net net cv::dnn::readNetFromCaffe(protoFile, weightsFile);if (net.empty()) {std::cerr Error: Could not load the network. std::endl;return -1;}// ---- 读取并处理图像 ----cv::Mat frame cv::imread(imageFile);if (frame.empty()) {std::cerr Error: Could not read the image. std::endl;return -1;}cv::Mat frameCopy frame.clone();3. 图像预处理与模型推理
神经网络需要特定格式的输入。我们使用 cv::dnn::blobFromImage 函数来创建一个 “blob”它将图像转换成适合网络输入的格式。然后执行 net.forward() 进行推理。 // ---- 准备输入 ----int inWidth 368;int inHeight 368;double thresh 0.1; // 置信度阈值// 将图像转换为 blobcv::Mat inpBlob cv::dnn::blobFromImage(frame, 1.0 / 255, cv::Size(inWidth, inHeight), cv::Scalar(0, 0, 0), false, false);// 设置网络输入net.setInput(inpBlob);// ---- 进行推理 ----// net.forward() 返回一个 4D Mat维度是 (1, num_parts, height, width)cv::Mat output net.forward();int H output.size[2];int W output.size[3];4. 解析输出并定位关键点
推理的输出是包含了所有关节点热力图的 Mat 对象。我们需要遍历每一张热力图使用 cv::minMaxLoc 找到置信度最高的点并将其坐标记录下来。 // ---- 寻找关键点 ----std::vectorcv::Point points(nPoints);for (int n 0; n nPoints; n) {// 获取第 n 个关节点的热力图cv::Mat heatMap(H, W, CV_32F, output.ptr(0, n));// 寻找热力图中的最大值及其位置double conf;cv::Point point;cv::minMaxLoc(heatMap, 0, conf, 0, point);// 如果置信度大于阈值则记录该点if (conf thresh) {// 将坐标从热力图尺寸映射回原图尺寸int x (int)((float)frame.cols * point.x / W);int y (int)((float)frame.rows * point.y / H);points[n] cv::Point(x, y);} else {points[n] cv::Point(-1, -1); // 标记为未检测到}}5. 绘制骨架和显示结果
最后一步是根据我们之前定义的 POSE_PAIRS 数组将检测到的关节点用线连接起来形成骨架。我们也在每个关节点的位置画一个圆圈来使其更显眼。 // ---- 绘制骨架 ----for (int i 0; i 14; i) {cv::Point2i partA points[POSE_PAIRS[i][0]];cv::Point2i partB points[POSE_PAIRS[i][1]];// 只绘制检测到的关节点之间的连线if (partA.x 0 partA.y 0 partB.x 0 partB.y 0) {cv::line(frame, partA, partB, cv::Scalar(0, 255, 0), 2);cv::circle(frame, partA, 5, cv::Scalar(0, 0, 255), -1);cv::circle(frame, partB, 5, cv::Scalar(0, 0, 255), -1);}}// ---- 显示结果 ----cv::imshow(Pose Estimation, frame);cv::waitKey(0);return 0;
}编译与运行
保存代码: 将上述所有代码片段整合到一个 C 文件中例如 pose_estimation.cpp。准备图片: 在项目目录下放一张名为 person.jpg 的图片。编译: 打开终端使用以下命令进行编译假设你使用 pkg-config 来链接 OpenCVg -o pose_app pose_estimation.cpp $(pkg-config --cflags --libs opencv4)注意如果你的 OpenCV 版本不是 4请将 opencv4 替换为你的版本例如 opencv。运行:./pose_app或者指定一张不同的图片./pose_app path/to/your/image.jpg程序运行后会弹出一个窗口显示带有骨架覆盖的图像。 总结
通过利用 OpenCV 的 DNN 模块和预训练的 Caffe 模型我们可以相对轻松地在 C 中实现复杂的人体姿态估计功能。这个基础可以进一步扩展例如应用在视频流上以实现实时的姿态跟踪或者分析特定姿态以用于人机交互等应用。