<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>所有人体姿态估计 -</title><link>https://tornado404.github.io/posts/pose-estimation/</link><description>所有人体姿态估计 |</description><generator>Hugo -- gohugo.io</generator><language>zh-CN</language><lastBuildDate>Mon, 01 Jan 2024 00:00:00 +0000</lastBuildDate><atom:link href="https://tornado404.github.io/posts/pose-estimation/" rel="self" type="application/rss+xml"/><item><title>MMPose 快速入门：人体姿态估计与动作捕捉实战</title><link>https://tornado404.github.io/posts/pose-estimation/01-mmpose-quickstart/</link><pubDate>Mon, 02 Mar 2026 00:00:00 +0000</pubDate><author>xxxx</author><guid>https://tornado404.github.io/posts/pose-estimation/01-mmpose-quickstart/</guid><description><![CDATA[<h2 id="什么是-mmpose">什么是 MMPose</h2>
<p><a href="https://github.com/open-mmlab/mmpose" target="_blank" rel="noopener noreffer ">MMPose</a> 是 OpenMMLab 推出的开源人体姿态估计工具箱，基于 PyTorch 实现。它提供了丰富的姿态估计算法，支持 2D/3D 姿态估计、手部/面部关键点检测等多种任务。</p>
<h3 id="核心特性">核心特性</h3>
<ul>
<li><strong>算法丰富</strong>：支持 80+ 种姿态估计算法</li>
<li><strong>高精度</strong>：多个 SOTA 模型</li>
<li><strong>易用性</strong>：简洁的 API 设计</li>
<li><strong>生产就绪</strong>：支持 ONNX/TensorRT 部署</li>
<li><strong>社区活跃</strong>：完善的文档和教程</li>
</ul>
<hr>
<h2 id="快速开始">快速开始</h2>
<h3 id="环境配置">环境配置</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 创建 Conda 环境</span>
</span></span><span class="line"><span class="cl">conda create -n mmpose <span class="nv">python</span><span class="o">=</span>3.8 -y
</span></span><span class="line"><span class="cl">conda activate mmpose
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 安装 PyTorch</span>
</span></span><span class="line"><span class="cl">pip install <span class="nv">torch</span><span class="o">==</span>2.0.0 <span class="nv">torchvision</span><span class="o">==</span>0.15.0 --index-url https://download.pytorch.org/whl/cu118
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 安装 MMCV</span>
</span></span><span class="line"><span class="cl">pip install -U openmim
</span></span><span class="line"><span class="cl">mim install <span class="nv">mmcv</span><span class="o">==</span>2.0.0
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 安装 MMPose</span>
</span></span><span class="line"><span class="cl">git clone https://github.com/open-mmlab/mmpose.git
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> mmpose
</span></span><span class="line"><span class="cl">pip install -r requirements.txt
</span></span><span class="line"><span class="cl">pip install -e .
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 验证安装</span>
</span></span><span class="line"><span class="cl">python -c <span class="s2">&#34;import mmpose; print(mmpose.__version__)&#34;</span></span></span></code></pre></div></div>
<h3 id="下载预训练模型">下载预训练模型</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 创建模型目录</span>
</span></span><span class="line"><span class="cl">mkdir checkpoints
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 下载 RTMPose 模型（推荐）</span>
</span></span><span class="line"><span class="cl"><span class="c1"># RTMPose 是 MMPose 最新的高性能模型</span>
</span></span><span class="line"><span class="cl">wget https://download.openmmlab.com/mmpose/v1/projects/rtmpose/rtmpose-m_simcc-aic-coco_pt-aic-coco_420e-256x192.py
</span></span><span class="line"><span class="cl">wget https://download.openmmlab.com/mmpose/v1/projects/rtmpose/rtmpose-m_simcc-aic-coco_pt-aic-coco_420e-256x192-63eb25f7.pth</span></span></code></pre></div></div>
<hr>
<h2 id="基础使用">基础使用</h2>
<h3 id="1-使用推理器推荐">1. 使用推理器（推荐）</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-python">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">mmpose.apis</span> <span class="kn">import</span> <span class="n">inference_topdown</span><span class="p">,</span> <span class="n">init_model</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">mmpose.structures</span> <span class="kn">import</span> <span class="n">merge_data_samples</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">cv2</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 初始化模型</span>
</span></span><span class="line"><span class="cl"><span class="n">config_file</span> <span class="o">=</span> <span class="s1">&#39;rtmpose-m_simcc-aic-coco_pt-aic-coco_420e-256x192.py&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">checkpoint_file</span> <span class="o">=</span> <span class="s1">&#39;rtmpose-m_simcc-aic-coco_pt-aic-coco_420e-256x192-63eb25f7.pth&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">model</span> <span class="o">=</span> <span class="n">init_model</span><span class="p">(</span><span class="n">config_file</span><span class="p">,</span> <span class="n">checkpoint_file</span><span class="p">,</span> <span class="n">device</span><span class="o">=</span><span class="s1">&#39;cuda:0&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 读取图像</span>
</span></span><span class="line"><span class="cl"><span class="n">image</span> <span class="o">=</span> <span class="n">cv2</span><span class="o">.</span><span class="n">imread</span><span class="p">(</span><span class="s1">&#39;test_image.jpg&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 推理（需要先检测人体）</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">mmdet.apis</span> <span class="kn">import</span> <span class="n">init_model</span> <span class="k">as</span> <span class="n">init_det_model</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">mmdet.apis</span> <span class="kn">import</span> <span class="n">inference_detector</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 初始化检测器</span>
</span></span><span class="line"><span class="cl"><span class="n">det_config</span> <span class="o">=</span> <span class="s1">&#39;mmdet_configs/rtmdet_tiny_8xb32-300e_coco.py&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">det_checkpoint</span> <span class="o">=</span> <span class="s1">&#39;https://download.openmmlab.com/mmdetection/v2.0/rtmdet/rtmdet_tiny_8xb32-300e_coco/rtmdet_tiny_8xb32-300e_coco_20220902_112414-78e30dcc.pth&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">detector</span> <span class="o">=</span> <span class="n">init_det_model</span><span class="p">(</span><span class="n">det_config</span><span class="p">,</span> <span class="n">det_checkpoint</span><span class="p">,</span> <span class="n">device</span><span class="o">=</span><span class="s1">&#39;cuda:0&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 检测人体</span>
</span></span><span class="line"><span class="cl"><span class="n">det_result</span> <span class="o">=</span> <span class="n">inference_detector</span><span class="p">(</span><span class="n">detector</span><span class="p">,</span> <span class="n">image</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">bbox</span> <span class="o">=</span> <span class="n">det_result</span><span class="o">.</span><span class="n">pred_instances</span><span class="o">.</span><span class="n">bboxes</span>  <span class="c1"># 获取检测框</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 姿态估计</span>
</span></span><span class="line"><span class="cl"><span class="n">pose_result</span> <span class="o">=</span> <span class="n">inference_topdown</span><span class="p">(</span><span class="n">model</span><span class="p">,</span> <span class="n">image</span><span class="p">,</span> <span class="n">bbox</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">pose_result</span> <span class="o">=</span> <span class="n">merge_data_samples</span><span class="p">(</span><span class="n">pose_result</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 可视化结果</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">mmpose.visualization</span> <span class="kn">import</span> <span class="n">PoseLocalVisualizer</span>
</span></span><span class="line"><span class="cl"><span class="n">visualizer</span> <span class="o">=</span> <span class="n">PoseLocalVisualizer</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">visualizer</span><span class="o">.</span><span class="n">set_dataset_meta</span><span class="p">(</span><span class="n">model</span><span class="o">.</span><span class="n">dataset_meta</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">img_vis</span> <span class="o">=</span> <span class="n">visualizer</span><span class="o">.</span><span class="n">add_datasample</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;result&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">image</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">pose_result</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">draw_gt</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">show</span><span class="o">=</span><span class="kc">False</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">cv2</span><span class="o">.</span><span class="n">imwrite</span><span class="p">(</span><span class="s1">&#39;output.jpg&#39;</span><span class="p">,</span> <span class="n">img_vis</span><span class="p">)</span></span></span></code></pre></div></div>
<h3 id="2-简化版本使用-mmpose-3x">2. 简化版本（使用 MMPose 3.x）</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-python">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">mmpose.apis</span> <span class="kn">import</span> <span class="n">MMPoseInferencer</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 初始化推理器（自动处理检测）</span>
</span></span><span class="line"><span class="cl"><span class="n">inferencer</span> <span class="o">=</span> <span class="n">MMPoseInferencer</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">pose2d</span><span class="o">=</span><span class="s1">&#39;rtmpose-m&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">det_model</span><span class="o">=</span><span class="s1">&#39;rtmdet_tiny&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">device</span><span class="o">=</span><span class="s1">&#39;cuda:0&#39;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 推理</span>
</span></span><span class="line"><span class="cl"><span class="n">result</span> <span class="o">=</span> <span class="n">inferencer</span><span class="p">(</span><span class="s1">&#39;test_image.jpg&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 获取关键点</span>
</span></span><span class="line"><span class="cl"><span class="n">keypoints</span> <span class="o">=</span> <span class="n">result</span><span class="p">[</span><span class="s1">&#39;predictions&#39;</span><span class="p">][</span><span class="mi">0</span><span class="p">][</span><span class="s1">&#39;keypoints&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;检测到 </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">keypoints</span><span class="p">)</span><span class="si">}</span><span class="s2"> 个关键点&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 保存可视化结果</span>
</span></span><span class="line"><span class="cl"><span class="n">inferencer</span><span class="p">(</span><span class="s1">&#39;test_image.jpg&#39;</span><span class="p">,</span> <span class="n">out_dir</span><span class="o">=</span><span class="s1">&#39;output/&#39;</span><span class="p">,</span> <span class="n">show</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span></code></pre></div></div>
<hr>
<h2 id="关键点说明">关键点说明</h2>
<h3 id="coco-数据集-17-个关键点">COCO 数据集 17 个关键点</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-python">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">COCO_KEYPOINTS</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;nose&#39;</span><span class="p">,</span>           <span class="c1"># 0</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;left_eye&#39;</span><span class="p">,</span>       <span class="c1"># 1</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;right_eye&#39;</span><span class="p">,</span>      <span class="c1"># 2</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;left_ear&#39;</span><span class="p">,</span>       <span class="c1"># 3</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;right_ear&#39;</span><span class="p">,</span>      <span class="c1"># 4</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;left_shoulder&#39;</span><span class="p">,</span>  <span class="c1"># 5</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;right_shoulder&#39;</span><span class="p">,</span> <span class="c1"># 6</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;left_elbow&#39;</span><span class="p">,</span>     <span class="c1"># 7</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;right_elbow&#39;</span><span class="p">,</span>    <span class="c1"># 8</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;left_wrist&#39;</span><span class="p">,</span>     <span class="c1"># 9</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;right_wrist&#39;</span><span class="p">,</span>    <span class="c1"># 10</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;left_hip&#39;</span><span class="p">,</span>       <span class="c1"># 11</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;right_hip&#39;</span><span class="p">,</span>      <span class="c1"># 12</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;left_knee&#39;</span><span class="p">,</span>      <span class="c1"># 13</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;right_knee&#39;</span><span class="p">,</span>     <span class="c1"># 14</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;left_ankle&#39;</span><span class="p">,</span>     <span class="c1"># 15</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;right_ankle&#39;</span>     <span class="c1"># 16</span>
</span></span><span class="line"><span class="cl"><span class="p">]</span></span></span></code></pre></div></div>
<h3 id="关键点置信度">关键点置信度</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-python">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="c1"># 每个关键点包含 (x, y, confidence)</span>
</span></span><span class="line"><span class="cl"><span class="n">keypoint</span> <span class="o">=</span> <span class="n">keypoints</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>  <span class="c1"># 例如鼻子</span>
</span></span><span class="line"><span class="cl"><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">conf</span> <span class="o">=</span> <span class="n">keypoint</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 过滤低置信度关键点</span>
</span></span><span class="line"><span class="cl"><span class="n">valid_keypoints</span> <span class="o">=</span> <span class="p">[</span><span class="n">kp</span> <span class="k">for</span> <span class="n">kp</span> <span class="ow">in</span> <span class="n">keypoints</span> <span class="k">if</span> <span class="n">kp</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mf">0.5</span><span class="p">]</span></span></span></code></pre></div></div>
<hr>
<h2 id="实战人体动作捕捉系统">实战：人体动作捕捉系统</h2>
<h3 id="完整代码示例">完整代码示例</h3>
<div class="code-block code-line-numbers" style="counter-reset: code-block 0">
    <div class="code-header language-python">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">人体姿态估计与动作捕捉系统
</span></span></span><span class="line"><span class="cl"><span class="s2">支持实时视频处理和骨骼绘制
</span></span></span><span class="line"><span class="cl"><span class="s2">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">cv2</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">mmpose.apis</span> <span class="kn">import</span> <span class="n">MMPoseInferencer</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span><span class="p">,</span> <span class="n">Tuple</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">PoseCapture</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> 
</span></span><span class="line"><span class="cl">                 <span class="n">pose_model</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s1">&#39;rtmpose-m&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                 <span class="n">det_model</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s1">&#39;rtmdet_tiny&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                 <span class="n">device</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s1">&#39;cuda:0&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                 <span class="n">conf_threshold</span><span class="p">:</span> <span class="nb">float</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">        初始化姿态捕捉器
</span></span></span><span class="line"><span class="cl"><span class="s2">        
</span></span></span><span class="line"><span class="cl"><span class="s2">        Args:
</span></span></span><span class="line"><span class="cl"><span class="s2">            pose_model: 姿态估计模型
</span></span></span><span class="line"><span class="cl"><span class="s2">            det_model: 人体检测模型
</span></span></span><span class="line"><span class="cl"><span class="s2">            device: 计算设备
</span></span></span><span class="line"><span class="cl"><span class="s2">            conf_threshold: 置信度阈值
</span></span></span><span class="line"><span class="cl"><span class="s2">        &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">inferencer</span> <span class="o">=</span> <span class="n">MMPoseInferencer</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="n">pose2d</span><span class="o">=</span><span class="n">pose_model</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">det_model</span><span class="o">=</span><span class="n">det_model</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">device</span><span class="o">=</span><span class="n">device</span>
</span></span><span class="line"><span class="cl">        <span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">conf_threshold</span> <span class="o">=</span> <span class="n">conf_threshold</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="c1"># 骨骼连接关系（COCO 格式）</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">skeleton</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">4</span><span class="p">),</span>    <span class="c1"># 头部</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">),</span>                             <span class="c1"># 肩膀</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">7</span><span class="p">),</span> <span class="p">(</span><span class="mi">7</span><span class="p">,</span> <span class="mi">9</span><span class="p">),</span>                    <span class="c1"># 左臂</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mi">6</span><span class="p">,</span> <span class="mi">8</span><span class="p">),</span> <span class="p">(</span><span class="mi">8</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span>                   <span class="c1"># 右臂</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">11</span><span class="p">),</span> <span class="p">(</span><span class="mi">6</span><span class="p">,</span> <span class="mi">12</span><span class="p">),</span>                  <span class="c1"># 躯干</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mi">11</span><span class="p">,</span> <span class="mi">13</span><span class="p">),</span> <span class="p">(</span><span class="mi">13</span><span class="p">,</span> <span class="mi">15</span><span class="p">),</span>                <span class="c1"># 左腿</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mi">12</span><span class="p">,</span> <span class="mi">14</span><span class="p">),</span> <span class="p">(</span><span class="mi">14</span><span class="p">,</span> <span class="mi">16</span><span class="p">)</span>                 <span class="c1"># 右腿</span>
</span></span><span class="line"><span class="cl">        <span class="p">]</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="c1"># 颜色映射</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">colors</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mi">255</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">255</span><span class="p">,</span> <span class="mi">85</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">255</span><span class="p">,</span> <span class="mi">170</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mi">255</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">170</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">85</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="mi">85</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="mi">170</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="mi">255</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">170</span><span class="p">,</span> <span class="mi">255</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">85</span><span class="p">,</span> <span class="mi">255</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">),</span> <span class="p">(</span><span class="mi">85</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">),</span> <span class="p">(</span><span class="mi">170</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mi">255</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">),</span> <span class="p">(</span><span class="mi">255</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">170</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">]</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">process_frame</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">frame</span><span class="p">:</span> <span class="n">np</span><span class="o">.</span><span class="n">ndarray</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Tuple</span><span class="p">[</span><span class="n">np</span><span class="o">.</span><span class="n">ndarray</span><span class="p">,</span> <span class="nb">dict</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">        处理单帧图像
</span></span></span><span class="line"><span class="cl"><span class="s2">        
</span></span></span><span class="line"><span class="cl"><span class="s2">        Args:
</span></span></span><span class="line"><span class="cl"><span class="s2">            frame: 输入图像
</span></span></span><span class="line"><span class="cl"><span class="s2">            
</span></span></span><span class="line"><span class="cl"><span class="s2">        Returns:
</span></span></span><span class="line"><span class="cl"><span class="s2">            绘制骨骼的图像，姿态数据
</span></span></span><span class="line"><span class="cl"><span class="s2">        &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 推理</span>
</span></span><span class="line"><span class="cl">        <span class="n">result</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">inferencer</span><span class="p">(</span><span class="n">frame</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="c1"># 提取关键点</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="s1">&#39;predictions&#39;</span> <span class="ow">in</span> <span class="n">result</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">result</span><span class="p">[</span><span class="s1">&#39;predictions&#39;</span><span class="p">])</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">keypoints</span> <span class="o">=</span> <span class="n">result</span><span class="p">[</span><span class="s1">&#39;predictions&#39;</span><span class="p">][</span><span class="mi">0</span><span class="p">][</span><span class="s1">&#39;keypoints&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">            <span class="n">scores</span> <span class="o">=</span> <span class="n">result</span><span class="p">[</span><span class="s1">&#39;predictions&#39;</span><span class="p">][</span><span class="mi">0</span><span class="p">][</span><span class="s1">&#39;keypoint_scores&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">keypoints</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">            <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="c1"># 绘制骨骼</span>
</span></span><span class="line"><span class="cl">        <span class="n">output_frame</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">draw_skeleton</span><span class="p">(</span><span class="n">frame</span><span class="o">.</span><span class="n">copy</span><span class="p">(),</span> <span class="n">keypoints</span><span class="p">,</span> <span class="n">scores</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">output_frame</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s1">&#39;keypoints&#39;</span><span class="p">:</span> <span class="n">keypoints</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s1">&#39;scores&#39;</span><span class="p">:</span> <span class="n">scores</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">draw_skeleton</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> 
</span></span><span class="line"><span class="cl">                      <span class="n">frame</span><span class="p">:</span> <span class="n">np</span><span class="o">.</span><span class="n">ndarray</span><span class="p">,</span> 
</span></span><span class="line"><span class="cl">                      <span class="n">keypoints</span><span class="p">:</span> <span class="n">List</span><span class="p">,</span> 
</span></span><span class="line"><span class="cl">                      <span class="n">scores</span><span class="p">:</span> <span class="n">List</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">np</span><span class="o">.</span><span class="n">ndarray</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">        绘制人体骨骼
</span></span></span><span class="line"><span class="cl"><span class="s2">        
</span></span></span><span class="line"><span class="cl"><span class="s2">        Args:
</span></span></span><span class="line"><span class="cl"><span class="s2">            frame: 输入图像
</span></span></span><span class="line"><span class="cl"><span class="s2">            keypoints: 关键点列表
</span></span></span><span class="line"><span class="cl"><span class="s2">            scores: 置信度列表
</span></span></span><span class="line"><span class="cl"><span class="s2">            
</span></span></span><span class="line"><span class="cl"><span class="s2">        Returns:
</span></span></span><span class="line"><span class="cl"><span class="s2">            绘制骨骼后的图像
</span></span></span><span class="line"><span class="cl"><span class="s2">        &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">person_idx</span><span class="p">,</span> <span class="p">(</span><span class="n">kp</span><span class="p">,</span> <span class="n">score</span><span class="p">)</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">keypoints</span><span class="p">,</span> <span class="n">scores</span><span class="p">)):</span>
</span></span><span class="line"><span class="cl">            <span class="c1"># 过滤低置信度关键点</span>
</span></span><span class="line"><span class="cl">            <span class="n">valid_mask</span> <span class="o">=</span> <span class="n">score</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">conf_threshold</span>
</span></span><span class="line"><span class="cl">            <span class="n">valid_kp</span> <span class="o">=</span> <span class="n">kp</span><span class="p">[</span><span class="n">valid_mask</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">            
</span></span><span class="line"><span class="cl">            <span class="c1"># 绘制关键点</span>
</span></span><span class="line"><span class="cl">            <span class="k">for</span> <span class="n">idx</span><span class="p">,</span> <span class="n">point</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">kp</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="n">score</span><span class="p">[</span><span class="n">idx</span><span class="p">]</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">conf_threshold</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                    <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">point</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="nb">int</span><span class="p">(</span><span class="n">point</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">                    <span class="n">color</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">colors</span><span class="p">[</span><span class="n">idx</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">colors</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl">                    <span class="n">cv2</span><span class="o">.</span><span class="n">circle</span><span class="p">(</span><span class="n">frame</span><span class="p">,</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">),</span> <span class="mi">5</span><span class="p">,</span> <span class="n">color</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            
</span></span><span class="line"><span class="cl">            <span class="c1"># 绘制骨骼连接</span>
</span></span><span class="line"><span class="cl">            <span class="k">for</span> <span class="n">bone</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">skeleton</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="n">idx1</span><span class="p">,</span> <span class="n">idx2</span> <span class="o">=</span> <span class="n">bone</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="p">(</span><span class="n">idx1</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">kp</span><span class="p">)</span> <span class="ow">and</span> <span class="n">idx2</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">kp</span><span class="p">)</span> <span class="ow">and</span>
</span></span><span class="line"><span class="cl">                    <span class="n">score</span><span class="p">[</span><span class="n">idx1</span><span class="p">]</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">conf_threshold</span> <span class="ow">and</span>
</span></span><span class="line"><span class="cl">                    <span class="n">score</span><span class="p">[</span><span class="n">idx2</span><span class="p">]</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">conf_threshold</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">                    
</span></span><span class="line"><span class="cl">                    <span class="n">pt1</span> <span class="o">=</span> <span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">kp</span><span class="p">[</span><span class="n">idx1</span><span class="p">][</span><span class="mi">0</span><span class="p">]),</span> <span class="nb">int</span><span class="p">(</span><span class="n">kp</span><span class="p">[</span><span class="n">idx1</span><span class="p">][</span><span class="mi">1</span><span class="p">]))</span>
</span></span><span class="line"><span class="cl">                    <span class="n">pt2</span> <span class="o">=</span> <span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">kp</span><span class="p">[</span><span class="n">idx2</span><span class="p">][</span><span class="mi">0</span><span class="p">]),</span> <span class="nb">int</span><span class="p">(</span><span class="n">kp</span><span class="p">[</span><span class="n">idx2</span><span class="p">][</span><span class="mi">1</span><span class="p">]))</span>
</span></span><span class="line"><span class="cl">                    <span class="n">color</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">colors</span><span class="p">[</span><span class="n">idx1</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">colors</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl">                    <span class="n">cv2</span><span class="o">.</span><span class="n">line</span><span class="p">(</span><span class="n">frame</span><span class="p">,</span> <span class="n">pt1</span><span class="p">,</span> <span class="n">pt2</span><span class="p">,</span> <span class="n">color</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">frame</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">process_video</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> 
</span></span><span class="line"><span class="cl">                      <span class="n">input_path</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> 
</span></span><span class="line"><span class="cl">                      <span class="n">output_path</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                      <span class="n">show</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">        处理视频文件
</span></span></span><span class="line"><span class="cl"><span class="s2">        
</span></span></span><span class="line"><span class="cl"><span class="s2">        Args:
</span></span></span><span class="line"><span class="cl"><span class="s2">            input_path: 输入视频路径
</span></span></span><span class="line"><span class="cl"><span class="s2">            output_path: 输出视频路径
</span></span></span><span class="line"><span class="cl"><span class="s2">            show: 是否实时显示
</span></span></span><span class="line"><span class="cl"><span class="s2">        &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="n">cap</span> <span class="o">=</span> <span class="n">cv2</span><span class="o">.</span><span class="n">VideoCapture</span><span class="p">(</span><span class="n">input_path</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="c1"># 获取视频信息</span>
</span></span><span class="line"><span class="cl">        <span class="n">fps</span> <span class="o">=</span> <span class="n">cap</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">cv2</span><span class="o">.</span><span class="n">CAP_PROP_FPS</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">width</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">cap</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">cv2</span><span class="o">.</span><span class="n">CAP_PROP_FRAME_WIDTH</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        <span class="n">height</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">cap</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">cv2</span><span class="o">.</span><span class="n">CAP_PROP_FRAME_HEIGHT</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="c1"># 创建写入器</span>
</span></span><span class="line"><span class="cl">        <span class="n">fourcc</span> <span class="o">=</span> <span class="n">cv2</span><span class="o">.</span><span class="n">VideoWriter_fourcc</span><span class="p">(</span><span class="o">*</span><span class="s1">&#39;mp4v&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">out</span> <span class="o">=</span> <span class="n">cv2</span><span class="o">.</span><span class="n">VideoWriter</span><span class="p">(</span><span class="n">output_path</span><span class="p">,</span> <span class="n">fourcc</span><span class="p">,</span> <span class="n">fps</span><span class="p">,</span> <span class="p">(</span><span class="n">width</span><span class="p">,</span> <span class="n">height</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="n">frame_count</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">        <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">ret</span><span class="p">,</span> <span class="n">frame</span> <span class="o">=</span> <span class="n">cap</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="ow">not</span> <span class="n">ret</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="k">break</span>
</span></span><span class="line"><span class="cl">            
</span></span><span class="line"><span class="cl">            <span class="c1"># 处理帧</span>
</span></span><span class="line"><span class="cl">            <span class="n">output_frame</span><span class="p">,</span> <span class="n">pose_data</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">process_frame</span><span class="p">(</span><span class="n">frame</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            
</span></span><span class="line"><span class="cl">            <span class="c1"># 显示 FPS</span>
</span></span><span class="line"><span class="cl">            <span class="n">cv2</span><span class="o">.</span><span class="n">putText</span><span class="p">(</span><span class="n">output_frame</span><span class="p">,</span> <span class="sa">f</span><span class="s1">&#39;Frame: </span><span class="si">{</span><span class="n">frame_count</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">,</span> 
</span></span><span class="line"><span class="cl">                       <span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">30</span><span class="p">),</span> <span class="n">cv2</span><span class="o">.</span><span class="n">FONT_HERSHEY_SIMPLEX</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="mi">2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            
</span></span><span class="line"><span class="cl">            <span class="c1"># 写入输出</span>
</span></span><span class="line"><span class="cl">            <span class="n">out</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">output_frame</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            
</span></span><span class="line"><span class="cl">            <span class="c1"># 显示</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="n">show</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="n">cv2</span><span class="o">.</span><span class="n">imshow</span><span class="p">(</span><span class="s1">&#39;Pose Capture&#39;</span><span class="p">,</span> <span class="n">output_frame</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="n">cv2</span><span class="o">.</span><span class="n">waitKey</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFF</span> <span class="o">==</span> <span class="nb">ord</span><span class="p">(</span><span class="s1">&#39;q&#39;</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">                    <span class="k">break</span>
</span></span><span class="line"><span class="cl">            
</span></span><span class="line"><span class="cl">            <span class="n">frame_count</span> <span class="o">+=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="n">frame_count</span> <span class="o">%</span> <span class="mi">30</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Processed </span><span class="si">{</span><span class="n">frame_count</span><span class="si">}</span><span class="s2"> frames&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="n">cap</span><span class="o">.</span><span class="n">release</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="n">out</span><span class="o">.</span><span class="n">release</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="n">cv2</span><span class="o">.</span><span class="n">destroyAllWindows</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Video processed: </span><span class="si">{</span><span class="n">output_path</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 使用示例</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">&#39;__main__&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># 初始化</span>
</span></span><span class="line"><span class="cl">    <span class="n">capture</span> <span class="o">=</span> <span class="n">PoseCapture</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1"># 处理单张图片</span>
</span></span><span class="line"><span class="cl">    <span class="kn">import</span> <span class="nn">cv2</span>
</span></span><span class="line"><span class="cl">    <span class="n">image</span> <span class="o">=</span> <span class="n">cv2</span><span class="o">.</span><span class="n">imread</span><span class="p">(</span><span class="s1">&#39;input.jpg&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">output</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">capture</span><span class="o">.</span><span class="n">process_frame</span><span class="p">(</span><span class="n">image</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">cv2</span><span class="o">.</span><span class="n">imwrite</span><span class="p">(</span><span class="s1">&#39;output.jpg&#39;</span><span class="p">,</span> <span class="n">output</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1"># 处理视频</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># capture.process_video(&#39;input.mp4&#39;, &#39;output.mp4&#39;, show=True)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1"># 处理摄像头</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># capture.process_video(0, &#39;webcam_output.mp4&#39;, show=True)</span></span></span></code></pre></div></div>
<hr>
<h2 id="高级应用">高级应用</h2>
<h3 id="1-多人姿态估计">1. 多人姿态估计</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-python">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">process_multi_person</span><span class="p">(</span><span class="n">frame</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="n">inferencer</span><span class="p">(</span><span class="n">frame</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">person_idx</span><span class="p">,</span> <span class="n">prediction</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">result</span><span class="p">[</span><span class="s1">&#39;predictions&#39;</span><span class="p">][</span><span class="mi">0</span><span class="p">][</span><span class="s1">&#39;keypoints&#39;</span><span class="p">]):</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Person </span><span class="si">{</span><span class="n">person_idx</span><span class="si">}</span><span class="s2">: </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">prediction</span><span class="p">)</span><span class="si">}</span><span class="s2"> keypoints&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="c1"># 计算每个人的人体中心</span>
</span></span><span class="line"><span class="cl">        <span class="n">center</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="n">prediction</span><span class="p">[:,</span> <span class="p">:</span><span class="mi">2</span><span class="p">],</span> <span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Center: </span><span class="si">{</span><span class="n">center</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span></span></span></code></pre></div></div>
<h3 id="2-动作识别">2. 动作识别</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-python">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">recognize_action</span><span class="p">(</span><span class="n">keypoints</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">    基于关键点识别简单动作
</span></span></span><span class="line"><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># 获取关键点</span>
</span></span><span class="line"><span class="cl">    <span class="n">nose</span> <span class="o">=</span> <span class="n">keypoints</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">left_shoulder</span> <span class="o">=</span> <span class="n">keypoints</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">right_shoulder</span> <span class="o">=</span> <span class="n">keypoints</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">left_hip</span> <span class="o">=</span> <span class="n">keypoints</span><span class="p">[</span><span class="mi">11</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">right_hip</span> <span class="o">=</span> <span class="n">keypoints</span><span class="p">[</span><span class="mi">12</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1"># 计算身体角度</span>
</span></span><span class="line"><span class="cl">    <span class="n">shoulder_vec</span> <span class="o">=</span> <span class="n">right_shoulder</span><span class="p">[:</span><span class="mi">2</span><span class="p">]</span> <span class="o">-</span> <span class="n">left_shoulder</span><span class="p">[:</span><span class="mi">2</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">hip_vec</span> <span class="o">=</span> <span class="n">right_hip</span><span class="p">[:</span><span class="mi">2</span><span class="p">]</span> <span class="o">-</span> <span class="n">left_hip</span><span class="p">[:</span><span class="mi">2</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="c1"># 判断站立/坐下</span>
</span></span><span class="line"><span class="cl">    <span class="n">body_height</span> <span class="o">=</span> <span class="nb">abs</span><span class="p">(</span><span class="n">nose</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="p">(</span><span class="n">left_hip</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">right_hip</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="o">/</span> <span class="mi">2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">body_height</span> <span class="o">&lt;</span> <span class="mi">50</span><span class="p">:</span>  <span class="c1"># 阈值需要根据实际情况调整</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="s2">&#34;sitting&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="s2">&#34;standing&#34;</span></span></span></code></pre></div></div>
<h3 id="3-姿态数据导出">3. 姿态数据导出</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-python">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">json</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">export_pose_data</span><span class="p">(</span><span class="n">results</span><span class="p">,</span> <span class="n">output_file</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;导出姿态数据为 JSON&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">data</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;frames&#39;</span><span class="p">:</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">frame_result</span> <span class="ow">in</span> <span class="n">results</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">frame_data</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="s1">&#39;keypoints&#39;</span><span class="p">:</span> <span class="n">frame_result</span><span class="p">[</span><span class="s1">&#39;keypoints&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">tolist</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">            <span class="s1">&#39;scores&#39;</span><span class="p">:</span> <span class="n">frame_result</span><span class="p">[</span><span class="s1">&#39;keypoint_scores&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">tolist</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="n">data</span><span class="p">[</span><span class="s1">&#39;frames&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">frame_data</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">output_file</span><span class="p">,</span> <span class="s1">&#39;w&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">json</span><span class="o">.</span><span class="n">dump</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">f</span><span class="p">,</span> <span class="n">indent</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Exported to </span><span class="si">{</span><span class="n">output_file</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span></span></span></code></pre></div></div>
<hr>
<h2 id="模型选择指南">模型选择指南</h2>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>速度</th>
          <th>精度</th>
          <th>适用场景</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>RTMPose-m</td>
          <td>快</td>
          <td>高</td>
          <td>实时应用</td>
      </tr>
      <tr>
          <td>RTMPose-l</td>
          <td>中</td>
          <td>很高</td>
          <td>离线处理</td>
      </tr>
      <tr>
          <td>ViTPose-B</td>
          <td>慢</td>
          <td>最高</td>
          <td>高精度需求</td>
      </tr>
      <tr>
          <td>HRNet-W32</td>
          <td>中</td>
          <td>高</td>
          <td>通用场景</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="部署优化">部署优化</h2>
<h3 id="onnx-导出">ONNX 导出</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 导出为 ONNX</span>
</span></span><span class="line"><span class="cl">python tools/deployment/pytorch2onnx.py <span class="se">\
</span></span></span><span class="line"><span class="cl">    configs/body_2d_keypoint/rtmpose/rtmpose-m_simcc-aic-coco.py <span class="se">\
</span></span></span><span class="line"><span class="cl">    checkpoints/rtmpose-m.pth <span class="se">\
</span></span></span><span class="line"><span class="cl">    --output-file rtmpose-m.onnx <span class="se">\
</span></span></span><span class="line"><span class="cl">    --input-shape <span class="m">1</span> <span class="m">3</span> <span class="m">256</span> <span class="m">192</span></span></span></code></pre></div></div>
<h3 id="tensorrt-加速">TensorRT 加速</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-python">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">tensorrt</span> <span class="k">as</span> <span class="nn">trt</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 加载 ONNX 模型</span>
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s1">&#39;rtmpose-m.onnx&#39;</span><span class="p">,</span> <span class="s1">&#39;rb&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">network</span> <span class="o">=</span> <span class="n">trt</span><span class="o">.</span><span class="n">load_network</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 构建 TensorRT 引擎</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ... (详细配置参考 TensorRT 文档)</span></span></span></code></pre></div></div>
<hr>
<h2 id="常见问题">常见问题</h2>
<h3 id="q1-检测不到人体">Q1: 检测不到人体？</h3>
<ul>
<li>检查检测模型是否正确加载</li>
<li>调整检测置信度阈值</li>
<li>确保图像中有人体且清晰</li>
</ul>
<h3 id="q2-关键点抖动">Q2: 关键点抖动？</h3>
<ul>
<li>使用 temporal smoothing</li>
<li>增加置信度阈值</li>
<li>使用更高质量的模型</li>
</ul>
<h3 id="q3-实时性不够">Q3: 实时性不够？</h3>
<ul>
<li>使用 RTMPose-tiny</li>
<li>降低输入分辨率</li>
<li>使用 TensorRT 加速</li>
</ul>
<hr>
<h2 id="总结">总结</h2>
<p>MMPose 是功能强大的人体姿态估计工具：</p>]]></description></item></channel></rss>