图像信息隐藏

数字图像处理   2023-12-25 22:33   101   0  

信息隐藏的基本特征

不易察觉型

· 也叫透明性隐蔽性,是指秘密信息的嵌入不改变原数字载体的主观质量和统计规律,不易被观察者和监视系统察觉。 

鲁棒性

· 指嵌入水印后的数据经过各种处理操作和攻击操作后,不导致其中的水印信息丢失或破坏的能力。

· 如图像文件经过缩放、裁剪、旋转、有损压缩等操作,隐藏信息不丢失。 

隐藏容量

· 它是指在隐藏秘密数据后仍满足不易觉察性的前提下,数字载体中可以隐藏秘密信息的最大比特数

图像信息伪装技术

伪装的基本原理

· 任何多媒体信息,在数字化时,都会产生冗余(数据冗余与感官冗余),冗余也可视为一种物理随机噪声,而人的感观系统对这些随机噪声是不敏感的。

· 伪装就是利用这个原理,试图用秘密信息比特替换掉冗余数据(随机噪声),以达到隐藏秘密信息的目的。

图像的冗余空间

· 图像的低4bit,我们通常认为可以做隐藏信息的空间,也就是载体的冗余空间。

31251_wujz_3620.png

· 由上面的对比可以看到,虽然图像矩阵的每个像素值都去掉了低4bit,但改变后的图像和原图像在给人的视觉上并没有太大的变化,因此可以认为低4bit是冗余空间,可以改变,这是可以进行图像嵌入伪装的理论基础

直接4Bit替换法

· 直接用秘密图像像素点高4位替换载体图像像素值的低4位

· 首先,提取图像信息并分层:

cover = imread('lenna.bmp');
data = cover;

msg = imread('woman.bmp');
[row, col] = size(cover);

# 把图像的R层作为载体图像
cover1 = cover(:, :, 1);

39652_lzrv_2224.png

· 然后,我们处理载体图像和秘密图像的低四位:

# 置载体图像R层的低四位为0
cover1 = bitand(cover1, 240);

# 置秘密图像的低四位为0
takemsg4 = bitand(msg, 240);

# 将秘密图像的高四位右移4位
shiftmsg4 = bitshift(takemsg4, -4);

39912_ak80_5637.png

· 让我们进行图像隐藏并保存:

# 图像隐藏
cover1 = bitor(cover1, shiftmsg4);

# 写回并保存
data(:, :, 1) = cover1;
imwrite(data, 'mix.bmp');

40123_qa6m_9499.png

· 然后我们来尝试提取一下秘密图像:

# 提取秘密图像信息
data = imread('mix.bmp');
[row, col] = size(data);
A = data(:, :, 1);

# 提取隐蔽图像的低四位
A = bitand(A, 15);

# 将提取的秘密图像的低四位左移四位
A = bitshift(A, 4);

40363_abxi_1555.png

· 对于隐藏在R、G、B各层的隐蔽载体,会产生泛红、泛绿、泛蓝现象。

· 为了改进,可以将秘密图像像素值的高四位分别藏于载体图像R、G、B层像素值的最低位或次低位

· 还有一个问题,直接4Bit替换法鲁棒性弱、安全性差(无密钥机制):

40828_tu9u_4261.png

图像置乱

· 所谓“置乱”,就是将图像的信息次序打乱,将a像素移动到b像素的位置上,b像素移动到c像素的位置上……使其变换成杂乱无章难以辨认的图像。

· 置乱实际上就是图像的加密,与加密保证安全性不同的是,置乱的图像作为秘密信息再进行隐藏,在提高系统安全性的同时可以很大限度的提高隐蔽载体的鲁棒性

· 图像置乱的模板变换如下:

41442_ymem_9376.png

· 置乱的优点——增加图像伪装的鲁棒性

· 例子:

41541_a8i1_4896.png

空域下隐藏:替换隐写技术

· 我们知道,任何多媒体信息,在数字化时,都会产生物理随机噪声,而人的感观系统对这些随机噪声是不敏感的。

· 替换技术就是利用这个原理,试图用秘密信息比特替换掉随机噪声,以达到隐藏秘密信息的目的。

LSB替换隐写

·  LSB是Least Significant Bits的英文缩写,对应的中文意思是:最不重要位。有时也称之为最低有效位或简称最低位

· 隐写过程如下:

  1. 在c中根据密钥k选择l(m)个像素。

  2. 对于选取的每个像素灰度值,若其LSB与要嵌入的信息比特相同,不进行更改;否则,执行下一步;

  3. 用秘密信息比特取代原灰度值的LSB,而高7位保持不变,修改后的图像即为s。

· 看一个例子:

45416_i019_6366.jpg

· 要在原图像嵌入一个字符A,首先知道A的ASCII码为65,转换为对应二进制为01000001,然后一个个对着嵌入即可。

· 120要嵌入0,不用动;131潜入1,不用动;251要潜入0,要减一,变成250;以此类推。

· 如果遇到奇数要嵌入0,则要变成1,即+1;遇到偶数要嵌入1,则要变成0,即-1

二值图像的隐写(重点)

