1D Guassian Filter

2018-12-13  本文已影响0人  0x55aa

一维高斯函数:

image.png

  高斯函数具有线性可分的性质,即可以通过2个一维的高斯函数,分别对图像进行纵向和横向进行一次处理,就能得到和二维高斯函数一致的效果。

  重点在于,一维高斯函数处理图像的复杂度为 2xy2r,而二维高斯函数的复杂度达到了xy4r^2,一维比二维降低了指数级的复杂度!

QT代码:

void getWeights1D(double* weights,int r){

    //计算高斯核权重

    const float sigma = (r*2+1) / 2.0;

    const float exp = std::exp(1);

    const float sigma2 = sigma*sigma;

    const float dSigma2 = 2*sigma2;

    const float k = 1 / sqrt(2*3.1415926*sigma2);

    double sum = 0;

    for(int i = -r;i<=r;i++){

        int absI =abs(i);

        int it = i+r;

        weights[it] = k * std::pow(exp,-absI*absI / dSigma2);

        sum+= weights[it];

    }

    for(int i = 0;i<=r*2;++i)

        weights[i] /= sum;

}

void MainWindow::GuassianBlur1D(){

    int r = 10;

    double* weights = new double[r*2+1];

    getWeights1D(weights,r);

    int width = m_srcImg.width();

    int height = m_srcImg.height();

    QImage newImg(m_srcImg);

    auto startTime = clock();

    //横向模糊

    for(int i = 0 ;i<width;++i){

        for(int j =0;j<height;++j){

            float sumR = 0;

            float sumG = 0;

            float sumB = 0;

            for(int x = -r;x<=r;++x){

                int pos = i+x;

                if(pos < 0 || pos >= width)

                   pos = i - x;

                QColor color = m_srcImg.pixel(pos,j);

                sumR += color.red()*weights[x+r];

                sumG += color.green()*weights[x+r];

                sumB += color.blue()*weights[x+r];

            }

            QColor finalColor;

            int r = std::round(sumR);

            int g = std::round(sumG);

            int b = std::round(sumB);

            finalColor.setRed(r);

            finalColor.setGreen(g);

            finalColor.setBlue(b);

            QPoint point(i,j);

            newImg.setPixelColor(point,finalColor);

        }

    }

    //纵向模糊

    for(int i = 0 ;i<width;++i){

        for(int j =0;j<height;++j){

            float sumR = 0;

            float sumG = 0;

            float sumB = 0;

            for(int x = -r;x<=r;++x){

                int pos = j + x;

                if(pos < 0 || pos >= height)

                    pos = j - x;

                QColor color = newImg.pixel(i,pos);

                sumR += color.red()*weights[x+r];

                sumG += color.green()*weights[x+r];

                sumB += color.blue()*weights[x+r];

            }

            QColor finalColor;

            int r = std::round(sumR);

            int g = std::round(sumG);

            int b = std::round(sumB);

            finalColor.setRed(r);

            finalColor.setGreen(g);

            finalColor.setBlue(b);

            QPoint point(i,j);

            newImg.setPixelColor(point,finalColor);

        }

    }

    auto endTime = clock();

    qDebug()<<"模糊耗时"<<endTime - startTime;

    newImg.save("D:/tag.jpg");

    qDebug()<<"done";

    delete [] weights;

}

void MainWindow::on_btnGaussBlur_clicked()

{

    //GuassianBlur2D();

    GuassianBlur1D();

}

运行结果为:

模糊耗时 1457

done

比二维高斯函数快了近10倍!

原图:

原图

一维高斯模糊效果图:

一维高斯模糊效果图
二维高斯模糊效果图
上一篇下一篇

猜你喜欢

热点阅读