我的AI之路(52)--如何制作自己的UCF101数据集

article/2025/5/6 20:57:25

      前面说过如何用自己的UCF101数据集训练3D识别模型video-caffe,那么怎么制作自己的UCF101数据集呢?这个稍微有点复杂。

      UCF101数据集其实是按101个动作类别分类了的短视频的集合,每类动作对应一个目录,每个目录下有很多avi格式的视频文件,我们需要制作自己的项目应用领域的UCF101格式的数据集时,可以像这样把项目应用的视频数据按动作分类这样分目录存放,一个目录对应一个动作,实际项目中一般不会有101种动作,比如有三种或者四种动作,那么对应就按三个或四个目录存放视频文件即可,然后写个shell脚本或者python脚本来生成模型所需的train和test视频数据文件的list文件,train和test的list文件的内容格式根据你所用的3D模型所需要的格式来写,如果模型直接支持UCF101的train/test list格式(从UCF101的trainlist.txt文件中摘取示例如下):

       ApplyEyeMakeup/v_ApplyEyeMakeup_g01_c01.aviApplyEyeMakeup/v_ApplyEyeMakeup_g01_c02.aviApplyEyeMakeup/v_ApplyEyeMakeup_g01_c03.avi...ApplyLipstick/v_ApplyLipstick_g01_c01.aviApplyLipstick/v_ApplyLipstick_g01_c02.aviApplyLipstick/v_ApplyLipstick_g01_c03.aviApplyLipstick/v_ApplyLipstick_g01_c04.avi...

除了上面的数据文件(路径)的列表,还需要有个对应的定义class值的class_index.txt的文件:

1 ApplyEyeMakeup
2 ApplyLipstick
3 Archery
4 BabyCrawling
5 BalanceBeam
6 BandMarching
7 BaseballPitch
8 Basketball
9 BasketballDunk
10 BenchPress...

    很显然,解析这两个文件里的列表,就可以把avi数据文件和class值对应起来。

    但是这样做稍显得有点麻烦,所以一般C3D模型在定义自己的train_list.txt和test_list.txt文件格式时进行了简化,直接把数据文件和class值的对应关系定义在一个文件里,也就是类似这样:

ApplyEyeMakeup/v_ApplyEyeMakeup_g01_c01.avi   1
ApplyEyeMakeup/v_ApplyEyeMakeup_g01_c02.avi   1
ApplyEyeMakeup/v_ApplyEyeMakeup_g01_c03.avi   1...
ApplyLipstick/v_ApplyLipstick_g01_c01.avi   2
ApplyLipstick/v_ApplyLipstick_g01_c02.avi   2
ApplyLipstick/v_ApplyLipstick_g01_c03.avi   2
ApplyLipstick/v_ApplyLipstick_g01_c04.avi   2
...

    至于每个class值对应的具体的class类别名对模型来说根本不需要,这是调用模型进行识别的应用程序关心的内容,所以调用模型进行识别的应用程序才需要class_index.txt这样的文件。

    如果是你所使用模型只支持读取序列图片(例如C3D TensorFlow版),并且每个动作的序列图片保存在一个独立的子目录下,那么train/test列表文件可以是类似这样:

ApplyEyeMakeup/v_ApplyEyeMakeup_g01_c01/act1   1
ApplyEyeMakeup/v_ApplyEyeMakeup_g01_c01/act2   1
ApplyEyeMakeup/v_ApplyEyeMakeup_g01_c02/act1   1
ApplyEyeMakeup/v_ApplyEyeMakeup_g01_c03/act1   1
ApplyEyeMakeup/v_ApplyEyeMakeup_g01_c03/act2   1
ApplyEyeMakeup/v_ApplyEyeMakeup_g01_c03/act3   1...
ApplyLipstick/v_ApplyLipstick_g01_c01/act1   2
ApplyLipstick/v_ApplyLipstick_g01_c02/act1   2
ApplyLipstick/v_ApplyLipstick_g01_c02/act2   2
ApplyLipstick/v_ApplyLipstick_g01_c03/act1   2
ApplyLipstick/v_ApplyLipstick_g01_c04/act1   2
ApplyLipstick/v_ApplyLipstick_g01_c04/act2   2
ApplyLipstick/v_ApplyLipstick_g01_c04/act3   2
ApplyLipstick/v_ApplyLipstick_g01_c04/act4   2
...

    当每个视频文件都并不是单纯包含一个动作的小视频,而是几个动作的连接的视频,或者有好几个同类别动作连续的视频,那么上面的train_list.txt/test_list.txt的内容还得进一步改造一下,中间还需要增加一列数据指定动作的起始帧(start_frame),结束帧(end_frame)则一般是你使用的3D模型的配置文件里设置的,比如3D模型的配置文件里设置的length为16,则表示为一次读取16帧来训练或推理识别一个动作,那么从train_list.txt/test_list.txt里读取start_frame的值作为开始帧号,连续读取16帧,结束帧号自然是start_frame+16。此时train_list.txt和test_list.txt文件的内容则类似如下所示:

