opencv实战---基于神经网络的文本检测

数据集和代码出处:https://gitee.com/zzhzwh/Opencv-project

软件:pycharm      解释器: python3.7 

目录

1、添加相关库

2、主要代码

2.1 训练部分training.py

2.1.1 需要的相关库

2.1.2 需要的变量区域

2.1.3 导入图片和标签

2.1.4 将图片及标签变为numpy数组形式

2.1.5 划分数据集:X里放的图片,y放的是标签

扫描二维码关注公众号,回复: 14602209 查看本文章

2.1.6 查看十个类别的训练集分布是否均匀(画图)

2.1.7 预处理图像

2.1.8 定义模型

2.1.9 训练模型

2.1.10 对模型进行评估

2.1.11 保存模型

2.2 应用(预测)

2.2.1 导入相关库

2.2.2 所有需要用到的变量

2.2.3 预处理

2.2.4 单张图片读入进行识别,结果出现在控制台

完整代码: 

 另外:启用摄像头实时进行文本识别

3、总结与收获


1、添加相关库

方法:pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple

numpy==1.21.6

sklearn

matplotlib==3.5.2

tensorflow==2.0.0

opencv-python==4.2.0.34

keras==2.3.1

2、主要代码

2.1 训练部分training.py

2.1.1 需要的相关库

import numpy as np
import cv2
import os
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from keras.preprocessing.image import ImageDataGenerator
from keras.utils.np_utils import to_categorical
from keras.models import Sequential
from keras.layers.convolutional import Conv2D,MaxPooling2D
from keras.layers import Dropout,Flatten
from keras.layers import Dense
from keras.optimizers import Adam
import pickle

2.1.2 需要的变量区域

#########################################
path = 'myData'
testRation = 0.2
valRation = 0.2
imageDimensions = (32, 32, 3)
batchSizeVal = 50
epochsVal = 10
stepsPerEpochVal = 2000
##########################################

2.1.3 导入图片和标签

images = []               # 存放图片
classNo = []              # 存放标签
myList = os.listdir(path)
print("Total Number of Classes Detected:", len(myList))
noOfClasses = len(myList)
print("Importing Classes.......")

for x in range (0, noOfClasses):               # 遍历mydata下面名称为0-9的文件夹
    myPicList = os.listdir(path+"/"+str(x))    
    for y in myPicList:                        # 遍历每个文件夹的照片
        curImg = cv2.imread(path+"/"+str(x)+"/"+y)
        # 原图是128*128的,太耗费计算机了,就统一成32*32大小的图片    
        curImg = cv2.resize(curImg, (imageDimensions[0], imageDimensions[0]))  
        images.append(curImg)          # images里面存放了所有的图片
        classNo.append(x)              # classNo存放了所有的图片所对应的标签
    print(x, end=" ")                  # end=" "会让输出x的值在控制台横向显示
print(" ")
print("Total Images in Images List = ", len(images))  # 打印总共有多少张图片
print("Total IDs in classNo List = ", len(classNo))   # 打印总共有多少图片的标签

此时的输出结果: 

2.1.4 将图片及标签变为numpy数组形式

images = np.array(images)    # 将图片转化成numpy数组
classNo = np.array(classNo)  # 将标签转化成numpy数组
print(images.shape)          # 此处输出为(10160, 32, 32, 3),每张图片为32*32*3

2.1.5 划分数据集:X里放的图片,y放的是标签

# 划分训练集和测试集,testRation代表将多少划分为测试集。此处值为0.2,即数据集中的20%为测试集
X_train, X_test, y_train, y_test = train_test_split(images, classNo, test_size=testRation) 

# 划分训练集和验证集
X_train, X_validation, y_train, y_validation = train_test_split(X_train, y_train, test_size=valRation)   

print(X_train.shape)       # 获得训练集的数量:6502
print(X_test.shape)        # 获得测试集的数量:2032
print(X_validation.shape)  # 获得验证集的数量:1626
此处输出结果:

 第一行:总图片的shape

第二行:训练集的shape

第三行:测试集的shape

第四行:验证集的shape

2.1.6 查看十个类别的训练集分布是否均匀(画图)

numOfSamples = []
for i in range(0, noOfClasses):
    # print(len(np.where(y_train==i)[0]))   
    numOfSamples.append(len(np.where(y_train==i)[0]))
print("No of Train:",numOfSamples)        # 查看训练集里ID为0-9的图各有多少

# 画图
plt.figure(figsize=(10, 5))
plt.bar(range(0, noOfClasses), numOfSamples)
plt.title("No of Images for each Class")
plt.xlabel("Class ID")
plt.ylabel("Number of Images")
plt.show()

此处输出结果:

2.1.7 预处理图像

普通预处理函数、预处理所有的图像、重塑图像、图像生成器、标签转换为独热向量形式

#### 定义预处理的函数
def preProcessing(img):
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  #灰度化
    img = cv2.equalizeHist(img)   #均衡化
    img = img/255       #归一化
    return img


