深度学习实战:基于TensorFlow与OpenCV的手语识别系统

简介: 深度学习实战:基于TensorFlow与OpenCV的手语识别系统


写在前面

本期内容:基于TensorFlow与OpenCV的手语识别系统

实验环境:
python(3.11.4)
tensorflow(2.13.0)
cv2(4.8.0)

注:本专栏内所有文章都包含完整代码以及数据集

基于TensorFlow与OpenCV的手语识别系统

安装环境

pip install tensorflow
pip install cv2

一、导入工具库

# 导入工具库
import pandas as pd
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import warnings
from tensorflow import keras
warnings.filterwarnings("ignore")

这些是Python中的标准库及第三方库及其相关的模块。

具体来说,这个代码导入了以下库:

  • Pandas:数据分析和数据处理库。
  • NumPy:科学计算库,用于处理多维数组和矩阵。
  • TensorFlow:机器学习和深度学习框架。
  • Matplotlib:绘图库,用于可视化数据。
  • Warnings:警告管理模块,用于忽略警告。
  • Keras:高层神经网络API,可以使用多种深度学习框架作为后端。

二、导入数据集

# 读取数据
test = pd.read_csv("sign_mnist/sign_mnist_test.csv")
train = pd.read_csv("sign_mnist/sign_mnist_train.csv")
# 输出基本信息
print("训练集维度", train.shape)
print("测试集维度", train.shape)
训练集维度 (27455, 785)
测试集维度 (27455, 785)

这段代码使用 Pandas 库中的 read_csv 函数读取了两个 CSV 文件:sign_mnist_train.csv(训练集)和 sign_mnist_test.csv(测试集),分别存储在 train 和 test 变量中。

接下来使用 shape 属性分别输出了训练集和测试集的维度信息,即行数和列数。train.shape 输出结果为训练集的行数和列数,test.shape 输出结果为测试集的行数和列数。可以看到 train 和 test 数据集都有 7,995 行和 785 列,其中前 784 列是图片的像素信息,最后一列是标签信息,标识了每个手语图片所表示的字母。

三、数据预处理

# 切分特征与标签
train_x = train.drop(labels = "label", axis = 1)
train_y = train["label"]
test_x = test.drop(labels = "label", axis = 1)
test_y = test["label"]
# 转为numpy格式
train_x = train_x.to_numpy()
test_x = test_x.to_numpy()
train_y = train_y.to_numpy()
test_y = test_y.to_numpy()
# 把数据转为3维图像数据(图片数量*宽*高*通道)
train_x = train_x.reshape(-1,28,28,1)
test_x = test_x.reshape(-1,28,28,1)
# 输出基本信息
train_x.shape, train_y.shape, test_x.shape, test_y.shape
((27455, 28, 28, 1), (27455,), (7172, 28, 28, 1), (7172,))

这段代码将训练集和测试集的特征和标签分别切分成 train_x、train_y 和 test_x、test_y 四个变量。

train_x 和 test_x 存储了训练集和测试集的特征信息,即手语图片的像素信息,这些信息被存储在 CSV 文件中的前 784 列。这里使用了 pandas 库的 drop 函数删除了每个样本的标签信息,axis = 1 表示删除列。

train_y 和 test_y 存储了训练集和测试集的标签信息,即每个手语图片所代表的字母。

接下来,使用 Pandas 库的 to_numpy 函数将 train_x、test_x、train_y、test_y 四个变量转换为 NumPy 数组。

由于卷积神经网络需要输入 3 维的图片数据,所以将 train_x 和 test_x 从 2 维重塑为 3 维,分别代表图片数量、宽度、高度和通道数(这里的通道数为 1)。

最后,使用 shape 属性输出 train_x、train_y、test_x、test_y 这四个变量的维度信息。可以看到 train_x 和 test_x 变为了 4 维的数组(图片数量、宽度、高度和通道数为 1),而 train_y 和 test_y 仍然是 1 维的数组(标签数)。

四、训练模型

基于CNN

卷积神经网络(CNN)是一种非常强大的深度学习算法,广泛应用于图像处理、计算机视觉和自然语言处理等领域。它是一种基于神经网络的监督学习算法,可以有效地识别和分类图像。

CNN算法的主要思想是通过卷积核从图像中提取重要的特征,然后将这些特征传递给全连接层进行分类。卷积核是一种模板,它可以应用于输入图像中的每个像素,并计算出一个新的特征图。通过不断应用卷积核,可以提取出图像中的多种特征。

CNN的结构主要由卷积层、池化层、全连接层三部分组成。卷积层是CNN中最重要的层,它通过不断应用卷积核来提取图像的特征,得到多个特征图。池化层主要用于减少特征图的维度,通过选择最大值或平均值来进行下采样。全连接层用于对特征进行分类,将特征图展开成向量,然后将其传递给一个或多个全连接层来输出分类结果。最后在输出层使用softmax函数进行分类输出。

