ffmpeg如何在结尾添加帧_一种“视频帧对齐”的测试方案实践

点击蓝字?关注【测试先锋】,不再迷路!一起成为互联网测试精英,前瞻测试技术~663e3c6ad3335b1a91b1b6ec12f05cfc.png导语全参考清晰度测算的时候,输入两个视频帧序列,但是视频帧序列没有对齐,怎么知道丢了哪帧?又怎么知道补回哪一帧?今天介绍一种直播视频帧的对齐方案,如果您有更好的方法,欢迎在公众号下方留言联系作者探讨交流(文章留言近期开放),再次感谢您的关注和阅读。ae0305a9539c2c4f60ddd0ff32adbeea.png1/  问题背景全参考测算视频质量,广泛存在在视频业务场景。开始算法计算时,是需要仔细的对齐这一系列的帧再能做计算的,因为全参考的计算原理是根据两张相同场景的图片数据,做比较测算。仔细想想:“帧对齐”其实这是一个挺麻烦的事儿,为什么这么说?因为:第一、帧非常多(手机端直播业务一般在 18-25fps,pc 直播业务一般 60fps),想让人工挑出到底哪帧丢了,这是非常不现实的。cce274d2fed89cf52a18878acd8704f3.png第二、由于人眼的一个重要特性——视觉惰性,表现在人眼会存在一个视觉暂留,肉眼基本看不出来连续两帧的区别。人眼可以保留 0.1-0.4秒的影像。所以每一个视频都是一个非常快的“走马灯”,人们是很难通过图像特征来区别每一帧。

1e3f272bd3849e8d339244bb83216e5d.png

所以,“帧对齐”这个问题,拆解为两个问题:如何识别每一个帧+找到未对齐的帧 这两个问题。根据上述分析,我们可以拿到具体的折损测试方案:

           de601b93ce8a5c0061f669439cdde46b.png

输入源为两个视频,分别是“原视频”和“待比较视频”(折损视频),首先将两个视频进行拆帧处理;将视频处理为一系列的图片帧文件,然后进行帧对齐处理(将帧的分辨率处理成一致的分辨率,将丢帧补齐,将卡帧删掉并记录帧号),输出两列对齐后的视频帧序列,再合成对齐帧后的视频序列,再进行VMAF,PSNR等全参考得分的分数计算。

了解了上述的测试方案,我们来看下每一个部分都是怎么解决的。

2/ 如何识别每一帧 识别帧的两个思路:物理识别与代码识别。物理识别是指,放大每一帧之间的区别,或者专门打上帧的标签来识别不同的图片。代码识别目前笔者没有找到比较有效的方法来区别两帧,因为在截取为 jpg 时这个信息已经丢失了。所以这里还是倾向于“物理识别”方案。这里根据两位测试前辈(在这特别感谢 eriel,austin)曾经尝试过的经验,有两种方法:方法一:给每一帧标记物理序号至某一个固定位置

ff810608dafabcb88e4210e2ae7205ed.png

方法二:给每一帧上方标记一个黑白条形码至某一个固定位置,再来读黑白条形码

f317add9f95ed62dc9c61eafdc0ea300.png

然后,再通过代码/工具识别这个更容易识别的物理特征。总之,上述两种方法都是为了放大帧和帧之间的区别。因为篇幅关系,现在我介绍一下方法一的方案具体怎么做,也给出一些代码/命令,感兴趣的小伙伴可以动手试一试:方案 1:先画后切-  step1:使用ffmpeg - drawtext 命令给整个视频画帧号
ffmpeg -i input.mp4 -vf drawtext=fontcolor=black:box=1:boxcolor=white:fontsize=40:fontfile=msyh.ttf:line_spacing=7:text=%{n}:x=0:y=0 -vframes 600  -y -qscale 0  out.mp4
     这样,你就得到了一个画好了帧号的视频:

af8c48f9f5600389f92f0aa00f2cd9d4.gif

