当前位置:文档之家› 数字水印算法的C++实现

数字水印算法的C++实现

实验报告实验名称:数字水印算法实现数字水印算法的C++实现[摘要]通过在原始数据中嵌入秘密信息--水印来证实数据的所有权。

这种被嵌入的水印可以是一段文字、标识、序列号等,而且这种水印通常是不可见或不可察的,它与原始数据紧密结合并隐藏其中,并可以经历一些不破坏源数据使用价值或商用价值的操作而能保存下来。

数字水印技术除了应具备信息隐藏技术的一般特点外,还有着其固有的特点和研究方法。

在数字水印系统中,隐藏信息的丢失,即意味着版权信息的丢失,从而也就失去了版权保护的功能,也就是说,这一系统就是失败的。

由此可见,数字水印技术必须具有较强的鲁棒性、安全性和透明性。

本文是关于在24位宿主图像的文档说明。

[关键词]数字水印标识安全性宿主图像水印图像1. 算法实现思路1.1 数字水印的提出及研究现状1994年在一次国际重要学术会议上由Tirkel等人发表了题目为“A digital watermark”的第一篇有关数字水印的文章,当时他们已经意识到了数字水印的重要性,提出了数字水印的概念及可能的应用,并针对灰度图像提出了两种向图像最低有效位中嵌入水印的算法。

1996年在英国剑桥牛顿研究所召开了第一届国际信息隐藏学术研讨会,标志着信息隐藏学的诞生,而作为信息隐藏学主要分支之一的数字水印技术的研究也得到了迅速的发展。

到1999年第三届国际信息隐藏学术研讨会,数字水印成为主旋律,全部33篇文章中有18篇是关于数字水印的研究。

我国近年来已有少数的研究所和大学开展了对水印技术的研究工作,如:中科院自动化研究所的模式识别国家重点实验室、天津大学图像信息中心等。

数字水印的研究引起了各种学科的研究人员的兴趣,但受关注的程度不及国外,研究的人员不多,研究的领域不广,从理论和实际成果两方面来看,国内在数字水印方面的研究工作还处于刚起步阶段。

我国已明确表示:所有的知识产权保护和安全认证问题不可能依靠国外的力量,必须由我们自主开发解决。

因此,无论从学术研究角度,还是从应用技术的角度,开展数字水印的研究都具有十分重要的意义。

1.2 程序开发思路因特网的出现以及计算机、扫描仪和打印机的广泛使用使得数字化多媒体数据的获取、交换和传输变得异常简单。

但是通过网络传播数据也使有恶意的个人或团体在没有得到数据文件所有者许可的情况下能肆意地复制和传播有版权保护的文档。

数字水印技术则为这种问题提供了一个潜在的解决方案。

数字水印(Digital Watermarking )是往多媒体数据(如图像、声音、视频信号等)中添加某些数字信息以达到版权保护等作用。

如果没有鲁棒性(Robustness )的要求,水印与信息伪装技术上的处理本质上是完全一致的。

在绝大多数情况下我们希望添加的信息是不可察觉的(Imperceptible ),并且希望攻击者在不破坏数据本身质量的情况下无法将水印去掉。

发展数字水印技术的原动力就是为了提供多媒体数据的版权保护。

1.3 数字水印的实现算法1) 空间域水印L.F.Turner与R.G.van Schyndel等人的空间域水印算法是最低有效位算法(LSB)与改进算法。

由于该算法是通过调整原始数据的最低几位来隐藏信息,使一般用户对于隐藏信息,在视觉上很难察觉。

虽然其有较大的信息嵌入量,但作为数字水印算法,因其基本原理限制,所隐藏的数字水印信息是极为脆弱的,无法经受一些有损的信号处理。

Bander等人提出的基于统计的数字水印方案(Patchwork)和纹理块映射编码方法则是空间域水印技术的典型设计。

Patchwork任意选择N对图像点,增加其一点的亮度的同时,相应降低另一点的亮度值。

通过这一调整过程完成水印的嵌入。

Pitas和Kaskalis利用“Patchwork”算法的基本原理,提出了数字图像签名的思想。

