单通道单核 --多通道多核--矩阵乘法

前文说过,要找一个放大卷积,而 LapSRN 是通过 matconvnet 的中的一个转置矩阵乘法来实现的,所以

我们先来实现矩阵乘法。

卷积        :是通过 核区对应项相乘,再求和

矩阵乘法:是通过 行列对应项相乘,再求和

由于SRCNN简单一点,先用Matlab来测试

1。先来看原卷积实现(外框架在《超分辨率重建SRCNN--Matlab 7.0中运行》一文中):

function im_h = SRCNN(model, im_b)

%% 加载 CNN 模型参数
load(model);
[conv1_patchsize2,conv1_filters] = size(weights_conv1);
conv1_patchsize = sqrt(conv1_patchsize2);
[conv2_filters,conv3_patchsize2] = size(weights_conv3);
conv3_patchsize = sqrt(conv3_patchsize2);
[hei, wid] = size(im_b);

%   第一层卷积:
%       输入LR图像块,卷积核为:cxf1xf1xn1。 1x9x9x64
%       c为输入图像通道数,Y的话,c为1。
%       f1为卷积核size,可以设置为9
%       n1为当前卷积层输出深度,可以设置为:64

% 第一层卷积:卷积核尺寸9×9(f1×f1),卷积核数目64(n1),输出64张特征图;

%% conv1   %reshape 把指定的矩阵改变形状,但是元素个数不变,
weights_conv1 = reshape(weights_conv1, conv1_patchsize, conv1_patchsize, conv1_filters);
conv1_data = zeros(hei, wid, conv1_filters);
for i = 1 : conv1_filters %=64
    conv1_data(:,:,i) = imfilter(im_b, weights_conv1(:,:,i), 'same', 'replicate');
    conv1_data(:,:,i) = max(conv1_data(:,:,i) + biases_conv1(i), 0);

    %保存64张特征图
%     im_tt=uint8(conv1_data(:,:,i) * 255);
%     imwrite(im_tt, ['conv1_data_0' num2str(i-1) '.jpg']);
end


%% conv2
% 第二层卷积:卷积核尺寸1×1(f2×f2),卷积核数目32(n2),输出32张特征图;
conv2_data = zeros(hei, wid, conv2_filters);
for i = 1 : conv2_filters %=32
    for j = 1 : conv1_filters
        conv2_data(:,:,i) = conv2_data(:,:,i) + weights_conv2(j,:,i) * conv1_data(:,:,j);
    end
    conv2_data(:,:,i) = max(conv2_data(:,:,i) + biases_conv2(i), 0);
    %保存32张特征图
%     im_tt=uint8(conv2_data(:,:,i) * 255);
%     imwrite(im_tt, ['conv2_data_0' num2str(i-1) '.jpg']);
end

%% conv3
% 第三层卷积:卷积核尺寸5×5(f3×f3),卷积核数目1(n3),输出1张特征图即为最终重建高分辨率图像。
conv3_data = zeros(hei, wid);
for i = 1 : conv2_filters %=32
    conv3_subfilter = reshape(weights_conv3(i,:), conv3_patchsize, conv3_patchsize);
    conv3_data(:,:) = conv3_data(:,:) + imfilter(conv2_data(:,:,i), conv3_subfilter, 'same', 'replicate');
    %保存32张特征图
%     im_tt=uint8(conv3_data(:,:) * 255);
%     imwrite(im_tt, ['conv3_data_0' num2str(i-1) '.jpg']);
end

%% SRCNN 重建
im_h = conv3_data(:,:) + biases_conv3;

2。卷积转化为矩阵乘法实现:

%卷积 通过矩阵相乘 实现
function im_h = col_SRCNN(model, im_b)

%% 加载 CNN 模型参数
load(model);
[conv1_patchsize2,conv1_filters] = size(weights_conv1);
conv1_patchsize = sqrt(conv1_patchsize2);
[conv2_filters,conv3_patchsize2] = size(weights_conv3);
conv3_patchsize = sqrt(conv3_patchsize2);
[hei, wid] = size(im_b);

%   第一层卷积:
%       输入LR图像块,卷积核为:cxf1xf1xn1。 1x9x9x64
%       c为输入图像通道数,Y的话,c为1。
%       f1为卷积核size,可以设置为9
%       n1为当前卷积层输出深度,可以设置为:64

% 第一层卷积:卷积核尺寸9×9(f1×f1),卷积核数目64(n1),输出64张特征图;

%% conv1   %reshape 把指定的矩阵改变形状,但是元素个数不变,
weights_conv1 = weights_conv1';
conv1_data = zeros(hei, wid, conv1_filters);