然后再执行切帧操作,这里关键参数是
text={n}
这个写法是表示标注的是帧号。更多写法可以参考 ffmpeg 说明书。    -  step 2:切帧命令 ffmpeg image2  或 opencv 切帧ffmpeg image2 命令:
ffmpeg -i out-1.flv -r 1 -q:v -f image2 ./result/image-%3d.jpeg
不知道为什么使用 ffmpeg 我总觉得切出来的损耗很高(可能是使用的无损参数有点问题),所以我用 opencv 实现了一把,这种方案看起来损耗至少看起来没那么大(opencv实现代码如下): 
def cutFrame(srcFilePath,dstFolderPath):    srcFileName = srcFilePath.split('/')[-1].split('.')[0]    print(srcFileName)    dstFolderPath = dstFolderPath + srcFileName + '/'    times=0    #提取视频的频率,每1帧提取一个    frameFrequency=1    if not os.path.exists(dstFolderPath):        #如果文件目录不存在则创建目录        os.makedirs(dstFolderPath)    camera = cv2.VideoCapture(srcFilePath)    count = 0    while True:        times+=1        res, image = camera.read()        if not res:            print('error ! not res , not image')            break        countMax = 400        if times%frameFrequency==0 and count < countMax:            count+=1            print(count)            cv2.imwrite(dstFolderPath + srcFileName + '-'+ str(times-1)+'.jpg', image)            print(dstFolderPath + srcFileName +'-'+ str(times)+'.jpg')    print('图片提取结束')    camera.release()
经过上面两步,你将得到:
             - 一个标记了帧号的视频文件- 每一帧都有帧号的图片文件集但在后面的识别图片帧号会遇到一个新的坑:你不知道需要具体需要预测的图片的坐标是多少(因为你在输入预测图片时,需要知道图片的具体 x,y,而不是整张图片输入),也就是说 个位数帧,和十位数帧,和百位数帧,具体的 x,y 都是不一样的,分别是(14,22);(28,22);(42,22) :

38f96a407d927087ad0836cfd6e3f8f6.png4a59702dec1616c91bfacbc64d7c7228.png529609fed38aad754da339de972fc92f.png

因为你在预测的时候,不知道具体帧号,所以这个预测位置你不好判断是多长。如果你一刀切使用最长的(42,22),个位数帧的空余位置,因为你的模型/ocr 工具 没有学习过,所以会预测出奇怪的字符串。为了解决这个裁切数字准确的问题,我们有了第二个方案:更好的方案 2先切后画-  step 1:切帧命令 ffmpeg image2  或 opencv 切帧同上文方案 1-  step 2:切好的帧画上帧号,具体命令和方案 1 不一样(text 参数)
ffmpeg -i test.jpg -vf drawtext=fontcolor=black:box=1:boxcolor=white:fontsize=40:fontfile=msyh.ttf:line_spacing=7:text='00001':x=0:y=0 -vframes 600  -y -qscale 0  output.jpg
这里的 text 参数
 text = '00001'
,可以通过读step1 的名字拿到(切视频的时候的视频帧是命名是可以控制的,比如 frame-01.jpg,你可以拿到'01',然后再通过格式化%03d 的方式,对齐帧号为“00001”,再填到命令中去,这样所有的帧号就都是 4 位数甚至更多,从而做到了对齐。)经过上面两步,你将得到:- 一个标注了帧号的且对齐了位数的图片集

ed27050a67dac116c76ef527e7eda580.png5b807f96adeb0aa0a4e7d5b460d70e8c.pngf971b12d5dd757c65b1ce2dfec196483.png

