学习记录之手势识别

手势识别

今天实践的内容是手势识别,手势识别属于图像分类中的细分问题,即用手势表达0~9的数字,理想化的状态就是表达是几识别的结果就是几
如图就是手势表达中的数字五,接下来的任务就是通过找一个合适的函数来进行正确的手势识别,使得识别的结果为数字5。
在这里插入图片描述

主要步骤:

  1. 准备数据
  2. 配置网络
  3. 训练网络
  4. 模型评估
  5. 模型评价

***。

1. 准备数据

准备网上公开的手势图像数据集:包含0~9数字识别,共2073张手势图片,图片大小为3100100,RGB格式文件。本次实验取10%作为测试集,90%作为训练集。遍历所有的图片,根据文件夹的名称,生成label(目的是为了方便做有监督学习)。生成test_list和train_list。
这样数据就准备好了,接下来先进行这部分的代码吧~~~

import os
import time
import random
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
import paddle
import paddle.fluid as fluid
import paddle.fluid.layers as layers
from multiprocessing import cpu_count
from paddle.fluid.dygraph import Pool2D,Conv2D
from paddle.fluid.dygraph import Linear
# 通过下载的数据集Dataset,生成训练列表和测试列表
data_path = 'C:/Users/Admin/demo/shoushi/data23668/Dataset'
character_folders = os.listdir(data_path)#导入数据

if(os.path.exists('./train_data.list')):
    os.remove('./train_data.list')#生成训练数据列表
if(os.path.exists('./test_data.list')):
    os.remove('./test_data.list')#生成测试数据列表
    
for character_folder in character_folders:
    
    with open('./train_data.list', 'a') as f_train:
        with open('./test_data.list', 'a') as f_test:
            if character_folder == '.DS_Store':
                continue
            character_imgs = os.listdir(os.path.join(data_path,character_folder))
            count = 0 
            for img in character_imgs:
                if img =='.DS_Store':
                    continue
                if count%10 == 0:
                    f_test.write(os.path.join(data_path,character_folder,img) + '\t' + character_folder + '\n')
                else:
                    f_train.write(os.path.join(data_path,character_folder,img) + '\t' + character_folder + '\n')
                count +=1
print('列表已生成')

接下来是定义训练集和测试集的reader

# data_mapper()是读取图片,对图片进行归一化处理,返回图片和标签
def data_mapper(sample):
    img, label = sample
    img = Image.open(img)
    img = img.resize((100, 100), Image.ANTIALIAS)#重新设置图片大小
    img = np.array(img).astype('float32')
    img = img.transpose((2, 0, 1))#对图像做转置,读取的图片是rgb,rgb,做转置后是rr,gg,bb
    img = img/255.0#对图像进行归一化处理
    return img, label

def data_reader(data_list_path):
    def reader():
        with open(data_list_path, 'r') as f:
            lines = f.readlines()
            for line in lines:
                img, label = line.split('\t')
                yield img, int(label)
    return paddle.reader.xmap_readers(data_mapper, reader, cpu_count(), 512)

训练的数据提供器

# train_reader()用于训练的数据提供器,达到乱序、按批次提供数据
train_reader = paddle.batch(reader=paddle.reader.shuffle(reader=data_reader('./train_data.list'), buf_size=256), batch_size=32)
# test_reader()用于测试的数据提供器
test_reader = paddle.batch(reader=data_reader('./test_data.list'), batch_size=32) 

2. 配置网络

这里配置的网络是DNN网络(线性网络),取名为MyDNN,如果为了提高准确率可以选择RNN或者CNN。
如下网络设置了3个隐藏层hidden1,hidden2,hidden3,由于数字手势识别的类别是10,所以输出层的hidden设置为10,最后根据输出最大概率值的为输出结果。比如,输出结果中0~8的概率都是0.3而9的概率值为0.7,则认为输出的结果就为9.
这里用到的DNN网络结构,如图所示。
在这里插入图片描述

#定义DNN网络并设置网络名称为MyDNN
class MyDNN(fluid.dygraph.Layer):
    def __init__(self):
        super(MyDNN,self).__init__()
        self.hidden1 = Linear(100,100,act='relu')#第一个隐藏层,激活函数为relu
        self.hidden2 = Linear(100,100,act='relu')#第二个隐藏层,激活函数为relu
        self.hidden3 = Linear(100,100,act='relu')#第三个隐藏层,激活函数为relu
        self.hidden4 = Linear(3*100*100,10,act='softmax')#输出层类别为10,激活函数为softmax,使得结果清晰明了
    def forward(self,input):
       x=self.hidden1(input)
       x=self.hidden2(x)
       x=self.hidden3(x)
       x=fluid.layers.reshape(x, shape=[-1,3*100*100])#做转置,拉伸,让维度保持一致,便于计算
       y=self.hidden4(x)
       return y

