MATLAB实现基于BP神经网络的图像压缩

神经网络建模

BP神经网络用于压缩的原理如下:

BP网络至少包含一个隐含层,这里只采用一个隐含层,因此整体构成了一个三层的网络。把一组输入模式通过少量的隐含层单元映射到一组输出模式,并使输出模式尽可能等于输入模式。因此,隐含层神经元的值和相应的权值向量可以输出一个与原输入模式相同的向量。当隐含层的神经元个数较少时,就意味着隐含层能用更少的数来表现输入模式,而这实际上就是压缩。

第一层为输入层,中间层为隐含层,网络的映射功能依赖隐含层实现。输入层到隐含层的变换相当于压缩的编码过程。而从隐含层到输出层的变换则相当于解码的过程。如下图:

image

假设网络的输入层和输出层均由M个神经元组成,隐含层包含K个神经元,且K<M。为了解码时能复原原有的数据信号,这里的输入样本与目标响应是相同的,输入模式即为导师信号。由于K<M,输入模式必须经过隐含层才能到达输入层,因此无法通过简单的线性映射将信号传递到网络的输出端,只能对数据进行压缩编码,保存在隐含层,再由隐含层输出到下一层。

假设输入图像为NxN像素大小,被细分为多个nxn的像素块。如果将像素块中每一个像素点与一个输入或输出神经元相对应,便得到了如下图的所示的模型:

image

在图像中,每个图像被量化为m比特,因此共有2m个可能的值。2m个灰度按线性关系转换为0~1之间的数值作为网络的输入和期望的输出。网络随机地抽出图像中各nxn图像块作为学习模式,使用反向传播算法进行学习,通过调整网络中神经元之间的连接权值,使训练数据图像的重建误差E=f-g的均值达到最小。训练好的网络隐层神经元矢量便是数据压缩的结果,而输出层神经元矢量便是重建的数据。BP网络的计算模型如下图所示:

image

至此,我们构建了一个三层BP神经网络。输入层与隐含层之间的连接权值矩阵为Wij,image。隐含层第j个神经元的阈值可表示为:bj,image

同理,输出层和隐含层之间的连接权值矩阵可表示为Wji,image。输出层第i个神经元的阈值可表示为bi,image。通过不断训练网络,调整网络的权值,使得网络的输入与输出的方差达到最小,最终将N维向量压缩为K维向量。

根据图13-5,隐含层第j个神经元的输出值为:

image

输出层第i个神经元的输出值为:

image

其中image为隐含层传递函数,一般为Sigmoid函数。image为输出层传递函数,一般采用线性函数。

神经网络压缩的实现

利用BP神经网络做图像压缩和解压的过程如下图所示:

image

其中,熵编码过程针对神经网络压缩的输出进行,进一步去除统计冗余,在这里不涉及。

压缩步骤

(1)图像块划分

为简单起见,这里将所有输入图像的大小调整为128×128像素大小。为了控制神经网络规模,规定网络输入神经元节点数为16个,即将图像划分为1024个4×4大小的图像块,将每个图像块作为一个样本向量,保存为16×1024大小的矩阵,如下图所示:

image

在MATLAB中新建函数文件block_divide.m输入代码如下,即可实现图像块的划分:

function P = block_divide(I,K)
% P=block_divede(I)
% [row,col]=size(I),row%K==0, and col%K==0
% divide matrix I into K*K block,and reshape to 
% a K^2*N matrix
% example:
% I=imread('lena.jpg');
% P=block_divide(I,4);

% 计算块的个数:R*C个
[row,col]=size(I); % 获取Image数组的大小
R=row/K; 
C=col/K; % 计算将Image划分为多少个小的像素块(K为一个小像素块的大小)

% 预分配空间
P=zeros(K*K,R*C);     
for i = 1 : R
    for j = 1 : C
        % 依次取K*K 图像块
        I2 = I((i-1) * K + 1 : i * K, (j-1) * K + 1:j * K);
        % 将K*K块变为列向量
        i3 = reshape(I2, K*K, 1);
        % 将列向量放入矩阵
        P( :, (i-1) * R + j) = i3;
    end
end

这个函数要求输入的图像矩阵为二维矩阵,且图像的函数和列数均是K的倍数,取K=4时,输出值为一个16xN矩阵,N的大小视图像大小而定。

