正反傅里叶变换、fft算法
dct变换、快速dct变换
(1)取一帧作为I帧,类似jpeg压缩编码,也就是 rgb转yuv,然后dct去除高频信息。因为这种压缩会造成边界block通常使用插值让边界模糊。
(2)运动预测来计算P帧,新的一帧同样做yuv、dct之后,划分为n个宏快(16*16),与上一个参考值的n个宏快(16*16)进行n*n的双重循环计算相似度。比如当前P宏快1和上一参考帧宏快10最相似,那么两个宏快的坐标可以求出矢量变换方程。当然大部分宏块是不会变换的。P1的内容是n个宏块坐标。用这个坐标在上一个参考帧内找到宏块数据。
(3)继续运动预测计算P帧,以前一个参考帧(I帧或P帧)为基础继续宏块变换计算。当然n*n的对比效率低下,通常是以当前点朝四周扩散并且一定范围内选点进行对比。
(4)连续运动预测计算多个P帧,最后结果是,I编码的是A帧,P1编码的是B帧(记录B帧相比A帧有变换的宏快的坐标),P2编码的是C帧(P2记录C相比B有变化的宏快的坐标)。
(5)P帧目前是坐标数据,用P帧结合前一个参考帧进行预测得到一个预测的图片a',因为同时序的真实图片a也是知道的,a'-a 得到预测误差 e,P帧最终保存的就是这个 e (也就是残差)。通过 e 以及前一个参考帧可以完美还原。
(6)双向运动预测计算B帧,B帧跟P帧计算一样,B帧就是根据P1、P3计算P2。
(7)完整的简版视频编码器,I帧和P帧编码已经够了,市面上任然有很多面向低延迟的商用编码器是直接干掉B帧的,因为做实时传输时收到B帧没法播放,之后再往后好几帧收到下一个I或者P帧时,先前收到的B帧才能被解码出来,造成不少的延迟。
(8)组装GOP,一个I多个B、P就组成了一个完整的GOP,然后将一组GOP记录分辨率、时序、帧率等记录下来进行封装,例如mp4格式就ok了。

不同的视频编码规范有不同的组织框架,但通常可以分为视频序列层、GOP图像组层、图像层、宏快组层、宏快层、YUV层

最早的基础编码器是h261,使用16*16的宏快(包含4个8*8的Y亮度块和2个8*8的UV色度块),以宏块为单位进行编码,帧内编码直接DCT量化然后熵编码(没有帧内预测)。帧间编码做运动估计和运动补偿,预测对原始块做残差后进行DCT量化再熵编码。帧间仅前向预测。后续的编码器结构都在次基础上进行优化升级。

之所以采用YUV,是因为它的亮度信号Y和色度信号U、V是分离的。如果只有Y信号分量而没有U、V分量,那么这样表示的图像就是黑白灰度图像。YUV最大的优点在于只需要占用极少的频宽(RGB要求三个独立的视频信号同时传输)。其中“Y”表示明亮度(Luminance或Luma),也称灰阶值;“U”和“V”表示的则是色度(Chrominance或Chroma),它们的作用是描述影像的色彩及饱和度,用于指定像素的颜色。因此如果只有Y数据,那么表示的图像就是黑白的。在编码时使用YUV格式能极大去除冗余信息,因为人眼对亮点信息的敏感度远高于色度敏感度,如果压缩UV数据,人眼对其感知较弱,所以压缩算法的第一步,往往先把RGB数据转换成YUV数据,对Y压缩一点,对UV多压缩一点,以平衡图像效果和压缩率。对亮度的变化敏感,对色度的变化相对不敏感。
RGB->YUV有损压缩,JPEG就是采用这个压缩方式。

