压缩感知(Compressed Sensing, CS)

一、理论知识

1、问题背景

在传统信号处理理论中,奈奎斯特采样定理指出:

采样频率 ≥ 信号最高频率的 2 倍,才能无失真重建信号

必须获取完整、均匀的采样数据

2、压缩感知的核心目标

在观测数量远小于信号维度的条件下,准确恢复原始信号。

3、稀疏性假设

(1)稀疏性的定义

信号 x ∈{R}^N 在某一表示空间中是稀疏的,x只有稀疏度k个非零元素:∥x∥0=k≪N

(2)变换域稀疏性

一般信号 不必在原始空间稀疏,但可在某一变换基下稀疏表示:x = A^T s

A∈{R}^{N × N}:正交变换基(如 DCT、小波);s:稀疏系数向量

4、压缩感知采样模型

y = Φx , Φ ∈ {R}^{M × N} , M≪N

Φ:测量矩阵;y:压缩观测向量

5、压缩感知成立的关键条件

(1)条件一:信号稀疏或可稀疏表示

信号在某一正交基或过完备字典下具有稀疏结构。

(2)条件二:测量矩阵的非相关性

测量矩阵 Φ 与稀疏基 A 之间应尽可能不相关,常用选择包括:高斯随机矩阵、Bernoulli 随机矩阵

该条件在理论上通常由 Restricted Isometry Property 描述。

6、稀疏重建的优化模型

(1)理想模型(L0 最小化)

min⁡ x ∥x∥0 s.t. y=Φx

该问题是 NP-hard,不可直接求解。

(2)凸松弛模型(L1 最小化)

min⁡ x ∥x∥1 s.t. y=Φx

在满足稀疏性和测量条件时,有理论保证:L1 最优解等价于 L0 最优解

这是压缩感知理论的核心结果。

范式 计算方法 优化偏好 是否产生稀疏解 典型应用
L0 非零元素的个数 非零元素越少越好 是(最稀疏) 理想压缩感知模型、稀疏表示理论
L1 每个元素取绝对值并求和 用尽量少的非零系数表示信号 是(可计算) 压缩感知(BP / LASSO)、稀疏重建
L2 每个元素平方后求和再开方(或平方和) 整体能量小、解平滑稳定 最小二乘、岭回归、去噪、平滑重建

7、总结

  • 利用信号结构减少冗余采样

  • 本质是:欠定线性系统 + 稀疏先验 + L1 优化

题一

1、分析

(1)块级压缩感知

(2)把二维图像,变成一维信号

(3)x原始信号,y观测,ψ测量矩阵,y=Ψx;高斯随机矩阵和任何稀疏基都"不对齐"

A稀疏表示基,s系数

二维 DCT(Discrete Cosine Transform)离散余弦变换:

把一块图像,用一组"从平滑到剧烈变化"的余弦基函数来表示,变换域表示

(4)测量 + 稀疏基 合并成一个等效测量矩阵

2、MATLAB代码

Matlab 复制代码
%% 压缩感知 ------ Cameraman 图像块的随机测量
clear; clc; close all;

%% (1) 读取 cameraman 图像
img = im2double(imread('cameraman.tif'));   % 256×256
[H, W] = size(img);

block_size = 32;
num_blocks = (H / block_size) * (W / block_size);  % 64

%% (2) 将图像分解为 32×32 块,并 reshape 为列向量
n = block_size * block_size;   % 1024
X = zeros(n, num_blocks);      % 存储所有 xi

% 复杂度:整图 256^2 = 65536,分块 32^2 = 1024
% 整张结构复杂;分块纹理更简单,更稀疏

idx = 1;
for i = 1:block_size:H
    for j = 1:block_size:W
        block = img(i:i+block_size-1, j:j+block_size-1);
        xi = reshape(block, [], 1);   % 1024×1
        X(:, idx) = xi;
        idx = idx + 1;
    end
end

%% (3) 构造测量矩阵 ψ 和二维 DCT 变换矩阵 A
% 观测数m < 原始维度n
m = round(0.6 * n);   % 614

% ψ:m×n 高斯随机矩阵,均值 0,方差 1/m
psi = sqrt(1/m) * randn(m, n);

% A:n×n 二维 DCT 变换矩阵
D = dctmtx(block_size);      % 32×32 的 1D DCT
A = kron(D, D);              % Kronecker 积 → 1024×1024

