1、矩阵卷积

卷积就是卷积核跟图像矩阵的运算。卷积核是一个小窗口,记录的是权重。卷积核在输入图像上按步长滑动,每次操作卷积核对应区域的输入图像,将卷积核中的权值和对应的输入图像的值相乘再相加,赋给卷积核中心所对应的输出特征图的一个值,如下图所示(这里卷积核要旋转180 °):

2、im2col的实现

2.1 im2col有什么作用

以上我们已经知道了卷积是如何操作的,im2col的作用就是优化卷积运算,如何优化呢,我们先学习一下这个函数的原理。
我们假设卷积核的尺寸为2*2,输入图像尺寸为3*3.im2col做的事情就是对于卷积核每一次要处理的小窗,将其展开到新矩阵的一行(列),新矩阵的列(行)数,就是对于一副输入图像,卷积运算的次数(卷积核滑动的次数),如下图所示:
以最右侧一列为例,卷积核为2*2,所以新矩阵的列数就为4;步长为一,卷积核共滑动4次,行数就为4.再放一张图应该看得更清楚。
输入为4*4,卷积核为3*3,则新矩阵为9*4 。看到这里我就产生了一个疑问:我们把一个卷积核对应的值展开,到底应该展开为行还是列呢?卷积核的滑动先行后列还是相反?区别在哪?
这其实主要取决于我们使用的框架访存的方式。计算机一次性读取相近的内存是最快的,尤其是当需要把数据送到GPU去计算的时候,这样可以节省访存的时间,以达到加速的目的。不同框架的访存机制不一样,所以会有行列相反这样的区别。在caffe框架下,im2col是将一个小窗的值展开为一行,而在matlab中则展开为列。所以说,行列的问题没有本质区别,目的都是为了在计算时读取连续的内存。
这也解释了我们为什么要通过这个变化来优化卷积。如果按照数学上的步骤做卷积读取内存是不连续的,这样就会增加时间成本。同时我们注意到做卷积对应元素相乘再相加的做法跟向量内积很相似,所以通过im2col将矩阵卷积转化为矩阵乘法来实现。

2.2 一个简单实现

基于以上对于im2col的理解,自己写了一个简单实现(c++ opencv3.2)。
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;int main()
{Mat img =imread("1.jpg");Mat kernel=Mat::ones(9,9,CV_8UC1);int stride=5;int kernum_w,kernum_h;if(img.rows%stride==0)kernum_w=img.rows/stride;elsekernum_w=img.rows/stride+1;if(img.cols%stride==0)kernum_h=img.cols/stride;elsekernum_h=img.cols/stride+1;int out_w=kernum_w*kernum_h;int out_h=kernel.cols*kernel.rows;int channel_size=img.cols*img.rows;//初始化输入、卷积核并计算新矩阵的尺寸Mat C=Mat::zeros(out_w,out_h,CV_8UC3);for (int channel=img.channels();channel--;channel>0){  int i=0;for (int im_row=0;im_row<img.rows;im_row+=stride){for (int im_col=0;im_col<img.cols;im_col+=stride){  for (int ker_row=0;ker_row<kernel.rows;ker_row++){for(int ker_col=0;ker_col<kernel.cols;ker_col++){int input_row=im_row-(kernel.rows-1)/2+ker_row;int input_col=im_col-(kernel.cols-1)/2+ker_col;//索引当前小窗内元素对应到输入的行列值if(input_row<0||input_col<0||input_row>=img.rows||input_col>=img.cols)C.at<Vec3b>(i,ker_col+kernel.cols*ker_row)[channel]=0;  else    C.at<Vec3b>(i,ker_col+kernel.cols*ker_row)[channel]=img.at<Vec3b>(input_row,input_col)[channel];//超出原图的范围,则新矩阵对应的位置赋零,否则将输入赋给对应的位置}}i++;}} }imshow("im2col",C);waitKey(0);return 0;
}

对于c++我也只是初学者,关于指针,我还要多加学习,这里对图像的遍历使用了Mat类的成员函数at(),也是一种比较低效率的方法。高效的方法(指针方法)参考这篇http://blog.csdn.net/daoqinglin/article/details/23628125

参考文献
http://lib.csdn.net/article/aiframework/62849(这里有caffe中的源码解读)
http://blog.csdn.net/mrhiuser/article/details/52672824

