LightStage
LightStage是一个多视图数据集,在NeuralBody中提出。该数据集使用具有 20+ 同步摄像头的多摄像头系统捕获多个动态人类视频。人类执行复杂的动作,包括旋转、太极、手臂摆动、热身、拳击和踢腿。我们提供使用EasyMocap恢复的SMPL-X参数,其中包含身体,手和面部的运动。
23个摄像机
363到388都有类似结构(396有点特殊)
整体架构(以363文件夹为例)
D:.
├─annots
│ ├─01
│ ├─02
│ ├─03
│ ├─04
│ ├─05
│ ├─06
│ ├─07
│ ├─08
│ ├─09
│ ├─10
│ ├─11
│ ├─12
│ ├─13
│ ├─14
│ ├─15
│ ├─16
│ ├─17
│ ├─18
│ ├─19
│ ├─20
│ ├─21
│ ├─22
│ └─23
├─smplx
└─videos
![在这里插入图片描述](https://img-blog.csdnimg.cn/214551c3b8af485ebdec51a57a9674ac.png)
相机内参文件intri.yaml
相机内参参数k 和 畸变系数(但是好像全部都是0)
![在这里插入图片描述](https://img-blog.csdnimg.cn/359ec1f6fb2844aea10c87821ac4a632.png)
相机外参文件extri.yml
自上到下应该是旋转向量,旋转矩阵,平移量
![在这里插入图片描述](https://img-blog.csdnimg.cn/bd92676f9d9a4e2bb85a15cba79f1c7f.png)
25个2d关节点对应
鼻子 下颈
右肩 右肘 右手腕
左肩 左肘 左手腕
骨盆 右骨盆 右膝 右脚踝 左骨盆 左膝 左脚踝
右眼 左眼 右耳 左耳 左大脚趾 左脚小拇指趾 左脚跟 右大脚趾 右脚小拇指趾 右脚跟
浙大指南【快速开始】
画点代码直接拿去用就行
def draw_points(img,uv,color=(255,255,255)):
for i in range(len(uv)):
img=cv.circle(img,(int(uv[i][0]),int(uv[i][1])),3, color, -1) #(x,y)
return img
def draw_points_one(imgpath,uv,outpath,color=(255,255,255)):
for i in range(len(uv)):
img=cv.imread(imgpath)
img=cv.circle(img,(int(uv[i][0]),int(uv[i][1])),3, color, -1) #(x,y)
cv.imwrite(os.path.join(outpath,"kp_{}.jpg".format(i)),img)
return img
def draw(points_2d,GT_2d,path):
img = cv.imread(path)
img = draw_points(img, GT_2d, color=(0, 255, 0))
img = draw_points(img, points_2d)
cv.imwrite(r"result.jpg", img)
annots文件夹中每个json文件的架构如下:
{
"filename": "images/23/000000.jpg",
"height": 1024,
"width": 1024,
"annots": [
{
"bbox": [
#应该是x1,y1,x2,y2,confidence
],
"personID": 0,
"keypoints": [
[
581.913,
249.231,
0.819745
],
#....25个关键点
],
"isKeyframe": false,
"face2d": [
#.....
],
"handl2d": [
#......
],
"handr2d": [
#......
]
}
],
"isKeyframe": false
}
smplx文件夹:
[
{
"id": 0,
"Rh": [
[1.408, 1.083, 1.204]
],
"Th": [
[0.218, 0.511, 1.286]
],
"poses": [
[0.000, 0.000, 0.000, -0.113, 0.069, -0.113, -0.062, -0.023, -0.183, -0.000, 0.000, 0.000, 0.076, 0.079, 0.044, 0.141, -0.106, -0.004, -0.000, 0.000, 0.000, -0.073, 0.085, -0.084, -0.231, -0.099, 0.008, -0.000, -0.000, 0.000, -0.000, 0.000, -0.000, 0.000, -0.000, 0.000, -0.097, 0.088, 0.070, 0.002, -0.000, -0.000, -0.000, 0.000, 0.258, -0.148, 0.070, -0.140, -0.069, -0.218, 0.653, -0.157, -0.054, 0.909, -0.173, -0.300, 0.053, -0.140, 0.038, 0.026, -0.199, 0.010, 0.237, 0.016, -0.177, -0.255, -1.322, 0.320, 0.552, -0.574, 0.144, 0.157, -0.867, 0.247, 0.371, -0.428, 0.013, 0.106, 0.022, -0.019, 0.006, -0.001, -0.000, 0.000, -0.001, -0.000, -0.000]
],
"expression": [
[0.000, 0.000, 0.000, -0.000, 0.000, 0.000, 0.000, -0.000, 0.000, 0.000]
],
"shapes": [
[-0.066, 0.078, 0.101, -0.077, -0.047, -0.080, 0.004, 0.010, 0.012, 0.008]
]
}
]
读取该数据集的脚本
import yaml
import cv2
import zipfile
import glob
import os
import json
import skvideo.io
# read_yml,write_yml 获得普通格式的文件夹
def read_yml(file):
"""读取yml,传入文件路径file"""
f = open(file, 'r', encoding="utf-8") # 读取文件
yml_config = yaml.load(f, Loader=yaml.FullLoader) # Loader为了更加安全
"""Loader的几种加载方式
BaseLoader - -仅加载最基本的YAML
SafeLoader - -安全地加载YAML语言的子集。建议用于加载不受信任的输入。
FullLoader - -加载完整的YAML语言。避免任意代码执行。这是当前(PyYAML5.1)默认加载器调用yaml.load(input)(发出警告后)。
UnsafeLoader - -(也称为Loader向后兼容性)原始的Loader代码,可以通过不受信任的数据输入轻松利用。
"""
return yml_config
def write_yml(file, data):
# 写入数据:
with open(file, "a", encoding='utf-8') as f:
# data数据中有汉字时,加上:encoding='utf-8',allow_unicode=True
f.write('\n') # 插入到下一行
yaml.dump(data, f, encoding='utf-8', allow_unicode=True)
# readListInFileNode,readCameraCfg用来获得opencv格式的yaml文件夹
def readListInFileNode(filenode):
assert (filenode.isSeq())
res = []
for i in range(filenode.size()):
res.append(filenode.at(i).real())
return res
def readextriCfg(yamlpath):
cv_file = cv2.FileStorage(yamlpath, cv2.FILE_STORAGE_READ)
"""
R:
Rot:
T:
"""
res = {}
for i in range(1, 24):
R = r'R_{}'.format(str(i).zfill(2))
Rot = r'Rot_{}'.format(str(i).zfill(2))
T = r'T_{}'.format(str(i).zfill(2))
extri = {
'R': cv_file.getNode(R).mat(),
'Rot': cv_file.getNode(Rot).mat(),
'T': cv_file.getNode(T).mat()
}
res['{}'.format(i)] = extri
return res
def readintriCfg(yamlpath):
cv_file = cv2.FileStorage(yamlpath, cv2.FILE_STORAGE_READ)
"""
K:内参
dist:畸变系数
"""
res = {}
for i in range(1, 24):
K = r'R_{}'.format(str(i).zfill(2))
dist = r'Rot_{}'.format(str(i).zfill(2))
intri = {
'K': cv_file.getNode(K).mat(),
'dist': cv_file.getNode(dist).mat(),
}
res['{}'.format(i)] = intri
# res = {
# "CameraExtrinsicMat": cv_file.getNode("CameraExtrinsicMat").mat(),
# "CameraMat": cv_file.getNode("CameraMat").mat(),
# "DistCoeff": cv_file.getNode("DistCoeff").mat(),
# # "ImageSize": readListInFileNode(cv_file.getNode("ImageSize")),
# # "ReprojectionError": cv_file.getNode("ReprojectionError").real(),
# # "DistModel": cv_file.getNode("DistModel").string()
# }
return res
# 解压文件夹
def unzip_file(zip_src, dst_dir):
r = zipfile.is_zipfile(zip_src)
if r:
fz = zipfile.ZipFile(zip_src, 'r')
for file in fz.namelist():
fz.extract(file, dst_dir)
print('unzip successfully {}'.format(zip_src))
else:
print('{} is not zip'.format(zip_src))
def unzipfile(datasetpath, dataset):
"""
解压zip数据集
"""
if dataset == 'LightStage':
# 获得所有zip文件夹
zipfiles = glob.glob(r"{}/*.zip".format(datasetpath))
for zipfile in zipfiles:
unzip_file(zipfile)
print("finish unzip!!!")
def readdata(datasetpath, dataset, tar, extract_img=True):
"""
datasetpath:数据集文件的路径
dataset:数据集名称
tar:是否进行解压
extract_img:是否提取视频文件(存放在"images/相机/"文件夹下)
return 字典
{
文件夹序号(e.g.363){ #相机 外参 内参
{'camera':{'1':{'excfg':{},'incfg':{}},.....}
{'annots':
{'01':#相机编号
[
{ #图片编号
"filename": "images/01/000000.jpg",
"height": 1024,
"width": 1024,
"annots":
[
` { "bbox": []
"personID": 0,
"keypoints": [....] #2d关键点,三个维度(x,y,confidence)
"face2d":[]
"handl2d": [..]
"handr2d":[....]`
}
]
"isKeyframe":.
}
......
]
}
{
'smpl':[....]
....
}
}
"""
# 这里最好加一个转化为小写的
if tar:
unzipfile(datasetpath, dataset)
if dataset == 'LightStage':
"""
(1)396号文件夹中不包含smpl文件和annot文件,故没有添加
"""
userlist = [i for i in range(363, 389)]
# userlist = [363]
cameralist = [i for i in range(1, 24)]
# cameralist= [1]
results = {}
for user in userlist:
user = str(user)
# step1:相机参数文件
camera = {}
res = {}
extripath = os.path.join(datasetpath, user, "extri.yml") # 外参文件
intripath = os.path.join(datasetpath, user, "extri.yml") # 内参文件
# intri.yml
# yaml文件上可以使用异常处理(opencv格式yaml文件和普通yaml文件)
excfg = readextriCfg(extripath)
incfg = readintriCfg(intripath)
camera['excfg'] = excfg
camera['incfg'] = incfg
res['camera'] = camera
videopath = os.path.join(datasetpath, user, "videos")
# step2:json文件处理: 处理对应annot中的json文件
camindex = {}
for cam in cameralist:
numberOfFrame = 0
cam = str(cam).zfill(2)
video = cam + '.mp4'
vid_file = os.path.join(videopath, video)
vidcap = cv2.VideoCapture(vid_file)
success, image = vidcap.read()
frames_num = vidcap.get(7)
print(">>>当前视频{}的总帧数是".format(video), int(frames_num))
annots_path = os.path.join(datasetpath, user, 'annots', cam)
annotlist = glob.glob("{}/*.json".format(annots_path))
# print(annotlist)
# 转成有序数列????
print(">>>只有{}个json文件,只生成{}帧".format(len(annotlist), len(annotlist)))
# step2.1:视频处理 (图片生成)
jsonInCamera = []
"""
for i in range(0,len(annotlist)):
print(i)
if extract_img:
success, image = vidcap.read()
if not success:
print('fail!')
break
print(cv2.CAP_PROP_POS_FRAMES)
"""
imgarray = skvideo.io.vread(vid_file)
print(">>>the total frames of {} is".format(video), imgarray.shape)
for frame in imgarray:
# 创建对应路径images/相机(images/01/000000.jpg)
img_dir = os.path.join(datasetpath, user, 'images')
if extract_img:
if not os.path.exists(img_dir):
os.mkdir(img_dir)
cam_dir = os.path.join(img_dir, cam)
if not os.path.exists(cam_dir):
os.mkdir(cam_dir)
imagename = "{}.jpg".format(str(numberOfFrame).zfill(6))
img_out = os.path.join(cam_dir, imagename)
cv2.imwrite(img_out, frame)
print(">>> creating {} frame of {} ".format(str(numberOfFrame).zfill(6), video))
annots = json.load(open(r"{}/{}/annots/{}/{}.json".format(datasetpath, user, str(cam).zfill(2),
str(numberOfFrame).zfill(6)), 'r'))
jsonInCamera.append(annots)
numberOfFrame = numberOfFrame + 1
camindex[(cam)] = jsonInCamera
res['annots'] = camindex
# step3:处理smplx参数
smplInCamera = []
smpllist = glob.glob(r"{}/{}/smplx/*.json".format(datasetpath, user))
print("smplx标注文件共有{}".format(len(smpllist)))
for i in range(0, len(smpllist)):
smplx = json.load(open(r"{}/{}/smplx/{}.json".format(datasetpath, user, str(i).zfill(6)), 'r'))
smplInCamera.append(smplx)
res['smplx'] = smplInCamera
# print(res)
results[(user)] = res
return results
if __name__ == '__main__':
datasetpath = '/hy-tmp/LightStage'
dataset = 'LightStage'
result = readdata(datasetpath, dataset, False, True)
package363 = result['363']
# 相机参数
# camera=package363['camera']
# print(">>>相机参数如下:",camera)
# annot
annot = package363['annots']['01'][0] # 第一帧的标注文件
print(type(annot))
print(">>>第一个annot如下:\n ", annot)
print(">>> filename \n", annot['filename'])
print(">>> height \n", annot['height'])
print(">>> width \n", annot['width'])
print(">>> annots \n", annot['annots'])
print(">>> bbox \n", annot['annots'][0]['bbox'])
# smplx参数
print(">>> smplx \n", package363['smplx'][0]) #
# print(">>> box \n",annot['box'])
# print(">>> box \n",annot['box'])
# print(result)
i = 363
# extripath = r"{}/{}/extri.yml".format(datasetpath, i) # 外参文件
# intripath = r"{}\{}\intri.yml".format(datasetpath, i) # 内参文件
#
# extripath = os.path.join(datasetpath, str(i), "extri.yml") # 外参文件
# excfg = readextriCfg(extripath)
# intripath = os.path.join(datasetpath, str(i), "extri.yml")
# incfg = readintriCfg(intripath)
# camera={}
# # print(incfg)
# camera['excfg'] = excfg
# camera['incfg'] = incfg
# print(camera)
# # print(extripath)
# # print(intripath)
# # excfg = read_yml(extripath)
# # incfg = read_yml(intripath)
#
# # print(excfg)
# # print(incfg)
# # excfg=readCameraCfg(extripath)
# # print(excfg)
#
# # filepath = "/home/yxhuang/data/CICV/task4/task4/camera.yaml"
# #D:\computervision\work\dataset\363\extri.yml
# # camera_cfg = readextriCfg(extripath)
# # print(camera_cfg)
# #
# # vid_file=r'D:\computervision\work\dataset\363\videos\02.mp4'
# # vidcap = cv2.VideoCapture(vid_file)
# # success, image = vidcap.read()
# # frames_num = vidcap.get(7)
# # print(frames_num)
# # img_dir = '{}/{}/images/'.format(datasetpath, i)
# # if not os.path.exists(img_dir):
# # os.mkdir(img_dir)
# annots = json.load(open(r"{}/{}/annots/{}/{}".format(datasetpath, i, str(1).zfill(2),'000000.json'), 'r'))
# print(annots)
# expected alphabetic or numeric character, but found ':'
"""
问题来自于:
%YAML:1.0
!!opencv-matrix
"""