opencv-12-高斯滤波-双边滤波(附C++代码实现)

图像降噪算法——中值滤波/均值滤波/高斯滤波/双边滤波 图像降噪算法——空间域滤波器图像降噪算法——空间域滤波器1. 局部滤波器2. 非局部滤波器——Non-Local Means1.1 原理介绍1.2 代码实现 图像降噪算法——空间域滤波器 空间域滤波器是最传统最简单的一类图像降噪算法,简单到我都有点不太想做写这篇博客(傲娇了…),但是为了内容的完整性,我还是在此总结下,空间域滤波器可以分为局部滤波器和非局部滤波器,其中局部滤波器又分为线性滤波器和非... 阅读详情

开始之前

这几天由于自己的原因没有写, 一个是因为自己懒了, 一个是感觉这里遇到点问题不想往下写了, 我们先努力结束这个章节吧, 之前介绍了比较常用而且比较好理解的均值和中值滤波, 但是呢,在例程Smoothing Images, 还有给出的其他的滤波方式, 主要是高斯滤波和双边滤波,

我们这一次完结掉滤波与平滑的这个部分, 写的有点多了,反而不想再写了, 加油

目录

本文目标

本文主要是介绍

  • 高斯滤波
  • 双边滤波

和之前介绍的一样, 我们仍然还是 介绍一下原理, 给出一下具体的形式, 然后使用 opencv 进行一下实现的过程, 最后使用我们之前的图像进行测试 进行算法的分析与总结.

正文

高斯滤波(Gaussian Filter)

我们在之前介绍了中值滤波是统计排序的结果, 属于非线性的结果, 均值滤波是使用模板核进行的操作, 我们在的文章中也提到了均值滤波在计算的过程中必须要考虑权重的问题, 进而提出了加权的均值滤波的操作, 比如最常见的加权均值滤波的操作核.
M = 1 16 [ 1 2 1 2 4 2 1 2 1 ] M = \frac{1}{16} \left [ \begin{array}{c} 1 & 2 & 1 \\ 2& 4 & 2 \\ 1 & 2 & 1 \end{array} \right ] M=161​⎣⎡​121​242​121​⎦⎤​

其实呢,这个核也就是高斯滤波器在 3*3窗口的离散取整的结果值, 最明显的特点就是模板的系数随着距离模板中心的距离而变换, 能够有效的抑制噪声,平滑图像, 相比均值滤波能够更好的平滑图像, 保留图像边缘.

高斯滤波原理

由于我们的图像是二维的, 但是高斯分布是一维的, 那我们先考虑一维的高斯分布, 就是我们常用的正太分布曲线,
G ( x ) = 1 2 π σ e − x 2 2 σ 2 G(x) = \frac{1}{\sqrt{2\pi \sigma}} e^{-\frac{x^2}{2\sigma^2}} G(x)=2πσ ​1​e−2σ2x2​

一维高斯分布

对于二维的高斯分布其实可以考虑成两个方向的运算相叠加的得到的结果
G ( x , y ) = 1 2 π σ 2 e − x 2 + y 2 2 σ 2 = G ( x ) ∗ G ( y ) G(x,y) = \frac{1}{2\pi \sigma^2} e^{-\frac{x^2+y^2}{2\sigma^2}} = G(x)*G(y) G(x,y)=2πσ21​e−2σ2x2+y2​=G(x)∗G(y)

二维高斯分布

考虑到图像的计算实际上是离散的座标, 对于窗口大小为 ( 2 k + 1 ) × ( 2 k + 1 ) (2k + 1) \times (2k + 1) (2k+1)×(2k+1) 模板, 我们可以表示成
G i , j = 1 2 π σ 2 e − ( i − k − 1 ) 2 + ( j − k − 1 ) 2 2 σ 2 G{i,j} = \frac{1}{2\pi \sigma ^ 2}e ^{-\frac{(i - k - 1)^2 + (j - k - 1)^2}{2 \sigma ^ 2}} Gi,j=2πσ21​e−2σ2(i−k−1)2+(j−k−1)2​

可以参考图像处理基础(4):高斯滤波器详解
里面给出的方法, 使用

void generateGaussianTemplate(double window[][11], int ksize, double sigma)
{
    static const double pi = 3.1415926;
    int center = ksize / 2; // 模板的中心位置,也就是坐标的原点
    double x2, y2;
    for (int i = 0; i < ksize; i++)
    {
        x2 = pow(i - center, 2);
        for (int j = 0; j < ksize; j++)
        {
            y2 = pow(j - center, 2);
            double g = exp(-(x2 + y2) / (2 * sigma * sigma));
            g /= 2 * pi * sigma*sigma;	// 
            window[i][j] = g;
        }
    }
    double k = 1 / window[0][0]; // 将左上角的系数归一化为1
    for (int i = 0; i < ksize; i++)
    {
        for (int j = 0; j < ksize; j++)
        {
            window[i][j] *= k;
        }
    }
}