看到这样的图片标注集合,别提多舒服了~可是,下一个问题来了,如果使用方案 2,那“带标记的视频源”如何拿到呢?这是折损的初始输入部分。这个问题简单,你可以通过 opencv 来合成无声视频片段,这个也是几乎视觉无损的:
def frameToAvi(srcFolderPath,dstFolderPath):        for root, dir, files in os.walk(srcFolderPath):            count = 0            for f in files:                #print(f)                if not f.endwith('jpg'):                    continue                else:                    count += 1            fourcc = cv2.VideoWriter_fourcc(*'XVID')            videoWriter = cv2.VideoWriter(dstFolderPath+'/'+srcFolderPath.split('/')[-1]+'.avi', fourcc, 18, (1088,1920)) ## 一定要对上  宽高,不然写不进去   3506463247-106.avi            for i in range(0,count):                img12 = cv2.imread(root + '/' + '1-' + str(i) + '.jpg')                print(root + '/' + '1-' + str(i) + '.jpg is reading')                cv2.imshow('img',img12)                cv2.waitKey(1)                videoWriter.write(img12)                print(root + '/' + '1-' + str(i) + '.jpg is succeed')            videoWriter.release()            print('over')
上面的代码拼图片链接,使用 os.path.join() 会更好,另外值得一提的是:
videoWriter = cv2.VideoWriter(dstFolderPath+'/'+srcFolderPath.split('/')[-1]+'.avi', fourcc, 18, (1088,1920)) ## 一定要对上 fps 宽高,不然写不进去   3506463247-106.avi
cv2.videoWriter 方法,要写生成视频的宽高,这里的宽高数据要从你切的图里面获得(opencv可以得到,你也可以打开右键图片简介读取),批量视频就写死,各种不同的视频就读一张图。fps 根据你的需求来调整,一切参数尽量模拟原未标号的视频。到这里,方案 2 就全部结束了。3/使用 OCR 识别模型/调用 OCR 工具,识别帧号未对齐的帧 经过part2 的一系列骚操作,你下一步需要做的就是使用 ocr 工具来识别帧号,工具如何制作和使用已经在我的前期公众号推送中说明了:《“自己动手,丰衣足食”——训练一个属于自己的OCR文字识别库(mac环境)》,我把我遇到的坑和解决方案都记录下来了;当然如果你嫌麻烦,你也可以使用在线的ocr 转换服务。4/ 丢帧的 2 种处理方法测试过程中发现不同流的丢帧处理方法不太一样,一共有 2 种类型,一种是传输过程中直接丢弃,另一种是延续上一帧,也就是说: - 传输过程中直接丢弃的方案,收集到的帧号是: 0,1,2,3,5 ... 丢了第 4 帧。- 传输过程中延续上一帧的方案,收集到的帧号是:0,1,2,3,3,5... 丢掉的第 4 帧用上一帧来弥补。值得一提的是,丢帧率和网络情况也是强相关的,如果对丢帧率的专项测试,需要将自己的网络情况仔细整理并划分类别(或者专业的网络损失实验室)来做这项专项测试。对帧率等指标感兴趣的朋友,可以参考我的这篇往期文章:《码率、分辨率、帧率那点事儿》对于全参考系算法的一些坑,我们下篇再讲,2020 年十一双节欢庆,预祝各位读者朋友节日快乐,月圆人团圆~!?

注:以上图片部分来自互联网,如有侵权请后台联系公众号,会第一时间删除,谢谢!ae0305a9539c2c4f60ddd0ff32adbeea.png974d0e3d1cfb335c454490e96b94c94a.pngedef4d0d973fdd705ac4d32bf97de86c.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/245518.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java mongo分组统计_探秘 Dubbo 的度量统计基础设施 - Dubbo Metrics

对服务进行实时监控&#xff0c;了解服务当前的运行指标和健康状态&#xff0c;是微服务体系中不可或缺的环节。Metrics 作为微服务的重要组件&#xff0c;为服务的监控提供了全面的数据基础。近日&#xff0c;Dubbo Metrics 发布了2.0.1版本&#xff0c;本文将为您探秘 Dubbo …

python可以做运动控制卡吗_今天,终于明白了运动控制器和运动控制卡的区别

原标题&#xff1a;今天&#xff0c;终于明白了运动控制器和运动控制卡的区别 运动控制器是完整的、独立的硬件平台&#xff0c;运动控制卡则需要一个载体(一个系统运行平台&#xff0c;必须基于PC)。 一、从安装使用方式来看 运动控制卡&#xff0c;一般是PCI插槽的&#xff0…

