用于图像认证的半脆弱水印算法研究
4.2.2水印嵌入的实现
由于JPEG压缩的不变性,也就是说,如果一个DCT系数是经过某个预先选定的量化步长量化并取整得到的,只要后续的量化步长小于选定值,则这个DCT系数可以被精确重建,换句话说,如果某幅图像预先经过某个选定的质量因子的JPEG有损压缩,那么这幅图像可以对任何大于该选定质量因子的后续JPEG压缩保持不变,因为原始量化图像所有DCT系数都可以精确重建,而如果后续JPEG压缩的质量因子小于选定值,原始量化图像的DCT系数则无法恢复。这个需要预先选定的质量因子一般可以设定为人眼最低可以接受的图像质量因子,也就是说,任何低于该质量因子的图像被视为不可接受的。JPEG标准推荐图像的质量因子在50一75之间均为视觉上可以接受的,因此我们可以选择50作为预先设定的质量因子,其对应的量化表为DCT系数的量化步长。
利用前面所述的JPEG压缩的不变性,首先将原始图像的8*8块DCT系数块按预定的质量因子对应的量化表进行量化,通过对量化后的DCT系数进行”微调”来嵌入水印信息比特,再进行DCT反变换得到水印图像。相同的过程提取出水印,并将其与原始水印信息匹配的百分比和设定的阈值比较,决定是否通过认证。该算法能够抵抗所有大于预定质量因子的攻击。
算法中水印信息的选择是基于图像内容特征的。一种简单的基于图像内容的特征是每个分块灰度值的均值的最重要位(MSB ,the Most Significant Bit),即最高位。水印的嵌人算法采用了一种无损数据隐藏方法环形直方图算法(Circular His-togram Algorithm)。首先把待嵌人水印的图像分成8*8块,每块64个像素通过密钥被随机地分为A和B两组,在每一组中,灰度值直方图映射为一个环形,环形的周长为256个单位,等分为Q个区间,每个区间分的弧长为256/O若一个像素灰度值落在某个区间之内,则这个区间的权重加1,这样每一组共有犯个权重加载在环上。计算每组环上的加权平均值,从统计学的角度分析,由于A, B两组的像素都是随机选择的,因而A, B两组的加权平均值应非常接近或近似相等。为了在每一个8*8块中嵌入1比特水印信息,将块中像素的灰度值作如下修改:
若嵌人比特为”1 ” C`=C+P当像素在A组中;
C`=C-P当像素在B组中;
若嵌入比特为”0″ C`=C-P当像素在A组中;
C`=C+P当像素在B组中;
其中c为待嵌入水印图像的像素灰度值,c为修改后,即嵌入水印后图像的像素灰度值,P= 256/Q。若嵌入比特”1″,则A组中的所有像素灰度值增加P,对应到环上即像素灰度值均顺时针方向偏转了一个区间,每个像素在环上的位置均顺时针转了360/Q度。相应的B组中的所有像素均逆时针方向偏转了相同的度数。这样当嵌入比特”10的时候,A组的加权平均值大于B组,且每个图像块灰度值的均值,即选定的图像特征保持不变。嵌入”0″比特的情况同理可得。通过这种环形直方图无损数据隐藏算法将由图像内容特征产生的水印信息嵌入了预压缩后的图像〔9〕。
4.2.3水印检测的实现
将接收到的待验证的图像先按预定质量因子压缩,恢复出预压缩后的水印图像;再依照环形直方图算法提取水印:将图像8*8分块按选定的密钥随机分成A, B两组,并映射到环上,计算A, B两组对应环的加权平均值。如果A组的加权平均值大于B组,则提取出比特”1″,反之则提取出比特”0″。图像认证过程将提取出的水印比特与对恢复出的预压缩图像再次计算得到的特征信息进行比较匹配,若匹配的百分比大于设定的域值则图像通过认证,反之判断为遭受过恶意篡改。由前面所说的JPEG压缩的不变性可知,该算法可以抵抗任何高于预定质量因子的JPEG压缩。并能根据认证过程中不匹配的比特定位遭受篡改的位置,精度为8*8块。由于嵌人的水印信息是基于图像内容特征的,每幅图像嵌人的比特信息必定各不相同,因而可以有效地抵抗共谋攻击〔10〕。
论文中用到的纠错编码现在就可以发挥它的优势了。程序实现到此,论文用纠错解码的方法得到36*4的提取水印,把这个水印和之前植入的水印信息进行比较,就可以作出是否被篡改的判断了。
for i=1:36
s1(i)=x1(i,1)+x1(i,2)+x1(i,3)+x1(i,5);
s2(i)=x1(i,2)+x1(i,3)+x1(i,4)+x1(i,6);
s3(i)=x1(i,1)+x1(i,2)+x1(i,4)+x1(i,7);
s1(i)=mod(s1(i),2);
s2(i)=mod(s2(i),2);
s3(i)=mod(s3(i),2);
if (s1(i)==0s2(i)==0)(s3(i)==1)
x1(i,7)=~x1(i,7);
elseif (s1(i)==0s2(i)==1)(s3(i)==0)
x1(i,6)=~x1(i,6);
elseif (s1(i)==0s2(i)==1)(s3(i)==1)
x1(i,4)=~x1(i,4);
elseif (s1(i)==1s2(i)==0)(s3(i)==0)
x1(i,5)=~x1(i,5);
elseif (s1(i)==1s2(i)==0)(s3(i)==1)
x1(i,1)=~x1(i,1);
elseif (s1(i)==0s2(i)==1)(s3(i)==0)
x1(i,3)=~x1(i,3);
elseif (s1(i)==1s2(i)==1)(s3(i)==1)
x1(i,2)=~x1(i,2);
end;
end;
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)