生成了 3 × 3 , σ = 0.8 3 \times 3, \sigma = 0.8 3×3,σ=0.8 的高斯模板, 对应的将其取整就得到了
M = 1 16 [ 1 2 1 2 4 2 1 2 1 ] M = \frac{1}{16} \left [ \begin{array}{c} 1 & 2 & 1 \\ 2& 4 & 2 \\ 1 & 2 & 1 \end{array} \right ] M=161​⎣⎡​121​242​121​⎦⎤​
上面给出的文章同样的详细介绍了 σ \sigma σ 在统计学中的意义, 可以去参考学习
不过根据高中的知识, 我们可以看到 正态分布的曲线

正态分布曲线

C++ 实现

在我们之前提到的图像处理基础(4):高斯滤波器详解 这里给出了基于 opencv 的代码实现, 这里是 O ( m ∗ n ∗ k 2 ) O(m*n*k^2) O(m∗n∗k2) 的算法实现

// 来源链接: https://www.cnblogs.com/wangguchangqing/p/6407717.html
void GaussianFilter(const Mat &src, Mat &dst, int ksize, double sigma)
{
    CV_Assert(src.channels() || src.channels() == 3); // 只处理单通道或者三通道图像
    const static double pi = 3.1415926;
    // 根据窗口大小和sigma生成高斯滤波器模板
    // 申请一个二维数组,存放生成的高斯模板矩阵
    double **templateMatrix = new double*[ksize];
    for (int i = 0; i < ksize; i++)
        templateMatrix[i] = new double[ksize];
    int origin = ksize / 2; // 以模板的中心为原点
    double x2, y2;
    double sum = 0;
    for (int i = 0; i < ksize; i++)
    {
        x2 = pow(i - origin, 2);
        for (int j = 0; j < ksize; j++)
        {
            y2 = pow(j - origin, 2);
            // 高斯函数前的常数可以不用计算,会在归一化的过程中给消去
            double g = exp(-(x2 + y2) / (2 * sigma * sigma));
            sum += g;
            templateMatrix[i][j] = g;
        }
    }
    for (int i = 0; i < ksize; i++)
    {
        for (int j = 0; j < ksize; j++)
        {
            templateMatrix[i][j] /= sum;
            cout << templateMatrix[i][j] << " ";
        }
        cout << endl;
    }
    // 将模板应用到图像中
    int border = ksize / 2;
    copyMakeBorder(src, dst, border, border, border, border, BorderTypes::BORDER_REFLECT);
    int channels = dst.channels();
    int rows = dst.rows - border;
    int cols = dst.cols - border;
    for (int i = border; i < rows; i++)
    {
        for (int j = border; j < cols; j++)
        {
            double sum[3] = { 0 };
            for (int a = -border; a <= border; a++)
            {
                for (int b = -border; b <= border; b++)
                {
                    if (channels == 1)
                    {
                        sum[0] += templateMatrix[border + a][border + b] * dst.at<uchar>(i + a, j + b);
                    }
                    else if (channels == 3)
                    {
                        Vec3b rgb = dst.at<Vec3b>(i + a, j + b);
                        auto k = templateMatrix[border + a][border + b];
                        sum[0] += k * rgb[0];
                        sum[1] += k * rgb[1];
                        sum[2] += k * rgb[2];
                    }
                }
            }
            for (int k = 0; k < channels; k++)
            {
                if (sum[k] < 0)
                    sum[k] = 0;
                else if (sum[k] > 255)
                    sum[k] = 255;
            }
            if (channels == 1)
                dst.at<uchar>(i, j) = static_cast<uchar>(sum[0]);
            else if (channels == 3)
            {
                Vec3b rgb = { static_cast<uchar>(sum[0]), static_cast<uchar>(sum[1]), static_cast<uchar>(sum[2]) };
                dst.at<Vec3b>(i, j) = rgb;
            }
        }
    }
    // 释放模板数组
    for (int i = 0; i < ksize; i++)
        delete[] templateMatrix[i];
    delete[] templateMatrix;
}

然后同样的给出了分离的实现, 将图像进行水平运算之后再进行竖直运算, 计算的时间上会有一定的速度提升

