【Python3-OpenCV】数字识别

1,663 阅读3分钟

这是我参与更文挑战的第23天,活动详情查看: 更文挑战

OpenCV是一个C++库,目前流行的计算机视觉编程库,用于实时处理计算机视觉方面的问题,它涵盖了很多计算机视觉领域的模块。在Python中常使用OpenCV库实现图像处理。

image.png

本文将介绍如何在Python3中使用OpenCV实现数字识别。

基本原理

1.载入训练图片

读取OpenCV安装目录下手写图片合集:

image.png

2.图片分割

此图片大小为2000*10005K个手写字符,可以求得每个数字大约占有400个像素,故将图像分割为 20 *20 的小块。

digits.png

# 将图片进行分割成5000块横向100纵向50,分割为20*20
cells = [np.hsplit(row,100) for row in np.vsplit(gray,50)]

3.灰度处理

将分割的图片进行灰度化,使原本的RGB多维数据转化为二维灰度数据,方便处理。

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

4.数据矩阵化

将灰度图像转换为矩阵横向划分为100份,纵向划分50份。

# 纵线分割np.hsplit(数组,份数),横线分割np.vsplit(数组,份数)
# 使其成为一个Numpy数组,大小为(50,100,20,20)
x = np.array(cells)

5.分配训练集与测试集

分别分配50列,前50列为训练集,后50列为测试集。

# 准备train_data和test_data
train = x[:,:50].reshape(-1,400).astype(np.float32)
test = x[:,50:100].reshape(-1,400).astype(np.float32)

6.将训练测试集进行标定

方便确定每个块内的数字具体是多少。

# 创建测试,训练标签
k = np.arange(10)
train_labels = np.repeat(k,250)[:,np.newaxis]
test_labels = train_labels.copy()

7.创建KNN邻近

训练模型。

# 初始化KNN,训练数据,然后使用k = 1的测试数据对其进行测试
knn = cv2.ml.KNearest_create()
knn.train(train,cv2.ml.ROW_SAMPLE,train_labels)

8.使用测试集

检测模型准确率。

matches = result==test_labels
correct = np.count_nonzero(matches)
accuracy = correct*100.0/result.size
print(accuracy)

实现代码

训练代码

import numpy as np
import cv2

img = cv2.imread('F:\\yolo-data\\opencv 3.3\\opencv\\sources\\samples\\data\\digits.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 将图片进行分割成5000块横向100纵向50,分割为20*20
# 纵线分割np.hsplit(数组,份数),横线分割np.vsplit(数组,份数)
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)
test = x[:,50:100].reshape(-1,400).astype(np.float32)

# 创建测试,训练标签
k = np.arange(10)
train_labels = np.repeat(k,250)[:,np.newaxis]
test_labels = train_labels.copy()
# 初始化KNN,训练数据,然后使用k = 1的测试数据对其进行测试
knn = cv2.ml.KNearest_create()
knn.train(train,cv2.ml.ROW_SAMPLE,train_labels)
ret,result,neighbours,dist = knn.findNearest(test,k=5)#test

matches = result==test_labels
correct = np.count_nonzero(matches)
accuracy = correct*100.0/result.size
print(accuracy)

训练输出为:

image.png

测试输入:

demo.png

测试代码

import numpy as np
import cv2

# ------------------输入图片处理部分--------------------------------
test_img = cv2.imread('E:\\demo\\demo.png')
# 缩放测试图片至20*20
height, width = test_img.shape[:2]
size = (int(width/25), int(height/25))
res = cv2.resize(test_img,size, interpolation=cv2.INTER_CUBIC)
# 图片进行灰度处理
res_gray = cv2.cvtColor(res,cv2.COLOR_BGR2GRAY)
# 生成等长的纯白255矩阵
test_array = np.array(res_gray)
g25 = np.ones(test_array.shape)
g25 = g25*255
# 相减将底色与字体实际灰度值调换(将底色变为黑色,字体变为白色)
test_array = g25-test_array
# 将多维矩阵转换为一维矩阵
input_test = test_array[:,:].reshape(-1,400).astype(np.float32)
print(input_test.size)

# ------------------输入图片处理完成--------------------------------

img = cv2.imread('F:\\yolo-data\\opencv 3.3\\opencv\\sources\\samples\\data\\digits.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 将图片进行分割成5000块横向100纵向50,分割为20*20
# 纵线分割np.hsplit(数组,份数),横线分割np.vsplit(数组,份数)
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)
test = x[:,50:100].reshape(-1,400).astype(np.float32)

# 创建测试,训练标签
k = np.arange(10)
train_labels = np.repeat(k,250)[:,np.newaxis]
test_labels = train_labels.copy()
# 初始化KNN,训练数据,然后使用k = 1的测试数据对其进行测试
knn = cv2.ml.KNearest_create()
knn.train(train,cv2.ml.ROW_SAMPLE,train_labels)
ret,result,neighbours,dist = knn.findNearest(input_test,k=5)#test


# 结果
print(type(result))
print(result)

测试输出:

image.png

本月将陆续推出相关系列文章,

篇篇精彩,尽请关注。