我们要C++ 来实现 LapSRN 中 vl_nnconvt 函数的功能,要转化 matconvnet 以我的能力是不够的,因为它和matlab紧密联系的,而且看人家源代码也是很难的,只能自己按原理搞,或者到哪里去抄(先要知道哪儿有得抄)
LapSRN 有两处用到该函数
1。2倍残差放大: 核3x3 参数是 'upsample', 2 ,'crop', [0 1 0 1],'numGroups', 1 有bias
2。2倍图像放大: 核4x4 参数是 'upsample', 2 ,'crop', [1 1 1 1],'numGroups', 1 无bias
有人说:反卷积就是卷积,只是中间填充零,然后再做卷积。
我们就按这句实现,先在matlab中和 vl_nnconvt 对比效果:
function Y = vl_nnconvt0(X, F, B, option1, value1, option2, value2, option3, valu3)
%vl_nnconvt(convfea, weight, bias,'upsample', 2 ,'crop', [0 1 0 1],'numGroups', 1) ;%2倍残差放大
%vl_nnconvt(convfea, weight, [] ,'upsample', 2 ,'crop', [1 1 1 1],'numGroups', 1) ;%2倍图像放大
% 2倍上采样
[h,w,d]=size(X);
newX=zeros(h,2*w,d);
for i=1:d
%加宽
y1=zeros(h,1);%一列(加列用)
tmpX=newX(:,:,i);
oldX=X(:,:,i);
p=1;
for j=1:w
tmpX(:,p+1)=oldX(:,j);%后1
tmpX(:,p)=y1(:,:);%前0
p=p+2;
end
newX(:,:,i)=tmpX;
end
X=zeros(2*h,2*w,d);
for i=1:d
%加宽
y1=zeros(1,2*w);%一行(加行用)
tmpX=X(:,:,i);
oldX=newX(:,:,i);
p=1;
for j=1:h
tmpX(p+1,:)=oldX(j,:);%后1
tmpX(p,:)=y1(:,:);%前0
p=p+2;
end
X(:,:,i)=tmpX;
end
X=single(X);
%然后卷积
[h,w,d,n]=size(F);
if h==3 %3x3
Y = vl_nnconv(X,F,B,'Pad',1); %这样和原始大小一样
else %4x4
Y = vl_nnconv(X,F,B,'Pad',2); %这里比原始图像大一行一列
[h,w,d,n]=size(Y);
Y=Y(2:h,2:w,:,:); %减一行一列
end
用42层的4x4卷积核来测试2倍放大:
%用42层的4x4卷积核来测试2倍放大
clear all;
img_filename = '6b.jpg';
%% 参数
scale = 8; % SR 采样比例 可以是 2、4 或 8 倍
im_l=imread(img_filename);
im_l=rgb2ycbcr(im_l);
imlow = single(im_l(:,:,1)) /255;%;
%% 加载预训练模型
model_filename = fullfile('pretrained_models', sprintf('LapSRN_x%d.mat', scale));
fprintf('载入 %s\n', model_filename);
net = load(model_filename);
net=net.net;
i=42; %42 是放大层
disp(['第 ',num2str(i),' 层']);
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
bias=[];
disp('输出是:');
disp(net.layers(i).outputs);
upsample=net.layers(i).block.upsample;
crop=net.layers(i).block.crop;
numGroups=net.layers(i).block.numGroups;
img_up1 = vl_nnconvt0(imlow, weight, bias,'upsample', upsample ,'crop', crop,'numGroups',numGroups) ;%
img_up2 = vl_nnconvt(imlow, weight, bias,'upsample', upsample ,'crop', crop,'numGroups',numGroups) ;%
figure;
subplot(2,2,1);imshow(uint8((img_up1)*255));title('1');
subplot(2,2,2);imshow(uint8(img_up2*255));title('2');
%然后两者相减
u2_1=uint8((img_up2-img_up1)*255);
u1_2=uint8((img_up1-img_up2)*255);
subplot(2,2,3);imshow(u1_2);title('1-2');
subplot(2,2,4);imshow(u2_1);title('2-1');
对比效果图:
然后到13层找一个3x3核来测试2倍残差放大:
...相同省略
i=13
...相同省略
img_up1 = vl_nnconvt0(imlow, weight(:,:,1,1), bias(1,1),'upsample', upsample ,'crop', crop,'numGroups',numGroups) ;%
img_up2 = vl_nnconvt(imlow, weight(:,:,1,1), bias(1,1),'upsample', upsample ,'crop', crop,'numGroups',numGroups) ;%
k=20 %经过残差核卷积后都是比较暗的,这里放大20倍来显示效果
figure;
subplot(2,2,1);imshow(uint8((img_up1)*255)*k);title('1');
subplot(2,2,2);imshow(uint8(img_up2*255)*k);title('2');
%然后两者相减
u2_1=uint8((img_up2-img_up1)*255*k);
u1_2=uint8((img_up1-img_up2)*255*k);
subplot(2,2,3);imshow(u1_2);title('1-2');
subplot(2,2,4);imshow(u2_1);title('2-1');
对比效果图:
在看上去好象差不多,但在相减图中有很多地方是不一样的
把上面的函数代入LapSRN重建程序中看一下结果:
2倍
4倍
8倍
如果只替换图像放大一处,还是可以的
4倍
8倍
这样,只完成了2倍图像放大这一半,还要找一个2倍残差放大函数
先这样吧