// 来源链接: https://www.cnblogs.com/wangguchangqing/p/6407717.html
// 分离的计算
void separateGaussianFilter(const Mat &src, Mat &dst, int ksize, double sigma)
{
    CV_Assert(src.channels()==1 || src.channels() == 3); // 只处理单通道或者三通道图像
    // 生成一维的高斯滤波模板
    double *matrix = new double[ksize];
    double sum = 0;
    int origin = ksize / 2;
    for (int i = 0; i < ksize; i++)
    {
        // 高斯函数前的常数可以不用计算,会在归一化的过程中给消去
        double g = exp(-(i - origin) * (i - origin) / (2 * sigma * sigma));
        sum += g;
        matrix[i] = g;
    }
    // 归一化
    for (int i = 0; i < ksize; i++)
        matrix[i] /= sum;
    // 将模板应用到图像中
    int border = ksize / 2;
    copyMakeBorder(src, dst, border, border, border, border, BorderTypes::BORDER_REFLECT);
    int channels = dst.channels();
    int rows = dst.rows - border;
    int cols = dst.cols - border;
    // 水平方向
    for (int i = border; i < rows; i++)
    {
        for (int j = border; j < cols; j++)
        {
            double sum[3] = { 0 };
            for (int k = -border; k <= border; k++)
            {
                if (channels == 1)
                {
                    sum[0] += matrix[border + k] * dst.at<uchar>(i, j + k); // 行不变,列变化;先做水平方向的卷积
                }
                else if (channels == 3)
                {
                    Vec3b rgb = dst.at<Vec3b>(i, j + k);
                    sum[0] += matrix[border + k] * rgb[0];
                    sum[1] += matrix[border + k] * rgb[1];
                    sum[2] += matrix[border + k] * rgb[2];
                }
            }
            for (int k = 0; k < channels; k++)
            {
                if (sum[k] < 0)
                    sum[k] = 0;
                else if (sum[k] > 255)
                    sum[k] = 255;
            }
            if (channels == 1)
                dst.at<uchar>(i, j) = static_cast<uchar>(sum[0]);
            else if (channels == 3)
            {
                Vec3b rgb = { static_cast<uchar>(sum[0]), static_cast<uchar>(sum[1]), static_cast<uchar>(sum[2]) };
                dst.at<Vec3b>(i, j) = rgb;
            }
        }
    }
    // 竖直方向
    for (int i = border; i < rows; i++)
    {
        for (int j = border; j < cols; j++)
        {
            double sum[3] = { 0 };
            for (int k = -border; k <= border; k++)
            {
                if (channels == 1)
                {
                    sum[0] += matrix[border + k] * dst.at<uchar>(i + k, j); // 列不变,行变化;竖直方向的卷积
                }
                else if (channels == 3)
                {
                    Vec3b rgb = dst.at<Vec3b>(i + k, j);
                    sum[0] += matrix[border + k] * rgb[0];
                    sum[1] += matrix[border + k] * rgb[1];
                    sum[2] += matrix[border + k] * rgb[2];
                }
            }
            for (int k = 0; k < channels; k++)
            {
                if (sum[k] < 0)
                    sum[k] = 0;
                else if (sum[k] > 255)
                    sum[k] = 255;
            }
            if (channels == 1)
                dst.at<uchar>(i, j) = static_cast<uchar>(sum[0]);
            else if (channels == 3)
            {
                Vec3b rgb = { static_cast<uchar>(sum[0]), static_cast<uchar>(sum[1]), static_cast<uchar>(sum[2]) };
                dst.at<Vec3b>(i, j) = rgb;
            }
        }
    }
    delete[] matrix;
}

这里的算法都是 上面提到的https://www.cnblogs.com/wangguchangqing/p/6407717.html 这篇文章, 具体可以去看内容

opencv 高斯滤波

其实这篇文章图像处理–高斯滤波写的很好
其实主要的结构也就是他给出的过程

高斯函数调用图

高斯滤波函数调用简图

其实整个高斯滤波的过程就是创建高斯核, 然后使用 filter2D 的方法进行的滤波操作, 具体要深入的话可以看函数的调用图, 实现起来也是一样的思路, 很简单的操作, 我们之后测试一下效果…

// /modules\imgproc\src\smooth.dispatch.cpp:600
void GaussianBlur(InputArray _src, OutputArray _dst, Size ksize,
                  double sigma1, double sigma2,
                  int borderType)
  • src ‪输入图像
  • dst 输出图像
  • ksize 核的尺寸 奇数
  • sigmaX x 方向 的 sigma 值
  • sigmaY ‪y 方向 的 sigma 值
  • borderType 边界处理的方式
高斯滤波效果对比

我们还是使用之前的高椒盐噪声图像, 然后直接进行算法滤波, 计算结果就好, 跟之前的测试图像很相似, 这里
测试结果图