ApplyEyeMakeup/v_ApplyEyeMakeup_g01_c01.avi   1  1
ApplyEyeMakeup/v_ApplyEyeMakeup_g01_c02.avi   1  1
ApplyEyeMakeup/v_ApplyEyeMakeup_g01_c03.avi   1  1...
ApplyLipstick/v_ApplyLipstick_g01_c01.avi   1  2
ApplyLipstick/v_ApplyLipstick_g01_c02.avi   1  2
ApplyLipstick/v_ApplyLipstick_g01_c03.avi   1  2
ApplyLipstick/v_ApplyLipstick_g01_c04.avi   1  2
...

    假若你使用的3D模型只支持一序列图片来识别一个动作,或者是你的项目的视频数据都很大,按动作切分视频或者标注视频不方便,或者觉得相对使用目前某些视频标注工具来标注视频说,把视频抽取成图片后再来分类比较可靠不容易出错 (反正我实验用过MS的VoTT和国内某视频数据标注工具,可靠性离实用还差很远,经常一个地方出错就把全部帧位标注都搞乱了,有时可能标注了大半天就一个错误就全废了,真有气得要吐血的感觉。另外,工具支持的保存格式有限,得自己写脚本转换成类似UCF101这样风格的标注方式),那么写脚本调用ffmpeg之类的工具把对应目录下的每个视频按一定的FPS抽取成jpg图片,如果你使用的模型不支持start_frame标注,那么每个目录下只能存放模型的length参数指定帧数的图片,每一个动作序列的图片(比如16帧图片)对应存放到相应动作类别对应的目录下的对应视频文件对应的目录下的子目录中,全路径可以表示为.../<action_name>/<video_name>/<action_set>/*.jpg,如果你使用的模型支持start_frame标注,那么一个子目录下可以存放多种动作的序列图片,当然,每个序列的图片数不能少于模型的length参数指定的帧数,但是呢,为了清晰和便于核对,我一般还是一个子目录下只存放一种动作的指定帧数的图片(例如16帧)。然后写脚本生成把上面的train_list.txt/test_list.txt的内容中的avi的路径换成对应的图片所在的目录的路径即可(不要包含图片文件名本身),例如,我实际项目中使用序列图片而不是视频来训练模型时,train_list.txt/test_list.txt文件内容类似如下: 

             

     至于抽取图片的脚本以及生成train_list.txt/test_list.txt的脚本可以使用shell脚本写也可以使用python写,我沿用的C3D Tensorflow版的写法使用的shell写的,其实使用python可能更容易实现也更灵活,因为python功能很强大。

      贴出相关命令和示例代码:

     从http://ffmpeg.org/download.html 下载linux版本的ffmpeg可执行程序,然后设置环境:

写个shell脚本convert_video2jpg.sh从各个视频中抽取图片并分目录对应存放:

for folder in $1/*
dofor file in "$folder"/*.mp4doif [[ ! -d "$2/${file[@]%.mp4}" ]]; thenmkdir -p "$2/${file[@]%.mp4}"fiffmpeg -i "$file" -vf fps=$3 "$2/${file[@]%.mp4}"/%05d.jpgdone
done

假设视频文件都在video目录里,抽取的图片以为文件名为目录存放到父目录video_images下去, 抽取帧率 FPS = 10,那么执行命令:

./convert_video2jpg.sh video video_images 10

对抽取出来的图片进行人工挑选,挑选出属于同一个动作的序列图片到同一个子目录,然后按照<action_name>/<video_name>/<action_set>/*.jpg这样的路径方式存放。当然如果全靠人工这么干太费时间了,所以我弄了个投机取巧的办法,让数据标注人员找到每个动作的起始关键帧(从图片看能明显判断出是该动作的开始)使用labelimg之类的标注工具标注一下动作名以生成这张图片对应的标注文件,标注文件和图片保存在一起,然后我写脚本去读取video_images下的所有标注文件,从标注文件对应的图片开始,按照图片的名字里的序号(图片文件的名字其实也可以不是连续的数字,关键是你写代码读取时要注意保证按照动作的先后顺序依次读取那些图片,不要顺序颠倒了就引起了混乱,如果你使用的3D模型只能读取图片文件的名字是连续数字的,但你又不想被这点束缚,那么可以修改模型文件里读取数据的代码,例如video-caffe里的读取动作对应的视频或者连续图片的数据代码就在src/caffe/util/io.cpp里,我就把相关代码注释掉了改成了可以按文件名字符串排序(这样就不受连续数据的束缚了)顺序读取每个动作集子目录下的全部图片)往后依次读取16帧,自动保存到一个动作集目录<action_name>/<video_name>/<action_set>/下去,这样只要人工标注完了每个动作的关键帧,就能很快按照<action_name>/<video_name>/<action_set>/*.jpg路径格式生成UCF101风格的数据集,然后使用下面的脚本convert_images_to_C3D_list.sh生成train_list.txt和test_list.txt(C3D里使用ucf101数据集训练是对应的文件名叫c3d_ucf101_train_split1.txt和c3d_ucf101_test_split1.txt,这里我保持一致):

> c3d_ucf101_train_split1.txt
> c3d_ucf101_test_split1.txt
COUNT=-1
for folder in $1/*
doprintf "${folder}\n"COUNT=$[$COUNT + 1]for imagesFolder in "$folder"/*/*doprintf "${imagesFolder}\n"if (( $(jot -r 1 1 $2)  > 1 )); thenecho "${imagesFolder}" 1 $COUNT >> c3d_ucf101_train_split1.txtelseecho "${imagesFolder}" 1 $COUNT >> c3d_ucf101_test_split1.txtfidone
done

