如何优化图像卷积

一、图像卷积:

二、DFT---离散傅里叶变换(Discrete Fourier Transform)

      1、傅里叶级数(DFS):表示一个周期信号可以用一族正交完备的正弦波通过线性组合得到。

                                                建立时频关系。

                                 

      2、离散傅里叶变换(DFT)

           1)为何使用Dirac(\delta)函数:

      3、快速傅里叶变换(FFT):加速多项式乘法         

 /************FFT***********/
  #include   <stdio.h>
  #include   <math.h>
  #include   <stdlib.h>

  #define   N   1000
  typedef   struct
  {
  double   real;
  double   img;
  }complex;
  void   fft(); /*快速傅里叶变换*/ 
  void   ifft(); /*快速傅里叶逆变换*/ 
  void   initW();
  void   change();
  void   add(complex   ,complex   ,complex   *);   /*复数加法*/   
  void   mul(complex   ,complex   ,complex   *);   /*复数乘法*/   
  void   sub(complex   ,complex   ,complex   *);   /*复数减法*/   
  void   divi(complex   ,complex   ,complex   *);/*复数除法*/   
  void   output(); /*输出结果*/

  complex   x[N],   *W;/*输出序列的值*/
  int   size_x=0;/*输入序列的长度,只限2的N次方*/
  double   PI;

  int   main()
  {
  int   i,method;

  system("cls");
  PI=atan(1)*4;
  printf("Please   input   the   size   of   x:\n");
  /*输入序列的长度*/
  scanf("%d",&size_x);
  printf("Please   input   the   data   in   x[N]:(such as:5 6)\n");
  /*输入序列对应的值*/
  for(i=0;i<size_x;i++)
  scanf("%lf %lf",&x[i].real,&x[i].img);
  initW();   
  /*选择FFT或逆FFT运算*/
  printf("Use   FFT(0)   or   IFFT(1)?\n");   
  scanf("%d",&method);   
  if(method==0)   
  fft();   
  else   
  ifft();   
  output();   
  return   0;   
  }   
    
  /*进行基-2 FFT运算*/
  void   fft()   
  {   
  int   i=0,j=0,k=0,l=0;   
  complex   up,down,product;   
  change();   
  for(i=0;i<   log(size_x)/log(2)   ;i++)
  {       
  l=1<<i;   
  for(j=0;j<size_x;j+=   2*l   )
  {                           
  for(k=0;k<l;k++)
  {                 
  mul(x[j+k+l],W[size_x*k/2/l],&product);   
  add(x[j+k],product,&up);   
  sub(x[j+k],product,&down);   
  x[j+k]=up;   
  x[j+k+l]=down;   
  }   
  }   
  }   
  }   
    

  void   ifft()   
  {   
  int   i=0,j=0,k=0,l=size_x;   
  complex   up,down;   
  for(i=0;i<   (int)(   log(size_x)/log(2)   );i++) /*蝶形运算*/  
  {     
  l/=2;   
  for(j=0;j<size_x;j+=   2*l   )  
  {                         
  for(k=0;k<l;k++) 
  {               
  add(x[j+k],x[j+k+l],&up);   
  up.real/=2;up.img/=2;   
  sub(x[j+k],x[j+k+l],&down);   
  down.real/=2;down.img/=2;   
  divi(down,W[size_x*k/2/l],&down);   
  x[j+k]=up;   
  x[j+k+l]=down;   
  }   
  }   
  }   
  change();   
  }   
    

  void   initW()   
  {   
  int   i;   
  W=(complex   *)malloc(sizeof(complex)   *   size_x);   
  for(i=0;i<size_x;i++)   
  {   
  W[i].real=cos(2*PI/size_x*i);   
  W[i].img=-1*sin(2*PI/size_x*i);   
  }   
  }   
    
 
  void   change()   
  {   
  complex   temp;   
  unsigned   short   i=0,j=0,k=0;   
  double   t;   
  for(i=0;i<size_x;i++)   
  {   
  k=i;j=0;   
  t=(log(size_x)/log(2));   
  while(   (t--)>0   )   
  {   
  j=j<<1;   
  j|=(k   &   1);   
  k=k>>1;   
  }   
  if(j>i)   
  {   
  temp=x[i];   
  x[i]=x[j];   
  x[j]=temp;   
  }   
  }   
  }   
    

  void   output()   /*输出结果*/
  {   
  int   i;   
  printf("The   result   are   as   follows\n");   
  for(i=0;i<size_x;i++)   
  {   
  printf("%.4f",x[i].real);   
  if(x[i].img>=0.0001)   
  printf("+%.4fj\n",x[i].img);   
  else   if(fabs(x[i].img)<0.0001)   
  printf("\n");   
  else     
  printf("%.4fj\n",x[i].img);   
  }   
  }   
  void   add(complex   a,complex   b,complex   *c)   
  {   
  c->real=a.real+b.real;   
  c->img=a.img+b.img;   
  }   
    
  void   mul(complex   a,complex   b,complex   *c)   
  {   
  c->real=a.real*b.real   -   a.img*b.img;   
  c->img=a.real*b.img   +   a.img*b.real;   
  }   
  void   sub(complex   a,complex   b,complex   *c)   
  {   
  c->real=a.real-b.real;   
  c->img=a.img-b.img;   
  }   
  void   divi(complex   a,complex   b,complex   *c)   
  {   
  c->real=(   a.real*b.real+a.img*b.img   )/(    
b.real*b.real+b.img*b.img);   
  c->img=(   a.img*b.real-a.real*b.img)/(b.real*b.real+b.img*b.img);   
  } 
