ST-GCN 自建kinetics数据集

在这里插入图片描述

目前我遇到过的,基于骨骼点的动作识别三种办法:

  1. 根据关节角度
  2. 跟踪算法
  3. 输入动作识别网络

该部分内容介绍的是自建动作识别网络数据集,达到自己想要的效果:

  1. 准备项目
  2. 准备视频
  3. 做视频水平翻转,增加训练集的数量(非必须)
  4. 提取骨骼点和置信度(一个视频一个生成json格式文件)
  5. 根据骨骼点和置信度文件生成label文件

参照的该博主的https://blog.csdn.net/qq_34551518/article/details/125510050,遇到有些错误,在这里连着流程一起总结一下

1 项目部署

拉取最新版的openpose的cpu版本:https://github.com/CMU-Perceptual-Computing-Lab/openpose/releases

gpu版本我遇到的问题是最少需要四块gpu才能运行,没找到修改这部分的源码

解压,运行models文件夹中的两个bat文件

2 准备视频

在这里插入图片描述

格式如下:每一类动作的视频放到一个文件夹下

3 水平翻转

原本这里用的是skvideo,我换成了cv2(主要我当时看到这里的时候skvideo有4.1节介绍的问题还没有解决)

import os
import cv2

if __name__ == '__main__':
    type_number = 4  # 修改,有几类动作
    typename_list = ["left", "right", "up", "down"]  # 修改,动作类别名/动作视频文件夹名

    for type_index in range(type_number):

        type_filename = typename_list[type_index]

        # 视频所在文件夹
        originvideo_file = './{}'.format(type_filename)
        # 得到文件夹内所有文件名
        videos_file_names = os.listdir(originvideo_file)

        # 左右镜像翻转视频
        for file_name in videos_file_names:
            video_path = '{}/{}'.format(originvideo_file, file_name)

            name_without_suffix = file_name.split('.')[0]
            outvideo_path = '{}/{}_mirror.mp4'.format(originvideo_file, name_without_suffix)  # 输出视频文件路径
            cap = cv2.VideoCapture(video_path)
            width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
            height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
            # 定义编解码器并创建VideoWriter对象
            fourcc = cv2.VideoWriter_fourcc(*'mp4v')
            out = cv2.VideoWriter(outvideo_path, fourcc, 30.0, (width, height))
            while cap.isOpened():
                ret, frame = cap.read()
                if not ret:
                    print("Cant receive frame...............")
                    break
                frame = cv2.flip(frame, 1)
                out.write(frame)
                cv2.imshow("frame", frame)
                if cv2.waitKey(1) == ord("q"):
                    break
            cap.release()
            out.release()
            cv2.destroyAllWindows()

4 提取骨骼点和置信度

这是处理一个视频文件夹下的视频,比如动作为向左的文件夹下的视频1,视频2…

import os
import argparse
import json
import shutil
import skvideo
skvideo.setFFmpegPath('D:/ffmpeg/bin')
import skvideo.io
# st_gcn项目下的文件
import st_gcn_tools
import st_gcn_tools.utils as utils


label_name, label_no = 'running', 0


