'harvitronix/five-video-classification-methods'视频分类-Code总结
- 环境要求
- 准备工作
- 提取视频帧
- CNN提取视频帧特征
- LSTM
- 验证模型
- 扩展
Code: https://github.com/harvitronix/five-video-classification-methods.
环境要求
requirements:
Keras>=2.0.2
numpy>=1.12.1
pandas>=0.19.2
tqdm>=4.11.2
matplotlib>=2.0.0
Pillow>=2.1.0
h5py>=2.7.0
项目文件目录概览:
准备工作
1)下载UCF101数据集压缩包并减压至data文件夹。
2)在data文件夹创建train、test 、sequences、checkpoints四个文件。
提取视频帧
1、UCF101数据集是由101类视频组成的,首先通过运行1_move_files.py将101类视频按照ucfTrainTestlist文件夹下的数据标签将101视频分别移至train、test文件夹。
Lable:
这里有个坑!!
1_move_files.py 第58行:
if not os.path.exists(filename):print("Can't find %s to move. Skipping." % (filename))continue# Move it.dest = os.path.join(group, classname, filename)print("Moving %s to %s" % (filename, dest))os.rename(filename, dest)print("Done.")
未将UCF101数据集读取!
修改后的代码:
filename_input = os.path.join('UCF-101', classname, filename)if not os.path.exists(filename_input):print("Can't find %s to move. Skipping." % (filename))continue# Move it.dest = os.path.join(group, classname, filename)print("Moving %s to %s" % (filename, dest))os.rename(filename_input, dest)print("Done.")
2、现在通过运行2_extract_files.py提取train、test文件夹中视频的视频帧,并生成一个CSV文件 。该CSV文件为之后特征提取及网络训练时数据读取提供帮助:
def get_data():"""Load our data from file."""with open(os.path.join('data', 'data_file.csv'), 'r') as fin:reader = csv.reader(fin)data = list(reader)return data
CNN提取视频帧特征
通过运行extract_features.py提取视频帧特征。
seq_length = 40
class_limit = 101
seq_length:每个视频段考虑的视频帧数目
class_limit:限制分类数
举个例子:一个视频段input_list有240帧,seq_length = 40,首先判断input_list是否大于seq_length即 assert len(input_list) >= seq_length
。然后将input_list与seq_length做地板除即: skip = len(input_list) // size
,本例中skip = 6,即每隔6帧从input_list中取一帧以列表的形式保存到output即:output = [input_list[i] for i in range(0, len(input_list), skip)]
,最终取得40帧。
def rescale_list(input_list, size):assert len(input_list) >= sizeskip = len(input_list) // sizeoutput = [input_list[i] for i in range(0, len(input_list), skip)]return output[:size]
在Imagenet上预训练好的InceptionV3卷积网络提取这40帧特征作为该视频段的特征。并将特征保存在sequences文件夹,numpy会自动在末尾添加 .npy。
path = os.path.join('data', 'sequences', video[2] + '-' + str(seq_length) + \'-features')
LSTM
将提取到的序列特征送入LSTM网络进行训练。通过运行 train.py生成 .hdf5文件,并将模型保存到checkpoints文件夹,并且会在logs文件夹生成一个 .log 训练日志文件,用来可视化训练过程中acc与loss的变化。
获取由CNN提取的序列特征:
def get_extracted_sequence(self, data_type, sample):"""Get the saved extracted features."""filename = sample[2]path = os.path.join(self.sequence_path, filename + '-' + str(self.seq_length) + \'-' + data_type + '.npy')if os.path.isfile(path):return np.load(path)else:return None
LSTM网络模型:
def lstm(self):model = Sequential()model.add(LSTM(2048, return_sequences=False,input_shape=self.input_shape,dropout=0.5))model.add(Dense(512, activation='relu'))model.add(Dropout(0.5))model.add(Dense(self.nb_classes, activation='softmax'))return model
用来可视化训练过程的plot_trainlog.py:
import csv
import matplotlib.pyplot as pltdef main(training_log):with open(training_log) as fin:reader = csv.reader(fin)next(reader, None) # skip the headeraccuracies = []Val_acc = []cnn_benchmark = [] # this is ridiculousfor epoch,acc,loss,val_acc,val_loss in reader:accuracies.append(float(acc))Val_acc.append(float(val_acc))cnn_benchmark.append(0.65) # ridiculousplt.plot(accuracies)plt.plot(Val_acc)plt.plot(cnn_benchmark)plt.show()if __name__ == '__main__':training_log = 'data/logs/lstm-training-1617251893.3342032.log'main(training_log)
绿线:cnn_benchmark
橘黄线:Val_acc
蓝线:accuracies
验证模型
通过运行validate_rnn.py将保存在checkpoints文件夹的模型加载进来验证模型准确度。结果如图:
扩展
若要将一段视频进行分段处理,十帧作为一个序列,首先送入CNN提取基础特征,后送入LSTM提取时间-空间特征,会遇到什么问题?能否完成视频分段任务?是否过拟合?模型鲁棒性如何?