%% (4) 计算 Φ = ψ A^T
% x = A^T s,A稀疏表示基,s稀疏系数
Phi = psi * A';

%% (5) 计算 yi = ψ xi
Y = psi * X;   % 每一列是一个 yi(m×64)

%% (6) 保存 yi, A, Φ
save('yi.mat', 'Y');
save('A.mat', 'A');
save('Phi.mat', 'Phi');

%% (7) 输出大小
disp('--- 矩阵大小 ---');
disp(['yi 的大小: ', mat2str(size(Y))]);
disp(['A 的大小:  ', mat2str(size(A))]);
disp(['Phi 的大小:', mat2str(size(Phi))]);

3、运行结果

bash 复制代码
yi 的大小: [614 64]
A 的大小:  [1024 1024]
Phi 的大小:[614 1024]

题二

1、分析

用最小二乘(带正则)的方法,在 DCT 域估计系数,再反变换得到图像

(2)最小二乘法计算系数

2、MATLAB代码

Matlab 复制代码
%% 第2题:最小二乘法重构,欠定线性系统的正则化解
clear; clc; close all;

%% (1) 读取数据
load('yi.mat');    % Y: m×64
load('A.mat');     % A: 1024×1024
load('Phi.mat');   % Phi: m×1024

[m, num_blocks] = size(Y);
n = size(A, 1);

block_size = 32;
lambda = 1e-5;

%% 预分配
X_rec_blocks = zeros(n, num_blocks);

%% 预计算公共项(加速)
I = eye(n);
PhiTPhi = Phi' * Phi;
PhiTY = Phi' * Y;

%% (2)(3) 对每个块做最小二乘 + 反变换
for i = 1:num_blocks
    yi = Y(:, i);

    % 最小二乘解(DCT 域)
    ci = (PhiTPhi + lambda * I) \ PhiTY(:, i);

    % 反 DCT 得到图像块,A^T DCT逆变换
    xi = A' * ci;

    X_rec_blocks(:, i) = xi;
end

%% (4)(5) reshape 并拼接图像
img_rec = zeros(256, 256);

idx = 1;
for i = 1:block_size:256
    for j = 1:block_size:256
        block = reshape(X_rec_blocks(:, idx), block_size, block_size);
        img_rec(i:i+block_size-1, j:j+block_size-1) = block;
        idx = idx + 1;
    end
end

%% (6) 输出重构图像
figure;
imshow(img_rec, []);
title('最小二乘法重构图像');

3、运行结果

题三

1、分析

OMP(Orthogonal Matching Pursuit)贪婪算法,每一步选择一个"当前最相关"的基向量,

并在已选子空间上做最小二乘修正。

用 OMP 算法在 Φ 的列中逐步选出 K 个"最相关原子"

(1)r残差,Φn当前选中的"原子集合",ci稀疏系数

(2)内积为相似度,和当前残差最像的基向量

(3)更新支持集

(4)所有已选列的子空间中,做一次最小二乘,当前残差与已选子空间正交

(5)更新残差,把已解释的部分"减掉"

(6)K为稀疏度,人为限定,对 L0 的近似控制

(7)填充完整的稀疏系数

(8)反DCT

(9)拼接

2、MATLAB代码

Matlab 复制代码
%% 第3题:OMP 算法重构
clear; clc; close all;

%% (1) 读取数据
load('yi.mat');     % Y: m × 64
load('A.mat');      % A: 1024 × 1024
load('Phi.mat');    % Phi: m × 1024

[m, num_blocks] = size(Y);
n = size(A, 1);

block_size = 32;
K = 50;             % 稀疏度(迭代次数)

%% 预分配
X_rec_blocks = zeros(n, num_blocks);