这种算法可以有效抵抗二次采样攻击与JPEG压缩。

2) 变换域算法基于变换域的技术可以嵌入大量比特数据而不会导致可察觉的缺陷,往往采用类似扩频图像的技术来隐藏数字水印信息。

这类技术一般基于常用的图像变换,基于局部或是全部的变换,这些变换包括离散余弦变换(DCT)、小波变换(WT)、傅氏变换(FT或FFT)以及哈达马变换(Hadamard transform)等等。

其中基于分块的DCT是最常用的变换之一,现在所采用的静止图像压缩标准JPEG也是基于分块DCT的。

最早的基于分块DCT的一种数字水印技术方案是由一个密钥随机地选择图像的一些分块,在频域的中频上稍稍改变一个三元组以隐藏二进制序列信息。

选择在中频分量编码是因为在高频编码易于被各种信号处理方法所破坏,而在低频编码则由于人的视觉对低频分量很敏感,对低频分量的改变易于被察觉。

该数字水印算法对有损压缩和低通滤波是稳健的。

另一种DCT数字水印算法是首先把图像分成8×8的不重叠像块,在经过分块DCT 变换后,即得到由DCT系数组成的频率块,然后随机选取一些频率块,将水印信号嵌入到由密钥控制选择的一些DCT系数中。

该算法是通过对选定的DCT系数进行微小变换以满足特定的关系,以此来表示一个比特的信息。

在水印信息提取时,则选取相同的DCT系数,并根据系数之间的关系抽取比特信息。

除了上述有代表性的变换域算法外,还有一些变换域数字水印方法,它们当中有相当一部分都是上述算法的改进及发展,这其中有代表性的算法是I.Podichuk和Zeng Wen-jun提出的算法。

他们的方法是基于静止图像的DCT变换或小波变换,研究视觉模型模块返回数字水印应加载在何处及每处可承受的JND(Just Noticeable Difference恰好可察觉差别)的量值(加载数字水印的强度上限),这种水印算法是自适应的。

3) 压缩域算法基于JPEG、MPEG标准的压缩域数字水印系统不仅节省了大量的完全解码和重新编码过程,而且在数字电视广播及VOD(Video Oil Demand)中有很大的实用价值。

相反地,水印检测与提取也可直接在压缩域数据中进行。

Hartung提出了一种针对MPEG-2压缩视频数据流的数字水印案。

在Hartung方案中,只有MPEG-2数据流最后一部分数据被改变,其原理是,首先对DCT编码数据块中每一输入的Huffman码进行解码和逆量化,以得到当前数据块的一个DCT系数;其次,把相应水印信号块的变换系数与之相加,从而得到水印叠加的DCT系数,再重新进行量化和Huffman编码,最后对新的Huffman码字的位数n,与原来的无水印系数的码字n0进行比较,只在n1不大于n0的时候,才能传输水印码字,否则传输原码字,这就保证了不增加视频数据流位率。

4) NEC算法该算法由NEC实验室的Cox等人提出,该算法在数字水印算法中占有重要地位,其实现方法是,首先以密钥为种子来产生伪随机序列,该序列具有高斯N(0,1)分布,密钥一般由作者的标识码和图像的哈希值组成,其次对图像做DCT变换,最后用伪随机高斯序列来调制(叠加)该图像除直流分量外的1000个最大的DCT系数。

该算法具有较强的鲁棒性、安全性、透明性等。

5) 生理模型算法人的生理模型包括人类视觉系统HVS和人类听觉系统HAS。

该模型不仅被多媒体数据压缩系统利用,同样可以供数字水印系统利用。

它们的基本思想均是利用从视觉模型导出的JND描述来确定在图像的各个部分所能容忍的数字水印信号的最大强度,从而能避免破坏视觉质量,也就是说,利用视觉模型来确定与图像相关的调制掩模,然后再利用其来插人水印。

这一方法同时具有好的透明性和鲁棒性。

2. 算法实现文中只给出部分关键代码。

2.1 水印图像的嵌入程序。