程序设计

# CNN
def CNN():
    model = tf.keras.models.Sequential([
    # 卷积层
    tf.keras.layers.Conv2D(32, (3,3), activation='relu', input_shape=(28, 28, 1)),
    # 池化层
    tf.keras.layers.MaxPooling2D(2,2),
    # 卷积层
    tf.keras.layers.Conv2D(32, (3,3), activation='relu'),
    # 池化层
    tf.keras.layers.MaxPooling2D(2,2),
    # 展平
    tf.keras.layers.Flatten(),
    # 全连接层
    tf.keras.layers.Dense(512, activation='relu'),
    # softmax分类
    tf.keras.layers.Dense(26, activation='softmax')])
    model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) #评估准则
    return model
# 初始化
cnn = CNN()
# 配置
cnn.compile(optimizer="adam",metrics=["accuracy"],loss = "sparse_categorical_crossentropy")
# 训练
cnn.fit(train_x, train_y, validation_data = (test_x, test_y), epochs =10)
# 保存模型
cnn.save_weights("CNN_weights.h")
# 评估模型
cnn = CNN()
cnn.load_weights("CNN_weights.h")
cnn.compile(optimizer="adam",metrics=["accuracy"],loss = "sparse_categorical_crossentropy")
score = cnn.evaluate(test_x, test_y, verbose=0)
print("Test loss:", score[0])
print("Test accuracy:", score[1])

这段代码定义了一个卷积神经网络模型。该模型包含了两个卷积层、两个最大池化层、一个全连接层和一个 softmax 分类层。

接下来,使用 compile 函数对模型进行配置。这里使用了 Adam 优化器、稀疏分类交叉熵损失函数和 accuracy 准确率评估指标。然后使用 fit 函数对模型进行训练。在训练过程中,使用了训练集和测试集进行验证,并设置了 epochs 参数为 10,即训练 10 轮。训练完毕后,使用 save_weights 函数保存训练好的模型权重。

接下来,重新加载保存的模型,使用 evaluate 函数对模型进行评估,并输出测试集的损失和准确率。

最后值得注意的是,代码中定义了一个 CNN 函数,用于返回模型对象。这样做的好处是,如果想要调整模型结构或者参数,只需要修改该函数即可,而不需要改动其他代码。

运行结果

Epoch 1/10
858/858 [==============================] - 13s 15ms/step - loss: 0.5334 - accuracy: 0.8840 - val_loss: 0.6763 - val_accuracy: 0.8371
Epoch 2/10
858/858 [==============================] - 13s 15ms/step - loss: 0.0507 - accuracy: 0.9848 - val_loss: 0.6326 - val_accuracy: 0.8595
Epoch 3/10
858/858 [==============================] - 14s 16ms/step - loss: 4.3012e-04 - accuracy: 1.0000 - val_loss: 0.6390 - val_accuracy: 0.8756
Epoch 4/10
858/858 [==============================] - 14s 17ms/step - loss: 1.2322e-04 - accuracy: 1.0000 - val_loss: 0.6612 - val_accuracy: 0.8779
Epoch 5/10
858/858 [==============================] - 14s 17ms/step - loss: 6.9371e-05 - accuracy: 1.0000 - val_loss: 0.6816 - val_accuracy: 0.8826
Epoch 6/10
858/858 [==============================] - 14s 17ms/step - loss: 4.1090e-05 - accuracy: 1.0000 - val_loss: 0.6932 - val_accuracy: 0.8784
Epoch 7/10
858/858 [==============================] - 13s 16ms/step - loss: 2.5985e-05 - accuracy: 1.0000 - val_loss: 0.7071 - val_accuracy: 0.8836
Epoch 8/10
858/858 [==============================] - 14s 16ms/step - loss: 1.6751e-05 - accuracy: 1.0000 - val_loss: 0.7241 - val_accuracy: 0.8837
Epoch 9/10
858/858 [==============================] - 15s 18ms/step - loss: 1.0805e-05 - accuracy: 1.0000 - val_loss: 0.7379 - val_accuracy: 0.8813
Epoch 10/10
858/858 [==============================] - 15s 17ms/step - loss: 7.0634e-06 - accuracy: 1.0000 - val_loss: 0.7716 - val_accuracy: 0.8823
Test loss: 0.7715592384338379
Test accuracy: 0.8823201060295105

基于LeNet5

LeNet5是一种经典的卷积神经网络结构,是Yann LeCun等人于1998年提出的,是图像识别领域中最早的深度学习算法之一。它将卷积层、池化层以及全连接层结合在一起,能够有效地处理图像数据。这个网络被广泛应用于手写数字识别、人脸识别和车牌识别等方面,并开创了卷积神经网络应用的新时代。

LeNet5网络结构的主要特点是由两个卷积层、两个池化层和三个全连接层组成,包含大约6万个权重和6百多个神经元。相比于其他深度学习算法,它非常小巧,并且便于实现和理解。

LeNet5的第一个卷积层是用于提取输入图像的低级特征的,第二个卷积层用于提取高级特征。两个池化层用于减小特征图的大小,以降低网络参数的数量,并增加网络的鲁棒性。全连接层用于将特征向量分类为不同的类别。

LeNet5的训练方式是基于误差反向传播算法。在训练的过程中,网络通过不断的迭代优化权重和偏置,以最小化损失函数。误差反向传播算法的本质是通过比较网络输出与实际标签之间的差异来计算损失,然后将损失反向传播到网络中,以调整权重和偏置的值,从而使网络的输出更接近实际标签。

LeNet5在当时的手写数字识别领域中取得了良好的效果,并开创了卷积神经网络应用的新时代。随着深度学习的发展,LeNet5逐渐被更加先进的卷积神经网络所取代。但是,它作为深度学习早期的里程碑之一,仍然是学习和了解卷积神经网络发展历史的重要基础。

程序设计

# LeNet5
def LeNet5():
    model = tf.keras.models.Sequential([
    # 第一层卷积层,使用6个5x5的卷积核,步长为1
    tf.keras.layers.Conv2D(6, (5,5), activation='relu', input_shape=(28, 28, 1), padding='valid'),
    # 第一层平均池化层,使用2x2的池化窗口,步长为2
    tf.keras.layers.AveragePooling2D(pool_size=(2, 2), strides=(2, 2), padding='valid'),
    # 第二层卷积层,使用16个5x5的卷积核,步长为1
    tf.keras.layers.Conv2D(16, (5,5), activation='relu', padding='valid'),
    # 第二层平均池化层,使用2x2的池化窗口,步长为2
    tf.keras.layers.AveragePooling2D(pool_size=(2, 2), strides=(2, 2), padding='valid'),
    # 展平
    tf.keras.layers.Flatten(),
    # 第一层全连接层,输出120维向量
    tf.keras.layers.Dense(units=120, activation='relu'),
    # 第二层全连接层,输出84维向量
    tf.keras.layers.Dense(units=84, activation='relu'),
    # softmax分类
    tf.keras.layers.Dense(units=26, activation='softmax')])
    model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
    return model

这段代码定义了一个 LeNet-5 模型。与 CNN 模型相似,该模型包含了两个卷积层、两个平均池化层、两个全连接层和一个 softmax 分类层。与 CNN 模型不同的是,该模型使用了不同的卷积核大小和步长,且加入了平均池化层。

接下来,使用 compile 函数对模型进行配置。这里使用了 Adam 优化器、稀疏分类交叉熵损失函数和 accuracy 准确率评估指标。然后使用 LeNet5 函数返回模型对象。

可以发现,该模型是经典的 LeNet-5 模型,是早期卷积神经网络的代表。虽然该模型相对简单,但其依然可以在手写数字识别等问题上取得相对良好的表现。

# 初始化
lenet5 = LeNet5()
# 配置
lenet5.compile(optimizer="adam",metrics=["accuracy"],loss = "sparse_categorical_crossentropy")
# 训练
lenet5.fit(train_x, train_y, validation_data = (test_x, test_y), epochs =10)
# 保存模型
lenet5.save_weights("LeNet5_weights.h")
Epoch 1/10
858/858 [==============================] - 6s 6ms/step - loss: 0.8555 - accuracy: 0.7541 - val_loss: 0.6739 - val_accuracy: 0.8066
Epoch 2/10
858/858 [==============================] - 5s 6ms/step - loss: 0.0495 - accuracy: 0.9863 - val_loss: 0.6888 - val_accuracy: 0.8318
Epoch 3/10
858/858 [==============================] - 5s 6ms/step - loss: 0.0479 - accuracy: 0.9858 - val_loss: 0.8006 - val_accuracy: 0.8101
Epoch 4/10
858/858 [==============================] - 5s 6ms/step - loss: 0.0194 - accuracy: 0.9945 - val_loss: 0.5524 - val_accuracy: 0.8567
Epoch 5/10
858/858 [==============================] - 5s 6ms/step - loss: 1.8097e-04 - accuracy: 1.0000 - val_loss: 0.5774 - val_accuracy: 0.8707
Epoch 6/10
858/858 [==============================] - 6s 7ms/step - loss: 6.7714e-05 - accuracy: 1.0000 - val_loss: 0.6000 - val_accuracy: 0.8713
Epoch 7/10
858/858 [==============================] - 7s 8ms/step - loss: 3.6441e-05 - accuracy: 1.0000 - val_loss: 0.6284 - val_accuracy: 0.8696
Epoch 8/10
858/858 [==============================] - 6s 7ms/step - loss: 2.2162e-05 - accuracy: 1.0000 - val_loss: 0.6540 - val_accuracy: 0.8681
Epoch 9/10
858/858 [==============================] - 7s 8ms/step - loss: 1.3525e-05 - accuracy: 1.0000 - val_loss: 0.6863 - val_accuracy: 0.8684
Epoch 10/10
858/858 [==============================] - 6s 7ms/step - loss: 8.3553e-06 - accuracy: 1.0000 - val_loss: 0.6980 - val_accuracy: 0.8674
# 评估模型
resnet50 = LeNet5()
resnet50.load_weights("LeNet5_weights.h")
resnet50.compile(optimizer="adam",metrics=["accuracy"],loss = "sparse_categorical_crossentropy")
score = resnet50.evaluate(test_x, test_y, verbose=0)
print("Test loss:", score[0])
print("Test accuracy:", score[1])
Test loss: 0.6979857087135315
Test accuracy: 0.8674010038375854

