本人最近开始做有关ocr的项目,具体要做的是身份证信息识别,所以我决定使用tesseract+opencv+Python来实现这个工作.
tesseract是由惠普开发,现在由Google进行维护的一个开源ocr软件,曾经想要深入了解其原理及构架,但整个体系过于庞大,了解其原理并自己修改的工作难以实现,所以这里就选择安装可执行程序,配合pytesseract调用可执行程序直接进行识别,安装包可直接在GitHub的wiki上找到下载地址,csdn上也有很多的安装包可以选择,这里推荐最新版的安装包识别率相对高一点,显示方式也比较合理.
地址
https://download.csdn.net/download/baidu_33473810/10882501
安装过程不加赘述,其他很多博客已经写得非常详细,注意几个重要的点即可,第一,注意安装中选择下载中文语言包,如chi_sim,chi_tar(中文简体,中文繁体),第二,注意安装完成后的环境变量的配置,特别是TESSDATA_PREFIX的配置,配置完成后
一定要重启电脑!!!一定要重启电脑!!!一定要重启电脑!!!
这一点很重要,不然程序一定报错,这一点搞了我快两个小时,就是因为没有重启.
也可选择通过源码编译的方式进行安装,该方法相对复杂一点,估计要再开一篇博客来讲,里面的坑可太多了.
opencv的安装就相对容易,可以直接用pip进行安装,但是这个地方需要注意一点,最新版的opencv存在版权问题,很多函数虽然存在但是他会报错,会出现如下错误:
cv2.error: OpenCV(3.4.3) C:\projects\opencv
python\opencv_contrib\modules\xfeatures2d\src\sift.cpp:1207: error: (-213:The
function/feature is not implemented) This algorithm is patented and is excluded in this
configuration; Set OPENCV_ENABLE_NONFREE CMake option and rebuild the
library in function ‘cv::xfeatures2d::SIFT::create’
这里的错误的原因是这个算法被注册了专利,所以这里不能使用,解决办法就是安装低版本的opencv (这是逼着我不用最新版的, Python也是,3.7还不能用TensorFlow要逼死我这个喜欢用最新版的人)
命令如下:
pip install opencv-python==3.4.2.16
pip install opencv-contrib-python==3.4.2.16
整个实现的过程为:
1.批量读取身份证图片
2.利用SIFT算法进行特征点匹配,找到身份证的位置,并用映射变换将身份证转换到合适的位置
3.利用模板匹配算法,确定姓名,性别,民族,住址,身份证号码的位置
4.对图片进行二值化,降噪等操作
5.用tesseract分别识别出姓名,性别,民族,住址,身份证号码的文字信息
这里需要用到skimage的库,实现代码如下
str1='这里是你图片所在的文件夹'
coll = io.ImageCollection(str1)
此时图片已经全部存入了coll之中
coll[0]即为第一张图片
SIFT特征点检测算法是一种检测局部特征的算法,它是通过求一幅图中的特征点及其有关scale和orientation的描述子得到特征并进行图像特征点匹配。具体原理可以去参考这一篇博客SIFT特征点检测
实现代码如下:
sift = cv2.xfeatures2d.SIFT_create()
kp1, des1 = sift.detectAndCompute(img1,None) #找到模板图像的特征点
kp2, des2 = sift.detectAndCompute(img2,None) #找到识别的特征点
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks = 10)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1,des2,k=2)
# store all the good matches as per Lowe's ratio test.
#两个最佳匹配之间距离需要大于ratio 0.7,距离过于相似可能是噪声点
good = []
for m,n in matches:
if m.distance < 0.8*n.distance:
good.append(m)
#reshape为(x,y)数组
if len(good)>MIN_MATCH_COUNT:
src_pts = np.float32([ kp1[m.queryIdx].pt for m in good]).reshape(-1,1,2)
dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good]).reshape(-1,1,2)
#用HomoGraphy计算图像与图像之间映射关系, M为转换矩阵
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0)
matchesMask = mask.ravel().tolist()
#使用转换矩阵M计算出img1在img2的对应形状
h,w = cv2.UMat.get(img1).shape
M_r=np.linalg.inv(M)
im_r = cv2.warpPerspective(img_org, M_r, (w,h))
即利用matchTemplate函数进行模板匹配,找到姓名,性别等文字的位置后,由于身份证是刚体,所以上面文字的位置是固定的,所以根据位置信息即可找到需要识别的文字的位置,并将其截取出来
利用opencv中的adaptiveThreshold进行自适应二值化,后通过腐蚀膨胀等型态学操作,对图片进行处理达到降低图片噪声的目的
用pytesseract中的函数
pytesseract.image_to_string(gray, config = "-l chi_sim --oem 1 --psm 7"))
第一个参数是要识别的图片,第二个参数中-l 后面是语言库的选择 --oem 后面的参数 1代表用lstm引擎识别, 0表示用传统引擎识别, --psm代表识别方式 7代表是将图片识别为一行字符
通过这些操作可以将很大的提高识别的准确率,但是由于识别引擎自身限制,对中文识别并不友好,识别率依然没有达到我所需要的程度.
接下来要做的:
1.通过对已有的图片进行训练,但官方给的LSTM模式训练的操作还没有吃透,传统方式训练对识别率提高不大
2.尝试理解其内部的原理,并尝试加入自己理解(好像不大可能毕竟别人花了10年才写出来 笑哭)问题还有就是在于并没有多少资料,只有没有多少注释的源码,预计会花费很多的时间