传感器那篇说过:传感器负责报告世界。光敏说"亮不亮",循迹那类模块说"线在不在"。它们一次回答一个问题。
视觉想回答的是另一件事:这一整幅画面里,有什么。
为什么这套教程只放得下这一篇视觉,我还是要写?因为它是我学得最久、也最兴奋的方向之一。从 OpenMV 一路摸到 Linux 板卡、Jetson、海思,中间打过两年电赛和智能车,学了一年多,能讲的东西装不下一百篇。这篇装得下的,只有一条线:图像在机器眼里到底是什么,机器又是怎么从"看见"走到"看懂"的。
图像在机器里,到底是什么东西
一张图,是一张点阵。相机镜头后面是一块感光阵列,像一张铺满小格子的网。光打在格子上,每个格子把亮度变成电压,芯片再把电压量化成数字------格子,就是像素。640×480 的意思,是横着 640 个、竖着 480 个格子,一整张图就是 640×480 个格子摆成的方阵。分辨率越高,格子越多,细节越多,数据也越多。
一个格子里存几个数,决定了它是黑白还是彩色。灰度图里,一个像素只存一个数,表示明暗,约定俗成 0 最黑、255 最白。彩色图里,一个像素存三个数,通常按红、绿、蓝排列(RGB)。每个数的取值范围叫位深------8 位就是 0~255。所以彩色图在机器眼里就是三张并排的明暗表:一张管红、一张管绿、一张管蓝,叠在一起才还原成颜色。
颜色这里有一个大坑:RGB 是"发光"的表示,不是"被看"的表示。它描述的是屏幕怎么发光,光照一变,同一个物体的 RGB 三个数一起变------白天拍的红球和晚上拍的红球,数字完全不同。视觉里更常用另一种表示:HSV,把颜色拆成三份------色相(是什么颜色)、饱和度(颜色浓不浓)、明度(亮不亮)。找颜色用 HSV,等于告诉程序"我找的是红色",光照变了也能稳住。这个坑,做视觉的人基本都踩过一遍。
图像是数据,就要算它的账。一帧 640×480 的彩色图,裸数据是 640×480×3,约 92 万个字节,接近 1 MB;按 30 fps 算,一秒就是 27 MB 的裸数据流过内存。这个数字是理解嵌入式视觉的钥匙:内存、带宽、拷贝成本,全压在这笔账上;帧率、分辨率、通道数,每一项都是乘进去的。先记住这句话------后面讲到真机时,这笔账怎么还,是整段故事的主线。
机器"看懂",就是在这张数表上找规律。有的规律人写得出来:设一个阈值把亮和暗分开,让像素跟邻居平均一下把噪点抹平,把连成片的同色区域圈出来找中心。这类人写的规则不学习,透明、好调,改一个数字就能看到效果。天花板也低:光照一变要重调,目标一变形就失灵。规则够不到的地方,才轮到让机器自己学------那是神经网络的地盘。
让机器自己学"特征"
规则写不出来的时候,神经网络上场。思路压缩成两句话:从画面里找出特征,用特征给出判断。特征不用人定义------模型在大量例子里自己学,哪些像素组合构成边,哪些构成纹理,再往上,哪些构成眼睛、轮子、道路。
沿着这条思路,分出几种常见任务:
- 目标检测:画面里有什么、在哪、多大------输出框和类别;
- 语义分割:给每个像素发一张"身份证",说它属于道路还是草地;
- OCR:把画面里的文字读成文本。
YOLO 是目标检测里有名的一类做法。旧思路是把图切成小窗、一块块判断;它整张图一次看完,直接输出所有框,快就快在这里。概念到这里收住,后面卷积、特征金字塔那些,等真正上手再往里走。
再往外一层,是"看懂之后怎么办":OCR 读出的文字、检测认出的目标,可以交给云端大模型去理解上下文------这行字是什么意思,下一步该往哪开。这是 26 年智能车那辆车里真实跑过的链路。
学习到底发生在哪:机器学习和人的学习,摆在一起看
神经网络说"学",到底学在哪?训练时,程序拿到成千上万张标好答案的图片,一次次预测,一次次和答案比,错了就微调内部那几百万个参数,几十万轮之后,压出一套"图片→答案"的统计规律。它没有背下任何一张图------它学的是规律。
这一点和人的学习有点像:小孩认猫,也是先见过很多猫,被人纠正过"那是狗不是猫"。模型被纠正的方式叫"损失",被纠正的过程叫训练。相似处到这里为止,接下来全是差别。
差别的第一处,在食物链。模型吃的是人工标注的数据。谁标的数据、标得全不全、覆盖了哪些场景,直接决定它见过什么世界------它只在那个世界里答得准。白天拍的猫学得好,晚上一拍就失灵,不是它笨,是它的世界里没有晚上。数据就是它的上限。
差别的第二处,在它学的是"像不像",不是"为什么"。模型判断一张图是猫,依据的是和训练集里猫的相似度,它不理解"猫"这个概念。给图片贴一小块人眼几乎无感的扰动,它能信心满满地把猫认成狗------这叫对抗样本。它没有常识兜底。
差别的第三处,在样本效率。人看几张猫的照片,加上"动物、有四条腿、毛茸茸"这些生活常识,就能认出没见过的猫;模型通常要几千上万张同类图片才压得稳。人能把开车学到的"控制"迁移到开船,模型换个任务,常常要从头再喂一遍数据。
所以机器学习的上限,很多时候不在算法新不新,先看喂给它的材料和它被允许看到的范围。这也是为什么真实项目里,收集和清洗数据常常比调模型更花时间------调模型的同时,其实是在替它补见识。
想跑视觉,硬件从一根线到一块板
电脑 + USB 摄像头:最便宜的入口。电脑装好 Python 和图像库,摄像头一插,几十行代码就能让画面里出现框。先把"图像怎么读、颜色怎么筛、框怎么画"在电脑上跑通,再上板子------板子上的报错,没有电脑上好查。
OpenMV:摄像头、处理器、MicroPython 装在一个小板子上,插上就能写,阈值、色块这类视觉函数开箱能用。适合第一次让机器看见,也适合快速验证思路。算力有限,跑不了大模型,但规则方法的全部战场它都接得住。我最早接触视觉就是它,第一次在屏幕上框住一个色块的时候,兴奋程度不亚于当年第一次点亮 LED。
K210 / K230:国产、便宜、板载 NPU------专门跑神经网络的硬件。K210 便宜,跑轻量模型够用;K230 算力更高,检测、分割这类能上真模型。它们的脾气写在价格里:工具链和文档要花时间摸,能搜到的现成答案比树莓派少。预算有限又要真跑模型的场合,它们是让模型跑进边缘设备的最现实选择之一。
树莓派、香橙派这类 Linux 板卡:跑完整 Linux,装 OpenCV、跑 YOLO、接 ROS 都行。它不是摄像头模块,是一台小电脑,适合做整机的大脑。这类板卡我用得最久,超过一年:上面跑过检测、分割、串口、电机,也踩过散热和功耗。香橙派这类国产板,价格和供货常比树莓派友好,生态差一点,这几年补得很快。
再往上,Jetson、海思这类带专用算力的板子:Jetson 算力大,适合需要较多算力的车和机器人;海思芯片的板子(海鸥派这一类)我拿来接过双目摄像头,直接出深度图------两个摄像头看同一场景,像素位置差就能算距离。到这里,视觉开始从"看见"走向"测距",和深度相机、激光雷达是同一件事的不同做法。
一个人、一块板子、三个模型
25 年电赛和智能车,26 年电赛和智能车,一路打下来,视觉用过不少板子。印象最深的,是 26 年智能车的人工智能模型组。
这一年,组里我一个人扛这块板卡上的所有任务。摄像头限制 30 fps。车上要跑三个模型:一个目标检测,认障碍物和奖励;一个语义分割,把道路从背景里分出来;一个 OCR,把画面里的文字读出来,再交给云端大模型去理解。但它们不是一起全速跑------检测和分割是常驻的,每帧都在跑;OCR 是触发的,等检测先认出"这是块路牌",才把那一小块 ROI 抠出来、仔细读里面的字。重活不常做,这是最早的一笔省账。
三份模型挤在一块板子上,账怎么还?我做的所有事,分成两类:让数据流快,让算力闲不下来。
数据流那一侧,搬运尽量不麻烦 CPU。摄像头帧经 DMA 直接进内存,不占 CPU 的搬运动作;再用内存映射让程序直接看到这块缓冲,省掉内核态和用户态之间的一次复制;帧从进来到进模型,一路能引用就引用、能指针就指针,少用甚至不用值传递------路径上尽量不产生第二份拷贝。零拷贝不是某个单一操作,是一路"避免复制"的习惯叠出来的:DMA 负责硬件的搬,内存映射负责地址的共享,引用和指针负责让数据只存在一份,每个环节省一点,整条流水线才轻得下来。模型输入往往要先缩放、换颜色格式,这些活交给板上的 RGA 硬件加速器,CPU 只等结果。帧和推理之间是生产者-消费者关系:摄像线程是生产者,推理池是消费者。队列满时,消费者先把当前一批取走排空,生产者再重试放入------背压式的排空重试,把压力留在生产者这一侧,不让帧在队列里越积越多。
算力那一侧,三个模型不是三套互不相干的程序。检测、分割、OCR 实现同一个泛型模型接口,注册进同一个模型池,运行时由动态线程分派,哪个实例闲了接哪个任务------不为每个模型各写一套调度。泛型池统一的是调度,不是网络本身:三个模型彼此独立,各算各的,没有共享的主干。省账的地方在别处------同一套模型要开好几个推理实例时,让它们共用同一份权重,内存只占一份;但省的是内存、不是算力,每个实例推理时照样自己跑一遍。板上的 NPU 也没什么玄学:RK3588 是三个同构的核,调度按核号轮流分派,图的是三个核的负载都别闲着。
零拷贝、RGA、背压排空、泛型池、权重内存复用、多核轮转------几样叠在一起,才把三个模型的负担塞进 30 fps 的天花板,最后稳定跑在 24 fps 以上。那段日子是另一种节奏:白天调车,晚上对着帧率数字改调度,板子烫手,屏幕上的 fps 从个位数往上爬。它稳稳停在 24 甚至 29 的时候,实验室就剩我一个人,对着屏幕笑。那套代码我一直留着。
说这些是想说清一件事:视觉的上限,往往不在模型多高级,在工程把每一帧喂得多快。三个模型再多一个,不如让数据流快一帧实在。这一点和嵌入式其它方向最像------拼到最后,拼的是搬运和调度。
最后橘猫说
图像在机器里先是一张数表:像素、通道、位深、颜色模型,一帧多大、一秒多少,账都在里面。机器在这张表上找规律,规则写得到的自己写,规则够不到的交给神经网络,让它自己学特征------学的是规律,吃的是人标的数据,上限常常在数据和见识上。把答案变成车的速度,靠的是工程:帧率、搬运、调度。
最后蜘蛛说
这又是一大部分内容啊qwq(挖坑ing...)