数字水印的价值,意义以及优点~谁能帮下忙

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数字水印的价值,意义以及优点~谁能帮下忙相关的知识,希望对你有一定的参考价值。

顺便把数字水印现在存在的一些问题以及以后的研究方向帮忙找一下下.感激不尽啊.毕业论文要用!!

数字版权的最后一道防线—数字水印

■ 北京大学计算机科学技术 研究所 朱新山

--------------------------------------------------------------------------------

数字水印被视做抵抗多媒体盗版的“最后一道防线”。因此从水印技术自身来说,它具有广泛的应用前景和巨大的经济价值。

当今社会的发展已经呈现两个明显的特征:数字化和网络化。数字化指的是信息的存储形式,特点是信息存储量大、便于编辑和复制;网络化指的是信息的传输形式,具有速度快、分布广的优点。过去10年,数字媒体信息的使用和分布呈爆炸性的增长。人们通过互联网可以快捷方便地获得数字信息和在线服务。但同时,盗版也变得更加容易,对数字内容的管理和保护成为业界迫切需要解决的问题。

数字信息在本质上有别于模拟信息,传统的保护模拟信息的方案对数字信息已不再奏效。再加上一些具有通用目的的处理器,如PC机,使得那些基于硬件的媒体保护方案很容易被攻破。而通常采用的加密技术事实上只能在信息从发送者到接受者的传输过程中保护媒体的内容。在信息被接收到以后,再利用的过程中所有的数据对使用者都是透明的,不再受到任何保护。在这一形势下,数字水印作为一种潜在的解决方案,得到了众多学者的青睐。

数字水印的基本思想是在原始媒体数据中,如音频、视频、图像等,隐藏具有一定意义的附加信息作为标记,这些信息与原始数据紧密结合,并随之一起被传输。在接收端,通过计算机水印信号被提取出来用于各种目的,可能的应用包括数字签名、数字指纹、广播监视、内容认证、拷贝控制和秘密通信等。数字水印被视做抵抗多媒体盗版的“最后一道防线”。因此从水印技术自身来说,它具有广泛的应用前景和巨大的经济价值。
数字水印的一般框架图

数字水印的基本框架

一个典型的水印系统由嵌入器和检测器组成,如图所示。嵌入器(式(1))根据要传送的信息M生成真正的水印信号,并把它隐藏到媒体数据x中,得到含水印的信号y。为了安全起见,水印信号的生成通常依赖于密钥K。

y经过传输网络可能会有一定的信息损失,到达检测器端变成y′,这段通道对于嵌入器和检测器来说都是不可控、不可知的,可以称其为攻击通道(attack channel)。检测器负责从y′中提取信息,如式(2)。对于不需要宿主信号的检测,我们称为盲水印(blind watermarking),相反称为非盲水印(non-blind watermarking)。由于应用的需求,盲水印一直是研究的主流。

数字水印的特性

数字水印的思想虽然简单,但是要达到应用的目的,就必须满足一定的性能指标,其中相对重要的特性包括:

● 保真性(fidelity):又常称为不可见性,指的是水印嵌入导致宿主信号质量变化的程度。鉴于宿主信号多是多媒体数据供人们观赏,水印应具有很高的保真性,同时又增加了水印自身的安全。

● 鲁棒性(robustness):是指水印在媒体数据编辑、处理过程中的生存能力。媒体数据的各种操作会导致宿主信号信息损失,从而破坏水印完整性,像压缩、滤波、加噪、剪切、缩放和旋转等,也包括一些恶意的攻击。

● 信息容量(data payload):是指在一定保真度下,水印信号可传递的信息量。实际应用要求水印可传送多位信息。

● 安全性:在应用中总有人要嵌入、检测或剔除水印,而必须限制其他人做同样的操作,这就是水印的安全性。要实现安全,必须保密重要信息,比如通常使用密钥产生水印。

● 错警率:是指在不含水印的宿主信号中,错误地检测出水印的概率。很显然,只有错警率足够低,系统才能安全可靠地使用。

设计水印必须围绕上述性能指标选择合适的技术。有些特性之间是不相容的,像不可见性、鲁棒性和信息容量,必须做权衡的考虑。

由水印的保真性将其分为可见水印和不可见水印,顾名思义可见水印可通过人眼检测。由水印的鲁棒性又可分为鲁棒水印(robust watermarking)和脆弱水印(fragile watermarking)。鲁棒水印可以抵抗一定程度的信号处理;而脆弱水印的特点是任何对媒体信息的更改都会破坏水印的完整性,使水印检测不出来。所以说鲁棒水印是尽力保证水印信息的完整性,脆弱水印是尽力保证媒体信息的完整性,它们各有各的用途。还有一种水印介于二者之间,称为半脆弱水印,对一些操作鲁棒,但对重要数据特征的修改操作是脆弱的。

数字水印技术的进展

早期,水印设计者关注的是如何把信息隐藏在数字媒体中并不被发现。为此,水印信息被置于二进制数据的最低位中,这类方案被统称为最低有效位调制。很明显,最低有效位内的信息容易在常用的信号处理中丢失,水印的鲁棒性差。

随后,出现了大量空间域内的水印算法。水印嵌入不再是修改空间域内的单个点,而是一个点集或一个区域的特征,例如均值、方差、奇偶性等。Patchwork是这类方法的一个典型代表。它在图像空间随机选取n对像素点(ai, bi),并且对像素ai的亮度加d,bi的亮度减d,结果这两组像素点之间亮度差值的均值被修改为2d。该均值和统计假设检验理论可确定水印的有无。可是Patchwork能嵌入的信息量有限,而且对几何变换敏感。空间域内水印算法存在的共性问题是对图像处理的鲁棒性差。