tmp1_data = padarray(im_b,[4 4],'replicate'); % 扩充原始数据 (核宽-1 分两边) 先加
col_data = im2col(tmp1_data,[9 9],'sliding');%图像数据重排 每个核相应区排成列
clear tmp1_data;

for i = 1 : conv1_filters %=64

    col_out=weights_conv1(i,:)*col_data;% 矩阵相乘

    conv1_data(:,:,i) = reshape(col_out, [hei, wid]);%图像数据重排 成原始大小 高-(核宽-1),宽-(核宽-1) 后减(正好大小)
    conv1_data(:,:,i) = max(conv1_data(:,:,i) + biases_conv1(i), 0);
end


%% conv2
% 第二层卷积:卷积核尺寸1×1(f2×f2),卷积核数目32(n2),输出32张特征图;
conv2_data = zeros(hei, wid, conv2_filters);
for i = 1 : conv2_filters %=32
    for j = 1 : conv1_filters
        conv2_data(:,:,i) = conv2_data(:,:,i) + weights_conv2(j,:,i) * conv1_data(:,:,j);
    end
    conv2_data(:,:,i) = max(conv2_data(:,:,i) + biases_conv2(i), 0);
end

%% conv3
% 第三层卷积:卷积核尺寸5×5(f3×f3),卷积核数目1(n3),输出1张特征图即为最终重建高分辨率图像。
conv3_data = zeros(hei, wid);
for i=1:conv2_filters %=32(和第二层同大)
    tmp3_data = padarray(conv2_data(:,:,i),[2 2],'replicate'); % 扩充原始数据 (核宽-1) 先加

    col_data = im2col(tmp3_data,[5 5],'sliding');%图像数据重排 每个核相应区排成列
    col_out=weights_conv3(i,:)*col_data;% 矩阵相乘

    col_out2=reshape(col_out, [hei, wid]);%图像数据重排 成原始大小 高-(核宽-1),宽-(核宽-1) 后减(正好大小)
    conv3_data=conv3_data+col_out2;%32图相加
end

%% SRCNN 重建
im_h = conv3_data + biases_conv3;


3。再把多核,多通道 放在一起乘,也就是一层所有卷积 只用一次乘法:

%多通道 多核矩阵相乘
function im_h = col_m_SRCNN(model, im_b)

%% 加载 CNN 模型参数
load(model);
[conv1_patchsize2,conv1_filters] = size(weights_conv1);
conv1_patchsize = sqrt(conv1_patchsize2);
[conv2_filters,conv3_patchsize2] = size(weights_conv3);
conv3_patchsize = sqrt(conv3_patchsize2);
[hei, wid] = size(im_b);

%   第一层卷积:
%       输入LR图像块,卷积核为:cxf1xf1xn1。 1x9x9x64
%       c为输入图像通道数,Y的话,c为1。
%       f1为卷积核size,可以设置为9
%       n1为当前卷积层输出深度,可以设置为:64

% 第一层卷积:卷积核尺寸9×9(f1×f1),卷积核数目64(n1),输出64张特征图;

%% conv1   %reshape 把指定的矩阵改变形状,但是元素个数不变,
weights_conv1 = weights_conv1';
conv1_data = zeros(hei, wid, conv1_filters);

tmp1_data = padarray(im_b,[4 4],'replicate'); % 扩充原始数据 (核宽-1 分两边) 先加
col_data = im2col(tmp1_data,[9 9],'sliding');%图像数据重排 每个核相应区排成列
clear tmp1_data;

col_out=weights_conv1*col_data;% 矩阵相乘 64核 1通道 

for i = 1 : conv1_filters %=64

    col_tmp=col_out(i,:);% 取一通道

    conv1_data(:,:,i) = reshape(col_tmp, [hei, wid]);%图像数据重排 成原始大小 高-(核宽-1),宽-(核宽-1) 后减(正好大小)
    conv1_data(:,:,i) = max(conv1_data(:,:,i) + biases_conv1(i), 0);
end
clear col_tmp;


%% conv2
% 第二层卷积:卷积核尺寸1×1(f2×f2),卷积核数目32(n2),输出32张特征图;
conv2_data = zeros(hei, wid, conv2_filters);
for i = 1 : conv2_filters %=32
    for j = 1 : conv1_filters
        conv2_data(:,:,i) = conv2_data(:,:,i) + weights_conv2(j,:,i) * conv1_data(:,:,j);
    end
    conv2_data(:,:,i) = max(conv2_data(:,:,i) + biases_conv2(i), 0);
