数字图像水印的FPGA软硬件实现-可编程逻辑-与非网
1. 系统设计
1.1背景介绍
当今世界,随着信息技术的不断更新和发展,各种传统的出版物,不论是文本、音乐、视频还是图片都使用了网络这一媒介,通过数字化和网络化,来扩展这类产品的传播范围,加快传播的速度。在网络和多媒体日新月异的同时,盗版问题日渐突出,极大的伤害了版权所有者的利益。现有的一些先进技术已用于防止非法盗版,例如密码技术,但仅靠密码技术并不能完全解决这一问题,因为加密仅能在数据的传输过程中对数据进行保护,一旦数据被接收并进行解密后,产品将不再受到保护。为了解决这一难题,近几年国际上提出了一种新的有效的数字信息产品版权保护和数据安全维护的技术-------数字水印技术。
1.2 方案提出
按照水印载体类型的不同,数字水印可分为:图像水印、视频水印和音频水印。图像水印是水印研究领域中成果最丰富、最成熟,应用最广泛,也是最直观的分支。因此,研究的算法是有意义的,再结合的硬件资源,充分发挥数字处理能力,实现水印过程,这应该是水印的一种新的尝试。
具体到方案:基本的算法上,我们采用基于DCT(离散余弦变换)域的水印算法。它是一种基于频域的图像水印,它的嵌入效果好,人眼几乎无法直觉与原始图像间的差别。它嵌入的内容可以有效抵抗JPEG等有损压缩编码的破坏,鲁棒性较好。而且该算法还可以嵌入灰度图像,及在一幅载体图像中嵌入多幅秘密图像。实验中我们选取的载体是一幅Bmp格式的灰度图片,水印是一幅Bmp格式的灰度图片。算法思想是首先将载体图像划分成8*8矩阵形式的小块,对每块做二维的,然后对中频系数进行修改,嵌入水印图像的像素值,再做二维的DCT逆变换,得到嵌入水印后的图像,并与原始图像进行比对,判断图像的改变情况。选择将信息嵌在中频系数上,是因为图像的大部分能量位于直流分量和低频系数上,若对他们进行修改会影响图像的视觉效果;高频系数值很小,去掉它们基本不引起察觉。水印的提取则是这个的逆过程,对含有水印的图像划分成块,进行DCT变换,在中频系数上提取出嵌入的信息,最后组合成一幅灰度图像,检测嵌入的效果。
结合到硬件上,因为算法的关键是DCT变换和IDCT变换,并且计算量较大,因此我们的重点放在了DCT和IDCT模块上。用VHDL语言描述了两个功能模块,用于实现8*8矩阵的DCT变换和IDCT变换。将它们作为Co-Processor,并挂在FSL上,和间进行通信。整个流程为:将载体图像信息和水印图像信息读入板子的内存中,调用两个功能模块实现水印嵌入过程,得到含有水印的图像,将其显示到PC机上。随后,将含有水印的图像读入板子,调用模块提取出水印,并将其显示到PC机上,并与原始水印图像进行对比,判断整个过程的最终实现效果。
2. 实现方案
2.1水印算法(引用)
算法基本思想是基于图像的离散余弦变换域算法[1][4][5][6],设原始水印图像为mark,载体水印图片为Ca,嵌入水印后的图片为Ca_emb,提取出的水印为mark_dec则算法流程为:
(1)先用两个密钥key1,key2对水印图像像素矩阵的行、列进行随机置换,以得到没有任何视觉效果的图像mark_c。因为密钥是嵌入者所私有的,这样即使水印被非法提取,也能保证不能得到任何有效的信息。即:
mark_c[i,j]=mark[k1(i),k2(j)]
(2)对载体水印图片做基于8&8块的DCT变换
Ca_dct=dct(Ca)
(3)在每个块的中频系数上嵌入一个像素值的信息,其中h应根据水印情况适当的选择
Ca_dct_block[4,4]=h*mark_c[i,j]
(4)进行IDCT变换,得到嵌入水印的图片
Ca_emb=idct(Ca_dct)
提取水印过程
(1)将含有水印的图片进行DCT变换
Ca_d=dct(Ca_emb)
(2)在每块的中频系数上提取出水印信息,组合得到初步水印图mark_c_dec
mark_c_dec[i,j]=Ca_d_block[4,4]/h
(3)用私有密钥对key1,key2对初步水印图进行调整,以恢复原始水印图
mark_dct[i,j]=mark_c_dec[k1&(i),k2&(j)]
创新性思路: 现在水印产品中存在着一个混淆攻击的问题,即同时存在伪水印、伪源数据、伪水印化数据和真实水印、真实源数据、真实水印化数据。要解决作品正确的所有权,必须在一个数据载体的几个水印中判断出具有真正主权的水印。一种可行的对策是采用时间戳技术,时间戮由可信的第三方提供,可以正确判断谁第一个为载体数据加入了水印。由于时间的限制,我们在硬件中没有实现这个思路,以后有时间我们可以加入这一部分,使水印更加完善。
2.2离散余弦变换/反变换
2.2.1 快速算法
离散余弦变换/反变换(Discrete/Inverse Discrete Cosine Transform)是与傅里叶变换相关的一种变换,它类似于离散傅立叶变换(Discrete Fourier Transform),但是只使用实数。离散余弦变换相当于一个长度大概是它两倍的离散傅里叶变换,这个离散傅里叶变换是对一个实偶函数进行的, 由于基于DCT/IDCT的水印技术中要使用到这两种变换[1][2][3],但是这两种变换的计算复杂度较高,使用硬件来处理DCT/IDCT可以大大的减少处理时间。
二维 NxN的DCT/IDCT变化定义如图1所示:
由于二维DCT/IDCT的正交可***性,可以把一个二维变换***成两个一维变换来处理,对于DCT变换,即将NxN的数据按行或列方向进行N个一维DCTT计算中间矩阵,然后再对中间结果按列或行的方向进行第二轮DCT计算,最后得到二维DCT矩阵。IDCT的算法结构与DCT相同,只是用相反的顺序计算,输出变成输入。普遍采用的一种DCT变换是把图像分成8x8的小型矩阵结构,再对这个小矩阵作DCT变换。对于8x8的DCT变换的每个一维变换,按照行的顺序,每次读入一列数据,即8个点的值,然后与对应的8个系数向量做内积运算,可以得到8个值,这样8行数据做完之后便完成了一轮的DCT变换。
对于一个8x8的矩阵,按照行的顺序处理数据,若某一行的数据为向量:
f[i]=[f(i,0),f(i,1), f(i,2), f(i,3) ,f(i,4), f(i,5), f(i,6), f(i,7)]
经过变换之后的向量为:
D[i]=[D(i,0), D(i,1), D(i,2), D(i,3) ,D(i,4), D(i,5), D(i,6), D(i,7)]
那么对应的数学变换形式如图2:
&&&&&&&&&&&&&&&&&&&&&&&&&& 图2
仔细分析右边的矩阵,可以发现右边矩阵中总共用到了16个系数,
矩阵经过化简之后得到表2:
&&&&&&&&&&&&&&&&&&&&&&&&&&& 表2
上面表格中呈现的计算系数有一个特点:对于0,2,4,6四列的8个系数,其中0个系数和第7个系数相同,第1个系数和第6个系数相同,其中2个系数和第5个系数相同,第3个系数和第4个系数相同;而第1,3,5,7这四列系数对应位置上的数字则互为相反数。因此利用这个特点可以进行提公因式的操作。即:
对于偶数列的计算式:
D[i]=Ci0*[f(i,0)+f(i,7)]+Ci0*[f(i,1)+f(i,6)]+Ci0*[f(i,2)+f(i,5)]
+Ci0*[f(i,3)+f(i,4)]
对于奇数列的计算式:
D[i]=Ci0*[f(i,0)-f(i,7)]+Ci0*[f(i,1)-f(i,6)]+Ci0*[f(i,2)-f(i,5)]
+Ci0*[f(i,3)-f(i,4)]
因此向量在做内积运算的过程中,可以先对输入向量轮流进行加法和减法的操作,之后再和相应的系数做内积运算,这样可以是乘法器的数量减少一半,节约了系统资源,付出的代价是增加了一轮加法处理的时间,在考虑到FPGA资源有限的情况下使用这种方法来优化设计。在做完一轮DCT变换之后,需要对中间矩阵进行转置处理,然后进行第二轮的DCT变换。
2.1.2 FPGA硬件设计结构:
对于具有256种像素值补码表示范围为-128&+127,需要8位二进制数据来表示;DCT变换后系数的动态范围为-,使用12位二进制数表示输出,DCT变换的过程中,需要处理余弦函数,小数和整数相乘十分困难,因此在考虑到精度的情况下,先把8个固定系数乘以一个整数,将小数转换成整数,系数都乘以211,对转换后的整数,先用这个整数和乘法器相乘,得到中间结果,再对中间结果除以211 ,即结果向右移动11位,这个过程中要对右起的第十一位数进行1进位,0丢弃的方法取舍。8个系数处理过以后得到如下结果:
C0= 0.35355=10b&
C1= 0.4904 =10b&
C2= 0.46195=10b&
C3= 0.41575=10b&
C4= 0.35355=10b&
C5= 0.2778 =10b&
C6= 0.19135=10b&
C7= 0.09755=10b&
整个设计采用并行流水线的工作方式,对于8位的图像数据,输入输出均采用补码表示,硬件结构流程图见图3:
下面对一维DCT变换进行分析:
一维DCT变换按照行的顺序每个时钟上升沿读入一个像素值即8位二进制数据,数据先要送到一个8x8的移位寄存器,并设置一个模8计数器,当每计数器寄到8时,移位寄存器的数据已经填满,此时一行的数据全部读入,在下一个时钟上升沿数据一并送到下一组寄存器中,之后对数据进行求绝对值运算和符号保存,然后这个向量与系数发生器产生的系数做内积运算,内积运算过程中,按照前述的提公因式方法,先进行一轮加法,接着再做乘加运算,最后对结果做补码运算得到中间结果,并把这个数据存入中间RAM之中。
对于中间矩阵存储部件,第一轮计算结果不断送入其中,当数据读满之后,第二轮DCT变换开始工作,并按照中间矩阵的列顺序读入数据,送到第二轮的DCT部件做运算。
中间RAM可以看成是8x8的存储阵列。当写入数据时,按照0,1,2,3,4&,63的地址顺序进行;当读出数据时按照0,8,16,&&,56; 1, 9, 17,&&,57,&&,7, 15, 23,&&,63进行。
IDCT的硬件结构和DCT的硬件结构相同,只是系数矩阵要进行转置,这样就无法进行提公因式操作,因此IDCT比DCT多用一倍的乘法器。
2.3系统实现方案:
2.3.1系统总体方案:&&&&&&
本系统如图5所示,由于单个开发板硬件资源有限,所以采用两个板子来完成本系统,第一块板子完成第一部分处理之后,中间数据送到第二块板子进行处理,最后处理完的数据送回PC机。
系统流程:
设宿主图像为H,嵌入的图像为E,嵌入图像后的宿主图像为H&,则:
(1).嵌入水印的过程:
水印预处理过程,使用密钥在PC机甲上完成对嵌入图像E的变换,使之成为一幅没有视觉意义的图片E&;
把宿主图片H和图片E&通过串口送到板子,并存入板子甲的DDR SDRAM中,然后板子甲对送入的信息进行初步处理,处理之后的中间结果通过串口送到开发板乙的DDR SDRAM中,进行第二步的处理。
经过开发板处理处理之后,得到嵌入了E&的图片H&,再通过串口把这个图片送到PC机乙。
(2).提取验证水印的过程:
提取水印的过程中,只需对嵌入了水印的图片做DCT变换,只需开发板甲,因此流程如下,PC机乙把嵌入了水印的图片H送入到开发板甲的DDR SDRAM中暂存。开发板甲对收到的图片信息的处理, 提取水印,完成之后把提出出的水印回送到PC机甲,PC机甲利用密钥恢复出原来嵌入的图片,并进行验证。
2.3.2 硬件及软件架构
本系统依靠EDK开发环境,应用microblaze软核,加上一些用户定义IP核,实现了对bmp格式位图进行数字水印处理。水印算法要在频域中做,故需要进行变换域处理[2],我们选择了在图像处理领域广泛应用的二维离散余弦变换。由于像二维离散余弦变换这样复杂的信号处理过程非常复杂,直接在microblaze中用软件处理是非常耗时的,我们采用microblaze提供的FSL接口用硬件实现DCT及IDCT,进行硬件加速,试验表明,硬件实现速度远远超过了软件,后面的试验数据表明,一幅256*256的灰度图像若用软件实现至少需要40多个小时,而采用硬件加速后只需短短几分钟。
(1)系统控制框架:由于DCT和IDCT模块需要占用很多的乘法器(DCT8个,IDCT16个),而一个系统只提供20个,我们只好用硬件描述语言自己写了乘法器模块来代替不够的系统提供的乘法器,但这样系统LUT资源又不够了,经过优化,我们还是没能解决这个问题,最终,最优化的资源利用如表3所示:
Utilization&&&&&&&&&&&&&&&&&&&&&&&&&&&&
Total Number Slice Registers: 6,364 out of&& 9,312&& 68%
Number used as Flip Flops: 6,358
Number used as Latches: 6
Number of 4 input LUTs: 9,371 out of& 9,312& 100% (OVERMAPPED)
Distribution&&&&&&&&&&&&&&&&&&&&&&&&&&&&
Number of Slices containing only related logic: 10,066 out of& 10,066 100%
Number of Slices containing unrelated logic: 0 out of& 10,066&& 0%
Total Number of 4 input LUTs: 9,696 out of& 9,312& 104% (OVERMAPPED)
Number used as logic: 8,226
Number used as a route-thru:& 325
Number used for Dual Port RAMs: 1,008
Number used as Shift registers: 137
Number of bonded IOBs: 62 out of&&&& 232&& 26%
IOB Flip Flops: 34
IOB Master Pads:& 1
IOB Slave Pads:& 1
Number of ODDR2s used: 22
Number of DDR_ALIGNMENT = NONE&& 22
Number of DDR_ALIGNMENT = NONE&& 22
Number of DDR_ALIGNMENT = C0&& 0
Number of DDR_ALIGNMENT = C1&& 0
Number of RAMB16s: 7 out of& 20&& 35%
Number of BUFGMUXs: 4 out of& 24& 16%
Number of DCMs: 2 out of& 4&& 50%
Number of MULT18X18SIOs: 20 out of& 20& 100%
&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&表3
最后,我们放弃了在一块板子上同时做dct和idct的努力,决定用两块板子分别实现两种变化,且板间用串口进行通信,这样做增加了数据传输的冗余时间,但和软件实现相比还是有很的优势的。
(2)软件流程:
第一轮软件流程如图5:
其中用到的led和dip用于控制,在board1上,流程细分为5步:
Stage1:read& file
Stage2:print& file information
Stage3:perform dct
Stage4:embed warter mark
Stage5:send data&
每做一步亮一盏灯,当五盏灯全亮时,board也就完成了他的任务,同时,在流程中,超级终端和board中的lcd会一直显示板子的工作状态。Dip的作用是保持两块板子之间通讯的同步,board1在工作过程中会提示把com连至board2的DTE,然后,推动board1的dip1,board1就开始向board2发送数据。
在board2上主要是做idct变换,以及把做两次变换后的数据和文件头整合在一起,最后把嵌入了水印的图像数据发送给pc机。
第二轮软件流程:
第二轮比较简单,主要是从pc机中读取嵌入了水印的图像,并在board1上做dct,在频域中提取嵌入的水印。最后发送给pc机进行验证。
(3)配置方案:
board1用rs232_dce作为标准输入输出,lmb_bram作为初始引导内存,用户程序放在spi_flash里面,引导程序和硬件数据的比特流整合成初始配置mcs文件下载到spi_flash里。启动时用spi方式配置,引导程序从spi&_flash里由预先定好的位置拷贝用户程序到ddr_sdram里,并转跳至ddr_sdram的用户程序区,开始工作。
Board2配置方案基本和board1一样。
(4)处理器与外围接口:
处理器配置为支持基本浮点,16kb的bram,无缓存,每块板子一对fsl接口,用于硬件加速。Fsl的fifo设为64,刚好符合dct算法中8*8数据块的要求。处理时只需调用一次函数刚和做一次8*8的dct操作。Flash选用16Mbit ST Micro SPI serial flash,这是由于系统的XCF04S serial platform flash太小,不足以容下用户程序。Fsl总线接口借用系统的example的状态链,加上另外一些必要的状态,在1500个时钟周期内完成一次dct变化,结构图如图6:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&图6
(5)外围通讯方案:
由于一块板子不能同时放下dct和idct,故两板之间必须提供通讯接口。Board1和board2都提供rs232_dce作为标准输入输出,board2附加提供rs232_dte作为与board1上rs232_dce的通讯接口。二者的同步通过标准输入输出的提示,由dip_button的配置实现。板子和pc机的通讯由现成的串口精灵提供。
3. 功能与指标
整个系统实现的功能分为两步:首先,将一幅灰度图片嵌入到载体图片中去,得到嵌入水印的图片。然后,从含水印的图片中提取出嵌入的水印图片。
3.2.1 不可感知性评价
数字水印的不可感知性评价又称透明性评价[3]。数字水印的嵌入信息量与透明性之间存在着矛盾,随着嵌入水印信息量的增加,水印载体的感官质量必然下降,因为从一定意义上讲,水印信息对于原始信息来说,本身就属于噪声。在实际中,这两个指标往往很难同时实现,应用中往往只偏重其中的一个方面。如果是为了隐蔽通信,数据量是最重要的,而如果为了保证数据安全,情况则相反,鲁棒性是最重要的。本设计中,对嵌入的信息量不强调,故重点放在图像质量上。
嵌入水印后载体图像的客观评估指标主要是峰值信噪比,一般来说,图像处理前后的峰值信噪比越小,图像的质量降低就越多。但这种评价并没有从根本上反映出图像处理前后在视觉上的变化情况。人眼对图像的感受是一个总体的感受。从根本上说,图像最终是由人来感观的,因此我们采用主观评估来衡量水印的透明性。我们的测试方法是评价对图像质量损害的可感知程度,根据ITU-R BT.500建议,采用5个等级:优秀(5分,降质不可察觉)、良好(4分,降质可察觉,不让人厌烦)、一般(3分,降质轻微,让人厌烦)、差(2分,降质让人厌烦)、极差(1分,降质非常让人厌烦)来定义图像受损质量。因为每个人的感受是不一样的,故检测时尽可能多的综合多人的评价,得到平均等级。
3.2.2 鲁棒性评价
目前没有任何一种方法来对某个数字水印系统的鲁棒性进行数学证明,常用的思路是:能够经受住现有鲁棒性攻击的数字水印就是鲁棒性好的水印。因此鲁棒性评价是建立在相应攻击的基础之上的。设计中我们主要进行了一些几何攻击和简单攻击:对嵌入水印的图像进行剪切、旋转、压缩、添加随机的噪声,然后提取出水印图片,与原始水印图像进行比对,判断水印的失真、变形情况。给出3个等级:好(失真较小,能反映原始水印的信息),中(失真较大,但能基本反映原始水印的信息),差(失真大,不能反映原始水印的信息),来评价失真情况。
4. 系统结构特点
本设计的结构特点是:
(1) 采用了基于DCT域的算法,在中频系数中嵌入水印,这样既保证水印的不可见性,又保证水印的鲁棒性,达到了一个平衡。
(2) DCT模块和IDCT模块都采用流水工作方式,由两片双口RAM,实现了数据的流水输入输出,在计算第N组数据的同时,第N-1组的数据的结果正在串行输入。从而节省了处理数据的时间,提高了工作效率。
(3) 设计中将两个模块作为用户IP核连接到FSL总路线上,由此整合到基于MicroBlaze的嵌入式软核处理器系统中。FSL是MicroBlaze软核特有的一个基于FIFO的单向链路,可以实现用户自定义IP核与MicroBlaze内部通用寄存器的直接相连。并且FSL总线则适用于对时间要求高的用户自定义IP核,以实现硬件加速。
(4) 采用了块浮点算法,不止可以解决精度问题,且硬件实现的结构和控制都很简单。
(5) 系统设计中对载体图片的大小没有特殊的要求,可以是灰度图片,也可以是真彩色图片,且格式上也可以不限于bmp格式,可以适当的进行扩展。
5.系统自测试方案
5.1 测试环境
FPGA中的EDK、SDK及 ISE 开发环境,windows XP操作系统,matlab软件环境
5.2 测试设备
FPGA Spartan-3E初级板两块.
笔记本电脑一台&& 配置为CPU::Genuine Inter(R) T2050 主频1.60GHZ,内存:1.5G 主频798MHZ.
USB-Platform数据线两根,PC3下载线一根.
5.3 测试过程及结果分析
5.3.1 DCT模块的测试
为了保证测试结果的可靠性,我们选取了二组具有代表性的数据:
第一组:1~64的自然数序列
第二组:完全的随机序列,如表4:
&&&&&&&&&&&&&&&&&&&&&&&&&& 表4
测试步骤:首先,在matlab上对数据进行计算得到准确的结果;其次,在Xilinx上进行FPGA仿真得到仿真结果;最后,硬件实现并将数据输出到PC机上,得到最终数据。
(1) 第一组数据
matlab结果,如表5:
&&&&&&&&&&&&&&&&&&&&&&&& &&&&表5
FPGA仿真结果如表6:
&&&&&&&&&&&&&&&&&&&&&&&&&& 表6
硬件实现结果如表7:
&&&&&&&&&&&&&&&&&&&&&&&&&& 表7
(2 ) 第二组数据
matlab结果如表8:
&&&&&&&&&&&&&&&&&&&&&&&&&& 表8
FPGA仿真结果如表9:
&&&&&&&&&&&&&&&&&&&&&&&&&& 表9
硬件实现结果如表10:
&&&&&&&&&&&&&&&&&&&&&&&&&&&& 表10
(3 ) 测试数据分析
测试中,时钟周期为20ns,仿真时间为5000ns。
从两组数据可以看出,仿真结果与硬件实现的结果是一致的,与实际结果数据相差在正负1.5之间,这是由cos( )的计算精度造成的,但相差不大,符合设计中的数据要求。
5.3.2 IDCT模块的测试
为了使数据更有说服力,我们对上面两组变换后的数据进行反变换
(1) 第一组:
FPGA仿真结果为:
1 2 3 4 4 5 6 7 9 10 11 12 13 13 15 16 17 18 19 20 20 21 22 23 25 26 27 28 28 29 31 31 33 34 35 36 36 37 38 39 41 42 43 44 44 45 46 47 48 49 51 52 52 53 54 55 57 58 59 60 60 61 62 63
硬件实现结果为:
1 2 3 4 4 5 6 7 9 10 11 12 13 13 15 16 17 18 19 20 20 21 22 23 25 26 27 28 28 29 31 31 33 34 35 36 36 37 38 39 41 42 43 44 44 45 46 47 48 49 51 52 52 53 54 55 57 58 59 60 60 61 62 63
(2) 第二组
FPGA仿真结果如表11:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 表11
硬件实现结果如表12:
&&&&&&&&&&&&&&&&&&&&&&&& 表12
从两组数据看出,仿真结果与硬件结果是一致的。结果数据与原始输入数据相差在正负1之间,且输入数据越随机,结果越准确。这说明我们的模块设计是可靠的,准确的。
5.3.3 系统功能测试
测试中选取载体水印图像为:lena.bmp
选取嵌入的水印为一串随机序列,其坐标图为:
经过水印嵌入过程,得到嵌入水印后的图片为:
经过水印提取过程,得到提取出的水印为:
(1)根据不可感知性的评价指标,我们选取了8位同学对我们嵌入水印后的图片进行了评价,结果为表13:
&&&&&&&&&&&&&&&&&&&&&&&&& 表13
根据指标:优秀(5分,降质不可察觉)、良好(4分,降质可察觉,不让人厌烦)、一般(3分,降质轻微,让人厌烦)、差(2分,降质让人厌烦)、极差(1分,降质非常让人厌烦)来定义图像受损质量。则测试平均得分为:3.625,为良好等级,这说明原始图像的受损程度较小,基本不影响其视觉效果。
(2)根据鲁棒性评价指标,我们另外选取了8位同学对提取出的水印与原始水印进行比对,并给出评价,如表14:
&&&&&&&&&&&&&&&&&&&&&&&&& 表14
根据指标:好(失真较小,能反映原始水印的信息),中(失真较大,但能基本反映原始水印的信息),差(失真大,不能反映原始水印的信息),来评价失真情况。
这充分说明我们提取出的水印效果很好,相对于原始水印,失真很小。结果是另人满意的。
本文主要介绍了用硬件实现数字图像水印的过程,硬件中设计并充分利用了DCT模块与IDCT模块,采用流水工作方式使整个过程得以快速流畅的实现。
II.源代码清单
硬件源代码清单
mul_16.vhd
part_mul.vhd
adder_2.vhd
adder_4.vhd
adder_8.vhd.
hw_idct.vhd
软件源代码清单
3:& hwdct.h
4:& hwdct.c
5:& hw_idct.h
6:& hw_idct.c
7:& test.c(board1上的主要代码)
8:& pro.c(board2上的主要代码)
9:& main.c(引导程序)
III:硬件原理图
Dct模块框图
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 系统总体连接框架
I.源代码清单
硬件源代码清单
mul_16.vhd
part_mul.vhd
adder_2.vhd
adder_4.vhd
adder_8.vhd.
hw_idct.vhd
软件源代码清单
3:& hwdct.h
4:& hwdct.c
5:& hw_idct.h
6:& hw_idct.c
7:& test.c(board1上的主要代码)
8:& pro.c(board2上的主要代码)
9:& main.c(引导程序)
软件源代码主要函数:
Lcd模块:参考edk_flow里的设计,自己打包成头文件,主要函数有:
void XromMoveCursorHome();光标移至左上角
void XromMoveCursorLeft();光标左移
void XromMoveCursorRight();光标右移
void XromLCDOn();打开LCD
void XromLCDOff();关闭lcd
void XromLCDClear();显示清除
void XromLCDInit();初始化
void XromLCDSetLine(int line);光标移至某行
void XromLCDPrintChar(char c);打印字符
void XromLCDPrintString(char * line);在当前行打印字符串
void XromLCDPrint2Strings(char * line1, char * line2);打印字符串,显示在两行上
硬件设计为以64个数据为单位进行整体变化,故一次函数调用相应做一次8*8的变换。
hwdct(input_slot_id, output_slot_id, input_0, output_0):以input_0和output_0所指位置取64个数进行dct变换,input_0输入,output_0输出。
Idct模块:
与dct相似,函数为hw_idct(input_slot_id, output_slot_id, input_0, output_0)
通讯模块:采用rs232通讯,polled模式,以系统最大fifo的16byte为单位进行传输。
void send_16_bytes(){
&&& u8 *p=send_
&&& for(i=0;i&16;i++)
&&&&&& XUartLite_SendByte(XPAR_RS232_DCE_BASEADDR,*(p++));
send_16_bytes()用于board1向board2发数据。
void receive_16_bytes(){
&&& int rx_count=0;
&&& u8 rx_
&&& while(rx_count&16)
&&& rx_byte = XUartLite_RecvByte(XPAR_RS232_DTE_BASEADDR);
&&& recv_data[rx_count] = rx_
&&& rx_count++;
eceive_16_bytes()用于board2从board1收数据。
Flash模块:参考***NET的设计,用其提供的sf_command进行flash的读写。
主要用到了:
void spi_transfer (unsigned char *send, unsigned char *recv, unsigned char num_bytes);
void SF_write_enable (Xuint32 BaseAddress);
void SF_write_disable (Xuint32 BaseAddress);
void SF_bulk_erase (Xuint32 BaseAddress);
void SF_sector_erase (Xuint32 BaseAddress, Xuint8 sector_address);
void SF_start_page_program (Xuint32 BaseAddress, Xuint8 sector_address, Xuint8 page_address, Xuint8 page_offset);
void SF_end_page_program (Xuint32 BaseAddress);
void SF_start_read (Xuint32 BaseAddress, Xuint8 sector_address, Xuint8 page_address,
&&&&&&&&&&&&&&&&&&&&&&& Xuint8 page_offset, Xuint8 speed_setting);
void SF_end_read (Xuint32 BaseAddress);
主控制模块:board1完成大部分工作,其主程序为:
int main(){
XGpio_Initialize (&led,XPAR_LEDS_8BIT_DEVICE_ID);
XromLCDInit();
XromLCDOn();
XromLCDClear();
int blocks_to_be_
int i,j,u,v;
int sigal_bytes_to_be_
Xint16 block_in[8][8];
Xint16 block_out[8][8];
Xint16 block_in_map[64];
Xint16 block_out_map[64];
XUartLite RS232_DCE;
XUartLite_Initialize(&RS232_DCE, XPAR_RS232_DCE_DEVICE_ID);
XGpio_Initialize (&dip,XPAR_DIP_SWITCHES_4BIT_DEVICE_ID);
/////////read head information//////////////////////////////////////////
print(&stage 1: reading file.......................\r\n&);
XGpio_DiscreteWrite (&led,1,1);
print(&input a file to be stored in ddrram\n\r&);
XromLCDPrintString(&stage1&);
XromLCDSetLine(2);
XromLCDPrintString(&reading file&);
receive_8_bytes();
size_of_file=recv_data[5]*+recv_data[4]*65536+recv_data[3]*256+recv_data[2];
receive_8_bytes();
offset=recv_data[5]*+recv_data[4]*65536+recv_data[3]*256+recv_data[2];
blocks_to_be_read=offset/8-2;
sigal_bytes_to_be_read=offset-(blocks_to_be_read+2)*8;
///////////////pass away useless information/////////////////////////
for(i=0;i&blocks_to_be_i++)
&&& receive_8_bytes();
for(i=0;i&sigal_bytes_to_be_i++)
&&& byte=XUartLite_RecvByte(STDIN_BASEADDRESS);
////////////////read data section to global matrix/////////////////////
for(i=0;i&SIZE;i++)
&&& for(j=0;j&SIZE;j+=8){
&&&&&& receive_8_bytes();
&&&&&& send_to_din(i,j);
print(&OK!\r\n\n\n&);
/////////////////////print file information//////////////////////////
print(&stage 2: print file imformation.......................\r\n&);
XGpio_DiscreteWrite (&led,1,3);
XromLCDClear();
XromLCDPrintString(&stage2&);
XromLCDSetLine(2);
XromLCDPrintString(&print info&);
xil_printf(&size_of_file is %d bytes!\r\n&,size_of_file);
xil_printf(&data esction offsets of file is %d!\r\n&,offset);
xil_printf(&blocks_to_be_read is %d!\r\n&,blocks_to_be_read);
xil_printf(&sigal_bytes_to_be_read is %d!\r\n&,sigal_bytes_to_be_read);
print(&OK!\r\n\n\n&);
///divide data to small blocks of 8*8 meanwhile performing dct//////
print(&stage 3:dct performing...............................\r\n&);
XGpio_DiscreteWrite (&led,1,7);
XromLCDClear();
XromLCDPrintString(&stage3&);
XromLCDSetLine(2);
XromLCDPrintString(&perform dct&);
for(i=0;i&SIZE/8;i++)
&&& for(j=0;j&SIZE/8;j++){
&&&&&& for(u=0;u&8;u++)
&&&&&&&&&& for(v=0;v&8;v++){
&&&&&&&&&&&&& block_in[u][v]=data_in[i*8+u][j*8+v]-128;
&&&&&&&&&&&&& block_in_map[u*8+v]=block_in[u][v];
&&&&&&&&&& }
&&&&&& hwdct(input_slot_id,output_slot_id,block_in_map,block_out_map);
&&&&&& for(u=0;u&8;u++)
&&&&&&&&&& for(v=0;v&8;v++){
&&&&&&&&&&&&& block_out[u][v]=block_out_map[u*8+v];
&&&&&&&&&&&&& //data_out[i*8+u][j*8+v]=block_out[u][v];
&&&&&&&&&&&&& data_out[i*8+u][j*8+v]=block_out[u][v];
&&&&&&&&&& }
print(&OK!\r\n\n\n&);
///////////embed warter mark//////////////////////////////////////
print(&stage 4:warter mark performing...............................\r\n&);
XGpio_DiscreteWrite (&led,1,15);
XromLCDClear();
XromLCDPrintString(&stage4&);
XromLCDSetLine(2);
XromLCDPrintString(&warter mark&);
for(i=0;i&SIZE/8;i++)
&&& for(j=0;j&SIZE/8;j++)
&&&&&& data_out[i*8+3][j*8+3]=1.03;&&&&&&&&&&
print(&OK!\r\n\n\n&);
//////////stage5 :transfer header and dct data to board2////
print(&stage 5 :transfering...............................\r\n&);
XGpio_DiscreteWrite (&led,1,31);
XromLCDClear();
XromLCDPrintString(&stage5&);
XromLCDSetLine(2);
XromLCDPrintString(&transfering&);
u8 *p=data_
print(&pluge com to board2,then push up dip 1 to begin transfer\r\n&);
while(i!=1)
&&& i=XGpio_DiscreteRead (&dip,1);
for(i=0;i&LENGTH/8;i++){
&&& for(j=0;j&16;j++){
&&&&&& *(send_data+j)=*(p++);
&&& send_16_bytes();
while(i!=3)
&&& i=XGpio_DiscreteRead (&dip,1);
print(&OK!/r/nmission on board 1 complete!&);
/////////////////////complete///////////////////////////////////////
II:硬件原理图
Dct模块框图
系统总体连接框架
关注与非网微信 ( ee-focus )
限量版产业观察、行业动态、技术大餐每日推荐
享受快时代的精品慢阅读
(有奖互动)“行话”里的冷知识……
旗下网站:
与非门科技(北京)有限公司 All Rights Reserved.
京ICP证:070212号
北京市公安局备案编号: 京ICP备:号