2D卷积算法(快速卷积)算法的实现

频域算法广泛用于图像处理。常用的去噪算法和边缘增强算法的实现都使用2D频域算法。这里介绍一下2D频域算法和快速频域算法的C语言实现。

频域定义

步骤:

1)滑动内核,使其中心位于输入图像g的(i,j)像素上;

2)用上式求和c语言实现图像处理c语言实现图像处理,得到输出图像的(i,j)像素值;

3) 完全操作,直到得到输出图像的所有像素值。

1、二维频域算法的实现

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 kernel
    float sum;                                      // temp accumulation buffer
    int rowIndex, colIndex;
    // 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 / 2;
    kCenterY = kernelSizeY / 2;
    for(i=0; i < dataSizeY; ++i)                // rows
    {
        for(j=0; j < dataSizeX; ++j)            // columns
        {
            sum = 0;                            // init to 0 before sum
            for(m=0; m < kernelSizeY; ++m)      // kernel rows
            {
                mm = kernelSizeY - 1 - m;       // row index of flipped kernel
                for(n=0; n = 0 && rowIndex = 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 核 h 拆分为一个行向量和一个列向量的乘积。实际实现是将二维频域拆分为两个一维频域。设求和的大小为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 divider
    float sum;                                      // temp accumulation buffer
    int k, kSize;
    // check validity of params
    if(!in || !out || !kernel) return false;
    if(dataSizeX <= 0 || 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;
}

2017.10.29

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 网站程序 2D卷积算法(快速卷积)算法的实现 https://www.wkzy.net/game/9637.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务