文章目录
- 0. 前言
- 1. JHMDB
- 1.1. 基本情况
- 1.2. 数据准备以及标签详解
- 2. UDF101_24
- 2.1. 基本情况
- 2.2. 数据准备与标签详解
- 3. 数据集可视化代码
0. 前言
- 现在常用的时空行为检测数据集只有AVA/JHMDB/UCF101_24。
- AVA数据集是每一秒标一帧,更多信息可以参考我的笔记。
- JHMDB/UCF101_24 是逐帧标注的数据
1. JHMDB
- 官网,HMDB官网
1.1. 基本情况
-
JHMDB是对HMDB数据集的二次标注,即 joint-annotated HMDB。
- HMDB数据集有51类,5100多视频。
- JHMDB只标注了HMDB的一部分,21类只包括一个人的行为,也删除了一些这21类行为中人不明显的样本。
- 21类每一类有36-55个样本,每个样本包括了行为的起始与终止时间,每个样本包括14-40帧。
- JHMDB一共标注了31838张图片。
-
类别列表(21类)
- sit
- run
- pullup
- walk
- shoot_gun
- brush_hair
- jump
- pour
- pick
- kick_ball
- golf
- shoot_bow
- catch
- clap
- swing_baseball
- climb_stairs
- throw
- wave
- shoot_ball
- push
- stand
-
每个视频最多只有一类目标行为,bbox只标了做目标行为的那几个人
1.2. 数据准备以及标签详解
- 下面内容参考了 mmaction2数据准备文档,数据下载在上面的文档中有介绍了,反正就是一个压缩包,没啥好说的。
- 原始JHMDB数据集中好像有关键点、分割等的标签,但我们这个任务中不用。
- 标签全部保存在
JHMDB-GT.pkl
中,这个文件是一个字段,包括了6个keylabels
(list): List of the 21 labels,21类行为标签,即上一小节中提到的。gttubes
(dict): Dictionary that contains the ground truth tubes for each video.- 每个视频、每帧对应的标签(bbox以及行为类别)
- key为每个样本的相对路径,比如
walk/Panic_in_the_Streets_walk_u_cm_np1_ba_med_5
- value也是list,表示一系列tubes
- 每个tube用字典表示,class_id/bboxes键值对
- A gttube is dictionary that associates with each index of label and a list of tubes.
- A tube is a numpy array with
nframes
rows and 5 columns, each col is in format like<frame index> <x1> <y1> <x2> <y2>
.
nframes
(dict): Dictionary that contains the number of frames for each video, like'walk/Panic_in_the_Streets_walk_u_cm_np1_ba_med_5': 16
.- 每个视频包含多少帧图片。
- key为每个样本的相对路径,value为帧数量。
train_videos
(list): A list withnsplits=1
elements, each one containing the list of training videos.- list对象,每个元素也是list(包含若干视频样本信息)
- 训练集相关视频有哪些
- 每个样本通过其相对路径表示
test_videos
(list): A list withnsplits=1
elements, each one containing the list of testing videos.- list对象,每个元素也是list(包含若干视频样本信息)
- 测试集相关视频有哪些
- 每个样本通过其相对路径表示
resolution
(dict): Dictionary that outputs a tuple (h,w) of the resolution for each video, like'pour/Bartender_School_Students_Practice_pour_u_cm_np1_fr_med_1': (240, 320)
.- key为每个样本的相对路径,value为对应分辨率
2. UDF101_24
2.1. 基本情况
-
UCF101_24是UCF101数据集的子集,使用了一些不一样的标签。
- 关于标签来源有点尴尬,UCF101中本来是有对应标签的,但现在已经不能下载了。
- 现在的UCF101_24标签是从这个repo中,说是进行了一些微调。
- 每个视频最多只有一类目标行为,bbox只标了做目标行为的那几个人。
- 感觉也有例外,salsospin有样本都有多个人跳舞(大于等于6个),但只标了俩人。
- 关于标签来源有点尴尬,UCF101中本来是有对应标签的,但现在已经不能下载了。
-
类别信息(共24类)
- WalkingWithDog
- Diving
- PoleVault
- SkateBoarding
- CricketBowling
- GolfSwing
- Skijet
- RopeClimbing
- FloorGymnastics
- Basketball
- Biking
- VolleyballSpiking
- Fencing
- CliffDiving
- HorseRiding
- SoccerJuggling
- TennisSwing
- LongJump
- SalsaSpin
- TrampolineJumping
- IceDancing
- Skiing
- Surfing
- BasketballDunk
2.2. 数据准备与标签详解
-
数据下载以及其他相关可以参考 mmaction2数据准备文档,数据下载在上面的文档中有介绍了,反正就是一个压缩包,没啥好说的。
-
标签与
1.2.数据准备以及标签详解
完全相同,这里就不多说了。
3. 数据集可视化代码
- 需求分析:根据类别展示训练样本,在图片上画bbox。
import argparse
import os
import cv2
import pickle
from collections import defaultdictdef _parse_args():parser = argparse.ArgumentParser()parser.add_argument("--dataset", type=str, default="ucf101_24")parser.add_argument("--dataset_root_path", type=str,default="/ssd01/data/ucf101_24")parser.add_argument("--rgb-dir-name", type=str, default="rgb-images")# JHMDB & UCF101_24parser.add_argument("--pkl-filename", type=str, default="UCF101v2-GT.pkl")parser.add_argument("--img-impl", type=str, default="%05d.jpg")return parser.parse_args()def _darknet_draw_bbox(bboxes,labels,scores,img,bboxes_color=(0, 255, 0),bboxes_thickness=1,text_color=(0, 255, 0),text_thickness=2,text_front_scale=0.5):"""bbox的形式是 xyxy,取值范围是像素的值labels是标签名称scores是置信度,[0, 1]的浮点数"""for idx, (bbox, label) in enumerate(zip(bboxes, labels)):xmin, ymin, xmax, ymax = bboxpt1 = (int(xmin), int(ymin)) # 左下pt2 = (int(xmax), int(ymax)) # 右上# 画bboxcv2.rectangle(img, pt1, pt2, bboxes_color, bboxes_thickness)# 写上对应的文字cur_label = labelif scores is not None:cur_label += " [" + str(round(scores[idx] * 100, 2)) + "]"cv2.putText(img=img,text=cur_label,org=(pt1[0], pt1[1] - 5),fontFace=cv2.FONT_HERSHEY_SIMPLEX,fontScale=.5,color=(0, 255, 0),thickness=2,)return imgdef _show_single_video(rgb_dir, tubes, nframes, label, img_impl):draw_imgs = []for i in range(nframes):img = cv2.imread(os.path.join(rgb_dir, img_impl % (i+1)))boxes = tubes[i+1]draw_img = _darknet_draw_bbox(boxes, [label]*len(boxes), None, img)draw_imgs.append(draw_img)cv2.imshow("demo", draw_img)cv2.waitKey(100)return draw_imgsdef _filter_samples(data_dict, args):# TODO: filter input data with categoriesreturn data_dictdef _show_spatiotemporal_datasets(args):pkl_path = os.path.join(args.dataset_root_path, args.pkl_filename)rgb_dir_path = os.path.join(args.dataset_root_path, args.rgb_dir_name)with open(pkl_path, "rb") as fid:cache = pickle.load(fid, encoding='bytes')labels = [c.decode() for c in cache[b'labels']]train_videos = [c.decode() for c in cache[b'train_videos'][0]]test_videos = [c.decode() for c in cache[b'test_videos'][0]]nframes = {k.decode(): v for k, v in cache[b'nframes'].items()}resolution = {k.decode(): v for k, v in cache[b'resolution'].items()}gttubes = {k.decode(): v for k, v in cache[b'gttubes'].items()}# key - sample relative dir# value - dict# label - int# nframes - int# reoslution - tuple# tubes - arraydata_dict = defaultdict(dict)for k in nframes:data_dict[k]['nframes'] = nframes[k]for k in resolution:assert data_dict[k]['nframes'] is not Nonedata_dict[k]['resolution'] = resolution[k]for k in gttubes:assert data_dict[k]['resolution'] is not Nonelabel = list(gttubes[k].keys())[0]data_dict[k]['label'] = labeldata_dict[k]['tubes'] = defaultdict(list)for boxes in gttubes[k][label]:for box in boxes:data_dict[k]['tubes'][int(box[0])].append(box[1:])for relative_path in data_dict.keys():sample = data_dict[relative_path]_show_single_video(os.path.join(rgb_dir_path, relative_path),sample['tubes'],sample['nframes'],labels[sample['label']],args.img_impl,)def main(args):if args.dataset in ["ucf101_24", "jhmdb"]:show_dataset_fn = _show_spatiotemporal_datasetselse:raise ValueError("Unknown dataset {}".format(args.dataset))show_dataset_fn(args)if __name__ == '__main__':main(_parse_args())