top of page
アンカー 1

已更新:2021年10月20日

一、前文回顾

在图像处理章节使用mediapipe进行了手势1-9的识别,但是既然学习了深度学习,所以我尝试使用深度学习来实现手势识别。


二、关键词语

Mediapipe:谷歌的一个训练好的神经网络模型。这个模块可以识别手,脸,姿态等等很多东西。我这次只使用手部识别的功能,以便确定手的位置

Tensorflow:谷歌的开源深度学习框架。这个框架封装了底层算法(比如池化操作,卷积操作,反向求导等等),我们只需要象搭积木一样就可以很快的搭建自己的网络模型。

※tensorflow版本为2.6.0

VGG16:经典深度学习网络模型,该结构有13个卷积层,3个全链接层。一共13+3=16层。

迁移学习:就是使用别人训练好的权重模型进行重新训练,这样一部分训练好的权重就不会重新参加训练,会大大缩小训练时间。

Imagenet:数据集名称,有超过1400万的图像。我们要使用该数据集的权重


三、实现思路

1.用Mediapipe来找到一幅图像中手的位置。

2.采集手势图像,每个手势1000张,0-5的手势总共6000张图像

3.使用VGG16神经网络以及imagenet权重进行迁移学习。

4.通过以上步骤会得到我们自己的权重,然后就可以进行识别了。


四、核心代码

# 调用VGG16模型,如果参数 weights ='imagenet',则读取 ImageNet 学习到的权重数据。
# include_top=False 不包含输出层的全结合层
vgg16 = tf.keras.applications.vgg16.VGG16(weights="imagenet", include_top=False,                                      input_tensor=tf.keras.Input(shape=(224, 224, 3)))    

创建一个VGG16网络模型,使用imagenet权重作为初始权重,不包含VGG16的输出端的全连接层(因为我们是6个分类,所以需要自定义全连接层)


# 冻结VGG16的固有参数(不参加训练)
vgg16.trainable = False

冻结VGG16的原有参数,这样他们就不会参加训练,从而减小训练时间


# 展开 VGG 的最大池化输出
flatten = vgg16.output
flatten = tf.keras.layers.Flatten()(flatten)
# 添加全连接层
dense = tf.keras.layers.Dense(128, activation="relu")(flatten)
dense = tf.keras.layers.Dense(64, activation="relu")(dense)
dense = tf.keras.layers.Dense(32, activation="relu")(dense)
dense = tf.keras.layers.Dense(class_num, activation="sigmoid")(dense)

自定义四层全链接输出层,输出分类为6个,分别对应手势0-6


五、效果视频



六、总结

1.采集的图像背景太过单一,导致测试图像背景和训练数据背景差别比较大时准确率变低。如果要改善这个问题,需要不同场景下的数据集,数据集变大意味着训练时间也会更长。

2.CPU来训练花费了8个小时。下一次训练打算用谷歌的colab来进行训练(GPU免费用)

3.VGG16网络稍微有点复杂,所以处理速度不是很理想。下一节改用轻量级MobieNet来试试。


源码下载:

·深度学习17弹

※包含权重文件,不包含数据集



bottom of page