当前位置: 首页 > news >正文

视频质量评价SimpleVQA

目录

一、研究意义

例子

二、介绍

三、文章解读

3.1 论文动机

3.2论文思路

3.3方法

3.3.1网络框架

3.3.2公式解读

3.3.3核心创新

3.3.4理解

!!!作者对模型的改进

本人算法框体

3.3.5实验细节:

四、代码复现

4.1代码文件简介

4.2数据集下载

4.3环境

4.4测试训练

4.4.1复现结果

五、后话

本文所涉及所有资源均在 传知代码平台可获取。

一、研究意义

用户生成内容(UGC)视频的质量评估对于确保终端用户的观看体验具有重要作用。典型的UGC视频如抖音视频、游戏视频等等。人们在观看这些视频的时候都希望有一个清晰的、稳定的视频带来更好的用户体验。

例子

如下图,模糊的视频让人没有观看欲望,但是这个草原的视频会吸引人们的注意甚至想去身临其境。所以,视频质量评价算法模型的意义在于筛选出高质量的视频供人们观看,并且为下游的视频去模糊、视频画质提升任务做上游工作。

二、介绍

A Deep Learning based No-reference Quality Assessment Model for UGC Videos是一篇CCF A类会议ACM MM2023年上发表的文章。

  • 源码中给出了LSVQ数据集上的训练的模型,本文补充KoNViD、youtube_ugc数据集上的训练模型
  • 源码中REDME文件中只给出了如何运行代码,本文对代码进行详细解读,解释每一块的作用
  • 本文提供多个数据集的下载连接,方便读者快速下载使用

三、文章解读

3.1 论文动机

对于视频质量评价而言,视频的质量主要取决于视频的内容、视频的稳定性、视频有无失真。所以基于上述内容,本文从空间-时间进行建模以对视频的质量进行整体评价。

3.2论文思路

提出一个时空模型对视频的图像和时间信息进行处理,最终得到视频预测的质量分数。

  • 视频抽帧处理:将视频每一秒抽取一帧关键帧
  • 空间信息处理:使用ImageNet上预训练的ResNet提取视频的空间信息
  • 时间信息处理:使用冻结参数的slowfast网络提取时间信息
  • 时空信息融合:使用concatenate连接时空特征
  • 质量分数回归:使用多层感知机MLP进行质量回归

3.3方法

3.3.1网络框架

  1. Input video即是数据集中训练数据,将输入视频进行Frame extraction,代码中是每一秒抽取第一帧作为视频的关键帧,并且只使用8秒,不足8秒的视频复制前面的帧。所以,最终一个视频得到的帧数为8
  2. Chunks即代表一个视频的所有帧,2D frames代表抽出来的帧。将Chunks馈送到Motion feature extraction模块,将2D frames馈送到Spatial feature extraction模块,分别进行特征提取
  3. Motion feature extraction模块是参数冻结的,可以直接使用训练好的参数进行特征提取,这个模块其内涵是使用3D CNN,Spatial feature extraction模块是可训练的,这个模块其内涵是预训练的ResNet,预训练的ResNet可以帮助模型提取充分的语义信息,并且将4个stage的特征图进行全局平均值和标准差池化,以满足多尺度视频
  4. 使用cat操作进行特征融合,就是很简单的在通道维度进行特征拼接。再到MLP进行质量回归,MLP也是需要训练的

3.3.2公式解读

  1. 抽取关键帧:将视频每一秒提取关键帧,对于N秒视频就抽取N帧,得到帧集合。代码中每一个视频都归一化抽取8帧。