(2)归一化

神经网络的输入样本一般都需要进行归一化处理,这样更能保证性能的稳定性。归一化可以使用mapminmax函数进行,考虑到图像数据的特殊性,像素点灰度值为整数,且处于0~255之间,因此归一化处理统一将数据除以255即可。例如,读入一副图像后,进行归一化:

%% 归一化
P=double(P)/255; % 对每一个像素点进行归一化处理

归一化后图像的数据处于0~1区间内。这样做还有一个好处,如果使用mapminmax函数,需要存储每一行数据的最大值和最小值,这样最终的压缩数据里必须包含这一部分数据,使得压缩率下降。

(3)建立BP神经网络

采用MATLAB神经网络工具箱feedforwardnet函数创建BP网络,并制定训练算法。为了达到较好的效果,采用LM训练法。同时确定目标误差和最大迭代次数。

%% 建立BP神经网络 feedforwardnet(hiddenSizes,trainFcn)
net=feedforwardnet(N,'trainlm'); % Feedforward neural network
T=P;
net.trainParam.goal=0.001; % 设置BP网络训练参数
net.trainParam.epochs=500;
tic % Start stopwatch timer
net=train(net,P,T); % Train neural network
toc % Read elapsed time from stopwatch

然后,就可以调用train函数进行训练了,tic和toc用于记录训练时间。

(4)保存结果

训练完成后,压缩的结果是每个输入模式对应的隐含层神经元的值,以及网络的权值和阈值。将输入模式输入网络,与输入层和隐含层的权值矩阵相乘,再用Sigmoid函数处理,即可得到隐含层神经元的值:

image

此时得到大结果为浮点数,为了提高压缩效率,将其量化为5~8比特的整数。方法是先对矩阵进行归一化,使其范围固定在0~1之间,在乘image,最后取整数即可。

在MATLAB中使用sava命令即可将变量保存至文件。

save comp com minlw maxlw minb maxb maxd mind

解压缩步骤

加载文件,使用load命令加载数据文件。

数据反归一化。每一个数据除以image,得到0~1之间的小数,再将其映射到函数原区间中去,形式如下:

com.lw=double(com.lw)/63;
com.lw=com.lw*(maxlw-minlw)+minlw;

重建。此时得到的数据为BP神经网络隐含层的神经元输出值,为了重建图像,需要将其输入到网络中,与隐含层和输出层之间的权重矩阵相乘。

图像反归一化。图像反归一化不需要使用自定义的区间范围,只需将没份数据乘以像素峰值255,并取整数即可。

图像块恢复。假设划分图像块时,以4×4位单位进行划分,则矩阵因为16xN大小。将每一列抽取出来,重新排列为4×4矩阵,并对各个4×4矩阵按行排列,即可恢复原图像。

在MATLAB中新建函数文件re_divide.m,输入代码如下:

function I=re_divide(P,col,K)
% I=re_divide(P)
% P:  K^2*N matrix
% example:
% I=re_divide(P);
% I=uint8(I*255);
% imshow(I)

% 计算大小
[~,N]=size(P);
m=sqrt(N);

% 将向量转为K*K矩阵
b44=[];
for k=1:N
    t=reshape(P(:,k),K,K);
    b44=[b44,t];
end

% 重新排布K*K矩阵
I=[];
for k=1:m
    YYchonggou_ceshi1=b44(:,(k-1)*col+1:k*col);
    I=[I;YYchonggou_ceshi1];
end

压缩/解压代码与运行结果

至此,已经完成使用BP神经网络进行压缩和解压的过程。下面为压缩程序的完成代码(需要使用block_divide函数):

% bp_imageCompress.m
% 基于BP神经网络的图像压缩

%% 清理
clc % Clear Command Window
clear all
rng(0) % Control random number generation

%% 压缩率控制
K=4; % 设置将图片分成的小像素块的大小(KxK)
N=2; % 设置创建的BP神经网络的隐层数
row=256; % 设置所有进行压缩的图像的原始大小都为256x256
col=256;

%% 数据输入
I=imread('d:\lena.bmp');

% 统一将形状转为row*col
I = imresize(I,[row,col]); % Resize image

