Python技术实现光学字符识别

Python技术实现光学字符识别

随着图像处理技术和机器学习算法的不断发展,光学字符识别(Optical Character Recognition,OCR)在各领域得到了广泛应用,如文本识别、自动化数据输入、身份证识别等。在Python语言中,有许多成熟的OCR库和开源项目,为从事OCR领域的工程师和技术爱好者提供了便利。本文将介绍如何使用Python实现基于深度学习的OCR系统,并提供完整代码实现,供读者参考学习。

一、OCR系统的基本流程

Python技术实现光学字符识别

OCR系统的基本流程是将图片中的字符转换为数字文本,这个过程可以分为四个阶段:

1、图像预处理:包括图像去噪、灰度化、二值化等操作,以减少噪声干扰。

2、字符分割:将整张图片中的每一个字符区分开来,为后续分类处理做准备。

3、特征提取:提取每个字符的特征向量,通常采用特征统计法、轮廓分析法等算法。

4、字符分类:将特征向量与预先训练好的分类模型进行比对,以得到最终的OCR结果。

二、使用Python实现OCR系统的步骤

下面将介绍使用Python实现OCR系统的具体步骤。

1、数据集准备

OCR系统需要训练好的分类模型,而分类模型需要大量的数据集进行训练,数据集的质量直接决定了OCR系统的准确率。在此,我们选择一个公开数据集——MNIST,该数据集是一个非常经典的手写数字数据集,它包含6万张28*28的灰度图像和1万张测试图像。MNIST数据集可以通过Keras预处理包中的函数load_data()导入,代码如下:

“`
from keras.datasets import mnist

(train_xs, train_ys), (test_xs, test_ys) = mnist.load_data()

print(train_xs.shape) # (60000,28,28)
print(train_ys.shape) # (60000,)
print(test_xs.shape) # (10000,28,28)
print(test_ys.shape) # (10000,)
“`

2、图像预处理

为了提高OCR系统的准确率,需要在图像处理中实现以下两个目标:

1)降噪:去掉图像中的噪点和不必要的信息,使整个图像更加清晰,提高准确率。

在Python中,可以使用OpenCV库和Scipy库中的ndimage模块来进行图像去噪。这里,我们选择使用Scipy进行图像降噪,代码如下:

“`
from scipy import ndimage

train_xs = ndimage.median_filter(train_xs, size=(3, 3))
test_xs = ndimage.median_filter(test_xs, size=(3, 3))

# 绘制降噪后的图片
import matplotlib.pyplot as plt

fig = plt.figure()
ax1 = fig.add_subplot(221)
ax1.imshow(train_xs[0])
ax2 = fig.add_subplot(222)
ax2.imshow(train_xs[1])
ax3 = fig.add_subplot(223)
ax3.imshow(train_xs[2])
ax4 = fig.add_subplot(224)
ax4.imshow(train_xs[3])
plt.show()
“`

2)二值化:将图像转化为黑白图像,去掉灰度信息,只保留黑白信息,以便更好地识别字符。

在Python中,可以使用Pillow库和OpenCV库来进行图像二值化。这里,我们选择使用Pillow进行图像二值化,代码如下:

“`
from PIL import Image

def img_binarize(image_path,threshold):
img = Image.open(image_path)
img_mtx = img.load()

row,col = img.size

for i in range(row):
for j in range(col):
if img_mtx[i,j] > threshold:
img_mtx[i,j] = 255
else:
img_mtx[i,j] = 0

return img

image = img_binarize(‘test.png’, 150)
image.show()
“`

3、字符分割

字符分割是OCR系统中比较关键的一步,它将图像中的每个字符区分开来,为后续的特征提取做准备。字符分割常见的算法有边缘检测法、形态学分析法、连通域分析法等。在Python中,可以使用OpenCV、Scipy等库进行字符分割。这里,我们选择使用OpenCV进行字符分割,代码如下:

“`
import cv2

image = cv2.imread(‘train.png’,0)

ret,thresh = cv2.threshold(image,127,255,cv2.THRESH_BINARY)

contours,hierarchy = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)

i = 0
for cnt in contours:
x,y,w,h = cv2.boundingRect(cnt)

if w > 5 and h > 5:
roi = image[y:y+h,x:x+w]
cv2.imwrite(str(i)+’.jpg’,roi)
i += 1
“`

4、特征提取

特征提取是OCR系统中一个极其重要的环节,通常采用的算法有如下两种:

1)统计特征法:利用图像的统计特征来描述图像,如几何矩、灰度共生矩阵、熵等。

2)轮廓分析法:利用字符的轮廓信息,根据其几何特征进行描述,如周长、面积、尺度不变特征变换等。