class PreProcess():
    """
        利用openpose提取自建数据集的骨骼点数据
    """

    def start(self):
        # 视频所在文件夹
        originvideo_file = './Data/hs'
        # resized视频输出文件夹
        resizedvideo_file = './Data/resize'
        os.makedirs(resizedvideo_file, exist_ok=True)

        videos_file_names = os.listdir(originvideo_file)  # 得到
        # 1. Resize文件夹下的视频到340x256 30fps
        for file_name in videos_file_names:
            video_path = '{}/{}'.format(originvideo_file, file_name)
            outvideo_path = '{}/{}'.format(resizedvideo_file, file_name)
            writer = skvideo.io.FFmpegWriter(outvideo_path, outputdict={'-s': '340x256'})
            reader = skvideo.io.FFmpegReader(video_path)
            for frame in reader.nextFrame():
                writer.writeFrame(frame)
            writer.close()
            print('{} resize success'.format(file_name))

        # 2. 利用openpose提取每段视频骨骼点数据
        resizedvideos_file_names = os.listdir(resizedvideo_file)
        for file_name in resizedvideos_file_names:
            if not file_name.endswith('mp4'):
                continue
            outvideo_path = '{}/{}'.format(resizedvideo_file, file_name)
            # 拉取的项目的openPoseDemo.exe文件
            openpose = f'E:/Code/BehaviorRecognition/openpose_cpu/bin/OpenPoseDemo.exe'
            video_name = os.path.splitext(file_name)[0]
            # 下面路径下存放的是每个视频的独立一帧的骨骼坐标和置信度
            output_snippets_dir = './Data/resize/snippets/{}'.format(video_name)
            # 下面文件夹一个文件存放的是一个视频的所有帧的骨骼坐标和置信度
            output_sequence_dir = './data/resize/data'
            os.makedirs(output_snippets_dir, exist_ok=True)
            os.makedirs(output_sequence_dir, exist_ok=True)
            output_sequence_path = '{}/{}.json'.format(output_sequence_dir, video_name)

            # pose estimation
            openpose_args = dict(
                video=outvideo_path,
                write_json=output_snippets_dir,
                display=0,
                render_pose=0,
                model_pose='COCO')
            command_line = openpose
            command_line += ' '+ ' '.join(['--{} {}'.format(k, v) for k, v in openpose_args.items()])
            # D:/Pycharm_project/Pose/openpose_all/openpose/bin/OpenPoseDemo.exe --video &outvideo_path \
            # --write_json &output_snippets_dir
            shutil.rmtree(output_snippets_dir, ignore_errors=True)
            os.makedirs(output_snippets_dir)
            os.system(command_line)

            # pack openpose ouputs
            video = utils.video.get_video_frames(outvideo_path)

            height, width, _ = video[0].shape

            # 这里可以修改label, label_index,创建标签的时候会使用的东西!!!
            video_info = utils.openpose.json_pack(
                output_snippets_dir, video_name, width, height, label_name, label_no)

            if not os.path.exists(output_sequence_dir):
                os.makedirs(output_sequence_dir)

            with open(output_sequence_path, 'w') as outfile:
                json.dump(video_info, outfile)
            if len(video_info['data']) == 0:
                print('{} Can not find pose estimation results.'.format(file_name))
                return
            else:
                print('{} pose estimation complete.'.format(file_name))

if __name__ == '__main__':
    p = PreProcess()
    p.start()

从上往下总结几个需要注意的地方:

4.1 skvideo库的经典错误

报错

    assert _HAS_FFMPEG, "Cannot find installation of real FFmpeg (which comes with ffprobe)."
AssertionError: Cannot find installation of real FFmpeg (which comes with ffprobe).

解决办法

网络上下载ffmpeg,并导入import skvideo.io之前输入以下代码

import skvideo
skvideo.setFFmpegPath('D:/ffmpeg/bin')  # 参数是解压的ffmpeg/bin的路径

4.2 额外文件的准备

import st_gcn_tools
import st_gcn_tools.utils as utils

从上面导入来看,我们需要st-gcn项目中的一些文件来完成目前的工作,大概如下:

在这里插入图片描述

5 生成label文件

##	json2kinetics.py
import json
import os