· 解决方案1:利用图像特定区域中黑像素的个数来编码秘密信息。

· 定义符号image.svg?P_1(B)代表一个区域Block内1值的占比。如image.svg?P_1(B)=0.5,代表图像中一半白一半黑。

· 如果image.svg?P_1(B)>0.5,则代表嵌入1,否则嵌入0。但这样就会出现问题:

  1. 如果一个块内要嵌入0,但是白色比黑色多,即image.svg?P_1(B)<0.5,就要找边缘去填充一些黑点image.svg?P_1(B)>0.5。但如果本身这么块里面黑白比例很悬殊,比如全是黑或者全白,那说明这一块不适合嵌入,应该跳过

  2. 如果一个块内黑白像素点比例很接近,如白点的占比是0.51,应该嵌入1,但我想嵌入0,最方便的方法就是删掉一两个白点,但这样鲁棒性就很低,别人可以通过轻易加上一两个白点来破坏。因此我们需要优化我们的编码方案,原来我们的阈值是0.5,现在应该改为双阈值,即image.svg?P_1(B)<0.45的时候嵌入0,image.svg?P_1(B)>0.55的时候嵌入1,中间0.45到0.55我们称为隔离区,这样我们就可以增加鲁棒性,别人破坏的点可以更多一点。

  3. 对于第一点提到的问题,黑白比例悬殊就应该跳过这一块,因此我们需要设置最左边和最右边为无效块,但这样又会诞生一个问题,和第二点一样,一点点的变化很难区分是不是无效块,因此还是需要给出一小段距离用于容错

· 为了解决上述提出的问题,最终我们把image.svg?P_1(B)可能的取值分为下面几块:

46682_bup8_4535.jpg

· 上图是嵌入时候的规则,对于提取,可以放宽,就用是不是50%来判断即可。

· 边界点定义:对于某一个点,其相邻的8个方向的像素,只要有一个值和自身相反,就认为这个点是边界点。

· 如何修改边界点:直接取反即可。

· 边界扩散现象

  1. 如下图中,B很明显是个边界点,要取反:

    48298_hutq_7206.png

  2. 取反之后变为下图,此时C就变为边界点了,那C也应该取反,但这不是我们所希望的,如果一直取反下去,就会造成突出或凹入的毛刺。

    48391_jyks_6025.png

  3. 为了防止这种边界扩散现象,只需要对取反后的点+0.01,这样C和B就不是相反了,就不会一直取反下去了。

· 我们来把这些区域切割开来分类讨论

46913_iox5_2234.jpg

  1. 对于落入b区间的比例,假设是左边的b区间,如果要嵌入0就很好,直接嵌入就行;如果要嵌入1,则多加白点,让他进入左边的a区间,即无效块,让这一块无效;因为如果要多加白点很难实现。

  2. 对于落入c区间的比例,假设是左边的c区间,如果是要插入0,则落入①、②的话交给b区间处理即可,若落入③则多加一点白点,让它往②靠;如果是要插入1,则落入①、②的话直接加白点使其无效,若落入③则交给d处理即可。

  3. 对于落入e区间的比例,其实就是b、c都处理了,这里不再赘述。

· 接下来我们讨论一下这个算法的性能,其实就是在讨论R0、R1的距离和λ

· 如果R1和R2的距离增大

  1. 鲁棒性增加,因为中间无效区域增大,容错性大。

  2. 无效区a变窄,有效区c、d变宽,容量增大

  3. 要修改的像素点数量变多,这样就会使边界不足现象增加

· 如果λ变

  1. 鲁棒性增加,因为中间无效区域增大,容错性大。

  2. 无效区a变窄,有效区c、d变宽,容量增大

  3. 要修改的像素点数量变多,这样就会使边界不足现象增加

· 可以发现,无论是R0、R1的距离增大还是λ变大,导致的结果都一样

· 对于提高透明性的讨论:

  1. 只修改边界点

  2. 引入无效块以保证修改的边界点数量尽可能少。

  3. 防护边界扩散现象

  4. 可以先置乱块,再嵌入。

  5. 对于查找边界点进行取反的过程,可以按置乱的顺序去查找而不是从上到下从左到右。

· 对于容量的讨论:

  1. 一张512*512的图像,可以分成2601块10*10的块。按照上面的算法筛选完后,只有105块可用,即105个bit可以嵌入,即10几个byte,即10几个字符,太少了。

  2. 根据上面的结论,增加R0、R1的距离,增大λ,可以增加容量。

  3. 选用尽可能大尺寸的图像也可以增加容量。

  4. 采用合适的二值化图像算法来生成二值化图像。我们一直使用的是阈值二值化,可以尝试误差扩散抖动技术来二值化,这样产生的二值化图像可以大幅提升容量。

· ----------------------------------------------------------------------

· 解决方案2:利用游程长度编码(Run Length Encoding,RLE)

· 水平方向扫描二值图像,在一条扫描线上做编码。如果左右的值一样,则标记为一个游程,记录第一个的位置以及长度

49411_quny_7657.png

· 然后,通过游程长度的奇偶性来决定嵌入0还是1,假设我规定嵌入1时游程长度为偶数,嵌入0时长度为奇数,这样只需要把边界的那一个像素进行翻转即可实现。