每一帧图像,划分成一个个块来进行编码的,这一个个块在 H264 中叫做宏块,宏块大小一般是16x16(H264、VP8),32x32(H265、VP9),64x64(H265、VP9、AV1),128x128(AV1)这几种。
一个图像一个帧内,每16*16作为一个字块,相邻的字块之间有较强的相关性和相似性。另外同一个 16*16 的小块内基本上每个像素点的颜色是一样的可以减少编码数据量。另外相邻的块之间是有联系的,也可以通过预测以及插值的方式来减少空间冗余,也就是在一帧内宏块A、B、C相似,那么只需要编码A同时记录BC坐标即可。
在连续的多个帧内,以fps=25为例,相邻两帧之间时间上为40毫秒,两个图像的变换很小,相似性很高。通过帧间预测的方法来去掉冗余的数据,例如前面a帧减去后面bcdef五帧得到残差,那么只需要保留a帧以及bcdef帧的残差进行编码就可以了,而且相邻帧变化不大残差去掉了相同像素点的冗余信息。又由于残差记录的是相邻帧的变化,那么连续的矢量变化是可以预测的,也就是说在残差的基础上只需要保留第一个和最后一个帧的残差,中间的残差可以通过运动预测计算出来。
人眼睛对于细节不敏感,对轮廓更加敏感,一个图像在去掉高频信息前后感官差别不大。通常在帧内预测或者帧间预测去除冗余信息之后得到一个像素点的残差(大部分是0小部分不是0),然后通过 dct 将高频信息和低频信息划分后,将高频信息也编码为0,这一步就能去除视觉冗余。
形如常见的哈夫曼编码,出现概率越大就用出现次数来代替的一种编码形式。在去除了时间、空间、视觉冗余之后得到的是一连串的量化后的数字,编码冗余进行最后一步的压缩。也称为信息熵冗余。
I帧:帧内编码帧 ,I帧表示关键帧,你可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成(因为包含完整画面)
P帧:前向预测编码帧。P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。
B帧:双向预测内插编码帧。B帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别,换言之,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是解码时CPU会比较累。
一般来说,I帧的压缩率是7(跟JPG差不多),P帧是20,B帧可以达到50。可见使用B帧能节省大量空间,节省出来的空间可以用来保存多一些I帧,这样在相同码率下,可以提供更好的画质。


(1) 进行帧内预测,决定所采用的帧内预测模式。
(2) 像素值减去预测值,得到残差。
(3) 对残差进行变换和量化。
(4) 变长编码和算术编码。
(5) 重构图像并滤波,得到的图像作为其它帧的参考帧。
(1) 进行运动估计,计算采用帧间编码模式的率失真函数(节)值。P帧只参考前面的帧,B 帧可参考后面的帧。
(2) 进行帧内预测,选取率失真函数值最小的帧内模式与帧间模式比较,确定采用哪种编码模式。
(3) 计算实际值和预测值的差值。
(4) 对残差进行变换和量化。
(5) 熵编码,如果是帧间编码模式,编码运动矢量
所谓GOP,意思是画面组,MPEG格中的帧序列,分为I、P、B三种,如排成IBBPBBPBBPBBPBBP...样式,这种连续的帧图片组合即为GOP(画面群,GROUP OF PICTURE),是MPEG将来存取的最本基本的单位,它的排列顺序将会一直重复到影像结束。一个GOP就是一组连续的IPB画面。GOP设置在直播领域设置为一到两秒。一个GOP的的编解码必须等到一个I帧才能开始解码,同时B帧也会带来编码延迟。
首先残差就是真实值和预测值的差值。所以计算残差首先需要进行预测。预测就需要根据原始坐标以及终点坐标计算运动矢量。然后根据原始点和运动矢量计算终点的预测值,得到一个预测图像。预测图像减去原始图像得到一个残差。只有残差是不能还原P帧所在帧的图像的,需要先将运动矢量根据参考帧图像得到P帧所在的预测图像,预测图像再加上残差才能得到真实的图像。也就是说P帧保存的是运动矢量、残差两个部分的信息,这两部分进行编码相比原图像编码大大减少了数据量。另外预测得越准确那么残差 越小,残差编码结果就越小。

这是因为运动矢量计算出来的预测图像,和真实的图像还是有一定的差别的,宏块的除了运动还有一定比例的旋转、缩放等非平移变换。计算残差一方面可以完美还原,另外一方面数据量也不大。
帧间预测是宏块时间上的移动,有明确的物理意义,可以预测移动来计算残差并且通过残差进行还原。而预测就是运动估计,假设参考帧为P(编码块为B),当前帧为Pr(编码快为Br),B经过运动后到达Br。寻找的过程就是宏快扫描然后求残差,如果两块的残差最小那么表明这两块最有可能是移动变换的前后两块。另外运动估计模型分两种,参数模型(估计参数来得到移动方程)和非参数模型()。
一个运动的物体移动后在二维平面的投影可以通过运动方程来计算,参数模型的运动估计就是估计这个运动方程的参数。而实际应用一般是非参数模型,例如光流方程法、贝叶斯法、像素递归法、块匹配等。而视频编码最使用的运动估计是基于空间域搜索的块匹配法。也就是假设视频划分为m个n*n的宏块,假设块之间是平移变换。实际视频内像素块在划分n*n的像素点内基本是平移变换,就算有一些倾斜和缩放,在实际运用中还会根据估计值和残差一起来还原图像。
前向预测:如果把当前帧所在时序以前的帧作为参考帧进行宏块运动估计。
后向预测:如果把当前帧所在时序以后的帧作为参考帧进行宏块运动估计。
双向预测:同时把前面、后面的帧作为参考帧。并且在两次宏块运动估计之后按照不同的权值求和得到运动矢量。
实际应用中都是前向预测,因为后向预测和双向预测会带来延迟。因为必须等到参考值传过来才能进行工作。
大部分编码算法以16*16、8*8为宏块大小,因为如果太大比如使用完整一帧计算残差会很大不利于压缩,如果划分太小每个宏块都有运动矢量和残差需要传输光运动矢量就要占用很大的码流也不利于压缩。实际运用是在减少残差、减小运动矢量之间的一个平衡。通常还有自适应的方法,如果画面移动较为平滑自动选择大的宏块、如果画面纹理复杂则选择小的宏块、运动剧烈选择小块、运动少选择大块。h264采用了自适应分块,即先采用大块扫描确定移动后目标大概范围,然后再用小块再此范围内二次搜索找到精确的位置。例如下图先确定一个16*16的大致范围,然后再进行8*8的匹配:

