编程语言研究书库

机器人视觉 — 摄像头、神经网络与颜色跟踪

机器人视觉 — 摄像头、神经网络与颜色跟踪

这一章讲什么: 摄像头上车,机器人从「感数」升级成「看图」。 三件套:① 相机核心(camera core)——取帧、标注(在画面上画出框和字)、经 MJPEG 推到浏览器, 检测数据走 MQTT;② 两条「看图」路线——神经网络(YuNet 人脸检测, 下载现成模型直接用)和颜色管线(HSV 掩码 + 轮廓提取,不用 AI); ③ 两个消费数据的行——云台 PID 追脸、轮子 PID 跟色块。 读完你会得到一个可复用的视觉服务架构,和一颗升级过的 PID(windup_limit)。

1. 先看现象:你手机上是机器人的眼睛

本章完成的画面:打开 Face detector 页,点 Start——手机屏幕出现摄像头画面, 你的脸上套着一个绿框,分数(比如 0.93)标在框上;你左右移动,机器人摇头跟着你。

把这一幕拆开,信息在四种介质里流转:光线(物理)→ 图像帧(内存)→ 标注后的 JPEG 流(给眼睛看)+ JSON 检测数据(给行为用)。 「给人看的」和「给机器用的」从同一帧分流——这是视觉系统的标准架构, 本章把它落成了代码。

2. 装配与联调:让摄像头先能出图

软件再漂亮,摄像头装不上车就全是零——原书把硬件装配列为本章第一题, 节奏是「算孔位 → 钻孔 → 装排线 → 通电首测 → 拉回第一张图」, 每一步都带验证动作和典型踩坑。1

先算孔位,再动手钻。 三个尺寸决定一切:云台头外形 36×38 mm; 摄像头自身的两个安装孔横向间距 21 mm、孔径 2.2 mm(纵向还有一对孔, 间距 14.5 mm)。摆放关系:下方那对孔会和云台头的槽位、背后的 tilt 舵机 发生干涉——弃用;上方那对用铜柱(stand-off,一头螺栓一头内螺纹的小柱, 把两件隔开固定)垫高,铜柱不是装饰,不让螺丝直接压到摄像头背面的 连接器。孔位两步算术:横向居中 =(36 − 21) ÷ 2 = 7.5 mm(距两侧各 7.5), 纵向从顶边往下 5.5 mm(避开云台头顶部的棱);钻头选 2.5 mm—— 最接近 M2 螺丝(直径 2 mm 的公制小螺丝规格)的常用钻头。 全程拒绝用胶:模块化、可替换是作者的机器人建筑原则, 胶粘的东西坏了得连件扔。2

动手两步:数显卡尺量出顶部 5.5 mm、两侧各 7.5 mm,用美工刀尖轻划构造线 (在塑料件上划出印即可);手捻钻——夹在指间手拧的小钻,转速低、 在塑料件上也好控制——沿划线交点钻出两个 2.5 mm 孔。两步都可以在机器人上 就位操作。扁嘴钳伸到背面捏住螺母,手指拧紧铜柱,不必再加钳。34

装排线:两个插座,蓝色都朝外。 排线是摄像头与 Pi 之间那条扁平柔性电缆, 两端各一个带卡扣的扁平插座。摄像头端:指甲轻撬排线卡扣,蓝色面朝自己 (正看着摄像头背面),排线平直插到底,压回卡扣,再用指甲沿卡扣刮一遍, 确认两侧都落座。装到云台时,排线先从 tilt head 与 pan base 之间的缝隙 穿过去,再上螺栓固定摄像头。树莓派端有个坑:板上有两个几乎一样的 扁平插座,要的是离 USB 口大块最近的那个;排线蓝色加强面朝向 USB 口, 平直插到底、压下卡扣。567

通电首测:先升级,再列相机,再拍照。 用树莓派电源供电(不要用电池); 相机软件更新频繁,先跑 pyinfra 全量升级(deploy/update_packages.py), sudo reboot 等绿灯回来。然后三级验证:8

