这个和前面差不多,
先外框架:
% 金字塔式网络实现的快速准确的超分辨率
clear all;
img_filename = '测试2.jpg';
%% 参数
scale = 4; % SR 采样比例 可以是 2、4 或 8 倍
%% 设置路径
addpath(genpath('utils'));
addpath(fullfile(pwd, 'matconvnet/matlab'));
vl_setupnn;
%% 加载预训练模型
model_filename = fullfile('pretrained_models', sprintf('LapSRN_x%d.mat', scale));
fprintf('载入 %s\n', model_filename);
net = load(model_filename);
net=net.net;
%% 加载 LR 图像
fprintf('载入 %s\n', img_filename);
im_l=imread(img_filename);
im_l=rgb2ycbcr(im_l);
img_LR = single(im_l(:,:,1)) /255;%;
%% 应用 LapSRN
fprintf('应用 LapSRN for %dx SR\n', scale);
%返回 2、4 和 8 倍重建(根据选中网络而定)
[im_HR1,im_HR2,im_HR3] = myLapSRN(net, img_LR);
%% 显示结果
im_H = imresize(im_l,2,'bicubic');
im_H=single(im_H);
im_H(:,:,1)= im_HR1*255;
im_H=ycbcr2rgb(uint8(im_H));
figure, imshow(im_H);title(sprintf('由 LapSRN %d 倍重建彩色', 2));
imwrite(im_H, ['LapSRN 2倍重建.jpg']);
if scale>2
im_H = imresize(im_l,4,'bicubic');
im_H=single(im_H);
im_H(:,:,1)= im_HR2*255;
im_H=ycbcr2rgb(uint8(im_H));
figure, imshow(im_H);title(sprintf('由 LapSRN %d 倍重建彩色', 4));
imwrite(im_H, ['LapSRN 4倍重建.jpg']);
end
if scale==8
im_H = imresize(im_l,8,'bicubic');
im_H=single(im_H);
im_H(:,:,1)= im_HR3*255;
im_H=ycbcr2rgb(uint8(im_H));
figure, imshow(im_H);title(sprintf('由 LapSRN %d 倍重建彩色', 8));
imwrite(im_H, ['LapSRN 8倍重建.jpg']);
end
核心函数:
% LapSRN 超分辨率重建 - 各层代码
function [hR1,hR2,hR3] = myLapSRN(net, imlow)
hR1=[];hR2=[];hR3=[];
%总层数
l=length(net.layers);
j=0;%卷积层计数,可以去掉
upsample_num=0;% 图像放大计数
residual_num=0;% 残差图计数
%循环各层直至结束
for i=1:l %
disp(['第 ',num2str(i),' 层']);
% disp(net.layers(i).name);
% disp(net.layers(i).type);
% disp(net.layers(i).inputs);
% disp(net.layers(i).outputs);
% disp(net.layers(i).params);
% disp(net.layers(i).block);
if strTong(net.layers(i).type,'dagnn.Conv')
j=j+1
disp('卷积层');
%得到权重(也就是卷积核)和偏移
disp('参数是:');
disp(net.layers(i).params);
fft=net.layers(i).params{1};
for k=1:length(net.params)
if strTong(net.params(k).name,fft)
weight=net.params(k).value;
break;
end
end
if net.layers(i).block.hasBias==false
bias=[]; % 无偏移
else
fft=net.layers(i).params{2};
for k=1:length(net.params)
if strTong(net.params(k).name,fft)
bias=net.params(k).value;
break;
end
end
end
%得到输入
disp('输入是:');
disp(net.layers(i).inputs);
disp('输出是:');
disp(net.layers(i).outputs);
if strTong(net.layers(i).inputs{1},'LR') %第一层
convfea = myconv(imlow,weight,bias,'Pad',1);%一图得出64特征图
else %一以后
if strBao(net.layers(i).outputs{:}, 'residual')
residual_num=residual_num+1;
if residual_num==1
residual1= myconv(convfea,weight,bias,'Pad',1);% 2倍残差图
end
if residual_num==2
residual2= myconv(convfea,weight,bias,'Pad',1);% 4倍残差图
end
if residual_num==3
residual3= myconv(convfea,weight,bias,'Pad',1);% 8倍残差图
end
else
%中间层 64特征图合成1图 再重新生成深一层64特征图
convfea = myconv(convfea,weight,bias,'Pad',1);
end
end
end
if strTong(net.layers(i).type,'dagnn.ReLU' )
disp('激励层');
disp('输入是:');
disp(net.layers(i).inputs);
disp('参数是:');
disp(net.layers(i).params);
disp('输出是:');
disp(net.layers(i).outputs);
convfea = vl_nnrelu(convfea,'leak', 0.2);
end
if strTong(net.layers(i).type,'dagnn.ConvTranspose')
disp('上采样层');%反向卷积,转置卷积
disp('输入是:');
disp(net.layers(i).inputs);
%得到权重(也就是卷积核)和偏移
disp('参数是:');
disp(net.layers(i).params);
fft=net.layers(i).params{1};
for k=1:length(net.params)
if strTong(net.params(k).name,fft)
weight=net.params(k).value;
break;
end
end
if net.layers(i).block.hasBias==false
bias=[]; % 无偏移
else
fft=net.layers(i).params{2};
for k=1:length(net.params)
if strTong(net.params(k).name,fft)
bias=net.params(k).value;
break;
end
end
end
disp('输出是:');
disp(net.layers(i).outputs);
upsample=net.layers(i).block.upsample;
crop=net.layers(i).block.crop;
numGroups=net.layers(i).block.numGroups;
opts=net.layers(i).block.opts{:}
% 字符串是否包含
if strBao(net.layers(i).outputs{:}, 'img_up') %残差
upsample_num=upsample_num+1;
% 图像放大参数是 'upsample', 2 ,'crop', [1 1 1 1],'numGroups', 1
if upsample_num==1 % 2倍放大图
img_up1 = vl_nnconvt(imlow, weight, bias,'upsample', upsample ,'crop', crop,'numGroups',numGroups, opts) ;
hR1=img_up1+residual1; % 合成2倍重建图
else
if upsample_num==2 % 4倍放大图
img_up2 = vl_nnconvt(hR1, weight, bias,'upsample', upsample ,'crop', crop,'numGroups',numGroups,opts) ;%
hR2=img_up2+residual2; % 4倍
end
if upsample_num==3 % 8倍放大图
img_up3 = vl_nnconvt(hR2, weight, bias,'upsample', upsample ,'crop', crop,'numGroups',numGroups, opts) ;%
hR3=img_up3+residual3; % 8倍
end
end
else
% 残差放大参数是 'upsample', 2 ,'crop', [0 1 0 1],'numGroups', 1
convfea = vl_nnconvt(convfea, weight, bias,'upsample', upsample ,'crop', crop,'numGroups',numGroups,opts) ;%
end
end
end
%--------------------------------------------------------------------------
%加边并卷积后还原
function [X] = myconv(X, F, B, option1, value1)
if nargin==3
X = vl_nnconv(X, F, B);
else
%消除四边一条线和左上角白点,否则会随着层数的增加,会越来越大
BoundarySize=1;
X = padarray(X, [BoundarySize,BoundarySize], 'replicate','both');
X = vl_nnconv(X, F, B, option1, value1);
X = X(BoundarySize+1:end-BoundarySize,BoundarySize+1:end-BoundarySize,:);
end
8倍重建效果图:
原图2倍4倍8倍
4倍网络重建图:
原2
4倍
这里和前面不同之处,有一个残差放大卷积,图像放大卷积层,这里调用的是 matconvnet 的 vl_nnconvt 。
只好再来编译 vl_nnconvt.cpp 了。而这要用到转置乘法,上文的sgemm已经不够用了,再加一点:
//printf("sgemm...\n");
//C := alpha * op ( A ) * op ( B ) + beta * C,
//beta=0 相当于清0
//beta=1 相当于加上原来的值
printf("alpha:%f\n",alpha);
printf("beta:%f\n",beta);
//printf("m:%d\n",m);
//printf("n:%d\n",n);
//printf("k:%d\n",k);
//printf("lda:%d\n",lda);
//printf("ldb:%d\n",ldb);
//printf("ldc:%d\n",ldc);
char op[2]={0};
op[0]=op1;printf("op1:%s\n",op);
op[0]=op2;printf("op2:%s\n",op);
int i;
if(beta==0.0) //这里完成 C = 0(beta) * C
{
float * c1=c;
for(i=0;i<m*n;i++)
{
*c1++=0;
}
}
if((op2 == 'N') || (op2 == 'n')) //这里完成 C = 1(alpha)* A * B
{
int q1,q2;
int p1,p2,p3;
int o1,o2;
o1=-m;p1=-m;
for(i=0;i<m;i++)
{
p1++;p3=p1;
q1=-k;
o1++;o2=o1;//-m+i
for(int j=0;j<n;j++)
{
q1+=k;q2=q1;// j*k+q
p2=p1;//q*m+i
o1+=m;//j*m+i
for(int q=0;q<k;q++)
{
//c[j*m+i]+=a[q*m+i]*b[j*k+q];
p1+=m;
c[o1]+=a[p1]*b[q1++];
}
q1=q2;
p1=p2;
}
o1=o2;
p1=p3;
}
}
else
{printf("start:t!\n"); 这里完成 C = 1(alpha)* A * B'
//就是把 b 转置成 tmpb 再矩阵相乘
float * tmpb=new float[k*n*sizeof(float)];
float * tb2=tmpb;
for(i=0;i<n;i++)
{
for(int j=0;j<k;j++)
{
*tb2++ =b[j*n+i];
}
}
int q1,q2;
int p1,p2,p3;
int o1,o2;
o1=-m;p1=-m;
for(i=0;i<m;i++)
{
p1++;p3=p1;
q1=-k;
o1++;o2=o1;//-m+i
for(int j=0;j<n;j++)
{
q1+=k;q2=q1;// j*k+q
p2=p1;//q*m+i
o1+=m;//j*m+i
for(int q=0;q<k;q++)
{
//c[j*m+i]+=a[q*m+i]*b[j*k+q];
p1+=m;
c[o1]+=a[p1]*tmpb[q1++];
}
q1=q2;
p1=p2;
}
o1=o2;
p1=p3;
}
delete []tmpb; tmpb=NULL;
}
成功后生成一个vl_nnconvt.dll
这个还是比较快的,如果改编成C++的话,要先找一个放大卷积函数,或者反向卷积,转置卷积什么的
先这样吧