如何优化图像卷积
一、图像卷积:
二、DFT---离散傅里叶变换(Discrete Fourier Transform)
1、傅里叶级数(DFS):表示一个周期信号可以用一族正交完备的正弦波通过线性组合得到。
建立时频关系。
2、离散傅里叶变换(DFT)
1)为何使用Dirac()函数:
3、快速傅里叶变换(FFT):加速多项式乘法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/************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); }
4、2d加速图像卷积
将2d核拆分成行向量与列向量乘积的形式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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; }