命令验证什么不对的迹象
rpicam-still --list-cameras列出 imx708 传感器(4608×2592)和它的模式表No cameras available
rpicam-still --immediate --output test.jpg在 Pi 上留下一张 test.jpg命令报错
pyinfra inventory.py -- files.get test.jpg test.jpg -y把图拉回自己电脑,方向应该是正的看不到图 / 全黑

踩坑三连(原书排错)。 报错先怀疑命令敲错;命令没错就断电查排线; 图能拍但发黑,查光照——摄像头对光线敏感,光不够, 后面所有跟踪都白搭。9

如果错,会错在: 排线插反或插错插座。扁平排线插错方向不会冒烟, 只会不工作——No cameras available 就是它在说话,别先怀疑软件。

3. 顶层全景:相机核心 + 两种处理器 + 两类行为

 相机核心(公共库)      Picamera2 取帧 → 处理器 → Queue 缓冲 → Flask → MJPEG → 浏览器
        │                            │
        │                       检测数据 MQTT
        ▼                            ▼
 处理器 A:人脸          行为 A:云台 PID 追脸(舵机)
 (YuNet 神经网络)        行为 B:轮子 PID 跟随色块
 处理器 B:颜色          (目标在画面中的 x 误差 → 方向 PID;
 (HSV 掩码+轮廓)          目标尺寸 vs 期望尺寸 → 速度 PID)

 图说:核心稳定,处理器可换(模型动物园里还有表情/手势/姿态),行为随数据流。

4. 核心原理之一:帧与流——视频是图片,流是替换

视频 = 一连串静止图像,每一张叫一帧(frame)。 分辨率直接决定处理耗时, 所以本章用 704×364 的小帧;在 Pi 上,别指望超过 20 帧/秒10。

图像数据太大,塞不进 MQTT(第 8 章那条「总线带宽」纪律),所以走另一条路: MJPEG——把帧一张张 JPEG 编码,浏览器里的 <img> 元素不断被新帧替换, 看上去就是视频10。

相机核心(camera core) 是这个系统的公共骨架,设计上拆成两种帧流11:

  • sourcing(取帧):Picamera2 把帧交给处理器;
  • sinking(沉帧):处理器把标注过的帧(画了框)放进帧缓冲, Web 服务器从缓冲取帧发给浏览器。

缓冲用的是 multiprocessing.Queue(maxsize=2)——取帧进程和发流进程解耦: 处理器不等浏览器,浏览器也不堵处理器;只缓冲 2 帧,保证看的是「最近的」而不是 「排队等播放的」12。Web 服务器用 Flask,按 multipart/x-mixed-replace 逐帧响应; JPEG 质量 90,卡了就调低13。

架构决策背后有性能账:视觉服务吃 CPU 吃电,一律不自启, 由 launcher 按需拉起——和相机同生命周期14。

5. 核心原理之二:神经网络——不训练,只取用

本章给机器人上了第一个 AI 模型。先补齐神经网络的最小知识 (照原书的教法和顺序接住)15:

  • 人工神经网络(ANN)由「神经元」组成:每个神经元把输入按权重加权求和, 加一个偏置(每个神经元自带的偏移量),过一道激活函数(给输出压出新形状的数学变换),输出给下一层;
  • 网络分层:输入层 → 若干隐藏层 → 输出层;
  • 权重和偏置怎么定?训练:给网络看成千上万「输入 + 期望输出」的例子, 学习算法按输出离期望多远,不断调整权重偏置;
  • 训练好的权重 + 网络结构 = 模型(model);别人训好的模型放在网上共享, 这类库叫模型动物园(model zoo)——我们取,不训15。

选模型三原则书里给了:小、轻、为 Pi 优化。具体选 YuNet (OpenCV 模型动物园的人脸检测模型),理由是量化(quantized)—— 权重压成 8 位整数,内存和处理量都大减,精度损失实战可接受16。

用法瘦到三行:

self.detector = cv2.FaceDetectorYN.create(MODEL_FILE, "", SIZE, SCORE_THRESHOLD)
_, faces = self.detector.detect(frame)

