在去年的时候,学习了神经网络,实现了手写数字识别:
https://www.cnblogs.com/FSYo/p/14802599.html
这个很容易实现的原因是,数据全部可以在 MNIST 下载
之后,我一直想实现一个生活场景中的文字识别,中文太难啦所以我们就做识别 English 的吧!
我用我曾经存下来的英语作文作为训练数据,这一步主要需要克服的困难为,将字母一个一个抠出来,做成 28 * 28 的灰度图,做成之后,就可以用之前写过的神经网络来跑了。
第一步:我们要从 jpg 或 png 文件里面读取像素信息。
- 这一步我使用了 opencv 这一工具,然后学习了一点点 python(因为我完全不会 python,所以是需要啥就百度一下)
使用下面这一份代码,就可以读取图片并展示出来(hello world 是展示图片的窗口的名字)
import cv2
image = cv2.imread("a.png")
cv2.imshow("hello world", image)
cv2.waitKey(0)
cv2.destroyAllWindows
- 读取灰度图只需要改一行:(会直接转换为灰度图)
image = cv2.imread("a.png",0)
- 下面,我们就可以查看长宽,以及每个像素是什么了,我们把信息转换后存到 mat.in 文件中
import cv2
import numpy as np
# 0 -> grey, 1 -> color, -1 -> original
img = cv2.imread("g.png",0)
rows = img.shape[0]
cols = img.shape[1]
fi = open("mat.in", "w")
print(rows, cols, file = fi)
for i in range(0, rows) :
for j in range(0, cols) :
print(img.item(i, j), end = ' ', file = fi)
print('', file = fi)
第二步: 将每个字母抠出来并缩放一下大小。
-
我使用的方法是搜连通块(由于大多数字母和符号是联通的,除了 i j ; : ) 代码
任然存在的问题:空格的处理需要调整参数;对于某些字体,字母间会连在一起。 -
可以使用下面的代码检查抠出来的字母:
import cv2
import numpy as np
fi = open("data7.in")
while 1 :
img = np.zeros((256,256), np.uint8)
ok = 1
for i in range(0, 28) :
arr = fi.readline().split()
for j in range(0, 28) :
if(int(arr[j]) == -1) :
ok = 0
break
img.itemset((i, j), int(arr[j]))
if(ok == 0) :
break
if(ok == 0) :
break
cv2.imshow("show", img)
cv2.waitKey(0)
cv2.destroyAllWindows
fi.readline()
fi.close()
第三步: 将抠出来的图和正确的字母一一对应,喂给神经网络。
- 由于之前写过,所以我就直接拿过来用啦!可以看文章开头的博客
效果:
这是第一次的效果,很不好的原因是造训练数据的程序缩放部分写锅了。
这是和训练数据用的同一种字体的文章识别出的结果。可以看出字体一样的时候效果还是不错的。
没有解决的问题是:I 和 l 长得太像了!(所以上面图中的 I 其实都是 l)
白色部分是从 Codeforces 首页随便截的图,效果一般般,但还能看。
另外,尝试了对纸质版照相并识别,但效果很不好,原因是很多字母连在一块了,所以不能简单的用搜连通块的方法来切字母。
之后应该要多训练几种字体,然后完善一下割字母的程序。
我猜肯定有更简单的方法干这件事,不过我边写边学边摸索确实挺好玩的啦!~