基于ResNet50

ResNet50是一种深度卷积神经网络,由Microsoft Research的Kaiming He等人于2015年提出。ResNet50是ResNet系列中的一个重要成员,需要训练的参数数量很大,但是具有非常高的准确性。

ResNet50网络结构包含50个卷积层,因此得名ResNet50。相对于传统的卷积神经网络,ResNet50通过引入残差模块来解决深度神经网络中梯度消失和梯度爆炸等问题。残差模块可以帮助神经网络在训练过程中更加容易地学习到有效的特征表征,从而提高网络的准确性。

ResNet50的残差模块主要包含了残差连接和批量标准化两个部分。残差连接是指在卷积层和全连接层之间添加一个旁路,使得输入的特征可以直接通过此旁路被输出到下一层,从而提高训练效率。批量标准化是指对网络的特征图进行归一化,减少特征之间的耦合,从而帮助神经网络更快更好地学习到有效的特征表征。

ResNet50的训练方式是基于端到端的误差反向传播算法,也就是通过比较网络输出与实际标签之间的差异来计算损失,然后通过反向传播算法不断优化网络权重和偏置,从而使得网络输出更加接近实际标签。

ResNet50在计算机视觉领域中取得了很好的效果,在ImageNet图像分类竞赛中获得了很高的排名,并且在其他各种图像处理任务中也获得了很好的表现。它的应用场景非常广泛,包括人脸识别、物体检测、图像分割等各种领域。

总之,ResNet50是一种非常有效的深度卷积神经网络结构,在图像识别领域取得了很好的表现。它通过引入残差模块来解决深度神经网络中的问题,并以其高精度、高鲁棒性和高可靠性成为了深度学习领域的经典之作。

程序设计

# 定义ResNet-50模型的标识块
def identity_block(X, f, filters, training=True):
    f1,f2,f3 = filters
    X_shortcut = X 
    X = tf.keras.layers.Conv2D(filters = f1, kernel_size = 1, strides = (1,1), padding = 'valid')(X)
    X = tf.keras.layers.BatchNormalization(axis = 3)(X, training = training) # Default axis
    X = tf.keras.layers.Activation('relu')(X)
    X = tf.keras.layers.Conv2D(filters = f2, kernel_size = f, strides = (1,1), padding = 'same')(X)
    X = tf.keras.layers.BatchNormalization(axis = 3)(X, training = training) # Default axis
    X = tf.keras.layers.Activation('relu')(X)
    X = tf.keras.layers.Conv2D(filters = f3, kernel_size = 1, strides = (1,1), padding = 'valid')(X)
    X = tf.keras.layers.BatchNormalization(axis = 3)(X, training = training) # Default axis
    X = tf.keras.layers.Add()([X_shortcut,X])
    X = tf.keras.layers.Activation('relu')(X)
    return X