相较于空间域,频谱则是一种很好的信号描述方法。低频分量代表了信号的平滑部分,是主体信息;高频分量表示信号的抖动部分,是边缘信息,信号的分析和处理非常直观方便。扩频水印引入了扩频通信理论,是一种非常流行的频率域内的水印设计思想。它将数字媒体视为信道,通常具有较宽的带宽,要嵌入的水印信号作为发射信号,带宽较窄。可以先将水印扩展到多个频率点上,再与媒体信号叠加。这样,每个频率分量内只含有微小能量的水印,既保证了不可见性,同时要破坏水印,则必须在每个频率上叠加幅值很高的噪声。这一思想首先被应用到DCT域内,之后又被推广到傅立叶变换域和小波域内。另外,为了兼顾水印的保真性,人类感知模型被用于控制每个频率点上水印的能量,使其不至于破坏信号质量,从而形成了一类自适应的扩频水印。

另一种重要的水印模型是把水印看成是已知边带信息的通信。边带信息指的是嵌入器端已知的信息,包括媒体数据。嵌入器应该充分利用边带信息,尽可能提高水印正确检测的概率。这对水印的设计有重要的指导意义,它说明含水印的宿主信号应该选择在可检测到水印的区域,同时保证一定的保真度。

当前,水印研究的热点是探讨媒体信号中能嵌入并可靠检测的最大信息量,它应用了已知边带信息的通信模型以及信息论的知识。水印算法的研究则侧重于针对压缩域,即JPEG、MPEG等压缩标准,因为压缩是信息传输中必须采用的技术。

数字水印的攻击技术

对媒体数据的各种编辑和修改常常导致信息损失,又由于水印与媒体数据紧密结合,所以也会影响到水印的检测和提取,我们把这些操作统称为攻击。水印的攻击技术可以用来测试水印的性能,它是水印技术发展的一个重要方面。如何提高水印的鲁棒性,抵抗攻击,是水印设计者最为关注的问题。

第一代水印性能评价系统Stirmark囊括了大量的信号和图像处理操作,它们可以分为:

● 去除水印攻击(Removal attack):主要包括A/D、D/A转换、去噪、滤波、直方图修改、量化和有损压缩等。这些操作造成了媒体数据的信息损失,特别是压缩,能在保证一定信息质量的前提下,尽可能多地剔出冗余,使得水印被去掉。

● 几何攻击(Geometrical attack):主要包括各种几何变换,例如旋转、平移、尺度变换、剪切、删除行或列、随机几何变换等。这些操作使得媒体数据的空间或时间序列的排布发生变化,造成水印的不可检测,因此也叫异步攻击。

● 共谋攻击:攻击者利用同一条媒体信息的多个含水印拷贝,使用统计方法构造出不含水印的媒体数据。

● 重复嵌入攻击:攻击者在已嵌入他人水印的媒体数据中嵌入自己的版权信息,从而造成版权纠纷。

第二代水印攻击系统由Voloshynovskiy提出,其核心思想是利用合理的媒体数据统计模型和最大后验概率来估计水印或者原始媒体信号,从而将水印剔除。

对攻击技术的分析和研究促进了水印技术的革新,但也为水印自身提出了一个又一个挑战。当前,还不存在一种算法能够抵抗所有的攻击,特别是几何攻击,是学术界公认的最困难的问题,目前还没有成熟的方案。

数字水印产品

20世纪90年代末期国际上开始出现一些水印产品。美国的Digimarc公司率先推出了第一个用于静止图像版权保护的数字水印软件,而后又以插件形式将该软件集成到Adobe公司的Photoshop和Corel Draw图像处理软件中。AlpVision公司推出的LavelIt软件,能够在任何扫描的图片中隐藏若干字符,用于文档的保护与跟踪。MediaSec公司的SysCop用水印技术来保护多媒体内容,欲杜绝非法拷贝、传播和编辑。

美国版权保护技术组织(CPTWG)成立了专门的数据隐藏小组(DHSG)来制定版权保护水印的技术标准。他们提出了一个5C系统,用于DVD的版权保护。IBM公司将数字水印用于数字图书馆的版权保护系统中。许多国际知名的商业集团,如韩国的三星、日本的NEC等,也都设立了DRM技术开发项目。另外,当前还有一些潜在的应用需求,例如软件的搜索和下载数量的统计、网页安全预警、数字电视节目的保护和机密文档的防遗失等。

一些国际标准中已结合了数字水印或者为其预留了空间。SDMI的目标是为音乐的播放、存储和发布提供一个开放的框架。SDMI规范中规定了多种音频文件格式,并联合加密和数字水印技术来实现版权保护。已经颁布的JPEG2000国际标准中,为数字水印预留了空间。即将颁布的数字视频压缩标准MPEG-4(ISO/IEC 14496),提供了一个知识产权管理和保护的接口,允许结合包括水印在内的版权保护技术。

在国内,政府对信息安全产业的发展极为重视。数字水印的研究得到了国家自然科学基金和“863”计划的资助。国内信息隐藏学术研讨会(CIHW)自1999年以来至今已成功举办了五届,有力地推动了水印技术的研究与发展。去年政府更颁布了《中华人民共和国电子签名法》,这给水印技术的应用提供了必要的法律依据。

尽管数字水印发展迅速,但离实际应用,还有一段距离要走。许多项目和研究都还处于起步和实验阶段,已出现的水印产品还不能完全满足使用需求。如今水印技术正在向纵深发展,一些基本的技术和法律问题正逐个得到解决。相信不久的将来,水印与其它DRM技术的结合,将彻底解决数字内容的管理和保护问题。

小资料2

多媒体数字版权保护的应用案例

在安全领域有20年发展历史的美商SafeNet推出的数字产权保护方案DMD是采用加密技术的DRM产品。SafeNet公司亚太地区副总裁陈泓应记者的要求介绍几个成功的应用案例。

