非接触式,视频,生理
自定义协议,非商业可用
Big-data节点
张文杰维护
由法国勃艮第-弗朗什孔泰大学所收集的多场景面部视频数据集
数据类型:可申请获取
数据来源:S. Bobbia et al.
创建时间:2019-06-01
数据集编号:No.12132
非接触式,视频,生理
自定义协议,非商业可用
Big-data节点
张文杰维护
详情
公共数据库UBFC-RPPG提供了使用网络摄像头(Logitech C920 HD pro)收集的50个视频数据以及由透射式脉搏血氧计CMS50E测量的PPG(脉搏率和SpO2)信息。 参与者与摄像机之间的距离约为1 m,视频以30 fps 的帧速率和640 × 480 的分辨率录制。 在不同的地方进行数据收集,并使用环境光作为照明源。 参与者的肤色各不相同,其中有留着胡须的男人,也有戴着眼镜的人。 该数据库由两个数据集组成。 第一个数据集中包含八个视频。 记录过程中,参与者保持静止状态,其中一名参与者在测量实验前进行练习,而另一名参与者则不进行练习。 第二个数据集包含 42 个视频。 在这个数据集中,参与者在测量过程中需要玩数学游戏,以模拟人与计算机之间交互等现实情况。
import torch
import os
import numpy as np
import pandas as pd
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms
import cv2
import random
class Normaliztion(object):
"""
same as mxnet, normalize into [-1, 1]
image = (image - 127.5)/128
"""
def __call__(self, sample):
video_x, clip_average_HR, ecg_label, frame_rate = sample['video_x'], sample['clip_average_HR'], sample['ecg'], \
sample['frame_rate']
new_video_x = (video_x - 127.5) / 128 #对每一个像素点进行归一化操作
return {'video_x': new_video_x, 'clip_average_HR': clip_average_HR, 'ecg': ecg_label, 'frame_rate': frame_rate}
class RandomHorizontalFlip(object): #以0.5的概率水平翻转图像
"""Horizontally flip the given Image randomly with a probability of 0.5."""
def __call__(self, sample):
video_x, clip_average_hr, ecg_label, frame_rate = sample['video_x'], sample['clip_average_HR'], sample['ecg'], \
sample['frame_rate']
h, w = video_x.shape[1], video_x.shape[2] #实现图像的翻转
new_video_x = np.zeros((clip_frames, h, w, 3))
p = random.random()
if p < 0.5:
# print('Flip')
for i in range(clip_frames):
# video
image = video_x[i, :, :, :]
image = cv2.flip(image, 1) #翻转函数
new_video_x[i, :, :, :] = image
return {'video_x': new_video_x, 'clip_average_HR': clip_average_hr, 'ecg': ecg_label,
'frame_rate': frame_rate}
else:
# print('no Flip')
return {'video_x': video_x, 'clip_average_HR': clip_average_hr, 'ecg': ecg_label, 'frame_rate': frame_rate}
class ToTensor(object): #实例化即调用
"""
Convert ndarrays in sample to Tensors.
process only one batch every time
"""
def __call__(self, sample):
video_x, clip_average_hr, ecg_label, frame_rate = sample['video_x'], sample['clip_average_HR'], sample['ecg'], \
sample['frame_rate']
# swap color axis because
# numpy image: (batch_size) x depth x H x W x C
# torch image: (batch_size) x C x depth X H X W
video_x = video_x.transpose((3, 0, 1, 2)) # ((0, 4, 1, 2, 3))
video_x = np.array(video_x)
clip_average_hr = np.array(clip_average_hr)
frame_rate = np.array(frame_rate)
return {'video_x': torch.from_numpy(video_x.astype(np.float)).float(),
'clip_average_HR': torch.from_numpy(clip_average_hr.astype(np.float)).float(),
'ecg': torch.from_numpy(np.array(ecg_label).astype(np.float)).float(),
'frame_rate': torch.from_numpy(frame_rate.astype(np.float)).float()}
class UBFC(Dataset):
def __init__(self,scale,info_list,transform = None):
self.info_df = pd.read_csv(info_list,delimiter=' ',header=None)
# self.rootpath = rootpath
self.transform = transform
self.scale = scale
def __len__(self):
return(len(self.info_df))
def __getitem__(self, index):
# videopath = os.path.join(self.rootpath,str(self.info_df.iloc[index][0])) #视频路径 rootpath + 视频文件
# videopath = os.path.join(self.rootpath,str(self.info_df.iloc[index][0]))
videopath = str(self.info_df.iloc[index][0])
start_frame = self.info_df.iloc[index,1]
frame_rate = self.info_df.iloc[index,2]
clip_average_HR = self.info_df.iloc[index,3]
# ecg = self.info_df.iloc[index,5:5+clip_frames]
ecg = self.info_df.iloc[index, 5: ]
video_x = self.get_single_video(videopath = videopath,start_frame = start_frame)
sample = {'video_x': video_x, 'frame_rate': frame_rate, 'ecg': ecg,
'clip_average_HR': clip_average_HR}
if self.transform:
sample = self.transform(sample)
return sample
def get_single_video(self,videopath,start_frame): #从startframe开始,将160帧存到video中,video是一个numpy数组
pngpath = videopath
# video = np.zeros(clip_frames, self.scale, self.scale, 3) # numpy image: (batch_size) x depth x H x W x C;torch image: (batch_size) x C x depth X H X W
video = np.zeros((clip_frames, self.scale, self.scale, 3))
# print(video.shape)
startframe = start_frame
video_capture = cv2.VideoCapture(pngpath)
count = 0
while True:
# 读取一帧视频
ret, frame = video_capture.read()
frame = cv2.resize(frame, (self.scale, self.scale), interpolation=cv2.INTER_CUBIC)
# if frame == None:
# frame = video[count-1, :, :, :]
if count == startframe:
video[count, :, :, :] = frame
count = count + 1
if count == clip_frames:
break
return video
# 释放视频捕获对象和关闭显示窗口
video_capture.release()
for i in range(clip_frames):
image_name = 'face_'+ str(imageid+i)+'.jpg'
image_path = os.path.join(pngpath,image_name)
tmp_image = cv2.imread(image_path)
if tmp_image == None:
tmp_image = cv2.imread(self.rootpath + '20201016/1/face_1.png')
tmp_image = cv2.resize(tmp_image, (self.scale, self.scale),interpolation=cv2.INTER_CUBIC) #采用双立方插值法进行图像缩放,变为128*128维度
video[i,:,:,:] = tmp_image
return video