H264编码原理(无损压缩)

无损压缩

DCT变换

在这里插入图片描述
经过有损压缩后的数据是分散在二维图标中的各个节点上,数据比较分散时不利于压缩,通过DCT变换,所有的分散数据都被集中在一块,左上角右下角等等。
DCT可以将数据由分散变为集中,利于压缩处理数据。
在这里插入图片描述
在DCT处理前是第一幅图中一个个凸起的方块,可以看出数据量十分分散,但是处理后将所有数据都放在了一个角落,变得聚集,这样非常有益于有损压缩的数据处理。

VLC压缩

在这里插入图片描述
当所有的数据通过DCT变换之后,就可以进行具体的无损压缩了。
所谓VLC就是可变长的编码,原理就是将26个字母,常出现的字符使用短码进行表示,将不经常出现的用长码进行表示,例如图中所示,字母A使用二进制11表示,字母Z利用二进制00000001011进行表示,这样一来可以将数据压缩的非常小。
当整个数据中的高频字符越多时,压缩效果就越好,这里的字符A只是一个例子,实际上可以是任何一个数据块。

CABAC压缩

在这里插入图片描述
所谓CABAC压缩就是上下文适配的二进制编码。
通过图中对比,输入大量的视频数据时,VLC的一直生成的数据量都很小,且平均,因为对他来说前后并没有关系。
但是CABAC可以看出,一开始略大一些,但是后面逐渐越来越小,因为它是有山下文记录的。

H264编码流程

在这里插入图片描述
图中蓝颜色的Fn是当前待压缩的视频帧,是一个IDR帧,即gop中的第一帧,因为是第一帧,是关键帧,所以肯定是要使用帧内压缩,所以第一步是选择帧内预测模式即如下图所示。
在这里插入图片描述
当选择好帧内预测模式时,就可以进行帧内预测,把每一个宏块都计算出来。
如下图所示:
在这里插入图片描述
然后将预测得到的全部图像数据与当前帧原数据进行对比,得到残差值,如下图所示:
在这里插入图片描述
得到残差值后进行转换,如下图所示:
在这里插入图片描述
经过转换后进行量化,也就是无损编码,如下图所示:

在这里插入图片描述
最后就是后边的拆包打成NAL头,然后数据分发,也就是数据吐出去了。
做帧间压缩时,就是以Fn-1为例,即需要参考前一帧(非b帧),首先要经过运动评估,如下图所示:

在这里插入图片描述
运动评估就是对所有的宏块进行匹配查找,找到后拿到的就是运动矢量,如下图所示:

在这里插入图片描述
得到运动矢量后,在与当前帧进行对比得到残差值,如下图所示:
在这里插入图片描述
得到残差值之后的流程与前面说的帧内压缩的得到残差值后的流程一样。

H264解码流程

在这里插入图片描述
H264的解码流程实际就是上面编码流程的逆向操作,。可以对比下解码流程图和上边编码流程图的粉色部分(解码流程)。

H264参考资料

  • H.264_MPEG-4-part-10-White-Paper
  • https://enwikipedia.org/wiki/Advanced_Video_Coding

第一个是白皮书,有H264整个变解码的流程
第二个网址介绍了整个H264不同编码级别,其区别是什么,以及现有的一些H264的具体实现,那个功能更强等。
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
哈夫曼编码是一种无损压缩算法,它可以通过将出现频率较高的字符用较短的编码表示,从而减少存储所需的位数。下面是用哈夫曼编码实现无损压缩的步骤: 1. 统计待压缩文件中每个字符出现的频率。 2. 根据字符频率构建哈夫曼树,其中频率越高的字符离根节点越近。 3. 根据哈夫曼树生成每个字符的编码,其中左子树路径上添加0,右子树路径上添加1。 4. 将编码后的字符按照哈夫曼编码表进行替换,从而实现压缩。 下面是一个Python实现的例子: ```python import heapq import os class HuffmanCoding: def __init__(self, path): self.path = path self.heap = [] self.codes = {} self.reverse_mapping = {} class HeapNode: def __init__(self, char, freq): self.char = char self.freq = freq self.left = None self.right = None def __lt__(self, other): return self.freq < other.freq def __eq__(self, other): if(other == None): return False if(not isinstance(other, HeapNode)): return False return self.freq == other.freq def make_frequency_dict(self, text): frequency = {} for character in text: if not character in frequency: frequency[character] = 0 frequency[character] += 1 return frequency def make_heap(self, frequency): for key in frequency: node = self.HeapNode(key, frequency[key]) heapq.heappush(self.heap, node) def merge_nodes(self): while(len(self.heap)>1): node1 = heapq.heappop(self.heap) node2 = heapq.heappop(self.heap) merged = self.HeapNode(None, node1.freq + node2.freq) merged.left = node1 merged.right = node2 heapq.heappush(self.heap, merged) def make_codes_helper(self, root, current_code): if(root == None): return if(root.char != None): self.codes[root.char] = current_code self.reverse_mapping[current_code] = root.char return self.make_codes_helper(root.left, current_code + "0") self.make_codes_helper(root.right, current_code + "1") def make_codes(self): root = heapq.heappop(self.heap) current_code = "" self.make_codes_helper(root, current_code) def get_encoded_text(self, text): encoded_text = "" for character in text: encoded_text += self.codes[character] return encoded_text def pad_encoded_text(self, encoded_text): extra_padding = 8 - len(encoded_text) % 8 for i in range(extra_padding): encoded_text += "0" padded_info = "{0:08b}".format(extra_padding) encoded_text = padded_info + encoded_text return encoded_text def get_byte_array(self, padded_encoded_text): if(len(padded_encoded_text) % 8 != 0): print("Encoded text not padded properly") exit(0) b = bytearray() for i in range(0, len(padded_encoded_text), 8): byte = padded_encoded_text[i:i+8] b.append(int(byte, 2)) return b def compress(self): filename, file_extension = os.path.splitext(self.path) output_path = filename + ".bin" with open(self.path, 'r+') as file, open(output_path, 'wb') as output: text = file.read() text = text.rstrip() frequency = self.make_frequency_dict(text) self.make_heap(frequency) self.merge_nodes() self.make_codes() encoded_text = self.get_encoded_text(text) padded_encoded_text = self.pad_encoded_text(encoded_text) b = self.get_byte_array(padded_encoded_text) output.write(bytes(b)) print("Compressed") return output_path """以下是解压缩的代码""" def remove_padding(self, padded_encoded_text): padded_info = padded_encoded_text[:8] extra_padding = int(padded_info, 2) padded_encoded_text = padded_encoded_text[8:] encoded_text = padded_encoded_text[:-1*extra_padding] return encoded_text def decode_text(self, encoded_text): current_code = "" decoded_text = "" for bit in encoded_text: current_code += bit if(current_code in self.reverse_mapping): character = self.reverse_mapping[current_code] decoded_text += character current_code = "" return decoded_text def decompress(self, input_path): filename, file_extension = os.path.splitext(self.path) output_path = filename + "_decompressed" + ".txt" with open(input_path, 'rb') as file, open(output_path, 'w') as output: bit_string = "" byte = file.read(1) while(len(byte) > 0): byte = ord(byte) bits = bin(byte)[2:].rjust(8, '0') bit_string += bits byte = file.read(1) encoded_text = self.remove_padding(bit_string) decompressed_text = self.decode_text(encoded_text) output.write(decompressed_text) print("Decompressed") return output_path ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值