%% 对每一个图像块做 OMP
for blk = 1:num_blocks

    %% -------- 第 (1) 步:初始化 --------
    yi = Y(:, blk);
    r = yi;                     % 残差
    index_set = [];             % 已选列索引
    Phi_selected = [];          % Φn
    c_selected = [];            % 已选系数

    %% -------- 第 (2)--(6) 步:OMP 迭代 --------
    for k = 1:K

        % (2) 计算所有列与残差的内积
        correlations = Phi' * r;

        % 找到绝对值最大的列
        [~, q] = max(abs(correlations));

        % (3) 更新支持集
        index_set = [index_set, q];
        Phi_selected = [Phi_selected, Phi(:, q)];

        % (4) 正交最小二乘求系数
        c_selected = (Phi_selected' * Phi_selected) \ ...
                     (Phi_selected' * yi);

        % (5) 更新残差
        r = yi - Phi_selected * c_selected;
    end

    %% -------- 第 (7) 步:构造完整稀疏系数 ci --------
    ci = zeros(n, 1);
    ci(index_set) = c_selected;

    %% -------- 第 (8) 步:反 DCT --------
    xi = A' * ci;

    X_rec_blocks(:, blk) = xi;
end

%% -------- 第 (9) 步:拼接图像 --------
img_rec = zeros(256, 256);
idx = 1;

for i = 1:block_size:256
    for j = 1:block_size:256
        block = reshape(X_rec_blocks(:, idx), block_size, block_size);
        img_rec(i:i+block_size-1, j:j+block_size-1) = block;
        idx = idx + 1;
    end
end

%% 输出重构图像
figure;
imshow(img_rec, []);
title('OMP 重构图像');

3、运行结果

题四

1、分析:迭代阈值算法IT(Iterative Thresholding)

用梯度下降往正确方向走 + 每一步强制只有 K 个非零系数

(2)zt残差,ct稀疏系数,t迭代

(3)分析

(4)更新残差

LS:只考虑误差
OMP:一次选一个最好的方向("一个一个选")
IT:全局修正 + 强制稀疏("每次全部算完再砍掉小的")

2、MATLAB代码

Matlab 复制代码
clc; clear; close all;

%% 1. 读取数据
load yi.mat      % yi: m × 64
load Phi.mat     % Phi: m × n
load A.mat       % A: n × n

[m, num_blocks] = size(Y);
n = size(A, 1);

%% 2. IT 参数设置
K = 200;      % 保留最大 K 个系数
T = 30;       % 迭代次数

X_rec = zeros(256, 256);   % 重构图像
block_size = 32;
block_idx = 1;

%% 3. 逐块重建
for i = 1:8
    for j = 1:8

        % 当前块的观测
        y = Y(:, block_idx);

        % 初始化
        z = y;              % 残差
        c = zeros(n, 1);    % 稀疏系数
        t = 1;

        %% IT 主循环
        while t <= T
            % 梯度更新 + 阈值 
            c_temp = pinv(Phi) * z + c;
            c = hard_threshold(c_temp, K);

            % 更新残差
            z = y - Phi * c;
            t = t + 1;
        end

        % 反 DCT 变换
        x = A' * c;
        x_block = reshape(x, block_size, block_size);

        % 拼接图像
        X_rec((i-1)*32+1:i*32, (j-1)*32+1:j*32) = x_block;
        block_idx = block_idx + 1;
    end
end

%% 4. 显示结果
figure;
imshow(X_rec, []);
title('IT Algorithm Reconstructed Image');

%% --------- 硬阈值函数 ---------
function y = hard_threshold(x, K)
    % 保留绝对值最大的 K 个元素,其余置零
    [~, idx] = sort(abs(x), 'descend');
    y = zeros(size(x));
    y(idx(1:K)) = x(idx(1:K));
end

3、结果

题五

1、分析

多先验 + 交替投影 + 去噪约束 的改进型 IT 重建框架

测量一致
→ Wiener 去噪
→ 块级测量修正
→ 全图 DCT 稀疏
→ 再测量修正
→ 循环

(1)伪逆给出的,是"在所有解中,L2 范数最小的那个解",(2)等价于最小二乘解

在 L2 意义下,最快、最直接地减少测量误差

(3)在保持图像结构的同时,抑制由欠采样和伪逆引入的噪声,非线性去噪先验。

Wiener 滤波是一种在"最小均方误差(MMSE)意义下最优"的去噪滤波方法。

(4)经过Wienner或者DCT之后,通常不再满足ψXi = yi,ψ* 把残差拉回图像X的空间,测量一致性修正

(6)整图 DCT 变换(全局稀疏性)

(7)只保留最大的 2000 个系数,频域硬阈值,L0 先验

(8)逆 DCT

(9)测量一致性修正,同(4)

2、MATLAB代码

Matlab 复制代码
clc; clear; close all;

%% ========== 1. 读取数据 ==========
load yi.mat      % Y: m × 64
load psi.mat     % psi: m × 1024
load A.mat       % A: 1024 × 1024

img_gt = im2double(imread('cameraman.tif'));  % Ground truth
[H, W] = size(img_gt);

block_size = 32;
num_blocks = 64;
n = block_size^2;

psi_pinv = pinv(psi);   % ψ*

%% ========== 2. Step (2): 初始最小二乘重构 ==========
X_init = zeros(H, W);
idx = 1;

for i = 1:8
    for j = 1:8
        y = Y(:, idx);
        Xi = psi_pinv * y;   % 最小二乘
        Xi = reshape(Xi, block_size, block_size);

        X_init((i-1)*32+1:i*32, (j-1)*32+1:j*32) = Xi;
        idx = idx + 1;
    end
end

% PSNR
psnr_init = psnr(X_init, img_gt);

figure;
imshow(X_init, []);
title(['Initial Reconstruction, PSNR = ', num2str(psnr_init)]);

%% ========== 3. 改进 IT 迭代 ==========
X = X_init;
T = 10;          % 外层迭代次数
K = 2000;        % 全图 DCT 稀疏度

for t = 1:T
    %% (3) Wiener 去噪
    X = wiener2(X, [5 5]);

    %% (4) 块级测量一致性修正
    idx = 1;
    for i = 1:8
        for j = 1:8
            Xi = X((i-1)*32+1:i*32, (j-1)*32+1:j*32);
            xi = Xi(:);
            y = Y(:, idx);

            % 测量一致性修正
            xi = xi + psi_pinv * (y - psi * xi);

            % 回写
            X((i-1)*32+1:i*32, (j-1)*32+1:j*32) = reshape(xi, 32, 32);
            idx = idx + 1;
        end
    end

    %% (6) 全图 DCT 稀疏约束
    alpha = dct2(X);
    alpha = hard_threshold(alpha, K);
    X = idct2(alpha);

    %% (9) 再一次测量一致性修正
    idx = 1;
    for i = 1:8
        for j = 1:8
            Xi = X((i-1)*32+1:i*32, (j-1)*32+1:j*32);
            xi = Xi(:);
            y = Y(:, idx);

            xi = xi + psi_pinv * (y - psi * xi);

            X((i-1)*32+1:i*32, (j-1)*32+1:j*32) = reshape(xi, 32, 32);
            idx = idx + 1;
        end
    end
end

%% ========== 4. 输出最终结果 ==========
psnr_final = psnr(X, img_gt);

figure;
imshow(X, []);
title(['Final Reconstruction, PSNR = ', num2str(psnr_final)]);

%% --------- 硬阈值函数 ---------
function y = hard_threshold(x, K)
    % 保留绝对值最大的 K 个元素
    x_vec = x(:);
    [~, idx] = sort(abs(x_vec), 'descend');

    y_vec = zeros(size(x_vec));
    y_vec(idx(1:K)) = x_vec(idx(1:K));

    y = reshape(y_vec, size(x));
end

3、结果

相关推荐
im_AMBER2 小时前
Leetcode 101 对链表进行插入排序
数据结构·笔记·学习·算法·leetcode·排序算法
快手技术2 小时前
AAAI 2026|全面发力!快手斩获 3 篇 Oral,12 篇论文入选!
前端·后端·算法
颜酱2 小时前
前端算法必备:滑动窗口从入门到很熟练(最长/最短/计数三大类型)
前端·后端·算法
做科研的周师兄2 小时前
【MATLAB 实战】栅格数据 K-Means 聚类(分块处理版)—— 解决大数据内存溢出、运行卡顿问题
人工智能·算法·机器学习·matlab·kmeans·聚类
X在敲AI代码2 小时前
leetcodeD3
数据结构·算法
码农小韩2 小时前
基于Linux的C++学习——循环
linux·c语言·开发语言·c++·算法
CoderCodingNo2 小时前
【GESP】C++五级/四级练习(双指针/数学) luogu-P1147 连续自然数和
开发语言·c++·算法
颜酱2 小时前
前端算法必备:双指针从入门到很熟练(快慢指针+相向指针+滑动窗口)
前端·后端·算法
Wect3 小时前
LeetCode 274. H 指数:两种高效解法全解析
算法·typescript