#### 预处理所有的图像
# map使我们可以在一个列表或元素数组上运行一个函数,处理好之后放进一个列表里
X_train = np.array(list(map(preProcessing, X_train)))
X_test = np.array(list(map(preProcessing, X_test)))
X_validation = np.array(list(map(preProcessing, X_validation)))


#### 为图像增加深度。原来图像的为(32,32),重塑后变为(32,32,1)
X_train = X_train.reshape(X_train.shape[0], X_train.shape[1], X_train.shape[2], 1)
X_test = X_test.reshape(X_test.shape[0], X_test.shape[1], X_test.shape[2], 1)
X_validation = X_validation.reshape(X_validation.shape[0], X_validation.shape[1], X_validation.shape[2], 1)


#### 图像生成器
# 对每批次的训练图片适时进行数据增强(可增强模型的泛化能力),
# ImageDataGenerator()来创建一个图像生成器
dataGen = ImageDataGenerator(width_shift_range=0.1,     # 随机水平位移10%
                             height_shift_range=0.1,    # 随机垂直位移10%
                             zoom_range=0.2,            # 随机缩放20%
                             shear_range=0.1,           # 随机剪裁10%
                             rotation_range=10)         # 随机旋转角度
# 调用fit()我们的图像生成器的功能,这将逐批地应用到图像的变化,
# 默认情况下,这些修改将被随机应用,所以并不是每一个图像都会被改变
dataGen.fit(X_train)


#### 标签转换为独热向量表示
y_train = to_categorical(y_train, noOfClasses)
y_test = to_categorical(y_test, noOfClasses)
y_validation = to_categorical(y_validation, noOfClasses)

2.1.8 定义模型

使用全连接的神经网络,使用序列模型Sequential进行搭建