DMD主要应用于音乐和铃声的下载、VOD、多媒体内容发布服务,以及最近的移动TV。基本来说,客户选择基于以下几点:基于电信级的性能,可以同时处理上千个用户;可以同步支持多种DRM技术,并且对未来的DRM技术有高支持能力;高互通性,确保服务器端与客户端能安全稳定地沟通;先进的授权能力,例如可以有效控制一个授权的使用量;高集成性,确保DRM的平台不是独立作业的,可以很容易地整合至服务器平台,与收费系统等结合。

在音乐下载方面,NPO是SafeNet在法国的客户。他们主要负责发布CD音乐及将发表的音乐放到FN@C的网络上供人付费下载。NPO将音乐内容做DRM处理后,将内容由FN@C (这是一个公开的入口网站)发布,提供给人付费下载。当终端用户付了钱,FN@C会将一部分的证明数据加密并提交给NPO,由NPO产生授权给此用户。

在VOD的应用层面,德国的Arcor公司是一家ISP供货商。透过DRM解决方案,Arcor将影音内容加密,透过互联网和Cable给客户做使用者付费的服务。客户付了钱,Arcor由SafeNet的DRM解决方案产生正式授权,让客户享用影音服务。

在3G的应用方面,英国的BT LiftTime公司也采用SafeNet的DMD方案。BT LifeTime向内容供货商购买cable TV的内容(如运动节目或音乐节目等),并将此内容转成dab格式,经过DMD加密并放到其平台,再转卖给无线运营商,提供移动装置用户直接付费下载内容。通过SafeNet DMD将授权提供给已经付费的客户。

(计算机世界报 2005年11月14日 第44期 B6、B7)

MPEG-4视频数字水印技术的设计与实现
武汉大学信号与信息处理实验室(430079) 裘风光 李富平
随着信息技术和计算机网络的飞速发展,人们不但可以通过互联网和CD-ROM方便快捷地获得多媒体信息,还可以得到与原始数据完全相同的复制品,由此引发的盗版问题和版权纷争已成为日益严重的社会问题。因此,数字多媒体产品的水印处理技术已经成为近年来研究的热点领域之一。
虽然数字水印技术近几年得到长足发展,但方向主要集中于静止图像。由于包括时间域掩蔽效应等特性在内的更为精确的人眼视觉模型尚未完全建立,视频水印技术的发展滞后于静止图像水印技术。另一方面,由于针对视频水印的特殊攻击形式的出现,为视频水印提出了一些区别于静止图像水印的独特要求。

本文分析了MPEG-4视频结构的特点种基于扩展频谱的视频数字水印改进方案应用实例。

1视频数字水印技术简介

1.1数字水印技术介绍

数字水印技术通过一定的算法将一些标志性信息直接嵌入到多媒体内容当中,但不影响原内容的价值和使用,并且不能被人的感知系统觉察或注意到。与传统的加密技术不同,数字水印技术并不能阻止盗版活动的发生,但可以判别对象是否受到保护,监视被保护数据的传播,鉴别真伪,解决版权纠纷并为法庭提供认证证据。为了给攻击者增加去除水印的难度,目前大多数水印制作方案都采用密码学中的加密体系来加强,在水印嵌入、提取时采用一种密钥,甚至几种密钥联合使用。水印嵌入和提取的一般方法如图1所示。

1.2视频数字水印设计应考虑的几个方面

·水印容量:嵌入的水印信息必须足以标识多媒体内容的购买者或所有者。

·不可察觉性:嵌入在视频数据中的数字水印应该不可见或不可察觉。

·鲁棒性:在不明显降低视频质量的条件下,水印很难除去。

·盲检测:水印检测时不需要原始视频,因为保存所有的原始视频几乎是不可能的。

·篡改提示:当多媒体内容发生改变时,通过水印提取算法,能够敏感地检测到原始数据是否被篡改。

1.3视频数字水印方案选择

通过分析现有的数字视频编解码系统,可以将目前MPEG-4视频水印的嵌入与提取方案分为以下几类,如图2所示。

(1)视频水印嵌入方案一:水印直接嵌入在原始视频流中。此类方案的优点是:水印嵌入的方法较多,原则上数字图像水印方案均可应用于此。缺点是:

·会增加视频码流的数据比特率;

·经MPEG-4有损压缩后会丢失水印;

·会降低视频质量;

·对于已压缩的视频,需先进行解码,然后嵌入水印,再重新编码。

(2)视频水印嵌入方案二:水印嵌入在编码阶段的离散余弦变换(DCT)的直流系数(DC)中(量化后、预测前)。此类方案的优点是:

·水印仅嵌入在DCT系数中,不会增加视频流的数据比特率;

·易设计出抗多种攻击的水印;

·可通过自适应机制依据人的视觉特性进行调制,在得到较好的主观视觉质量的同时得到较强的抗攻击能力。

缺点是对于已压缩的视频,有一个部分解码、嵌入、再编码的过程。

(3)视频水印嵌入方案三:水印直接嵌入在MPEG-4压缩比特流中。优点是不需完全解码和再编码的过程,对整体视频信号的影响较小。缺点是:

·视频系统对视频压缩码率的约束将限制水印的嵌入量;

·水印的嵌入可能造成对视频解码系统中运动补偿环路的不良影响;

·该类算法设计具有一定的复杂度。

2 MPEG-4视频水印的实现

基于上述的各种方案,本文在方案二的基础上提出了一种针对MPEG-4视频编码系统的扩展频谱数字水印技术改进方案,将扩频调制后的水印信息嵌入到视频流IVOP(Intra Video Object Plane)中色度DCT直流系数的最低位。本方案不需要完全解码,大大减少了运算的
复杂度,提高了实时性。同时由于水印嵌入在直流系数中,在保证视频效果不失真的前提下,水印具有很强的鲁棒性。

2.1 MPEG-4视频的特点 MPEG-4视频编解码基于VOP(Video Object Plane)。