这里的四张图分别对应 高噪声图像, 直接高斯滤波的结果, 分离xy方向进行滤波结果,以及opencv 自带的高斯滤波效果图, 这里是预览图像, 实际的检测结果就是上面给出的参数值, 实际上效果只能说一般, 我们之后再进行算法层面的对比.

image-noise: psnr:19.4727, mssim: B:0.353134 G:0.383638 R:0.629353
image-noise: psnr:26.3155, mssim: B:0.584585 G:0.617172 R:0.812303
image-noise: psnr:26.1721, mssim: B:0.574719 G:0.607494 R:0.809844
image-noise: psnr:26.4206, mssim: B:0.598176 G:0.630657 R:0.819658

双边滤波(Bilateral Filter)

双边滤波原理

我们在上面提出了高斯滤波的原理是对于距离模板中心 距离不同给予不同的权重, 而双边滤波则不仅考虑图像的空间距离, 还要考虑其灰度距离, 对于越接近中间灰度值的点权重越高, 灰度值相差大的则权重更小.

双边滤波的原理可以参考双边滤波(Bilateral Filter)详解,
可以参考Bilateral Filtering for Gray and Color Images

双边滤波原理

在文章图像处理基础(5):双边滤波器详细介绍了双边滤波
其实跟上面给出的滤波演示一致, 都是在保证图像边缘信息的情况下进行噪声的滤波…

双边滤波原理

可以参考bilateral filter双边滤波器的通俗理解 给出的双边滤波的数学表达
g ( x , y ) = ∑ k l f ( k , l ) w ( i , j , k , l ) ∑ k l w ( i , j , k , l ) g(x,y) = \frac{\sum_{kl}f(k,l)w(i,j,k,l)}{\sum_{kl}w(i,j,k,l)} g(x,y)=∑kl​w(i,j,k,l)∑kl​f(k,l)w(i,j,k,l)​

对于不同的模板系数又有两个部分, 主要是 空间域模板权值 w d w_d wd​ 和 灰度域 模板权值 w r w_r wr​,
w d ( i , j , k , l ) = e − ( i − k ) 2 + ( j − l ) 2 2 σ d 2 w r ( i , j , k , l ) = e − ∥ f ( i , j ) − f ( k , l ) ∥ 2 σ r 2 w = w d ∗ w r \begin{array}{rl} w_d(i,j,k,l) &= e^{-\frac{(i-k)^2 +(j-l)^2}{2\sigma_d^2}} \\ w_r(i,j,k,l) &= e^{-\frac{\left \| f(i,j) - f(k,l) \right \|} {2\sigma_r^2}} \\ w &= w_d * w_r \end{array} wd​(i,j,k,l)wr​(i,j,k,l)w​=e−2σd2​(i−k)2+(j−l)2​=e−2σr2​∥f(i,j)−f(k,l)∥​=wd​∗wr​​
其中, q ( i , j ) q(i,j) q(i,j) 为模板窗口的其他系数的坐标, f ( i , j ) f(i,j) f(i,j) 表示图像在点 q ( i , j ) q(i,j) q(i,j) 处的像素值; p ( k , l ) p(k,l) p(k,l) 为模板窗口的中心坐标点,对应的像素值为 f ( k , l ) f(k,l) f(k,l) ; σ r \sigma_r σr​ 为高斯函数的标准差。

C++ 实现 双边滤波

感觉这里写的挺好的 图像处理基础(5):双边滤波器, 手动实现了双边滤波, 我们可以详细的参考, 这里