SAD:绝对误差和(实际应用最多)
SATD:先Hadamard变换,然后再绝对值求和。
SSD:差值平方和
MAD:平均绝对差值
MSD:平均平方误差
x264快搜有三种算法,me-dia菱形搜索、me_hex六边形、ne_umh非对称十字形六边形格点搜索。都是先确定一个初始搜索点,然后按照各自的形状进行搜索。
帧内预测并不是计算的宏块的移动,而是在宏观图像上划分的微小宏块都有连续性,颜色是渐变的,不可能在几个像素内颜色突变,所以利用这一部分的相关性来进行预测。宏块周围的其他宏块如果相似度高,则只需要进行一次编码。帧间预测占了大部分冗余,在早期视频编码甚至直接没有做帧内预测,衣蛾帧内预测仅占用较少的冗余。
帧内预测实际上就是一张图的预测编码,很多时候性能都是和 jpeg 进行对比参考,方法也类似。
h263:采用dct/mc混合编码,也就是帧间预测DPCM和帧内DCT同时进行,也就是说舍弃了帧内预测。
h263+:引入基于频域的帧内预测,利用频域内相邻块的DCT系数 DC和AC的相关性。用当前块DC和AC系数来预测后一块DC和AC系数。不太理想。
h264:改进为空域帧内预测,也就是相邻宏快之间的变换不大,同当前块来预测围绕一圈的相邻块,预测后求残差,对残差(很多0)进行编码。
DCT是离散傅里叶变换。就是将图像转换到频域,去掉高频信息,类似音频的频域高通滤波,在图像领域DCT效果比DFT好。傅里叶变换表明任何信号都可以表示为多个不同振幅和频率的正弦或余弦函数叠加。DCT就是离散余弦变换,也就是输入和离散信号的余弦函数叠加。图像视频领域中,最常用的是DCT-Ⅱ,平常说的DCT一般指的是DTC-Ⅱ。DTC-Ⅲ是 DTC-Ⅱ的反变换,一般说的反DCT指的就是DCT-Ⅲ。由公式可以看出,X(k)就是在频率k下,求序列上各点对应余弦项的累加和。当k=0时,各点的余弦项均为1,此时得到的结果X(0)正比于x(n)的和,被称为直流分量。当k>0时,得到个频率下的X(k)被称为交流分量。

因为对图像矩阵存储,一个二维数组进行二维DCT之后,将图像转到频域能量分布图,能量较为集中。

因为DCT不可避免需要浮点乘法,浮点的经度问题不可避免也就是不能无损压缩。而整数DCT则避免了这个问题。
量化是为了降低比特率,因为编码后的矩阵取值范围大需要过多比特数来表达一个数字。量化需要将某个量强行归一化到某个输出,因为是一对多所以是不可逆过程。视频压缩的亮化过程主要发生在以下过程,在预测、差分、正交变换、之后对这些系数和值的亮化。亮化发生在熵编码之前。例如求残差之后对残差进行DCT变换得到的DCT系数,就需要对系数进行量化以方便后续的熵编码。
指定量化步长,每个标量表示为量化补偿的n个倍数。按照对半的方式,在一个区间内高于步长一半则上取值,低于步长一半则下取值。由此可以知道,一个标量本身小于步长二分之一的话会直接量化为零。
量化就是把信号的连续取值映射成多个离散的幅值的过程,实现了信号取值多对一的映射(参考pcm采样量化)。残差数据进过变换之后,变换系数具有较大的取值范围,量化可以有效减小信号的取值范围,进而获得更好的压缩效果。量化是造成失真的根本原因。在视频编码器中,标量量化操作用(带圆整的)整数除法实现,除数是量化步长(QStep)。举例来说,除 10 再圆整到最近的整数操作会将 量化到 0, 量化到 1。量化步长越大,量化强度与信号损失越高。反量化是由标准规定的,基本上就是量化后的信号乘上量化步长。

