您的位置:首页 > 编程语言

深度学习【15】darknet中im2col代码分析

2017-07-24 10:56 1211 查看
darknet里面的im2col用的是caffe的im2col代码。多通道矩阵数据(如彩色图像)经过im2col操作后得到一个矩阵,同时将多个卷积核也转成一个矩阵的形式。这样一来就能够把卷积操作转换成矩阵乘法。本文主要讨论im2col的实现。
看一下im2col的参数:voidim2col_cpu(float*data_im,intchannels,intheight,intwidth,intksize,intstride,intpad,float*data_col)具体意义如下:data_im:输入数据channels:输入数据通道数height:输入数据的高width:输入数据的宽ksize:卷积核的大小stride:卷积核移动的步长,下文都以stride=1来处理pad:padding时所需要填充的长度,padding的长度为ksize/2data_col:输出为了更好的理解im2col,先看看卷积的实现过程。假设im2col的输入参数如下:channels:3;height:4;width:4;ksize:3;stride:1;pad:1先利用im2col转换成矩阵,具体可参考一下博文:http://blog.csdn.net/mrhiuser/article/details/52672824只不过在darknet中输出的是27*16的一个矩阵,而不是27*4。原因是darknet中的im2col相当于对原来的输入图像进行了padding操作,使原来的4*4图像变为6*6的。然后才从原来的4*4中的第一行第一列的元素开始执行操作。而上面的博文介绍的是直接从第二行第二列开始的,也就是只对不超出核矩阵范围的元素进行操作。在darknet中要生成一个27*16的矩阵,是按照行来生成的。也就是先生成第一行的16个点,然后以此类推,生成所有行的16个点。以下是对源码的分析:void im2col_cpu(float* data_im,
int channels, int height, int width,
int ksize, int stride, int pad, float* data_col)
{
int c,h,w;
//计算卷积后的图像宽和高,在darknet中似乎认为卷积后的输出图像跟输入图像尺寸是一样的
int height_col = (height + 2*pad - ksize) / stride + 1;
int width_col = (width + 2*pad - ksize) / stride + 1;

int channels_col = channels * ksize * ksize;//im2col后的矩阵行数如3*3*3=27
for (c = 0; c < channels_col; ++c) {//按照行逐点生成
int w_offset = c % ksize;
int h_offset = (c / ksize) % ksize;
int c_im = c / ksize / ksize;//计算目前处理第几个通道的图像
//遍历整个4*4的图像点生成16个第c点的数据
for (h = 0; h < height_col; ++h) {
for (w = 0; w < width_col; ++w) {
//计算出3*3中要生成某个点的数据在padding后图像的位置,比如在当c=5时,也就是要生成3*3中的第二行第三列的点(1*2),在下面的im2col_get_pixel中im_row和im_col都会减去pad=1
//所以im_row和im_col分别为2和3,当im_row和im_col中只要有超出图像边界的时候im2col_get_pixel返回的像素值为0。也就是相当于先对输入图像进行了padding操作。
int im_row = h_offset + h * stride;
int im_col = w_offset + w * stride;
int col_index = (c * height_col + h) * width_col + w;
data_col[col_index] = im2col_get_pixel(data_im, height, width, channels,
im_row, im_col, c_im, pad);
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  代码分析
相关文章推荐