# 定义ResNet-50模型的卷积块 
def convolutional_block(X, f, filters, s=2,training=True):
    # filter of the three convs 
    f1,f2,f3 = filters
    X_shortcut = X 
    X = tf.keras.layers.Conv2D(filters = f1, kernel_size = 1, strides = (1,1), padding = 'valid')(X)
    X = tf.keras.layers.BatchNormalization(axis = 3)(X, training = training) # Default axis
    X = tf.keras.layers.Activation('relu')(X)
    X = tf.keras.layers.Conv2D(filters = f2, kernel_size = f, strides = (s,s), padding = 'same')(X)
    X = tf.keras.layers.BatchNormalization(axis = 3)(X, training = training) # Default axis
    X = tf.keras.layers.Activation('relu')(X)
    X = tf.keras.layers.Conv2D(filters = f3, kernel_size = 1, strides = (1,1), padding = 'valid')(X)
    X = tf.keras.layers.BatchNormalization(axis = 3)(X, training = training) # Default axis
    X_shortcut =tf.keras.layers.Conv2D(filters = f3, kernel_size = 1, strides = (s,s), padding = 'valid')(X_shortcut)
    X_shortcut = tf.keras.layers.BatchNormalization(axis = 3)(X_shortcut, training = training)
    X = tf.keras.layers.Add()([X_shortcut,X])
    X = tf.keras.layers.Activation('relu')(X)
    X = tf.keras.layers.Add()([X, X_shortcut])
    X = tf.keras.layers.Activation('relu')(X)
    return X
# 使用标识块和卷积块定义修改的ResNet-50模型
def ResNet50(input_shape = (28, 28, 1), classes = 26):
    X_input = tf.keras.Input(input_shape)
    X = tf.keras.layers.ZeroPadding2D((3, 3))(X_input)
    X = tf.keras.layers.Conv2D(64, (5, 5), strides = (1, 1))(X)
    X = tf.keras.layers.BatchNormalization(axis = 3)(X)
    X = tf.keras.layers.Activation('relu')(X)
    X = tf.keras.layers.MaxPooling2D((3, 3), strides=(2, 2))(X)
    X = convolutional_block(X, f = 3, filters = [64, 64, 256], s = 1)
    X = identity_block(X, 3, [64, 64, 256])
    X = identity_block(X, 3, [64, 64, 256])
    X = tf.keras.layers.AveragePooling2D((2,2))(X)
    X = tf.keras.layers.Flatten()(X)
    X = tf.keras.layers.Dense(classes, activation='softmax')(X)
    model = tf.keras.Model(inputs = X_input, outputs = X)
    return model

这段代码定义了 ResNet-50 模型的标识块、卷积块和整个模型。ResNet-50 模型是在传统的卷积神经网络模型基础上增加了残差链接,可以更好地解决梯度消失等问题,进而训练更深的网络。

在这里,定义了 identity_block 函数和 convolutional_block 函数分别对应 ResNet-50 模型中的标识块和卷积块。标识块中,使用了三次卷积操作,中间加入了批量归一化层和激活函数层,并在最后添加了残差链接,输出结果为输入加上残差,并过激活函数。卷积块与标识块相似,但在第一层卷积操作中使用了步长,以降低输出的空间尺寸。

最终,使用定义好的标识块和卷积块以及其他常见的卷积神经网络模型层(如卷积层、全连接层等),组成了修改版的 ResNet-50 模型。在该模型中,使用了一个卷积层、一个最大池化层、一个卷积块、两个标识块和一个全局平均池化层,并使用 Dense 函数作为分类层,输出最终结果。