从时间上看,VOP分为内部VOP(1VOP)、前向因果预测VOP(PVOP)、双向非因果预测VOP(BVOP)、全景的灵影VOP(SVOP)。IVOP只用本身的信息进行编码;PVOP利用过去的参考VOP进行运动补偿的预测编码;BVOP利用过去和将来的参考VOP进行双向运动补偿的预测编码;SVOP一系列运动图像中的静止背景。因此IVOP的图像信息较独立,最适合嵌入水印信息。

从空间上看,它由若干个大小为16×16的宏块(Macro Block)组成,每个宏块包括大小为8×8的6个子块。其中4个亮度子块Y,1个色差子块U,1个色差子块V。IVOP编码基本流程如图3所示。

为了不受量化过程的影响,本方案将水印嵌入在量化后的DCT系数中,从而提高了水印生存的稳定性。在MPEG-4压缩算法中,DCT系数的量化是关键,它直接影响视频的质量和码流控制算法。为此,MPEG-4提供了一个供参考的标准量化表。该表根据人类视觉模型(HVS)建立。考虑到人眼对高频信息损失的敏感度较低频损失小很多,因此通常把水印嵌入到中低频信息中,提高了水印信息的鲁棒性。另外,根据人眼对亮度信息的变化比色度信息较敏感这一特性,为最大限度地保持视频质量,本方案将水印嵌入到色度(U子块)DCT系数中。由于DCT是目前多媒体视频压缩中被广泛采用的技术基础,因此基于DCT的视频水印方案具有显著的优势。将水印信息嵌入到IVOP色度量化后的DCT直流系数中,不但无需引入额外的变换以获取视频的频谱分布,且水印信息不受DCT系数量化带来的影响。

2.2视频数字水印算法与实现

在MPEG-4视频中,由于IVOP中色度子块的DCT直流系数是一个在视频流中始终存在且很鲁棒的参数,本方案将水印信息经m序列(最长线性反馈移存器序列)调制后嵌入到IVOP的色度子块DCT的直流系数中。这样水印信息在不影响视频效果的情况下难以去除,所以鲁棒性足够强。本方案采用扩频的方法,以方便有效地检测水印,抵抗各种攻击和干扰,保密性好。关键问题是色度DCT的直流系统是一个对视觉系统很敏感的参数,本方案在色度DCT的直流系数上加水印相当于对其加入微量干扰,必须使这种干扰低于一定的门限值,使人眼的视觉系统对视频中色度的微小变化感觉不到。经过试验将水印嵌入到IVOP的色度DCT的直流系数的最低位能满足要求。

2.2.1视频数字水印的嵌入

伪随机的扩展序列长度为255(28-1),每一水印信息位通过伪随机扩展序列的调制嵌入到相应的IVOP色度对应的DCT直流系数(量化后、预测前)的最低位,这样水印信息在不影响视频效果的情况下一般难以去除。同时,嵌入在直流系数的最低位,带来的误差非常小。

伪随机的扩展序列产生代码如下:

#define M_LEN 255
#define M_SERIES 8
for(I=0;i for(i=M_SERIES;i
m[i]=m[i-1]+m[i-5]+m[I-6]+m[i-7]
m[i]=m[i]%2;

水印信息位扩展调制方式为:

·水印信息位为0,伪随机的扩展序列不变;

·水印信息位为1,伪随机的扩展序列取反。

这个过程可以用异或运算实现。代码如下:

Wmij=Wi^m[j];

/*每一水印信息位扩展调制成255位的扩展调制位*/
这里Wi表示水印信息码流,WMij表示水印信息扩展调制码流。设UDCij表示视频IVOP色度DCT的直流系数(量化后、DC预测计算之前)序列,为了方便,用一个字节表示一位二进制码流信息。

水印嵌入过程如下:

if(WMij) UDCij 1=1;

/*根据扩展调制后的码流嵌入水印信息*/

else UDCij&=0xFFFE;

2.2.2视频数字水印的提取

水印信息提取是水印信息嵌入的逆过程,代码如下:

if(inv_UDCij &1)inv_Wmij=1;
else inv_Wmij=0;

这里inv_UDCij表示带有水印信息的视频IVOP色度DCT的直流系数(反量化前、DC预测计算之后)序列;inv_WMij表示检测到的水印信息扩展调制码流。每个IVOP色度子块在解码时得到一位扩展调制的信号位,每连续255个扩展调制的信号位可解调得到1位水印
信息,具体分析如下:

用与原始伪随机序列结构相同且完全同步的序列与得到的连续255个扩展调制的信号接收序列进行异或运算,统计运算后1的个数记为OneCount。由于m序列的自相关函数只有两种取值(1和-1/(2n-1)),属于双值自相关序列。因此,如果数据未受到任何攻击和干扰,OneCount只有两种结果:255或0。当OneCount=255时,得到的水印信息位为1;当OneCount=0时,得到的水印信息位为0。如果数据受到攻击或干扰,OneCount有多种结果。根据统计分析,当OneCount>127时,得到的水印信息位为1,并且这255个IVOP色度子块中有(255-OneCount)个子块受到攻击或干扰;当OneCount<127时,得到的水印信息位为0,并且这255个IVOP色度子块中有OneCount个子块受到攻击或干扰。这样既可以统计总共有多少视频IVOP色度子块受到攻击或干扰,同时又能极强地恢复出原始水印信息。

3试验结果分析

试验结果表明,m序列的长度越长,检测效果越好,但能够嵌入的水印信息量也相应地减少。本方案中水印只嵌入在视频的IVOP中,不修改PVOP和BVOP,对帧跳跃与帧删除攻击稳健,因为IVOP不可以被跳跃或删除。同时,由于水印信息嵌入在DCT的直流系数中,而直流系数的变化对视频效果会有较大的影响,所以采取将水印信息嵌入到色度子块DCT直流系数的最低位。这样不仅使水印嵌入计算的复杂度大为降低,为MPEG-4编解码节省了时间,还可取得良好的视频效果,达到了不可觉察性。从统计角度看也不会增加视频码流。另外,水印提取时无需原始视频。若水印信息未受到攻击,则本方案可准确地提取到原始视频的完全水印;若水印信息受到攻击,根据扩频解调性质,本方案可以最大限度地恢复出原始水印信息,并统计出有多少个IVOP色度子块受到攻击。

由于DCT是目前多媒体视频压缩几大标准(H.261、H.263、MPEG-4等)共同采用的技术基础。因此基于DCT的水印方案在视频压缩中具有非常重要的研究意义和应用前景。本文在此基础上提出了一个基于扩展频谱的MPEG-4视频数字水印方案。实践证明,在不需要原始视频的情况下,本方案能敏感地检测到数据是否被篡改或破坏,并具有良好的稳定性和鲁棒性,从而提供了知识产权的保护,防止非法获取。

本文摘自《电子技术应用》

应用:数字水印

消息认证与数字签名可以应用到数字水印中。

传统水印用来证明纸币或纸张上内容的合法性,数字水印(digital watermark)用以证明一个数字产品的拥有权、真实性。数字水印是嵌在数字产品中的数字信息。可以是作者的序列号、公司标志、有特殊意义的文本等。

数字水印主要用于:阻止非法复制(间接的)、确定所有权(作者、发行人、分发商、合法的最终用户)、确定作品的真实性和完整性(是否伪造、被篡改)、证实收件人、不可否认的传送、法庭证据的验证、赝品甄别、识别文件来源与版本、Web网络巡逻监视盗贼等。

传统水印是人眼可以看得见的,而数字水印可以分为可感知的(Perceptible)和不易感知的(Inperceptible)两种。

可感知的数字水印,主要用于当场声明对产品的所有权、著作权及来源,起到一个宣传广告或约束的作用。可感知水印一般为较淡的或半透明的不碍观瞻的图案;比如电视台节目播放的同时,在某个角落插上电视台的半透明标志。另一个用途是为了在线分发作品,比如先将一个低分辨率的有可见水印的图像免费送人,其水印往往是拥有者或卖主的信息,它提供了寻找原高分辨率作品的线索,若想得到高分辨率的原作品则需付费。有些公司在产品出售前为了在网络上宣传其产品,先做上可逆可见水印分发,付费购买时,再用专用软件将可见水印去掉,加入不可见水印(发行人、分发商、最终用户等的信息)。可见水印还有另一些用途,那就是为了节约带宽、存储空间等原因,在VCD、DVD等电影拷贝中用嵌入不可见水印的方式配上多种语言的副标题和字幕,待播放时由硬件根据需要实时地解出每一帧中的水印文字,将其显示在屏幕上。

可见水印在某些产品中或多或少降低了作品的观赏价值,使其用途相对受到一定限制。不易感知的水印的应用层次更高,制作难度更大。

不易感知的数字水印就像隐形墨水技术中的看不见的文字,隐藏在数字产品中。水印的存在要以不破坏原数据的欣赏价值、使用价值为原则。数字水印按照某种方式植入被保护的信息中,在产生版权纠纷时,通过相应的算法提取出该数字水印,从而验证版权的归属。被保护的信息可以是图像、声音、视频或一般性的电子文档等。为了给攻击者增加去除水印的难度,大多数水印制作方案都在水印的嵌入、提取时使用密钥。

图5.7水印的嵌入与提取

数字水印技术虽然不能阻止盗版活动的发生,但它可以判别对象是否受到保护,监视被保护数据的传播、真伪鉴别和非法拷贝、解决版权纠纷并为法庭提供证据。

数字水印的设计需要考虑以下几个方面:

鲁棒性:是指被保护的信息经过某种改动后抵抗隐藏信息丢失的能力。例如传输过程中的信道噪音、滤波操作、重采样、有损编码压缩、D/ A或 A/ D转换、图像的几何变换(如平
参考技术A 并非专业只是提点个人看法

C语言高手帮下忙!

1、计算n阶矩阵的两条对角线上的元素的乘积。

2、统计通过键盘输入文件名,统计该文件名下的文件里字符的个数!!

用C语言表达!!!

1.for(i1=0;i1<n;i1++)
for(i2=n;i2>0;i2--)
sum+=a[i1][i1]*a[i1][i2];

2.我用语法生成器生成的c:

/* A lexical scanner generated by flex */

/* Scanner skeleton version:
* $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.85 95/04/24 10:48:47 vern Exp $
*/

#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 5

#include <stdio.h>

/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
#ifdef c_plusplus
#ifndef __cplusplus
#define __cplusplus
#endif
#endif

#ifdef __cplusplus

#include <stdlib.h>
#include <unistd.h>

/* Use prototypes in function declarations. */
#define YY_USE_PROTOS

/* The "const" storage-class-modifier is valid. */
#define YY_USE_CONST

#else /* ! __cplusplus */

#if __STDC__

#define YY_USE_PROTOS
#define YY_USE_CONST

#endif /* __STDC__ */
#endif /* ! __cplusplus */

#ifdef __TURBOC__
#pragma warn -rch
#pragma warn -use
#include <io.h>
#include <stdlib.h>
#define YY_USE_CONST
#define YY_USE_PROTOS
#endif

#ifdef YY_USE_CONST
#define yyconst const
#else
#define yyconst
#endif

#ifdef YY_USE_PROTOS
#define YY_PROTO(proto) proto
#else
#define YY_PROTO(proto) ()
#endif

/* Returned upon end-of-file. */
#define YY_NULL 0

/* Promotes a possibly negative, possibly signed char to an unsigned
* integer for use as an array index. If the signed char is negative,
* we want to instead treat it as an 8-bit unsigned char, hence the
* double cast.
*/
#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)

/* Enter a start condition. This macro really ought to take a parameter,
* but we do it the disgusting crufty way forced on us by the ()-less
* definition of BEGIN.
*/
#define BEGIN yy_start = 1 + 2 *

/* Translate the current start state into a value that can be later handed
* to BEGIN to return to the state. The YYSTATE alias is for lex
* compatibility.
*/
#define YY_START ((yy_start - 1) / 2)
#define YYSTATE YY_START

/* Action number for EOF rule of a given start state. */
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)

/* Special action meaning "start processing a new file". */
#define YY_NEW_FILE yyrestart( yyin )

#define YY_END_OF_BUFFER_CHAR 0

/* Size of default input buffer. */
#define YY_BUF_SIZE 16384

typedef struct yy_buffer_state *YY_BUFFER_STATE;

extern int yyleng;
extern FILE *yyin, *yyout;

#define EOB_ACT_CONTINUE_SCAN 0
#define EOB_ACT_END_OF_FILE 1
#define EOB_ACT_LAST_MATCH 2

/* The funky do-while in the following #define is used to turn the definition
* int a single C statement (which needs a semi-colon terminator). This
* avoids problems with code like:
*
* if ( condition_holds )
* yyless( 5 );
* else
* do_something_else();
*
* Prior to using the do-while the compiler would get upset at the
* "else" because it interpreted the "if" statement as being all
* done when it reached the \';\' after the yyless() call.
*/

/* Return all but the first \'n\' matched characters back to the input stream. */

#define yyless(n) \\
do \\
\\
/* Undo effects of setting up yytext. */ \\
*yy_cp = yy_hold_char; \\
yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \\
YY_DO_BEFORE_ACTION; /* set up yytext again */ \\
\\
while ( 0 )

#define unput(c) yyunput( c, yytext_ptr )

/* The following is because we cannot portably get our hands on size_t
* (without autoconf\'s help, which isn\'t available because we want
* flex-generated scanners to compile on their own).
*/
typedef unsigned int yy_size_t;

struct yy_buffer_state

FILE *yy_input_file;

char *yy_ch_buf; /* input buffer */
char *yy_buf_pos; /* current position in input buffer */

/* Size of input buffer in bytes, not including room for EOB
* characters.
*/
yy_size_t yy_buf_size;

/* Number of characters read into yy_ch_buf, not including EOB
* characters.
*/
int yy_n_chars;

/* Whether we "own" the buffer - i.e., we know we created it,
* and can realloc() it to grow it, and should free() it to
* delete it.
*/
int yy_is_our_buffer;

/* Whether this is an "interactive" input source; if so, and
* if we\'re using stdio for input, then we want to use getc()
* instead of fread(), to make sure we stop fetching input after
* each newline.
*/
int yy_is_interactive;

/* Whether we\'re considered to be at the beginning of a line.
* If so, \'^\' rules will be active on the next match, otherwise
* not.
*/
int yy_at_bol;

/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
int yy_fill_buffer;

int yy_buffer_status;
#define YY_BUFFER_NEW 0
#define YY_BUFFER_NORMAL 1
/* When an EOF\'s been seen but there\'s still some text to process
* then we mark the buffer as YY_EOF_PENDING, to indicate that we
* shouldn\'t try reading from the input source any more. We might
* still have a bunch of tokens to match, though, because of
* possible backing-up.
*
* When we actually see the EOF, we change the status to "new"
* (via yyrestart()), so that the user can continue scanning by
* just pointing yyin at a new input file.
*/
#define YY_BUFFER_EOF_PENDING 2
;

static YY_BUFFER_STATE yy_current_buffer = 0;

/* We provide macros for accessing buffer states in case in the
* future we want to put the buffer states in a more general
* "scanner state".
*/
#define YY_CURRENT_BUFFER yy_current_buffer

/* yy_hold_char holds the character lost when yytext is formed. */
static char yy_hold_char;

static int yy_n_chars; /* number of characters read into yy_ch_buf */

int yyleng;

/* Points to current character in buffer. */
static char *yy_c_buf_p = (char *) 0;
static int yy_init = 1; /* whether we need to initialize */
static int yy_start = 0; /* start state number */

/* Flag which is used to allow yywrap()\'s to do buffer switches
* instead of setting up a fresh yyin. A bit of a hack ...
*/
static int yy_did_buffer_switch_on_eof;

void yyrestart YY_PROTO(( FILE *input_file ));

void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
void yy_load_buffer_state YY_PROTO(( void ));
YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )

YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *str ));
YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));

