图像处理中的滤波_均值滤波、中值滤波、高斯滤波 图像处理函数的适用图像 - CSDN
  • 图像处理的几种滤波

    2018-06-19 01:57:50
    均值滤波均值滤波,是图像处理中最常用的手段,从频率域观点来看均值滤波是一种低通滤波器,高频信号将会去掉,因此可以帮助消除图像尖锐噪声,实现图像平滑,模糊等功能。理想的均值滤波是用每个像素和它周围像素...

    均值滤波

    均值滤波,是图像处理中最常用的手段,从频率域观点来看均值滤波是一种低通滤波器,高频信号将会去掉,因此可以帮助消除图像尖锐噪声,实现图像平滑,模糊等功能。理想的均值滤波是用每个像素和它周围像素计算出来的平均值替换图像中每个像素。采样Kernel数据通常是3X3的矩阵,如下表示:

    从左到右从上到下计算图像中的每个像素,最终得到处理后的图像。均值滤波可以加上两个参数,即迭代次数,Kernel数据大小。一个相同的Kernel,但是多次迭代就会效果越来越好。同样,迭代次数相同,Kernel矩阵越大,均值滤波的效果就越明显。


    中值滤波

    中值滤波也是消除图像噪声最常见的手段之一,特别是消除椒盐噪声,中值滤波的效果要比均值滤波更好。中值滤波是跟均值滤波唯一不同是,不是用均值来替换中心每个像素,而是将周围像素和中心像素排序以后,取中值,一个3X3大小的中值滤波如下:

     


    最大最小值滤波

    最大最小值滤波是一种比较保守的图像处理手段,与中值滤波类似,首先要排序周围像素和中心像素值,然后将中心像素值与最小和最大像素值比较,如果比最小值小,则替换中心像素为最小值,如果中心像素比最大值大,则替换中心像素为最大值。一个Kernel矩阵为3X3的最大最小值滤波如下:

     


    双边滤波

    一种同时考虑了像素空间差异与强度差异的滤波器,因此具有保持图像边缘的特性。

    先看看高斯滤波器


    其中W是权重,i和j是像素索引,K是归一化常量。公式中可以看出,权重只和像素之间的空间距离有关系,无论图像的内容是什么,都有相同的滤波效果。

    再来看看双边滤波器,它只是在原有高斯函数的基础上加了一项,如下


    其中 I 是像素的强度值,所以在强度差距大的地方(边缘),权重会减小,滤波效应也就变小。总体而言,在像素强度变换不大的区域,双边滤波有类似于高斯滤波的效果,而在图像边缘等强度梯度较大的地方,可以保持梯度


    引导滤波

    与双边滤波最大的相似之处,就是同样具有保持边缘特性。在引导滤波的定义中,用到了局部线性模型,至于该模型,可以暂时用下图简单的理解


    该模型认为,某函数上一点与其邻近部分的点成线性关系,一个复杂的函数就可以用很多局部的线性函数来表示,当需要求该函数上某一点的值时,只需计算所有包含该点的线性函数的值并做平均即可。这种模型,在表示非解析函数上,非常有用。

    同理,我们可以认为图像是一个二维函数,而且没法写出解析表达式,因此我们假设该函数的输出与输入在一个二维窗口内满足线性关系,如下


    其中,q是输出像素的值,I是输入图像的值,i和k是像素索引,a和b是当窗口中心位于k时该线性函数的系数。其实,输入图像不一定是待滤波的图像本身,也可以是其他图像即引导图像,这也是为何称为引导滤波的原因。对上式两边取梯度,可以得到


    即当输入图像I有梯度时,输出q也有类似的梯度,现在可以解释为什么引导滤波有边缘保持特性了。

    下一步是求出线性函数的系数,也就是线性回归,即希望拟合函数的输出值与真实值p之间的差距最小,也就是让下式最小


    这里p只能是待滤波图像,并不像I那样可以是其他图像。同时,a之前的系数(以后都写为e)用于防止求得的a过大,也是调节滤波器滤波效果的重要参数。通过最小二乘法,我们可以得到


    其中,是I在窗口w_k中的平均值,是I在窗口w_k中的方差,是窗口w_k中像素的数量,是待滤波图像p在窗口w_k中的均值。

    在计算每个窗口的线性系数时,我们可以发现一个像素会被多个窗口包含,也就是说,每个像素都由多个线性函数所描述。因此,如之前所说,要具体求某一点的输出值时,只需将所有包含该点的线性函数值平均即可,如下


    这里,w_k是所有包含像素i的窗口,k是其中心位置。

    当把引导滤波用作边缘保持滤波器时,往往有 I = p ,如果e=0,显然a=1, b=0是E(a,b)为最小值的解,从上式可以看出,这时的滤波器没有任何作用,将输入原封不动的输出。如果e>0,在像素强度变化小的区域(或单色区域),有a近似于(或等于)0,而b近似于(或等于),即做了一个加权均值滤波;而在变化大的区域,a近似于1,b近似于0,对图像的滤波效果很弱,有助于保持边缘。而e的作用就是界定什么是变化大,什么是变化小。在窗口大小不变的情况下,随着e的增大,滤波效果越明显。

    在滤波效果上,引导滤波和双边滤波差不多,在一些细节上,引导滤波较好。引导滤波最大的优势在于,可以写出时间复杂度与窗口大小无关的算法,因此在使用大窗口处理图片时,其效率更高。


    [python] view plain copy
    1. def guidedfilter(I,p,r,eps):  
    2.     '''''I:引导图图; 
    3.     p:输入图(p=I); 
    4.     r :半径: 
    5.     eps:regulation  
    6.     f:为窗口半径为r的均值滤波器; 
    7.     corr:相关; 
    8.     var:方差; 
    9.     cov:协方差 
    10.     '''  
    11.     height,width = I.reshape()  
    12.     m_I = cv2.boxFilter(I,-1,(r,r))  #f_mean(I) 均值滤波blur和盒式滤波一样  
    13.     m_p = cv2.boxFilter(p,-1,(r,r))  #f_mean(p)  
    14.   
    15.   
    16.     m_II = cv2.boxFilter(I*I,-1,(r,r)) #f_mean(I.*I)  
    17.     m_Ip = cv2.boxFilter(I * p, -1, (r, r))  #f_mean(I.*p)  
    18.   
    19.     var_I = m_II-m_I*m_I   #求方差:corr_I -mean_I.*mean_I  
    20.     cov_Ip = m_Ip - m_I * m_p  #协方差: #cov_Ip-mean_I.*mean_p  
    21.   
    22.     a = cov_Ip/(var_I+eps)  #cov_Ip./(var_I+eps)  
    23.     b = m_p-a*m_I   #mean_p -a.*mean_I  
    24.     m_a = cv2.boxFilter(a,-1,(r,r))  #mean_a  
    25.     m_b = cv2.boxFilter(b,-1,(r,r))  #mean_b  
    26.     return m_a*I+m_b  
    展开全文
  • 图像滤波:即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。 消除图像的噪声...

    1.什么是滤波?

    图像滤波:即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。

    消除图像中的噪声成分叫作图像的平滑化或滤波操作。信号或图像的能量大部分集中在幅度谱的低频和中频段是很常见的,而在较高频段,感兴趣的信息经常被噪声淹没。因此一个能降低高频成分幅度的滤波器就能够减弱噪声的影响。

    2.平滑处理的目的

    图像滤波的目的有两个:

    一是抽出对象的特征作为图像识别的特征模式;
    另一个是为适应图像处理的要求,消除图像数字化时所混入的噪声。

    而对滤波处理的要求也有两条:

    一是不能损坏图像的轮廓及边缘等重要信息;
    二是使图像清晰视觉效果好。

    3.平滑处理的应用

    关于滤波器,一种形象的比喻法是:
    我们可以把滤波器想象成一个包含加权系数的窗口,当使用这个滤波器平滑处理图像时,就把这个窗口放到图像之上,透过这个窗口来看我们得到的图像。

    举一个滤波在我们生活中的应用:
    美颜的磨皮功能。如果将我们脸上坑坑洼洼比作是噪声的话,那么滤波算法就是来取出这些噪声,使我们自拍的皮肤看起来很光滑。

    4.中值滤波的处理方法

    中值滤波是一种典型的非线性滤波,是基于排序统计理论的一种能够有效抑制噪声的非线性信号处理技术,基本思想是用像素点邻域灰度值的中值来代替该像素点的灰度值,让周围的像素值接近真实的值从而消除孤立的噪声点。该方法在取出脉冲噪声、椒盐噪声的同时能保留图像的边缘细节。这些优良特性是线性滤波所不具备的。

    中值滤波首先也得生成一个滤波模板,将该模板内的各像素值进行排序,生成单调上升或单调下降的二维数据序列,二维中值滤波输出为

    g(x, y)=medf{f(x-k, y-1),(k, l∈w)}

    	其中f(x,y)和g(x,y)分别是原图像和处理后图像, w为输入的二维模板,能够在整幅图像上滑动,通常尺寸为3*3或5*5区域,也可以是不同的形状如线状、圆形、十字形、圆环形等。通过从图像中的二维模板取出奇数个数据进行排序,用排序后的中值取代要处理的数据即可。 
    

    5.中值滤波的示意图

    首先,我们复习中值。在一连串数字{1,4,6,8,9}中,数字6就是这串数字的中值。由此我们可以应用到图像处理中。依然我们在图像中去3*3的矩阵,里面有9个像素点,我们将9个像素进行排序,最后将这个矩阵的中心点赋值为这九个像素的中值。

    引用

    中值滤波示意图

    椒盐噪声

    椒盐噪声(salt-and-pepper noise)是由图像传感器,传输信道,解码处理等产生的黑白相间的亮暗点噪声。
      所谓椒盐,椒就是黑,盐就是白,椒盐噪声就是在图像上随机出现黑色白色的像素。椒盐噪声是一种因为信号脉冲强度引起的噪声,产生该噪声的算法也比较简单。
      椒盐噪声往往由图像切割引起,去除脉冲干扰及椒盐噪声最常用的算法是中值滤波。大量的实验研究发现,由摄像机拍摄得到的图像受离散的脉冲、椒盐噪声和零均值的高斯噪声的影响较严重。噪声给图像处理带来很多困难,对图像分割、特征提取、图像识别等具有直接影响。因此,实时采集的图像需进行滤波处理。消除图像中的噪声成份叫做图像的平滑化或滤波操作。滤波的目的有两个:一是抽出对象的特征作为图像识别的特征模式;二是为适应计算机处理的要求,消除图像数字化时所混入的噪声。对滤波处理的要求有两条:一是不能损坏图像轮廓及边缘等重要信息;二是使图像清晰,视觉效果好。

    我们使用信噪比(Signal NoiseRate)衡量图像噪声,图象的信噪比应该等于信号与噪声的功率谱之比,但通常功率谱难以计算,有一种方法可以近似估计图象信噪比,即信号与噪声的方差之比(其实在均值为零的情况下,功率就是方差)。首先计算图象所有像素的局部方差,将局部方差的最大值认为是信号方差,最小值是噪声方差,求出它们的比值,再转成dB数,最后用经验公式修正。

    6.椒盐处理和中值滤波的效果展示

    在这里插入图片描述

    7.代码(面向过程)

    #%matplotlib inline
    from matplotlib import pyplot as plt
    import cv2
    import numpy as np
    from copy import deepcopy
    
    
    filename = input("请输入图像名称:")
    winname = "figure"
    img = cv2.imread(filename)
    
    def add_salt_noise(img, snr=0.5):
        # 指定信噪比
        SNR = snr
        # 获取总共像素个数
        size = img.size
        print(size)
        # 因为信噪比是 SNR ,所以噪声占据百分之10,所以需要对这百分之10加噪声
        noiseSize = int(size * (1 - SNR))
        # 对这些点加噪声
        for k in range(0, noiseSize):
            # 随机获取 某个点
            xi = int(np.random.uniform(0, img.shape[1]))
            xj = int(np.random.uniform(0, img.shape[0]))
            # 增加噪声
            if img.ndim == 2:
                img[xj, xi] = 255
            elif img.ndim == 3:
                img[xj, xi] = 0
        return img
    
    img_demo = deepcopy(img)
    snr = float(input("请输入一个信噪比(小数表示):"))
    img_salt = add_salt_noise(img_demo, snr)
    img_medianblur = cv2.medianBlur(img, 11)
    
    img_all = np.hstack([
        img, img_salt, img_medianblur
    ])
    
    plt.figure(figsize=(20,10))
    plt.imshow(img_all[:,:,::-1])
    plt.show()
    
    

    8.程序演示(面向对象)

    用tkinter 做的界面化处理操作

    面向对象制作的界面程序处理中值滤波

    完整代码(码云):码云分享
    完整代码(github):github分享

    觉得不错的朋友,可以与我交流关注,以及去码云和github点星,真的感谢!~

    有问题可以联系

    展开全文
  • 滤波器作为图像处理课程的重要内容,大致可分为两类,空域滤波器和频率域滤波器。本文主要介绍常用的四种滤波器:中值滤波器、均值滤波器、高斯滤波器、双边滤波器,并基于opencv做出实现。空域的滤波器一般可以通过...

    1. 滤波器介绍

    滤波器作为图像处理课程的重要内容,大致可分为两类,空域滤波器和频率域滤波器。本文主要介绍常用的四种滤波器:中值滤波器、均值滤波器、高斯滤波器、双边滤波器,并基于opencv做出实现。空域的滤波器一般可以通过模板对原图像进行卷积。

    注意:空域滤波器和频率域滤波器对比

    1)空间域指图像本身,空域变换直接对图像中的像素进行操作。

    2)图像变换是将图像从空间域变换到某变换域(如 傅立叶变换中的频率域)的数学变换,在变换域 中进行处理,然后通过反变换把处理结果返回到空间域。

    3)图像在空域上具有很强的相关性,借助于正交变 换可使在空域的复杂计算转换到频域后得到简化

    4)借助于频域特性的分析,将更有利于获得图像的 各种特性和进行特殊处理

     

    2、理论知识:

    图像的空域滤波无非两种情况,线性滤波和非线性滤波。

          滤波的意思就是对原图像的每个像素周围一定范围内的像素进行运算,运算的范围就称为掩膜。而运算就分两种了,如果运算只是对各像素灰度值进行简单处理(如乘一个权值)最后求和,就称为线性滤波;而如果对像素灰度值的运算比较复杂,而不是最后求和的简单运算,则是非线性滤波;如求一个像素周围3x3范围内最大值、最小值、中值、均值等操作都不是简单的加权,都属于非线性滤波。

    常见的线性滤波有:均值滤波、高斯滤波、盒子滤波、拉普拉斯滤波等等,通常线性滤波器之间只是模版系数不同。

    非线性滤波利用原始图像跟模版之间的一种逻辑关系得到结果,如最值滤波器,中值滤波器和双边滤波器等。

    1、线性滤波

    线性滤波器表达公式:,其中均值滤波器和高斯滤波器属于线性滤波器,首先看这两种滤波器

    均值滤波器:

    模板:

     

    从待处理图像首元素开始用模板对原始图像进行卷积,均值滤波直观地理解就是用相邻元素灰度值的平均值代替该元素的灰度值。

    高斯滤波器:

    高斯滤波一般针对的是高斯噪声,能够很好的抑制图像输入时随机引入的噪声,将像素点跟邻域像素看作是一种高斯分布的关系,它的操作是将图像和一个高斯核进行卷积操作: 

     

    模板:通过高斯内核函数产生的

    高斯内核函数:

    例如3*3的高斯内核模板:

    中值滤波:同样是空间域的滤波,主题思想是取相邻像素的点,然后对相邻像素的点进行排序,取中点的灰度值作为该像素点的灰度值。

    统计排序滤波器,对椒盐噪声有很好的抑制

    详细请参考:数字图像处理之椒盐噪声和中值滤波

    中值滤波将窗口函数里面的所有像素进行排序取得中位数来代表该窗口中心的像素值,对椒盐噪声和脉冲噪声的抑制效果特别好,同时又能保留边缘细节,用公式表示是: 

    双边滤波(Bilateral filter)也是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的,具有简单,非迭代、局部的特点,它比高斯滤波多了一个高斯方差σd,用公式表示就是: 

    w(x,y)为加权系数,取决于定义域核和值域核的乘积。

    注意:

    1)均值模糊无法克服边缘像素信息丢失的缺陷,原因是均值滤波是基于平均权重的。

    2)高斯模糊部分克服了该缺陷,但无法完全避免,因为没有考虑像素值的不同。

    3)高斯双边模糊-是边缘保留额滤波方法,避免了边缘信息丢失,保留了图像轮廓不变。

    3. 实验

    filter results

     

    结论:从滤波的结果可以看出各种滤波算法对图像的作用非常不同,有些变化非常大,有些甚至跟原图一样。在实际应用时,应根据噪声的特点、期望的图像和边缘特征等来选择合适的滤波器,这样才能发挥图像滤波的最大优点。

     

     

    4. C++实现

    4.1均值滤波

    static void exchange(int& a, int& b)
    {    
        int t = 0;
        t = a;
        a = b;
        b = t;
    }
     
    static void bubble_sort(int* K, int lenth)
    {
        for (int i = 0; i < lenth; i++)
            for (int j = i + 1; j < lenth; j++)
            {
                if (K[i]>K[j])
                    exchange(K[i], K[j]);
            }
    }
    ///产生二维的高斯内核
    static cv::Mat generate_gassian_kernel(double u, double sigma, cv::Size size)
    {
        int width = size.width;
        int height = size.height;
        cv::Mat gassian_kernel(cv::Size(width, height), CV_64FC1);
        double sum = 0;
        double sum_sum = 0;
        for (int i = 0; i < width; i++)
            for (int j = 0; j < height; j++)
            {
                sum = 1.0 / 2.0 / CV_PI / sigma / sigma * exp(-1.0 * ((i - width / 2)*(i - width / 2) + (j - width / 2)*(j - width / 2)) / 2.0 / sigma / sigma);
                sum_sum += sum;
                gassian_kernel.ptr<double>(i)[j] = sum;
            }
        for (int i = 0; i < width; i++)
            for (int j = 0; j < height; j++)
            {
                gassian_kernel.ptr<double>(i)[j] /= sum_sum;
            }
        return gassian_kernel;
    }
    ///均值滤波
    void lmt_main_blur(cv::Mat& img_in, cv::Mat& img_out, int kernel_size)
    {
        img_out = img_in.clone();
        cv::Mat mat1;
        cv::copyMakeBorder(img_in, mat1, kernel_size, kernel_size, kernel_size, kernel_size, cv::BORDER_REPLICATE);
     
        int cols = mat1.cols;
        int rows = mat1.rows;
        int channels = img_out.channels();
        const uchar* const pt = mat1.ptr<uchar>(0);
        uchar* pt_out = img_out.ptr<uchar>(0);
     
        for (int i = kernel_size; i < rows - kernel_size; i++)
        {
            for (int j = kernel_size; j < cols - kernel_size; j++)
            {
                if (channels == 1)
                {
                    long long int sum_pixel = 0;
                    for (int m = -1 * kernel_size; m < kernel_size; m++)
                        for (int n = -1 * kernel_size; n < kernel_size; n++)
                        {
                            sum_pixel += pt[(i + m)*cols + (j + n)];
                        }
                    img_out.ptr<uchar>(i - kernel_size)[j - kernel_size] = (double)sum_pixel / (kernel_size*kernel_size * 4);
                }
                else if (channels == 3)
                {
                    long long int sum_pixel = 0;
                    long long int sum_pixel1 = 0;
                    long long int sum_pixel2 = 0;
                    for (int m = -1 * kernel_size; m < kernel_size; m++)
                        for (int n = -1 * kernel_size; n < kernel_size; n++)
                        {
                            sum_pixel += pt[((i + m)*cols + (j + n))*channels + 0];
                            sum_pixel1 += pt[((i + m)*cols + (j + n))*channels + 1];
                            sum_pixel2 += pt[((i + m)*cols + (j + n))*channels + 2];
                        }
                    img_out.ptr<uchar>(i - kernel_size)[(j - kernel_size)*channels + 0] = (double)sum_pixel / (double)(kernel_size*kernel_size * 4);
                    img_out.ptr<uchar>(i - kernel_size)[(j - kernel_size)*channels + 1] = (double)sum_pixel1 / (double)(kernel_size*kernel_size * 4);
                    img_out.ptr<uchar>(i - kernel_size)[(j - kernel_size)*channels + 2] = (double)sum_pixel2 / (double)(kernel_size*kernel_size * 4);
                }
            }
        }
     
    }
    ///中值滤波
    void lmt_median_blur(cv::Mat& img_in, cv::Mat& img_out, int kernel_size)
    {
        img_out = img_in.clone();
        cv::Mat mat1;
        cv::copyMakeBorder(img_in, mat1, kernel_size, kernel_size, kernel_size, kernel_size, cv::BORDER_REPLICATE);
     
        int cols = mat1.cols;
        int rows = mat1.rows;
        int channels = img_out.channels();
     
        cv::Mat mat[3];
        cv::Mat mat_out[3];
        cv::split(mat1, mat);
        cv::split(img_out, mat_out);
        for (int k = 0; k < 3; k++)
        {
            const uchar* const pt = mat[k].ptr<uchar>(0);
            uchar* pt_out = mat_out[k].ptr<uchar>(0);
            for (int i = kernel_size; i < rows - kernel_size; i++)
            {
                for (int j = kernel_size; j < cols - kernel_size; j++)
                {
                    long long int sum_pixel = 0;
                    int* K = new int[kernel_size*kernel_size * 4];
                    int ker_num = 0;
                    for (int m = -1 * kernel_size; m < kernel_size; m++)
                        for (int n = -1 * kernel_size; n < kernel_size; n++)
                        {
                            K[ker_num] = pt[(i + m)*cols + (j + n)];
                            ker_num++;
                        }
                    bubble_sort(K, ker_num);
                    mat_out[k].ptr<uchar>(i - kernel_size)[j - kernel_size] = K[ker_num / 2];
                }
            }
        }
        cv::merge(mat_out, 3, img_out);
    }
    ///高斯滤波
    void lmt_gaussian_blur(cv::Mat& img_src, cv::Mat& img_dst, cv::Size kernel_size)
    {
        img_dst = cv::Mat(cv::Size(img_src.cols, img_src.rows), img_src.type());
        int cols = img_src.cols;
        int rows = img_src.rows;
        int channels = img_src.channels();
        cv::Mat gassian_kernel = generate_gassian_kernel(0, 1, kernel_size);
        int width = kernel_size.width / 2;
        int height = kernel_size.height / 2;
        for (int i = height; i < rows - height; i++)
        {
            for (int j = width; j < cols - width; j++)
            {
                for (int k = 0; k < channels; k++)
                {
                    double sum = 0.0;
                    for (int m = -height; m <= height; m++)
                    {
                        for (int n = -width; n <= width; n++)
                        {
                            sum += (double)(img_src.ptr<uchar>(i + m)[(j + n)*channels + k]) * gassian_kernel.ptr<double>(height + m)[width + n];
                        }
                    }
                    if (sum > 255.0)
                        sum = 255;
                    if (sum < 0.0)
                        sum = 0;
                    img_dst.ptr<uchar>(i)[j*channels + k] = (uchar)sum;
                }
            }
        }
     
        
    }
    ///双边滤波
    void lmt_bilateral_filter(cv::Mat& img_in, cv::Mat& img_out, const int r, double sigma_d, double sigma_r)
    {
        int i, j, m, n, k;
        int nx = img_in.cols, ny = img_in.rows, m_nChannels = img_in.channels();
        const int w_filter = 2 * r + 1; // 滤波器边长  
     
        double gaussian_d_coeff = -0.5 / (sigma_d * sigma_d);
        double gaussian_r_coeff = -0.5 / (sigma_r * sigma_r);
        double  **d_metrix = new double *[w_filter];
        for (int i = 0; i < w_filter; ++i)
            d_metrix[i] = new double[w_filter];
        
        double r_metrix[256];  // similarity weight  
        img_out = cv::Mat(img_in.size(),img_in.type());
        uchar* m_imgData = img_in.ptr<uchar>(0);
        uchar* m_img_outData = img_out.ptr<uchar>(0);
        // copy the original image  
        double* img_tmp = new double[m_nChannels * nx * ny];
        for (i = 0; i < ny; i++)
            for (j = 0; j < nx; j++)
                for (k = 0; k < m_nChannels; k++)
                {
                    img_tmp[i * m_nChannels * nx + m_nChannels * j + k] = m_imgData[i * m_nChannels * nx + m_nChannels * j + k];
                }
     
        // compute spatial weight  
        for (i = -r; i <= r; i++)
            for (j = -r; j <= r; j++)
            {
                int x = j + r;
                int y = i + r;
     
                d_metrix[y][x] = exp((i * i + j * j) * gaussian_d_coeff);
            }
     
        // compute similarity weight  
        for (i = 0; i < 256; i++)
        {
            r_metrix[i] = exp(i * i * gaussian_r_coeff);
        }
     
        // bilateral filter  
        for (i = 0; i < ny; i++)
            for (j = 0; j < nx; j++)
            {
                for (k = 0; k < m_nChannels; k++)
                {
                    double weight_sum, pixcel_sum;
                    weight_sum = pixcel_sum = 0.0;
     
                    for (m = -r; m <= r; m++)
                        for (n = -r; n <= r; n++)
                        {
                            if (m*m + n*n > r*r) continue;
     
                            int x_tmp = j + n;
                            int y_tmp = i + m;
     
                            x_tmp = x_tmp < 0 ? 0 : x_tmp;
                            x_tmp = x_tmp > nx - 1 ? nx - 1 : x_tmp;   // 边界处理,replicate  
                            y_tmp = y_tmp < 0 ? 0 : y_tmp;
                            y_tmp = y_tmp > ny - 1 ? ny - 1 : y_tmp;
     
                            int pixcel_dif = (int)abs(img_tmp[y_tmp * m_nChannels * nx + m_nChannels * x_tmp + k] - img_tmp[i * m_nChannels * nx + m_nChannels * j + k]);
                            double weight_tmp = d_metrix[m + r][n + r] * r_metrix[pixcel_dif];  // 复合权重  
     
                            pixcel_sum += img_tmp[y_tmp * m_nChannels * nx + m_nChannels * x_tmp + k] * weight_tmp;
                            weight_sum += weight_tmp;
                        }
     
                    pixcel_sum = pixcel_sum / weight_sum;
                    m_img_outData[i * m_nChannels * nx + m_nChannels * j + k] = (uchar)pixcel_sum;
     
                } // 一个通道  
     
            } // END ALL LOOP  
        for (i = 0; i < w_filter; i++)
            delete[] d_metrix[i];
        delete[] d_metrix;
    }
     

    5. Opencv API实现

    opencv相关函数简介:

    双边滤波函数:bilateralFilter(InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace,int borderType=BORDER_DEFAULT )

       src待滤波图像

       dst滤波后图像

       d滤波器半径

       sigmaColor滤波器值域的sigma

       sigmaSpace滤波器空间域的sigma

       borderType边缘填充方式 BORDER_REPLICATE BORDER_REFLECT BORDER_DEFAULT BORDER_REFLECT_101BORDER_TRANSPARENT BORDER_ISOLATED

     

    均值滤波函数:blur(InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), intborderType=BORDER_DEFAULT );

       src待滤波图像

       dst滤波后图像

       ksize 均值滤波器的大小

    Piont(-1,-1)指中心

       anchor均值滤波器的锚点也就是模板移动点

       borderType边缘填充方式 BORDER_REPLICATE BORDER_REFLECT BORDER_DEFAULT BORDER_REFLECT_101BORDER_TRANSPARENT BORDER_ISOLATED

     

    高斯滤波函数:GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0,int borderType=BORDER_DEFAULT );

       src待滤波图像

       dst滤波后图像

       ksize 高斯滤波器的大小Size(x,y),x和y必须是整数且是奇数。

       sigmaX 高斯滤波器的x方向的滤波器高斯sigma

       sigmaY 高斯滤波器的y方向的滤波器高斯sigma

       borderType边缘填充方式 BORDER_REPLICATE BORDER_REFLECT BORDER_DEFAULT BORDER_REFLECT_101BORDER_TRANSPARENT BORDER_ISOLATED

     

    中值滤波函数:medianBlur(InputArray src, OutputArray dst, int ksize );

        src待滤波图像

        dst滤波后图像

        ksize 中值滤波器的大小

    函数演示:

    void bilateral_filter_show(void)
    {
        cv::Mat mat1 = cv::imread("F:\\CVlibrary\\obama.jpg", CV_LOAD_IMAGE_GRAYSCALE); //灰度图加载进来,BGR->HSV 然后取H参数
        if (mat1.empty())
            return;
        cv::imshow("原图像", mat1); 
        cv::Mat src = cv::imread("F:\\CVlibrary\\obama.jpg");
        cv::imshow("原始彩色图像", src);
        std::cout << "channel = " << mat1.channels() << std::endl;
        
        cv::Mat mat3;
        cv::bilateralFilter(src, mat3, 5, 50, 50,cv::BORDER_DEFAULT);
        cv::imshow("opencv给出的双边滤波器", mat3);
        cv::Mat mat4;
        cv::blur(src, mat4, cv::Size(3, 3));
        cv::imshow("均值滤波", mat4);
        cv::Mat mat5;
        cv::GaussianBlur(src, mat5, cv::Size(5, 5), 1,1);
        cv::imshow("高斯滤波器", mat5);
        cv::Mat mat6;
        cv::medianBlur(src, mat6, 3);
        cv::imshow("中值滤波", mat6); 
        cv::Mat mat7;
        lmt_gaussian_blur(src, mat7, cv::Size(5, 5));
        cv::imshow("my gaussian image",mat7);
     
        cv::waitKey(0);
    }

    高斯、中值、均值、双边滤波的效果

    #include "cv.h"
    #include "highgui.h"
    #include <iostream>
    
    using namespace std;
    using namespace cv;
    
    int main(int argc, char* argv[])
    {
            Mat src = imread("misaka.jpg");
            Mat dst;
    
            //参数是按顺序写的
    
            //高斯滤波
            //src:输入图像
            //dst:输出图像
            //Size(5,5)模板大小,为奇数
            //x方向方差
            //Y方向方差
            GaussianBlur(src,dst,Size(5,5),0,0);
            imwrite("gauss.jpg",dst);
            
            //中值滤波
            //src:输入图像
            //dst::输出图像
            //模板宽度,为奇数
            medianBlur(src,dst,3);
            imwrite("med.jpg",dst);
            
            //均值滤波
            //src:输入图像
            //dst:输出图像
            //模板大小
            //Point(-1,-1):被平滑点位置,为负值取核中心
            blur(src,dst,Size(3,3),Point(-1,-1));
            imwrite("mean.jpg",dst);
    
            //双边滤波
            //src:输入图像
            //dst:输入图像
            //滤波模板半径
            //颜色空间标准差
            //坐标空间标准差
            bilateralFilter(src,dst,5,10.0,2.0);//这里滤波没什么效果,不明白
            imwrite("bil.jpg",dst);
    
            waitKey();
    
            return 0;
    }
    展开全文
  • 本人转自 http://blog.csdn.net/haoji007/article/details/53911940图像处理中滤波和卷积是常用到的操作。很多人认为卷积就是滤波,两者并无区别,其实不然。两者在原理上相似,但是在实现的细节上存在一些区别。这...

    本人转自 http://blog.csdn.net/haoji007/article/details/53911940

    图像处理中滤波和卷积是常用到的操作。很多人认为卷积就是滤波,两者并无区别,其实不然。两者在原理上相似,但是在实现的细节上存在一些区别。这篇博文主要叙述这两者之间的区别。

    1、滤波

    简单来说,滤波操作就是图像对应像素与掩膜(mask)的乘积之和。

    比如有一张图片和一个掩膜,如下图:



    那么像素(i,j)的滤波后结果可以根据以下公式计算:

    其中G(i,j)是图片中(i,j)位置像素经过滤波后的像素值。

    当掩膜中心m5位置移动到图像(i,j)像素位置时,图像(i,j)位置像素称为锚点

    滤波步骤:

    1. 对原始图像的边缘进行某种方式的填充(一般为0填充)。
    2. 将掩膜划过整幅图像,计算图像中每个像素点的滤波结果。
    依照这个步骤,假设我们有一个二维矩阵I,掩膜M,则滤波的结果如下:


    滤波后的图像大小不变。



    2、卷积

    卷积的原理与滤波类似。但是卷积却有着细小的差别。
    卷积操作也是卷积核与图像对应位置的乘积和。但是卷积操作在做乘积之前,需要先将卷积核翻转180度,之后再做乘积。

    卷积步骤:
    1. 180度翻转卷积核。
    2. 不做边界填充,直接对图像进行相应位置乘积和。
    从以上步骤可以看出,如果卷积核不是中心对称的,那么卷积和滤波操作将会得到完全不一样的结果。另外,卷积操作会改变图像大小!

    由于卷积操作会导致图像变小(损失图像边缘),所以为了保证卷积后图像大小与原图一致,经常的一种做法是人为的在卷积操作之前对图像边缘进行填充。

    最后,关于卷积后图像尺寸的计算:假设原始图像为M*M,卷积核大小为N*N,边缘填充像素个数为pad,步长为stride。则卷积后图像的尺寸变为:m =(M-N+2*pad)/sride+1。
    展开全文
  • 图像处理中滤波和卷积是常用到的操作。很多人认为卷积就是滤波,两者并无区别,其实不然。两者在原理上相似,但是在实现的细节上存在一些区别。这篇博文主要叙述这两者之间的区别。 1、滤波 简单来说,滤波操作...

    图像处理中滤波和卷积是常用到的操作。很多人认为卷积就是滤波,两者并无区别,其实不然。两者在原理上相似,但是在实现的细节上存在一些区别。这篇博文主要叙述这两者之间的区别。

    1、滤波

    简单来说,滤波操作就是图像对应像素与掩膜(mask)的乘积之和。

    比如有一张图片和一个掩膜,如下图:

    那么像素(i,j)的滤波后结果可以根据以下公式计算:

    其中G(i,j)是图片中(i,j)位置像素经过滤波后的像素值。

    当掩膜中心m5位置移动到图像(i,j)像素位置时,图像(i,j)位置像素称为锚点。

    滤波步骤:

    1. 对原始图像的边缘进行某种方式的填充(一般为0填充)。
    2. 将掩膜划过整幅图像,计算图像中每个像素点的滤波结果。

    依照这个步骤,假设我们有一个二维矩阵I,掩膜M,则滤波的结果如下:

    滤波后的图像大小不变。

     

    2、卷积

    卷积的原理与滤波类似。但是卷积却有着细小的差别。

    卷积操作也是卷积核与图像对应位置的乘积和。但是卷积操作在做乘积之前,需要先将卷积核翻转180度,之后再做乘积。

    卷积步骤:

    1. 180度翻转卷积核。
    2. 不做边界填充,直接对图像进行相应位置乘积和。

    从以上步骤可以看出,如果卷积核不是中心对称的,那么卷积和滤波操作将得到完全不一样的结果。卷积操作会改变图像大小!

    由于卷积操作会导致图像变小(损失图像边缘),所以为了保证卷积后图像大小与原图一致,经常的一种做法是人为的在卷积操作之前对图像边缘进行填充。

    最后,关于卷积后图像尺寸的计算:假设原始图像为M*M,卷积核大小为N*N,边缘填充像素个数为pad,步长为stride。则卷积后图像的尺寸变为:m =(M-N+2*pad)/sride+1。

    转载:https://blog.csdn.net/haoji007/article/details/53911940

    展开全文
  • 图像处理中滤波(filtering)与卷积(convolution)的区别
  • 转自:openCV之滤波&amp;均值滤波(及代码实现):https://blog.csdn.net/weixin_37720172/article/details/72627543  在开始我们今天的博客之前,我们需要先了解一下什么是滤波: openCV之滤波&...
  • 图像滤波大多数用于图像的模糊处理和减小噪声(个人理解)。常见的滤波有:均值滤波,中值滤波,高斯滤波等。在这我主要介绍一下中值滤波,它对于处理椒盐噪声十分有效。下面我简单介绍下它的原理,以及我自己写的...
  • 图像处理 中值滤波与均值滤波 matlab算法实现
  • 图像处理滤波算法

    2016-06-30 15:03:31
    一、学习心得: 在我学习基本滤波算法原理的时候,因为刚接触不是很理解算法具体是怎样实现的,不过在学习了图像形态学之后,发现滤波算法其实很简单。所以在此建议初学者在...而在图像处理中滤波算法,处理的
  • 产生模糊冲击函数的模板,对图像尺寸进行延拓,在频域对图像进行模糊,对模糊后的图像叠加高斯噪声,逆滤波,维纳滤波
  • 而在数字图像处理中滤波可以分为空间域滤波和频率域滤波。这篇博文主要来学习下空间域滤波。空间域滤波机理 *空间滤波器由一个邻域(典型的是一个较小的矩形)构成,对该邻域所包围的像素按照一定的操作计算出目标...
  • OpenCV图像处理滤波

    2018-12-29 15:38:13
     即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。 二、图像滤波分类  大体上图像滤波可以分为...
  • 中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,中值滤波的基本原理是把数字图像或数字序列一点的值用该点的一个邻域各点值的中值代替,让周围的像素值接近的真实值,从而消除孤立的噪声...
  • 图像中的噪声 噪声的来源:数字图像的噪声主要产生于获取、传输图像的过程。在获取图像的过程,摄像机组件的运行情况受各种客观因素的影响,包括图像拍摄的环境条件和摄像机的传感元器件质量在内都有可能会对...
  • 数字图像处理的均值滤波,用于图像去噪。很完整的源代码
  • 数字图像处理维纳滤波Matlab代码分享,另外有高斯滤波Matlab代码,有需要的同学请点击关注查看
  • 基于MATLAB图像处理的中值滤波、均值滤波以及高斯滤波的实现与对比 1.背景知识 中值滤波法是一种非线性平滑技术,它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值. 中值滤波是基于排序...
  • import numpy as np import cv2 def convert_2d(r): r_ext = np.zeros((r.shape[0] * 2, r.shape[1] * 2)) for i in range(r.shape[0]): for j in range(r.shape[1]): r_ext[i][j] = r...
1 2 3 4 5 ... 20
收藏数 40,296
精华内容 16,118
关键字:

图像处理中的滤波