end

%% conv3
% 第三层卷积:卷积核尺寸5×5(f3×f3),卷积核数目1(n3),输出1张特征图即为最终重建高分辨率图像。
conv3_data = zeros(hei, wid);
for i=1:32

    %重排核
    weights0=zeros(32,25);
    for j=1:32
        if j==i
            weights0(i,:)=weights_conv3(i,:);%只有这里有数据
        %else
            %其它位置都是 0
        end
    end
    
     tmp3_data = padarray(conv2_data(:,:,i),[2 2],'replicate'); % 扩充原始数据(核宽-1)
   if i>1
        col_data=[col_data;im2col(tmp3_data,[5 5],'sliding')];%图像数据重排 后面的放到前面的后一个位置(层叠)
        
        weights=[weights,weights0];%排在一线
   else %i==1
        col_data = im2col(tmp3_data,[5 5],'sliding');%图像数据重排 第一图像重排
        weights=weights0;%第一个
    end
end
clear tmp3_data;
    
% 矩阵相乘(多通道32 多核32)  
conv3_data=weights*col_data;

%32通道相加
conv3_data=sum(conv3_data);
conv3_data=reshape(conv3_data, [hei, wid]);%图像数据重排 成原始大小 高-(核宽-1),宽-(核宽-1) 后减(正好大小)


%% SRCNN 重建
im_h = conv3_data + biases_conv3;


4。再把vl_nnconv.dll, vl_nnrelu.m 和 vl_argparse.m 也拿过来:

%使用 vl_nnconv.dll 或 vl_nnconv.m 实现 SRCNN
function im_h = vl_SRCNN(model, im_b)

im_b=single(im_b);

%% 加载 CNN 模型参数
load(model);
[conv1_patchsize2,conv1_filters] = size(weights_conv1);
conv1_patchsize = sqrt(conv1_patchsize2);
[conv2_filters,conv3_patchsize2] = size(weights_conv3);
conv3_patchsize = sqrt(conv3_patchsize2);
[hei, wid] = size(im_b);

%   第一层卷积:
%       输入LR图像块,卷积核为:cxf1xf1xn1。 1x9x9x64
%       c为输入图像通道数,Y的话,c为1。
%       f1为卷积核size,可以设置为9
%       n1为当前卷积层输出深度,可以设置为:64

% 第一层卷积:卷积核尺寸9×9(f1×f1),卷积核数目64(n1),输出64张特征图;

%% conv1   %reshape 把指定的矩阵改变形状,但是元素个数不变,
weights_conv1 = reshape(weights_conv1, conv1_patchsize, conv1_patchsize,1, conv1_filters);
weights_conv1=single(weights_conv1);
biases_conv1=single(biases_conv1);
%这个使用vl_函数实现第一层
    conv1_data = vl_nnconv(im_b,weights_conv1,biases_conv1,'Pad',4);
    conv1_data =  vl_nnrelu(conv1_data);

%% conv2
% 第二层卷积:卷积核尺寸1×1(f2×f2),卷积核数目32(n2),输出32张特征图;

conv2_data = zeros(hei, wid, conv2_filters);
for i = 1 : conv2_filters
    for j = 1 : conv1_filters
        conv2_data(:,:,i) = conv2_data(:,:,i) + weights_conv2(j,:,i) * conv1_data(:,:,j);
    end
end

%这个使用vl_函数实现第二层
    conv2_data =  vl_nnrelu(conv2_data);

%% conv3
% 第三层卷积:卷积核尺寸5×5(f3×f3),卷积核数目1(n3),输出1张特征图即为最终重建高分辨率图像。

%这个使用vl_函数实现第三层
conv3_subfilter=zeros(conv3_patchsize, conv3_patchsize,conv2_filters);
for i = 1 : conv2_filters
    conv3_subfilter(:,:,i) =reshape(weights_conv3(i,:), conv3_patchsize, conv3_patchsize);
end

conv2_data=single(conv2_data);
conv3_subfilter=single(conv3_subfilter);
biases_conv3=single(biases_conv3);

conv3_data = vl_nnconv(conv2_data,conv3_subfilter,biases_conv3,'Pad',2);
    
%% SRCNN 重建
im_h = conv3_data;

最后比较一下四种重建时间(3倍):

原图:

1。3.40秒

2。4.35秒

3。7.65秒

4。3.43秒,这个边界是0填充 有个框

小图是不是不能体现矩阵乘法的优势,还是别的原因呢?

先这样吧。

猜你喜欢

转载自blog.csdn.net/juebai123/article/details/81105379