· 这样保证了透明性,因为只修改了边界。

· 容量也不错,这取决于边界点的数量,即游程的数量。

· 但是鲁棒性很差,因为只要我对图像的长度做任意修改,就完全破坏了原来的游程。

· 还有一点,一开始就要规定好是修改头的点还是尾的点,一旦规定后续不能修改!

· 例题:给出游程编码<a0, 3>,<a1, 4>,<a2, 4>,<a3, 5>,嵌入规则为【0-长度为偶数,1-长度为奇数】,约定游程长度在2i到2i+1变换,现要求嵌入1100时,写出新的游程编码。

  1. 首先我们把题目给出的已有的游程编码写出来:

    49766_zlno_3805.png

  2. 然后开始重新编码,第一个是1,a0长度为奇数,不用变。

  3. 第二个是1,a1长度为偶数,长度要变,因为给出范围是2i-2i+1,因此4要变成5,吃掉一个a2的位置:

    49861_iu9u_1145.png

  4. 然后第三个是0,此时a2的长度已经从4变为3了,因此a2也要变,根据范围,a2长度3要变成2,多出来的位置给a3:

    49952_xjpz_5240.png

  5. 最后一个是1,此时a3已经是奇数了,所以不用管。

  6. 最后得到的新的游程编码为<a0, 3>,<a1, 5>,<a2, 2>,<a3, 6>。

· 值得注意的是,游程要求长度至少为2,如果是1则是无效游程,因为如果它被翻转,就和其它游程融合了,这样会改变游程的数量

· 最简单的处理方法就是先对图像做预处理,先对只有一个像素的游程点做翻转。大部分情况下,单像素的游程基本都是噪声。

频域下隐藏:离散余弦变换(DCT)

· DCT是一种实数域变换。在中频中做信息隐藏,同时保证了鲁棒性透明性

两点法

· 先把图像分成一个个8*8的小块,分别选其中的两个点,如(μ1, v1),(μ2, v2)。

· 若Bi(μ1, v1)>Bi(μ2, v2),代表隐藏1;如果相反则交换两系数。

· 若Bi(μ1, v1)<Bi(μ2, v2),代表隐藏0;如果相反则交换两系数。

· 这里的交换两系数指的是:我规定了第一个值比第二个值大才嵌入1,现在这个块要嵌入1,但第一个值比第二个小,这个时候我在图像上直接把这两个值对调。

· 两点法的特点是:

  1. 不需要原始图像。

  2. 对JPEG图像压缩是鲁棒的。

三点法

· 同样的,先把图像分为一个个8*8的小块,然后接下来用伪代码展示:

# 取三个点
Bi(u1, v1);
Bi(u2, v2);
Bi(u3, v4);

# 获取三者中谁最大谁最小
max = max(...);
min = min(...);

# 定义一个系数D
D = ...;

# 定义一个值MD,用于后续衡量
MD = ...;

# 若规定嵌入1的时候,Bi(u3, v3)要是三者中最大的
if Bi(u3, v3) == max:
    # 让Bi(u3, v3)大的更明显,D人为设定
    Bi(u3, v3) = Bi(u3, v3) + D;
else if max-Bi(u3, v3) < MD:
    # Bi(u3, v3)与最大值离得不远
    Bi = max + D;
else:
    (设定该块为无效块)
    Bi(u3, v3) = (Bi(u1, v1) + Bi(u2, v2)) / 2;

# 若规定嵌入0的时候,Bi(u3, v3)要是三者中最小的
if Bi(u3, v3) == min:
    # 让Bi(u3, v3)小的更明显
    Bi(u3, v3) = Bi(u3, v3) - D;
else if Bi(u3, v3) - min < MD:
    # Bi(u3, v3)与最小值离得不远
    Bi(u3, v3) = min - D;
else:
    (设定该块为无效块)
    Bi(u3, v3) = (Bi(u1, v1) + Bi(u2, v2)) / 2;

· 设置为无效块的方法很简单,就是把Bi(u3, v3)的值设置为Bi(u1, v1)和Bi(u2, v2)的中间即可:

51967_rapv_7176.png

· 例题:使用三点法隐藏,给定规则为,隐藏1的时候,令Bi(u1, v1)>Bi(u3, v3)+D且Bi(u2, v2)>Bi(u3, v3)+D,问:

  1. 补全余下的规则,即隐藏0的规则是什么?

    1的时候Bi(u3, v3)要小的很明显,那么0的时候就让Bi(u3, v3)大的很明显即可。

  2. 已知三个点的DCT系数值为(1.6, 2.1, 1.0),(0.7, 1.2, 1.8),(0.9, 1.9, 1.4),问根据给定规则能提取出什么?

    第一个,Bi(u3, v3)是最小的,那就是提取出1;第二个,Bi(u3, v3)是最大的,那就是提取出0;第三个Bi(u3, v3)处于二者中间,无效。

博客评论
还没有人评论,赶紧抢个沙发~
发表评论
说明:请文明发言,共建和谐网络,您的个人信息不会被公开显示。