import numpy as np
import os
import pandas as pd
import cv2#    /    home/dataset/LSVQLSVQ video_name  LSVQ_image
def extract_frame(videos_dir, video_name, save_folder):
    filename = os.path.join(videos_dir, video_name + '.mp4')
    video_capture = cv2.VideoCapture()
    video_capture.open(filename)
    cap = cv2.VideoCapture(filename)    video_length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    video_frame_rate = int(round(cap.get(cv2.CAP_PROP_FPS)))    video_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))  # the heigh of frames
    video_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))  # the width of frames    # 按短边进行等比例缩放
    if video_height > video_width:
        video_width_resize = 520
        video_height_resize = int(video_width_resize / video_width * video_height)
    else:
        video_height_resize = 520
        video_width_resize = int(video_height_resize / video_height * video_width)    dim = (video_width_resize, video_height_resize)    video_read_index = 0    frame_idx = 0    video_length_min = 8    for i in range(video_length):
        has_frames, frame = video_capture.read()
        if has_frames:
            # key frame
            if (video_read_index < video_length) and (frame_idx % video_frame_rate == 0):  # 保存 帧数/帧率个帧,每次保存第一帧
                read_frame = cv2.resize(frame, dim)
                exit_folder(os.path.join(save_folder, video_name))
                cv2.imwrite(os.path.join(save_folder, video_name,
                                         '{:03d}'.format(video_read_index) + '.png'), read_frame)
                video_read_index += 1
            frame_idx += 1    if video_read_index < video_length_min:  # 不足video_length_min个帧,直接复制前面的一帧
        for i in range(video_read_index, video_length_min):
            cv2.imwrite(os.path.join(save_folder, video_name,
                                     '{:03d}'.format(i) + '.png'), read_frame)    returndef exit_folder(folder_name):
    if not os.path.exists(folder_name):
        os.makedirs(folder_name)    returnif __name__ == "__main__":
    # train subset
    filename_path = '/data/user/gbb/SimpleVQA-main/data/LSVQ_whole_train.csv'
    column_names = ['name', 'p1', 'p2', 'p3',
                    'height', 'width', 'mos_p1',
                    'mos_p2', 'mos_p3', 'mos',
                    'frame_number', 'fn_last_frame', 'left_p1',
                    'right_p1', 'top_p1', 'bottom_p1',
                    'start_p1', 'end_p1', 'left_p2',
                    'right_p2', 'top_p2', 'bottom_p2',
                    'start_p2', 'end_p2', 'left_p3',
                    'right_p3', 'top_p3', 'bottom_p3',
                    'start_p3', 'end_p3', 'top_vid',
                    'left_vid', 'bottom_vid', 'right_vid',
                    'start_vid', 'end_vid', 'is_test', 'is_valid']    dataInfo = pd.read_csv(filename_path, header=0, sep=',', names=column_names, index_col=False, encoding="utf-8-sig")    video_names = dataInfo['name']
    n_video = len(video_names)
    videos_dir = '/data/dataset/LSVQ'    save_folder = 'LSVQ_image'
    for i in range(n_video):
        video_name = video_names.iloc[i]
        print('start extract {}th video: {}'.format(i, video_name))
        extract_frame(videos_dir, video_name, save_folder)

  1. 提取时空特征:空间特征提取就是对每一张的图像进行特征提取,时间特征提取就是对整个视频进行处理,提取视频的时间信息。空间特征提取器公式中使用fw.空间特征提取器是在Imgenet上预训练的Resnet50,fwk是提取出的特征图。

时间特征提取器是预训练的Slowfast网络,时间特征提取器论文中公式使用MOTION表示.

  1. 特征融合与质量回归:使用最简单的concatnate也可以有很好的效果

使用多层感知机MLP进行质量回归

3.3.3核心创新

  1. 提出了一种有效、高效的基于深度学习的UGC VQA模型,该模型包括特征提取模块、质量回归模块和质量池模块。该模型不仅在五个流行的UGC VQA数据库上取得了显著的性能,而且具有较低的计算复杂度,非常适合实际应用。
  2. 特征提取模块提取两种质量感知特征:空间失真的空间特征和运动失真的时空特征,其中空间特征通过端到端的方式从视频帧的原始像素中学习,时空特征通过预训练的动作识别网络来提取。
  3. 提出了一种多尺度质量融合策略来解决不同分辨率的质量评价问题,其中多尺度权重是通过考虑观看环境信息从人类视觉系统的对比度敏感度函数中获得的。

3.3.4理解

以下是我自己对这个模型的理解解释图,对输入维度做了一定解释。时间特征流由于多了时间信息会比空间特征流多一个维度特征。所有在进行cat操作的时候需要降维。降维处理:先进行全局平均池化再将帧数维度和通道维度融合成一个维度。

