前言
在之前的系列文章中,已经讨论了编码参数域的隐写。本文章将从另一个嵌入域方向叙述隐写:熵编码域。对于编码参数域来讲,修改编码参数将引起很多关联的频域系数发生改变,此举对音频的内容修改很大,也不能精确控制,最终导致对统计特性的改变也很大。
相反地,量化系数修改的方式更加接近原子操作,能够定量精确控制音频内容质量修改和噪声扩散。当然,随意修改熵码字也会导致码流膨胀,进一步导致编码器崩溃。从可行性角度来看,隐写算法要兼容编码标准、有约束地修改量化系数,保证修改后的哈夫曼码流的长度保持不变。
一. 三种基本嵌入方式
以下三种嵌入方式都是基于MP3码流结构。
1.1 等长熵码字替换嵌入
在编码标准中提供了很多张哈夫曼码表,每张码表都会存在很多码字长度相等的哈夫曼码字。所以可以使用码长相同的哈夫曼码字替换来嵌入隐藏信息,采用等长码字替换方式是保持码流长度的前提之一。如下图替换例子:
此时替换是基于一个安全性假设:根据哈夫曼码字构造原理,码长相同的码字统计概率相近,所以导致等长哈夫曼码字替换对码字分布的影响很小。
1.2 系数符号位反转嵌入
根据MP3编码标准,非零系数使用一个比特来表示其符号信息,其中比特“0”代表正数,比特“1”代表负数。所以,通过反转编码符号位来嵌入信息也不会改变原始码流的结构和长度。当然,为了不影响音频的听觉质量,对修改符号位的位置以及系数值有一定的限制。
此时的替换是基于一个安全性假设:由于量化系数服从0值对称的广义拉普拉斯分布,所以系数符号位翻转能够对系数直方图攻击免疫。
1.3 linbits位LSB嵌入
当系数值超过15时,就需要使用linbits位来编码系数溢出部分,每张哈弗曼码表分配的linbits位长度是固定的,这样的linbits位的编码规则等价于定长编码。所以采用linbits位LSB嵌入方式也能够保持修改后码流的结构与原始码流结构的一致性。
此时的替换基于一个安全性假设:linbits为LSB嵌入的安全性与通常的LSB算法是类似的
二. 码字映射表的构造
2.1 解决码字替换规则问题
令表示第k张哈夫曼码表中的第i个码字,
表示与码字
对应的频域系数对。因此,对
,可相互替换的哈夫曼码字对
和
需要满足如下三个条件:
(1)哈夫曼码字长度。哈夫曼码字
和
码字的长度相等,如下数学表达形式:
(2)系数符号位个数。频域系数对
和
具有相同的符号位个数,如下数学形式:
其中
函数的定义如下:
(3)linbits位标志。频域系数
linbits位的存在性与
一致。当然,
和
也同样满足此条件。
2.2 构造映射表
映射表在构建时,需要使得码字替换对频域系数变化造成的影响尽可能地降低,同时需要控制搜索算法的时间复杂度。具体有三个步骤,如下:
步骤一:先对码字搜索空间采取Zig-zag方式进行遍历。以7号码表的Zig-zag搜索为例,如下:
步骤二:令表示包含第k张码表中所有哈夫曼码字的集合,由此可将
分成两个子集:
和
,如下:
集合:可用码字,也就是可隐写码字,可被用来嵌入信息
集合:都是不可用于隐写的哈夫曼码字
和
可以通过迭代的方式生成:首先将
初始化为
,如果码字对
满足可替换码字的三个限定条件,就将
和
放入
,否则将它们放入
;重复上述操作,直到
为
。
步骤三:对于可用码字空间中的每个哈夫曼码字
,按照它被放入
的顺序进行编码。为了编码嵌入信息比特“0”和“1”,进一步将
划分为两个子空间:
和
。
:放入哈夫曼码字
序号为奇数,哈夫曼码字表示嵌入比特“1”
:放入哈夫曼码字
序号为偶数,哈夫曼码字表示嵌入比特“0”
到此为止,就完成了码字映射表的构建,依据映射表就可以实现比特信息的嵌入,且每个中可隐写1比特信息码字。
举例 1
搜索码字空间划分为三个区域和
,三个区域都是封闭的,每个区域独立进行搜索过程。下图描述了区域
的搜索过程,搜索的顺序按图中的箭头方向,实心点标注的哈夫曼码字分别是
,这些哈夫曼码字的长度都等于8。
按照搜索顺序,可以将这6个哈夫曼字依次组成3个可替换的哈夫曼码字对,记为。根据之前讨论过的划分规则,
和
被划分入
;
和
被划分入
。具体的哈夫曼码字替换关系图可见如下:
2.3 嵌入函数与提取函数
根据2.2中构造的映射表,码字到二进制映射的关系可解释为如下:
上式子中h表示哈夫曼码字。
类似情况,逆映射二进制到码字的映射关系可解释为如下:
上式子中是一对可以相互替换的哈夫曼码字对,s是对应比特流的当前状态值。而且,每个码表都能形成对应的映射表。
三. 码字符号位修改方法
选择不同的符号位置会影响到隐写算法的安全性和负载率的平衡,找到最合适的位置,就可以达到最优的安全负载临界点。大值区和小值区的系数都需要进行哈夫曼编码,并且所有的非零系数的符号位都是一个比特,当然零值区系数是不需要编码的。
在传输时,最大的隐藏负载率是1比特/非零系数。在做嵌入操作时,需要修改系数的符号位,也就是需要反转量化系数的值,比如:
从以上例子可以看出,绝对值较大的系数,翻转其符号位会造成系数修改幅度很大,有可能会引起较为严重的感知失真。所以,为了避免对大值系数的修改,隐写算法可以设置阈值T,控制嵌入时可选用的修改系数范围。例如,当系数绝对值大于预设的阈值时,那么当前系数的符号位就不用来进行信息的嵌入。
以下举出四个不同阈值和码率下可用系数占比:
根据待嵌入的消息比特,可以用来判定是否需要反转系数
的符号位.
四. Linbits位修改方法
根据哈夫曼码流结构和量化系数的分布特点,linbits位域比系数符号位域和码字替换域的可利用空间要小很多,从而导致linbits位嵌入的隐写负载率较低。为了提高隐写容量,可以在某些位置使用更大强度的嵌入方式,也就是采用多个最低位嵌入来代替LSB嵌入方式。
利用代表第i个系数的linbits位嵌入前的数值;
代表第i个系数的linbits位嵌入后的数值;m代表待嵌入的信息值;k代表嵌入强度,k可以理解为使用的最低比特位。由此可得嵌入算法和提取算法如下: