单通道单核--转置乘法--反向卷积

本文详细解析了反卷积过程中的各个步骤,包括图像转置、2倍上采样、图像数据重排、矩阵相乘及结果处理等,并通过Matlab代码实现了关键步骤。

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

前面的矩阵乘法卷积流程:

图像-->扩充边界(padarray)-->图像数据重排(im2col)-->矩阵相乘-->图像数据重排(reshape)-->图像
哪么反向卷积应该是:

图像<--缩减边界()<--图像数据重排(col2im)<--矩阵转置相乘<--图像数据重排(reshape)<--图像
转置应该是作用图像上,所以也就是:

图像-->转置-->图像数据重排(reshape)-->矩阵相乘-->图像数据重排(col2im)-->缩减边界-->图像
matlab中的col2im好象只能作用在一行,网上也找不到使用方法,

这里先用《Python中如何实现im2col和col2im函数(sliding类型)》的col2im改编到matlab中使用

%对于col2im的实现,我们沿着列块矩阵逐行计算,将得到的行展成子矩阵,
%然后将子矩阵放置在最终结果对应的位置(每次当前值进行相加),
%同时记录每个位置的值放置的次数。最后,将当前位置的值除以放置的次数,
%即可得到结果(原始矩阵)。
function result = Python_col2im(mtx, image_size, block_size)

    %p, q = block_size
    p=block_size(2);q=block_size(1);
    sx = image_size(2) - p + 1;
    sy = image_size(1) - q + 1;
    result = zeros(image_size);
    weight = zeros(image_size); % # weight记录每个单元格的数字重复加了多少遍
    col = 1;
    %# 沿着行移动,所以先保持列(i)不动,沿着行(j)走
    %for i in range(sy):
    for i=1:sy
        %for j in range(sx):
        for j=1:sx
            tmp2=reshape(mtx(:,col),p,q);
           result( i:i + q-1, j:j + p-1) = result( i:i + q-1, j:j + p-1) + tmp2;
            %weight[j:j + p, i:i + q] += np.ones(block_size)
            weight(i:i + q-1,j:j + p-1)=weight(i:i + q-1,j:j + p-1) +ones(block_size);
            col =col  +1;
        end
                    

    end
    %col
    result = result ./ weight;

这个col2im 只是实现了步长为1,还要有一个2倍上采样:

% 2倍上采样(加空行 空列)
function Y = up2(X)

[h,w,d]=size(X);
newX=zeros(h,2*w,d);
    %加宽
    y1=zeros(h,1,d);%加列用
    p=1;
    for j=1:w
        newX(:,p+1,:)=X(:,j,:);%后1
        newX(:,p,:)=y1(:,:,:);%前0
        p=p+2;
    end

clear X;
Y=zeros(2*h,2*w,d);
    %加宽
    y1=zeros(1,2*w,d);%加行用
    p=1;
    for j=1:h
        Y(p+1,:,:)=newX(j,:,:);%后1
        Y(p,:,:)=y1(:,:,:);%前0
        p=p+2;
    end

流程就成这样了:
图像-->转置-->2倍上采样-->图像数据重排(reshape)-->矩阵相乘-->图像数据重排(col2im)-->缩减边界-->图像

然后到13层取核来和vl_nnconvt比较结果:

load m13.mat;%让程序运行到13层,保存,这里取出
clear convfea;
clear net;
 
   
% 1。是上采样2倍 放大2倍(加空行 空列)
u1=(imlow);% 图像
u1=u1'; %转置
u1=up2(u1);%2倍上采样

%2。图像数据重排(reshape)
[h,w,c]=size(u1);
u1=reshape(u1,1,h*w);%一行


%3.核排成一列
weight0=weight(:,:,2,1);%取其中一个核,和后面的vl_nnconvt 要同一个

[wh,ww,wc]=size(weight0);
weight0=reshape(weight0,wh*ww,1);%一列

%4。矩阵相乘
u2=weight0*u1;

%5。图像数据重排(col2im)
u3 = Python_col2im(u2, [w+2,h+2], [3,3]);

% %缩减边界
u3=u3(2:end-1,2:end-1);

ups1=u3+bias(2);%偏置

%与vl_nnconvt来比较
ups2 = vl_nnconvt(imlow, weight(:,:,2,1), bias(2),'upsample', upsample ,'crop', crop,'numGroups',numGroups) ;%

ups1 = vl_nnrelu(ups1, 0.2);%激励函数
ups2 = vl_nnrelu(ups2, 0.2);

k=10;%这个只是让效果更明显
u1_2=uint8((ups1-ups2)*255*k);%ups2-ups1;
u2_1=uint8((ups2-ups1)*255*k);%ups1-ups2;

figure;%显示
subplot(2,2,1);imshow(uint8((ups1*255))*k);title('1');
subplot(2,2,2);imshow(uint8(ups2*255)*k);title('2');
%然后显示两者相减
subplot(2,2,3);imshow(u1_2);title('1-2');
subplot(2,2,4);imshow(u2_1);title('2-1');

%     imwrite(u1_2, ['1-2.jpg']);
%     imwrite(u2_1, ['2-1.jpg']);

效果:

不对呀,我们的图像很暗,如果乘上9 (行数),ups1=ups1*9;好象就差不多了,

在Python_col2im 函数中有个平均除法,把它去掉:

%对于col2im的实现,我们沿着列块矩阵逐行计算,将得到的行展成子矩阵,
%然后将子矩阵放置在最终结果对应的位置(每次当前值进行相加),
%同时记录每个位置的值放置的次数。最后,将当前位置的值除以放置的次数,
%即可得到结果(原始矩阵)。
function result = Python_col2im(mtx, image_size, block_size)

    %p, q = block_size
    p=block_size(2);q=block_size(1);
    sx = image_size(2) - p + 1;
    sy = image_size(1) - q + 1;
    result = zeros(image_size);
%     weight = zeros(image_size); % # weight记录每个单元格的数字重复加了多少遍
    col = 1;
    %# 沿着行移动,所以先保持列(i)不动,沿着行(j)走
    %for i in range(sy):
    for i=1:sy
        %for j in range(sx):
        for j=1:sx
            tmp2=reshape(mtx(:,col),p,q);
           result( i:i + q-1, j:j + p-1) = result( i:i + q-1, j:j + p-1) + tmp2;
            %weight[j:j + p, i:i + q] += np.ones(block_size)
%             weight(i:i + q-1,j:j + p-1)=weight(i:i + q-1,j:j + p-1) +ones(block_size);
           col =col  +1;
        end
                    

    end
    %col
%     result = result ./ weight;

再来看效果:

好象差不多了,再看一下数据:

从这里可以看到除了左上角,其它的地方已经完全一样了

这个单通道单核应该可以用了,但是在2倍残差放大中还是不能用,因为按照反向要得到输入图,就要

用64个方程求解,才得输入图,不象正向,只是简单的加法。

还得再找一个。

先这样吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值