matlab自定义函数实现图像小波变换

matlab中提供了小波变换函数lwt和ilwt,可以方便地实现提升小波变换。

我们按照小波变换的定义,粗糙地实现一个针对图像的小波变换,如下:


% 使用方法:
img = imread('lena256.bmp');  % 假设lena.png是灰度图像
subplot(2,2,1),imshow(img,[]);title('原始图像');
[m,n]=size(img);
result = wavelet_transform(img);
subplot(2,2,2),imshow(result,[]);title('小波');
subplot(2,2,3),imshow(result(1:m/2,1:n/2),[]);title('小波LL');
image = inverse_wavelet_transform(result);
subplot(2,2,4),imshow(image,[]);title('粗糙复原');

function temp = wavelet_transform(image)
% 对输入图像进行一次5/3小波变换
% image: 输入的灰度图像
% LL, LH, HL, HH: 分解得到的四个子带图像
% 预处理 - 将图像转为double类型
image = double(image);

% 水平方向提升小波变换
[rows, cols] = size(image);
temp = zeros(size(image));  % 用于存储水平方向处理后的临时结果
for i = 1:rows
    [sL, dL] = lifting_scheme(image(i, :));
    temp(i, 1:end/2) = sL;  % 放在前面
    temp(i, end/2+1:end) = dL;  % 放在后面
end

% 垂直方向提升小波变换
for j = 1:cols
    [sL, dL] = lifting_scheme(temp(:, j)');
    temp(1:end/2,j) = sL;  %放前面
    temp(end/2+1:end,j) = dL;  %放后面
end

end

function [s, d] = lifting_scheme(x)
% 提升小波分解
% 输入序列 x 应为偶数长度
% 输出 s 为近似系数序列,d 为细节系数序列

% 分裂步骤
e = x(1:2:end);
o = x(2:2:end);

% 预测步骤
p = (e + [e(2:end), e(end)]) / 2;  % 使用边界延拓对最后一个元素进行处理
d = o - p;  % 计算细节系数

% 更新步骤
u = (d + [d(2:end), d(end)]) / 4;  % 类似地处理最后一个元素
s = e + u;  % 更新近似系数
end


function image = inverse_wavelet_transform(temp)
% 对输入的小波变换结果进行逆变换
% temp: 小波变换的结果
% image: 重建后的灰度图像

% 先进行垂直方向的逆变换
[rows, cols] = size(temp);
image = zeros(size(temp));  % 用于存储垂直方向处理后的临时结果
for j = 1:cols
    sL = temp(1:end/2, j)';
    dL = temp(end/2+1:end, j)';
    image(:, j) = inverse_lifting_scheme(sL, dL);
end

% 再进行水平方向的逆变换
for i = 1:rows
    sL = image(i, 1:end/2);
    dL = image(i, end/2+1:end);
    image(i, :) = inverse_lifting_scheme(sL, dL);
end

% 后处理 - 将图像转为uint8类型(如果需要)
image = uint8(image);

end

function x = inverse_lifting_scheme(s, d)
% 提升小波重建
% s: 近似系数序列
% d: 细节系数序列
% x: 重建后的序列

% 逆更新步骤
u = (d + [d(2:end), d(1)]) / 4;  % 注意这里首尾相接的方式不同于上面
e = s - u;

% 逆预测步骤
p = (e + [e(1), e(1:end-1)]) / 2;  % 同理,这里使用的也是不同的边界延拓方式
o = d + p;

% 合并步骤
x(1:2:length(e)*2) = e;
x(2:2:length(o)*2) = o;

end



%% 下面的代码进行图像本身的拓边,保证在预测、更新过程中能被除尽
% % 检查 e 和 o 的长度,确保它们匹配
% if length(e) > length(o)
%     % 如果 e 的长度比 o 长,则需要扩展 o
%     o(end+1) = 2 * o(end) - e(end); % 可以是其他边界扩展策略
% end

%% 下面的代码涉及到边界拓展模式,可以作为参考。

% function [s, d] = lifting_scheme(x)
%     % 提升小波分解
%     % 输入序列 x 应为偶数长度
%     % 输出 s 为近似系数序列,d 为细节系数序列
%
%     % 分裂步骤
%     e = x(1:2:end);
%     o = x(2:2:end);
%
%     % 预测步骤
%     p = zeros(1, length(o));
%     p(1) = e(1);  % 对于序列的首端,直接取值(或使用其他边界延拓策略)
%     p(2:end) = (e(1:end-1) + e(2:end)) / 2;  % 平均相邻的e值进行预测
%     d = o - floor(p);
%
%     % 更新步骤
%     u = zeros(1, length(e));
% %     u(1:end-1) = (d(1:end-1) + [d(2:end), 0]) / 4;  % 更新e值,除最后一个d外
%     u(1:end-1) = (d(1:end-1) + d(2:end)) / 4;  % 更新e值,除最后一个d外
%     u(end) = (d(end) + d(end-1)) / 4;  % 最后一个e值的更新
%     s = e + floor(u);
% end

% function [s, d] = lifting_scheme(x)
% % 提升小波分解
% % 输入序列 x 应为偶数长度
% % 输出 s 为近似系数序列,d 为细节系数序列
%
% % 分裂步骤
% e = x(1:2:end);
% o = x(2:2:end);
%
% %     % 预测步骤
% %     p = [e(1); (e(1:end-1) + e(2:end)) / 2];  % 对于序列的首端,使用边界延拓
% %     d = o - floor(p);
% %
% %     % 更新步骤
% %     u = [(d(1) + d(2)) / 4; (d(1:end-1) + d(2:end)) / 4];
% %     s = e + floor(u);
%
% % 预测步骤
% % 对于序列的首端和末端,使用边界延拓
% p = [(e(1) + e(2)) / 2; (e(1:end-1) + e(2:end)) / 2; (e(end-1) + e(end)) / 2];
% p = p(1:length(o)); % 使 p 和 o 长度一致
% d = o - floor(p);
%
% % 更新步骤
% u = [(d(1) + d(2)) / 4; (d(1:end-1) + d(2:end)) / 4; (d(end) + d(end-1)) / 4];
% u = u(1:length(e)); % 使 u 和 e 长度一致
% s = e + floor(u);
% end

运行结果如下:

matlab自定义函数实现图像小波变换_第1张图片

你可能感兴趣的:(计算机视觉,opencv,图像处理)