zoukankan      html  css  js  c++  java
  • 图像处理之基础---二维卷积c实现

    http://wenku.baidu.com/link?url=4RzdmvP9sdaaUbnVEW4OyBD-g67wIOiJjKFF3Le_bu7hIiBS7I6hMcDmCXrQwsHvrsPvR4666J1qF1ff5JVvd2xL8rzL9N81qvL-1dwkiim

     特别说明一下,根据那本书所说,这算的是线性卷积。还有种卷积叫循环卷积。

    (1)、二维卷积运算之C语言实现

     

    若x为N1*M1的二维信号,y为N2*M2的二维信号,则卷积为(N1+N2-1)*(M1+M2-1)的信号 

    z(i,j)=∑ ∑ x(m,n)y(i

    -m,j-n) 

     ........m n

     

     #define N1 8 信号1的行

     #define M1 10 信号1的列

     #define N2 2 信号2的行

     #define M2 3 信号2的列

     

    void juanji(int x[N1][M1],int y[N2][M2],int z[N1+N2-1][M1+M2-1]) 

    int i,j; 

    int n,m; 

    for(i=0;i<N1+N2-1;i++) 

    for(j=0;j<M1+M2-1;j++) 

    int temp=0; 

    for(m=0;m<N1;m++) 

    for(n=0;n<M1;n++) 

    if((i-m)>=0&&(i-m)<N2&&(j-n)>=0&&(j-n)<M2) 

    temp+=x[m][n]*y[i-m][j-n]; 

    z[i][j]=temp; 

    }

     

    http://www.netfoucs.com/article/linger2012liu/76164.html#

     

     

    (2)、

        看卷积神经网络的时候,发现代码中计算卷积是通过矩阵乘法来计算的。

    搜了一下发现网上这方面的资料很少。刚开始找中文的,找到两个。

    http://blog.csdn.net/anan1205/article/details/12313593

    http://zhongcheng0519.blog.163.com/blog/static/161690688201122141335874/

            看了之后,还是不懂。然后开始搜英文的。

    最后搜到两个挺有用的,一个是维基百科对Toeplitz的介绍,一个是图像处理的书籍。

    http://en.wikipedia.org/wiki/Toeplitz_matrix

    Toeplitzmatrix

    http://books.google.com.hk/books?id=JeDGn6Wmf1kC&pg=PA110&lpg=PA110&dq=2-D+convolution+as+a+matrix-matrix+multiplication&source=bl&ots=kdxpa_C-Ax&sig=afy2CMZHEkoV-7ymwcBFMwvRB8U&hl=zh-CN&sa=X&ei=wjVOU_jkEMypkgW09IDwCQ&ved=0CEEQ6AEwAg#v=onepage&q=2-D%20convolution%20as%20a%20matrix-matrix%20multiplication&f=false

    下面拿一个例子来讲解一下,怎么把卷积运算转换为矩阵乘法运算。其实是那本书的一个例子。

    X=[

    1   2

    3  4]

    h= [

    5   6

    7  8]

    其中,X是卷积核。

    1 X的每一行生成一个小矩阵

    第一行[1 2],

    首先插入1,得[1 0],补的0的数量等于H的列数-1。这里,h的列数是2,故补2-1=1个0。

    再右移一位插入2,得出第二行,得[10

    2   1]

    再右移一位得出第三行,得

    [

    1 0

    2 1

    0 2]。把这个等于H0。

    第二行[3 4],同理得

    H1=[

    3 0

    4 3

    0 4]。

    观察这个过程,明显是将上一行右移再插入新的值到第一个列从而得出下一行。

    我们可以假设第0行是[0 0],最后一行是[0 0]。

    [

    0 0

    3 0

    4 3

    0 4

    0 0

    ]就可以看到规律。

    2 算出Toeplitz矩阵

    A= [

    H0  O

    H1 H0

    O  H1],其中O是一个由若干个0组成的小矩阵。

    这个例子中,

    A=

    [

    1 0 0 0

    2 1 0 0

    0 2 0 0

    3 0 1 0

    4 3 2 1

    0 4 0 2

    0 0 3 0

    0 0 4 3

    0 0 0 4

    ]

    3 将h变为列向量,按照行的顺序来,得

    [

    5

    6

    7

    8

    ]

    4 将Toeplitz矩阵和列向量相乘,得

    [

    5

    16

    12

    22

    60

    40

    21

    52

    32

    ]

    整理为矩阵得,

    [

    5 16 12

    22 60 40

    21 52 32

    ]。

    下面来验证一下,

    首先将卷积核旋转180度,得

    [

    4 3

    2 1

    ]

    从左上开始,滑动算点积,得

    5*1= 5,

    5*2+ 6*1 = 16,

    6*2= 12,

    5*3+7*1=22,

    5*4+6*3+7*2+8*1=60,

    。。。。。。

    正确!!!

    特别说明一下,根据那本书所说,这算的是线性卷积。还有种卷积叫循环卷积。

     值得注意的是:

      第一种方法是根据定义来的,浙大、北大的教案都是这种方法,

      第二种是根据几何定义来求得

      其实有第三种方法:根据原理 多项式加权相乘求和,跟第二种类似

    http://www.netfoucs.com/article/linger2012liu/76164.html#

    (4)、

    http://www.php100.com/html/program/html5/2013/0905/5441.html

    // 计算卷积矩阵的函数
    function ConvolutionMatrix(input, matrix, divisor, offset){
        // 创建一个输出的 imageData 对象
        var output = document.createElement("canvas")
                             .getContext('2d').createImageData(input);
     
        var w = input.width, h = input.height;
        var iD = input.data, oD = output.data;
        var m = matrix;
     
        // 对除了边缘的点之外的内部点的 RGB 进行操作,透明度在最后都设为 255
        for (var y = 1; y < h-1; y += 1) {
            for (var x = 1; x < w-1; x += 1) {
                for (var c = 0; c < 3; c += 1) {
                    var i = (y*w + x)*4 + c;
                    oD[i] = offset
                        +(m[0]*iD[i-w*4-4] + m[1]*iD[i-w*4] + m[2]*iD[i-w*4+4]
                        + m[3]*iD[i-4]     + m[4]*iD[i]     + m[5]*iD[i+4]
                        + m[6]*iD[i+w*4-4] + m[7]*iD[i+w*4] + m[8]*iD[i+w*4+4])
                        / divisor;
                }
                oD[(y*w + x)*4 + 3] = 255; // 设置透明度
            }
        }
        return output;
    }

    (5)、

    http://zhidao.baidu.com/question/50407836.html?fr=qrl&index=3&qbl=topic_question_3&word=%BE%D8%D5%F3%BE%ED%BB%FD

      code:

      

    一个5*5的图像和一个3*3的图像做卷积运算,具体过程如下:
    *
    * 函数名称:
    * TemplateMatchDIB()
    *
    * 参数:
    * LPSTR lpDIBBits - 指向源DIB图像指针
    * LPSTR lpDIBBitsBK - 指向背景DIB图像指针
    * LONG lWidth - 源图像宽度(象素数)
    * LONG lHeight - 源图像高度(象素数)
    * LONG lTemplateWidth - 模板图像宽度(象素数)
    * LONG lTemplateHeight - 模板图像高度(象素数)
    *
    * 返回值:
    * BOOL - 运算成功返回TRUE,否则返回FALSE。
    *
    * 说明:
    * 该函数用于对图像进行模板匹配运算。
    *
    * 要求目标图像为255个灰度值灰度图像
    ************************************************************************/

    BOOL WINAPI TemplateMatchDIB (LPSTR lpDIBBits, LPSTR lpTemplateDIBBits, LONG lWidth, LONG lHeight,
    LONG lTemplateWidth,LONG lTemplateHeight)
    {
    // 指向源图像的指针
    LPSTR lpSrc,lpTemplateSrc;

    // 指向缓存图像的指针
    LPSTR lpDst;

    // 指向缓存DIB图像的指针
    LPSTR lpNewDIBBits;
    HLOCAL hNewDIBBits;

    //循环变量
    long i;
    long j;
    long m;
    long n;

    //中间结果
    double dSigmaST;
    double dSigmaS;
    double dSigmaT;

    //相似性测度
    double R;

    //最大相似性测度
    double MaxR;

    //最大相似性出现位置
    long lMaxWidth;
    long lMaxHeight;

    //像素值
    unsigned char pixel;
    unsigned char templatepixel;

    // 图像每行的字节数
    LONG lLineBytes,lTemplateLineBytes;

    // 暂时分配内存,以保存新图像
    hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);

    if (hNewDIBBits == NULL)
    {
    // 分配内存失败
    return FALSE;
    }

    // 锁定内存
    lpNewDIBBits = (char * )LocalLock(hNewDIBBits);

    // 初始化新分配的内存,设定初始值为255
    lpDst = (char *)lpNewDIBBits;
    memset(lpDst, (BYTE)255, lWidth * lHeight);

    // 计算图像每行的字节数
    lLineBytes = WIDTHBYTES(lWidth * 8);
    lTemplateLineBytes = WIDTHBYTES(lTemplateWidth * 8);

    //计算dSigmaT
    dSigmaT = 0;
    for (n = 0;n < lTemplateHeight ;n++)
    {
    for(m = 0;m < lTemplateWidth ;m++)
    {
    // 指向模板图像倒数第j行,第i个象素的指针
    lpTemplateSrc = (char *)lpTemplateDIBBits + lTemplateLineBytes * n + m;
    templatepixel = (unsigned char)*lpTemplateSrc;
    dSigmaT += (double)templatepixel*templatepixel;
    }
    }

    //找到图像中最大相似性的出现位置
    MaxR = 0.0;
    for (j = 0;j < lHeight - lTemplateHeight +1 ;j++)
    {
    for(i = 0;i < lWidth - lTemplateWidth + 1;i++)
    {
    dSigmaST = 0;
    dSigmaS = 0;

    for (n = 0;n < lTemplateHeight ;n++)
    {
    for(m = 0;m < lTemplateWidth ;m++)
    {
    // 指向源图像倒数第j+n行,第i+m个象素的指针
    lpSrc = (char *)lpDIBBits + lLineBytes * (j+n) + (i+m);

    // 指向模板图像倒数第n行,第m个象素的指针
    lpTemplateSrc = (char *)lpTemplateDIBBits + lTemplateLineBytes * n + m;

    pixel = (unsigned char)*lpSrc;
    templatepixel = (unsigned char)*lpTemplateSrc;

    dSigmaS += (double)pixel*pixel;
    dSigmaST += (double)pixel*templatepixel;
    }
    }
    //计算相似性
    R = dSigmaST / ( sqrt(dSigmaS)*sqrt(dSigmaT));
    //与最大相似性比较
    if (R > MaxR)
    {
    MaxR = R;
    lMaxWidth = i;
    lMaxHeight = j;
    }
    }
    }

    //将最大相似性出现区域部分复制到目标图像
    for (n = 0;n < lTemplateHeight ;n++)
    {
    for(m = 0;m < lTemplateWidth ;m++)
    {
    lpTemplateSrc = (char *)lpTemplateDIBBits + lTemplateLineBytes * n + m;
    lpDst = (char *)lpNewDIBBits + lLineBytes * (n+lMaxHeight) + (m+lMaxWidth);
    *lpDst = *lpTemplateSrc;
    }
    }

    // 复制图像
    memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);

    // 释放内存
    LocalUnlock(hNewDIBBits);
    LocalFree(hNewDIBBits);

    // 返回
    return TRUE;
    }Top
      这是模板匹配的代码,   
    里面用的就是时域卷积的算法。

    同时,时域卷积就是频域的乘积,
    可以把时域的图转化成频域,相乘。

    ps
    卷积需要补位,
    a ,b
    l >= a+b-1;
    http://wenku.baidu.com/link?url=N_AvksJPpds6tlT7uGKE896ByVDH7n8olJjYiCwoqrWgUIoAA2KLVfUI-OSBYYp3j0jA6kOAYCsh4Y19IPYoG71YS2lrNgQcHUMJumYuk2O
    (6)、卷积的各种优化
     包括二维转一维
    http://bbs.csdn.net/topics/30472434

    卷积的应用太广泛了:比如说 考试舞弊找代考的,把两个人的照片进行卷积就,类似同一个人了

  • 相关阅读:
    UVa 1364
    一个无向图博弈游戏
    poj 2777 Count Color (线段树)
    UVA 1660
    JS中的caller属性
    “给在读研究生+未来要读研同学们的一封受益匪浅的信”(摘录+整合)
    用cmd重命名.htaccess
    java Scoket的c\s结构聊天室
    log4j详解
    检查文本文件编码的Java程序
  • 原文地址:https://www.cnblogs.com/pengkunfan/p/3947140.html
Copyright © 2011-2022 走看看