static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
static void yy_flex_free YY_PROTO(( void * ));

#define yy_new_buffer yy_create_buffer

#define yy_set_interactive(is_interactive) \\
\\
if ( ! yy_current_buffer ) \\
yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \\
yy_current_buffer->yy_is_interactive = is_interactive; \\


#define yy_set_bol(at_bol) \\
\\
if ( ! yy_current_buffer ) \\
yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \\
yy_current_buffer->yy_at_bol = at_bol; \\


#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)

typedef unsigned char YY_CHAR;
FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
typedef int yy_state_type;
extern char *yytext;
#define yytext_ptr yytext

static yy_state_type yy_get_previous_state YY_PROTO(( void ));
static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
static int yy_get_next_buffer YY_PROTO(( void ));
static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));

/* Done after the current pattern has been matched and before the
* corresponding action - sets up yytext.
*/
#define YY_DO_BEFORE_ACTION \\
yytext_ptr = yy_bp; \\
yyleng = (int) (yy_cp - yy_bp); \\
yy_hold_char = *yy_cp; \\
*yy_cp = \'\\0\'; \\
yy_c_buf_p = yy_cp;

#define YY_NUM_RULES 4
#define YY_END_OF_BUFFER 5
static yyconst short int yy_accept[9] =
0,
0, 0, 5, 3, 2, 1, 1, 0
;