里面用到个产生随机数的工具athena-jot,首先安装它:

apt-get install athena-jot

然后执行下面的命令产生train/test列表文件:

./convert_images_to_C3D_list.sh data/video-labeled-3dds 4

生成的train/test列表文件内容示例如下:

   

另外呢,统计计算图片数据的均值时也需要这样的列表文件,例如我写了个生成这样的列表文件的脚本convert_images_to_caffe_lmdb_list.sh如下:

> caffe_lmdb.list
COUNT=-1
for folder in $1/*
doprintf "${folder}\n"COUNT=$[$COUNT + 1]for imagesFolder in "$folder"/*/*doprintf "${imagesFolder}\n"for f in "${imagesFolder}"/*.jpgdoecho "$f" $COUNT >> caffe_lmdb.listdonedone
done

然后执行脚本生成列表文件

./convert_images_to_caffe_lmdb_list.sh data/video-labeled-3dds 4

然后使用这个列表文件去统计生成lmdb database文件

cd  /workspace/video-caffe/build/tools
./convert_imageset  /workspace/video-caffe/ /workspace/video-caffe/caffe_lmdb.list laundry.lmdb --resize_width=171 --resize_height=128

然后使用lmdb文件算出均值:

./compute_image_mean laundry.lmdbI0610 21:26:28.706018  2337 db_lmdb.cpp:35] Opened lmdb laundry.lmdb
I0610 21:26:28.707100  2337 compute_image_mean.cpp:70] Starting iteration
I0610 21:26:29.398113  2337 compute_image_mean.cpp:95] Processed 10000 files.
I0610 21:26:29.505965  2337 compute_image_mean.cpp:101] Processed 11584 files.
I0610 21:26:29.506062  2337 compute_image_mean.cpp:108] Write to laundry_mean.binaryproto
I0610 21:26:29.506680  2337 compute_image_mean.cpp:114] Number of channels: 3
I0610 21:26:29.506724  2337 compute_image_mean.cpp:119] mean_value channel [0]: 121.643
I0610 21:26:29.506786  2337 compute_image_mean.cpp:119] mean_value channel [1]: 124.514
I0610 21:26:29.506829  2337 compute_image_mean.cpp:119] mean_value channel [2]: 126.064

然后使用这些均值去设置ucf101训练video-caffe的配置文件c3d_ucf101_ train_test.prototxt,一并设置好train/test列表文件c3d_ucf101_train_split1.txt和c3d_ucf101_test_split1.txt的路径作为训练和测试的数据source:

    

  

  

然后根据需要修改c3d_ucf101_solver.prototxt里的超参数后就可以执行下面的命令开始训练了:

cd /workspace/video-caffe
./examples/c3d_ucf101/train_ucf101.sh

 


http://chatgpt.dhexx.cn/article/E0lKq4Ox.shtml

相关文章

时空行为检测数据集 JHMDB UCF101_24 详解

文章目录 0. 前言1. JHMDB1.1. 基本情况1.2. 数据准备以及标签详解 2. UDF101_242.1. 基本情况2.2. 数据准备与标签详解 3. 数据集可视化代码 0. 前言 现在常用的时空行为检测数据集只有AVA/JHMDB/UCF101_24。 AVA数据集是每一秒标一帧&#xff0c;更多信息可以参考我的笔记。…

行为识别TSM训练ucf101数据集

序言 最近有个行为检测的需求&#xff0c;打算用行为识别做&#xff0c;纯小白入这个方向&#xff0c;啃了两周的TSM原理和源码&#xff0c;训练好自己的数据集后&#xff0c;发现好像没法应用到自己的需求场景&#xff1f;&#xff1f;玛德&#xff01;算了&#xff0c;还是要…

UCF101数据集处理

UCF101数据集处理 在复现动作识别类的算法时&#xff0c;常需要用到数据集。ucf101就是其中一个。 之前复现代码时所用的ucf101数据集是直接将原数据集中的视频处理成图片。数据集目录如下&#xff1a; UCF101/ApplyEyeMakeup/v_ApplyEyeMakeup_g01_c01/img_00001.jpg (此时通过…

深度学习视频数据集(动作识别):UCF-101

UCF-101 官网&#xff1a;https://www.crcv.ucf.edu/research/data-sets/ucf101/ 网盘&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1RsJuykWyUlQ4_c1TwqxR_Q 提取码&#xff1a;909g 官方解释 UCF101是一个现实动作视频的动作识别数据集&#xff0c;收集自YouTub…

UCF101数据集提取帧+TDN部署(Anaconda+Python3.7+Pytorch)

UCF101数据集提取帧TDN部署&#xff08;AnacondaPython3.7Pytorch&#xff09; 前言一、安装MMAction21.引入库2.环境搭建3.安装4.准备原始数据集5.制作视频提取帧数据集 二、部署TDN1.引入库2.读入数据3.训练模型4.查看结果 本人实测结果 前言 将TDN部署在个人电脑上&#xf…

UCF101动作识别数据集简介绍及数据预处理

文章目录 一、数据集简介&#xff1a;二、数据集获取及解压缩&#xff1a;1. 数据下载2. 数据集解压缩&#xff1a; 三、数据集划分四、数据集预处理1. 生成pkl文件2. 直接对视频文件处理 一、数据集简介&#xff1a; UCF101是一个现实动作视频的动作识别数据集&#xff0c;收…

【Java】内部类的定义

目录 一、前言 二、内部类 语法格式&#xff1a; static修饰内部类 内部类未被static修饰时&#xff1a; 内部类被static修饰后 演示操作&#xff1a; 一、前言 前面我们学习了一个小的项目&#xff0c;现在我们来学习新的知识点&#xff0c;关于内部类的描述&#xff0…

Java类的定义、声明及使用

1、 class 类名称{属性方法} 2、声明一个类需要通过一个关键字class 3、类与对象的关系 1&#xff09;类是对某一类事物的描述&#xff0c;是抽象的、概念上的意义&#xff0c;对象是实际存在的该类事物的每一个个体&#xff0c;也被称为实例。 package classdemo; class …

C#类的定义

在C#语言中创建的任何项目都有类的存在&#xff0c;通过类能很好地体现面向对象语言中封装、继承、多态的特性。 类的访问修饰符&#xff1a;用于设定对类的访问限制&#xff0c;包括 public、internal 或者不写&#xff0c;用 internal 或者不写时代表只能在当前项目中访问类…

C#类的定义和声明及使用

类的定义 类的成员 } 例如&#xff0c;以水果为例来声明一个类&#xff0c;代码如下&#xff1a;在 C# 语言中创建的任何项目都有类的存在&#xff0c;通过类能很好地体现面向对象语言中封装、继承、多态的特性。 简单的来说&#xff0c;在C#编程里&#xff0c;类是一种数据结…

(27)python类的定义和使用

面向对象初步 面向对象&#xff08;Object oriented Programming&#xff0c;OOP&#xff09;编程的思想主要是针对大型软件设计而来的。面向对象编程使程序的扩展性更强、可读性更好&#xff0c;使的编程可以像搭积木一样简单。 面向对象编程将数据和操作数据相关的方法封装…

类的认识和定义

前言 C为啥要引入类这个概念呢&#xff0c;以C实现栈为例说明。 typedef int STDataType; typedef struct Stack { . . . .int top; . . . .STDataType* data; . . . .int capacity; }Stack; void StackInit(Stack* ps); //栈的初始化 void StackDestory(Stack* ps); //栈的销…

Python类的定义

类的定义&#xff1a;我们把对象比作一个“饼干”&#xff0c;类就是制造这个饼干的模具。通过类定义数据类型的属性和方法&#xff0c;也就是说&#xff0c;“类将行为和状态打包在一起”。 类的结构 方法&#xff08;函数&#xff09;..............行为 属性&#xff08;…

java类的定义

目录 一、概念二、使用1.成员变量2.成员方法3.权限修饰符4.静态方法 三、重写toString方法 一、概念 我们不能将一个事物称之为一类事物&#xff0c;例如一只鸟我们不能称为鸟类&#xff0c;但是我们需要给一类事物统称&#xff0c;例如大雁&#xff0c;麻雀&#xff0c;燕子&…

C++ 类的定义与使用

十二、类与对象 对象&#xff1a;就是我们生活中的具体事物&#xff0c;看得见摸得到&#xff0c;有一定的属性和行为或操作方式 面向对象&#xff1a;是一种软件的开发方法&#xff0c;对象所指的是计算机系统中的某一个成分。在面向对象程序设计中&#xff0c;对象包含两个…

4.类的定义,变量类型,方法类型

文章目录 1.类的概念1.1 如何创建一个类1.2 如何定义一个类1.2.1变量1.2.2 方法 2.对象3.类定义使用实例4.理解类和对象的关系4.1.一个java程序和类之间的关系 5.细节知识分析5.1.类与类的关系5.2.变量和变量区别5.3.方法的区别5.4.类方法和类变量的特点 1.类的概念 类java是基…

关于类的定义

类的定义 类的概念如何定义类修饰符 类的概念 1、类是把事物的数据与相关功能封装到一起&#xff0c;形成一种特殊的数据结构&#xff0c;用以表达真是事物的一种抽象&#xff1b;而对象则是实际存在的属该类事物的具体个体&#xff0c;因而也称为实例&#xff08;instance&am…

python 爬虫爬取疫情数据,爬虫思路和技术你全都有哈(一)

python 爬虫爬取疫情数据&#xff0c;爬虫思路和技术你全都有哈&#xff08;二、数据清洗及存储&#xff09; 爬起疫情数据&#xff0c;有两个网址&#xff1a; 1、百度&#xff1a;链接 2、丁香园疫情&#xff1a;链接 在这两个中&#xff0c;丁香园的爬虫相对简单一点&#…

采用python爬虫爬取数据然后采用echarts数据可视化分析

前言&#xff1a;采用python爬虫爬取天气数据然后采用echarts数据可视化画图分析未来天气变化趋势 从获取数据到可视化的流程 &#xff08;熟悉爬虫爬取数据然后数据可视化这个过程&#xff09; 一、python爬取未来8-15天的天气数据 1、导入用到的一些python第三方库 imp…

python网络爬虫爬取数据,python全网爬取内容

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python网络爬虫爬取数据&#xff0c;利用python爬取数据&#xff0c;现在让我们一起来看看吧&#xff01; 网络爬虫&#xff0c;就是按照一定规则自动访问互联网上的信息并把内容下载下来的程序或脚本。 在整个的Python…