水印图像嵌入://转换公式为Gray(i,j)=0.11*R(i,j)+0.59*G(i,j)+0.3*B(i,j),//其中Gray(i,j)为转换后的黑白图像在(i,j)点处的灰度值,//其中绿色所占的比重最大,所以转换时可以直接使用G值。

void CWaterMarkDlg::OnWaterEmbed(){// TODO: Add your control notification handler code hereif ((bm[0].bmHeight*bm[0].bmWidth)<3*(bm[1].bmHeight*bm[1].bmWidth)) {//不能嵌入水印MessageBox("水印图象过大请更换较大宿主图象","错误",MB_OK);Mark=FALSE;}if(!Mark)return ;if(biBitCount<biBitCount1){MessageBox("水印受限制");return ;}RGBQUAD *m_copymater; //定义一个水印信息的数据副本m_copymater = new RGBQUAD [WaterHeight*WaterWidth];int i,j;int count=0;BYTE m_r,m_b;if(m_waterEmbed !=NULL) //m_waterEmbed是水印.嵌入后.的位图数据全局变量if(m_Ih!=0)for(int l =0;l<m_Ih;l++)delete [] m_waterEmbed[l];m_waterEmbed = new RGBQUAD*[ImageHeight];for(i=0;i<ImageHeight;i++)m_waterEmbed[i] = new RGBQUAD [ImageWidth];for(i=0;i<ImageHeight;i++) //将原来的图象的数据复制到m_waterEmbed里for(j=0;j<ImageWidth;j++)m_waterEmbed[i][j]=m_tOriPixelArray[i][j];for(i=0;i<WaterHeight;i++)//将水印信息的数据复制到一维数组m_copymater水印信息的数据副本里for(j=0;j<WaterWidth;j++){m_copymater[i*WaterHeight+j]=m_watermarkdata[i][j];count++;}number=count;//记录嵌入的点数int k=0;if (biBitCount==24) //Operate_Byte()嵌入水印信息位操作{for(i=0;i<IMAGEHEIGHT&&COUNT>0;i++)for(j=0;j<ImageWidth&&count>0;j++,count--)//下面可以用一条语句的但为了测试还是多句{m_r=m_waterEmbed[i][j].rgbRed;m_b=m_waterEmbed[i][j].rgbBlue;BYTE &a=m_r;BYTE &b=m_b;BYTE c=m_copymater[i*ImageHeight+j].rgbGreen;Operate_Byte(a,b,c);m_waterEmbed[i][j].rgbRed=m_r;m_waterEmbed[i][j].rgbBlue=m_b;}PutInWaterMessage();}elsereturn;CDC *dc=GetDC();//将象素打印出来RECT m_rect;float w,h,p,q;GetDlgItem(IDC_STATIC2)->GetClientRect(&m_rect);if(m_rect.right<ImageWidth&&m_rect.bottomw=(float)m_rect.right/(float)ImageWidth;h=(float)m_rect.bottom/(float)ImageHeight;}elsew=h=1;for( p=0,i=0;i<ImageHeight;i++,p++)for( j=0, q=0;j<ImageWidth;j++,q++)dc->SetPixel(2+(int)(q*w),235+(int)(p*h),RGB(m_waterEmbed[i][j].rgbRed, m_waterEmbed[i][j].rgbGreen,m_waterEmbed[i][j].rgbBlue));ReleaseDC(dc);delete [] m_copymater;m_Ih=ImageHeight; //为保证直接更换水印信息而没有更换宿主图象提供原宽高 void error bugm_Iw=ImageWidth;m_Wh=WaterHeight;m_Ww=WaterWidth;TRACE("\n%d\n",ImageHeight);GetDlgItem(IDC_BUTTON4)->EnableWindow(TRUE);GetDlgItem(IDC_BUTTON5)->EnableWindow(TRUE);}3. 程序运行开发环境 Microsoft Visual C++ 6.0程序功能在程序中打开宿主图像24位(保存格式为:24位位图),水印图像8位(H*W最好为:131*170)(保存格式为256色位图)。

相关主题