SOM是一种无监督学习的神经网络,先贴上最近写的一个利用SOM对图片进行压缩并恢复的简单应用,留个大坑:1.有空再来总结SOM的概念,学习过程,优化算法。2.把代码再用python和C++重新实现一遍作为编程练习。。。
训练过程大致如下:
将图片分解并形成输入向量X = {Xi}, 竞争层只设了一层,即竞争层即是输出层。 对每个Xi,计算其与所有竞争结点的距离,并找到最小距离,最小距离对应的结点竞争获胜,获得修改权值的权利,(这里还定义的获胜结点的邻居,及获胜结点及其邻居获得修改权值的权利)。
图片压缩传输过程:
训练完成获得的权值矩阵作为码本,对于一张新的图片,我们计算图片中各个patch与竞争层结点的距离,最小距离对应的结点的权值向量即可近似认为是图片的patch的表示。然而在传输图片时并不直接传输权值向量,而是传输权值向量的索引,这样就达到了压缩图片进行传输的目的。
在另一端:
假设保存了该权值向量(码本),对于接收到的索引,逐一从码本中找出索引对应的权值向量,并将其按照对应位置组成图片,即完成了图片的恢复。
算法的质量评估:
通常用PSNR(峰值信噪比)描述,一般好的应该在30以上吧,由于这里仅用了最简单的实现算法,PSNR仅有21. 图片的质量并不是非常好。
main.m
clear,clc; %------------------------------------------------------------ % represent the image by vectors %------------------------------------------------------------ foo = pwd; path = fullfile(foo,'Image'); cd(path); im = imread('LENA.BMP'); % LENA.BMP for the training cd(foo); im = double(im); % (256*256)/(4*4) % 将(256*256) 分成(4*4)的图像块 n = 4; m = 4; block_n = n*ones(1,256/n); % block_n = [4,4....4] 64个4 block_m = m*ones(1,256/m); im_block = mat2cell (im,block_n,block_m); %im_block = reshape(im_block,1,4096); X = ones(16,4096); for i =1:4096 tmp = cell2mat(im_block(i)); %X(:,i) = reshape(tmp,16,1); for a = 1:4 for b = 1:4 X(:,i) = tmp(a,b); end end end [L,K] = size(X); %------------------------------------------------------------ % code book design %------------------------------------------------------------ N = 512; d = ones(1,N); a = 0.3; dq = ones(1,4096); q = ones(1,4096); t = 1; W = randint(16,512,[0,255]); % j=1:512 N=512 L=16 random values for W for initialization pW = ones(16,512); % W(k-1) iter = 10; % iteration while iter > 0 %(norm((pW-W),2) > exp(-10)) while (t<=K) % start to train the SOM for j = 1:N d(j) = dist(X(:,t),W(:,j)); end [D,IX] = min(d); %disp(sprintf('%d',IX(1))); dq(t) = D; % find the min{dj} and label q q(t) = IX; pW = W; % record current W W = Update(W,q(t),X(:,t),t,a); % update the W through index %W = Update2(W,q(t),X(:,t),t,a,d); % update the W through distances t = t+1; end iter = iter - 1; a = a * 0.95; end if pW == W % norm((pW-W),2) 求矩阵的2范数 disp('Training Done!!!'); else disp('dimensions run out!!!'); end %------------------------------------------------------------ % testing %------------------------------------------------------------ foo = pwd; path = fullfile(foo,'Image'); cd(path); im_1 = imread('CR.BMP'); im_2 = imread('HS4.BMP'); im_3 = imread('LENA.BMP'); cd(foo); im_1 = double(im_1); % im_2 = double(im_2); % im_3 = double(im_3); test(im_1,W); % test(im_2,W); % test(im_3,W);
dist.m
function [d] = dist(x,y) % compute the dist between two vectors m = size(x,1); n = size(y,1); if m ~= n disp('different dimensions!!!'); end s = 0; for i =1:n s = s + (x(i)-y(i))^2; end d = sqrt(s);
Update.m
function [W] = Update(W,q,X,t,a) % update the values in W [m,n] = size(W); Nq = 60; % distance of Neighbor for j = q-Nq:q+Nq if j <= 0 || j > 512 continue end for i = 1:m W(i,j) = W(i,j) + a * (X(i)-W(i,j)); end end
test.m
function [res] = test(im,W) % test for the image data compression based on SOM network % (256*256)/(4*4) % 将(256*256) 分成(4*4)的图像块 n = 4; m = 4; block_n = n*ones(1,256/n); % block_n = [4,4....4] 64个4 block_m = m*ones(1,256/m); im_block = mat2cell (im,block_n,block_m); %im_block = reshape(im_block,1,4096); X = ones(16,4096); for i =1:4096 tmp = cell2mat(im_block(i)); %X(:,i) = reshape(tmp,16,1); for a = 1:4 for b = 1:4 X(:,i) = tmp(a,b); end end end [L,K] = size(X); dq = ones(1,4096); q = ones(1,4096); t = 1; N = 512; while (t<=K) for j = 1:N d(j) = dist(X(:,t),W(:,j)); end [D,IX] = min(d); dq(t) = D; % find the min{dj} and label q q(t) = IX; t = t+1; end %---------------------------------------------------------------- % recover the image %---------------------------------------------------------------- Y = zeros(L,K); i =1; while (i<=K) tmp = q(i); for j = 1:16 Y(j,i) = W(j,tmp); end i = i+1; end res = ones(256,256); block_n = 4*ones(1,256/4); % block_n = [4,4....4] 64个4 block_m = 4*ones(1,256/4); res = mat2cell(res,block_n,block_m); for i =1:K %temp = reshape(Y(:,i),4,4); for a = 1:4 for b = 1:4 temp(a,b) = Y(4*(a-1)+b,i); end end res(i) = mat2cell(temp); end; res = cell2mat(res); %Y = imresize(Y,[256,256]); figure:imshow(res,[0,255]); tmp = 0; for m = 1 : 256 for n = 1 : 256 tmp = tmp + (im(m,n) - res(m,n))^2; end; end; MSE = tmp/(256*256); a = 255*255/MSE; PSNR = 10*log10(a); disp(sprintf('%f',PSNR));