// 参考来源: https://www.cnblogs.com/wangguchangqing/p/6416401.html
void myBilateralFilter(const Mat &src, Mat &dst, int ksize, double space_sigma, double color_sigma)
{
    int channels = src.channels();
    CV_Assert(channels == 1 || channels == 3);
    double space_coeff = -0.5 / (space_sigma * space_sigma);
    double color_coeff = -0.5 / (color_sigma * color_sigma);
    int radius = ksize / 2;
    Mat temp;
    copyMakeBorder(src, temp, radius, radius, radius, radius, BorderTypes::BORDER_REFLECT);
    vector<double> _color_weight(channels * 256); // 存放差值的平方
    vector<double> _space_weight(ksize * ksize); // 空间模板系数
    vector<int> _space_ofs(ksize * ksize); // 模板窗口的坐标
    double *color_weight = &_color_weight[0];
    double *space_weight = &_space_weight[0];
    int    *space_ofs = &_space_ofs[0];
    for (int i = 0; i < channels * 256; i++)
        color_weight[i] = exp(i * i * color_coeff);
    // 生成空间模板
    int maxk = 0;
    for (int i = -radius; i <= radius; i++)
    {
        for (int j = -radius; j <= radius; j++)
        {
            double r = sqrt(i*i + j * j);
            if (r > radius)
                continue;
            space_weight[maxk] = exp(r * r * space_coeff); // 存放模板系数
            space_ofs[maxk++] = i * temp.step + j * channels; // 存放模板的位置,和模板系数相对应
        }
    }
    // 滤波过程
    for (int i = 0; i < src.rows; i++)
    {
        const uchar *sptr = temp.data + (i + radius) * temp.step + radius * channels;
        uchar *dptr = dst.data + i * dst.step;
        if (channels == 1)
        {
            for (int j = 0; j < src.cols; j++)
            {
                double sum = 0, wsum = 0;
                int val0 = sptr[j]; // 模板中心位置的像素
                for (int k = 0; k < maxk; k++)
                {
                    int val = sptr[j + space_ofs[k]];
                    double w = space_weight[k] * color_weight[abs(val - val0)]; // 模板系数 = 空间系数 * 灰度值系数
                    sum += val * w;
                    wsum += w;
                }
                dptr[j] = (uchar)cvRound(sum / wsum);
            }
        }
        else if (channels == 3)
        {
            for (int j = 0; j < src.cols * 3; j+=3)
            {
                double sum_b = 0, sum_g = 0, sum_r = 0, wsum = 0;
                int b0 = sptr[j];
                int g0 = sptr[j + 1];
                int r0 = sptr[j + 2];
                for (int k = 0; k < maxk; k++)
                {
                    const uchar *sptr_k = sptr + j + space_ofs[k];
                    int b = sptr_k[0];
                    int g = sptr_k[1];
                    int r = sptr_k[2];
                    double w = space_weight[k] * color_weight[abs(b - b0) + abs(g - g0) + abs(r - r0)];
                    sum_b += b * w;
                    sum_g += g * w;
                    sum_r += r * w;
                    wsum += w;
                }
                wsum = 1.0f / wsum;
                b0 = cvRound(sum_b * wsum);
                g0 = cvRound(sum_g * wsum);
                r0 = cvRound(sum_r * wsum);
                dptr[j] = (uchar)b0;
                dptr[j + 1] = (uchar)g0;
                dptr[j + 2] = (uchar)r0;
            }
        }
    }
}
opencv 实现 双边滤波
void bilateralFilter( InputArray _src, OutputArray _dst, int d,
                      double sigmaColor, double sigmaSpace,
                      int borderType )
  • InputArray src: 输入图像,可以是Mat类型,图像必须是8位或浮点型单通道、三通道的图像。
  • OutputArray dst: 输出图像,和原图像有相同的尺寸和类型。
  • int d: 表示在过滤过程中每个像素邻域的直径范围。如果这个值是非正数,则函数会从第五个参数sigmaSpace计算该值。
  • double sigmaColor: 颜色空间过滤器的sigma值,这个参数的值月大,表明该像素邻域内有越宽广的颜色会被混合到一起,产生较大的半相等颜色区域。 (这个参数可以理解为值域核的)
  • double sigmaSpace: 坐标空间中滤波器的sigma值,如果该值较大,则意味着越远的像素将相互影响,从而使更大的区域中足够相似的颜色获取相同的颜色。当d>0时,d指定了邻域大小且与sigmaSpace无关,否则d正比于sigmaSpace. (这个参数可以理解为空间域核的)
  • int borderType=BORDER_DEFAULT: 用于推断图像外部像素的某种边界模式,有默认值BORDER_DEFAULT.

双边滤波函数调用图

双边滤波算法对比

一开始的时候看双边滤波真的搞不懂, 也不知道这么做有什么目的, 最终的结果又代表什么, 我们按照之前的方法去测试我们的图像, 结果真的是几种算法中最差的了, 但是这只是说不适用于我们的图像结果, 在实际使用过程中还是要进行测试之后才能得出结论

测试结果如下: 对应原始图和 手动实现的结果以及 opencv 的结果 都使用的 是3 的窗口, sigma 的值 为 255
, 这篇文章https://blog.youkuaiyun.com/Jfuck/article/details/8932978 讲的很好, 介绍了参数对滤波的影响, 可以学习一下…

image-noise: psnr:19.4727, mssim: B:0.353134 G:0.383638 R:0.629353
image-noise: psnr:24.4502, mssim: B:0.538774 G:0.570666 R:0.776195
image-noise: psnr:24.4691, mssim: B:0.539177 G:0.571087 R:0.776461

双边滤波算法

总结

