放大卷积--反向卷积--猜测

本文介绍了如何使用 C++ 重新实现 LapSRN 中的 vl_nnconvt 函数,该函数用于实现图像的上采样操作。文中详细解释了如何在 C++ 中通过插入零值并进行卷积运算来达到反卷积的效果,并通过与 Matlab 中的 vl_nnconvt 函数进行对比验证正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们要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倍残差放大函数

先这样吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值