美文网首页
1D Guassian Filter

1D Guassian Filter

作者: 0x55aa | 来源:发表于2018-12-13 21:26 被阅读0次

    一维高斯函数:

    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倍!

    原图:

    原图

    一维高斯模糊效果图:

    一维高斯模糊效果图
    二维高斯模糊效果图

    相关文章

      网友评论

          本文标题:1D Guassian Filter

          本文链接:https://www.haomeiwen.com/subject/ttlihqtx.html