detect 返回一组人脸,每个 15 个参数,我们只要 5 个:x、y、宽、高、置信分。 SCORE_THRESHOLD = 0.7 是过滤线——太低满屏假脸,太高漏真脸17。 检测结果发 face_detector/faces(JSON 列表,没脸发空列表), 同时把绿框和分数画在帧上回流浏览器18。三件套齐全:给人看的(框)、 给机器用的(JSON)、给调试用的(分数)。

6. 核心原理之三:云台追脸——PID 第一次管「注视」

look_at_face 行为把 face_detector 的数据喂给云台:

  • pan 方向 PID:人脸框中心 x − 画面中心 = 误差 → PID → pan 舵机;
  • tilt 方向 PID:人脸框中心 y − 画面中心 = 误差 → PID → tilt 舵机。

被跟踪的目标是把脸「钉」在画面中央。调参症状书里给得极好: 「机器人从脸上滑走(一副社恐的样子)——积分太高,减一点 I; 找脸太慢——I 太低。」19 这一句把积分项的性格说透了: I 是耐心,耐心过剩到处乱咬,耐心不足懒得追。

比调参症状更值得带走的是这个行为的三处设计,书里都给了理由:20

  1. P = 0,只用积分。 两个 PID 建成 PIDController(0, 0.006)—— 比例常数给 0,只留积分常数 0.006(tilt 那个取 −0.006)。 书里明写的理由:这个 PID 的输出是舵机位置,任务是 把云台保持在与人脸位置相对应的地方——而「保持」靠记忆, 积分恰好就是位置记忆:误差逐帧攒进积分,脸一进画面中央误差归零, 积分停在当前值,云台就停在原地。反过来看就明白 P 为什么必须关: 误差一消失,P 的输出立刻归零,云台会缩回中点—— 脸明明在中央,头却回了零位。tilt 系数取负是机械事实,不是数学技巧: 舵机的安装朝向决定了「输出为正」时镜头往哪边转,和误差符号对不上, 加一个负号对齐。21
  2. np.clip 限位:防扯线。 积分能攒到任意大,但 pan 的安全行程 ±70、tilt ±50(舵机位置单位)就是这个云台的机械极限—— 指令再往前,要么舵机齿轮打坏,要么把摄像头的排线扯伤。 所以 PID 输出发出去之前先 np.clip 到 ±70/±50: 积分在里面随便攒,执行机构只走到安全线。 这和第 8 节的 windup_limit 是同一思路的两道闸: 一个限积分,一个限输出。22
  3. 丢脸的处置:原地停,而不是回中。 一帧里检测不到脸,代码把 人脸坐标重置为画面中心——误差归零、积分停攒,云台就地停住等脸回来, 而不是转回中点乱扫。这与颜色跟随的「丢目标停车」是同一条 安全哲学的两个版本:轮子停住不动,云台停住不动。23

如果错,会错在: 把「只用积分」读成「积分万能」。它成立有前提: 执行器要的是保持型位置,且误差会频繁归零。循线(第 15 章)里 同一个 PID 骨架就不是这么配的——那里主活儿是 P(0.001), I 只有 0.0001,只管消残差。同一副骨架两种配法,差别在执行器要什么。

7. 核心原理之四:颜色管线——不用 AI 的看图法

人脸有现成模型;一个绿瓶子没有。第二种看法回归经典图像处理, 管线四步照原书接住24:

 ① BGR → HSV   换颜色空间:色相(H,0–179°色轮)/ 饱和度(S,灰↔艳)/ 明度(V,暗↔亮)
                RGB 里滤「蓝色」没法抗光照,HSV 里滤「色轮 100–130°」就稳
 ② 掩码        cv2.inRange(帧, low, high) → 黑白二值图:范围内白、范围外黑
                绿色例:H 30–80、S 90–255、V 50–255
 ③ 轮廓        cv2.findContours(掩码) → 白色块的边界线列表
 ④ 包围盒      cv2.boundingRect(轮廓) → 每个块一个矩形 → 画框 + 发 MQTT

 图说:图 → 信息 = 一步步扔掉不需要的细节,只留下「绿东西在哪、多大」。

两个实战细节:掩码会把保龄球瓶上的高光、花纹切出多个小块—— 检测列表里一堆 1×1、3×3 的噪声框,行为层要选最大的那个; 红色是出了名的麻烦:色轮上红跨 0/179 边界,一个掩码罩不住, 得做两个掩码再 bitwise_or 合并24。