因为QP量化影响码率,QP越高压缩率越高则视频码率越低视频越模糊。在一些直播场景中,可以根据贷款情况动态设置码率。
矢量是一组量本点,矢量通常通过欧氏距离来求是否近似。会有一个码本库包含很多矢量。矢量量化就是从库中找到一个矢量和当前需要量化的矢量最相似的,然后记录库中的下标。传递时仅仅需要传递下标即可。实际上视频编码的矢量通常是运动矢量也就是2维坐标来描述运动的方向和距离。
游程编码类似哈夫曼编码,也就是统计连续出现的个数来进行压缩。在DCT之后还需要系数的量化,量化之后会出现很多0且集中在右下角。通过锯齿扫描出来然后用游程编码进行压缩传递。

熵编码即编码过程中按熵原理不丢失任何信息的编码。信息熵为信源的平均信息量(不确定性的度量)。常见的熵编码有:香农(Shannon)编码、哈夫曼(Huffman)编码和算术编码(arithmetic coding)。
在实际运用中,视频编解码后质量评估,ITU规定了一种主观标志的测试程序,最常用的方法DSC-QS。通过人眼主观打分。而客观的评价标准则是使用 MSE(均方根误差)、SNR(信噪比)、PSNR(峰值信号比) 来判断质量。以输入图像 f(x,y) 为原始图像,g(x,y)为压缩后图像,图像分辨率 m*n,则f和g的质量评估公式为,注意需要在YUV三个分量上分别计算mse、snr、psnr。

我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我正在使用ruby1.9解析以下带有MacRoman字符的csv文件#encoding:ISO-8859-1#csv_parse.csvName,main-dialogue"Marceu","Giveittohimóhe,hiswife."我做了以下解析。require'csv'input_string=File.read("../csv_parse.rb").force_encoding("ISO-8859-1").encode("UTF-8")#=>"Name,main-dialogue\r\n\"Marceu\",\"Giveittohim\x97he,hiswife.\"\
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
动漫制作技巧是很多新人想了解的问题,今天小编就来解答与大家分享一下动漫制作流程,为了帮助有兴趣的同学理解,大多数人会选择动漫培训机构,那么今天小编就带大家来看看动漫制作要掌握哪些技巧?一、动漫作品首先完成草图设计和原型制作。设计草图要有目的、有对象、有步骤、要形象、要简单、符合实际。设计图要一致性,以保证制作的顺利进行。二、原型制作是根据设计图纸和制作材料,可以是手绘也可以是3d软件创建。在此步骤中,要注意的问题是色彩和平面布局。三、动漫制作制作完成后,加工成型。完成不同的表现形式后,就要对设计稿进行加工处理,使加工的难易度降低,并得到一些基本准确的概念,以便于后续的大样、准确的尺寸制定。四、
2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p
Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图
我最喜欢的Google文档功能之一是它会在我工作时不断自动保存我的文档版本。这意味着即使我在进行关键更改之前忘记在某个点进行保存,也很有可能会自动创建一个保存点。至少,我可以将文档恢复到错误更改之前的状态,并从该点继续工作。对于在MacOS(或UNIX)上运行的Ruby编码器,是否有具有等效功能的工具?例如,一个工具会每隔几分钟自动将Gitcheckin我的本地存储库以获取我正在处理的文件。也许我有点偏执,但这点小保险可以让我在日常工作中安心。 最佳答案 虚拟机有些人可能讨厌我对此的回应,但我在编码时经常使用VIM,它具有自动保存功
查看Ruby代码,它具有以下proc_arity:staticVALUEproc_arity(VALUEself){intarity=rb_proc_arity(self);returnINT2FIX(arity);}更多的是C编码风格问题,但为什么staticVALUE在单独的一行而不是像这样的:staticVALUEproc_arity(VALUEself) 最佳答案 它来自UNIX世界,因为它有助于轻松grep函数的定义:$grep-n'^proc_arity'*.c或使用vim:/^proc_arity
我创建了一个由于“在运行时执行的单例元类定义”而无法编码的对象(这段代码的描述是否正确?)。这是通过以下代码执行的:#defineclassXthatmyusesingletonclassmetaprogrammingfeatures#throughcallofmethod:break_marshalling!classXdefbreak_marshalling!meta_class=class我该怎么做才能使对象编码正确?是否可以从对象instance_of_x的classX中“移除”单例组件?我真的需要一个建议,因为我们的一些对象需要通过Marshal.dump序列化机制进行缓存。
我在使用Ruby1.9.2p290更改文本文件的编码时遇到问题。我收到错误消息invalidbytesequenceinUTF-8(ArgumentError)。问题(我认为)在于字符集似乎是未知的。如果我执行以下操作,则从命令行:$filetest.txt我得到:Non-ISOextended-ASCIIEnglishtext,withCRLFlineterminators或者,或者,如果我这样做:$file-itest.txt我得到:test.txt:text/plain;charset=unknown但是,如果我这样做,在Ruby中:data=File.open("test.tx