上一篇讲了正方形检测的一套套路。这一篇上个台阶,做一个能真正落地的项目------让 OpenCV 自动读指针仪表。工业现场有海量的机械仪表(压力表、温度表、转速表)需要人眼抄表,这套 pipeline 能代替人眼:霍夫圆定表盘、霍夫线找指针、角度映射出读数。这也是 97 个实例里少见的完整项目级示例。
一、效果先行
先看读数效果。左边是合成仪表盘(指针指向 -45°),右边是检测结果------红色圆圈精准圈住表盘,绿色线标出指针方向,检测读数 50.3,真实值 50.0,误差只有 0.3:

第二张是伪彩色映射。同一张灰度图,用 JET、TURBO、INFERNO、VIRIDIS 四种 colormap 上色,色调差异一目了然------这是工业视觉里「数据可视化」的标配:

两张图记住两件事:仪表读数靠「霍夫圆 + 霍夫线 + 角度映射」一条龙;伪彩色是把「数据」变成「图」的利器。
二、仪表读数:一个能真正落地的项目
官方 gauge.cpp 给了一套完整的指针仪表读数流程,我拆成 5 步:
cpp
// ① HoughCircles 定表盘圆(圆心 + 半径)
HoughCircles(gray, circles, HOUGH_GRADIENT, 1, 50, 100, 50, 150, 220);
// ② 阈值反相 + HoughLinesP 找指针线
threshold(gray, bin, 175, 255, THRESH_BINARY_INV);
HoughLinesP(bin, lines, 3, CV_PI/180, 100, 10, 0);
// ③ 几何过滤:一端近圆心、一端近刻度
// ④ atan2 算指针角度
// ⑤ 线性映射到读数
这套东西的价值在于:它是 97 个实例里少见的「完整项目级」代码,从图像进来到读数出来,一个函数走完,直接能迁移到真实抄表场景。
三、HoughCircles:先找到表盘在哪
第一步是定位表盘圆。HoughCircles 是霍夫变换找圆的经典实现,返回每个圆的圆心和半径。
这里有个关键细节:半径范围要按图的比例来设。官方用的是 height 的 0.35 到 0.48 倍作为半径搜索范围。为什么?因为表盘圆通常占图的大部分,把半径范围限定在这个区间,能避免检出一堆同心圆或者漏检。
四、HoughLinesP:找指针,靠的是几何约束
找到表盘后,第二步是在表盘里找指针线。HoughLinesP 是概率霍夫线检测,它会返回一堆线段------问题在于,表盘圆环上全是切线,圆会贡献一大堆线。
怎么从一堆线里挑出真指针?官方用的不是「找最长的线」,而是一条几何约束:
cpp
// 线的一端要靠近圆心(指针根部),另一端要靠近刻度(指针尖端)
if (dmin < 0.25*r && dmin > 0.15*r && dmax < 1.0*r && dmax > 0.5*r) {
// 这是指针
}
指针必然「根部在圆心附近、尖端在刻度附近」,这条约束一举排除了圆的切线(两端都距圆心约等于半径)和噪声短线。这就是工程里常说的「先想清楚目标长什么样,再用几何约束过滤」------比无脑调参靠谱得多。
五、角度到读数:一条线性映射
找到指针后,用 atan2 算出指针方向角,再线性映射到量程:
cpp
double phi = atan2(tip.y - c.y, tip.x - c.x) * 180.0 / CV_PI; // 图像角
double val = (phi - min_angle) / (max_angle - min_angle) * 100.0;
校准就是告诉程序「指针从哪个角扫到哪个角,对应多少读数」。我用合成图做了对账:指针指向 -45°,检测读数 50.3,真实 50.0,误差 0.3------这就是「已知值 vs 检测值」的精确验证,比肉眼看图靠谱得多。
六、伪彩色:数据可视化的另一双眼睛
falsecolor 这个示例演示 applyColorMap,把单通道的「数据」映射成彩色。工业视觉里,深度图、红外图、热力图都需要这种可视化:
| colormap | 色调 | 适用 |
|---|---|---|
| JET | 蓝→青→绿→黄→红 | 老牌彩虹色,但色带明显 |
| TURBO | 深紫→蓝→青→黄→红 | JET 的现代替代,过渡平滑 |
| INFERNO | 黑紫→红→橙→黄 | 热力图首选,感知均匀 |
| VIRIDIS | 深紫→蓝→绿→黄 | 数据科学默认配色 |
工程建议记两条:热力图用 INFERNO,替代老 JET 用 TURBO。JET 有「色带伪影」------相邻灰阶在绿色区被拉得很开、蓝色区压得很挤,做测量可视化时容易误导判断。
七、踩坑记录
| 坑 | 现象 | 原因 | 正确姿势 |
|---|---|---|---|
| HoughCircles 漏检/爆检 | 找不到圆或检出一堆同心圆 | 半径范围没按图比例设 | 用 height 的 0.35~0.48 倍限定半径 |
| 指针检不出来 | 过滤条件把指针滤掉了 | 指针根部从圆心画起,diff1≈0 | 指针根部要偏离圆心,落在 0.15r,0.25r |
| 检到的是背景 | HoughLinesP 结果全是圆的切线 | 没做几何过滤,直接取第一条线 | 用「一端近圆心一端近刻度」约束 |
| 阈值方向反了 | 找不到线 | 黑指针白底要用 THRESH_BINARY_INV | 反相阈值,把目标变白 |
八、AI 与 LLM Wiki:这一课沉淀了什么
LLM Wiki 现在 19 页了,这一课新增「伪彩色与仪表读数」概念页,沉淀了仪表读数的 5 步 pipeline、几何过滤的约束条件、角度映射公式、以及 4 种 colormap 的选型建议。两张截图归档进素材目录,进度表上 falsecolor 和 gauge 勾选完成,从 23 个变成 25 个,进度 26%。

这一课最值得记的,是「用几何约束过滤,而不是无脑调参」这个方法论。HoughLinesP 检出一堆线,新手会去调阈值调到天荒地老,老手直接想清楚「指针的几何特征是什么」,一条约束就筛出来了。这种「先建模、再过滤」的思路,比具体某个参数值更值得进知识库。
imgproc 到这里,边缘、形态学、轮廓、形状检测、直方图、伪彩色、仪表读数,七个主题全过了。接下来 imgproc 就剩几个零散实例,然后是重头戏------视频读写和特征检测。
写在最后
97 个实例,今天完成第 25 个,进度 26%。这一课的核心收获是:真正的落地项目,靠的不是单个 API,而是「霍夫圆定表盘 + 霍夫线找指针 + 几何过滤 + 角度映射」这一条完整链路。学会用「几何约束」思考问题,比记住一百个参数都值钱。
下一篇进入视频 I/O------摄像头采集、视频写入、GStreamer 管道,从静态图像走向动态视频流。到时候见。