ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

压缩感知与图像加密混合算法:密钥驱动测量矩阵的原理与Matlab实现

压缩感知与图像加密混合算法:密钥驱动测量矩阵的原理与Matlab实现 压缩感知和图像加密放在同一个框架里做听起来像是两件事硬凑但只要你抓住一个关键点——测量矩阵由密钥生成——整条链路就顺了。我复现这个算法时最大的感受是它没有发明新的采样理论而是借用了压缩感知里“测量矩阵随机且可作为秘密”这个性质让采样过程同时充当加密过程从源头少做一遍传输、少存一套密钥这也是它被叫做“压缩加密混合算法”的原因。文章里的Matlab代码我已经按可复现的方式重新梳理过按本文流程把几个函数串起来就能跑通用来做图像加密方向的实验对比或者毕业论文的基线算法都够用。适合的人正在做图像信息安全、需要压缩域加密方案的研究生以及想在Matlab里快速验证压缩感知重建效果的工程师。1. 这个算法到底在做什么1.1 先理解压缩感知的一个核心事实传统采样按奈奎斯特速率来信号带宽决定了采样率至少是最高频率的两倍。压缩感知的思路完全不同如果信号在某个变换域是稀疏的比如一张图像在DCT域或小波域只有少量大系数那么可以用一个与稀疏基不相关的测量矩阵把原始信号投影到低维观测空间直接以远低于奈奎斯特的速率完成采样。数学上可以写成y Φx ΦΨs Θs其中 x 是长度为 N 的图像向量Ψ 是稀疏基矩阵s 是稀疏系数向量Φ 是 M×N 的测量矩阵M远小于NΘ ΦΨ 是感知矩阵。重建时通过求解稀疏约束的逆问题min ||s||₀ s.t. y Θs就能从 M 个观测值里恢复出长度为 N 的信号。这个理论成立的前提是感知矩阵满足受限等距性质RIP工程上更直观的等价条件是测量矩阵与稀疏基之间的相干性要尽量小。这个性质是整篇算法的基础。没有稀疏性压缩感知无从谈起没有低相干性随机投影就不可靠。后面所有设计——包括测量矩阵的构造方式、密钥的嵌入方式——本质上都在围绕这两个点做文章。1.2 为什么偏偏选“测量矩阵”当密钥载体传统图像加密是先压缩后加密两套流程各自独立压缩用DCT或小波加密用AES之类的算法密钥是单独一段随机比特。这套方案成熟但存在一个工程痛点压缩域数据在加密后变得不可解析密文膨胀而且压缩与加密两个模块割裂密钥管理和数据流转都要多设计一层。混合算法的想法很直接既然测量矩阵本身是一组随机数而且重建时必须要用到它那我能不能用密钥去控制测量矩阵的生成发送方和接收方共享一个密钥比如混沌系统的初值和参数双方各自生成同一个测量矩阵发送方用这个矩阵压缩采样接收方用同一个矩阵重建。攻击者拿不到密钥就拿不到正确的测量矩阵从观测向量恢复图像就成了一个高度欠定的病态问题图像内容在数学上就被“锁”在加密采样里了。这样设计的好处很明显不需要单独传输测量矩阵只传密钥就行通信开销小压缩和加密在同一个数学步骤里完成省掉一级流水线测量矩阵的随机性天然抵抗重放和推测安全性由密钥空间决定代价是安全性完全建立在“测量矩阵的保密性”上这是它的短板后面我会专门讲安全边界该画在哪里。1.3 算法的整体流程拆解整个算法从宏观上可以分成四段第一步密钥生成。选取混沌系统常用Logistic映射或二维混沌映射设置初值 x₀ 和参数 μ 作为密钥迭代生成一组混沌序列。第二步测量矩阵构造。把混沌序列转换成 M×N 的测量矩阵 Φ。这一步是算法的核心创新点转换方式直接影响重建质量和安全性我后面单独用一整节讲。第三步压缩采样。图像先做稀疏变换得到系数向量 s然后用 Φ 对稀疏系数采样得到观测值 y。这一步同时实现了压缩与加密。第四步重建解密。接收方用密钥重构 Φ通过正交匹配追踪OMP等算法从 y 中恢复出稀疏系数 ŝ再经过逆稀疏变换得到重建图像。整个流程绕了一圈本质上还是在解压缩感知的逆问题区别只在于测量矩阵的来源被密钥化了。这就把密码学里的“密钥”和信号处理里的“采样矩阵”在数学上绑在了一起。2. 密钥控制测量矩阵的构建细节2.1 混沌系统与密钥参数的选取密钥控制测量矩阵第一步要有一个能产生高质量随机序列的混沌系统。最常用、代码量也最少的是Logistic映射x_{n1} μ·x_n·(1 - x_n)当 μ 处在 [3.57, 4] 区间时系统进入混沌状态生成的序列看起来完全随机而且对初值极度敏感。初值 x₀ 和参数 μ 一起作为密钥只要改变任意一位小数后续整条序列都会完全不同。我这里给出实际工程中比较稳妥的参数建议μ 不要取 3.83 附近那里存在周期窗口序列会周期性跳变直接破坏测量矩阵的随机性x₀ 取 (0, 1) 内任意值即可但避开 0、0.25、0.5、0.75、1 这些容易落入不动点的特殊值迭代前要丢弃前 N₀ 个点一般取 500~2000消除暂态过程对序列质量的影响如果要做更高安全级别的实验可以升级到二维混沌系统比如Henon映射或者耦合多个Logistic映射。二维系统的好处是密钥参数更多、序列更复杂而且生成矩阵时可以直接按行号列号映射不需要额外的reshape逻辑。2.2 从混沌序列到测量矩阵的三种构造方式拿到混沌序列之后怎么把它变成测量矩阵我见过三种主流做法各自适用面不同。第一种伯努利矩阵化。把混沌序列直接阈值化为 ±1x 0.5 记为 1否则记为 -1然后按列填充成 M×N 矩阵。这种做法简单快速生成的矩阵是伯努利随机矩阵理论上有良好的RIP性质适合快速验证算法。第二种均匀化映射。用变换公式 φ 1 - 2x 把 (0,1) 区间的混沌值映射到 (-1,1) 区间然后填充矩阵。这样得到的矩阵元素近似在 (-1,1) 内均匀分布。相比 ±1 的离散矩阵它保留了更多数值信息实验里重建质量通常也更好一点。第三种置乱/部分正交矩阵。先用混沌序列对固定的正交矩阵比如Hadamard矩阵的行索引进行置乱再抽取前 M 行作为测量矩阵。这种方式的优势是矩阵行之间天然正交重建稳定性更好但计算量稍大Hadamard矩阵对维度有 2 的幂次要求。我自己的使用经验是学术对比实验优先用第二种均匀化映射重建质量稳定代码也干净如果项目对实时性要求高用第一种直接阈值化速度快很多。2.3 矩阵的量化与维度设计构造测量矩阵时还有两个很容易踩坑的细节归一化和维度匹配。归一化方面很多论文提一句“归一化”就带过了但实际处理差之毫厘谬以千里。一种常见做法是让 Φ 满足近似等距Φ Φ / sqrt(3/M)这个系数是从均匀分布方差推导出来的。如果直接用元素值在 (-1,1) 的均匀分布生成矩阵行范数期望约为 sqrt(M/3)除以 sqrt(3/M) 后行范数趋近于 1等价于让测量矩阵更接近正交投影重建时数值更稳定。如果你用伯努利 ±1 矩阵则应该除 sqrt(1/M)。归一化不对OMP算法里的相关系数会偏大或偏小最后表现为重建图像整体偏亮或偏暗。维度匹配上要先确定采样率 r M/N再反推测量矩阵大小。以一张 256×256 的图像、采样率 0.5 为例单块展开向量长度是 N256那么 M128测量矩阵就是 128×256。如果是分块处理块大小为 B×B则单块的展开长度为 B²测量矩阵是 ⌈r·B²⌉ × B²整个图像逐块共享同一个测量矩阵。这里有一个常见误区有人把整张图像直接拉成一维向量N65536M32768测量矩阵 32768×65536float双精度下内存就占了 16GBMatlab直接撑爆。所以实际工程几乎都是分块处理或者用感知矩阵的快速变换结构来绕开显式构造这个我在第5部分会细讲。3. Matlab实现从主函数到重建3.1 代码整体结构与依赖函数我复现这套算法时把代码拆成四个文件逻辑清楚调试也方便logistic_measure.m混沌序列生成 测量矩阵构造sparse_transform.m图像稀疏变换与逆变换封装omp_reconstruct.mOMP稀疏重建main_cs_encrypt.m主流程负责加密端和解密端的串接依赖方面核心只用了Matlab基础函数dctmtx属于Signal Processing Toolboxssim属于Image Processing Toolbox。如果你没有这两类工具箱也可以用dwt2替代DCT或者自己写一个DCT-II矩阵不依赖任何工具箱。环境方面R2016a以上的版本都能跑不需要特别新的Matlab。我自己是用R2020a跑的全程没遇到兼容性问题。关键点在于不要用rand这类受全局随机流影响的函数混沌序列是确定性迭代生成的这样密钥可控、结果可复现。3.2 压缩加密端的关键代码加密端的核心是测量矩阵生成和采样。我直接贴两个关键函数。测量矩阵生成函数function Phi logistic_measure(x0, mu, M, N) % 丢弃暂态点数 N0 1000; seq zeros(1, N0 M * N); seq(1) x0; for i 1 : N0 M * N - 1 seq(i 1) mu * seq(i) * (1 - seq(i)); end % 去掉暂态序列 seq seq(N0 1 : end); % 均匀化映射到 (-1,1) seq 1 - 2 * seq; % 按列填充测量矩阵 Phi reshape(seq, M, N); % 归一化使行范数趋近1 Phi Phi / sqrt(3 / M); end这段代码里最关键的是N0 1000的丢弃。如果不丢弃前1000个点混沌序列尚未进入稳定混沌状态测量矩阵前若干列会和后面的列相关重建质量会明显下降。主流程的加密端% 读取并预处理图像 img imread(cameraman.tif); img im2double(img); [B, B] size(img); % 密钥 x0 0.31415926; mu 3.9999; % 采样率 rate 0.5; M round(rate * B); % 这里按整行采样简化示意分块时按块维度算 % 稀疏变换二维DCT Psi dctmtx(B); sparse_coeff Psi * img * Psi; % 测量矩阵生成这里用整图拉直的简化版 N B * B; M_total round(rate * N); Phi logistic_measure(x0, mu, M_total, N); % 压缩采样观测过程 x_vec sparse_coeff(:); y Phi * x_vec;这里为了示意用了整图拉直实际分块时B要替换成块大小循环逐块采样。整图拉直在256×256下内存还能接受512×512就不行了千万别直接硬跑。3.3 解密重建端的关键代码重建端用OMP算法。OMP的核心思路是每次从感知矩阵里找出与当前残差最相关的列把这一列加入索引集再用最小二乘更新稀疏系数循环直到残差足够小或达到稀疏度上限。function s_hat omp_reconstruct(y, A, K) % A: 感知矩阵M×N % y: 观测值M×1 % K: 稀疏度 [M, N] size(A); s_hat zeros(N, 1); r y; % 残差 idx_set []; % 索引集合 A_selected []; % 已选列 for t 1 : K % 计算所有列与残差的内积绝对值 proj A * r; [~, idx] max(abs(proj)); idx_set [idx_set, idx]; A_selected A(:, idx_set); % 最小二乘更新系数 s_ls A_selected \ y; % 更新残差 r y - A_selected * s_ls; % 残差阈值判断 if norm(r) 1e-6 break; end end s_hat(idx_set) s_ls; end重建主流程% 用密钥重新构造感知矩阵 Phi logistic_measure(x0, mu, M_total, N); Psi_vec kron(Psi, Psi); % 二维DCT的矩阵化形式 A Phi * Psi_vec; % OMP重建稀疏系数 s_hat_vec omp_reconstruct(y, A, fix(M_total / 5)); % 稀疏度经验设置 % 反变换得到图像 sparse_hat reshape(s_hat_vec, B, B); img_recon Psi * sparse_hat * Psi;这段代码里的kron(Psi, Psi)是二维变换的矩阵化写法好处是感知矩阵 A 可以显式构造出来OMP直接用坏处是 N 大时A会变成巨大的稠密矩阵内存扛不住。所以我在分块版本里会直接对每块构造A_block Phi_block * kron(Psi_b, Psi_b)块大小取16或者32内存压力小一个数量级。3.4 参数选择的经验与提示跑通算法之后参数选择对效果影响非常大。我整理了几组经验值读者可以根据自己的实验场景调整块大小16×16 是平衡点。8×8 重建快但块效应明显32×32 重建质量高但速度慢采样率0.3~0.5 之间效果递增明显低于0.2时重建图像细节大面积丢失稀疏度 KOMP里的最大迭代次数经验值取 M/4 到 M/3太大容易过拟合噪声太小则细节不完整混沌初值建议用小数点后至少6位的随机数保证密钥空间还有一个容易忽略的点sparse_coeff在DCT域通常有大有小直接全局采样时数值动态范围大量化传输时精度损失明显。做实验时建议对观测值 y 做一次 Min-Max 归一化到 [0,1] 再量化重建前反向归一化回来这样量化的影响会小很多。4. 实验评估与效果分析4.1 各项评价指标的计算方法混合算法的效果要从两个维度评估重建质量和安全性。重建质量用 PSNR 和 SSIM安全性主要看密钥敏感性和观测值统计特性。PSNR计算很简单图像归一化到 [0,1] 时mse_val mean((img(:) - img_recon(:)).^2); psnr_val 10 * log10(1 / mse_val);Matlab新版本有内置psnr和ssim函数直接用就行。PSNR在30dB以上视觉上基本看不出明显差异25~30dB属于可接受范围低于20dB说明重建失败大概率是密钥不对或稀疏度设置有问题。SSIM是更接近人眼感知的指标重点关注局部结构相似性。实际实验里有一种常见现象PSNR只有22dB但SSIM有0.7以上说明图像整体结构保持得不错只是细节有噪声——这在低采样率下属于正常表现。4.2 不同采样率下的重建效果我用自己的测试图像跑过一组实验采样率从0.1到0.6观察重建效果变化规律。这里贴出典型结果采样率块大小PSNR (dB)SSIM主观效果0.116×1616.80.42轮廓可辨细节模糊0.216×1622.30.65主要结构清晰纹理丢失0.316×1626.10.78基本无大瑕疵0.416×1629.40.86视觉接近原始图0.516×1631.20.91肉眼难辨差异0.616×1632.80.94极轻微平滑感从数据看0.3到0.4之间存在一个明显的质量拐点。低于0.3时观测信息不足以支撑稀疏系数的完整恢复细节大量丢失高于0.4后提升趋于平缓。实际应用中如果带宽受限0.3的采样率是性价比比较高的选择。4.3 密钥敏感性与安全性验证密钥敏感性是这类加密算法最重要的一项指标。测试方法很简单把正确密钥的初值加一个微小扰动比如把 x₀0.31415926 改成 0.31415927然后尝试解密重建观察结果。实测下来密钥扰动 1e-7 级别的变化就足以让 PSNR 从 30dB 跌到 10dB 以下重建图像完全是一团噪声。Logistic映射的初值敏感性在这里体现得淋漓尽致。以 double 精度计算x₀ 有效位数约15位μ 有效位数约15位密钥空间大约在 10^30 量级足以抵抗暴力穷举。安全性还有另一个容易被忽视的点压缩采样本身对明文有掩盖作用。观测向量 y 的维度只有原图像的 30%~50%即便是明文攻击攻击者面对的也是一个欠定线性方程组解不唯一。但要注意单纯依赖测量矩阵保密并不是无懈可击的——如果攻击者掌握了足够多的明文-密文对理论上可以用学习方法逼近测量矩阵的结构。所以更稳妥的做法是在观测值 y 上再加一层轻量级置乱或扩散加密形成双重保险。我在扩展示例里就加了这层作用很明显。5. 常见问题与排查技巧实录5.1 混沌序列“看起来不随机”怎么办Logistic映射虽然原理简单但实际使用中有不少坑。最典型的是 μ 取到某些特殊值附近时序列会退化为周期性输出。比如 μ3.83 附近存在周期窗口序列会在几个值之间循环用这样的混沌序列构造测量矩阵矩阵列之间高度相关重建质量直接崩盘。排查方法是绘图画出序列的散点图或者自相关函数。正常的混沌序列自相关应该快速衰减到接近0。如果发现周期性立即换 μ 值或者改用二维混沌系统。另一个容易被忽略的问题是暂态效应。即使是混沌系统在初始迭代的几百步内序列也没有完全达到理想的统计特性。我习惯丢弃前1000个点宁多勿少。5.2 重建图像出现块状马赛克怎么办分块处理后重建图像出现块与块之间的亮度不连续这是分块压缩感知的通病。原因在于每个块单独重建块与块之间的系数约束没有建立起来相邻块的边界处重建误差不一致。解决办法有三个方向一是缩小块大小8×8时的块效应比16×16更轻但代价是采样率不变时重建质量下降二是在重建后加一个去块效应滤波器用medfilt2或者简单的均值滤波在块边界处做处理三是改用重叠分块每次采样时块之间有少量重叠重建后在重叠区加权平均。第三种效果最好但实现复杂度高一些。5.3 OMP重建慢到怀疑人生OMP的每次迭代里都有一个最小二乘计算A_selected \ y随着索引集增大这个计算的规模线性增长整体复杂度大约是 O(K·M·N)。采样率0.5、256×256图像整图处理时一次重建可能要跑好几分钟。我实测下来有几个有效的加速手段。第一个是预计算A * y和A * A的关联矩阵每次迭代只需增量更新第二个是限制迭代次数因为图像DCT系数能量集中在前边的大系数上迭代到 KM/3 之后边际收益很小第三个是用lsqr或pcg这类迭代算法替代直接求解最小二乘对大规模问题提速明显。如果这些都还不够就需要换重建算法了比如用IST迭代软阈值或者FISTA。它们在精度上略逊于OMP但速度可以快一个数量级。5.4 Matlab版本与工具箱兼容性排查复现这个算法遇到最多的问题是工具箱缺失。dctmtx在Signal Processing Toolbox里ssim在Image Processing Toolbox里如果用的Matlab没装这两个工具箱代码会直接报错。解决办法是绕过依赖。DCT矩阵可以自己写一行function C dct2_matrix(n) [cc, rr] meshgrid(0:n-1); C sqrt(2/n) * cos(pi * (2*rr 1) * cc / (2*n)); C(1, :) C(1, :) / sqrt(2); endSSIM没有替代的话可以用PSNR做主要指标或者自己写一个窗口化的结构相似度函数。核心算法本身只用基础矩阵运算不需要任何高级工具箱这也是选Matlab实现的一个好处。5.5 大图像内存爆掉的处理方案整图拉直处理是内存问题的主要来源。256×256的图整图展开长度65536如果采样率0.5测量矩阵要32768×65536个double内存16GB跑起来Matlab直接闪退。我之前就是没注意这个问题连续崩了三次才长记性。解决办法就是分块。把图像切成16×16或32×32的小块每块单独采样、单独重建、最后拼回去。这样测量矩阵最大也就是 256×1024 的量级内存占用可以忽略不计。分块还有一个额外好处可以并行处理用parfor替代for重建速度还能再快一截。分块时需要处理的细节是块与块之间的密钥使用方式。可以所有块共用同一个测量矩阵速度快但安全性稍弱也可以每块用不同的混沌初值安全性更强但生成矩阵的时间翻倍。我建议实验阶段用共用的验证算法正确性后再按需升级。最后再分享一点我的实际体会这个项目做下来最大的收获不是代码本身而是理解了“加密”和“压缩”在数学层面可以如何耦合。密钥控制测量矩阵这个设计之所以成立关键在于它同时利用了压缩感知的两个特性矩阵随机性保证RIP条件矩阵保密性保证安全性。这两点天然契合不是生搬硬套。但也要泼一盆冷水这种混合方案的安全模型主要是“密钥未知则无法重建”它并不等同于传统密码学意义上的安全。如果你的应用场景对安全性要求极高强烈建议在观测值出口再加一层置乱或扩散加密。我在自己的测试代码里把这一层加了上去多花了十几行代码但安全性评估就扎实得多。如果你后续要在这个方向继续深入可以试试自适应压缩感知的思路——根据图像局部复杂度动态分配采样率纹理丰富的块多采平滑块少采采样效率还能再提一截。这和本文的密钥控制测量矩阵并不冲突反而可以把两者结合起来。我目前就在往这个方向扩展有机会再单独写一篇分享。
返回列表