基于DRPE与压缩感知的安全图像加密方案及MATLAB仿真
发布时间:2026/9/26 16:12:59来源:尧图网络
图像数据在传输和存储过程中的安全隐患是这几年很多人找我聊的一个实际问题。无论是医疗影像、机密图纸还是普通用户的云端相册一旦原始图像泄露损失往往比文件本身更大。传统方案要么只做加密不做压缩要么为了压缩牺牲安全性。基于双随机相位编码Double Random Phase EncodingDRPE和压缩感知Compressive SensingCS的安全图像加密方案正是把两件事合并成一道流程压缩感知先把图像变成更小的测量值双随机相位编码再对测量值进行数值层面的加密整套链路用 MATLAB 就能完整仿真出来。这篇东西没有太多公式堆砌我按自己做实验的顺序从原理、参数、代码到踩坑一条条讲清楚适合正在做图像加密方向课程设计、毕设或者需要工程验证的读者参考。1. 为什么非要把“压缩”和“加密”放在一起做1.1 传统图像加密方案的短板先说常规的图像加密思路也是很多教材里最先教你做的两种操作位置置乱和灰度扩散。位置置乱就是用手动版或者 Arnold 变换把像素位置打乱灰度扩散则是用异或、混沌序列把像素值改掉。这些方案本身的逻辑没有错对图像内容也有隐藏作用但有一个现实问题始终绕不过去它们不改变数据量。现在随便一张相机原图就是几十MB医学CT、遥感影像动不动上千像素宽密文如果是完全随机的噪声式像素熵变大之后文件反而比原图还膨胀。传输带宽和存储空间不是无限资源很多场景里你先加密再传输到另一端还要解密中间那一大坨密文数据本身就是负担。加密不带上压缩效率上永远差一截。另外一个隐患是安全性。单纯的置乱和扩散抗不住选择明文攻击攻击者挑一批特殊图像喂进去比对输入输出就能反推出置乱表或密钥流。DRPE 本身也有类似问题它是一个线性变换经典的双随机相位板如果可以构造已知明文对等效密钥是可以被推算出来的。所以把 DRPE 单独拿出来用并不像名字听上去那么“绝对安全”。1.2 组合方案到底安全在哪压缩感知和双随机相位编码组合起来核心意义有两个。第一CS 把高维图像信号投影到低维测量值数据量真正降下来了这是传统加密做不到的。第二压缩感知的测量矩阵本身就是一把密钥再加上 DRPE 的两块随机相位板整套系统变成“先降维嵌入、再随机相位调制”的两级保护。我用一个生活化的类比来解释你把一幅画先缩小放进一个特制密码箱缩小本身就丢掉了大量视觉信息没钥匙的人看到的只是一堆抽象点随后你又在箱子外面加两道随机相位锁第一道锁打不开就取不到画第二道锁参数错了取出来的也是一团噪声。攻击者要同时知道测量矩阵和两块相位板才能从密文一路恢复到明文缺任何一环都解不出来。密钥空间在这里是相乘关系攻击成本比特意做完每一层加密要高得多。1.3 方案整体流程与模块划分整个 MATLAB 仿真链路我建议分成四个模块来理解预处理读入灰度图归一化到0到1范围必要时把彩色图转成灰度图。压缩感知模块对图像分块逐块做稀疏变换DCT或DWT再用高斯随机测量矩阵投影到低维测量空间。双随机相位编码模块对拼接好的测量值矩阵施加第一块相位板做二维傅里叶变换再乘第二块相位板做逆傅里叶变换得到复值密文。解密与重构模块逆DRPE恢复测量值用OMP重构稀疏系数逆变换回图像块并拼接。这样拆开之后每一部分都能单独调试出了问题也容易定位。具体实现时先在一张小图上跑通再放大到完整尺寸是我个人比较推荐的调试方式。2. 双随机相位编码原理与MATLAB数值实现2.1 从光学到数值DRPE的两次随机相位调制DRPE 最早是光学加密方案它有两个随机相位掩膜一个放在输入平面一个放在频谱平面。加密过程是原始图像先乘以第一块随机相位板相当于给明文的每个像素叠加上一个随机相位扰动然后经过透镜做傅里叶变换在频域中乘以第二块随机相位板再经过一次逆傅里叶变换得到复值密文。直接用公式表达更清楚E(x) IFT{ FT{ I(x) · exp(iφ1(x)) } · exp(iφ2(u)) }解密则完全逆过来先对密文做傅里叶变换并乘上第二块相位板的共轭再逆变换回来最后乘第一块相位板的共轭就能恢复明文。相位共轭在光学上对应相位共轭波前在 MATLAB 里就是对 exp(iφ) 取 conj。这里我必须提醒一条容易踩的坑数值仿真不是真的光路没有透镜焦距和光阑所以我们用 fft2 和 ifft2 来模拟两次傅里叶变换。光学系统里光路有一定的对齐精度要求数值仿真则不需要关心这些物理对准但代价是仿真结果偏理想真实光学实现时还要考虑SLM的像素分辨率、相位量化位数和光强噪声。2.2 密钥生成与离散傅里叶变换的实现要点两块随机相位板的生成方式我习惯用均匀分布的随机相位。MATLAB 里写起来非常简单row 128; col 256; phase1 exp(2i * pi * rand(row, col)); phase2 exp(2i * pi * rand(row, col));rand 生成 0 到 1 的均匀分布乘上 2π 后相位覆盖整个单位圆。这个均匀性很重要如果相位集中在某个小区间频域调制就不均匀加密效果会打折。接着就有一个新手必踩的坑rand 每次运行结果都不一样。如果你在脚本里直接生成相位板没有固定随机种子也没有把相位板存下来那解密的时候就等于丢了一把钥匙。我最开始做这个实验时就是直接在脚本里原地生成相位矩阵跑到解密阶段发现恢复图像全是噪声找了半天原因才发现是相位板变了。我现在的习惯是固定 rng 种子把 phase1、phase2、测量矩阵 Phi 一起存到 keys.mat 文件里。fft2 的缩放也是老生常谈的问题。MATLAB 里 fft2 和 ifft2 是配对使用的加密端用了 fft2 和 ifft2解密端也要对应使用不要自己引入额外的缩放系数。如果你不理解为什么恢复图像整体偏暗可以先检查加密和解密的傅里叶变换是否成对。2.3 为什么不能只依赖DRPE本身可能有人会问DRPE 已经有随机相位做密钥了为什么还要叠一个压缩感知这里要说清楚一个事实DRPE 本质是线性变换所有操作都是乘相位、傅里叶变换、再乘相位输入输出之间存在线性映射关系。对于选择明文攻击场景攻击者如果能够选定若干明文并拿到对应密文就能通过线性代数手段推算出等效的频域密钥哪怕不能直接得到相位板的原始相位值也能构造一个功能等价的解密算子。DRPE 单独用时密文尺寸和明文尺寸完全一致没有任何压缩能力。高分辨率图像直接进光路也好进 MATLAB 仿真也好数据量一点没减。把它放在 CS 后面一方面隐藏了明文的结构信息另一方面让整个加密映射变成“先降维嵌入再随机相位调制”的复合非线性流程破解难度和密钥维度都大幅提升。我个人的体会是DRPE 适合当第二层保险而不是唯一防线。3. 压缩感知如何给图像再上一把锁3.1 稀疏表示、测量矩阵与重构算法压缩感知的前提是信号在某个变换域下具有稀疏性。自然图像就是这样绝大多数像素在 DCT 或 DWT 域里只有少数大系数其余系数接近0。我以 DCT 举例一个 64×64 的小块用 dct2 变换后左上角低频系数集中在少量位置把系数按阈值截断后大量位置都是0这就是稀疏表示。测量过程用公式说就是 y Φ · xx 是稀疏系数向量Φ 是 M×N 的测量矩阵M 远小于 N。因为测量值维度低于信号维度理论上这是个欠定问题但结合稀疏性先验可以用压缩感知重构算法恢复原始系数向量。常用算法有 OMP、SP、CoSaMP还有基于凸优化的基追踪。OMP 思路很直观每次都找和当前残差相关性最大的那一列原子把该原子加入支撑集做最小二乘更新系数更新残差重复迭代直到满足停止条件。在 MATLAB 里手写一版教学用的 OMP 并不难但它对迭代次数、终止阈值都比较敏感我后面会给一个可用的实现。3.2 测量矩阵作为额外密钥安全增益与方法讨论如果把压缩感知单独当成加密手段只用测量矩阵当密钥安全强度其实有限因为测量过程也是线性的已知明文攻击下同样存在被反推的风险。但放到整个系统里CS 起的作用就不是单纯加密而是“压缩后牺牲一部分明文信息换取安全性”的前端处理。测量矩阵 Φ 本身是随机矩阵攻击者不知道 Φ就无法建立测量值 y 与稀疏系数 x 之间的对应关系就算攻击者从信道里拿到了密文并成功逆DRPE面对的仍然是一个欠定线性系统没有稀疏性先验和测量矩阵解不出来。反过来如果测量矩阵泄露了DRPE 的相位板也仍然保护着测量值两层密钥是互补的。我测试过的测量矩阵类型有高斯随机矩阵、伯努利随机矩阵和部分哈达玛矩阵。高斯随机矩阵在 RIP受限等距性质上表现稳定实现简单适合做基础方案。伯努利矩阵计算更快但在低测量率时恢复质量略有下降。实际项目中如果对存储有要求可以考虑用固定种子生成循环测量矩阵但安全余量会小一点这个需要权衡。3.3 分块处理与参数选择我最开始是把整张 256×256 图像直接拉成向量做压缩感知结果测量矩阵是 M×65536内存直接爆炸重构也是灾难级的慢。后来改成 Block CS 分块处理图像先切成 64×64 的块每块拉成 4096 维向量测量矩阵只要 M×4096计算量小了很多还可以用并行循环加速。块大小和测量率的搭配有讲究。块太小比如 16×16块内稀疏性差DCT 系数不够集中重构质量会明显下降块太大比如 128×128虽然稀疏性更好但测量矩阵维数高OMP 每一步最小二乘都变慢内存占用也上来了。我这里最推荐 64×64配合测量率 0.5 到 0.75是速度和质量的平衡点。测量率的选择千万不要照抄论文参数就完事。我习惯的做法是固定块大小和稀疏基把测量率从 0.3 扫到 0.9画一条 PSNR 曲线优先保证解密后的图像能看清关键结构再看压缩倍数能不能接受。一般低于 0.4 时恢复图像会明显出现块效应和振铃高于 0.8 时PSNR 提升趋于饱和但密文数据量反而变大压缩收益就没了。4. MATLAB完整实现流程与核心代码4.1 从明文到复值密文加密端代码我直接贴简化版加密端代码。这里默认输入是 256×256 灰度图块大小64测量率0.5稀疏基用 DCT。% 加密端 orig im2double(imread(lena_256.bmp)); [M, N] size(orig); blockSize 64; measureRate 0.5; numRow M / blockSize; numCol N / blockSize; blocks mat2cell(orig, blockSize*ones(1,numRow), blockSize*ones(1,numCol)); measCells cell(numRow, numCol); PhiCells cell(numRow, numCol); n blockSize^2; m round(n * measureRate); for i 1:numRow for j 1:numCol block blocks{i,j}; coef dct2(block); % DCT稀疏化 coefVec coef(:); phi randn(m, n); % 高斯测量矩阵 phi phi * diag(1 ./ sqrt(sum(phi.^2, 2))); % 行归一化 PhiCells{i,j} phi; meas phi * coefVec; % 压缩观测 measCells{i,j} reshape(meas, m/blockSize*blockSize, blockSize); end end measureImage cell2mat(measCells); % 拼接测量值 [rm, rn] size(measureImage); % 双随机相位编码 rng(2024); phase1 exp(2i * pi * rand(rm, rn)); phase2 exp(2i * pi * rand(rm, rn)); tmp measureImage .* phase1; freq fft2(tmp); cipher ifft2(freq .* phase2); save(keys.mat, phase1, phase2, PhiCells, measureRate, blockSize);有几个细节说明一下。m 除以 blockSize 再乘 blockSize 这个写法是为了当测量率不是整数时保证每个测量块能 reshape 成二维矩阵。如果测量率是 0.5每块测量值就是 32×64。所有测量值块拼接后measureImage 的尺寸变成了 128×256比原图小了一半这就是压缩效果。加密端生成的 cipher 是复数矩阵。MATLAB 的 imwrite 不支持直接保存复数所以我在仿真时通常会把它拆成实部和虚部两个通道保存或者直接保存成 .mat 文件后面解密直接 load。4.2 从密文到明文解密端代码解密端核心有两步先逆 DRPE再做分块压缩感知重构。% 解密端 load(keys.mat); % 逆DRPE注意运算顺序 freq_rec fft2(cipher) .* conj(phase2); tmp_rec ifft2(freq_rec); measureRecover real(tmp_rec .* conj(phase1)); % 虚部残差可忽略 % 把恢复的测量值矩阵按原来的分块方式切回去 blockMeasRow size(measCells{1,1}, 1); blockMeasCol size(measCells{1,1}, 2); measBlocks mat2cell(measureRecover, ... blockMeasRow*ones(1,numRow), blockMeasCol*ones(1,numCol)); recBlocks cell(numRow, numCol); for i 1:numRow for j 1:numCol y measBlocks{i,j}(:); phi PhiCells{i,j}; s_hat OMP(phi, y, 30); % OMP重构稀疏系数 recBlocks{i,j} idct2(reshape(s_hat, blockSize, blockSize)); end end recovered cell2mat(recBlocks); PSNR_val psnr(recovered, orig);这里用到的 OMP 函数我写一个教学版本function s_hat OMP(Phi, y, maxIter) residual y; support []; n size(Phi, 2); s_hat zeros(n, 1); for iter 1:maxIter corr abs(Phi * residual); [~, pos] max(corr); if ismember(pos, support) continue; end support(end1) pos; Phi_s Phi(:, support); s_sub Phi_s \ y; residual y - Phi_s * s_sub; if norm(residual) 1e-6 break; end end s_hat(support) s_sub; % 注意最终s_hat维度是n×1 end这个 OMP 版本去掉了很多细枝末节主要目的是让你理解支撑集迭代、最小二乘更新、残差更新这三件事。真正跑正式实验时建议用成熟的 OMP 工具包或者用凸优化库做基追踪重构质量会更稳定。解密端最容易出的问题就是块尺寸不匹配。mat2cell 分裂时要求第二个参数和第三个参数之和刚好等于矩阵的行数和列数。我在写这段代码时特意用原始 measCells 里第一块的尺寸来生成切分向量就是为了避免这类错误。4.3 测量率与重构质量的实测关系为方便你看趋势我把同一张 Lena 256×256 图分别用不同测量率跑了一次块大小固定64稀疏基DCTOMP迭代次数30。结果如下测量率密文尺寸与原图比例解密PSNR/dB主观效果0.330%19.2明显块效应细节丢失0.440%21.8轮廓可辨纹理模糊0.550%25.6细节中等基本可读0.660%27.4主体清晰边缘轻微振铃0.7575%29.8接近原图肉眼难辨差异0.990%31.2质量很好但压缩收益很小需要说明这个表是我本地 MATLAB R2023b 环境下的结果随机矩阵每次生成都有差异你跑出来上下浮动一两分贝都正常。看趋势比看绝对值重要0.5 到 0.75 这一段是性价比最高的区间低于 0.4 就不要指望质量了高于 0.8 则压缩意义不大。加密端的信息熵在密文阶段基本都能达到7.99左右也就是接近理想随机噪声说明DRPE的随机相位调制确实把测量值的统计特性洗得很平。5. 实验评估与常见问题排查5.1 加密效果评价指标与实测方法判断一套图像加密方案好不好不能只看“能不能解出来”。我每次实验会固定算四个指标。第一个是信息熵。明文图像熵值往往在7左右密文熵值接近8说明像素分布均匀没有明显统计特征。第二个是相邻像素相关系数。正常明文图像的水平相邻像素相关性通常在0.95以上密文应该降到0.1以下甚至接近0。这个指标直观反映像素扩散是否彻底。第三个是NPCR和UACI也就是密钥敏感性测试。只改变相位板中的一个像素两张密文的NPCR要大于99%UACI在33%左右。我自己实测中单像素相位改动后的NPCR在99.6%上下说明方案对密钥变化非常敏感雪崩效应明显。第四个是鲁棒性测试。把密文加上高斯噪声或者裁剪掉一部分看解密图像还能不能辨别内容。压缩感知本身有重建容错能力测量率越高抗噪和抗裁剪能力越强。这也是这个方案比传统置乱加密强的地方传统方案密文一旦损坏解密出来就是整块噪声基本无法恢复。5.2 仿真中常见问题与避坑清单我来整理一份按频次排列的问题清单每一条都是我实际踩过或者帮别人调试时遇到过的。问题现象根本原因解决方法解密图像全是噪点相位板或测量矩阵和加密时不一致固定rng种子把所有密钥存到.mat文件恢复图像整体偏暗或偏亮fft2与ifft2没有成对使用或缩放系数错误检查加密和解密傅里叶变换层级保持对称图像有分块边界痕迹测量率太低或块太小增大测量率或改用64/128块大小重构速度非常慢整图直接CS未分块改用Block CS把块大小控制在32到128OMP不收敛迭代次数不够或稀疏度假设过高迭代次数从30起步观察残差变化密文无法用imwrite保存复值矩阵问题拆实部虚部保存或直接存.matDRPE解密后虚部残差偏大相位量化噪声或FFT截断误差取real后做一次中值滤波但不建议替代正确解码这里我要单独提醒一下前两个问题在校验代码时最容易被忽视。很多同学把加密端解密端放在同一个脚本里密钥变量还在工作区所以一直能跑通但只要关掉工作区重新跑解密马上就露馅。这类问题本质上不是算法问题是工程习惯问题。5.3 一点个人调试经验这套组合方案想跑通并不难真正花时间的是把 CS 和 DRPE 两个模块的参数调到互相舒服。按我的经验调参顺序比调参本身更重要先固定块大小和稀疏基扫描测量率画出PSNR和密文熵的曲线然后固定测量率调 OMP 迭代次数看残差收敛曲线。不要一上来就把所有参数同时改否则解密图像出问题的时候你根本分不清是 CS 恢复失败还是 DRPE 密钥错了。再分享一个小技巧调试时不要用真人照片先用 Lena 或 Checkerboard 这类结构简单的测试图方便肉眼判断块效应和边缘振铃。等整条链路稳定了再换自然图像效果会好很多。还有加密和解密代码拆成两个独立脚本非常重要每次运行之间只通过 keys.mat 传递密钥这样模拟的是真实传输场景而不是同一进程里的内存复用。
网站建设高端定制企业官网