# 初始化模型
resnet50 = ResNet50()
# 配置
resnet50.compile(optimizer="adam",metrics=["accuracy"],loss = "sparse_categorical_crossentropy")
# 训练
resnet50.fit(train_x, train_y, validation_data = (test_x, test_y), epochs = 20)
Epoch 1/20
858/858 [==============================] - 172s 197ms/step - loss: 0.8110 - accuracy: 0.9030 - val_loss: 0.6665 - val_accuracy: 0.8830
Epoch 2/20
858/858 [==============================] - 167s 194ms/step - loss: 0.1136 - accuracy: 0.9795 - val_loss: 0.7510 - val_accuracy: 0.8900
Epoch 3/20
858/858 [==============================] - 163s 190ms/step - loss: 0.0304 - accuracy: 0.9949 - val_loss: 0.3036 - val_accuracy: 0.9582
Epoch 4/20
858/858 [==============================] - 173s 201ms/step - loss: 0.1140 - accuracy: 0.9867 - val_loss: 0.5101 - val_accuracy: 0.9561
Epoch 5/20
858/858 [==============================] - 172s 201ms/step - loss: 7.6016e-04 - accuracy: 0.9998 - val_loss: 0.3638 - val_accuracy: 0.9554
Epoch 6/20
858/858 [==============================] - 175s 205ms/step - loss: 1.2263e-05 - accuracy: 1.0000 - val_loss: 0.3518 - val_accuracy: 0.9597
Epoch 7/20
858/858 [==============================] - 178s 207ms/step - loss: 3.8450e-05 - accuracy: 1.0000 - val_loss: 0.4060 - val_accuracy: 0.9561
Epoch 8/20
858/858 [==============================] - 185s 216ms/step - loss: 3.8043e-06 - accuracy: 1.0000 - val_loss: 0.3811 - val_accuracy: 0.9583
Epoch 9/20
858/858 [==============================] - 184s 214ms/step - loss: 7.3366e-07 - accuracy: 1.0000 - val_loss: 0.3785 - val_accuracy: 0.9594
Epoch 10/20
858/858 [==============================] - 174s 203ms/step - loss: 1.2010e-06 - accuracy: 1.0000 - val_loss: 0.4261 - val_accuracy: 0.9573
Epoch 11/20
858/858 [==============================] - 169s 198ms/step - loss: 1.3640e-06 - accuracy: 1.0000 - val_loss: 0.4166 - val_accuracy: 0.9583
Epoch 12/20
858/858 [==============================] - 177s 206ms/step - loss: 1.7177e-07 - accuracy: 1.0000 - val_loss: 0.4165 - val_accuracy: 0.9578
Epoch 13/20
858/858 [==============================] - 175s 204ms/step - loss: 1.5472e-07 - accuracy: 1.0000 - val_loss: 0.4170 - val_accuracy: 0.9579
Epoch 14/20
858/858 [==============================] - 178s 208ms/step - loss: 2.2307e-07 - accuracy: 1.0000 - val_loss: 0.4177 - val_accuracy: 0.9583
Epoch 15/20
858/858 [==============================] - 178s 207ms/step - loss: 9.6281e-08 - accuracy: 1.0000 - val_loss: 0.4099 - val_accuracy: 0.9584
Epoch 16/20
858/858 [==============================] - 181s 211ms/step - loss: 9.0053e-08 - accuracy: 1.0000 - val_loss: 0.4162 - val_accuracy: 0.9576
Epoch 17/20
858/858 [==============================] - 179s 209ms/step - loss: 5.3058e-08 - accuracy: 1.0000 - val_loss: 0.4095 - val_accuracy: 0.9578
Epoch 18/20
858/858 [==============================] - 183s 214ms/step - loss: 6.8558e-08 - accuracy: 1.0000 - val_loss: 0.4065 - val_accuracy: 0.9579
Epoch 19/20
858/858 [==============================] - 183s 213ms/step - loss: 2.2604e-08 - accuracy: 1.0000 - val_loss: 0.4065 - val_accuracy: 0.9583
Epoch 20/20
858/858 [==============================] - 179s 208ms/step - loss: 2.4879e-08 - accuracy: 1.0000 - val_loss: 0.3946 - val_accuracy: 0.9587
# 保存模型
resnet50.save_weights("ResNet50_weights.h")
# 评估模型
model = ResNet50()
model.load_weights("ResNet50_weights.h")
model.compile(optimizer="adam",metrics=["accuracy"],loss = "sparse_categorical_crossentropy")
score = model.evaluate(test_x, test_y, verbose=0)
print("Test loss:", score[0])
print("Test accuracy:", score[1])
Test loss: 0.4331090748310089
Test accuracy: 0.9584495425224304

五、模型预测

基于OpenCV

OpenCV是一种基于开源代码的计算机视觉和机器学习库,由英特尔公司开发并维护。它是一种跨平台的库,可以在Windows、Linux、Mac OS等操作系统上运行,支持多种编程语言,包括C++、Python、Java等,为计算机视觉和机器学习研究提供了强大的工具。在计算机视觉领域中,OpenCV是一种非常重要的工具,可以帮助开发人员更方便地实现各种计算机视觉算法,包括目标检测、人脸识别、图像分割等。

OpenCV提供了很多的图像处理函数,包括图像读取、显示、保存、转换、操作等。其中最常用的功能是图像读取和显示。使用OpenCV可以快速地读取图像文件,可以是常见的图像格式,如JPEG、PNG、BMP等。一旦读入图像,就可以使用OpenCV的显示函数在屏幕上显示它们。除此之外,OpenCV还提供了一些常用的图像处理函数,如图像增强、滤波器、边缘检测等等。

在机器学习领域中,OpenCV可以用来进行特征提取、特征匹配、分类和检测等任务。其中最常见的任务是特征提取和特征匹配。在特征提取方面,OpenCV提供了一些常用的特征提取方法,如SIFT、SURF、ORB等。这些方法可以帮助我们从图像中提取出一些具有独特性质的特征,用于后续的特征匹配、分类等任务。在特征匹配方面,OpenCV提供了一些基于特征的匹配方法,如FLANN、BFMatcher等。这些方法可以帮助我们进行图像配准、目标跟踪等任务。

OpenCV在计算机视觉和机器学习领域有着广泛的应用。其中比较重要的应用场景包括人脸识别、物体检测、图像分割等。在人脸识别方面,OpenCV提供了一些人脸检测和识别算法,能够从图像或视频中快速准确地识别出人脸并进行特征提取。在物体检测方面,OpenCV可以用于训练、优化和运行各种物体检测算法。在图像分割方面,OpenCV提供了多种图像分割算法,能够将一张图像分成多个不同的区域,用于识别和分析。

