OpenCV-Python 系列 五十三 | 使用OCR手写数据集运行KNN
本文是全系列中第15 / 63篇:OpenCV-Python
- OpenCV-Python 系列 四 | 视频入门
- OpenCV-Python 系列 十二 | 图像的几何变换
- OpenCV-Python 系列 二十 | 轮廓:入门
- OpenCV-Python 系列 二十八 | 直方图4:直方图反投影
- OpenCV-Python 系列 三十六 | 哈里斯角检测
- OpenCV-Python 系列 四十四 | 特征匹配 + 单应性查找对象
- OpenCV-Python 系列 五十二 | 理解K近邻
- OpenCV-Python 系列 六十 | 高动态范围
- OpenCV-Python 系列 五 | OpenCV中的绘图功能
- OpenCV-Python 系列 十三 | 图像阈值
- OpenCV-Python 系列 二十一 | 轮廓特征
- OpenCV-Python 系列 二十九 | 傅里叶变换
- OpenCV-Python 系列 三十七 | Shi-tomas拐角检测器和益于跟踪的特征
- OpenCV-Python 系列 四十五 | 如何使用背景分离方法
- OpenCV-Python 系列 五十三 | 使用OCR手写数据集运行KNN
- OpenCV-Python 系列 六十一 | 级联分类器
- OpenCV-Python 系列 六 | 鼠标作为画笔
- OpenCV-Python 系列 十四 | 图像阈值
- OpenCV-Python 系列 二十二 | 轮廓属性
- OpenCV-Python 系列 三十 | 模板匹配
- OpenCV-Python 系列 三十八 | SIFT尺度不变特征变换
- OpenCV-Python 系列 四十六 | Meanshift和Camshift
- OpenCV-Python 系列 五十四 | 理解SVM
- OpenCV-Python 系列 六十二 | 级联分类器训练
- OpenCV-Python 系列 七 | 轨迹栏作为调色板
- OpenCV-Python 系列 十五 | 图像平滑
- OpenCV-Python 系列 二十三 | 轮廓:更多属性
- OpenCV-Python 系列 三十一 | 霍夫线变换
- OpenCV-Python 系列 三十九 | SURF简介(加速的强大功能)
- OpenCV-Python 系列 四十七 | 光流
- OpenCV-Python 系列 五十五 | 使用OCR手写数据集运行SVM
- OpenCV-Python 系列 六十三 | OpenCV-Python Bindings 如何工作?
- OpenCV-Python 系列 八 | 图像的基本操作
- OpenCV-Python 系列 十六 | 形态学转换
- OpenCV-Python 系列 二十四 | 轮廓分层
- OpenCV-Python 系列 三十二 | 霍夫圈变换
- OpenCV-Python 系列 四十 | 用于角点检测的FAST算法
- OpenCV-Python 系列 四十八 | 相机校准
- OpenCV-Python 系列 五十六 | 理解K-Means聚类
- OpenCV-Python 系列 一 | 系列简介与目录
- OpenCV-Python 系列 九 | 图像上的算术运算
- OpenCV-Python 系列 十七 | 图像梯度
- OpenCV-Python 系列 二十五 | 直方图-1:查找、绘制和分析
- OpenCV-Python 系列 三十三 | 图像分割与Watershed算法
- OpenCV-Python 系列 四十一 | BRIEF(二进制的鲁棒独立基本特征)
- OpenCV-Python 系列 四十九 | 姿态估计
- OpenCV-Python 系列 五十七 | OpenCV中的K-Means聚类
- OpenCV-Python 系列 二 | 安装OpenCV-Python
- OpenCV-Python 系列 十 | 性能衡量和提升技术
- OpenCV-Python 系列 十八 | Canny边缘检测
- OpenCV-Python 系列 二十六 | 直方图-2:直方图均衡
- OpenCV-Python 系列 三十四 | 交互式前景提取使用GrabCut算法
- OpenCV-Python 系列 四十二 | ORB(面向快速和旋转的BRIEF)
- OpenCV-Python 系列 五十 | 对极几何
- OpenCV-Python 系列 五十八 | 图像去噪
- OpenCV-Python 系列 三 | 图像入门
- OpenCV-Python 系列 十一 | 改变颜色空间
- OpenCV-Python 系列 十九 | 图像金字塔
- OpenCV-Python 系列 二十七 | 直方图-3:二维直方图
- OpenCV-Python 系列 三十五 | 理解特征
- OpenCV-Python 系列 四十三 | 特征匹配
- OpenCV-Python 系列 五十一 | 立体图像的深度图
- OpenCV-Python 系列 五十九 | 图像修补
目标
在本章中
– 我们将使用我们在kNN上的知识来构建基本的OCR应用程序。
– 我们将尝试使用OpenCV自带的数字和字母数据集。
手写数字的OCR
我们的目标是构建一个可以读取手写数字的应用程序。为此,我们需要一些train_data
和test_data
。OpenCV带有一个图片digits.png
(在文件夹opencv/samples/data/
中),其中包含5000
个手写数字(每个数字500个)。每个数字都是20x20
的图像。因此,我们的第一步是将图像分割成5000
个不同的数字。对于每个数字,我们将其展平为400
像素的一行。那就是我们的训练集,即所有像素的强度值。这是我们可以创建的最简单的功能集。我们将每个数字的前250
个样本用作train_data
,然后将250
个样本用作test_data
。因此,让我们先准备它们。
import numpy as np
import cv2 as cv
img = cv.imread('digits.png')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 现在我们将图像分割为5000个单元格,每个单元格为20x20
cells = [np.hsplit(row,100) for row in np.vsplit(gray,50)]
# 使其成为一个Numpy数组。它的大小将是(50,100,20,20)
x = np.array(cells)
# 现在我们准备train_data和test_data。
train = x[:,:50].reshape(-1,400).astype(np.float32) # Size = (2500,400)
test = x[:,50:100].reshape(-1,400).astype(np.float32) # Size = (2500,400)
# 为训练和测试数据创建标签
k = np.arange(10)
train_labels = np.repeat(k,250)[:,np.newaxis]
test_labels = train_labels.copy()
# 初始化kNN,训练数据,然后使用k = 1的测试数据对其进行测试
knn = cv.ml.KNearest_create()
knn.train(train, cv.ml.ROW_SAMPLE, train_labels)
ret,result,neighbours,dist = knn.findNearest(test,k=5)
# 现在,我们检查分类的准确性
#为此,将结果与test_labels进行比较,并检查哪个错误
matches = result==test_labels
correct = np.count_nonzero(matches)
accuracy = correct*100.0/result.size
print( accuracy )
因此,我们的基本OCR应用程序已准备就绪。这个特定的例子给我的准确性是91%。一种提高准确性的选择是添加更多数据进行训练,尤其是错误的数据。因此,与其每次启动应用程序时都找不到该培训数据,不如将其保存,以便下次我直接从文件中读取此数据并开始分类。您可以借助一些Numpy函数(例如np.savetxt,np.savez,np.load等)来完成此操作。请查看其文档以获取更多详细信息。
# 保存数据
np.savez('knn_data.npz',train=train, train_labels=train_labels)
# 现在加载数据
with np.load('knn_data.npz') as data:
print( data.files )
train = data['train']
train_labels = data['train_labels']
在我的系统中,它需要大约4.4 MB
的内存。由于我们使用强度值(uint8数据)作为特征,因此最好先将数据转换为np.uint8
,然后再将其保存。在这种情况下,仅占用1.1 MB
。然后在加载时,您可以转换回float32
。
英文字母的OCR
接下来,我们将对英语字母执行相同的操作,但是数据和功能集会稍有变化。在这里,OpenCV代替了图像,而在opencv/samples/cpp/
文件夹中附带了一个数据文件letter-recognitiontion.data
。如果打开它,您将看到20000行,乍一看可能看起来像垃圾。实际上,在每一行中,第一列是一个字母,这是我们的标签。接下来的16个数字是它的不同功能。这些功能是从UCI机器学习存储库获得的。您可以在此页面中找到这些功能的详细信息。
现有20000个样本,因此我们将前10000个数据作为训练样本,其余10000个作为测试样本。我们应该将字母更改为ASCII字符,因为我们不能直接使用字母。
import cv2 as cv
import numpy as np
# 加载数据,转换器将字母转换为数字
data= np.loadtxt('letter-recognition.data', dtype= 'float32', delimiter = ',',
converters= {0: lambda ch: ord(ch)-ord('A')})
# 将数据分为两个,每个10000个以进行训练和测试
train, test = np.vsplit(data,2)
# 将火车数据和测试数据拆分为特征和响应
responses, trainData = np.hsplit(train,[1])
labels, testData = np.hsplit(test,[1])
# 初始化kNN, 分类, 测量准确性
knn = cv.ml.KNearest_create()
knn.train(trainData, cv.ml.ROW_SAMPLE, responses)
ret, result, neighbours, dist = knn.findNearest(testData, k=5)
correct = np.count_nonzero(result == labels)
accuracy = correct*100.0/10000
print( accuracy )
它给我的准确性为93.22%
。同样,如果要提高准确性,则可以迭代地在每个级别中添加错误数据。
附加资源
练习
原创文章,作者:磐石,如若转载,请注明出处:https://panchuang.net/2020/04/02/opencv-python-%e7%b3%bb%e5%88%97-%e4%ba%94%e5%8d%81%e4%b8%89-%e4%bd%bf%e7%94%a8ocr%e6%89%8b%e5%86%99%e6%95%b0%e6%8d%ae%e9%9b%86%e8%bf%90%e8%a1%8cknn/