简单BP网络识别数码表字符
01数码识别
这学期的人工神经网络课程已经进行完了第三章内容,关于经典网络重要的BP(误差反向传播网络)是所有学习人工神经网络最先接触到的一个实用网络。它的原理相对比较简单,在很多平台中都非常容易实现。
学习神经网络的基本原理之后,更重要的是能够通过一些应用场合来应用它,使他能够帮助自己解决一些实际的工程问题。
近期购买到的 LC100-A 电感电容测量模块,用于测量一些实验中实验对象的电感、电容值随着其他一些物理变量(工作电压、距离、温度等)所产生变化规律。为了便于实验,需要能够将LC100-A测量数值自动记录。
▲ 上电过程
▲ LC100-A显示的数字
在开始的方式就是直接使用摄像头获取液晶显示数据,然后使用字符识别软件来完成其中数字的识别。
测试一下CNOCR识别效果。它对于屏幕截图中的文字识别效果还不错:
▲ 屏幕截取的一段文字
- 识别时间:1.98。* 识别结果:
[[‘●’, ‘更’, ‘新’, ‘了’, ‘训’, ‘练’, ‘代’, ‘码’, ‘,’, ‘使’, ‘用’, ‘m’, ‘x’, ‘n’, ‘e’, ‘t’, ‘的’, ‘r’, ‘e’, ‘c’, ‘o’, ‘r’, ‘d’, ‘i’, ‘o’, ‘首’, ‘先’, ‘把’, ‘数’, ‘据’, ‘转’, ‘换’, ‘成’, ‘二’, ‘进’, ‘制’, ‘格’, ‘式’, ‘,’, ‘提’, ‘升’, ‘后’, ‘续’, ‘的’], [‘训’, ‘练’, ‘效’, ‘率’, ‘。’, ‘训’, ‘练’, ‘时’, ‘支’, ‘持’, ‘对’, ‘图’, ‘片’, ‘做’, ‘实’, ‘时’, ‘数’, ‘据’, ‘增’, ‘强’, ‘。’, ‘也’, ‘加’, ‘入’, ‘了’, ‘更’, ‘多’, ‘可’, ‘传’, ‘入’, ‘的’, ‘参’, ‘数’, ‘。’], [‘●’, ‘允’, ‘许’, ‘训’, ‘练’, ‘集’, ‘中’, ‘的’, ‘文’, ‘字’, ‘数’, ‘量’, ‘不’, ‘同’, ‘,’, ‘目’, ‘前’, ‘是’, ‘中’, ‘文’, ‘1’, ‘0’, ‘个’, ‘字’, ‘,’, ‘英’, ‘文’, ‘2’, ‘0’, ‘个’, ‘字’, ‘母’, ‘。’], [’。’, ‘提’, ‘供’, ‘了’, ‘更’, ‘多’, ‘的’, ‘模’, ‘型’, ‘选’, ‘择’, ‘,’, ‘允’, ‘许’, ‘大’, ‘家’, ‘按’, ‘需’, ‘训’, ‘练’, ‘多’, ‘种’, ‘不’, ‘同’, ‘大’, ‘小’, ‘的’, ‘识’, ‘别’, ‘模’, ‘型’, ‘。’], [‘●’, ’ ', ‘内’, ‘置’, ‘了’, ‘各’, ‘种’, ‘训’, ‘练’, ‘好’, ‘的’, ‘模’, ‘型’, ‘,’, ‘最’, ‘小’, ‘的’, ‘模’, ‘型’, ‘只’, ‘有’, ‘之’, ‘前’, ‘模’, ‘型’, ‘的’, ‘1’, ‘/’, ‘5’, ‘大’, ‘小’, ‘。’, ‘所’, ‘有’, ‘模’, ‘型’, ‘都’, ‘可’, ‘免’, ‘费’], [‘使’, ‘用’, ‘。’]]
那么对于前面液晶屏幕识别效果呢:
▲ 只是数字部分
识别结果:
[[’.’, ‘。’, ‘与’, ‘F’, ‘早’, ‘H’]]
好像驴唇不对马嘴。
这主要原因还是原来网络没有针对上述液晶实现数字进行训练过。由于液晶显示图片质量非常好,实际上只需要最简单的BP网络就可以达到很好的效果。
下面给出在MATLAB中构建网络并进行实验的过程。
02准备数据集
使用神经网络解决问题,一个重要的环节就是进行训练数据的准备。通过对采集到的一些图片中的数字进行提取并手工标注,来完成对网络的训练。
1.数字分割
下面是桌面摄像头捕捉到的测量图片,通过简单的图片灰度投影,比较方便将显示数字所在图片中的位置定出。为了简单起见,也可以固定摄像头与LCD相对位置,这样手工定标出结果字符位置也可以适用于后面测量结果。
▲ 液晶数字显示以及数字部分
这个问题简单之处在于所有字符都是等宽,而且对比度非常好,简单的分离就可以将所有的字符单独分离出来。由于摄像头位置固定,所以简单分割之后的字符之后少量的上下左右平移,没有旋转。对于图片位置、尺寸就不再进行归一化。这些差异最后有神经网络来弥补。
▲ 分割出的数字
液晶显示字符的图片对比度很好。但就是有一个问题,在摄像头拍摄的时候,经常会遇到字符变化过程,这就会使得图片中字符呈现两个字符叠加的情况。下面是一些示例:
▲ 数字变化过程的图片
这些过程,说实在的,即使人工识别也会无法分辨。
后面通过人工输入标注了2000多个样本。
2.图片二值化
对于分割的图片进行二值化,可以消除环境光对于图片亮度的影响。在一定程度上,也可以消除液晶字符在变化时所引起的模糊。
▲ 图像二值化对应的点阵
▲ 二值化对应的数组
▲ 二值化对应的数字
上面所有的字符的尺寸是23乘以38点阵。
03训练神经网络
1.构建网络和训练
简单的实验,就用简单的方法。对于前面所得到的字符,不再人工定义它们的特征。仅仅将原来的彩色图片变换成灰度图像,然后排列成23×38=874维向量。然后增加一层中间隐层便组成了最简单的分类网络。
net = patternnet(11)
▲ 构造一个单隐层神经网络
将前面人工标注的样本一半用于训练,全部样本用于测试。下面给出了测试的结果。
plotconfusion(xx, net(yy))
▲ 训练结果
2.训练结果与分析
整体的错误率大约为:ERR= 2.99%。
下面是识别正确的字符。
▲ 识别正确的字符
下面给出了部分识别错误字符的情况。基本上都是一些拍摄到液晶字符在变化过程中的重叠字符情况。这些情况本身在人工标注的时候就存在模糊。
▲ 错误样本集合
▲ 错误的识别字符
3.网络结构与错误率
下面给出了网络的隐层节点个数与识别错误样本个数之间的关系。可以看到当中间隐层节点大于5之后,识别性能就不再有明显的变化了。
隐层节点个数 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
---|---|---|---|---|---|---|---|---|---|---|
错误数量 | 1810 | 656 | 216 | 77 | 69 | 66 | 65 | 72 | 58 | 68 |
▲ 隐层节点个数与错误率
04讨论
使用神经网络解决问题,不是寻找最强大的网络,而是需要最合适的网络。
通过上面的测试结果来看,简单的单隐层网络便可以很好的满足液晶显示数字识别。那么对于那些由于数字跳动所引起的错误该怎么处理呢?
这个问题如果仅仅依靠增加训练样本和改进网络结构是很难进行彻底解决,规避这个错误可以通过对连续识别结果进行比对来解决。对显示数字进行连续快速采集5帧图像,其中液晶跳动往往只发生在其中一帧,或者两帧。那么对于五个图像识别出的数字进行对比,找到相同次数最多的数字作为输出结果。
#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# TEST1.PY -- by Dr. ZhuoQing 2020-10-16
#
# Note:
#============================================================
from headm import *
import imgsub
picdir = tsptext2string('pic2dir')
files = os.listdir(picdir)
#------------------------------------------------------------
for f in files:
fn = os.path.join(picdir, f)
if os.path.isfile(fn):
printf(f)
imgsub.cropimage(fn, imgsub.digitdir)
# break
printf('\a')
#------------------------------------------------------------
# END OF FILE : TEST1.PY
#============================================================
#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# IMGSUB.PY -- by Dr. ZhuoQing 2020-10-16
#
# Note:
#============================================================
from head import *
from PIL import Image
#------------------------------------------------------------
'''
imageid = 121
boxid = 122
imagebox = tspgetrange(imageid)
boxbox = tspgetrange(boxid)
printff(imagebox, boxbox)
pos_left = boxbox[0] - imagebox[0]
pos_top = boxbox[1] - imagebox[1]
boxwidth = boxbox[2] - boxbox[0]
boxheight = boxbox[3] - boxbox[1]
tspsave('digitbox', left=pos_left, top=pos_top, width=boxwidth, height=boxheight)
printff(pos_left, pos_top, boxwidth, boxheight)
'''
#------------------------------------------------------------
left, top, width, height = tspload('digitbox', 'left', 'top', 'width', 'height')
numnum = 7 # digit num
def cropimage(imagefile, savedir):
im = Image.open(imagefile)
for i in range(5):
cleft = int(left + i * width/numnum)
cwidth = int(width/numnum)
im1 = im.crop((cleft, int(top), cleft+cwidth, int(top+height)))
fbn = os.path.basename(imagefile).split('.')
savefn = os.path.join(savedir, fbn[0]+'_%d'%i+'.'+fbn[1])
im1.save(savefn)
printf(savefn)
#============================================================
imname = r'd:\temp\201013173456\0000.bmp'
digitdir = r'd:\temp\digitdir'
if __name__ == "__main__":
cropimage(imname, digitdir)
#------------------------------------------------------------
# END OF FILE : IMGSUB.PY
#============================================================
#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# TEST2.PY -- by Dr. ZhuoQing 2020-10-16
#
# Note:
#============================================================
from headm import *
from PIL import Image
digitid = 147
filename = tspgetdopfile(digitid)
printf(filename)
im = Image.open(filename)
imdata = im.getdata()
imsize = size(imdata)
imdata = resize(array(im.getdata()).mean(axis=1), imsize[::-1])
imb = imdata>80
imb1 = [[int(a) for a in b] for b in imb]
for l in imb1:
printf(l)
exit()
printf(shape(imdata))
printf(imdata[5])
#------------------------------------------------------------
# END OF FILE : TEST2.PY
#============================================================
#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# MKDIRALL.PY -- by Dr. ZhuoQing 2020-10-16
#
# Note:
#============================================================
from head import *
from shutil import copyfile
labeldir = r'D:\Temp\digitlabel'
dirstr = r'D:\Temp\digitall'
labelalldir = r'd:\temp\labelall'
#------------------------------------------------------------
for i in range(11):
dirname = os.path.join(dirstr, 'digit_%x'%i)
printf(dirname)
for f in os.listdir(dirname):
fb = os.path.basename(f)
fromfile = os.path.join(dirname, f)
tofile = os.path.join(labelalldir, fb)
copyfile(fromfile, tofile)
printf('\a')
#------------------------------------------------------------
'''
fileall = os.listdir(labeldir)
for f in fileall:
fn = os.path.basename(f).split('_')[1]
if fn[0] == '.': continue
copydir = os.path.join(dirstr, 'digit_%s'%fn[0])
savefile = os.path.join(copydir, os.path.basename(f))
printf(fn)
copyfile(os.path.join(labeldir, f), savefile)
# break
printf(len(fileall))
'''
#------------------------------------------------------------
'''
for i in range(11):
dirname = 'digit_%x'%i
dirname = os.path.join(dirstr, dirname)
printf(dirname)
if not os.path.isdir(dirname):
os.mkdir(dirname)
'''
#------------------------------------------------------------
#------------------------------------------------------------
# END OF FILE : MKDIRALL.PY
#============================================================
#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# TEST4.PY -- by Dr. ZhuoQing 2020-10-16
#
# Note:
#============================================================
from head import *
from PIL import Image
tfname = r'd:\temp\t.txt'
xfname = r'd:\temp\x.txt'
filedir = r'D:\Temp\labelall'
allfile = os.listdir(filedir)
tf = open(tfname, 'w')
xf = open(xfname, 'w')
xdata = []
tdata = []
#------------------------------------------------------------
for f in allfile:
fn = os.path.join(filedir, f)
im = mean(array(Image.open(fn).getdata()), axis=1)
imint = [int(a) for a in im]
xdata.append(imint)
imintstr = str(imint).strip('[]')
# printf(imintstr)
fb = f.split('_')[1][0]
if fb == 'a': t = 10
else: t = int(fb)
tdim = [0] * 11
tdim[t] = 1
tdata.append(tdim)
tstr = str(tdim).strip('[]')
# printf(tstr)
tf.write('%s\n'%tstr)
xf.write('%s\n'%imintstr)
# imsize = size(im)
# printf(imsize)
# imdata = resize(mean(array(im), axis=1), imsize[::-1])
# printf(shape(imdata))
# imint = [[int(a>80) for a in b] for b in imdata]
# for l in imint:
# printf(l)
# break
tf.close()
xf.close()
printf('\a')
tspsave('digitdata',x=xdata, t=tdata)
#------------------------------------------------------------
# END OF FILE : TEST4.PY
#============================================================
#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# TESTERR.PY -- by Dr. ZhuoQing 2020-10-16
#
# Note:
#============================================================
from headm import *
from tsmodule.tsdraw import *
x, t = tspload('digitdata', 'x', 't')
#y = tspload('ydata', 'y')
result = clipboard.paste().strip('[]').split(';')
tdim = []
for r in result:
tdim.append(r.split(' '))
y = [[int(float(b) > 0.5) for b in a] for a in zip(*tdim)]
printf(y[0])
err = 0
#------------------------------------------------------------
def t2num(t):
if any(t) == 1:
return list(t).index(1)
else: return 0
#------------------------------------------------------------
pltgif = PlotGIF()
for yy,tt,xx in zip(t, y, x):
# if list(yy==tt).count(False) == 0:
# err += 1
# plt.clf()
# plt.imshow(resize(xx, (32, 23)), cmap='gray')
# plt.title('识别结果:%d'%t2num(yy))
# plt.draw()
# plt.pause(.1)
# pltgif.append(plt)
# if err > 250: break
if list(yy==tt).count(False) > 0:
err += 1
# plt.clf()
# plt.imshow(resize(xx,(38,23)), cmap='gray')
# plt.title('%s-->%s'%(t2num(yy),t2num(tt)))
# plt.draw()
# plt.pause(.1)
# pltgif.append(plt)
#printf(list((t[0] == y[0])).count(False))
printf(err)
#pltgif.save(r'd:\temp\1.gif')
#------------------------------------------------------------
# END OF FILE : TESTERR.PY
#============================================================
文章来源: zhuoqing.blog.csdn.net,作者:卓晴,版权归原作者所有,如需转载,请联系作者。
原文链接:zhuoqing.blog.csdn.net/article/details/109110907
- 点赞
- 收藏
- 关注作者
评论(0)