总之,OpenCV是一种非常重要的计算机视觉和机器学习库,在计算机视觉和机器学习领域中有着广泛的应用。它丰富的功能库和跨平台的特性,使得开发人员能够快速地构建各种计算机视觉和机器学习应用程序,并为开源和商业应用提供了很好的支持。

程序设计

# 导入OpenCV
import cv2
import string
# 设定维度
dim = (28, 28) # 图像维度
letters = list(string.ascii_lowercase) # 识别的字母
x0,x1,y0,y1 = 0, 300, 0, 200
# 初始化视频捕获
video = cv2.VideoCapture(0)
cv2.namedWindow('Webcam', cv2.WINDOW_NORMAL) # 构建1个窗口
cv2.resizeWindow('Webcam', 500, 400) 
cv2.moveWindow('Webcam',500,200) # 放置窗口
while video.isOpened(): # 只要没有关掉实时摄像头
    ret,capture = video.read() # 抓取每个视频帧
    cropped = capture[y0:y1, x0:x1] # 截取
    plt.figure(figsize=(4, 3)) 
    plt.imshow(cropped) # 可视化展示图片
    plt.axis("off")
    plt.show() # 展示
    img = cv2.cvtColor(cropped, cv2.COLOR_BGR2GRAY) # 转成灰度图
    img = cv2.GaussianBlur(img, (5, 5), 0) # 图像平滑
    img = cv2.resize(img, dim) # 图像大小缩放
    img = np.reshape(img, (1,img.shape[0],img.shape[1], 1))
    img = tf.cast(img, tf.float32)
    pred=resnet50.predict(img)
    # 可视化实时效果
    cv2.rectangle(capture, (x0,y0),(x1,y1), (255,0,0) ,2) # 为图片添加矩形框
    cv2.putText(capture,'This is {}'.format(letters[np.argmax(pred[0])]), (x0+25,y0+50), cv2.FONT_HERSHEY_SIMPLEX, 1,(0, 0, 255),1) # 预测字母
    cv2.imshow('Webcam', capture) # 展示视频
    # 输出预测结果
    print("This is " + letters[np.argmax(pred[0])])
    # 退出视频输入
    key = cv2.waitKey(1)
    if key == ord('w'):
        break
video.release()
cv2.destroyAllWindows()

程序分析

这段代码主要功能是利用OpenCV库实现对实时摄像头捕获到的图像进行识别,判断出图像中手势所表示的字母,并进行可视化展示。

具体实现时,代码首先导入了OpenCV库,并设定了图像的维度和识别的字母集合。然后初始化视频捕获,并构建一个窗口展示实时捕获的视频。

这段代码主要的循环语句是:

while video.isOpened():
    ret,capture = video.read()
    # ... 
    cv2.imshow('Webcam', capture)
    # ...

主要是通过一个while循环不断读取视频帧,然后对读取到的图像进行预测和展示。

其中,代码通过一些图像处理技术,如图像平滑、大小缩放等,对图像进行预处理,并使用ResNet50模型对处理后的图像进行预测。同时,代码还添加了一个矩形框,并在上面展示预测出的字母,以便观察效果。最后,通过waitKey函数获取按键输入,当按下’w’键时退出程序。

总体上,这段代码实现了实时图像识别的功能,可以应用于很多场景,如拍照APP、安防监控等。但是需要注意的是,代码的准确率和效率并不高,因此可以根据实际需求进行优化。

运行结果

1/1 [==============================] - 0s 22ms/step
This is y

1/1 [==============================] - 0s 22ms/step
This is v

1/1 [==============================] - 0s 22ms/step
This is w

附:英文字母手语表

写在后面

我是一只有趣的兔子,感谢你的喜欢!

