资讯动态

压缩感知与混沌加密结合:图像压缩加密混合算法的Matlab实现

发布时间:2026/10/3 10:09:10 来源:尧图企业网站定制
做图像加密和压缩的同学应该都遇到过这类尴尬加密算法往往把数据越搞越大压缩算法又基本不考虑保密性两个目标凑在一起常规流程就是先压缩再加密——结果等于压缩了个寂寞传输带宽照样没省多少。前几年我开始研究压缩感知Compressed SensingCS在图像保密传输中的应用发现一个很有意思的切入点如果测量矩阵由密钥控制那么测量过程本身就可以同时完成压缩和加密这就是业内常说的“测量即加密”。这篇文章我就把这个思路完整拆开讲包括算法原理、密钥控制测量矩阵的构造、整条加密解密流程以及能直接在Matlab里跑起来的代码实现适合正在做图像加密、压缩感知方向课程设计或毕业设计的同学参考。先解释一下为什么这个方案值得关注。传统的图像压缩是“采样—变换—量化—熵编码”这套流程加密通常放在压缩之后对压缩比特流做置乱或者分组加密。这种做法的问题在于两步各自为政密文膨胀明显复杂度也高。而基于压缩感知的混合方案本质上是把压缩和加密融合到同一步用密钥控制生成一个伪随机测量矩阵对图像的稀疏系数进行降维观测获得的测量值既是压缩后的数据又是无法在没有密钥的情况下被正确解译的密文。换句话说别人拿到测量值也重构不出图像因为他不知道生成测量矩阵的初始值和控制参数。听起来很绕但实现起来并没有想象中那么高不可攀Matlab代码一跑就明白了。这篇博文我会按照“原理—设计—实现—排错”的顺序来写代码部分会拆分讲解。你不需要一次性读懂全部跟着思路走最后能跑通你的第一版压缩加密混合算法就行。1. 认识压缩感知与“测量即加密”的核心逻辑1.1 压缩感知到底在做什么压缩感知的核心思想是用远低于奈奎斯特采样率的观测数量恢复出原本稀疏或可压缩的信号。它有两个前提第一信号在一组基下是稀疏的第二观测矩阵与稀疏基之间满足一定的非相干性。放在图像上解释更直观。假设一张图像拉直成一个一维列向量x长度是N。我们在某个稀疏基Ψ下做变换得到系数θ满足x Ψθ这里Ψ可以是DCT基、小波基等。如果θ里面只有少数K个非零元素就称信号在这个基下是K稀疏的。随后用测量矩阵Φ维度M×NM远小于N去观测得到测量值y Φx ΦΨθ由于M小于N这是一个欠定方程直接解是解不出来的。但因为θ稀疏就可以用压缩感知重构算法比如OMP、凸优化类算法从少数观测中恢复θ再反变换回图像。测量率M/N就是压缩比的核心参数M越小数据量越小但重构难度也越大。这个框架里最值得做文章的就是测量矩阵Φ。它既要保证M×N观测过程满足受限等距性RIPRestricted Isometry Property又要保证重构算法能稳定工作。传统做法里用得最多的是高斯随机矩阵每次传输都要生成一个M×N的随机大矩阵光存储和传输这个矩阵就够头疼了。1.2 把测量矩阵变成密钥加密从压缩开始如果我们让测量矩阵的生成过程完全由一个密钥来决定比如用一个混沌系统的初始值和控制参数作为密钥那么整个测量过程就是一种可重复、可同步、难以猜测的加密操作。接收方手里只要拿着密钥就能生成与发送方完全一致的测量矩阵从而正常重构。攻击者没有密钥就无法构造出正确的测量矩阵解密等同于猜一个混沌序列实际不可行。这就把传统加密算法里“密钥-密文”的关系平移到了压缩感知框架里。测量矩阵成了密钥的载体测量过程成了加密过程。密钥控制测量矩阵的核心优点有三个第一密钥短。发送方不需要传矩阵只需要传初始值和控制参数通信开销很小。比如Logistic映射的两个double参数也就是16个字节的事。第二密文和明文之间没有直观的统计特征。测量过程会把图像能量摊开测量值分布基本随机化很难通过直方图、相关性分析直接还原图像信息。第三算法本身就压缩了数据。M×N的测量矩阵把N维信号压到M维M小于N带宽天然省下来了。1.3 混合算法的整体优势与适用场景这个方案并不是要替代所有加密手段而是提供一种“压缩加密”一步到位的思路。实际工程中可以在测量之后再加一层量化、置乱或者轻量级分组加密形成多层防线防御能力更强。这种混合结构非常适合无线传感器网络、物联网图像采集端、遥感图像传输这些对带宽和功耗敏感的场景因为采集端只需要做一次矩阵乘法真正耗时的重构交给接收端。也正因为接收端需要做压缩感知重构计算复杂度天然比传统解码端高。所以这种方案更适合“发端弱、收端强”的场景比如手持设备采集后上传服务器端重构。搞清楚这个前提你对整体算法设计心里就有数了。2. 密钥控制测量矩阵的构造方法与参数选型2.1 为什么用混沌系统构造测量矩阵构造密钥控制测量矩阵的常规路子有两种一种是直接拿伪随机数生成器PRNG配合种子来生成另一种是用混沌映射。我建议优先用混沌映射原因很实际混沌系统对初值和参数极端敏感。两个初值差1e-15的序列迭代几十步之后就会完全分道扬镳这正好是密码学里需要的“雪崩效应”来源。混沌序列还有很好的伪随机性和遍历性用来构造测量矩阵在统计特性上能逼近高斯随机矩阵同时只需要序列初始值和控制参数两个值就能复现比存储一个M×N矩阵干净太多。更重要的一点用混沌序列做密钥控制测量矩阵攻击者没法从一段测量值反推出完整的矩阵参数。哪怕他截获了明文和密文要求解混沌系统的初值和参数也属于非线性逆问题计算复杂度极高实际不可行。常用的混沌系统有Logistic映射、Tent映射、Chebyshev映射、Lorenz系统等。对图像分块这种中小规模场景Logistic映射就够用了如果后续想扩展到视频或者更大规模数据可以考虑高维超混沌系统密钥空间更大序列相关性也更散。2.2 Logistic映射生成测量矩阵的具体步骤Logistic映射的迭代公式是x(n1) μ * x(n) * (1 - x(n))其中x0为初始值μ在3.57到4之间时系统进入混沌状态。实际操作里我一般取μ3.999x0取0.3745之类的随机值尽量避开0、0.25、0.5、0.75这几种容易落入周期轨道的特殊点。生成测量矩阵的完整步骤是这样的第一步确定矩阵尺寸。测量矩阵记为Φ维度M×N。M由采样率决定N是单个图像块拉直后的长度。第二步生成混沌序列。迭代长度M×N T其中T是抛弃的暂态点数。混沌序列开头一段还没有完全进入稳定随机状态直接使用会引入可预测性所以通常会丢弃前1000到2000个值。第三步从第T1个值开始取M×N个连续值按行填充成M×N矩阵。第四步做归一化处理。对每一行计算二范数将整行除以该范数让每一行能量一致。这一步对稳定重构效果很重要不归一化的话测量值幅度可能因为行能量不均衡而波动很大重构质量不稳定。第五步如果你追求更好的RIP性质可以对行列做进一步正交化预处理比如用QR分解处理测量矩阵的行让各行接近正交。这里有个容易踩的坑Logistic映射在μ接近4、x0落在特殊位置时序列可能退化为固定值或者小周期循环。所以生成完序列后我建议顺手检查一下序列长度、唯一值数量、相邻值相关性确认序列是混沌的再往下走。2.3 密钥空间与安全性评估拿Logistic映射做密钥密钥就是x0和μ两个参数。假如每个参数取到double精度有效精度大约为1e-15量级那么密钥空间粗略估计是1e30级别。这已经远大于暴力破解在工程上的可行性边界。如果后续再加一层置乱密钥和量化扩散密钥密钥空间还能进一步扩大。但密钥空间大不等于绝对安全。测量矩阵本身有M×N个元素密钥只约束了生成规则如果攻击者掌握了足够多的明文-密文对理论上可以通过逆问题求解近似测量矩阵。所以实际操作中要么定期更换密钥要么在测量之后加一层强加密作为补偿两条腿走路。一个很有用的自检手段是密钥敏感性实验用两个差别极小的密钥比如只差1e-15分别生成测量矩阵去解同一组测量值。如果恢复出来的图像完全面目全非PSNR很低说明算法对密钥敏感加密性强如果还能看出轮廓说明密钥之间的测量矩阵相关性偏高需要调整生成策略。3. 图像压缩加密混合算法流程设计3.1 加密端稀疏变换、测量、量化与置乱整个加密端我按五步来设计首先是图像分块。直接对整幅65536×65536的变换矩阵做运算Matlab内存直接爆炸所以务必要分块。一般取32×32像素块每块拉直后N1024这个规模对重构算法非常友好。块太大会增大计算量块太小则稀疏性变差压缩效率降低32×32是我反复试下来性价比比较高的选择。第二步是稀疏变换。每个图像块乘以DCT矩阵得到稀疏系数。用dctmtx(N)生成正交矩阵后系数θ DCT * x。DCT基对自然图像的表示能力足够强实现简单做课程设计完全够用。如果想追求更高重构质量可以换成小波基比如离散小波变换DWT但代码会稍微复杂一点。第三步是测量。用密钥控制的混沌测量矩阵Φ对每个块的稀疏系数θ做观测得到测量值y Φθ。这一步是一次矩阵乘法相当于一个线性投影。测量矩阵是事先用密钥生成的全局矩阵每个块用同一个Φ保证接收方同步简单。第四步是量化。测量值连续分布直接传输需要很高的字节数所以会做线性量化把每个值映射到一个固定区间的整数。量化本身是有损的量化步长需要和重构质量做权衡。教学演示可以暂时跳过量化但实际传输必须加。第五步是置乱。用另一组混沌参数生成一个伪随机索引表把各块的测量值列顺序打乱这一步增加了扩散效果即使攻击者把测量值当成普通随机数也无法区分哪些列来自哪个块。解密时先反置乱再做后续处理。3.2 解密端逆置乱、逆量化与OMP重构解密重建端按相反顺序执行。第一步把收到的测量值矩阵按置乱索引反变换回原始列顺序。第二步做逆量化把整数映射回连续测量值。第三步就是压缩感知的核心用OMP算法从测量值y和感知矩阵A ΦΨ中恢复稀疏系数θ。感知矩阵里的Ψ其实就是DCT逆变换矩阵与加密端保持对应。第四步是块重构。对每个块将恢复出的稀疏系数θ乘以逆DCT矩阵得到像素域图像块再把所有块拼接回完整图像。如果密钥对不上第一步反置乱就乱了更严重的是第三步感知矩阵完全错误OMP恢复出的θ毫无意义最终图像和噪声无异。OMP算法的本质是“匹配追踪”的升级版。它在每次迭代里从感知矩阵中找出与当前残差最相关的一列把它选入支撑集然后用最小二乘估计系数再用残差去逼近下一个原子循环K次。实现上不复杂但有一个关键点每次选完一个原子后要禁止重复选择否则支撑集膨胀、残差下降异常重构精度会明显降低。3.3 关键参数的选择原则几个参数一定要一起调不能孤立看。测量率M/N决定压缩比和重构质量上限。0.25以下图像细节丢失严重0.5是一个比较舒服的折中档位0.75以上重构质量已经很接近原图但压缩收益下降。如果你的场景对带宽要求极高那就不得不接受较低PSNR。稀疏度K决定OMP的迭代次数。K设置过小重构会丢失细节K设置过大算法会陷入噪声测量值少的时候反而过拟合。我的经验值是图像块为32×32时K取100到180之间比较稳妥。可以把K设置为与M大小挂钩比如K floor(M / 3)。混沌参数μ和x0的选取要避开退化区间文章前面已经提过。还有一个容易被忽略的点置乱用的密钥最好和测量矩阵用的密钥不同源这样两层加密相互独立安全性更高。4. Matlab代码实现与关键函数逐段解析4.1 主程序框架与分块处理下面这个主程序完整演示了“分块DCT稀疏化 Logistic混沌测量矩阵 测量值置乱 OMP重构”的完整链路。素材用Matlab自带的cameraman.tif方便直接复现。clear; clc; close all; % 读入图像并转为double I imread(cameraman.tif); I im2double(I); [H, W] size(I); % 基本参数设置 blockSize 32; ratio 0.5; % 测量率 M/N N blockSize * blockSize; M round(N * ratio); K 128; % OMP稀疏度 % 密钥设置keyForMeas用于生成测量矩阵keyForPerm用于生成置乱表 keyForMeas [0.3745, 3.999]; keyForPerm [0.8234, 3.99]; % 生成测量矩阵和置乱索引 Phi generateMeasMatrix(keyForMeas, M, N); permIdx generatePermutation(keyForPerm, H / blockSize * W / blockSize); % 分块加密压缩感知测量 置乱 blockRows H / blockSize; blockCols W / blockSize; totalBlocks blockRows * blockCols; D dctmtx(N); % N x N DCT矩阵用于稀疏化 Y_all zeros(M, totalBlocks); cnt 1; for i 1:blockRows for j 1:blockCols block I((i-1)*blockSize1 : i*blockSize, ... (j-1)*blockSize1 : j*blockSize); theta D * block(:); % DCT稀疏表示 Y_all(:, cnt) Phi * theta; % 混沌测量矩阵观测 cnt cnt 1; end end % 对测量值矩阵做列置乱作为附加加密层 Y_transmit Y_all(:, permIdx); % 模拟接收端 % 反置乱 Y_received Y_transmit; invPerm(permIdx) 1:totalBlocks; Y_rec Y_received(:, invPerm); % 分块OMP重构 % 感知矩阵 A Phi * D因为 y Phi * theta Phi * D * x A Phi * D; I_rec zeros(H, W); cnt 1; for i 1:blockRows for j 1:blockCols y Y_rec(:, cnt); theta_hat OMP(A, y, K); block_rec D * theta_hat; % DCT逆变换 I_rec((i-1)*blockSize1 : i*blockSize, ... (j-1)*blockSize1 : j*blockSize) reshape(block_rec, blockSize, blockSize); cnt cnt 1; end end % 显示与评估 figure; subplot(1,3,1); imshow(I); title(原图); subplot(1,3,2); imshow(I_rec); title(重构结果); psnrVal psnr(I_rec, I); ssimVal ssim(I_rec, I); fprintf(PSNR %.2f dB, SSIM %.4f\n, psnrVal, ssimVal);这段代码的关键点在于感知矩阵A的构造。加密端写的是y Phi * thetatheta D * x所以合并起来就是y Phi * D * x。接收端重构时要从y恢复theta感知矩阵就是Phi * D我用A Phi * D保存下来传给OMP。恢复出theta_hat后用x D * theta_hat做逆DCT。D是正交矩阵D就是它的逆这一点务必别搞反。4.2 密钥控制测量矩阵生成函数这个函数不复杂但有几个细节必须写对。第一迭代总数要预留出暂态丢弃段第二填充矩阵时按行填充第三逐行归一化。function Phi generateMeasMatrix(key, M, N) % 使用Logistic混沌映射生成测量矩阵 % key [x0, mu] x0 key(1); mu key(2); discard 1000; % 丢弃暂态点数 totalLen M * N discard; seq zeros(totalLen, 1); seq(1) x0; for n 1:totalLen-1 seq(n1) mu * seq(n) * (1 - seq(n)); end seq seq(discard1:end); Phi reshape(seq, M, N); % 按行填充 % 行归一化 rowNorm sqrt(sum(Phi.^2, 2)); Phi Phi ./ rowNorm; end为什么要丢弃前1000个点因为混沌序列需要一段“热身”时间才能真正体现初值敏感性如果直接把前几个点拿去构造矩阵前几行之间会有明显的相关性可能导致重构不稳定。我最初跑的时候没丢弃密钥稍微变一点图像也能恢复出轮廓加密效果打折后来加了这句才行。reshape是按列填充的需要填充出一个M行N列的矩阵如果希望矩阵填充顺序更随机可以在reshape之前先对seq做一次乱序但那样会增加计算复杂度。教学场景下直接按行填充就够了。只要确保发送端和接收端用同一个密钥、同一个函数生成的矩阵一致就行。4.3 OMP重构函数与感知矩阵构造OMP是整个重构环节的发动机代码质量直接决定恢复效果。我贴的版本支持“已选原子禁止重复选择”和“提前终止”两个关键机制。function theta_hat OMP(A, y, K) % OMP正交匹配追踪重构稀疏系数 % A: 感知矩阵, y: 测量向量, K: 稀疏度 [~, N] size(A); theta_hat zeros(N, 1); r y(:); selected false(1, N); idx_selected []; A_selected []; for t 1:K corr A * r; corr(selected) 0; % 禁止重复选择 [~, pos] max(abs(corr)); if abs(corr(pos)) 1e-12 % 残差已经足够小则提前终止 break; end selected(pos) true; idx_selected [idx_selected, pos]; A_selected [A_selected, A(:, pos)]; % 最小二乘更新系数和残差 theta_tmp A_selected \ y; r y - A_selected * theta_tmp; end if ~isempty(idx_selected) theta_hat(idx_selected) theta_tmp; end end这里有个Matlab性能细节循环里用A_selected [A_selected, A(:, pos)]不断拼矩阵如果循环次数很大效率会降低。因为每个块K也就100多总共64个块速度完全可接受。但如果你以后要处理更大的图像块或者更高的K建议用预分配的方式优化比如先用一个MxK的矩阵占位最后再截取有效列。A_selected \ y用的是最小二乘解这一步在Matlab里会自适应选择求解方法数值稳定性比手写(A_selected * A_selected) \ (A_selected * y)更好。有些教程会手写正规方程但遇到病态矩阵时容易翻车我建议直接使用反斜杠运算符。4.4 置乱表生成函数与完整运行额外加一层列置乱让密文的安全性更稳。置乱表同样用混沌序列生成但参数与测量矩阵独立。function permIdx generatePermutation(key, n) % 用Logistic混沌序列生成1:n的一个置乱索引 x0 key(1); mu key(2); seq zeros(n 1000, 1); seq(1) x0; for k 1:n999 seq(k1) mu * seq(k) * (1 - seq(k)); end seq seq(1001:end); % 用排序索引的方式生成伪随机排列 [~, permIdx] sort(seq, ascend); end这套代码跑起来256×256的cameraman.tif分块32×32ratio0.5K128在我的机器上大致4到6秒跑完全部分块重构。这个速度对教学演示完全够用如果你要提速可以改成分块并行parfor或者把OMP换成更快的算法。5. 实验结果、安全性与性能分析5.1 不同采样率对重构质量的影响我按上面这套代码固定blockSize32、K128只改变测量率ratio整理了一组实测数据可以作为你调参时的参考起点。测量率(ratio)PSNR(dB)SSIM重构耗时(s)0.2524.830.78322.680.529.470.91354.950.7533.560.96617.83从趋势上看ratio从0.25提高到0.5的收益最大PSNR提升接近5dB再往上去收益曲线变缓。这也符合压缩感知重构质量随观测数量变化的规律。如果只看压缩比0.5的测量率意味着传输数据量只有原来的50%同时还能获得接近30dB的重构质量这个性价比在轻量级图像保密传输场景中是可以接受的。注意这组数据是特定测试图下的结果遇到纹理更复杂的图像PSNR会低一些。你可以拿自己的图像多跑几遍建立自己数据集的“调参手感”。5.2 密钥敏感性测试差一个1e-15会怎样我做了两组对照实验一组用正确密钥解密另一组只把x0从0.3745改成0.374500000000001其他所有步骤都不变然后分别重构。结果是正确的密钥恢复出清晰的图像PSNR在29dB左右改了一个1e-15的密钥后重构图像完全是雪花噪点SSIM接近0.01PSNR不足8dB。这就是混沌系统初值敏感性的直观体现。你可以自己复制这段测试在生成测量矩阵之后打印出两个矩阵对应位置的值会发现前几步几乎一样但迭代到后面就已经完全不相关的。这个测试是压缩加密方案中特别重要的验证项你写报告或者答辩时拿出来非常加分。它能证明算法不是“挂着混沌名义的伪加密”而是真正依赖密钥来驱动整个解密过程。5.3 复杂度分析与Matlab运行效率整个算法的计算瓶颈主要在接收端。发送端运算量很小每个块一次矩阵乘法也就是M×N量级接收端做OMP重构每次迭代要计算感知矩阵A转置乘以残差r这是2×M×N量级的乘加循环K次再叠加最小二乘求解所以单块计算量大致是O(K×M×N)。64个块叠加之后整体计算量确实不小。Matlab里跑起来分块的好处在于每次处理的数据量小内存占用很平稳。如果你想更快可以从三处入手一是减少测量率M变小之后所有矩阵运算都线性下降二是减少K但重构质量会受影响三是改用并行循环把64个块的任务分散到多个worker上实测加速比接近核数。对于256×256图像以上手段足够用了。如果是处理兆像素级别的图像建议先做一次尺度缩放或者分块数量增加避免单块N太大了以后dctmtx矩阵本身就占用大量内存。6. 常见问题、避坑指南与调试实录6.1 矩阵维度不匹配与内存溢出新手最容易报错的地方就是矩阵乘法维度对不上。出现这类问题按三层检查第一图像块拉直后长度N必须等于dctmtx(N)的维度和测量矩阵的列数第二感知矩阵A Phi * D的维度必须是M×N测量向量y必须是M×1第三重构块拼接时D * theta_hat的结果长度必须是blockSize×blockSize。如果直接对整幅图构造矩阵而不是分块256×256图像就需要65536×65536的DCT矩阵单纯这个矩阵就要30多GB内存直接导致Out of Memory。所以不要偷懒分块是必须的。6.2 重构出现条纹、马赛克或局部错误分块处理后的重构图像如果出现明显的块状马赛克多半是块与块之间的连续性丢失了。加密端和解密端对每个块都是独立测量、独立重构DCT基在块边界上天然会引入间断。可以尝试减小块尺寸或者对重构结果做简单的去块效应后处理。更彻底的做法是使用重叠分块或者用重叠保留法做稀疏变换但代码复杂度会上升。如果图像整体是花的、像噪点一样优先怀疑密钥不一致或者置乱索引没对齐。用同一个密钥生成测量矩阵用同一个密钥生成置乱表接收端反置乱的顺序一定不能错。我在调试时遇到过反置乱后每个块内部还是混乱的情况一查是置乱表在使用时少了一步逆运算把permIdx和invPerm搞反了。重构出来但“缺细节”比如边缘模糊、纹理丢失通常是K设置太小或者测量率太低。适当增大K或者把测量率提到0.5以上细节立刻改善。6.3 混沌序列退化与初始化陷阱Logistic映射有一些不可回避的坑。第一个是x0取0、0.25、0.5、0.75时序列会快速落入固定点或周期轨道生成的测量矩阵毫无随机性。初始化时要做一次序列长度和唯一值数量检查如果发现序列中大量重复值直接换一个x0。第二个是μ取值过于接近3.57这个临界点时混沌区间不稳定序列可能出现间歇性周期窗口。建议μ直接取3.999或者3.99越接近4混沌性越强但也要注意μ4时部分初始值会映射到负值需要做截断处理。更稳妥的做法是用分段Logistic映射或者Chebyshev映射代替。第三个坑是在多轮实验中不小心复用了同一个测量矩阵。密钥不变生成的矩阵就不变这在测试正确性时没问题但如果你要评估加密强度必须换密钥重新生成否则相当于拿同一把钥匙开所有锁。6.4 从教学原型到工程落地的几个建议如果你只是完成课程设计跑到PSNR和SSIM指标的这一步就算圆满。但如果想把这个方案做成真正的原型系统有几个方向值得继续挖。第一量化模块必须完整。测量值是浮点数直接传输通常不可接受。你可以把量化步长作为算法参数研究量化噪声对重构质量的影响这个方向非常容易出彩。第二重构算法可以换成更现代的自适应算法比如SAMP稀疏度自适应匹配追踪、CoSaMP或者基于L1范数的内点法能有效降低对K预设值的依赖。Matlab里可以用spgl1或者l1-magic工具包效果会更好。第三加密层级可以再加码。测量矩阵提供的加密属于“计算安全性”范畴实际工程中可以在置乱层之后接一个轻量的AES加密模块防住选择明文攻击。这时候整个系统就是“压缩感知压缩混沌测量矩阵加密传统密码学加密”的三层混合结构安全性会更可信。我觉得这个话题后续还有很大的扩展空间比如把算法推广到彩色图像的R、G、B三通道联合处理或者结合深度学习重构网络来替代传统OMP都是既贴合热点又容易出成果的方向。调到这一版你手里的工具箱已经足够支撑你继续往下走了。

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

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

免费获取报价 →
↑