跟随行为用两个 PID 各管一个维度(这是控制里的标准手法)25:

PID误差驱动效果
方向 PID色块中心 x − 画面中心左右轮差速把目标钉在画面中线上
速度 PID色块宽度 − 期望宽度(370 像素)两轮同速近了大(退)、远了小(追)

目标消失就停车——「看不见就不动」是给视觉行为的安全默认值25。

8. 核心原理之五:windup_limit——PID 的又一层护甲

本章给 PID 加第二件防具(第一件是第 13 章的 smart_reset):

积分饱和(integral windup):误差持续存在时,积分无限增长; 而执行机构(电机)有上限,跟不上积分的野心—— 等误差终于反向,巨大的积分把输出顶到反向饱和,大超调26。

windup_limit 参数给积分值本身戴箍:integral = clip(integral, ±limit)—— 积分可以攒,但最多攒这么多。和 smart_reset(符号相反清零)、 80% 速度余量(第 11 章)凑成抗饱和三件套:事前留余量、事中限幅、过零清账26。

9. 作者的判断与证据

  • 判断: 「看」和「用」分流——标注帧给人、JSON 给行为,一套核心多种处理器。 模型动物园是外卖菜单:换模型(表情/手势/姿态)只换处理器文件27。
  • 判断: 不训练、只取用——训练要月级时间和算力(计算能力),与本书定位(机器人编程)不符; 「用模型」才是机器人工程师的日常15。
  • 事实层: 20 fps 上限、704×364、JPEG 质量 90、阈值 0.7、绿色 HSV 区间、 windup 现象——都可上机复核10172426。
  • 诚实: 颜色管线「不认识物体的形状,只认识匹配掩码的色块」—— 手一挡就丢,抗干扰远不如人脸模型28。

10. 边界与局限

  • 没有训练,没有微调。 全书对深度学习的态度是消费级:下载、调用、换阈值。
  • 依赖光照。 书在两处(摄像头安装、跟随排错)重复「光线不足什么都白搭」29。
  • 单目标。 多个人脸会跳变跟踪;多个色块靠「取最大」硬扛,没有数据关联。
  • 行为层仍是手动调参。 PID 和期望尺寸写死在代码里,挑战题才指向 config store30。

11. 可带走的

  1. 视频 = 帧序列;Pi 上 20 fps 是现实天花板;图像不走 MQTT,走 MJPEG10。
  2. 相机核心三件套:取帧(sourcing)/ 沉帧入队(sinking)/ Flask 推流;Queue(maxsize=2) 解耦1112。
  3. 神经网络最小知识:加权求和 + 偏置 + 激活函数;训练调权重;模型 = 权重 + 结构;模型动物园15。
  4. 量化(int8)= 小模型的价格;阈值过滤 = 精确率(报对的占报出总数的比例)/召回率(该认出的占实际总数的比例)的旋钮1617。
  5. 视觉行为铁律:目标丢失 → 停车25。
  6. HSV 是颜色过滤的正确空间;掩码 → 轮廓 → 包围盒三步出「位置 + 尺寸」24。
  7. 多维控制拆多个 PID:方向误差管差速、尺寸误差管速度25。
  8. 积分饱和三件套:80% 余量、windup_limit、smart_reset2426。

补遗:相机流与跟随行为的实现细节

视频流的最后几米。 相机核心的发流端是一个 Flask 路由,按 multipart/x-mixed-replace 格式响应:每个响应块就是一帧 JPEG, --boundary 分隔、浏览器收到一块替换一块——「MJPEG」的全部秘密就在这个 Content-Type 里31。编码质量 90 是默认值,带宽吃紧就调低; 缓冲队列刻意只留 2 帧,宁可丢旧帧也不让浏览器看「几秒前」的画面。

追脸行为的两个 PID。 look_at_face 与颜色跟随同构,只是执行器换成了舵机: 人脸框中心的 x 坐标减画面中心 = pan 误差,y 同理喂 tilt; PID 输出直接是舵机角度增量。书里的调参直觉很生动: 机器人从脸上滑走(一副社恐的样子)= I 太高,微减; 找脸太慢 = I 太低,加一点32——积分项的耐心多少,决定了它是「黏人」还是「走神」。

