前言
四月份,在师兄的推荐下,报名参加了中兴捧月大赛。一开始只是为了混一个面笔试的资格(因为提交有效成绩即可免笔试),然后为了找一个简单的赛道,注册了几个号看了两三个赛道的题目。发现自己每个都不熟悉,然后就选了一个看起来比较小众的赛道(图灵派,音视频编解码),可能竞争压力会小一点(报一点侥幸)。
初赛
初赛因为就是为了混免笔试,因此就调库(不调库也没办法,我也不会,也没时间天天搞这个,毕竟还有科研任务)。
具体的初赛内容可以看前几篇文章。
https://blog.csdn.net/qq_37207042/article/details/116209375
复赛
这个赛道的复赛好像特别简单(其他赛道好像还有题),复赛就是面试,郭老师远程面试我们,然后基本没有问技术层面的,就问了一下思路。然后做了一些自我介绍,其实我就是念了一下简历,另外问了一些项目经验之类的以及就业意向。因为毕竟不是本专业学这个的,技术深度还是不够,只能问一些浅层的思路。本以为复赛混个奖品就可以了,意外的是,公布决赛名单时候竟然找到了我的牛客ID。
决赛
听说决赛还有参与奖品,而且还包差旅食宿(还有这种好事,当然要去)。然后领我意外的是,中兴对待比赛还挺认真的,赛务组安排的都很好,吃住等生活事务都安排的明明白白。
第一天去先是入住,然后等晚上发布赛题,发布完赛题会住处就开始开发了。
第二天,第三天都是开发,第三天下午5点提交,提交完开始做PPT,第四天答辩,第四天下午终极答辩(前六名),晚上颁奖典礼。
开发开始比较累的,我每天差不多都搞到晚上1点,搞了两天。吃住都在中兴自己的酒店,酒店还行吧,吃饭就酒店自助。
赛题
扯了那么多,毕竟这是个技术博客,还是谈一谈技术。
决赛(图灵派)赛题
图灵派主要涉及的就是音视频编解码,涉及一些深度学习方法。
决赛题目是VR视频编码算法的问题
背景
在VR领域中,对于传输带宽要求极高,需要对于视频进行进一步的压缩,
以降低传输带宽的需求,给用户更好的使用体验,业内常用 tile 编码方案进行传输。
问题1:tile权重预测
根据相关研究表明,对于 360°视频,大约有超过 30%的内容未被参与测试的人观看。因此,通过 tile 编码,可以对于不重要内容进行低权重编码,对于观看频率较高的采用高权重编码。
上图展示了一个全景图像中,用户关注的重点位置和图像。
在 tile 编码时,根据 saliency 的预测权重结果进行西能优化,有线高质量编码更容易被观看的 tile,对不容易被观看的区域视权重情况进行低质量快速编码。 从而完成对编码服务器的性能优化,降低服务成本。 根据附件中所提供的 40 个参与用户对于 40 个视频的头动数据集,对于 tile 编码算法进行设计和训练。
评分标准
在测试的 8 个视频中(赛程过程不提供),对于视频数据进行 tile 编码,对于所预测的权重结果和实际的头动数据集进行相关性计算。最后输出一个 txt 文 本文件,输出分为两列,分别为各个 tile 的观看命中次数和该 tile 对应的权重, 示例如所给压缩包中的 txt 文件。运行压缩包中 pcc.py 计算相关性,获取最终的 相关性评分。同时,对于本问题的解题思路,输出相关文档进行阐述。
问题2:tile编码方案优化
对于单个 tile 的编码方案进行优化。 在第一题全景 tile 编码的基础上,相同的视频内容,不同的编码方案(q、s、t)对主观感知质量的影响较大。不同的视频内容呈现出的规律有一定的差异。 可参考:
https://github.com/NJUVISION/QSTAR
https://vision.nju.edu.cn/20/86/c29466a467078/page.htm
请给出在给定码率下的最佳编码策略。
评分标准
针对测试的 8 个视频,以及第一题解出的 tile 数据,输出最佳编码方案。与理论最佳编码方案匹配的给分。同时,对于本问题的解题思路,输出相关文档进行阐述。
赛题思路
由于赛方给配备了一台服务器,虽然算力不高,但还是比我的小笔记本强的,所以首先就是配置服务器,服务器配置为ubuntu18.04 + cuda 11.0.2/Driver 450.80.02/CUDNN 8.0.4
由于之前没有用过linux系统和服务器,所以用的都是比较简单的操作:
主要操作在window PowerShell上完成,使用ssh指令完成连接,例如:ssh root@47.98.183.224
。
输入密码,由于linux键入后是不显示的,所以不要担心没输进去。
进入服务器后,左侧的提示符会变为root@xxxx:
。
另外比较简单的几个操作是必要的:
ls
:显示文件夹内容
cd xxx
:到xxx文件
cd ..
:回退到上一级文件夹
vim xxx
:编辑xxx,进入编辑模式后需要按i
进入insert编辑模式,按ESC退出模式,输入:wq
保存退出
python xxx.py
:执行python文件
unzip xxx.zip :解压xxx文件
至于工具的安装和python的安装就不啰嗦了,大多都是pip install xxx
以及apt install xxx
这些操作。
另外重要的就是主机与服务器的文件交互,这个交互需要在cmd命令提示薄。
下面是从服务器下载weg.txt文件
下面是从主机上传test.txt文件
主要是用了scp指令。
这些只是下酒菜,下面到正题,赛题应该如何解决。
为了尽可能容易理解并且少看文字,着重用图解释问题。
在球体中相同的角度对应的弧长相同,因此在坐标转换时根据经纬度等比例转换
由于用户关注的tile通常是关注图像中的人物或者物体、抑或是图像信息较多的部分(图像细节较多),因此考虑使用擅长图像感知的卷积神经网络进行训练建立
使用卷积神经网络实现对图像每块tile的权值预测,模型的输入为图像、输出为tile权重。
由于资源与时间限制,该卷积神经网络模型使用使用4层卷积层,两层映射层。
利用头动数据集与划分好的tile可以建立每一帧图像的tile权重(命中为1,未命中为0)
还有不明白的可以看下面文字补充解释:
问题1:tile权重预测
已知40个VR视频与40个参与用户观看40个视频的头动数据(头动数据给出的是用户观看的VR视频的经纬度)。目的是要根据已知的数据建立算法模型,以达到预测参与用户对视频的不同位置块的关注程度,也就是tile权重。
根据已知数据可以抽象一个简单的数学模型,输入设计为视频中的每一帧图像,输出为tile权重。由于用户关注的tile通常是关注图像中的人物或者物体、抑或是图像信息较多的部分(图像细节较多),因此考虑使用擅长图像感知的卷积神经网络进行训练建立(进一步可以考虑前后帧图像之间的关系,加入循环神经网络的元素,结合实现序列上的轨迹与视频内容以达到更好的预测)。
明确数学模型后,需要得到模型的输入与输出数据用于神经网络的训练。首先,对头动数据集进行坐标转换,将头动数据集的经纬度转换为图像中的坐标位置。由于头动数据的经纬度所表示的为球面的位置,球面高纬度的纬线周长小,低纬度的纬线周长大,因此根据经纬度对其进行等比例变换到平面坐标。其次,需要明确图像中的tile划分,由于VR视频本质是一个球形的图像形式,因此将其转化为平面图像后,其高纬度部分的图像也就是平面图像的上下两侧存在拉伸,拉伸会导致用户在VR图像中所关注的部分在平面图像下会变大。因此,将平面图像上下两侧的tile划分为较大的块,中部划分为较小的块。其中,上下部分与中部划分的线为60°纬度线,因为当纬度为60°时,纬线周长等于赤道线周长的一半,也就是 c o s ( 6 0 ∘ ) cos(60^{\circ}) cos(60∘)。
确定tile区块划分后,根据头动数据可以计算每一帧图像中用户所关注的tile位置,由此建立深度学习的Label集(用户关注的tile位置标签为1,其余区域为0)。
确定模型的输入输出后,建立卷积神经网络,(由于训练时间与资源限制,使用较为简便的卷积模型)。
由于图像数据较大,服务器的存储容量不足,将图像的分辨率调整为480*240,每次读取一个视频的图像数据进行训练,头动数据与图像帧的长短不一致的以起始数据为基准对齐进行截取训练。训练完成后的神经网络可以针对视频中的每一帧图像输出tile权重,若输出权重总和不为1,按比例调整到总和为1。
采用神经网络对每个视频中图像的tile权重预测求均值,得到每个tile块的权重;将坐标转换后的头动数据与划分的tile比对,得出每个tile的统计命中次数,写入最后输出的txt。
使用pcc.py求取根据头动数据得到的tile命中次数与深度学习算法给出的tile权重预测两个统计变量之间的皮尔逊相关系数,得出机器预测与用户观看之间的相关度作为评价指标。
问题2:tile编码方案优化
目前针对基于视点的全景视频的视频质量评价机制主要是基于SP、QP、TR等代表空间、时间、量化幅度、分辨率等的参数。建立这些参数与主观观看平均评分(MOS)之间的关系,形成客观视频评分模型。
为了达到在给定码率下尽可能的提供视频质量,可以依据tile的权重调整上述几中影响视频评分的参数。
上述评分模型中,设计三个参数,时间(t,帧速率)、空间(s,分辨率)、量化(q,量化质量)。若上述三个参数增加则视频的码率相应的增加,若其减小,则视频评分质量将下降。
依据评价模型对编码方案进行优化需要在上述参数与cost funtion也就是评价模型的值Q之间做trade-off。
假设量化值为q、帧速率为t、分辨率为s,码率为b,假定以下数学模型:
其中,
f
f
f为已知常数。
根据Q质量模型转化为寻优问题。
根据南京大学视觉实验室文章的描述,求取多个tile的视频质量时,直接对其进行加权求和即可得到最终的视频质量 。由此可以有以下式子:
根据第一问得到的权值的预测 ,结合上式,可以建立视频全局的质量评价模型与参数之间的关系,进而在码率约束条件下,可以利用拉格朗日乘数法求取多元函数极值,得到参数值。
另外,当tile划分的块较小时,可以更精确的定位到用户所关注的区域,但是当tile过小时,一个tile将无法覆盖用户的关注的视觉区域。
一般而言人眼的观察范围为180°,当观看视频时,关注的区域往往小于60°的范围,当视频分辨率为4k时,用户关注的区域大小大致为680x680。考虑到若tile的大小划分为680x680时,若用户关注的范围在tile边缘时,提高邻近的tile画面质量将造成码率资源浪费。应将680x680的块划分为4等分,甚至16等分,并且在进行基于视点的视频编码时,提高视点关注的tile以及邻近tile的画面质量。
代码
还是贴几行代码吧,只贴小部分仅供参考。
写的比较乱,将就着看吧。
# -*- coding: utf-8 -*-
"""
Created on Fri Jun 25 23:56:01 2021
@author: MYM
"""
'''将头动数据的经纬度转换为平面图像的坐标系,平面图像的大小通过读取图片得到。'''
import numpy as np
import os
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
for person in range(1,41):
folder_name = r"H:\tuning\head-tracking\Subject_" + str(person)
for file_name in os.listdir(folder_name):
# print(file_name)
img_path = r"H:\tuning\48Sequences" + "\\" + file_name[0:-4] + r"\0.jpg"
img = mpimg.imread(img_path)
length = img.shape[1]
highth = img.shape[0]
data = np.loadtxt(folder_name + '\\' + file_name)
data_num = len(data) # 数据数目
high = [0 for x in range(data_num)] # 初始化列表
leng = [0 for x in range(data_num)]
for i in range(data_num):
high[i] = ((90 - data[i][0]) / 90) * highth / 2
leng[i] = ((180 + data[i][1]) / 180) * length /2
new_folder_name = "new_Subject_" + str(person)
new_file_name = "new_" + file_name
isExists=os.path.exists(new_folder_name)
if not isExists:
os.mkdir(new_folder_name)
else:
print("文件夹已存在")
with open(new_folder_name + '\\' + new_file_name,"w") as f:
for j in range(data_num):
f.write(str(high[j]))
f.write(' ')
f.write(str(leng[j]))
f.write('\n')
import tensorflow as tf
from tensorflow.keras.layers import Conv2D,MaxPooling2D,Dense,Flatten,Activation
from tensorflow.keras import Input
from tensorflow.keras import Model
import os
import cv2
import numpy as np
'''建立并训练卷积神经网络(改自vgg16)'''
def conv2d_1(input_tensor,filters,kernel_size=3):
x=Conv2D(filters,kernel_size,padding='same',activation='relu')(input_tensor)
x=Conv2D(filters,kernel_size,padding='same',activation='relu')(x)
x=MaxPooling2D(strides=2)(x)
return x
def conv2d_2(input_tensor,filters,kernel_size=3):
x=Conv2D(filters,kernel_size,padding='same',activation='relu')(input_tensor)
x=Conv2D(filters,kernel_size,padding='same',activation='relu')(x)
x=MaxPooling2D(strides=2)(x)
return x
def vgg16(filters,input_tensor):
filter1,filter2,filter3,filter4=filters
x=conv2d_1(input_tensor,filter1)
x=conv2d_2(x,filter4)
return x
inputs=Input([240,480,3])
x=vgg16([64,64,64,8],inputs)
x=Flatten()(x)
x=Dense(32,activation='relu')(x)
x=Dense(32)(x)
outputs=Activation('softmax')(x)
model=Model(inputs,outputs)
model.summary()
model.compile(
optimizer="rmsprop",
loss='CategoricalCrossentropy',
metrics='mse',
)
# 读取数据
'''训练网络'''
folder_name = os.listdir("./48Sequences")
for name_f in folder_name :
file_name = os.listdir("./48Sequences/" + name_f)
img_num = len(file_name)
img_list = []
for x in range(img_num): # 读取图片
img = cv2.imread("./48Sequences/" + name_f + "/" + str(x) + ".jpg")
img_list.append(img)
img_data = np.stack(img_list, axis=0)
del img_list
for i in range(1,41):
label_path = "./label/"
label = np.loadtxt(label_path + str(i) + "_" + name_f + ".txt")
cut_num = min(img_num,len(label))
model.fit(img_data[0:cut_num,:,:,:],label[:cut_num,:],epochs =1)
model.save('my_model.h5')
'''预测步骤,并写入tile预测权重,对每张图片预测的权重取均值,每张图片32的权重,因为32个tile'''
ans_list = []
for name_f in folder_name :
file_name = os.listdir("./48Sequences/" + name_f)
img_num = len(file_name)
img_list = []
for x in range(img_num): # 读取图片
img = cv2.imread("./48Sequences/" + name_f + "/" + str(x) + ".jpg")
img_list.append(img)
img_data = np.stack(img_list, axis=0)
del img_list
ans = model.predict(img_data[:,:,:,:])
ans_list.append(ans)
ans_data = np.concatenate(ans_list,axis = 0)
del ans_list
total_num = ans_data.shape[0]
weg_sum = np.sum(ans_data,axis = 0)
weg = weg_sum/total_num
with open("weg.txt",'w') as f:
for x in weg:
f.write(str(x))
f.write('\n')
参考文献
[1]基于深度学习的视频编解码技术研究_邓宣
[2]全景视频处理与呈现架构和关键技术研究_罗莹
[3]3D_HEVC帧内编码优化算法研究_任海
[4]基于用户观看行为预测的全景视频高效编码与传输_戴震宇
[5]全景视频的质量评估研究_闵楠
[6]基于超高分辨率全景视频的VR系统研究_陈志杰
结语
大概思路就是这样,结束当天身体不舒服,没认真听得奖大佬的思路,不过后来听同学说好像也差不多,没有什么更特别的东西。
最后,本人由于不是视频编解码方向,只是突击了几天,如有描述不当或者错误,请大家指正,谢谢。
以上内容纯属原创,如有转载,请注明。