View Code

      4、2d加速图像卷积

           将2d核拆分成行向量与列向量乘积的形式 

bool convolve2DFast(unsigned char* in, unsigned char* out, int dataSizeX, int dataSizeY,
                    float* kernel, int kernelSizeX, int kernelSizeY)
{
    int i, j, m, n, x, y, t;
    unsigned char **inPtr, *outPtr, *ptr;
    int kCenterX, kCenterY;
    int rowEnd, colEnd;                             // ending indice for section divider
    float sum;                                      // temp accumulation buffer
    int k, kSize;

    // check validity of params
    if(!in || !out || !kernel) return false;
    if(dataSizeX <= 0 || kernelSizeX <= 0) return false;

    // find center position of kernel (half of kernel size)
    kCenterX = kernelSizeX >> 1;
    kCenterY = kernelSizeY >> 1;
    kSize = kernelSizeX * kernelSizeY;              // total kernel size

    // allocate memeory for multi-cursor
    inPtr = new unsigned char*[kSize];
    if(!inPtr) return false;                        // allocation error

    // set initial position of multi-cursor, NOTE: it is swapped instead of kernel
    ptr = in + (dataSizeX * kCenterY + kCenterX); // the first cursor is shifted (kCenterX, kCenterY)
    for(m=0, t=0; m < kernelSizeY; ++m)
    {
        for(n=0; n < kernelSizeX; ++n, ++t)
        {
            inPtr[t] = ptr - n;
        }
        ptr -= dataSizeX;
    }

    // init working  pointers
    outPtr = out;

    rowEnd = dataSizeY - kCenterY;                  // bottom row partition divider
    colEnd = dataSizeX - kCenterX;                  // right column partition divider

    // convolve rows from index=0 to index=kCenterY-1
    y = kCenterY;
    for(i=0; i < kCenterY; ++i)
    {
        // partition #1 ***********************************
        x = kCenterX;
        for(j=0; j < kCenterX; ++j)                 // column from index=0 to index=kCenterX-1
        {
            sum = 0;
            t = 0;
            for(m=0; m <= y; ++m)
            {
                for(n=0; n <= x; ++n)
                {
                    sum += *inPtr[t] * kernel[t];
                    ++t;
                }
                t += (kernelSizeX - x - 1);         // jump to next row
            }

            // store output
            *outPtr = (unsigned char)((float)fabs(sum) + 0.5f);
            ++outPtr;
            ++x;
            for(k=0; k < kSize; ++k) ++inPtr[k];    // move all cursors to next
        }

        // partition #2 ***********************************
        for(j=kCenterX; j < colEnd; ++j)            // column from index=kCenterX to index=(dataSizeX-kCenterX-1)
        {
            sum = 0;
            t = 0;
            for(m=0; m <= y; ++m)
            {
                for(n=0; n < kernelSizeX; ++n)
                {
                    sum += *inPtr[t] * kernel[t];
                    ++t;
                }
            }

            // store output
            *outPtr = (unsigned char)((float)fabs(sum) + 0.5f);
            ++outPtr;
            ++x;
            for(k=0; k < kSize; ++k) ++inPtr[k];    // move all cursors to next
        }

        // partition #3 ***********************************
        x = 1;
        for(j=colEnd; j < dataSizeX; ++j)           // column from index=(dataSizeX-kCenter) to index=(dataSizeX-1)
        {
            sum = 0;
            t = x;
            for(m=0; m <= y; ++m)
            {
                for(n=x; n < kernelSizeX; ++n)
                {
                    sum += *inPtr[t] * kernel[t];
                    ++t;
                }
                t += x;                             // jump to next row
            }

            // store output
            *outPtr = (unsigned char)((float)fabs(sum) + 0.5f);
            ++outPtr;
            ++x;
            for(k=0; k < kSize; ++k) ++inPtr[k];    // move all cursors to next
        }

        ++y;                                        // add one more row to convolve for next run
    }

    // convolve rows from index=kCenterY to index=(dataSizeY-kCenterY-1)
    for(i= kCenterY; i < rowEnd; ++i)               // number of rows
    {
        // partition #4 ***********************************
        x = kCenterX;
        for(j=0; j < kCenterX; ++j)                 // column from index=0 to index=kCenterX-1
        {
            sum = 0;
            t = 0;
            for(m=0; m < kernelSizeY; ++m)
            {
                for(n=0; n <= x; ++n)
                {
                    sum += *inPtr[t] * kernel[t];
                    ++t;
                }
                t += (kernelSizeX - x - 1);
            }

            // store output
            *outPtr = (unsigned char)((float)fabs(sum) + 0.5f);
            ++outPtr;
            ++x;
            for(k=0; k < kSize; ++k) ++inPtr[k];    // move all cursors to next
        }

        // partition #5 ***********************************
        for(j = kCenterX; j < colEnd; ++j)          // column from index=kCenterX to index=(dataSizeX-kCenterX-1)
        {
            sum = 0;
            t = 0;
            for(m=0; m < kernelSizeY; ++m)
            {
                for(n=0; n < kernelSizeX; ++n)
                {
                    sum += *inPtr[t] * kernel[t];
                    ++inPtr[t]; // in this partition, all cursors are used to convolve. moving cursors to next is safe here
                    ++t;
                }
            }

            // store output
            *outPtr = (unsigned char)((float)fabs(sum) + 0.5f);
            ++outPtr;
            ++x;
        }

        // partition #6 ***********************************
        x = 1;
        for(j=colEnd; j < dataSizeX; ++j)           // column from index=(dataSizeX-kCenter) to index=(dataSizeX-1)
        {
            sum = 0;
            t = x;
            for(m=0; m < kernelSizeY; ++m)
            {
                for(n=x; n < kernelSizeX; ++n)
                {
                    sum += *inPtr[t] * kernel[t];
                    ++t;
                }
                t += x;
            }

            // store output
            *outPtr = (unsigned char)((float)fabs(sum) + 0.5f);
            ++outPtr;
            ++x;
            for(k=0; k < kSize; ++k) ++inPtr[k];    // move all cursors to next
        }
    }

    // convolve rows from index=(dataSizeY-kCenterY) to index=(dataSizeY-1)
    y = 1;
    for(i= rowEnd; i < dataSizeY; ++i)               // number of rows
    {
        // partition #7 ***********************************
        x = kCenterX;
        for(j=0; j < kCenterX; ++j)                 // column from index=0 to index=kCenterX-1
        {
            sum = 0;
            t = kernelSizeX * y;

            for(m=y; m < kernelSizeY; ++m)
            {
                for(n=0; n <= x; ++n)
                {
                    sum += *inPtr[t] * kernel[t];
                    ++t;
                }
                t += (kernelSizeX - x - 1);
            }

            // store output
            *outPtr = (unsigned char)((float)fabs(sum) + 0.5f);
            ++outPtr;
            ++x;
            for(k=0; k < kSize; ++k) ++inPtr[k];    // move all cursors to next
        }

        // partition #8 ***********************************
        for(j=kCenterX; j < colEnd; ++j)            // column from index=kCenterX to index=(dataSizeX-kCenterX-1)
        {
            sum = 0;
            t = kernelSizeX * y;
            for(m=y; m < kernelSizeY; ++m)
            {
                for(n=0; n < kernelSizeX; ++n)
                {
                    sum += *inPtr[t] * kernel[t];
                    ++t;
                }
            }

            // store output
            *outPtr = (unsigned char)((float)fabs(sum) + 0.5f);
            ++outPtr;
            ++x;
            for(k=0; k < kSize; ++k) ++inPtr[k];
        }

        // partition #9 ***********************************
        x = 1;
        for(j=colEnd; j < dataSizeX; ++j)           // column from index=(dataSizeX-kCenter) to index=(dataSizeX-1)
        {
            sum = 0;
            t = kernelSizeX * y + x;
            for(m=y; m < kernelSizeY; ++m)
            {
                for(n=x; n < kernelSizeX; ++n)
                {
                    sum += *inPtr[t] * kernel[t];
                    ++t;
                }
                t += x;
            }

            // store output
            *outPtr = (unsigned char)((float)fabs(sum) + 0.5f);
            ++outPtr;
            ++x;
            for(k=0; k < kSize; ++k) ++inPtr[k];    // move all cursors to next
        }

        ++y;                                        // the starting row index is increased
    }

    return true;
}
View Code
posted @ 2019-07-02 11:08  cjh1122  阅读(455)  评论(0编辑  收藏  举报