颜色跟随的两个 PID 各管一轴。 方向 PID 吃「色块中心 x − 画面中心」, 输出差速;速度 PID 吃「色块宽度 − 期望宽度(370 像素)」,输出同速33: 宽度大于期望 = 太近,退;小于 = 太远,追。目标一旦离开画面, 两个 PID 的输出都归零——「看不见就不动」是视觉行为的安全默认值。

噪声框的过滤。 掩码切出来的轮廓列表里满是 1×1、3×3 的碎块(高光、花纹), 行为层只取面积最大的那个轮廓当目标,其余视为噪声—— 这是流水线出口的最后一道筛子34。

12. 原文地图

主题原书位置
装配材料清单text/122-fm-technical-requirements.txt:8(搜「stand-off kit」) · text/122-fm-technical-requirements.txt:13(搜「bowling set」)
孔位尺寸与算式text/122-fm-technical-requirements.txt:53(搜「36 mm by 38 mm」) · text/122-fm-technical-requirements.txt:63(搜「pan-tilt head width minus」) · text/122-fm-technical-requirements.txt:67(搜「2.5 mm is a reasonable」)
钻孔与铜柱装配text/122-fm-technical-requirements.txt:76(搜「craft knife」) · text/122-fm-technical-requirements.txt:89(搜「pliers to hold the nut」)
排线与两个插座text/122-fm-technical-requirements.txt:97(搜「cable-retaining clip」) · text/122-fm-technical-requirements.txt:125(搜「nearest to the big block of USB」)
相机首测三连text/122-fm-technical-requirements.txt:148(搜「list-cameras」) · text/122-fm-technical-requirements.txt:160(搜「immediate」) · text/122-fm-technical-requirements.txt:164(搜「files.get」)
相机排错三连text/123-fm-setting-up-computer-vision-software.txt:4(搜「typed the commands correctly」) · text/123-fm-setting-up-computer-vision-software.txt:6(搜「dark images」)
帧、MJPEG、20 fpstext/123-fm-setting-up-computer-vision-software.txt:48(搜「series of images, called frames」) · text/123-fm-setting-up-computer-vision-software.txt:55(搜「MJPEG」)
相机核心架构text/123-fm-setting-up-computer-vision-software.txt:100(搜「camera core」) · text/123-fm-setting-up-computer-vision-software.txt:142(搜「frame_buffer」)
神经网络与模型动物园text/124-fm-tracking-faces-with-ai-in-python.txt:42(搜「weighted sum」) · text/124-fm-tracking-faces-with-ai-in-python.txt:97(搜「model zoo」)
量化与阈值text/124-fm-tracking-faces-with-ai-in-python.txt:100(搜「quantized」) · text/124-fm-tracking-faces-with-ai-in-python.txt:150(搜「SCORE_THRESHOLD = 0.7」)
检测结果与画框text/124-fm-tracking-faces-with-ai-in-python.txt:228(搜「face_detector/faces」)
追脸调参症状text/125-fm-following-colored-objects-with-python.txt:9(搜「antisocial robot」)
追脸三项设计text/124-fm-tracking-faces-with-ai-in-python.txt:398(搜「0, 0.006」) · text/124-fm-tracking-faces-with-ai-in-python.txt:416(搜「np.clip」) · text/124-fm-tracking-faces-with-ai-in-python.txt:453(搜「stop the camera from」)
颜色管线text/125-fm-following-colored-objects-with-python.txt:50(搜「hue represents where the color is」) · text/125-fm-following-colored-objects-with-python.txt:121(搜「cv2.inRange」)
windup_limittext/125-fm-following-colored-objects-with-python.txt:252(搜「integral windup」)
跟随行为双 PIDtext/125-fm-following-colored-objects-with-python.txt:352(搜「direction_pid = PIDController」)
章节总结text/126-fm-summary.txt:33(搜「windup」)