电子计算机技能竞赛数据,2015年浙江省中等职业学校计算机应用技术专业学生职业技能大赛“计算机检测维修与数据恢复”赛项规程.doc...

2015年浙江省中等职业学校计算机应用技术专业学生职业技能大赛“计算机检测维修与数据恢复”赛项规程.doc还剩8页未读&#xff0c;继续阅读下载文档到电脑&#xff0c;马上远离加班熬夜&#xff01;亲&#xff0c;喜欢就下载吧&#xff0c;价低环保&#xff01;内容要点&#x…

设备的dpr_湘潭污水处理设备_处理污水设备生产厂

湘潭污水处理设备_处理污水设备生产厂?氮磷过度排放导致水体富营养化仍是全球关注的水污染热点问题, 而对于传统城市污水处理厂来说, 污水的深度脱氮除磷和同步达标排放仍是需要攻克的难点问题.传统脱氮除磷工艺存在脱氮与除磷对有限碳源的竞争、硝化反应产物对厌氧释磷的抑制…

奥鹏大工17秋计算机文化基础,大工17秋《数字电路与系统》在线作业100分满分答案...

大工17秋《数字电路与系统》在线作业1一、单选题&#xff1a;1.实现与运算功能的逻辑器件称为( )。 (满分:5)A.与门B.或门C.非门D.与或门正确答案:——A——2.变量每增加一个&#xff0c;其函数卡诺图的小格数就增加( )倍。 (满分:5)A.0.5B.1C.1.5D.2正确答…

git 32位_编译64位的BorderlessGaming

BorderlessGaming确实是一款很好用的工具,我主要用来把AS的模拟器全屏,来把Surface当安卓平板用,但是这东西的官方Release和Steam版本都是32位的,不过好在它开源,那就自己动手魔改一份吧首先把源码clone到本地git clone https://github.com/Codeusa/Borderless-Gaming.git用VS打…

十分钟计算机说课稿,足球十分钟说课稿范文(精选3篇)

足球十分钟说课稿范文(精选3篇)作为一位杰出的老师&#xff0c;常常要写一份优秀的说课稿&#xff0c;编写说课稿助于积累教学经验&#xff0c;不断提高教学质量。怎样写说课稿才更能起到其作用呢&#xff1f;以下是小编为大家整理的足球十分钟说课稿范文&#xff0c;欢迎阅读与…

主叫号码未显示怎么设置_微信未授权抖音,应该怎么设置?

微信未授权抖音&#xff0c;应该如何设置&#xff1f;这篇文章&#xff0c;笔点酷玩手把手教你完成。首先我们要明确&#xff0c;这种设置属于将微信账户的授权给第三方&#xff0c;用于统一身份的登录&#xff0c;需要用户自己手动授权“绑定”&#xff0c;也可以随时进行解绑…

eclipse没有日志_「开源资讯」Jboot v3.3.6 发布,更强大的控制台请求日志

Jboot 是一个基于 JFinal、JFinal-Undertow、Dubbo、Seata、Sentinel、ShardingSphere、Nacos 等开发的微服务框架&#xff0c;帮助开发者降低微服务开发门槛。同时完美支持在 idea、eclipse 下多 maven 模块&#xff0c;对 java 代码、html、css、js 等资源文件进行热加载。爽…

计算机地址码特点,电脑摇头灯的地址码的设定问题你必须要注意的

原标题&#xff1a;电脑摇头灯的地址码的设定问题你必须要注意的在上一期文章中&#xff0c;我们广州舞台灯光设备批发厂家歌斯达为大家分享了电脑摇头灯的供电电源问题和信号线问题之后&#xff0c;这一次的文章&#xff0c;我们将继续为大家分享更多关于电脑摇头光束灯的相关…

java项目经验怎么写_模具工简历项目经验怎么写

项目经验(案例一)项目时间&#xff1a;2015-04 - 2015-05项目名称&#xff1a;活动策划项目描述&#xff1a;项目介绍通过策划一系列的活动来提高家具店的知名度&#xff0c;从而拔高家具店正式开业后的销售额。我的职责协助经理完成开业前后的活动策划以及提出个人见解&#x…

