《Learning to Estimate 3D Hand Pose from Single RGB Images》代码运行阅读笔记

读懂这个文章的代码,并能在自己的照片上测试

文章链接

代码链接

环境搭建

环境是很久以前搭的,已经忘了。不过按照github中的readme一步一步来基本没问题。

数据集

根据文章中所讲目前可用的带关键点位置的RGB数据集有:Steror和Dexter。NYU数据集主要用于深度图不作考虑。不过这两个数据集太小,而且人工标注不够精确,所以用模型生成的数据做一个补充(工具:MixamoBlender背景)。一共有320*320大小的41258张训练图像和2728张测试图像。

值得注意的是文章中说有深度图的数据和分割标签。

网络训练

训练分三个阶段,HandSegNet对应程序中的training_handsegnet.py,PoseNet对应程序中的training_posenet.py,PosePrior、ViewPoint对应程序中的training_lifting.py

  • training_handsegnet.py

1:训练数据读取

创建一个dataset对象,其中存放了读取数据需要的信息,比较重要的有:batch大小、噪音设置、图片大小320*320、样本数量41258、数据集路径rhd、shuffle是否打乱顺序等信息。

用dataset.get()读取需要的数据。

2:搭建网络

搭建网络的各种层的具体操作封装在NetworkOps类里面。

网络输入:图像8*256*256*3和权重(true or false)是否更改

网络输出:8*256*256*2的特征,与标签mask一致

 

数据读取操作和根据图片都是用tensorflow的计算图进行的,分别封装在dataset类和ColorHandPose3DNetwork类里面

# build network
evaluation = tf.placeholder_with_default(True, shape=())
net = ColorHandPose3DNetwork()
hand_mask_pred = net.inference_detection(data['image'], train=True)

3:开启session

# Start TF
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.8)
sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))
tf.train.start_queue_runners(sess=sess)

4:逐点计算loss,计算梯度,设置学习率

# Loss
loss = 0.0
s = data['hand_mask'].get_shape().as_list()
for i, pred_item in enumerate(hand_mask_pred):
    gt = tf.reshape(data['hand_mask'], [s[0]*s[1]*s[2], -1])
    pred = tf.reshape(hand_mask_pred, [s[0]*s[1]*s[2], -1])
    loss += tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=gt))

# Solver
global_step = tf.Variable(0, trainable=False, name="global_step")
lr_scheduler = LearningRateScheduler(values=train_para['lr'], steps=train_para['lr_iter'])
lr = lr_scheduler.get_lr(global_step)
opt = tf.train.AdamOptimizer(lr)
train_op = opt.minimize(loss)

5:初始化权重,加载参数

# init weights
sess.run(tf.global_variables_initializer())
saver = tf.train.Saver(max_to_keep=1, keep_checkpoint_every_n_hours=4.0)

rename_dict = {'CPM/PersonNet': 'HandSegNet',
               '_CPM': ''}
load_weights_from_snapshot(sess, './weights/cpm-model-mpii', ['PoseNet', 'Mconv', 'conv6'], rename_dict)
  • training_posenet.py和training_lifting.py也是类似的操作顺序

网络测试

修改run.py,把输入数据换成自己的摄像头获取的数据,把显示改成连续显示。连接自己的摄像头实验效果如下:

1:相机使用

把相机插上,然后运行如下代码,应该就可以获取了。

import cv2

cap = cv2.VideoCapture(0)

_,image_raw =  cap.read()

2:图像整形

将获取的图像缩放到240**320大小,并归一化到0~1范围。

image_raw = scipy.misc.imresize(image_raw, (240, 320))
image_v = np.expand_dims((image_raw.astype('float') / 255.0) - 0.5, 0)

3:网络计算

 整个流程: HandSegNet + PoseNet + PosePrior.

    Inputs:
        image: [B, H, W, 3] tf.float32 tensor, Image with mean subtracted
        hand_side: [B, 2] tf.float32 tensor, one hot encoding 需要限制为左手
        evaluation: [] tf.bool tensor, True while evaluation false during training (controls dropout)

    Outputs:
        hand_scoremap: [B, H, W, 2] 像素点是否属于手部的得分
        image_crop: [B, 256, 256, 3] 切出来的手部图像,并进行缩放
        scale_crop: [B, 1] 切分出来的手部相对于原图的大小
        center: [B, 1] 切出来的手部中心位置
        keypoints_scoremap: [B, 256, 256, 21] 每个手部关节点的概率图
        keypoint_coord3d: [B, 21, 3] 3D关节点位置

注意,最后2D和3D之间,不仅仅是相机矩阵转换和预测3D点位置而已,3D的似乎更符合运动学规律。

猜你喜欢

转载自blog.csdn.net/duyue3052/article/details/82252013