Footnotes

  1. 出处:「Setting up the Raspberry Pi camera」第 21 段(text/122-fm-technical-requirements.txt:21,搜「install the Raspberry Pi camera」)。原文:本节把摄像头物理装上机器人、接线、并让 Pi 能取图;开工前机器人和 Pi 应断电。 ↩

  2. 出处:「Setting up the Raspberry Pi camera」第 53 段(text/122-fm-technical-requirements.txt:53,搜「36 mm by 38 mm」)与第 54 段(搜「21 mm apart」)、第 59 段(搜「will not use them」)、第 61 段(搜「no pressure is applied」)、第 63 段(搜「pan-tilt head width minus」)、第 66 段(搜「5.5 mm down」)、第 67 段(搜「2.5 mm is a reasonable」)、第 35 段(搜「glue」)。原文:云台头外形 36×38;摄像头孔横向间距 21、孔径 2.2、纵向 14.5;下孔与槽位及背后舵机干涉,弃用;必须用铜柱,不给摄像头背面连接器施压;(36−21)÷2 = 7.5,距顶 5.5 避棱;2.5 是最接近 M2 的常用钻头;Tip:不用胶,追求模块化可替换。 ↩

  3. 出处:「Setting up the Raspberry Pi camera」第 76 段(text/122-fm-technical-requirements.txt:76,搜「craft knife」)与第 78 段(搜「carefully drill」)。原文:卡尺量 5.5 mm、美工刀划构造线、两侧各 7.5 mm;手捻钻在交点钻 2.5 mm 孔;可在机器人上就位操作。 ↩

  4. 出处:「Setting up the Raspberry Pi camera」第 89 段(text/122-fm-technical-requirements.txt:89,搜「pliers to hold the nut」)。原文:扁嘴长嘴钳固定螺母,手指拧紧铜柱。 ↩

  5. 出处:「Setting up the Raspberry Pi camera」第 97 段(text/122-fm-technical-requirements.txt:97,搜「cable-retaining clip」)与第 101 段(搜「gently slot in」)。原文:指甲撬开卡扣;看摄像头背面时蓝面朝自己;平直插到底;压回卡扣并用指甲确认平整。 ↩

  6. 出处:「Setting up the Raspberry Pi camera」第 112 段(text/122-fm-technical-requirements.txt:112,搜「gap between the tilt head」)。原文:排线从 tilt head 与 pan base 之间的缝隙穿过,再装摄像头。 ↩

  7. 出处:「Setting up the Raspberry Pi camera」第 125 段(text/122-fm-technical-requirements.txt:125,搜「nearest to the big block of USB」)与第 127 段(搜「facing the USB ports」)。原文:两个相似的扁平座,用离 USB 大块最近的;蓝色加强面朝 USB 口;平直插到底再压卡扣。 ↩

  8. 出处:「Setting up the Raspberry Pi camera」第 135 段(text/122-fm-technical-requirements.txt:135,搜「Raspberry Pi power」)与第 139 段(搜「updates frequently」)、第 148 段(搜「list-cameras」)、第 154 段(搜「imx708」)、第 160 段(搜「immediate」)、第 164 段(搜「files.get」)、第 167 段(搜「right way up」)。原文:用树莓派电源而非电池;相机软件更新频繁,先全量升级再 reboot;list-cameras 应列出 imx708 与模式表;immediate 拍 test.jpg;files.get 拉回本地;图应方向正确。 ↩

  9. 出处:「Setting up the Raspberry Pi camera」排错(text/123-fm-setting-up-computer-vision-software.txt:4,搜「typed the commands correctly」)与第 6 段(搜「dark images」)、第 8 段(搜「not getting enough light」)。原文:报错先查命令;再错就断电查排线;图黑查光照——光不够,后面所有跟踪都不工作。 ↩

  10. 出处:「Setting up computer vision software」第 48 段(text/123-fm-setting-up-computer-vision-software.txt:48,搜「series of images, called frames」)与第 50 段(搜「MJPEG」)。原文:视频视为帧序列;分辨率与处理时间相关,本章用低分辨率;图像处理开销大,帧率别指望超 20 fps;图像数据太重不走 MQTT,用 MJPEG——一帧帧 JPEG 更新单个 img 元素。 ↩ ↩2 ↩3 ↩4

  11. 出处:「Setting up computer vision software」第 100 段(text/123-fm-setting-up-computer-vision-software.txt:100,搜「camera core」)。原文:相机核心供图给处理器;处理器做三件事:标注帧、发 MQTT 检测结果、可接收配置消息;核心把处理后的帧送进 Web 服务器发视频流;处理器进公共库,行为独立成应用以便多种行为共用检测器。 ↩ ↩2

  12. 出处:「Setting up computer vision software」第 142 段(text/123-fm-setting-up-computer-vision-software.txt:142,搜「frame_buffer」)。原文:Queue(maxsize=2) 同时读写不破帧;普通变量会读到写了一半的帧;服务器与处理器互不等待;只在上一帧被消费后缓冲新帧。 ↩ ↩2

  13. 出处:「Setting up computer vision software」第 130 段(text/123-fm-setting-up-computer-vision-software.txt:130,搜「ENCODE_PARAM」)。原文:IMWRITE_JPEG_QUALITY 90;有问题可降百分比换更快输出;Flask 的 Response 按 multipart 逐帧推送。 ↩

  14. 出处:「Setting up computer vision software」第 94 段(text/123-fm-setting-up-computer-vision-software.txt:94,搜「expensive」)。原文:相机行为费电费 CPU,用 launcher 启停;视觉处理主用 OpenCV,Web 服务器用 Flask。 ↩

  15. 出处:「Tracking faces with AI in Python」第 42 段(text/124-fm-tracking-faces-with-ai-in-python.txt:42,搜「weighted sum」)与第 100 段(搜「model zoo」)。原文:神经元 = 输入加权求和 + 偏置 + 激活函数;分层;10 神经元的小网已有 24 个权重;训练 = 看大量例子调权重偏置;训练好的权重 + 架构 = 模型;模型动物园 = 针对问题或网络规模的模型库;本书不训练,用现成模型。 ↩ ↩2 ↩3 ↩4

  16. 出处:「Tracking faces with AI in Python」第 100 段(text/124-fm-tracking-faces-with-ai-in-python.txt:100,搜「quantized」)。原文:YuNet 来自 OpenCV 模型动物园,小而轻;已量化——权重变成 8 位数,内存与处理量大减,精度略降但实战很好;输出即预期的矩形检测结果;PyInfra 从 raw 链接下载 int8 版。 ↩ ↩2

  17. 出处:「Tracking faces with AI in Python」第 150 段(text/124-fm-tracking-faces-with-ai-in-python.txt:150,搜「SCORE_THRESHOLD = 0.7」)。原文:阈值是最低置信分;太低假阳性多,太高漏检;模型返回 15 参数/脸,取 x、y、w、h、score 五项。 ↩ ↩2 ↩3

  18. 出处:「Tracking faces with AI in Python」第 228 段(text/124-fm-tracking-faces-with-ai-in-python.txt:228,搜「face_detector/faces」)。原文:画绿框 + 分数;发布 JSON 列表;无脸发空列表;if __name__ == "__main__" 防止多进程重建;订阅 camera_view/url/get 报视频地址。 ↩

  19. 出处:「Following colored objects with Python」第 9 段(text/125-fm-following-colored-objects-with-python.txt:9,搜「antisocial robot」)。原文排错:滑离人脸 = I 太高,微减;找脸太慢 = I 太低;多脸会跳变;电池低会抖。 ↩

  20. 出处:「Tracking faces with AI in Python」Tracking the face 第 382 段(text/124-fm-tracking-faces-with-ai-in-python.txt:382,搜「pan_range = 70」)。原文:pan_range = 70、tilt_range = 50、center_x = 704/2、center_y = 364/2——限制舵机行程。 ↩

  21. 出处:「Tracking faces with AI in Python」第 398 段(text/124-fm-tracking-faces-with-ai-in-python.txt:398,搜「0, 0.006」)与第 401 段(搜「hold a servo at a position」)、第 402 段(搜「negative to match」)。原文:PIDController(0, 0.006) 与 (0, −0.006);「PIDs here hold a servo at a position relative to where the face is, so we only use the integral term」;tilt 系数取负以匹配舵机朝向。 ↩

  22. 出处:「Tracking faces with AI in Python」第 416 段(text/124-fm-tracking-faces-with-ai-in-python.txt:416,搜「np.clip」)与第 420 段(搜「damage the servo motors」)。原文:pan/tilt 位置 np.clip 到 ±pan_range/±tilt_range,防止走太远损坏舵机或摄像头排线。 ↩

  23. 出处:「Tracking faces with AI in Python」第 453 段(text/124-fm-tracking-faces-with-ai-in-python.txt:453,搜「stop the camera from」)。原文:无脸时把坐标设回画面中心,误差归零,镜头停止移动。 ↩

  24. 出处:「Following colored objects with Python」第 50 段(text/125-fm-following-colored-objects-with-python.txt:50,搜「hue represents where the color is」)与第 110 段(搜「cv2.inRange」)。原文:HSV——hue 在色轮位置(0–179,0 红、~30 绿)、saturation 灰↔艳、value 明暗;BGR 没法按色相抗光照过滤;inRange 出黑白掩码;findContours 取轮廓;boundingRect 取包围盒;Note:红色跨 0/179 边界,要两个掩码 bitwise_or 合并;小噪声框要按大小过滤。 ↩ ↩2 ↩3 ↩4 ↩5

  25. 出处:「Following colored objects with Python」第 352 段(text/125-fm-following-colored-objects-with-python.txt:352,搜「direction_pid = PIDController」)。原文:方向 PID(x 误差→差速) + 速度 PID(宽度 vs 期望 370→同速);目标不在视野则电机归零;排错:撞东西降速度 PID,扫过目标降方向 PID;背景里的绿树会骗它;它不认识形状只认识色块。 ↩ ↩2 ↩3 ↩4

  26. 出处:「Following colored objects with Python」第 252 段(text/125-fm-following-colored-objects-with-python.txt:252,搜「integral windup」)。原文:积分增长而电机跟不上 → 大超调,即 windup;给 PID 加可选 windup_limit;本章用它护航跟随行为。 ↩ ↩2 ↩3 ↩4

  27. 出处:「Challenges」第 5 段(text/127-fm-challenges.txt:5,搜「facial expressions」)。原文:模型动物园还有表情、手势、姿态模型;考虑换一个进处理器;把 PID/期望尺寸/颜色接进 config store。 ↩

  28. 出处:「Summary」第 23 段(text/126-fm-summary.txt:23,搜「hands to cover the」)。原文:用手捂住目标看反应——它没有人脸模型那样的鲁棒性,只认色块。 ↩

  29. 出处:「Setting up the Raspberry Pi camera」(text/122-fm-technical-requirements.txt:15,搜「well-lit」)。原文:摄像头对光照敏感,需要光线充足的空间;光不够,后面所有跟踪都不工作。 ↩

  30. 出处:「Challenges」第 14 段(text/127-fm-challenges.txt:14,搜「configurable」)。原文:用 config store 让 PID、参考尺寸、跟踪颜色可配。 ↩

  31. 出处:「Setting up computer vision software」第 170 段(text/123-fm-setting-up-computer-vision-software.txt:170,搜「multipart」)。原文:Flask 按 multipart/x-mixed-replace 逐帧响应;JPEG 质量 90 可调。 ↩

  32. 出处:「Following colored objects with Python」排错(text/125-fm-following-colored-objects-with-python.txt:9,搜「antisocial robot」)。原文:滑离人脸 = I 太高微减;找脸太慢 = I 太低。 ↩

  33. 出处:「Following colored objects with Python」第 298 段(text/125-fm-following-colored-objects-with-python.txt:298,搜「speed PID controller」)与第 314 段(搜「object_size_ref = 370」)。原文:尺寸进速度 PID(带期望尺寸参考);中心 x 进方向 PID;双 PID 各管一轴;期望宽度 object_size_ref = 370,作者把目标放到想要的距离上后从 MQTT 输出的宽度读得。 ↩

  34. 出处:「Following colored objects with Python」第 147 段(text/125-fm-following-colored-objects-with-python.txt:147,搜「detections」)。原文:检测列表混着大量碎块框,行为层按大小过滤取主目标。 ↩

On this page