%% 图像块划分,形成K^2*N矩阵
P=block_divide(I,K); % 调用自定义函数block_divide将图像进行划分,形成K^2 x N大小的矩阵

%% 归一化
P=double(P)/255; % 对每一个像素点进行归一化处理

%% 建立BP神经网络 feedforwardnet(hiddenSizes,trainFcn)
net=feedforwardnet(N,'trainlm'); % Feedforward neural network
T=P;
net.trainParam.goal=0.001; % 设置BP网络训练参数
net.trainParam.epochs=500;
tic % Start stopwatch timer
net=train(net,P,T); % Train neural network
toc % Read elapsed time from stopwatch

%% 保存结果
com.lw=net.lw{2};
com.b=net.b{2};
[~,len]=size(P); % 训练样本的个数
com.d=zeros(N,len);
for i=1:len
    com.d(:,i)=tansig(net.iw{1}*P(:,i)+net.b{1}); % Hyperbolic tangent sigmoid transfer function
end
minlw= min(com.lw(:));
maxlw= max(com.lw(:));
com.lw=(com.lw-minlw)/(maxlw-minlw);
minb= min(com.b(:));
maxb= max(com.b(:));
com.b=(com.b-minb)/(maxb-minb);
maxd=max(com.d(:));
mind=min(com.d(:));
com.d=(com.d-mind)/(maxd-mind);

com.lw=uint8(com.lw*63);
com.b=uint8(com.b*63);
com.d=uint8(com.d*63);

save comp com minlw maxlw minb maxb maxd mind
% web -broswer http://www.ilovematlab.cn/forum-222-1.html

进行解压的完整脚本如下(需要使用re_divide函数):

% bp_imageRecon.m

%% 清理
clear,clc
close all

%% 载入数据
col=256;
row=256;
I=imread('d:\lena.bmp'); % 重新载入原始图片,用作对比
load comp
com.lw=double(com.lw)/63;
com.b=double(com.b)/63;
com.d=double(com.d)/63;
com.lw=com.lw*(maxlw-minlw)+minlw;
com.b=com.b*(maxb-minb)+minb;
com.d=com.d*(maxd-mind)+mind;

%% 重建
for i=1:4096
   Y(:,i)=com.lw*(com.d(:,i)) +com.b;
end

%% 反归一化
Y=uint8(Y*255);

%% 图像块恢复
I1=re_divide(Y,col,4); % 将重建后的图片存储在I1变量中

%% 计算性能
fprintf('PSNR :\n  ');
psnr=10*log10(255^2*row*col/sum(sum((I-I1).^2)));
disp(psnr)
a=dir();
for i=1:length(a)
   if (strcmp(a(i).name,'comp.mat')==1) 
       si=a(i).bytes;
       break;
   end
end
fprintf('rate: \n  ');
rate=double(si)/(256*256);
disp(rate) % Display value of variable
figure(1) % Create figure window
imshow(I) % Display image
title('原始图像');
figure(2)
imshow(I1)
title('重建图像'); <br>

运行脚本bp_imageCompress.m,指定待压缩图像为d:\lena.bmp,系统构建BP网络,并开始训练。

image

训练完成后,压缩结果将会保存到comp.mat数据文件中。

运行bp_imageRecon.m脚本进行解压,脚本读入comp.mat文件中的数据,计算网络输出,并显示原始图像和压缩后重建的图像,分别如下所示:

image

同时在命令窗口中输出重建图像的峰值信噪比和压缩比率:

image

从上图中可以看出,由于算法将图像强行分割成4×4大小的块,并分别进行训练,图像会在某种程度上出现块效应现象,表现为块与块之间差异较大。另外,由于后续没哟进行熵编码等原因,算法的压缩率(31%)并不高。这是基本的BP网络用于图像压缩的算法,基于BP神经网络的图像压缩还有一些改进的算法,如对分块进行分类,采用不同的隐含层点数进行训练,可以显著提高效果,这里暂时不做介绍。

此外,修改算法的参数可以调节图像压缩的质量。将隐含层神经元个数设为N=6时,可以提高压缩率,但图像的质量会出现一定的降低。如下图:(但图像质量还是会高于上述中N=2的情况)

image

 

  • 14
    点赞
  • 79
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值