在本次实现中,我们将采用第一种算法——组合统计特征的方法来提取特征,代码如下:

“`
import numpy as np

def feature_extraction(image):
hist = np.zeros(256)

row, col = image.shape

for i in range(row):
for j in range(col):
pixel = image[i, j]
hist[pixel] += 1

# 特征向量
features = []
features += list(hist)

return np.array(features)

image = cv2.imread(‘character.jpg’, 0)
features = feature_extraction(image)
“`

5、字符分类

字符分类是OCR系统的最终目标,它将特征向量与预先训练好的分类模型进行比对,以得到最终的OCR结果。当然,在深度学习中,字符分类采用的是神经网络,这里我们选择使用Keras深度学习框架来完成字符分类。代码如下:

“`
from keras.models import Sequential
from keras.layers import Dense, Dropout

model = Sequential()
model.add(Dense(512, activation=’relu’, input_shape=(784,)))
model.add(Dropout(0.2))
model.add(Dense(256, activation=’relu’))
model.add(Dropout(0.2))
model.add(Dense(10, activation=’softmax’))

model.compile(loss=’categorical_crossentropy’, optimizer=’adam’, metrics=[‘accuracy’])

train_xs = train_xs.reshape(60000,784)
test_xs = test_xs.reshape(10000,784)
train_ys = np_utils.to_categorical(train_ys, num_classes=10)
test_ys = np_utils.to_categorical(test_ys, num_classes=10)
model.fit(train_xs, train_ys, batch_size=128, epochs=10, verbose=1, validation_data=(test_xs, test_ys))
“`

三、完整代码实现

“`
# -*- coding:utf-8 -*-
from PIL import Image
import numpy as np
from scipy import ndimage

import cv2
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.utils import np_utils

def img_binarize(image_path,threshold):
img = Image.open(image_path)
img_mtx = img.load()

row,col = img.size

for i in range(row):
for j in range(col):
if img_mtx[i,j] > threshold:
img_mtx[i,j] = 255
else:
img_mtx[i,j] = 0

return img

# 数据集准备
(train_xs, train_ys), (test_xs, test_ys) = mnist.load_data()

# 维度变换
train_xs = train_xs.reshape(60000,784)
test_xs = test_xs.reshape(10000,784)

# 图像预处理
train_xs = ndimage.median_filter(train_xs, size=(3, 3))
test_xs = ndimage.median_filter(test_xs, size=(3, 3))

# 图像二值化
_,train_xs = cv2.threshold(train_xs, 150, 255, cv2.THRESH_BINARY_INV)
_, test_xs = cv2.threshold(test_xs, 150, 255, cv2.THRESH_BINARY_INV)

# 特征提取
def feature_extraction(image):
hist = np.zeros(256)

row, col = image.shape

for i in range(row):
for j in range(col):
pixel = image[i, j]
hist[pixel] += 1

# 特征向量
features = []
features += list(hist)

return np.array(features)

train_feature_set = []
test_feature_set = []

for i in range(60000):
img = train_xs[i]
img = img.reshape(28, 28).astype(‘uint8’)
features = feature_extraction(img)
train_feature_set.append(features)

for i in range(10000):
img = test_xs[i]
img = img.reshape(28, 28).astype(‘uint8′)
features = feature_extraction(img)
test_feature_set.append(features)

train_xs = np.array(train_feature_set)
test_xs = np.array(test_feature_set)

# 标签处理
train_ys = np_utils.to_categorical(train_ys, num_classes=10)
test_ys = np_utils.to_categorical(test_ys, num_classes=10)

# 模型训练
model = Sequential()
model.add(Dense(512, activation=’relu’, input_shape=(784,)))
model.add(Dropout(0.2))
model.add(Dense(256, activation=’relu’))
model.add(Dropout(0.2))
model.add(Dense(10, activation=’softmax’))
model.compile(loss=’categorical_crossentropy’, optimizer=’adam’, metrics=[‘accuracy’])
model.fit(train_xs, train_ys, batch_size=128, epochs=10, verbose=1, validation_data=(test_xs, test_ys))

# 测试OCR效果
image = cv2.imread(‘test.png’, 0)
_, image = cv2.threshold(image, 150, 255, cv2.THRESH_BINARY_INV)
img = image.reshape(28, 28).astype(‘uint8’)
features = feature_extraction(img)
features = np.array(features)
features = features.reshape(1,-1)
result = np.argmax(model.predict(features))
print(result)
“`

PS:文章中的代码及测试数据已上传至https://github.com/Aiden-liu128/OCR-python,读者可以自行下载测试。

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023年6月3日 下午12:03
下一篇 2023年6月3日 下午12:24

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注