【算法+图像处理】2D卷积与快速卷积算法C语言实现
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                【算法+图像处理】2D卷积与快速卷积算法C语言实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                卷積算法在圖像處理中有著廣泛的應用,通常使用的去噪算法、邊緣增強算法等的實現都使用到了2D卷積算法。這里介紹一下2D卷積算法和快速卷積算法的C語言實現。
 
卷積定義
 
即
 
步驟:
 1)滑動核,使其中心位于輸入圖像g的(i,j)像素上;
 2)利用上式求和,得到輸出圖像的(i,j)像素值;
 3)充分上面操縱,直到求出輸出圖像的所有像素值。
 
 
1、2D卷積算法的實現
 
bool convolve2DSlow(unsigned char* in, unsigned char* out, int dataSizeX, int dataSizeY,float* kernel, int kernelSizeX, int kernelSizeY) {int i, j, m, n, mm, nn;int kCenterX, kCenterY; // center index of kernelfloat sum; // temp accumulation bufferint rowIndex, colIndex;// check validity of paramsif(!in || !out || !kernel) return false;if(dataSizeX <= 0 || kernelSizeX <= 0) return false;// find center position of kernel (half of kernel size)kCenterX = kernelSizeX / 2;kCenterY = kernelSizeY / 2;for(i=0; i < dataSizeY; ++i) // rows{for(j=0; j < dataSizeX; ++j) // columns{sum = 0; // init to 0 before sumfor(m=0; m < kernelSizeY; ++m) // kernel rows{mm = kernelSizeY - 1 - m; // row index of flipped kernelfor(n=0; n < kernelSizeX; ++n) // kernel columns{nn = kernelSizeX - 1 - n; // column index of flipped kernel// index of input signal, used for checking boundaryrowIndex = i + m - kCenterY;colIndex = j + n - kCenterX;// ignore input samples which are out of boundif(rowIndex >= 0 && rowIndex < dataSizeY && colIndex >= 0 && colIndex < dataSizeX)sum += in[dataSizeX * rowIndex + colIndex] * kernel[kernelSizeX * mm + nn];}}out[dataSizeX * i + j] = (unsigned char)((float)fabs(sum) + 0.5f);}}return true; }
 
2、2D快速卷積算法的實現
快速卷積算法需要核2D核h能夠拆分成一個行向量和一個列向量的乘積的形式。實際實現也就是將2D卷積,拆分成兩次1D卷積的形式。設和的大小為n*n,這樣可以將算法復雜度從n*n降低為2n。
 
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 dividerfloat sum; // temp accumulation bufferint k, kSize;// check validity of paramsif(!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-cursorinPtr = new unsigned char*[kSize];if(!inPtr) return false; // allocation error// set initial position of multi-cursor, NOTE: it is swapped instead of kernelptr = 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 pointersoutPtr = out;rowEnd = dataSizeY - kCenterY; // bottom row partition dividercolEnd = dataSizeX - kCenterX; // right column partition divider// convolve rows from index=0 to index=kCenterY-1y = 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; }
 
2017.10.29
總結
以上是生活随笔為你收集整理的【算法+图像处理】2D卷积与快速卷积算法C语言实现的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 【python图像处理】python绘制
- 下一篇: 【Hisi音频】Hi3520D音频输出调
