目录
1.Tesseract Ocr文字识别
1.1 运行环境
1.2 python模块
1.3 配置tesseract运行文件
1.4 代码识别
2. 手写汉字识别
2.1 下载库
2.2 代码
1.Tesseract Ocr文字识别
前半部分原github地址:faceai/tesseractOCR.md at master · vipstone/faceai · GitHub
1.1 运行环境
windows10 + python 3.9 + tesseract 5.2.0
https://github.com/UB-Mannheim/tesseract/wiki一、安装tesseract orc
下载地址:https://github.com/UB-Mannheim/tesseract/wiki
点击“tesseract-ocr-w64-setup-v5.2.0.20220712.exe”下载安装。
安装的时候注意选择中文包
本人安装目录:"D:\APP\OCR"
1.2 python模块
matplotlib==3.6.0
numpy==1.23.3
scipy==1.9.1
pywavelets==1.4.1
1.3 配置tesseract运行文件
D:\anaconda\envs\ocr_lhy\Lib\site-packages\pytesseract\pytesseract.py 找到文件:
tesseract_cmd = 'tesseract'
修改为(注意'\\'):
tesseract_cmd = "D:\APP\OCR\\tesseract.exe"
1.4 代码识别
from PIL import Image
import pytesseractpath = "image\\img.png"text = pytesseract.image_to_string(Image.open(path), lang='eng')
print(text)
lang='eng'表示英文识别,效果如下:
(被识别图源于网络)
中文用 lang= ‘chi_sim’,识别效果如下:
“聒” 识别成了 “联”,识别效果还可以
2. 手写汉字识别
OCR还可以通过MINIST数据库,做手写文字识别
以下部分参考,代码有更改https://blog.csdn.net/qq_43006184/article/details/121604452?spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-6-121604452-blog-90744871.topnsimilarv1&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-6-121604452-blog-90744871.topnsimilarv1&utm_relevant_index=13
2.1 下载库
(opencv要注意对应numpy的版本,我用的是1.23.3)
tensorflow==2.10.0
第二个代码要用:
opencv==4.5.5.64
opencv-python==4.5.5.64
下载opencv参考https://blog.csdn.net/qq_43605229/article/details/114572661
2.2 代码
代码如下:
import os
import cv2
import numpy as np
import tensorflow as tf2
import matplotlib.pyplot as plt
import tensorflow.compat.v1 as tfdef nextBatch(data,batch_size,n):#小批量梯度下降法获取当前数据集函数#data为全部数据[X,Y],batch_size为当前子数据集大小,n为第n个子数据集a=n*batch_sizeb=(n+1)*batch_sizelimdata=len(data[0])if b>limdata:b=limdataa=b-batch_sizedata_x=data[0][a:b]data_y=data[1][a:b]return data_x,data_ydef main_train():(x_tr0,y_tr0),(x_te0,y_te0)=tf2.keras.datasets.mnist.load_data()#手写数据库y_tr=np.zeros((len(y_tr0),10))y_te=np.zeros((len(y_te0),10))for i in range(len(y_tr0)):y_tr[i][y_tr0[i]]=1for i in range(len(y_te0)):y_te[i][y_te0[i]]=1x_tr=x_tr0.reshape(-1,28,28,1)x_te=x_te0.reshape(-1,28,28,1)training_epochs=100#训练步数batch_count=20#小批量训练子集数量L=32#卷积层1所提取特征个数M=64#卷积层2所提取特征个数N=128#卷积层3所提取特征个数O=625#全连接就层神经元数with tf.device('/cpu:0'):# with tf.device('/gpu:0'):Xin=tf.placeholder(tf.float32,[None,28,28,1],name='Xin')#28×28维输入特征Yout=tf.placeholder(tf.float32,[None,10],name="Yout")#10类分类结果标签W1=tf.Variable(tf.random_normal([3,3,1,L],stddev=0.01))#卷积层1的卷积核权值张量,卷积核大小3×3,输入数据为1通道,输出特征为32通道W2=tf.Variable(tf.random_normal([3,3,L,M],stddev=0.01))#卷积层2的卷积核权值张量,卷积核大小3×3,输入数据为32通道,输出特征为64通道W3=tf.Variable(tf.random_normal([3,3,M,N],stddev=0.01))#卷积层3的卷积核权值张量,卷积核大小3×3,输入数据为64通道,输出特征为128通道W4=tf.Variable(tf.random_normal([N*4*4,O],stddev=0.01))#全连接层权值张量,输入数据为128×4×4个,输出为625个,这里需要把上一层的高维张量扁平化W5=tf.Variable(tf.random_normal([O,10],stddev=0.01))#输出层权值张量,输入数据为625,输出为10类b1=tf.Variable(tf.random_normal([L],stddev=0.01))#卷积层1的输出特征阈值,输出特征为32通道,每个通道共享一个阈值b2=tf.Variable(tf.random_normal([M],stddev=0.01))#卷积层2的输出特征阈值,输出特征为64通道,每个通道共享一个阈值b3=tf.Variable(tf.random_normal([N],stddev=0.01))#卷积层3的输出特征阈值,输出特征为128通道,每个通道共享一个阈值b4=tf.Variable(tf.random_normal([O],stddev=0.01))#全连接层阈值b5=tf.Variable(tf.random_normal([10],stddev=0.01))#输出层阈值'''卷积层一'''conv1a=tf.nn.conv2d(Xin,W1,strides=[1,1,1,1],padding='SAME')conv1b=tf.nn.bias_add(conv1a,b1)conv1c=tf.nn.relu(conv1b)'''池化层一'''conv1=tf.nn.max_pool(conv1c,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')'''卷积层二'''conv2a=tf.nn.conv2d(conv1,W2,strides=[1,1,1,1],padding='SAME')conv2b=tf.nn.bias_add(conv2a,b2)conv2c=tf.nn.relu(conv2b)'''池化层二'''conv2=tf.nn.max_pool(conv2c,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')'''卷积层三'''conv3a=tf.nn.conv2d(conv2,W3,strides=[1,1,1,1],padding='SAME')conv3b=tf.nn.bias_add(conv3a,b3)conv3c=tf.nn.relu(conv3b)'''池化层三'''conv3d=tf.nn.max_pool(conv3c,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')conv3=tf.reshape(conv3d,[-1,W4.get_shape().as_list()[0]])#扁平化'''全连接层'''FCa=tf.matmul(conv3,W4)+b4FC=tf.nn.relu(FCa)'''输出层'''Y_=tf.matmul(FC,W5)+b5Y=tf.nn.softmax(Y_,name="output")#经历softmax分类激活函数后的数值'''损失'''cross_entropy=tf.nn.softmax_cross_entropy_with_logits(logits=Y_, labels=Yout)loss=tf.reduce_mean(cross_entropy)*100#交叉损失correct_prediction=tf.equal(tf.argmax(Y,1),tf.argmax(Yout,1))accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32),name='accuracy')#正确率'''优化器'''trainer=tf.train.RMSPropOptimizer(learning_rate=0.001,momentum=0.9).minimize(loss)init=tf.global_variables_initializer()#变量初始化赋值器with tf.Session() as sess:sess.run(init)#变量初始化out_init=sess.run(accuracy,feed_dict={Xin:x_tr[0:20000],Yout:y_tr[0:20000]})#计算初始误差print("初始准确率为:{:.4f}%".format(out_init*100))#输出初始误差for epoch in range(training_epochs):#训练步数print("当前训练步为第{}步".format(epoch+1))batch_size=int(len(y_tr)/batch_count)#当前子集大小for i in range(batch_count):#对每个子集遍历训练batch_x,batch_y=nextBatch([x_tr[0:20000],y_tr[0:20000]],batch_size,i)#当前子集的训练集特征和标签数据sess.run(trainer,feed_dict={Xin:batch_x,Yout:batch_y})out=sess.run(accuracy,feed_dict={Xin:x_tr[0:20000],Yout:y_tr[0:20000]})#计算当前误差print("当前准确率为:{:.4f}%".format(out*100))#当前初始误差'''当前会话存储'''if out>out_init:out_init=outsaver=tf.train.Saver()saver.save(sess,r".\savefile\CNN\FigureCNN.ckpt")returndef main_test():(x_tr0,y_tr0),(x_te0,y_te0)=tf2.keras.datasets.mnist.load_data()#手写数据库y_tr=np.zeros((len(y_tr0),10))y_te=np.zeros((len(y_te0),10))for i in range(len(y_tr0)):y_tr[i][y_tr0[i]]=1for i in range(len(y_te0)):y_te[i][y_te0[i]]=1x_tr=x_tr0.reshape(-1,28,28,1)x_te=x_te0.reshape(-1,28,28,1)road=[r".\savefile\CNN\FigureCNN.ckpt.meta",r".\savefile\CNN\FigureCNN.ckpt"]sess=tf.InteractiveSession()new_saver=tf.train.import_meta_graph(road[0])new_saver.restore(sess,road[1])tf.get_default_graph().as_graph_def()Xin=sess.graph.get_tensor_by_name('Xin:0')Yout=sess.graph.get_tensor_by_name("Yout:0")accuracy=sess.graph.get_tensor_by_name('accuracy:0')Y=sess.graph.get_tensor_by_name('output:0')roadpic='./image/one.jpeg' # './image/eight.jpeg' # 手写数字文件,大小28x28像素pic=cv2.imread(roadpic,flags=0)pic1=255-pic # 因为MINIST数据库是黑底白字,我用的是白底黑字# pic1 = cv2.resize(pic1,(28,28))pic=pic1.reshape(-1,28,28,1)Otem=sess.run(Y,feed_dict={Xin:pic})print('南笙手写的数字为:{}'.format(Otem.argmax()))returnif __name__=="__main__":tf.disable_v2_behavior()os.environ['TF_CPP_MIN_LOG_LEVEL']='2'# 如果已经生成模型,可以注释掉main_train()函数main_train()main_test()
其中,main_train()函数用于训练模型,
截取部分运行结果,最高的成功率大概为99.21%(当然每次运行结果会有不一样):
main_test()函数用于识别自己的手写数字,需要注意几点:
① MINIST数据集是黑底白字,我用的是白底黑字,所以要有 pic1=255-pic 的操作。
② 图片是经过我预先处理成28x28像素大小的,不然会报错。(也可以通过代码处理成28x28大小的)
自己的手写字体识别效果(图片预处理成28x28的大小):