目录
相关文章
|
6天前
|
机器学习/深度学习 API 语音技术
|
28天前
|
机器学习/深度学习 传感器 自动驾驶
基于深度学习的图像识别技术在自动驾驶系统中的应用
【2月更文挑战第29天】 随着人工智能技术的飞速发展,深度学习作为其核心分支之一,在图像识别领域取得了显著成就。本文聚焦于探讨深度学习技术在自动驾驶系统中的应用,重点分析了卷积神经网络(CNN)在车辆环境感知中的关键作用。文章首先概述了深度学习的基础理论和关键技术,随后详细阐述了CNN如何通过多层次特征提取实现精确的图像分析,以及这些技术如何帮助自动驾驶系统实时理解复杂道路情况。最后,文章讨论了当前技术面临的挑战与未来的发展方向,为相关领域的研究提供参考。
|
1月前
|
机器学习/深度学习 数据采集 人工智能
m基于深度学习网络的手势识别系统matlab仿真,包含GUI界面
m基于深度学习网络的手势识别系统matlab仿真,包含GUI界面
38 0
|
25天前
|
机器学习/深度学习 数据采集 监控
基于深度学习的图像识别技术在智能监控系统中的应用
随着人工智能技术的飞速发展,深度学习作为其核心分支之一,在图像处理和分析领域取得了显著成就。本文将探讨一种基于深度学习的图像识别技术,并分析其在智能监控系统中的应用。该技术通过构建复杂的神经网络模型,实现了对监控视频中异常行为的准确识别与实时反应。实验结果表明,与传统算法相比,该方法在准确率和处理速度上都有明显提升,有效增强了监控系统的智能化水平。
16 3
|
26天前
|
机器学习/深度学习 传感器 自动驾驶
基于深度学习的图像识别技术在自动驾驶系统中的应用
【2月更文挑战第31天】 随着人工智能技术的飞速发展,深度学习已成为推动自动驾驶系统革新的核心动力之一。特别是在图像识别领域,深度学习模型已经显示出了卓越的性能和广阔的应用前景。本文旨在探讨基于深度学习的图像识别技术如何被集成进自动驾驶系统中,以及这一集成对提高系统准确性、可靠性的影响。我们将详细分析卷积神经网络(CNN)等先进深度学习架构在处理车载摄像头捕获的复杂交通场景中的作用,并讨论数据增强、迁移学习等策略在提升模型泛化能力方面的重要性。此外,我们还将评估这些技术在真实世界条件下的性能及其面临的挑战。
|
8天前
|
机器学习/深度学习 自动驾驶 算法
基于深度学习的图像识别技术在自动驾驶系统中的应用
【4月更文挑战第9天】 随着人工智能技术的不断进步,深度学习已成为推动多个领域革新的核心动力。特别是在图像识别领域,通过模仿人类视觉系统的处理机制,深度学习模型已展现出超越传统算法的性能。本文将探讨深度学习在图像识别中的关键技术,并重点分析这些技术如何被应用于自动驾驶系统中以实现车辆环境的实时理解与决策。我们将从卷积神经网络(CNN)的基础结构出发,讨论其在特征提取、物体检测和分类中的作用,以及如何通过增强学习和迁移学习等策略来优化模型性能。此外,我们还将评估当前技术面临的挑战,如数据集偏差、实时处理需求以及模型泛化能力,并提出可能的解决方案。
10 1
|
10天前
|
机器学习/深度学习 并行计算 监控
基于深度学习的电动自行车头盔佩戴检测系统
基于深度学习的电动自行车头盔佩戴检测系统
23 0
|
10天前
|
机器学习/深度学习 自动驾驶 安全
基于深度学习的图像识别技术在自动驾驶系统中的应用
【4月更文挑战第7天】 随着人工智能技术的飞速发展,尤其是深度学习在图像处理领域的突破性进展,自动驾驶系统得到了前所未有的推动。本文旨在探讨如何将基于深度学习的图像识别技术有效集成到自动驾驶系统中,以提高其准确性和可靠性。文章首先介绍了深度学习的基本概念及其在图像识别中的关键作用,随后详细分析了自动驾驶系统对图像识别技术的具体需求,接着提出了一种改进的卷积神经网络模型,并通过实验验证了该模型在复杂环境下的性能表现。最后,本文还讨论了在实际部署过程中可能遇到的挑战及潜在的解决方案。
13 0
|
12天前
|
机器学习/深度学习 运维 监控
深度视野:深度学习技术在智能监控系统中的革新应用
【4月更文挑战第5天】 随着人工智能技术的飞速发展,深度学习已成为图像处理和分析领域的核心技术之一。本文将深入探讨基于深度学习的图像识别技术在智能监控领域的应用及其带来的变革。我们将从神经网络的基本构成出发,解析其如何实现对监控图像中复杂场景的高效识别与分析,并进一步讨论这些技术在提高监控准确性、实时性和自动化水平方面的作用。此外,文中还将涉及深度学习技术面临的挑战及未来发展趋势。
|
13天前
|
机器学习/深度学习 传感器 数据采集
基于深度学习的图像识别技术在自动驾驶系统中的应用
【4月更文挑战第4天】随着人工智能技术的飞速发展,深度学习已经成为计算机视觉领域的核心推动力。尤其是在图像识别任务中,深度神经网络表现出了超越传统算法的性能。本文将探讨深度学习模型在自动驾驶汽车图像识别系统中的应用,重点分析卷积神经网络(CNN)的结构、训练过程以及优化策略,并讨论其在处理实时交通场景中的效率和准确性。此外,文章还将涉及数据增强、迁移学习等先进技术如何进一步提升模型的泛化能力和鲁棒性。

热门文章

最新文章