基于STM32芯片的燃气表读数系统设计

自动寻找仪表读数区域,识别红色区域三个数字,能判别数字完整性,不完整就可以反推之前的数字; 2.5秒识别一帧;能经受长时间运行考验(连续运行一晚上)。

主要硬件配置:
分辨率为320*240的 LCD 70元
OV7670摄像头(带AL422B FIFO) 80元
STM32F103ZE芯片 23元
外扩SRAM:IS62WV51216,1MB字节 18元

程序框架:
一 硬件初始化。
主要是相机,LCD,外部SRAM的初始化。
重点:相机初始化需要仔细配置,一共有110个寄存器,配置成QVGA,RGB565输出,亮度设置寄存器要-1,饱和度设置寄存器+1能显著提升图像效果。STM32内部RAM小(64KB),初始化FSMC后,可以把图像存到外部SRAM中进行处理。

二 相机刷新。
把灰度图保存到pic_gray[240][320]数组,给定阈值,把黑白图存到pic_binary[240][320]数组中。
重点:相机读取进来是RGB565数据,要转换成灰度图像。位移读取出R,G,B分量后,根据转换公式:GRAY=R*0.299+G*0.587+B*0.114,经实践,显示速度1帧/秒,改GRAY=((R*1224+G*2404+B*467)>>12)后,显示速度达到5帧/秒。


图1:RGB565输入


图2:转换为灰度图

三 自动寻找仪表读数区域并二值化。
腐蚀上一步得到的黑白图,可见:对实验目的无用信息:条形码,厂家名称等,都被腐蚀成细小黑色线条,只有黑色区域面积大的仪表读数区域突出。
图像二维数组中,从上到下,下到上,设定黑色像素个数阈值280,得到仪表读数区域上下边;同理,设定黑色像素个数阈值100,得到仪表读数区域左右边界。把边界坐标保存为全局变量。
对灰度图pic_gray[240][320]中该区域内二值化,丢弃pic_binary[240][320]数组,接下来的步骤都是对pic_gray[240][320]进行操作了。


图3:pic_binary[240][340]二值化图像

四 减少读数区域白色噪点。
因为存在光照,仪表数字间隔中白色齿轮反射因素,读数区域二值化后,边缘和交界区域存在白色噪点。对pic_gray[240][320]该区域内强制写0,即变为黑色,减少干扰。

五 投影法得到包围住数字的最小边框。
已知仪表读数区域坐标,第一个数字必定在左边界到左边界加上1/3读数区域宽度,上边界到下边界的范围中。把每一竖包含的白色像素点个数投影到长度为1/3读数区域宽度的数组中,找到该数组中连续非0的最长长度及最长非0串的起始点,得到框住第一个数字的最小框的左右边界,类似的,得到框住第一个数字的最小框的上下边界。


图4:找到仪表区域仅对该区域二值化后的图像

六 判断最后一位数字完整性。
最后一位数字滚动速度快,常显示不完整,有白色刻度的图像干扰,使得该位数字识别较困难。
从仪表读数区域右边界到右边界加上1/3区域宽度是最后一位数字所在区域。同第五步一样,对区域内每一竖包含的白色像素点个数做投影。数组中,每一竖拥有白点个数小于1/4仪表读数区域高度的都记为0,这样排除了白色刻度的干扰(一竖白色刻度白点加起来个数不超过高度1/4),得到数组中最长非0串和它的起始结束坐标,即为框住最后一位无论是否完整的数字的左右边界。
在框住数字的左右边界,仪表读数的上下边界这一区域内,对每一行白色像素个数投影到长度为仪表读数区域高度的数组中,统计连续为0串的个数,如果有2个,此时为完整数字,因为当显示完整数字时候,它的上下有连续黑色区域;有三个,说明数字不完整,多出的一个是2个不完整数字之间的黑色区域。


图5:不完整的最后一位数字


图6:完整的数字

七 识别。
可以根据框住数字最小框的宽高比,快速判断是否为数字1,所以,不需要样本数字1。共有9个90*150大小的数字样本。求的包围数字的最小区域,将9个样本均缩放到与其一致大小,统计每个像素异同,得到数字与每一个样本的相似比例,得到识别结果。
重点:邻接插值法缩放样本大小。


图7:随着燃气表转动读数随之改变

Comments
Write a Comment