资讯动态

基于DWT的Matlab图像水印嵌入与攻击测试实战指南

发布时间:2026/9/16 19:28:46 来源:尧图企业网站定制
简介面向数字图像版权保护与信息安全应用场景这份MATLAB源码围绕离散小波变换DWT实现了完整的图像水印嵌入与提取流程并对缩放、旋转、裁剪、加噪等常见攻击下的鲁棒性进行了测试。压缩包内共2个文件包括一个负责DWT分解、水印系数修改、反变换重建与攻击模拟的MATLAB脚本以及一个Word文档整体大小约1.1MB。目前已有299人学习下载适合课程设计、毕业设计或算法对比研究。通过运行源码可直观看到水印嵌入前后图像的变化理解LL、LH、HL、HH四个子带在嵌入中的作用分析高频系数调整幅度对水印不可见性和提取准确率的影响源码中的攻击模拟部分还能帮助对比多种干扰下的提取效果为改进嵌入策略与提升抗攻击能力提供实验依据。1. 用DWT做图像水印先想清楚你挡的是哪类攻击如果只是给图片加个“仅供预览”的文字水印前端或Photoshop就够了。真正需要DWT这套方案的场景是水印要扛得住截图之外的常规处理被压缩、被缩放过、被加了噪声、被裁掉一块甚至被旋转几度仍然能从图像里把水印信息解出来。这就是图像水印和“贴个标签”的本质区别。本篇讲的这套Matlab源码提供了嵌入、提取和各类攻击测试的完整路径涵盖dwt2分解、系数叠加、提取比对、NC值评估四个环节。对于刚接触数字水印的读者小波变换DWT目前是鲁棒性研究和工程实现中用的最多的一类做法它可以和空间域LSB方法、DCT频域方法直接对比。对于有5年以上图像处理经验的人来说值得关注的是嵌入强度alpha的取值策略、小波基选择对不可见性的影响以及攻击模拟里“提取出来了但NC很低”这种结果的排查方法。适合人群包括课程设计与论文复现的学生、做版权保护和内容溯源预研的工程师以及需要快速验证DWT水印效果的算法开发人员。2. 为什么嵌入要用DWT四个子带的取舍逻辑2.1 离散小波变换的空间与频率局部化优势DWT和DCT、DFT最大的不同在于它把图像同时拆成了空间位置和频率两个维度。一次dwt2分解得到四个子带CA是低频近似分量CH是水平细节CV是垂直细节CD是对角细节。低频子带集中了图像绝大部分能量人眼对它最敏感但对压缩、滤波、缩放的改动也最不敏感高频子带则相反改动不易察觉却很容易在处理中被抹掉。图像水印要做的是在“感知不到”和“丢不掉”之间找平衡。低频能量大水印嵌入后抗干扰能力强但嵌入过强会看到块状伪影高频嵌入隐蔽但JPEG压缩一次可能就没了。这就是为什么大多数DWT水印方案把目标锁定在CA子带或者CA再继续分解一次的LL2子带上。2.2 常见做法CA子带加性嵌入与提取以“加性嵌入”为例核心公式是CA_watermarked CA_original alpha * watermark_sequence其中alpha是嵌入强度watermark_sequence是水印的二值序列通常映射为-1和1两种值。提取时用待测图像的CA子带减去原始图像的CA子带再做符号判决超过0判为1否则判为-1。这种方案需要原始图像参与属于非盲水印如果希望做盲提取一般会改用量化索引调制将CA系数按量化步长映射到不同区间提取时不需要原始载体。小波基选择上db1即Haar计算最快但块效应略明显db2到db4系数滤波更长透明性更好。分解层数上1层适合快速验证2层到3层对低通攻击的鲁棒性更好。2.3 子带选择对照表子带能量占比不可见性压力抗JPEG压缩抗噪声常见用途CALL最高大强强主流嵌入区域CH水平中中中中配合LL增强鲁棒性CV垂直中中中中同上CD对角低小弱弱一般不单独用在MATLAB里做一层小波变换只需要一行核心调用但真正影响水印效果的是嵌入强度、水印长度和层数。参数写死在源码里跑通很容易换一张图就失效的典型原因往往是alpha没有随着图像能量做自适应调整。3. Matlab源码跑通DWT水印嵌入提取的完整步骤3.1 嵌入端核心代码% 嵌入端读图、分解、叠加水印 clear; clc; alpha 0.1; % 嵌入强度典型范围 0.05 ~ 0.3 watermark_len 1024; % 水印序列长度 rng(2024); wm_seq (-1).^(rand(1, watermark_len) 0.5); % 生成 [-1,1] 二值序列 I imread(lena.png); if size(I, 3) 3 I rgb2gray(I); % 统一转灰度 end I im2double(I); % 转double避免uint8溢出 [CA, CH, CV, CD] dwt2(I, db2); % 将CA展开成一维长度不足时裁剪 ca_vec CA(:); if length(ca_vec) watermark_len error(CA系数数量不足请减小水印长度或增加图像尺寸); end ca_sel ca_vec(1:watermark_len); % 加性嵌入 ca_sel_mark ca_sel .* (1 alpha * wm_seq); % 写回并重构 ca_mark CA; ca_mark(1:watermark_len) ca_sel_mark; % 注意这里要按列展开的索引顺序 I_watermarked idwt2(ca_mark, CH, CV, CD, db2); I_watermarked max(0, min(1, I_watermarked)); imwrite(I_watermarked, watermarked.png);这段代码先对原图做一层db2小波分解取CA子带的一维向量化表示按位置叠加水印。alpha乘在CA系数上而不是直接相加好处是让强度跟着局部能量走能量大的区域改动也大视觉上不易暴露。写回时ca_mark(1:watermark_len) ca_sel_mark;这一行的索引必须和前面ca_vec CA(:);的顺序完全一致否则嵌入位置错位提取时对不上。3.2 提取端核心代码% 提取端读含水印图像利用原图CA恢复水印 I_w imread(watermarked.png); if size(I_w, 3) 3 I_w rgb2gray(I_w); end I_w im2double(I_w); [CA_w, ~, ~, ~] dwt2(I_w, db2); ca_w_vec CA_w(:); ca_w_sel ca_w_vec(1:watermark_len); % 关键这里需要原始图像的CA系数 [CA0, ~, ~, ~] dwt2(I, db2); ca0_vec CA0(:); ca0_sel ca0_vec(1:watermark_len); % 差值判决 diff_seq ca_w_sel - ca0_sel; extracted sign(diff_seq); % 大于0为1小于0为-1等于0按0处理 % 与原始水印比对 correct sum(extracted wm_seq) / watermark_len; fprintf(提取正确率: %.2f%%\n, correct * 100);正确率的本质是“符号一致性比例”这在学术里对应相关系数或比特错误率。上面代码用的是最简单的硬判决。如果遇到正确率刚好在50%附近先检查嵌入和提取用的watermark_len是否一致再检查攻击后是否发生了几何变换导致系数位置错乱。3.3 参数选择建议参数建议值说明alpha0.05~0.15越小越隐蔽0.05以下容易提取失败小波基db2/db4不要用sym8这类长滤波器系数定位复杂且无明显收益分解层数1~23层后CA尺寸太小容纳不了较长水印水印长度512~2048图像越小越要压缩水印长度图像尺寸256×256以上越小越不适合DWT方案3.4 扩展为二级小波分解% 对低频再分解一次水印嵌在LL2 [CA2, CH2, CV2, CD2] dwt2(CA, db2); ca2_vec CA2(:); % ... 同样的嵌入逻辑放在ca2_vec上 ... % 重构idwt2还原CA再用CA重构图像二级分解的优势是水印落在更接近图像本质低频的区域抗缩放和抗压缩能力更强代价是CA2尺寸缩小到原图的四分之一能嵌入的比特数变少。嵌入前可以打印size(CA2)确认水印长度不超过系数总数。4. 各类攻击模拟与提取失败排查4.1 攻击类型对应的Matlab实现攻击代码说明高斯噪声imnoise(I_w, gaussian, 0, 0.01)模拟传感器噪声椒盐噪声imnoise(I_w, salt pepper, 0.01)模拟传输丢点缩放攻击imresize(I_w, 0.5); imresize(..., [H, W])两次缩放恢复原尺寸旋转攻击imrotate(I_w, 5, bilinear, crop)会引入边缘裁剪剪切攻击置零一个矩形区域模拟局部篡改JPEG压缩imwrite(I_w, tmp.jpg, Quality, 30); imread(tmp.jpg)最常见攻击4.2 批量攻击测试脚本attacks {noise, jpeg, resize, rotate, crop}; for k 1:length(attacks) switch attacks{k} case noise I_att imnoise(I_w, gaussian, 0, 0.005); case jpeg imwrite(I_w, tmp_q30.jpg, Quality, 30); I_att imread(tmp_q30.jpg); I_att im2double(I_att); case resize I_att imresize(I_w, 0.5); I_att imresize(I_att, size(I_w)); case rotate I_att imrotate(I_w, 3, bilinear, crop); case crop I_att I_w; I_att(50:150, 50:150) 0; end % 提取 [CA_a, ~, ~, ~] dwt2(rgb2gray(I_att), db2); ca_a_vec CA_a(:); diff_a ca_a_vec(1:watermark_len) - ca0_sel; ext_a sign(diff_a); acc sum(ext_a wm_seq) / watermark_len; fprintf(%s 攻击后正确率: %.2f%%\n, attacks{k}, acc*100); end每一次提取失败先分开看是“攻击把能量推到了别的系数上”还是“攻击导致几何位置错位”。旋转和缩放最常见的问题是子带系数位置和原图对不齐如果旋转后正确率接近50%那几乎不是alpha不够大而是坐标对齐问题需要先做图像配准或模板同步单纯提高alpha没有用。4.3 常见失败现象对照现象真正原因对策无攻击时正确率也低嵌入提取索引错位检查CA(:)的展开顺序JPEG质量30后正确率低于60%alpha偏低或水印过长提高alpha到0.15缩短水印到256旋转后正确率在50%附近坐标没有对齐放弃直接提取改用同步模板或旋转校正缩放后提取失真尺寸恢复用了不同插值提取前保持完全相同尺寸剪切区域覆盖嵌入位置水印信息过于集中把水印扩散到整个低频子带而不是前N个位置5. 调优思路从“能跑通”到“能拿去答辩或演示”做完上述步骤这套源码已经具备“嵌入、提取、攻击测试”的能力。常见改进方向有三个。第一是自适应的alpha策略。固定alpha在小图或纹理复杂区域易产生可见伪影可以统计CA子带每个系数的局部方差方差大的系数用较大alpha方差小的用较小alpha在MATLAB里用nlfilter或矩阵运算步长做局部统计即可。第二是水印信息加密生成的随机序列如果由固定的伪随机种子决定攻击者一旦知道种子就能擦除水印建议对水印做一次置乱比如用randperm重新排序提取后再逆向还原。第三是自动验证脚本写一个循环扫描alpha从0.02到0.3的所有值输出每个值下的PSNR和NC曲线用这个曲线选参数比手调更有说服力答辩评委通常吃这一套。若遇到“打开PDF提示无法提取嵌入的字体”这类问题那是把Matlab figure导出到PDF时字体渲染的问题和水印无关exportgraphics输出时把字体格式设为标准的TrueType就行。最后验收时建议先跑一遍无攻击的嵌入提取确认正确率达到100%再逐个开启攻击记录每个攻击的NC值这才算把demo序列完整走通。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价