其实个人使用双边滤波真的不算很多, 在之前研究导向滤波的时候才了解过很多, 这里写的比较差吧, 只能说勉强能看, 强烈推荐 https://www.cnblogs.com/wangguchangqing/category/740760.html 这个系列, 将的很详细, 很多都是博文里面的内容, 可以参考学习, 高斯滤波就比较简单了, 其实复杂的滤波过程主要是理解算法, 然后根据算法的思路进行代码的实现过程, 最后做一定的程序上的优化就好, 理解第一, 实现其次… 希望带给读者一点点启发…

我这里一开始不准备写这么多的, 结果越写越多, 导致自己收不住了, 很多自己说不上很了解的地方, 这一次也是深入的了解了一下, 但是还是很僵硬, 只能说能用而已, 这里还是推荐看我给出的链接或者自己去查阅相关的内容, 我这里只是给出一个大略的介绍, 如果有错误还请指名, 十分感谢

参考链接

  1. 《快速高斯滤波、高斯模糊、高斯平滑(二维卷积分步为一维卷积)_人工智能_青城山小和尚-优快云博客》. 见于 2020年5月10日. https://blog.youkuaiyun.com/qq_36359022/article/details/80188873.
  2. 《双边滤波 - 旗亭涉的博客 | Qitingshe Blog》. 见于 2020年5月10日. https://qitingshe.github.io/2018/06/14/%E5%8F%8C%E8%BE%B9%E6%BB%A4%E6%B3%A2/.
  3. 《双边滤波(Bilateral Filter)详解_人工智能_Jfuck的专栏-优快云博客》. 见于 2020年5月10日. https://blog.youkuaiyun.com/Jfuck/article/details/8932978.
  4. 《雙邊濾波器》. 收入 维基百科,自由的百科全书, 2019年11月16日. https://zh.wikipedia.org/w/index.php?title=%E9%9B%99%E9%82%8A%E6%BF%BE%E6%B3%A2%E5%99%A8&oldid=56898678.
  5. 《图像处理–高斯滤波_网络_L-inYi的专栏-优快云博客》. 见于 2020年5月10日. https://blog.youkuaiyun.com/L_inYi/article/details/8915116.
  6. 《图像处理基础(4):高斯滤波器详解 - Brook_icv - 博客园》. 见于 2020年5月10日. https://www.cnblogs.com/wangguchangqing/p/6407717.html.
  7. 《图像处理基础(5):双边滤波器 - Brook_icv - 博客园》. 见于 2020年5月10日. https://www.cnblogs.com/wangguchangqing/p/6416401.html.
  8. 《图像处理-线性滤波-3 高斯滤波器 - Tony Ma - 博客园》. 见于 2020年5月10日. https://www.cnblogs.com/pegasus/archive/2011/05/20/2052031.html.
  9. 《【转】高斯图像滤波原理及其编程离散化实现方法_Smile_Gogo_新浪博客》. 见于 2020年5月10日. http://blog.sina.com.cn/s/blog_640577ed0100yz8v.html.
  10. 《bilateral filter双边滤波器的通俗理解_网络_pan_jinquan的博客-优快云博客》. 见于 2020年5月10日. https://blog.youkuaiyun.com/guyuealian/article/details/82660826.
  11. 《Bilateral Filtering》. 见于 2020年5月10日. http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html.
  12. 《Cv图像处理 - OpenCV China :图像处理,计算机视觉库,Image Processing, Computer Vision》. 见于 2020年5月10日. http://wiki.opencv.org.cn/index.php/Cv%e5%9b%be%e5%83%8f%e5%a4%84%e7%90%86.
  13. 《o(1)复杂度之双边滤波算法的原理、流程、实现及效果。 - 云+社区 - 腾讯云》. 见于 2020年5月10日. https://cloud.tencent.com/developer/article/1011738.
OpenCV(十一)图像滤波(平滑处理)(平均、中值、高斯、双边滤波) 目录 一、概念 二、线性滤波 1、概述 2、线性滤波原理: 三、滤波实例 1、均值滤波(cv::blur())(简单滤波) 2、中值滤波(cv::medianBlur()) 3、高斯滤波(cv::GaussianBlur()) 4、双边滤波(cv::bilateralFilter()) 参考资料 一、概念 “平滑”通常又称“模糊”,是一种简单常用的图像处理操作。进行平滑处理的原因有很多,但通常是用来去除噪声和相机失真,平滑在按照一定的原理来降低图像分辨率中也有重要应用。 阅读详情

相关推荐

**双边滤波(Bilateral Filter)原理解析及代码实现**

