基于OpenCV的圆形表盘示数的自动读取

本文介绍了如何利用OpenCV的霍夫变换检测圆形表盘和指针,实现自动读取示数。通过图像处理找到指针位置,结合表盘刻度计算出数值,解决了人工读表的效率和精度问题。
摘要由CSDN通过智能技术生成

背景:

来源于一个真实的需求,一些设备需要通过读取诸如气压表的示数来判断设备是否正常工作或者确定是否达到加工产品所需的环境。一直以来都是依赖人工读取示数,车间工人定时巡检读表,相当于等间隔采样,但是示数的变化是一个连续值,用离散的采样值近似连续值总会漏掉一些信息,太密集的采样又是对人力的极大消耗,所以希望开发一个基于计算机视觉的系统全天候24小时不间断的读取示数并且通过后续的数据处理及时给工厂反馈机器的运行状态便于管控。

 

Part 1   这些表盘是什么样子的?

图一 单个表盘

 

图二 多个表盘

实际场景中第二幅图更常见,也就是好几个表同时出现在一张图中,但是我们在实际处理时要把它们都变成它上面那张图的形式,也就是一张图中只有一只表盘,因为这样处理起来最简单高效。如果不对图像进行切割裁剪,这个问题会很复杂。(有兴趣的可以自己尝试以下,反正博主是没有解决)

 

Part 2  如何从图中读出表盘上的数字

对于人来说,如果图像足够清晰可以一眼从图中看出示数,那么我们是如何一眼就得出了数字呢。这个过程大概分两步:首先,基于我们已有的知识,我们知道表盘上指针所指的位置就是最终的示数;然后,表盘上的刻度对应着实际的数值。也就是说我们先找到了指针指向的位置然后根据标好的刻度读出具体的数值。

同样的,计算机也需要这两步才能得到准确的数值。那么计算机如何才能找到指针所指的位置呢?可以发现,表盘是一个圆形,指针类似这个圆的半径是经过圆心的一条线段,所以第一步的问题就变成了如何从一幅图中找到一个圆以及经过圆心的一条与半径有密切数学关系的直线。

Little Tips
这个数学关系大概是:
圆心坐标c(x, y),半径 r,指针的两个端点的坐标是a(x1,y1)
b(x2,y2),令 d1 = ||c - a||, d2 = ||c - b||
则有(保证d1 < d2)
d1 < 0.5*r and d1 > 0.15*r  and d2 < 1.5*r and d2 > 0.5*r
当然对于不同的表盘略有差异,这个根据实际情形进行调整。

隆重介绍一下OpenCV中经典的直线以及圆检测方法:霍夫变换。这里只大概介绍,想要完全了解的可以自行查阅资料。

 

霍夫直线检测:
原理:笛卡尔坐标系中的直线可以通过参数斜率和截距(m, b)表示,在极坐标中这条直线可以由一组唯一的
(r, theta)表示。对于笛卡尔坐标系中的每一个点,我们在极坐标下用(r, theta)曲线表示通过它的所有直线,然后统计不同曲线的交点,曲线的交点数目越多则表示越多的点在交点所对应的直线上。然后根据交点的(r,theta)找到原图中的直线。
霍夫圆监测:
这个是把笛卡尔坐标转换成了三维坐标(x,y,r)。细节我也不懂,可以自行百度。

cv::HoughCircles()--输入图像是单通道的灰度图像
cv::HoughLinesP()--输入是单通道二值图像
检测结果如下图。

 

图三 圆和指针线段

把圆按360度等分是为了方便计算指针所指的示数,计算方法如下:

计算得到指针指向的角度 theta,直接测量可以得到指针刻度起点所对应的角度 minangle,
以及终止角度maxangle,以及最大刻度量 10.
则可以得到实际的示数:

value = (theta - minangle)*10/(maxangle - minangle)

利用这个公式对上图的示数进行计算,

minangle = 60 maxangle = 320 最大刻度量 10,theta = 220

value = (220 - 60)*10/(320 - 60)= 6.15384615....

接近真实数值,当然为了获得尽可能准确的数值,我们需要精确的 minangle maxangle 以及theta。

那么问题来了:theta 是怎么计算的?

指针所在的线段是我们通过霍夫检测得到的,
所以我们可以得到线段的两个端点 a(x1, y1) b(x2, y2)
计算线段的 tan(theta), 然后计算反三角函数得到 theta
前面我们得到圆的一些基本参数:圆心坐标 c(x, y), 半径 r
假设 a 是离圆心的近点,b 是远点

x_angle = x2 - x
y_angle = y -  y2

一定要注意这里是 y - y2,不是 y2 - y,
这是因为对图像所在的笛卡尔直角坐标系,(0,0)点在图像的左上角,
所以越往下 y 越大。

则有 tan(theta) = y_angle/x_angle  theta = arctan(tan(theat))

(本想画张示意图的,然后没有在mac上折腾出来。。。)

另一个重要的问题如何确定 theta 的象限?四个象限对应四种情况。

图四 tan(theta) 函数

参考图三,以180度为界可以把表盘分成左右两个部分,左半部分角度(0 - 180),右边(180 - 360),参考图四,由于tan(theta) 在 \pi/2 ,\pi*3/2 处不连续,所以 theta 的四个区间为(0 - \pi/2)、(\pi​​​​​​​/2,\pi​​​​​​​)、(\pi​​​​​​​ ,\pi​​​​​​​*3/2 )、(\pi*3​​​​​​​/2,\pi​​​​​​​*2),可以得到 theta 不在 \pi​​​​​​​/2 的左边就是右边,或者 \pi​​​​​​​*3/2 的左边或右边。则有:

(1)(x_angle > 0 and y_angle >0) or (x_angle > 0 and y_angle < 0)
    
    final_theta = 270 - theta
    
    但是这包含了两种小情况,前半部分说明指针的终点在右半部分的上半部分,
    theta > 0, final_theta < 270;后半部分说明指针的终点在右半部分的
    下半部分,theta < 0, final_theta > 270.
(2) (x_angle < 0 and y_angle >0) or (x_angle < 0 and y_angle < 0)

    final_theta = 90 - theta

    依然是两种情况,前半部分说明指针指向的是左半部分的上半部分,
    theta < 0, final_theta > 90; 后半部分说明指针指向了左半部分的
    下半部分,theta > 0, final_theta < 90

到这就全部完成了,然后根据前面的 value 公式计算得到值即可。

总结:

算法没有太多难点,主要是通过霍夫检测出直线和圆,计算角度,得到最后的示数即可。

附上代码下载链接:https://download.csdn.net/download/zshluckydogs/10943490

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nobrody

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值