3.训练网络

with fluid.dygraph.guard():
    model=MyDNN() #模型实例化
    model.train() #训练模式
    opt=fluid.optimizer.SGDOptimizer(learning_rate=0.01, parameter_list=model.parameters())#优化器选用SGD随机梯度下降,学习率为0.001.这里可以选择其他优化器

    epochs_num=150 #根据数据选择合适的迭代次数,迭代次数并不是越多越好(出现过拟合现象)
    
    for pass_num in range(epochs_num):
        
        for batch_id,data in enumerate(train_reader()):
            
            images=np.array([x[0].reshape(3,100,100) for x in data],np.float32)
            
            labels = np.array([x[1] for x in data]).astype('int64')
            labels = labels[:, np.newaxis]
            # print(images.shape)
            image=fluid.dygraph.to_variable(images)#现在是numpy的形式,将numpy转换为DyGraph接收的输入,该函数实现从numpy.ndarray对象创建一个variable类型的对象
            label=fluid.dygraph.to_variable(labels)
            predict=model(image)#预测
            # print(predict)
            loss=fluid.layers.cross_entropy(predict,label)
            avg_loss=fluid.layers.mean(loss)#获取avg_loss值
            
            acc=fluid.layers.accuracy(predict,label)#计算精度
            
            if batch_id!=0 and batch_id%50==0:
                print("train_pass:{},batch_id:{},train_loss:{},train_acc:{}".format(pass_num,batch_id,avg_loss.numpy(),acc.numpy()))
            
            avg_loss.backward()#使用backward()方法执行反向网络
            opt.minimize(avg_loss)#调用定义的优化器对象的minimize方法进行参数更新
            model.clear_gradients()
            
    fluid.save_dygraph(model.state_dict(),'MyDNN')#保存模型

结果图
在这里插入图片描述
其中train_pass是当前迭代次数,batch_id就是batch数,train_loss就是损失函数的值,其值越接近于0说明模型越好,train_acc是训练集的准确率。在训练集上准确率高,并不代表测试集上有同样的效果。

4.模型评估

with fluid.dygraph.guard():
    accs = []
    model_dict, _ = fluid.load_dygraph('MyDNN')
    model = MyDNN()
    model.load_dict(model_dict) #加载模型参数
    model.eval() #评估模式
    for batch_id,data in enumerate(test_reader()):#测试集
        images=np.array([x[0].reshape(3,100,100) for x in data],np.float32)
        labels = np.array([x[1] for x in data]).astype('int64')
        labels = labels[:, np.newaxis]

        image=fluid.dygraph.to_variable(images)
        label=fluid.dygraph.to_variable(labels)
        
        predict=model(image)       
        acc=fluid.layers.accuracy(predict,label)
        accs.append(acc.numpy()[0])
        avg_acc = np.mean(accs)
    print(avg_acc)

5.模型评价

#读取预测图像,进行预测
def load_image(path):
    img = Image.open(path)
    img = img.resize((100, 100), Image.ANTIALIAS)
    img = np.array(img).astype('float32')
    img = img.transpose((2, 0, 1))
    img = img/255.0
    print(img.shape)
    return img#以上是对测试图像进行预处理

#构建预测动态图过程
with fluid.dygraph.guard():
    infer_path = 'C:/Users/Admin/demo/shoushi/手势.JPG'#输入预测图像
    model=MyDNN()#模型实例化
    model_dict,_=fluid.load_dygraph('MyDNN')
    model.load_dict(model_dict)#加载模型参数
    model.eval()#评估模式
    infer_img = load_image(infer_path)
    infer_img=np.array(infer_img).astype('float32')
    infer_img=infer_img[np.newaxis,:, : ,:]
    infer_img = fluid.dygraph.to_variable(infer_img)
    result=model(infer_img)
    display(Image.open('C:/Users/Admin/demo/shoushi/手势.JPG'))
    print(np.argmax(result.numpy()))

***结果图可以看到,图像手势表示的是数字五,上面显示的结果也是5.***可以看到,图像手势表示的是数字五,上面显示的结果也是5.

以上就是手势识别的全过程啦再次感谢飞浆,我正在慢慢的靠近你,也请你等一等,希望在跟完你所有课程之后,我也可以从菜鸟变成厉害的道友~~~

附上链接:https://www.paddlepaddle.org.cn/飞浆官网

发布了12 篇原创文章 · 获赞 3 · 访问量 230

猜你喜欢

转载自blog.csdn.net/weixin_43468161/article/details/105594165