双边滤波(Bilateral Filter)原理解析及代码实现 双边滤波基本原理: 双边滤波与高斯滤波器相比,对于图像的边缘信息能过更好的保存。其原理为一个 与空间距离相关的高斯函数与一个灰度距离相关的高斯函数相乘。 空间距离: 公式中(xi,yi)为当前点位置,(xc,yc)为中心点的位置,sigma为空间域标准差。 灰度距离: 公式中gray(xi,yi)为当前点灰度值,gray(...

molihong28的博客 3625

opencv-双边滤波

视觉测量任务重点关注的是目标的边缘信息,滤波过程不应破坏目标的边缘信息,因此,保边降噪的滤波方法应运而生。常用的保边降噪的滤波方法是双边滤波,其思想是在灰度梯度平缓的区域使用高斯滤波进行降噪,在灰度梯度突变的边缘位置不进行滤波处理,保证边缘信息不被破坏。

我的博客 5213

双边滤波数学原理和C++代码实现

详细分析了双边滤波的数学原理,配有C++实现代码及详细注释

qq_21603315的博客 1237

OpenCV图像模糊:高斯滤波、双边滤波

opencv高斯滤波原理及函数(c++),自用

qq_43389847的博客 3979

双边滤波(bilateralFilter)原理及C++实现

写在前面 双边滤波是一种非线性滤波,能够达到去噪保边的效果。相比高斯滤波,双边滤波多了一种掩膜,也就是还考虑了灰度相似性,所以双边滤波是结合图像的空间邻近度和像素值相似度的一种折衷处理。 先看看对比效果:wsize=23*23, sigma(space)=10,sigma(color)=35 在同样的掩膜尺寸、sigma(space)的情况下,双边滤波能去除噪声污染并能保持边缘。 应用:图像增强、图像去雾、图像去噪、图像恢复、美颜等等 opencv函数: void bilateralFilter(Inpu

thequitesunshine007的博客 3348

快速导向滤波

很好的快速导向滤波代码,可用于做边缘保持滤波和人物磨皮等,欢迎下载。

OpenCV双边滤波详解及实代码实现

双边滤波(Bilateral Filter)是非线性滤波中的一种。这是一种结合图像的空间邻近度与像素值相似度的处理办法。在滤波时,该滤波方法同时考虑空间临近信息与颜色相似信息,在滤除噪声、平滑图像的同时,又做到边缘保存。 双边滤波采用了两个高斯滤波的结合。一个负责计算空间邻近度的权值,也就是常用的高斯滤波器原理。而另一个负责计算像素值相似度的权值。在两个高斯滤波的同时作用下,就是双边滤波。 如...

青城山小和尚 3万+

数字图像高斯滤波C++源代码

对一幅数字图片进行高斯滤波,编程语言C/C++

c++视觉处理---高斯滤波

c++视觉处理---高斯滤波

qq_46107892的博客 1527

opencv方框均值高斯中值双边滤波

本人亲测可用,本人opencv版本2.4.10 vs2013 直接编译即可运行

高斯滤波的c++代码实现

分别利用一阶高斯与二阶高斯实现了图像的滤波算法,总体来说一阶高斯滤波会更加的快速

【c++|opencv】二、灰度变换和空间滤波---4.高斯滤波

/ 定义高斯滤波函数return -1;// Opencv 自带的滤波int a= 7;// 自定义高斯滤波waitKey(0);return 0;m <= k;n++){// 定义高斯滤波函数 void myfilter(int filter_size , Mat & img_input , Mat & img_output);return - 1;

胡侃有料的博客 707

基于Qwen3-14B大模型的智能UI自动化测试实践

UI自动化测试是软件工程中保障产品质量的关键环节,其核心原理是通过脚本模拟用户操作,对软件界面进行功能验证。传统方法依赖于编写和维护基于元素定位的固定规则脚本,在面对复杂交互或频繁变化的界面时,维护成本高昂。大语言模型(LLM)的出现为这一领域带来了新的技术价值,其强大的自然语言理解和代码生成能力,使得测试脚本的编写从精确编码转向了任务描述。通过将大模型作为决策大脑,结合Playwright等自动化工具作为执行器,可以构建出能够理解界面、规划操作并验证结果的智能测试系统。这种方案特别适用于处理变化频繁、逻辑

weixin_42619742的博客 303

双边滤波(bilateralfiter)原理及C++实现

写在前面 双边滤波是一种非线性滤波,能够达到去噪保边的效果。相比高斯滤波,双边滤波多了一种掩膜,也就是还考虑了灰度相似性,所以双边滤波是结合图像的空间邻近度和像素值相似度的一种折衷处理。 先看看对比效果:wsize=23*23, sigma(space)=10,sigma(color)=35 ...

小武的博客 1万+

【UV打印机】RYPC打印软件教程(二)-软件界面概述

下图是控制软件的主操作界面.将喷绘机的操作规纳为四块,分别为参数设置,任务选择,打印控制,系统维护,对于日常打印而言,只需操作任务选择,打印控制。从而使汲及的操作相对较少,使得系统对普通用户而言简单易用.

Print World的专栏 3601

配置思科交换机冗余链路汇聚

本文对交换机端口汇聚配置进行说明

istrangeboy&begin zero的博客 6684

【C++ OpenCV】模糊原理 、均值滤波 、高斯滤波、中值滤波 、双边滤波

1.模糊原理 2.均值滤波 3.高斯滤波 4.中值滤波 5.双边滤波

Feeryman_Lee的博客 2437

贝叶斯神经网络(Bayesian Neural Network)

最近在研究贝叶斯神经网络,一些概念一直搞不清楚,这里整理一下相关内容,方便以后查阅。

梁小憨憨的博客 3656

【OpenCV+Cpp】day05图像模糊

一张图像可以通过多种方法进行图像模糊,不同的方法会有不同的侧重点,今天我们分别介绍均值滤波、高斯滤波、中值滤波和双边滤波的方法。

hiconsistent的博客 1019

深入解析SOC芯片设计中DFT OCC与ATPG的协同优化策略

本文深入探讨了在复杂SOC芯片设计中,DFT(可测试性设计)的核心组件OCC(片上时钟控制器)与ATPG(自动测试向量生成)的协同优化策略。文章从基本原理出发,分析了OCC作为测试时钟管理者的关键作用,以及ATPG作为故障检测引擎的工作机制,并重点阐述了二者在测试架构选择、参数对齐、低功耗测试等场景下的协同方法与实战技巧,旨在实现更高的测试覆盖率与更低的测试成本。

efc123456的博客 1035

SAP HANA CDS View Syntax Options 全解:从语法到工程实践

本文面向SAP HANA工程师,深入解析CDS视图的语法与应用场景。文章涵盖XS Advanced环境下的CDS视图设计要点,包括SELECT基础语法、聚合函数与分组约束、参数化视图实现以及常见连接操作。特别强调工程实践中的注意事项:GROUP BY禁用表达式、原生表名大小写规范、结果集裁剪方式选择等。通过两个真实案例(办公室占用率统计和客户画像分析)展示CDS视图在实际业务中的应用,并提供性能优化建议。全文采用中英文混排规范,技术术语使用反引号标注,旨在为开发者提供清晰的CDS视图开发指南。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 212

OpenCV——几种图像滤波总结(python实现和c++实现)

图像滤波总结 4.1 简介 图像的实质是一种二维信号,滤波是信号处理中的一个重要概念。在图像处理中,滤波是一种非常常见的技术,它们的原理非常简单,但是其思想却十分值得借鉴,滤波是很多图像算法的前置步骤或基础,掌握图像滤波对理解卷积神经网络也有一定帮助。 4.2 学习目标 了解图像滤波的分类和基本概念 理解均值滤波/方框滤波、高斯滤波的原理 掌握OpenCV框架下滤波API的使用 4...

qq_44957388的博客 9999

【C++实战(62)】从0到1:C++打造TCP网络通信实战指南

本文是 C++ 网络编程实战专栏第 62 篇,聚焦 TCP 客户端与服务端开发。先阐述 TCP 协议特点、核心 API 及阻塞与非阻塞 IO 区别,打牢基础;再详解 TCP 服务端初始化、客户端连接处理与数据收发,以及客户端初始化、异常处理和协议设计;最后通过简易聊天系统实战,介绍线程池应用、协议解析及稳定性测试,助力开发者掌握 TCP 网络编程实操技能。

邓邓子的博客 999

C++调用OpenCV实现图像平滑处理

在OpenCV中,经常用到的二维图像平滑处理有4种:均值滤波、中值滤波、高斯滤波和双边滤波。本节我们一起看一下,用C++调用OpenCV接口,如何实现对图像的平滑处理。

Bruce Che 的专栏 4473

WordPress插件depicter存在SQL注入漏洞(CVE-2025-2011)

Depicter 是一款功能强大的 WordPress 幻灯片插件,允许用户通过直观的拖放编辑器轻松创建响应式滑块、轮播和动态内容展示。该插件提供丰富的模板库、动画效果和图层控制,支持多媒体内容嵌入(如图片、视频、HTML),并优化了移动端显示和SEO性能。其无代码操作界面适合非技术用户,同时提供高级自定义选项,适用于产品展示、营销推广和视觉叙事等多种场景,是提升网站视觉吸引力的高效工具。

m0_50125527的博客 555

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

上一篇: opencv-11-中值滤波的C++实现与自适应中值滤波
下一篇: 数据分析2020年全国各省分高考成绩分布情况
SChen00
博客等级 码龄11年 26粉丝 32原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值