im2col的原理和实现相关推荐

  1. im2col原理小结

    网上最流行的卷积核原理是: 一边移动,一边计算. im2col的原理是: 一次性移动完,然后一次性计算. 代码来自第七章,如下: import sys, os import numpy as np s ...

  2. im2col函数实现超级详细解释

    前言 阅读<深度学习入门:基于python的理论与实现>,其中在实现CNN的章节中,提到为了CNN的快速计算需要将输入数据展开是以适合滤波器(权重),对于输入数据,将应用滤波器的区域(3维 ...

  3. 深度学习(二)卷积计算

    写在前面:所有关于深度学习的基础知识均为鄙人的笔记分享,很多内容摘自大神们的博客或论文,因时间太长记不清了分别来自哪里.若有侵权,请联系鄙人邮箱min.wenfang@qq.com 目前,卷积的计算大 ...

  4. im2col矩阵卷积原理

    im2col的实现 1 im2col有什么作用 以上我们已经知道了卷积是如何操作的,im2col的作用就是优化卷积运算,如何优化呢,我们先学习一下这个函数的原理. 我们假设卷积核的尺寸为2*2,输入图 ...

  5. im2col原理详解

    图像的卷积计算有很多种算法,目前各个开源框架常用的都是im2col+gemm的方式 该方法的做法,就是将卷积过程转化为矩阵乘法,其好处在于可以通过优化矩阵乘算法,优化计算过程,并且有利于CUDA等并行 ...

  6. Caffe学习 五 conv_layer与im2col

    1.BaseConvolutionLayer & ConvolutionLayer 成员变量 注释引用自caffe代码阅读10:Caffe中卷积的实现细节(涉及到BaseConvolution ...

  7. im2col函数解析

    im2col函数是进行卷积运算所常用的一个函数,它的作用是将进行卷积运算的一组图片二维化,而后再与卷积核进行矩阵相乘,代替了卷积运算原来相乘再相加的运算形式,可以大大减少运算所需时间.接下来介绍im2 ...

  8. opencv基础:罗德里格斯旋转公式(Rodrigues' rotation formula)推导 rodrigues()函数原理

    参考:1-https://openhome.cc/Gossip/WebGL/Rodrigues.html(比较好的理解流程) 2-https://www.cnblogs.com/wtyuan/p/12 ...

  9. MATLAB--数字图像处理 im2col()

    im2col() 矩阵卷积 卷积就是卷积核跟图像矩阵的运算.卷积核是一个小窗口,记录的是权重.卷积核在输入图像上按步长滑动,每次操作卷积核对应区域的输入图像,将卷积核中的权值和对应的输入图像的值相乘再 ...

  10. YOLOv3反向传播原理 之 全流程源码分析

    YOLOv3反向传播原理 之 全流程源码分析 1.YOLOv3网络训练中反向传播主体流程 1.1 初始化 1.2 batch内梯度累加 1.3 network和layer 中的关键变量 2.YOLO层 ...

最新文章

  1. 极客新闻——17、给决定长久做程序员的你三个建议
  2. linux 检查 文件末尾 是否有空行
  3. PHP垃圾回收机制防止内存溢出
  4. hdu3622 二分+2sat
  5. 时隔七个月,我终于弄懂了汉诺塔的思想
  6. Avalonia跨平台入门第十五篇之ListBox聊天窗口
  7. 二分法查找是基于有序_201,查找顺序查找
  8. .Net4.0 Parallel编程(三)Data Parallelism下
  9. linux一g运行内存不足,在linux运行weblogic出现运行内存不足错误,求鞭挞....
  10. 删除ELK中的数据。。
  11. idea的debug基本用法快捷键
  12. WebService cxf简单入门附视频教程
  13. wow修改人物模型_wow - 1.12 - 修改 人物 模型 ,
  14. Linux指令——tailf
  15. 必备技能10:管理学类重要期刊名录 -- UTD24 和 FT50
  16. matlab 光平面标定代码,光平面标定法
  17. QCOM chi-camera bring up
  18. Channel Attention 通道注意力
  19. java实现Stripe信用卡支付
  20. 使用PHP获取网站Favicon的方法

热门文章

  1. 木头也要懂得讲故事的时代
  2. 三星typec转接耳机没反应_1MORE最新双旗舰无线降噪耳机评测:国货强于外夷的希望...
  3. Kubernetes网络flannel之host-gw模式分析
  4. jenkins 国内插件源无效问题的解决方案
  5. python拼音四线格书写格式_Python 中拼音庫 PyPinyin 的用法
  6. IE8中text-align:center偏左的解决办法
  7. python求和函数详解_python 中求和函数 sum详解
  8. vue中views新建文件夹的代码规范
  9. 原来清理手机内存,使用管家是不够的!还需删除这4个文件夹
  10. 阿里云服务器使用xshell连接