freemaker if 多个条件_第4天|14天搞定Vue3.0,条件渲染和template

所谓的条件&#xff0c;指的就是满足什么条件&#xff0c;允许做什么事&#xff0c;不满足时&#xff0c;是不允许做的。如共享单车&#xff0c;规定满12周岁或以上才可以骑行&#xff0c;没满的则不被允许。学每门编程语言&#xff0c;条件语句都是必须熟练掌握的&#xff0c;…

服务器用户配置文件在哪里找,管理远程桌面服务的用户配置文件

用户配置文件描述特定用户的配置&#xff0c;包括用户的环境和首选项设置。除非在 RD 会话主机 服务器环境中认真地规划和管理用户配置文件&#xff0c;否则&#xff0c;用户配置文件可能会变大&#xff0c;在用户连接到 RD 会话主机 服务器时可能会造成问题&#xff0c;例如登…

matlaba绘制gps星空图_教大家用EXCEL配合CAD绘制道路标准断面图

在道路绘制横断面时&#xff0c;往往要借助一些针对性比较强的专业软件进行&#xff0c;而作为施工单位的技术人员&#xff0c;却面临着&#xff1a;软件种类五花八门&#xff0c;而实际运用却存在着界面不熟悉&#xff0c;操作熟练度小&#xff0c;导致效率不高的问题&#xf…

微信无法连接到服务器(110087)),110087无法连接网络是什么意思

手机在使用的时候提示110087无法连接网络则说明手机此时无法连接网络是不能上网的&#xff0c;而手机不能上网的原因也是多方面的&#xff0c;找到手机不能上网的原因才能更好的解决问题。首先&#xff0c;可能是手机有短信或者电话正在进入&#xff0c;因此很多手机在该情况下…

pandas 每一列相加_Python数据分析——Pandas 教程(上)

Python 在数据分析领域里是一门非常强大的语言&#xff0c;在数据分析方面有着出色的生态系统。Pandas 包就是其中之一&#xff0c;它的主要特点是导入和分析数据非常的容易&#xff0c;Pandas 类似 Numpy、Matplotlib&#xff0c;提供了单一且方便的方式来处理数据分析和形象化…

ajax刷新iframe页面,通过iframe实现简单的ajax表单提交

之前做项目都是用现成的jquery插件实现表单的校验以及ajax提交&#xff0c;但是今天有个简单的头像图片ajax上传&#xff0c;以及一个很简单的表单提交&#xff0c;实在不想引入一个插件了&#xff0c;本着代码量最小&#xff0c;最简单的原则&#xff0c;照着豆瓣照抄了一个&a…

bat文件设置dns服务器,.bat文件设置IP、DNS

这几天遇到个烦心事&#xff0c;每次开机之后都要去手动去设置一下IP地址&#xff0c;一大串的数字还是有点麻烦&#xff0c;于是就想写个批处理文件设置IP注意&#xff1a;在DOS下设置IP时需要管理员权限运行1.查看机子设置IP需要用到的名字名字是Ethernet2.查看机子在DOS下设…

cv2 画多边形不填充_你不知道的4种方法:python方法绘制扇形

1 说明&#xff1a;1.1 是问答中的我的一个回答。1.1 因为问答中没有代码块的&#xff0c;所以我改为这里写文章&#xff0c;然后链接过去。1.2 4种方法&#xff1a;turtle法、OpenCV法、pygame法和matplotlib法。2 turtle法&#xff1a;2.1 代码&#xff1a;#第1步&#xff1a…

不同角色进入使用不同功能_如何在不同页面上使用不同的Joomla CSS

简介&#xff1a; 我们的一位用户希望其网站首页具有不同的背景。 Joomla确实提供了几种自定义单个页面的方法。本教程将向您介绍两个Joomla选项。让我们开始吧 ...我们的一位用户希望其网站首页具有不同的背景。 Joomla确实提供了几种自定义单个页面的方法。本教程将向您介绍两…