假如不考虑图片视频利用人类视觉特点的有损压缩,只讨论无损压缩。
熵编码实现压缩,是利用了数据流里“重复出现的部分”,把这些重复部分代换成更短且能一对一无歧义还原的片段,就实现了压缩。
那么图片、视频中其实也有“重复的部分“。比如,视频压缩中利用相邻帧之间变化很小这一特点,那是不是可以说,相邻帧之间“重复的部分”非常多呢?(虽然不是完全重复,至少可以说很类似。)既然重复的部分很多,是不是可以用更 smart 的熵编码算法来直接压缩呢?
终于看明白为什么这个问题显得有点儿傻,我重新问一遍试试。
为什么仅仅用 huffman 这种熵编码来压缩视频,压缩比不如 h264 这种视频压缩方法?
我知道视频编码有运动预测、运动补偿、帧内预测、频域变换等等机制,熵编码是最后一环。 我也知道视频编码利用了人类视觉特点,在让人看起来差别不大的情况下做了有损压缩。 但探索这些机制的原因,前提都是因为单纯的熵编码压缩比不理想。
那这是不是因为熵编码还不够优化,方法还不够好呢? 也就是说,会不会随着通用压缩算法的进化,发展出某一种压缩方法,能够绕过“帧”的概念压缩视频,同时压缩比不输给 h264 呢?
有这个想法是因为,熵编码和视频编码都是在利用数据中重复的部分。 如果用最原始的方法表示视频(一系列 bmp 图片),数据当中也会有许多重复(正因为有这些重复,h264编码器才有可能把视频压小),只不过通用压缩方法还没有发现这些重复,不知道如何利用它们而已。
1
ipwx 2022-06-01 13:34:06 +08:00
1. 什么叫图片视频。。。
2. 现代视频编码确实是这么搞的。有兴趣可以看 h264, h265 |
2
learningman 2022-06-01 13:34:47 +08:00
肯定是啊,h264/h265/vp9 不都是吗
|
3
learningman 2022-06-01 13:35:30 +08:00
你算算按 bmp 那种方式,一个 10 分钟的 1080p 视频该多大
|
4
ruixue 2022-06-01 13:36:31 +08:00 7
知乎有句名言:先问是不是再问为什么
|
5
fashioncj 2022-06-01 13:40:30 +08:00 via iPhone
你有没有发现,大部分视频图片格式你压缩后大小几乎没有变化🤓
|
6
icyalala 2022-06-01 13:41:42 +08:00
现在的 HEVC 就是 CABAC 熵编码,也有帧内预测帧间预测
|
7
lingxi27 2022-06-01 13:42:38 +08:00 5
“思而不学则殆”
|
8
nothingistrue 2022-06-01 13:44:30 +08:00
你说得这个方法,正是 h264 、h265 的基本原理。也许可能不叫做熵编码算法。
还有你的第一句话,我还是第一次听说利用人类视觉特点的压缩。 |
9
newmlp 2022-06-01 13:52:57 +08:00
小伙子很有想法,vp10 h266 av2 编码标准就交给你了
|
10
litec 2022-06-01 13:56:46 +08:00
@nothingistrue 事實上影像壓縮在 DCT 後做 quantize 時,就是考慮人眼對於高頻較不敏感,所以用較少 bit 表達做壓縮。多數影像壓縮標準也都會考量真人的感受做為評比
|
11
xtreme1 2022-06-01 13:59:33 +08:00
由于你能问出这种问题, 直接看楼上们提示的 h264 你可能很难看懂(没有恶意).
建议先从 MPEG2 开始入手, 现代编码器的基础概念都是有的. |
12
tusj 2022-06-01 14:22:44 +08:00 6
是不是刚听老师新讲了一个新章节,就突然灵机一动。。。
|
13
iamzuoxinyu 2022-06-01 14:51:18 +08:00
> 我还是第一次听说利用人类视觉特点的压缩。
事实上通常视频使用 YUV420 而不是 RGB444 就是 [利用人类视觉特点] 的压缩手段。 |
14
nthhdy OP @ipwx 图片视频指的就是图片和视频
@learningman @lingxi27 @nothingistrue h264 以及其它的视频编码的确用了熵编码,但那只是其中的一个步骤。 可能我没有说清楚,我想说的是,为什么不能只用熵编码这一个步骤。 比如我想压缩文本,一个简单的方法是,先统计字出现的频率,用 huffman 生成编码表,然后到原文中代换,出来的结果大小接近理论压缩极限。gzip 这种工具用的方法更 smart ,但是肯定不像视频那样,需要 motion estimation 等步骤。 |
15
iamzuoxinyu 2022-06-01 14:53:30 +08:00
因为只用帧内压缩远远不够啊…
|
16
nthhdy OP |
17
nthhdy OP @iamzuoxinyu 帧内压缩相当于单张图片压缩,单张图片压缩也比单纯的熵编码压缩复杂很多。
|
19
imn1 2022-06-01 15:12:39 +08:00
你语言组织不好,把一个高阶问题问成了低阶
高阶的部分我也答不上 只知道现在的算法好像也有用到相邻帧之间的类似部分,key frame 好像就是为了这个设计的?定时修正 raw ,避免太多的帧压缩导致靠后的失真越来越严重 一知半解,不对的话可以 pass |
20
ipwx 2022-06-01 15:13:43 +08:00 10
@nthhdy 信息熵是个数学概念,在实际数据集上几乎无法计算。
任何计算“熵”、“概率”,都要先假设数据服从某些分布,然后才能进行计算。各种不同的压缩方法,显然是假设数据服从不同的分布,然后用这种假设去搞了具体的编码方案。 你在教材上看到的 Huffman 编码,是假设 alphabetic 是定长的(比如 a~z ),并且每个 alphabetic 都用定长的 0-1 串编码。在这个前提下给出的最佳编码方案是霍夫曼树。但是呢。。。 显然现实世界不是这样的。你完全可以用不定长的 alphabetic 去做不定长串的压缩。这就是各路通用压缩算法大显神通的地方了。然而即便如此,通用压缩算法处理 .avi 也达不到很高的压缩比。 各种视频和图片编码显然是做了更激进的概率建模,在这种特殊的概率分布上用了更高压缩比的方案。比如视频的帧间编码,显然是利用了你“视频的帧与帧之间的信息有很多重复”这个额外信息。在通用压缩方法里面可没有这个额外信息。 ---- 信息论有一条,“数据的信息量 = 编码后的信息量 + 编码器的信息量”。虽然和上面的论述其实没有多大关系,但是也能提示你一点:你给程序多一点信息,你压缩以后的东西就能变得更小。 |
21
ipwx 2022-06-01 15:19:11 +08:00
@nthhdy 其实如果外延一下的话,上面的乱七八糟的讨论和条件熵有关。
H[X|Y] = H[X,Y] - H[Y] 已知 Y: 数据是视频。 所蕴含的信息量其实是非常非常巨大的。同样的文件,没有 Y 这个信息的话,你无法自动推断出 “帧与帧之间有图像相似性” 这个结论的。因为每张图的 0-1 串其实相差巨大。图片就是这个样子,上面的 object 移动一个像素,二进制串就一大堆变化(而且还不是连续的二进制位发生变化)。通用压缩算法几乎不可能在有限的时间里面去 discover 这种信息。 |
22
yukiww233 2022-06-01 15:20:42 +08:00
已经用了; 比如视频,H.264 压缩对比原始数据甚至小于 1/100, 靠无损编码是没可能达到的
|
23
yangzzzzzzzt1 2022-06-01 16:15:46 +08:00
作为一个专门研究编码器的人表示槽点太多无从吐起
|
24
unco020511 2022-06-01 16:22:20 +08:00
不仅仅是媒体文件,好多压缩算法都是这个原理吧
|
25
misdake 2022-06-01 16:23:24 +08:00
“为什么不能只用熵编码这一个步骤”
因为只用这一个步骤的话,压缩比太低。 想要提高压缩比,允许有损压缩,就会有那些频率域上的操作和前后运动估算之类的方法。 |
26
nthhdy OP |
27
nthhdy OP @misdake
你说的对。问题就在于,那些压缩算法对文本都挺好的,对图片和视频就不行?道理是什么? > 想要提高压缩比,允许有损压缩,就会有那些频率域上的操作和前后运动估算之类的方法。 我的理解是,引入运动预测等机制,即使无损也能一定程度上提高压缩比。所以并不仅仅是有损无损的问题。 |
28
nthhdy OP @yangzzzzzzzt1 看错了,14 楼
|
30
littlefishcc 2022-06-01 16:39:30 +08:00
图片:单个文件压缩算法,不就是帧内压缩, 能压缩就那么大。
视频:压缩体积大的原因,通过帧间压缩。 自己写一个手机协同工具,开始用一张张图片压缩后传送到 PC ,网络传送可以大概一直是 8M ,后面欢用 h264 基本就是 200 多 KB 。 h264 说白就是 前和图片有关联只要传送变化就可以了, 以前看远程控制的软件,没有用 h264 ,自己写压缩算法,就是计算前后图片的改变内容,然后传送改变的 rbg 值。。。 |
31
misdake 2022-06-01 16:43:31 +08:00 1
另外开阔眼界的话,png 里面用到的压缩方法也挺有意思,还有最近的 qoi 压缩,都是很针对图片的压缩方法。可能比熵编码更好一点
How PNG Works: Compromising Speed for Quality: |
32
oldshensheep 2022-06-01 16:45:21 +08:00 1
楼主大概的意思是把 一捆图片 打个压缩包(固实压缩),然后就变成了视频吧。(大概)
然后楼主认为,压缩程序应该能够提取出这些图片间的相似处,达到更高的压缩率。所以我们为什么不用压缩软件来压缩视频? |
33
TK4E 2022-06-01 16:54:38 +08:00 via Android
二进制数据体积很大 所以用了无损压缩
无损压缩的数据体积很大 所以用了有损压缩 而视频编码里也有使用去重这一操作 |
34
kkocdko 2022-06-01 16:58:36 +08:00 via Android
这个问题就像水洗煤一样。。。
建议先拓宽自己的知识面,起码先看看 h264 ,或者看看 vp8 也许更简单一些(对的其实我并不懂 h264 ),就会发现从前的自己是多么渺小。你所指出的这一切都是非常原始的说法,贻笑大方罢了。 |
35
zhs227 2022-06-01 17:02:07 +08:00
单 Huffman 无法消除时域上的重叠。而视频压缩中的 I/P/B 是利用了时域上有很大相似性的特点来达到更高的压缩比。所以,为什么不能只用 Huffman ,因为 Huffman 的限定范围在一帧之内。
|
36
misdake 2022-06-01 17:19:58 +08:00
@nthhdy
文本有无损的硬性需求,即使压缩率低也没办法。 图片和视频没有无损的硬性需求,相反,尤其是视频因为原始内容太大太大,超高压缩率是很多情况下的硬性要求。 另外你说的运动预测你说的是对的,不管有损无损,都可以提高压缩比。(不过这个就不是熵编码的范畴啦) 不少提到的方法最后都要经过一次熵编码,但感觉就像是最后的万金油方法或者兜底方法,而不是真正压缩数据的地方。 |
37
tinybaby365 2022-06-01 17:36:33 +08:00
jpeg 格式里面就有使用 huffman 编码啊,但 jpeg 中主要压缩的方法是离散余弦变换(用信号处理的方式实现有损压缩)
|
38
microxiaoxiao 2022-06-01 17:49:44 +08:00 via Android
你这个套路明显有问题,可以适合已知所有图片。但是真实的环境中存在大量实时视频,比如监控,直播,会议等,码流持续产生。那你这时候咋计算,或者大幅运动的情况下,你那种商编也不行了,有损压缩能大福提高传输,存储效率。
|
39
microxiaoxiao 2022-06-01 18:01:01 +08:00 via Android
编码器里面有多趟编码的说法,可以进一步压缩。和你说的这个商编码套路有点类似。不适合实时编码。实时编码主要就靠压缩,补偿,然后不断插入 I 帧,然后 P ,B 帧前后预测比对,编码标准本身会对各种场景和业务形态进行不同处理。
|
40
systemcall 2022-06-01 18:17:02 +08:00 via Android
你知道一分钟的 1080p30 RGB888 ,是多大吗?
你可以用 bmp 格式保存一段视频的每帧画面,看看有多大,再丢到 7zip 或者 WinRAR ,看能压缩多少 |
41
mxT52CRuqR6o5 2022-06-01 18:23:40 +08:00
视频还要考虑播放的问题,需要可以流式的获取到从头到尾的帧数据,这个问题你考虑过吗
|
42
mxT52CRuqR6o5 2022-06-01 18:25:41 +08:00 1
就比如我需要拖拽进度条到中间位置,播放器需要快速获取到视频中间位置的帧数据
像 RAR 那种压缩算法,解压得从头开始解压,要咋完成播放功能呢? |
43
mxT52CRuqR6o5 2022-06-01 18:30:41 +08:00
还有就是 7z 压缩时可以选择字典大小和单词大小,字典大小调大会增加压缩时的内存使用,单词大小调大会增加压缩时的 cpu 使用(增加压缩时间),要是按你的设想压缩视频就得把这两个参数设的很大去匹配帧数据,这所增加的代价你考虑过吗
|
44
nthhdy OP @oldshensheep
> 楼主大概的意思是把 一捆图片 打个压缩包(固实压缩),然后就变成了视频吧。(大概) 逻辑上来讲,视频的确可以看成时间上离散的一系列图片。虽然在文件格式当中并不是这样的。 > 然后楼主认为,压缩程序应该能够提取出这些图片间的相似处,达到更高的压缩率。所以我们为什么不用压缩软件来压缩视频? 我这个问题的确是想问,是否存在某种通用压缩算法,绕过“帧”这种概念,直接去掉重复的部分。 |
45
nthhdy OP |
46
nthhdy OP |
48
loopinfor 2022-06-01 19:08:02 +08:00
@nthhdy 当然可以通用压缩算法压缩视频文件啊。
你可以简单用图片做个实验。随便一张图片保存为 BMP 格式,然后压缩为 ZIP 文件,压缩之后大小基本上跟 PNG 和 JPEG 差不多。 问题是视频这样压缩之后就没法直接解码播放了啊,1GB 的视频你只能全部解压才能开始播放。 |
49
nthhdy OP @ipwx 有损发生在 DCT 变换之后数量化和去掉高频分量这一步。
即使不做数量化,不去掉高频分量,运动补偿和运动预测还是有用的,因为会让 P 帧表示的残差非常小。 压缩这一帧,相当于压缩一张几乎“全黑”的图片。还是会比压缩一张一般图片小一些的。 |
50
GeruzoniAnsasu 2022-06-01 19:21:20 +08:00
> 我这个问题的确是想问,是否存在某种通用压缩算法,绕过“帧”这种概念,直接去掉重复的部分。
有没有一种可能,就是通用算法的效率远远不如专用的视频压缩算法 |
51
jhdxr 2022-06-01 19:30:13 +08:00
@nthhdy
『我这个问题的确是想问,是否存在某种通用压缩算法,绕过“帧”这种概念,直接去掉重复的部分。』 你好,有的。常见的压缩软件就是干这件事情的。 那为啥我们不这么做呢? 压缩比太低,在针对图片视频这个场景下有更高效的针对特定场景的压缩方法。 |
52
rus4db 2022-06-01 19:30:29 +08:00 3
香农第一定理(无失真信源编码定理)表明,楼主所说的“通用压缩算法”是存在的。
但是对于音视频这种与人类感官有关的信息,由于感官对于失真有一定的容忍度,此时就可以运用香农第三定理(保真度准则下的信源编码定理),在 rate 和 distortion 之间寻求平衡。其中 R(D)的选取和优化是关键。变换域编码、帧间 /帧内预测等编码工具,以及拉格朗日等优化算法,都是实现率失真优化的手段。视频、音频、点云等不同“模态”的信息,其失真度量和 R(D)都是不同的。 失真度量是关键,反映了信源的内在性质。例如 MP3 、AAC 等标准,都大量引入了心理声学算法,衡量不同场景下编码失真与人类听阈之间的关系,用来引导码率-失真优化循环来寻找最优编码参数。 总结起来就是,根据香农第一定理,只用熵编码固然是可行的,因为它是通用的。但是对于特定模态的数据,可以容忍一定的失真,因此可以在失真和码率之间权衡,此时适用香农第三定理。 |
53
tinytoadd 2022-06-01 19:31:49 +08:00 via Android
视频一般都要支持流式传输吧,如果只用哈夫曼编码,岂不是播放视频之前要先全部载入内存再解码。
|
54
haah 2022-06-01 20:35:47 +08:00
|
55
statumer 2022-06-01 20:51:33 +08:00 3
作为搞视频编码器的,我建议你去学一下信息论与编码这个课
视频编码器和 huffman 编码器之间的差距是 huffman 编码等熵编码技术只能学习到连续的比特特征,学习不到高层次的特征,比如说衣服上的花纹,台球的运动 如果你的视频内容不是正常的视频,而是一堆完全随机的色彩,那么熵编码器其实效果比视频编码器更好,因为视频编码器实际上是针对常见视频设计的。 另外就是 RDO 优化的问题,视觉内容是容忍失真的,视频编码器也有 PCM 模式,视频编码器有 RDO 优化器决定是否采用无损模式。大多数情况不会用,因为无损模式 RD Cost 绝大多数情况都很差。 https://imgur.com/lWwybSL.png |
56
akira 2022-06-01 21:04:20 +08:00
假如,发现了某种算法,能更好的无损压缩视频数据,那么基于他改进的有损压缩只会更好。
|
57
AX5N 2022-06-01 21:27:58 +08:00
你怎么知道没用?
|
58
mxalbert1996 2022-06-01 21:52:10 +08:00 via Android
楼主可能根本就没有意识到现代视频编码的压缩率有多小,常见的 H264 视频,相对未压缩的 RAW 格式的压缩率是千分之一这个级别的,再不济也有百分之一,你文本压缩能有这个压缩率?更何况视频本来就比文本复杂得多。
|
59
msg7086 2022-06-01 23:56:54 +08:00 via Android
因为只用熵编码无法满足人们对压缩的需求。熵太高了,容量下不去。
|
60
dant 2022-06-02 00:09:00 +08:00
> 即使不做数量化,不去掉高频分量,运动补偿和运动预测还是有用的,因为会让 P 帧表示的残差非常小。
压缩这一帧,相当于压缩一张几乎“全黑”的图片。还是会比压缩一张一般图片小一些的。 你要找的是不是:qp=0 的 h264 |
61
msg7086 2022-06-02 00:18:02 +08:00 1
> 那这是不是因为熵编码还不够优化,方法还不够好呢?
够好了。只是熵编码是有理论极限的,这个极限远远比我们现在用的视频编码技术要惨。 比如,一集 30 分钟 1080P30 YUV420P8 的电视剧的容量大概是 168GB 。 其中的信息熵,少说也有 20G 以上。 也就是说,在你没有找到突破宇宙物理极限的方法之前,是绝对不可能无损压缩到信息熵容量以下的。 等人类科技发展到能够高速航行宇宙征服太阳系了都不一定能把这集电视剧无损压缩到 20G 以下。 而 15 年前的 x264 就可以轻易压缩到 500MB 。 你说的「更 smart 的熵编码算法」可能是在讨论数万年甚至数十万年后的科技了。 |
62
mikewang 2022-06-02 00:23:37 +08:00
首先,目前来看,Huffman 编码本身不够优秀,因为概率要是 2 的幂次方时才达到熵,压缩比不如算数编码。
其次,视频的压缩不仅要考虑压缩本身,还要考虑到播放的功能,比如跳跃到某时间点、流播放等等,所以“帧”“关键帧”等等概念还是有必要的。 然后,有损处理肯定是必要的,这种方式可以简单而又明显地减少文件大小。 这是一系列因素互相妥协的结果。不仅考虑到压缩比,还要考虑到解码效率,功能性等等。 |
63
msg7086 2022-06-02 00:50:58 +08:00 2
我又仔细读了一下你的帖子,再补充一些吧。
无损压缩本质上是从数据里尽可能去掉冗余数据,尽可能让残留的数据接近信息熵极限。 视频编码有很多步骤都是去掉冗余数据,减少信息量的行为。 你说的运动预测帧内预测频域变换这些,都属于去掉冗余数据,减少信息量的行为。 熵编码是无损压缩算法里比较低效率的一种,因为它是介质特征无关的编码。 一个工程师拿到了熵编码以后,他肯定会想办法去改进它,比如增加对介质特征有关的处理。 你说了「通用压缩方法还没有发现这些重复」,就是因为这些重复数据不能被通用压缩方法所发现,而需要针对特征的算法来辅助发现。 比如说有一张图片,我们做一个淡出淡入的效果,从图片过渡到全黑画面,30 帧。 这 30 帧,每帧的数据都不一样,因为他们的亮度不一样。 如果你要直接做熵编码,效率就非常低,因为熵编码不会考虑大段数据同步偏移的情况。 而视频编码器就可以针对这种场景进行优化。 不管熵编码效率有多高,视频编码器总是能站在熵编码的基础上继续进行改进,加入针对特征的处理。 |
64
msg7086 2022-06-02 01:08:39 +08:00 3
然后像#61 以及其他人说的一样。
视频的帧是它的硬性特征。你播放视频的时候,就是一帧一帧播放的,你不可能脱离帧的概念去编码。 比如播放蓝光光碟的时候,播放器是逐步读取文件,一帧一帧解码的。 不可能先花 20 分钟,把整个光盘 50G 内容全部读取出来,然后在 256G 的内存里解压缩,然后再开始播放吧? 算法必须要有办法把解码每一帧的数据限制在一定的范围内。 比如你要解码第 10000 帧,那么就必须要在读取 10000 的前后几十帧之后就能解码出 10000 帧。 再比如串流播放,像是直播,你不可能先让观众等个半小时,等直播结束了,打包熵编码完了以后再播出吧。 现在的视频编码器技术都是那些电视台或者视频音频相关的企业资助开发的。 就算你说的能突破宇宙极限的熵编码存在,谁投钱给你去研发呢。 你说 NHK 或者 BBC 投几千万给你研发一个让观众等半小时才能看到节目的编码技术吗? 没钱还开发个 P 。 其实就算是视频编码圈子内部也是这样。你看看 VP9 ,没有商业环境支撑,现在是什么个鬼样。这已经是有谷歌这个金主投钱的结果了。反观 x264 x265 这种商业产品,有钱才有动力开发,才能把编码标准发挥到比较好的状态。HEVC 2013 年定稿,x265 2013 年就开始开发,到前几年就已经成熟了基本停止开发了,最多折腾些 HDR 之类的新技术。AV1 2018 年定稿,现在还是半个笑话,连个成熟好用的编码器都没有,至今还只在在线视频网站内部用。 |
65
wizardyhnr 2022-06-02 01:48:02 +08:00
png 就是无损的啊,下一代 jpeg xl 无损压缩可以比 png 大概再小一半。楼主可以研究一下
|
66
xuboying 2022-06-02 11:31:20 +08:00
虽然完全是个外行,但是感觉可以这么解释,视频采集制作是 CMOS 的记录结果,但是播放是给人眼球接收的。CNOM 记录了额外的人眼球消化不了的信息,所以可以用额外的技术剔除这些信息,减少文件尺寸。如果视频是 CMOS 记录,给电子眼看,那么现在所谓的高清编码输出对电子眼来说就是‘AV“画质。
|
67
whusnoopy 2022-06-02 11:58:09 +08:00
只说视频,如果内存够大,可以把编码后的视频文件都解码成帧到内存里(或别的显存缓存什么的都行),给显示设备输出时一帧一帧给就是了
实际情况是很多场景内存不够大,怎么把编码后的视频文件输出给显示设备呢?只能一段一段给,这时候 H.264 之类基于帧和前后压缩补偿就有意义了,看哪段取哪段,源文件也只用读一部分,内存里解码后的也只要放一部分 还有就是视频播放不一定是顺序的,会跳着看或拖回去,如果是全解码到内存当然可以直接操作,但如果每一帧都依赖前面所有帧信息才能得到,这就和全量解码没区别了,所以要有存全部信息的关键帧,后面跟若干差异帧,跳到指定位置时,用最近的一个全量信息关键帧,加到当前位置中间的差异帧做计算就好 |