<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>深度估计 on CloudLake</title><link>https://cloudlake.eu.org/tags/%E6%B7%B1%E5%BA%A6%E4%BC%B0%E8%AE%A1/</link><description>Recent content in 深度估计 on CloudLake</description><generator>Hugo -- gohugo.io</generator><language>zh-CN</language><lastBuildDate>Tue, 20 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://cloudlake.eu.org/tags/%E6%B7%B1%E5%BA%A6%E4%BC%B0%E8%AE%A1/index.xml" rel="self" type="application/rss+xml"/><item><title>给 AI 装上一双能测距的眼睛</title><link>https://cloudlake.eu.org/p/visionmate/</link><pubDate>Tue, 20 Oct 2026 00:00:00 +0000</pubDate><guid>https://cloudlake.eu.org/p/visionmate/</guid><description>&lt;img src="https://cloudlake.eu.org/p/visionmate/cover.jpg" alt="Featured image of post 给 AI 装上一双能测距的眼睛" /&gt;&lt;p&gt;你戴着它，问一句「前面有什么」。&lt;/p&gt;&#10;&lt;p&gt;它需要回答的其实&lt;strong&gt;不是&lt;/strong&gt;「前面有一个人」——而是「&lt;strong&gt;前面 0.8 米有一个人&lt;/strong&gt;」。&lt;/p&gt;&#10;&lt;p&gt;这两句话对一个只会做目标检测的系统来说，差着一整个维度。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="只有-2d-检测是看不见多远的"&gt;&lt;a href="#%e5%8f%aa%e6%9c%89-2d-%e6%a3%80%e6%b5%8b%e6%98%af%e7%9c%8b%e4%b8%8d%e8%a7%81%e5%a4%9a%e8%bf%9c%e7%9a%84" class="header-anchor"&gt;&lt;/a&gt;只有 2D 检测，是看不见「多远」的&#10;&lt;/h2&gt;&lt;p&gt;YOLO 能给你一个框、一个类别、一个置信度。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;person 0.89 [x1,y1,x2,y2]&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;但它不知道这个人在一米外还是五米外。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;而这件事在真实场景里是致命的：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;「前面有人」→ 你继续走&lt;/li&gt;&#10;&lt;li&gt;「前面 0.4 米有人」→ 你必须停&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;同一个检测结果，两种完全相反的行动。&lt;/p&gt;&#10;&lt;p&gt;所以我给这个系统加了两个东西：&lt;strong&gt;深度估计&lt;/strong&gt;和&lt;strong&gt;激光雷达&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="三层感知"&gt;&lt;a href="#%e4%b8%89%e5%b1%82%e6%84%9f%e7%9f%a5" class="header-anchor"&gt;&lt;/a&gt;三层感知&#10;&lt;/h2&gt;&lt;p&gt;&lt;img alt="VisionMate 感知管线" class="gallery-image" data-flex-basis="473px" data-flex-grow="197" height="760" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://cloudlake.eu.org/p/visionmate/vision-pipeline.jpg" srcset="https://cloudlake.eu.org/p/visionmate/vision-pipeline_hu_af1eff1de34b85b2.jpg 800w, https://cloudlake.eu.org/p/visionmate/vision-pipeline.jpg 1500w" width="1500"&gt;&lt;/p&gt;&#10;&lt;p&gt;整个系统的骨架是这样的：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;层&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;干什么&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;① 输入&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;文本指令，或 Whisper 实时语音转写&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;② 调度&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Orchestrator 把自然语言映射到一个视觉能力&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;③ 视觉&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;YOLOv8n 检测 / MiDaS 深度 / EasyOCR 文字&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;④ 标定&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;用 LiDAR 快照重标定深度尺度&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;⑤ 输出&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;hazard_level&lt;/code&gt; + 人话 message + 结构化 meta&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;对外是 &lt;strong&gt;FastAPI 的 MCP 接口&lt;/strong&gt;：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;POST&lt;/span&gt; &lt;span class="err"&gt;/api/v&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;/mcp&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;描述周围&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;返回里既有给人看的句子，也有给程序用的字段。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="五个能力带优先级"&gt;&lt;a href="#%e4%ba%94%e4%b8%aa%e8%83%bd%e5%8a%9b%e5%b8%a6%e4%bc%98%e5%85%88%e7%ba%a7" class="header-anchor"&gt;&lt;/a&gt;五个能力，带优先级&#10;&lt;/h2&gt;&lt;p&gt;调度器不猜——它把指令映射到一个明确的 function：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;vision.ocr_read&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;high&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# 读文字&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;vision.detect_objects&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;medium&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# 检测物体&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;vision.distance_query&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;medium&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# 问距离&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;vision.describe_scene&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;medium&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# 描述场景&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;vision.check_hazards&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;low&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# 判断危险&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;&lt;code&gt;check_hazards&lt;/code&gt; 优先级最低，因为它&lt;strong&gt;要调用前面全部能力&lt;/strong&gt;才能回答——它是管线末端，不是入口。&lt;/p&gt;&#10;&lt;p&gt;意图分类有两路：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;规则匹配&lt;/strong&gt;（关键词、正则）—— 快、可预测&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;sklearn 模型&lt;/strong&gt;（&lt;code&gt;intent_sklearn.joblib&lt;/code&gt;，965 KB）—— 处理规则覆盖不到的说法&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;规则优先，模型兜底。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="核心设计lidar-只做标定不做判定"&gt;&lt;a href="#%e6%a0%b8%e5%bf%83%e8%ae%be%e8%ae%a1lidar-%e5%8f%aa%e5%81%9a%e6%a0%87%e5%ae%9a%e4%b8%8d%e5%81%9a%e5%88%a4%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;核心设计：LiDAR 只做标定，不做判定&#10;&lt;/h2&gt;&lt;p&gt;这是整个项目里我最想讲的一个决定。&lt;/p&gt;&#10;&lt;p&gt;先说结论（这也是代码注释里的原话）：&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&lt;strong&gt;基于视觉深度和 YOLO 距离统一评估危险，LiDAR 仅用于深度标定。&lt;/strong&gt;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;h3 id="为什么不直接用雷达测距"&gt;&lt;a href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e4%b8%8d%e7%9b%b4%e6%8e%a5%e7%94%a8%e9%9b%b7%e8%be%be%e6%b5%8b%e8%b7%9d" class="header-anchor"&gt;&lt;/a&gt;为什么不直接用雷达测距？&#10;&lt;/h3&gt;&lt;p&gt;因为雷达虽然准，但&lt;strong&gt;它只有一条线&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;forward_min_distance&lt;/code&gt; 是 ±30° 扇区内的最小距离——它告诉你「正前方最近的东西有多远」，但&lt;strong&gt;不告诉你是谁、有几个、在哪&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;如果我拿这个数字直接判定危险，会有两个问题：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;误报&lt;/strong&gt;：地上一个 5 厘米的纸盒，距离 0.3 米 → 判定「危险」。但你可以直接跨过去。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;漏报&lt;/strong&gt;：右边 0.5 米有个台阶，不在 ±30° 扇区内 → 雷达看不到，可你会撞上。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;&lt;strong&gt;雷达给的是标量，安全需要的是语义。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;h3 id="那怎么用雷达"&gt;&lt;a href="#%e9%82%a3%e6%80%8e%e4%b9%88%e7%94%a8%e9%9b%b7%e8%be%be" class="header-anchor"&gt;&lt;/a&gt;那怎么用雷达？&#10;&lt;/h3&gt;&lt;p&gt;把它当&lt;strong&gt;标尺&lt;/strong&gt;，不当&lt;strong&gt;裁判&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;MiDaS 输出的是&lt;strong&gt;相对深度&lt;/strong&gt;——它知道「这个人比那面墙近」，但不知道「近多少米」。所以：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. 先做线性投影，把相对深度映射到一个先验区间 near=0.4m, far=8.0m&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. 再用 LiDAR 的 forward_min_distance 对这个投影做一次重标定&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. 如果雷达认为近，就动态放宽 YOLO 的置信度阈值（0.5 → 0.3）&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;第 3 步是个很实用的联动：&lt;strong&gt;雷达说近，就宁可多报一点&lt;/strong&gt;。因为近距离下漏检的代价，远大于误检。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="深度估计可视化" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="720" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://cloudlake.eu.org/p/visionmate/vision-depth.jpg" srcset="https://cloudlake.eu.org/p/visionmate/vision-depth_hu_5c09b38f815b486a.jpg 800w, https://cloudlake.eu.org/p/visionmate/vision-depth.jpg 1280w" width="1280"&gt;&lt;/p&gt;&#10;&lt;p&gt;上图是 MiDaS 的输出叠加——颜色代表距离（暖色近、冷色远）。可以看出它能把空间关系画得很清楚，但&lt;strong&gt;具体数值需要标尺&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="危险分级"&gt;&lt;a href="#%e5%8d%b1%e9%99%a9%e5%88%86%e7%ba%a7" class="header-anchor"&gt;&lt;/a&gt;危险分级&#10;&lt;/h2&gt;&lt;p&gt;最终判定基于两条证据：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;nearest_box_dist&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hazard_level&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;danger&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# 有物体且极近&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;nearest_box_dist&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hazard_level&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;warning&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# 有物体但还远&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hazard_level&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;safe&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;没有检测到物体时，退回到&lt;strong&gt;视觉深度&lt;/strong&gt;给出的前方最小距离。&lt;/p&gt;&#10;&lt;p&gt;所以：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;有语义 → 用「谁 + 多远」&lt;/li&gt;&#10;&lt;li&gt;无语义 → 用「最近的表面多远」&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;两条路兜底，不会出现沉默失败。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="没有硬件也能跑stub-后端"&gt;&lt;a href="#%e6%b2%a1%e6%9c%89%e7%a1%ac%e4%bb%b6%e4%b9%9f%e8%83%bd%e8%b7%91stub-%e5%90%8e%e7%ab%af" class="header-anchor"&gt;&lt;/a&gt;没有硬件也能跑：Stub 后端&#10;&lt;/h2&gt;&lt;p&gt;这套系统依赖摄像头、激光雷达、YOLO 权重、MiDaS 权重。&lt;strong&gt;换一台机器就全没了。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;所以每个后端都有两套实现：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;真实后端&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Stub 后端&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;YOLOv8n&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;固定框 + 固定距离&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;MiDaS&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;合成深度图&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;EasyOCR&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;固定文本&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;LiDAR&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;模拟快照&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;配置文件一行就能切：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;SIMULATION_MODE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;这不是为了偷懒，是为了让测试能跑。&lt;/strong&gt; 有了 Stub，CI 里不需要 GPU、不需要串口、不需要摄像头，全套流程照样能验证。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="测试让软融合这个说法可被验证"&gt;&lt;a href="#%e6%b5%8b%e8%af%95%e8%ae%a9%e8%bd%af%e8%9e%8d%e5%90%88%e8%bf%99%e4%b8%aa%e8%af%b4%e6%b3%95%e5%8f%af%e8%a2%ab%e9%aa%8c%e8%af%81" class="header-anchor"&gt;&lt;/a&gt;测试：让「软融合」这个说法可被验证&#10;&lt;/h2&gt;&lt;p&gt;三个测试文件，分别守一件事：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;测试&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;在验证什么&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;test_p0_smoke&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;API 契约、分阶段耗时、雷达快照新鲜度&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;test_p1_lidar_soft_fusion&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;紧急闸门、自适应阈值&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;test_p2_depth_metadata&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;深度可用/缺失时的元数据与降级&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;其中最有价值的是 &lt;strong&gt;P1&lt;/strong&gt;：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;hazard_level&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;high&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;forward_min_distance&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;approx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;thresholds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;yolo_conf_threshold&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;approx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;这两条断言把「雷达软融合」从一个&lt;strong&gt;形容词&lt;/strong&gt;变成了一个&lt;strong&gt;可验证的行为&lt;/strong&gt;：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;雷达报 0.4 米 → 危险等级必须是 high&lt;/li&gt;&#10;&lt;li&gt;雷达报近 → 置信度阈值必须降到 0.3&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;如果哪天我重构代码把这个逻辑弄丢了，测试会立刻失败。&lt;/p&gt;&#10;&lt;p&gt;P2 守的是另一件事——&lt;strong&gt;深度失败时必须明确降级，而不是静默给出错误的距离&lt;/strong&gt;：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;depth_error&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;midas_missing&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dist&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;box&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;宁可承认「我不知道多远」，也不编一个数字。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="为什么这个项目值得做"&gt;&lt;a href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e8%bf%99%e4%b8%aa%e9%a1%b9%e7%9b%ae%e5%80%bc%e5%be%97%e5%81%9a" class="header-anchor"&gt;&lt;/a&gt;为什么这个项目值得做&#10;&lt;/h2&gt;&lt;p&gt;因为「AI 能看见」这件事，大多数人理解成「能识别」。&lt;/p&gt;&#10;&lt;p&gt;但识别和&lt;strong&gt;感知&lt;/strong&gt;是两件事：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;识别&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;感知&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;这是什么&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;这是什么 + 多远 + 算不算危险&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;一张图&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;连续的一段时间&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;给人看&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;给行动用&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;一个只会识别的系统，永远只能当玩具。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;要让它能驱动机器人、能辅助视障者、能放进 XR 头显——它必须先知道距离。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="技术栈"&gt;&lt;a href="#%e6%8a%80%e6%9c%af%e6%a0%88" class="header-anchor"&gt;&lt;/a&gt;技术栈&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Python&lt;/code&gt; · &lt;code&gt;FastAPI&lt;/code&gt; · &lt;code&gt;YOLOv8n&lt;/code&gt; · &lt;code&gt;MiDaS&lt;/code&gt; · &lt;code&gt;EasyOCR&lt;/code&gt; · &lt;code&gt;Whisper&lt;/code&gt; · &lt;code&gt;RPLIDAR A1&lt;/code&gt; · &lt;code&gt;scikit-learn&lt;/code&gt; · &lt;code&gt;pytest&lt;/code&gt;&lt;/p&gt;&#10;&lt;hr&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;这个项目最后教会我的，不是怎么调深度模型。&lt;/p&gt;&#10;&lt;p&gt;是&lt;strong&gt;「多一个传感器」不等于「多一份信任」&lt;/strong&gt;——多一个传感器，意味着你要更清楚地决定&lt;strong&gt;该在什么时候听它的&lt;/strong&gt;。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;</description></item></channel></rss>