#定义模型
def myModel():
    #卷积核的数量,多个卷积核叠加起来组成一个滤波器   卷积核是二维的,滤波器是三维的
    noOfFilters = 60    
    sizeOfFilter1 = (5, 5)    #第一个卷积核的大小
    sizeOfFilter2 = (3, 3)    #第二个卷积核的大小
    sizeOfPool = (2, 2)       #池化层的大小
    noOfNode = 500     #节点数

    # 序列模型Sequential,是实现全连接网络的最好方式
    model = Sequential()   #搭建神经网络
    model.add((Conv2D(noOfFilters,sizeOfFilter1,input_shape=(imageDimensions[0],
                                                            imageDimensions[1],
                                                             1),activation='relu'
                                                                )))
    model.add((Conv2D(noOfFilters,sizeOfFilter1,activation='relu')))
    model.add(MaxPooling2D(pool_size=sizeOfPool))          
    model.add((Conv2D(noOfFilters//2, sizeOfFilter2, activation='relu')))
    model.add((Conv2D(noOfFilters//2, sizeOfFilter2, activation='relu')))
    model.add(MaxPooling2D(pool_size=sizeOfPool))
    model.add(Dropout(0.5))
    model.add(Flatten())   
    model.add(Dense(noOfNode,activation='relu'))   
    model.add(Dropout(0.5))
    model.add(Dense(noOfClasses,activation='softmax'))

    # 在使用sequential模型的时候要定义损失函数,优化器。
    # lr:学习率    loss:损失函数
    # 精确度,评估模型在训练和测试时的网络性能的指标
    model.compile(Adam(lr=0.001),loss='categorical_crossentropy',     
                  metrics=['accuracy'])     
    return model

model = myModel()
print(model.summary())   #打印模型

 模型结构大概形式:

输出大小计算公式:

卷积层:

 池化层:

 此处的输出结果:

2.1.9 训练模型

# batch_size 整数,指定进行梯度下降时每个批次包含的样本数训练时一个批次的样本,
# 批量大小,即每批用batchSizeVal个样本(每经过batchSizeVal个样本更新一次权重)
# steps_per_epoch 每轮的步数,即每次迭代执行的批次
history = model.fit_generator(dataGen.flow(X_train,y_train,
                                 batch_size=batchSizeVal),      
                                 steps_per_epoch=stepsPerEpochVal,   
                                 epochs=epochsVal,       # 迭代次数
                                 validation_data=(X_validation,y_validation),
                                 shuffle=1)   # 打乱(洗牌)

模型训练中:

2.1.10 对模型进行评估

score = model.evaluate(X_test,y_test,verbose=0)
print('Test Score = ', score[0])   # 打印测试的分数
print('Test Accuracy = ', score[1])  # 打印测试的准确率

输出结果:

2.1.11 保存模型

pickle_out = open("model_trained.p", "wb")
pickle.dump(model,pickle_out)
pickle_out.close()

训练结束后会出现一个“model_trained.p”的文件 

2.2 应用(预测)

2.2.1 导入相关库

import numpy as np
import cv2
import pickle

2.2.2 所有需要用到的变量

#################################################
# width = 640
# height = 480
threshold = 0.7
pickle_in = open("model_trained.p","rb")   # 导入训练好的模型
model = pickle.load(pickle_in)              
#################################################

2.2.3 预处理

def preProcessing(img):
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  #灰度化
    img = cv2.equalizeHist(img)   #均衡化
    img = img/255       #归一化
    return img

2.2.4 单张图片读入进行识别,结果出现在控制台

img = cv2.imread("7.jpg")
img = np.asarray(img)
img = cv2.resize(img, (32, 32))
img = preProcessing(img)
img = img.reshape(1, 32, 32, 1)   #这一步骤的目的,因为神经网络输入的就要是(32,32,1)

classIndex = int(model.predict_classes(img))
predictions = model.predict(img)
probVal = np.amax(predictions)
print("识别结果为:",classIndex)
print("概率为:", probVal)

 此时输出结果:

完整代码: 

import numpy as np
import cv2
import pickle

#################################################
threshold = 0.7
pickle_in = open("model_trained_10.p","rb")
model = pickle.load(pickle_in)
#################################################

##################################################
def preProcessing(img):
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  #灰度化
    img = cv2.equalizeHist(img)   #均衡化
    img = img/255       #归一化
    return img
###################################################

## 单张图片读入进行识别,结果出现在控制台
img = cv2.imread("7.png")
img = np.asarray(img)
img = cv2.resize(img, (32, 32))
img = preProcessing(img)
img = img.reshape(1, 32, 32, 1)   #这一步骤的目的,因为神经网络输入的就要是(32,32,1)

classIndex = int(model.predict_classes(img))
predictions = model.predict(img)
probVal = np.amax(predictions)
print("识别结果为:",classIndex)
print("概率为:", probVal)

 另外:启用摄像头实时进行文本识别

使用的库和2.2.1一样

需要的变量:

#################################################
width = 640
height = 480
threshold = 0.7
pickle_in = open("model_trained.p","rb")   # 导入训练好的模型
model = pickle.load(pickle_in)              
#################################################

预处理代码和2.2.3一样

 启用摄像头:

# 使用摄像头进行识别
#cap = cv2.VideoCapture(1)   # 启用摄像头,如果是外接摄像头则为“1”,如果是笔记本自带的则为“0”
#cap.set(3,width)   # 设置摄像头的宽度
cap.set(4,height)   # 设置摄像头的高度

预测:

while True:
    success, imgOriginal = cap.read()
    img = np.asarray(imgOriginal)
    img = cv2.resize(img, (32, 32))
    img = preProcessing(img)
    img = img.reshape(1, 32, 32, 1)

    # 识别。和上面识别图片的代码一样
    classIndex = int(model.predict_classes(img))
    predictions = model.predict(img)
    probVal = np.amax(predictions)
    print(classIndex, probVal)

    # 如果大于阈值,那么在视频上面显示出来识别结果和概率
    if probVal>threshold:
        cv2.putText(imgOriginal, str(classIndex)+"    "+str(probVal), (50, 50), cv2.FONT_HERSHEY_COMPLEX,
                    1, (255, 0, 0),1)
    cv2.imshow("Original Image", imgOriginal)

    # 摁下键盘上的“q”键即可关闭摄像头
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

完整代码: 

import numpy as np
import cv2
import pickle

#################################################
width = 640
height = 480
threshold = 0.7
pickle_in = open("model_trained_10.p","rb")
model = pickle.load(pickle_in)
#################################################

##################################################
def preProcessing(img):
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  #灰度化
    img = cv2.equalizeHist(img)   #均衡化
    img = img/255       #归一化
    return img
###################################################

# 使用摄像头进行识别
cap = cv2.VideoCapture(1)
cap.set(3,width)
cap.set(4,height)

while True:
    success, imgOriginal = cap.read()
    img = np.asarray(imgOriginal)
    img = cv2.resize(img, (32, 32))
    img = preProcessing(img)
    # cv2.imshow("processed Image", img)
    img = img.reshape(1, 32, 32, 1)
    #Predict
    classIndex = int(model.predict_classes(img))
    predictions = model.predict(img)
    probVal = np.amax(predictions)
    print(classIndex, probVal)

    if probVal>threshold:
        cv2.putText(imgOriginal, str(classIndex)+"    "+str(probVal), (50, 50), cv2.FONT_HERSHEY_COMPLEX,
                    1, (255, 0, 0),1)
    cv2.imshow("Original Image", imgOriginal)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 图片显示
if probVal>threshold:
    cv2.putText(img, str(classIndex)+"    "+str(probVal), (100, 100), cv2.FONT_HERSHEY_COMPLEX,
                2, (0, 0, 255),2)
cv2.imshow("Original Image", img[0])
cv2.waitKey(0)

3、总结与收获

  • 库的版本并不是越新越好,考虑兼容性,根据项目,下载相对应的版本。
  • 图像生成器能够在一定程度上解决训练集不够的问题。
  • 这个项目主要的收获是明白训练的步骤,神经网络的搭建。测试准确率虽然可以达到99%,但如果要应用实际中,还是需要更强大的神经网络。
  • 在模型训练的过程中, 这个简单的神经网络,十轮,两千次,差不多也需要半个小时左右。所以在学习的过程中,拥有一个好的设备可能会减少一定的烦躁。

猜你喜欢

转载自blog.csdn.net/m0_57224196/article/details/126123240
今日推荐