if __name__ == '__main__':
    train_json_path = './Data/resize/data'    # './mydata/kinetics-skeleton/kinetics_train'
    # val_json_path = 'D:/VIDEOS/mydata/kinetics-skeleton/kinetics_val'  # './mydata/kinetics-skeleton/kinetics_val'

    output_train_json_path = './Data/output/1.json'
    # output_val_json_path = 'D:/VIDEOS/mydata/kinetics-skeleton/kinetics_val_label.json'

    train_json_names = os.listdir(train_json_path)
    # val_json_names = os.listdir(val_json_path)

    train_label_json = dict()
    # val_label_json = dict()

    for file_name in train_json_names:
        name = os.path.splitext(file_name)[0]
        json_file_path = '{}/{}'.format(train_json_path, file_name)
        # D:/VIDEOS/mydata/kinetics-skeleton/kinetics_train/{file_name}
        json_file = json.load(open(json_file_path))

        file_label = dict()
        if len(json_file['data']) == 0:
            file_label['has_skeleton'] = False
        else:
            file_label['has_skeleton'] = True
        file_label['label'] = json_file['label']
        file_label['label_index'] = json_file['label_index']

        train_label_json['{}'.format(name)] = file_label

        print('{} success'.format(file_name))

    with open(output_train_json_path, 'w') as outfile:
        json.dump(train_label_json, outfile)

    # for file_name in val_json_names:
    #     name = file_name.split('.')[0]
    #     json_file_path = '{}/{}'.format(val_json_path, file_name)
    #     json_file = json.load(open(json_file_path))
    #
    #     file_label = dict()
    #     if len(json_file['data']) == 0:
    #         file_label['has_skeleton'] = False
    #     else:
    #         file_label['has_skeleton'] = True
    #     file_label['label'] = json_file['label']
    #     file_label['label_index'] = json_file['label_index']
    #
    #     val_label_json['{}'.format(name)] = file_label
    #
    #     print('{} success'.format(file_name))

    # with open(output_val_json_path, 'w') as outfile:
    #     json.dump(val_label_json, outfile)

注释掉的部分是测试集的部分,如果需要把注释去掉

6 另一种尝试

上面提取骨骼点用的是OpenPoseDemo.exe文件,理论上直接使用源码也是可以的。经过尝试确定了需要解决的问题,记录一下

  1. 源码输出的置信度只有两种,检测到的节点为2,检测不到的节点为0,这样归一化后任何检测到的点的值应该也是一样的,但是kinetics数据集中是不同的,不知道是哪里出了问题
  2. 我们输入到st-gcn中的骨骼坐标是经过归一化的
    因为是学习为主,重点还是用源码
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
要使用STGCN训练自己的数据集,你需要按照以下步骤进行操作: 1. 收集数据集:首先,你需要收集与你的任务相关的数据集。确保你的数据集包含时间序列数据,例如传感器读数、行为轨迹或其他类型的时间序列数据。 2. 数据预处理:对于STGCN,你需要将数据转换为图形结构。这通常涉及到构建邻接矩阵(表示节点之间的连接)和将时间序列数据转换为图节点的特征向量。你可以使用一些预处理工具库,如NetworkX或PyGSP来处理这些任务。 3. 构建模型:接下来,你需要使用STGCN模型来训练你的数据集STGCN模型是基于图卷积网络(GCN)的,它能够处理图形结构的数据。你可以使用深度学习框架如PyTorch或TensorFlow来实现STGCN模型。 4. 划分数据集:将你的数据集划分为训练集、验证集和测试集。通常,你可以将大部分数据用于训练,一小部分用于验证和测试。 5. 训练模型:使用训练集来训练STGCN模型。在训练过程中,你可以定义损失函数(如均方误差)和优化器(如Adam)来优化模型的参数。 6. 模型评估:使用验证集来评估模型的性能。你可以计算各种指标,如均方根误差(RMSE)或平均绝对误差(MAE),以衡量模型对于预测时间序列的准确性。 7. 模型调优:根据验证集的评估结果,调整模型的超参数,如学习率、批量大小、层数等。通过反复训练和验证,找到最佳的模型配置。 8. 测试模型:最后,使用测试集来评估最终模型的性能。这可以帮助你确定模型在真实世界中的表现如何。 以上是使用STGCN训练自己的数据集的基本步骤。需要注意的是,这只是一个概述,具体步骤和实现细节可能因你的具体任务而有所不同。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白三点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值