!!!作者对模型的改进

举个例子:同样的设备,同一个摄影师,同一个模特,拍照姿势也一样,只有背景不同,保持单一变量的条件下。站在垃圾堆前面拍摄的视频和站在来福士前面拍摄的视频,人们在进行主观评价做数据标注时,肯定会觉得在来福士前面拍摄的更好看。因为背景的美学已经开始影响视频的质量分数了。所以,本人从这个方面对论文模型进行改进。

本人算法框体

  1. 视频抽帧
  2. 空间信息提取分为两个分支:第一、美学特征提取网络;第二、技术特征提取网络
  3. 时间信息提取
  4. 特征融合与质量回归

由于本人改进主要针对图像美学分支,从而在这里重点概述。

美学特征提取网络:

特征提取网络使用Resnet50框架,使用现在图像美学质量评价领域最大的数据集AVA数据集进行预训练。然后加载预训练权重。再使用图像美学数据集AADB进行美学属性回归,从而使网络具有图像美学特征提取能力。保存训练最好的权重。1、2、3、4、5、6个特征分别使AADB数据集中的6种美学客观属性。得到美学特征提取网络后,将视频关键帧馈送到美学特征提取网络中提取美学特征。

注:附件中有美学分支详细代码

3.3.5实验细节:

  • 损失函数:L1RankLoss
  • 优化器:Adam
  • 超参数设置如下:

parser = argparse.ArgumentParser()
    # input parameters
    parser.add_argument('--database', type=str, default='LSVQ')  # LSVQ
    parser.add_argument('--model_name', type=str, default='UGC_BVQA_model')  # UGC_BVQA_model
    # training parameters
    parser.add_argument('--conv_base_lr', type=float, default=1e-5)
    parser.add_argument('--decay_ratio', type=float, default=0.9)  # 0.9
    parser.add_argument('--decay_interval', type=int, default=2)  #多少步长来控制权重衰减
    parser.add_argument('--n_trial', type=int, default=0)
    parser.add_argument('--results_path', type=str)
    parser.add_argument('--exp_version', type=int, default=0)  # 0
    parser.add_argument('--print_samples', type=int, default=1000)
    parser.add_argument('--train_batch_size', type=int, default=8) #16
    parser.add_argument('--num_workers', type=int, default=6)  # 6
    parser.add_argument('--resize', type=int, default=520)
    parser.add_argument('--crop_size', type=int, default=448)
    parser.add_argument('--epochs', type=int, default=20)
    # misc
    parser.add_argument('--ckpt_path', type=str, default='ckpts')   #用于存储最好的效果
    parser.add_argument('--multi_gpu', action='store_true')  # 当命令行中触发multi_gpu参数时,返回为True,没有触发的时候返回False
    parser.add_argument('--gpu_ids', type=list, default=None)
    parser.add_argument('--loss_type', type=str, default='L1RankLoss')    config = parser.parse_args()

四、代码复现

在附件中下载代码文件,先看到对应的代码文件结构,以下是代码文件简介。

4.1代码文件简介

  1. 文件夹Aes存放图像美学代码
  2. 文件夹ckpts存放权重
  3. 文件夹data存放数据集的csv文件
  4. datasettimages_originalsize存放的图像美学数据集AADB
  5. 文件夹model存放模型
  6. data_loader.py数据集加载处理代码
  7. extract_frame_***.py抽取各个数据集的帧代码
  8. extract_slowfast_feature_***.py抽取各个数据集的时间特征代码
  9. test_on_pretrained_model.py和test_demo.py分别是美学和视频的测试代码
  10. 其他文件都是包文件或者本人该模型的测试代码

4.2数据集下载

数据集文件数据较大,自行下载

视频质量评价目前最大的数据集:LSVQ、Konvid1k

图像美学数据集:AVA、AADB注:数据集下载链接放在附件README中!

4.3环境

  • python=3.8.8
  • torch=1.10.2
  • torchvision=0.11.3
  • scipy

4.4测试训练