static yyconst int yy_ec[256] =
0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 1, 1, 1,
1, 1, 1, 1, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1, 1, 1, 1, 1, 1, 3, 3, 3, 3,

3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1
;

static yyconst int yy_meta[4] =
0,
1, 1, 2
;

static yyconst short int yy_base[10] =
0,
0, 0, 5, 6, 6, 0, 0, 6, 2
;

static yyconst short int yy_def[10] =
0,
8, 1, 8, 8, 8, 9, 9, 0, 8
;

static yyconst short int yy_nxt[10] =
0,
4, 5, 6, 7, 8, 3, 8, 8, 8
;

static yyconst short int yy_chk[10] =
0,
1, 1, 1, 9, 3, 8, 8, 8, 8
;

static yy_state_type yy_last_accepting_state;
static char *yy_last_accepting_cpos;

/* The intent behind this definition is that it\'ll catch
* any uses of REJECT which flex missed.
*/
#define REJECT reject_used_but_not_detected
#define yymore() yymore_used_but_not_detected
#define YY_MORE_ADJ 0
char *yytext;
#line 1 "lex.l"
#define INITIAL 0
#line 2 "lex.l"
/*a lex program for counting the number of character, word and line in the input file*/
#include <stdio.h>
#include <string.h>

/*the line count*/
int iLineNo = 0;
/*the character counter*/
int iCharNo = 0;
/*the word counter*/
int iWordNo = 0;
#line 372 "lex.yy.c"

/* Macros after this point can all be overridden by user definitions in
* section 1.
*/

#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
extern "C" int yywrap YY_PROTO(( void ));
#else
extern int yywrap YY_PROTO(( void ));
#endif
#endif

#ifndef YY_NO_UNPUT
static void yyunput YY_PROTO(( int c, char *buf_ptr ));
#endif

#ifndef yytext_ptr
static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
#endif

#ifndef YY_NO_INPUT
#ifdef __cplusplus
static int yyinput YY_PROTO(( void ));
#else
static int input YY_PROTO(( void ));
#endif
#endif

#if YY_STACK_USED
static int yy_start_stack_ptr = 0;
static int yy_start_stack_depth = 0;
static int *yy_start_stack = 0;
#ifndef YY_NO_PUSH_STATE
static void yy_push_state YY_PROTO(( int new_state ));
#endif
#ifndef YY_NO_POP_STATE
static void yy_pop_state YY_PROTO(( void ));
#endif
#ifndef YY_NO_TOP_STATE
static int yy_top_state YY_PROTO(( void ));
#endif

#else
#define YY_NO_PUSH_STATE 1
#define YY_NO_POP_STATE 1
#define YY_NO_TOP_STATE 1
#endif

#ifdef YY_MALLOC_DECL
YY_MALLOC_DECL
#else
#if __STDC__
#ifndef __cplusplus
#include <stdlib.h>
#endif
#else
/* Just try to get by without declaring the routines. This will fail
* miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
* or sizeof(void*) != sizeof(int).
*/
#endif
#endif

/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
#define YY_READ_BUF_SIZE 8192
#endif

/* Copy whatever the last rule matched to the standard output. */

#ifndef ECHO
/* This used to be an fputs(), but since the string might contain NUL\'s,
* we now use fwrite().
*/
#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
#endif

/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
* is returned in "result".
*/
#ifndef YY_INPUT
#define YY_INPUT(buf,result,max_size) \\
if ( yy_current_buffer->yy_is_interactive ) \\
\\
int c = \'*\', n; \\
for ( n = 0; n < max_size && \\
(c = getc( yyin )) != EOF && c != \'\\n\'; ++n ) \\
buf[n] = (char) c; \\
if ( c == \'\\n\' ) \\
buf[n++] = (char) c; \\
if ( c == EOF && ferror( yyin ) ) \\
YY_FATAL_ERROR( "input in flex scanner failed" ); \\
result = n; \\
\\
else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \\
&& ferror( yyin ) ) \\
YY_FATAL_ERROR( "input in flex scanner failed" );
#endif

/* No semi-colon after return; correct usage is to write "yyterminate();" -
* we don\'t want an extra \';\' after the "return" because that will cause
* some compilers to complain about unreachable statements.
*/
#ifndef yyterminate
#define yyterminate() return YY_NULL
#endif

/* Number of entries by which start-condition stack grows. */
#ifndef YY_START_STACK_INCR
#define YY_START_STACK_INCR 25
#endif

/* Report a fatal error. */
#ifndef YY_FATAL_ERROR
#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
#endif

/* Default declaration of generated scanner - a define so the user can
* easily add parameters.
*/
#ifndef YY_DECL
#define YY_DECL int yylex YY_PROTO(( void ))
#endif

/* Code executed at the beginning of each rule, after yytext and yyleng
* have been set up.
*/
#ifndef YY_USER_ACTION
#define YY_USER_ACTION
#endif

/* Code executed at the end of each rule. */
#ifndef YY_BREAK
#define YY_BREAK break;
#endif

#define YY_RULE_SETUP \\
YY_USER_ACTION

YY_DECL

register yy_state_type yy_current_state;
register char *yy_cp, *yy_bp;
register int yy_act;

#line 15 "lex.l"

#line 521 "lex.yy.c"

if ( yy_init )

yy_init = 0;

#ifdef YY_USER_INIT
YY_USER_INIT;
#endif

if ( ! yy_start )
yy_start = 1; /* first start state */

if ( ! yyin )
yyin = stdin;

if ( ! yyout )
yyout = stdout;

if ( ! yy_current_buffer )
yy_current_buffer =
yy_create_buffer( yyin, YY_BUF_SIZE );

yy_load_buffer_state();


while ( 1 ) /* loops until end-of-file is reached */

yy_cp = yy_c_buf_p;

/* Support of yytext. */
*yy_cp = yy_hold_char;

/* yy_bp points to the position in yy_ch_buf of the start of
* the current run.
*/
yy_bp = yy_cp;

yy_current_state = yy_start;
yy_match:
do

register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
if ( yy_accept[yy_current_state] )

yy_last_accepting_state = yy_current_state;
yy_last_accepting_cpos = yy_cp;

while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )

yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 9 )
yy_c = yy_meta[(unsigned int) yy_c];

yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;

while ( yy_base[yy_current_state] != 6 );

yy_find_action:
yy_act = yy_accept[yy_current_state];
if ( yy_act == 0 )
/* have to back up */
yy_cp = yy_last_accepting_cpos;
yy_current_state = yy_last_accepting_state;
yy_act = yy_accept[yy_current_state];


YY_DO_BEFORE_ACTION;

do_action: /* This label is used only to access EOF actions. */

switch ( yy_act )
/* beginning of action switch */
case 0: /* must back up */
/* undo the effects of YY_DO_BEFORE_ACTION */
*yy_cp = yy_hold_char;
yy_cp = yy_last_accepting_cpos;
yy_current_state = yy_last_accepting_state;
goto yy_find_action;

case 1:
YY_RULE_SETUP
#line 16 "lex.l"
iWordNo++; iCharNo += strlen(yytext);
YY_BREAK
case 2:
YY_RULE_SETUP
#line 17 "lex.l"
iLineNo++;
YY_BREAK
case 3:
YY_RULE_SETUP
#line 18 "lex.l"
iCharNo++;
YY_BREAK
case 4:
YY_RULE_SETUP
#line 19 "lex.l"
ECHO;
YY_BREAK
#line 624 "lex.yy.c"
case YY_STATE_EOF(INITIAL):
yyterminate();

case YY_END_OF_BUFFER:

/* Amount of text matched not including the EOB char. */
int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;

/* Undo the effects of YY_DO_BEFORE_ACTION. */
*yy_cp = yy_hold_char;

if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )

/* We\'re scanning a new file or input source. It\'s
* possible that this happened because the user
* just pointed yyin at a new source and called
* yylex(). If so, then we have to assure
* consistency between yy_current_buffer and our
* globals. Here is the right place to do so, because
* this is the first action (other than possibly a
* back-up) that will match for the new input source.
*/
yy_n_chars = yy_current_buffer->yy_n_chars;
yy_current_buffer->yy_input_file = yyin;
yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;


/* Note that here we test for yy_c_buf_p "<=" to the position
* of the first EOB in the buffer, since yy_c_buf_p will
* already have been incremented past the NUL character
* (since all states make transitions on EOB to the
* end-of-buffer state). Contrast this with the test
* in input().
*/
if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
/* This was really a NUL. */
yy_state_type yy_next_state;

yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;

yy_current_state = yy_get_previous_state();

/* Okay, we\'re now positioned to make the NUL
* transition. We couldn\'t have
* yy_get_previous_state() go ahead and do it
* for us because it doesn\'t know how to deal
* with the possibility of jamming (and we don\'t
* want to build jamming into it because then it
* will run more slowly).
*/

yy_next_state = yy_try_NUL_trans( yy_current_state );

yy_bp = yytext_ptr + YY_MORE_ADJ;

if ( yy_next_state )

/* Consume the NUL. */
yy_cp = ++yy_c_buf_p;
yy_current_state = yy_next_state;
goto yy_match;


else

yy_cp = yy_c_buf_p;
goto yy_find_action;



else switch ( yy_get_next_buffer() )

case EOB_ACT_END_OF_FILE:

yy_did_buffer_switch_on_eof = 0;

if ( yywrap() )

/* Note: because we\'ve taken care in
* yy_get_next_buffer() to have set up
* yytext, we can now set up
* yy_c_buf_p so that if some total
* hoser (like flex itself) wants to
* call the scanner after we return the
* YY_NULL, it\'ll still work - another
* YY_NULL will get returned.
*/
yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;

yy_act = YY_STATE_EOF(YY_START);
goto do_action;


else

if ( ! yy_did_buffer_switch_on_eof )
YY_NEW_FILE;

break;


case EOB_ACT_CONTINUE_SCAN:
yy_c
参考技术A 第二个


FILE *fp;
fp=fopen(\"****\",rb);////////****表示你要打开的文件路径
if(NULL==fp)
printf(\"出错了!\");exit(0);
long tt;
fseek(fp,0,2);
tt=ftell(fp);
printf(\"个数为:%l\",tt);
fclose(fp);
参考技术B 1。N阶矩阵你可以使用2维数组来存放,然后把里面的对应元素乘起来就行了
伪代码:
for(int i=0;i<=n;i++)

for(int h=0;h<=n;h++)

if(h==i)result1=result1*juzhen[h][i]; //当为对角线时候,计算乘积
if((n-h)==i))result1=result1*juzhen[n-h][i]; //当为另一对角线时候,计算乘积




result跟result1就是结果

第二题用文件流就行,定义一个变量存放文件流,文件的内容就放在变量里面

以上为伪代码
参考技术C 这两个都简单的

以上是关于数字水印的价值,意义以及优点~谁能帮下忙的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Agora android 中添加文字水印?

谁能告诉我MD5值的用途?怎样去用呢?下面问题补充中文件检验码的SHA和CRC32又有啥用呢?帮下忙哈!谢谢

水印攻击信息提取基于盲带矩阵DWT变换和DCT变换数字水印嵌入和水印攻击之后的图像信息提取解析matlab仿真(包括噪声攻击,旋转攻击以及压缩攻击)

图像隐写基于matlab GUI DCT数字水印嵌入+提取含Matlab源码 1671期

语音隐写基于matlab GUI DCT音频数字水印嵌入提取含Matlab源码 837期

语音隐写基于matlab GUI DCT音频数字水印嵌入提取含Matlab源码 837期