以抽帧模块为演示。

  1. 安装相应的包代码中import部分,可以在终端使用pip install安装(简单方便)

  1. 数据集路径修改,其他代码类似操作,将路径修改到自己对应文件

  1. 运行,右键run或者终端输入python extract_frame_LSVQ.py命令

4.4.1复现结果

本人挂在后台运行。实验结果如下

五、后话

附件

  • 有源码中没有的新的模型
  • 有源码没有的模块详细注释
  • 有源码没有的模型权重

原文:A Deep Learning based No-reference Quality Assessment Modelfor UGC Videos github代码

感觉不错,点击我,立即使用

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 力扣反转链表系列【25. K 个一组翻转链表】——由易到难,一次刷通!!!
  • 时序预测 | Python实现KAN+LSTM时间序列预测
  • elasticsearch实战应用
  • 缓存的思考与总结
  • 《拿下奇怪的前端报错》:nvm不可用报错`GLIBC_2.27‘‘GLIBCXX_3.4.20‘not Found?+ 使用docker构建多个前端项目实践
  • 计算机网络:概述 --- 体系结构
  • ML 系列:机器学习和深度学习的深层次总结(08)—欠拟合、过拟合,正确拟合
  • QT中添加资源文件(一看就会)
  • 开源实时多模态AI聊天机器人Moshi,语音对话延迟低至200毫秒!
  • MySQL面试题——第一篇
  • 信息学奥赛:青少年编程的高光舞台,通向未来科技的敲门砖
  • text2sql(NL2Sql)综述《The Dawn of Natural Language to SQL: Are We Fully Ready?》
  • 【游戏引擎】C++自制游戏引擎 Lunar Game Engine
  • spring与springmvc整合
  • Stable Diffusion 使用详解(13)--- 3D纹理增强
  • [iOS]Core Data浅析一 -- 启用Core Data
  • CentOS从零开始部署Nodejs项目
  • JavaScript工作原理(五):深入了解WebSockets,HTTP/2和SSE,以及如何选择
  • LeetCode刷题——29. Divide Two Integers(Part 1靠自己)
  • Netty+SpringBoot+FastDFS+Html5实现聊天App(六)
  • react 代码优化(一) ——事件处理
  • SAP云平台运行环境Cloud Foundry和Neo的区别
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • Webpack 4x 之路 ( 四 )
  • win10下安装mysql5.7
  • 近期前端发展计划
  • 如何胜任知名企业的商业数据分析师?
  • 三栏布局总结
  • 用jquery写贪吃蛇
  • 追踪解析 FutureTask 源码
  • ​如何在iOS手机上查看应用日志
  • ​十个常见的 Python 脚本 (详细介绍 + 代码举例)
  • ​一、什么是射频识别?二、射频识别系统组成及工作原理三、射频识别系统分类四、RFID与物联网​
  • ​直流电和交流电有什么区别为什么这个时候又要变成直流电呢?交流转换到直流(整流器)直流变交流(逆变器)​
  • #php的pecl工具#
  • #数据结构 笔记三
  • #我与Java虚拟机的故事#连载02:“小蓝”陪伴的日日夜夜
  • $.ajax中的eval及dataType
  • (2021|NIPS,扩散,无条件分数估计,条件分数估计)无分类器引导扩散
  • (AtCoder Beginner Contest 340) -- F - S = 1 -- 题解
  • (c语言)strcpy函数用法
  • (function(){})()的分步解析
  • (Java)【深基9.例1】选举学生会
  • (Oracle)SQL优化技巧(一):分页查询
  • (编程语言界的丐帮 C#).NET MD5 HASH 哈希 加密 与JAVA 互通
  • (附源码)springboot课程在线考试系统 毕业设计 655127
  • (规划)24届春招和25届暑假实习路线准备规划
  • (四)Linux Shell编程——输入输出重定向
  • (五)MySQL的备份及恢复
  • (一)SpringBoot3---尚硅谷总结
  • ****** 二十三 ******、软设笔记【数据库】-数据操作-常用关系操作、关系运算
  • **PHP二维数组遍历时同时赋值
  • .mysql secret在哪_MYSQL基本操作(上)
  • .net core使用EPPlus设置Excel的页眉和页脚
  • .NET MAUI Sqlite数据库操作(二)异步初始化方法