opencv(十)-图像滤波

索引目录

  • 1.功能
    • 1.1 图像平滑
    • 1.2 图像锐化
  • 2.空间滤波
    • 2.1 平滑滤波-去除高频分量,降噪
        • 2.1.1 方框滤波
        • 2.1.2 均值滤波
        • 2.1.3高斯滤波
          • 高斯核的计算
          • 高斯滤波
      • 2.1.4 非局部均值去噪声
      • 2.1.5 中值滤波
    • 2.2 边缘保留滤波
      • 2.2.1 高斯双边滤波
        • 参数选择
      • 2.2.2 均值迁移模糊(mean-shift blur)
      • 2.2.3 局部均方差模糊
      • 2.2.4 edgePreservingFilter
  • 2.2 锐化滤波(边缘检测)
      • 2.2.1 Roberts交叉梯度算子
      • 2.2.2 Prewitt算子
      • 2.2.3 sobel滤波器
      • 2.2.4 Isotropic Sobel算子
      • 2.2.5 Scharr算子
      • 2.2.6 Laplacian滤波器
      • 2.2.7 LOG算子
      • 2.2.8 Unsharpen Mask
    • 2.3 非微分边缘检测算子——Canny算子
  • 3.形态学滤波
  • 4.自定义滤波器
  • 5.频域滤波
    • 5.1频率域滤波器平滑图像
      • 5.1.1 理想低通滤波器
      • 5.1.2 巴特沃思低通滤波器
      • 5.1.3 高斯低通滤波器
    • 5.2 频率域滤波器锐化图像
  • 参考

1.功能

1.1 图像平滑

消除图像中混入的噪声,即低通滤波,噪声在图像中一般是高频信号图像滤波。
图像噪声产生的原因很复杂,有的可能是数字信号在传输过程中发生了丢失或者受到干扰,有的是成像设备或者环境本身导致成像质量不稳定,反应到图像上就是图像的亮度与颜色呈现某种程度的不一致性。从噪声的类型上,常见的图像噪声可以分为如下几种:

  • 椒盐噪声,
    是一种随机在图像中出现的稀疏分布的黑白像素点, 对椒盐噪声一种有效的去噪手段就是图像中值滤波
  • 高斯噪声/符合高斯分布
    一般会在数码相机的图像采集(acquisition)阶段发生,这个时候它的物理/电/光等各种信号都可能导致产生高斯分布噪声。
  • 均匀分布噪声
    均匀/规则噪声一般都是因为某些规律性的错误导致的

图像去噪声在OCR、机器人视觉与机器视觉领域应用开发中是重要的图像预处理手段之一,对图像二值化与二值分析很有帮助

1.2 图像锐化

为图像识别抽取出图像特征,一般为边缘纹理的特征,即高通滤波,图像中边缘和纹理细节是高频信号。

对滤波处理的要求:一是不能损坏图像的轮廓及边缘等重要信息;二是使图像清晰视觉效果好

2.空间滤波

线性滤波器的原始数据与滤波结果是一种算术运算,即用加减乘除等运算实现,如均值滤波器(模板内像素灰度值的平均值)、高斯滤波器(高斯加权平均值)等。由于线性滤波器是算术运算,有固定的模板,因此滤波器的转移函数是可以确定并且是唯一的(转移函数即模板的傅里叶变换)。
非线性滤波器的原始数据与滤波结果是一种逻辑关系,即用逻辑运算实现,如最大值滤波器、最小值滤波器、中值滤波器等,是通过比较一定邻域内的灰度值大小来实现的,没有固定的模板,因而也就没有特定的转移函数(因为没有模板作傅里叶变换),另外,膨胀和腐蚀也是通过最大值、最小值滤波器实现的。
实际上对图像进行二维傅立叶变换得到频谱图,就是图像梯度的分布图,当然频谱图上的各点与图像上各点并不存在一一对应的关系,即使在不移频的情况下也是没有。傅立叶频谱图上我们看到的明暗不一的亮点,实际上图像上某一点与邻域点差异的强弱,即梯度的大小,也即该点的频率的大小(可以这么理解,图像中的低频部分指低梯度的点,高频部分相反)。一般来讲,梯度大则该点的亮度强,否则该点亮度弱。这样通过观察傅立叶变换后的频谱图,也叫功率图,我们首先就可以看出,图像的能量分布,如果频谱图中暗的点数更多,那么实际图像是比较柔和的(因为各点与邻域差异都不大,梯度相对较小),反之,如果频谱图中亮的点数多,那么实际图像一定是尖锐的,边界分明且边界两边像素差异较大的。
平滑滤波器主要是使用邻域的均值(或者中值、积分)来代替模板中心的像素,消弱和邻域间的差别,以达到平滑图像和抑制噪声的目的;模糊图像,称为低通滤波器
锐化滤波器则使用邻域的微分作为算子,增大邻域间像素的差值,使图像的突变部分变的更加明显。锐化的作用是加强图像的边沿和轮廓,通常也成为高通滤波器。

2.1 平滑滤波-去除高频分量,降噪

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

“平滑处理“(smoothing)也称“模糊处理”(bluring),通过滤波实现。平滑处理的用途有很多,最常见的是用来减少图像上的噪点或者失真。在涉及到降低图像分辨率时,平滑处理是非常好用的方法。平滑滤波是低频增强的空间域滤波技术。它的目的有两类:一类是模糊;另一类是消除噪音。
比如高斯滤波,低通就是模糊,高通就是锐化。

2.1.1 方框滤波

boxFilter()

信号或者图像的能量大部分集中在低频和中频段,而在高频段,有用的信息常常会被噪声淹没,因此,为了抑制噪声,改善图像质量,便于更高层次的处理,必须对图像进行去噪预处理。
方框滤波归一化(normalized)就是把要处理的量都缩放到一个范围内,比如(0,1),以便统一处理和直观量化。均值滤波是方框滤波归一化的特例。
非归一化(Unnormalized)的方框滤波用于计算每个像素邻域内的积分特性,比如密集光流算法中用到的图像倒数的协方差矩阵
如果我们要在可变的窗口中计算像素总和,可以使用integral()函数。

2.1.2 均值滤波

blur()//归一化后的方框滤波。blur函数内部中调用了boxFilter

它不能很好地保护图像细节,在图像去噪的同时也破坏了图像的细节部分,从而使图像变得模糊,不能很好地去除噪声点。易收到噪声的干扰,不能完全消除噪声,只能相对减弱噪声。

2.1.3高斯滤波

高斯噪声通常是因为不良照明和高温引起的传感器噪声。通常在RGB图像中,显现比较明显。

高斯核的计算

在这里插入图片描述

    getGaussianKernel()//获得一维的高斯核
    //获得二维的高斯核
    Mat kernelX = getGaussianKernel(3, 1);  
    Mat kernelY = getGaussianKernel(3, 1);
    Mat G = kernelX * kernelY.t();
createGaussianKernels()代码中的公式,ksize = round(2 * 3 * sigma + 1) | 1; 注意与1按位或,是保证结果为奇数.

opencv(十)-图像滤波_第1张图片

//getGaussianKernel() 源码分析
cv::Mat cv::getGaussianKernel( int n, double sigma, int ktype )
{
    const int SMALL_GAUSSIAN_SIZE = 7;
    //定义了固定的filter即Kernels.
    static const float small_gaussian_tab[][SMALL_GAUSSIAN_SIZE] =
    {
        {1.f},
        {0.25f, 0.5f, 0.25f},
        {0.0625f, 0.25f, 0.375f, 0.25f, 0.0625f},
        {0.03125f, 0.109375f, 0.21875f, 0.28125f, 0.21875f, 0.109375f, 0.03125f}
    };
//对滤波器的类型进行判断,1,尺寸为奇数;2,尺寸小于等于7;3.sigma小于等于0(注)
    const float* fixed_kernel = n % 2 == 1 && n <= SMALL_GAUSSIAN_SIZE && sigma <= 0 ?
        small_gaussian_tab[n>>1] : 0;
//前文注释中介绍了,Kernels的数据类型为float,double也是ok的.
    CV_Assert( ktype == CV_32F || ktype == CV_64F );
    Mat kernel(n, 1, ktype);
    float* cf = kernel.ptr<float>();
    double* cd = kernel.ptr<double>();
//确定sigma,如果sigma > 0,ok,不用修改;否则按照公式计算(注)
    double sigmaX = sigma > 0 ? sigma : ((n-1)*0.5 - 1)*0.3 + 0.8;
    double scale2X = -0.5/(sigmaX*sigmaX);//高斯公式
    double sum = 0;
 
    int i;
    for( i = 0; i < n; i++ )
    {
        double x = i - (n-1)*0.5;
        //如果fixed_kernel为真,也就是符合上文中的3个条件,则区固定的系数;否则按照高斯公式计算
        //后续归一化时系数会被去掉,所以会省略系数的计算,只计算指数级exp(scale2X*x*x)
        double t = fixed_kernel ? (double)fixed_kernel[i] : std::exp(scale2X*x*x);
        //对kernels进行归一化
        if( ktype == CV_32F )
        {
            cf[i] = (float)t;
            sum += cf[i];
        }
        else
        {
            cd[i] = t;
            sum += cd[i];
        }
    }
 
    sum = 1./sum;
    for( i = 0; i < n; i++ )
    {
        if( ktype == CV_32F )
            cf[i] = (float)(cf[i]*sum);
        else
            cd[i] *= sum;
    }
    return kernel;
}

OpenCV认为当图像类型为CV_8U的时候能量集中区域为3 * sigma,其他类型图像的能量集中区域为4*sigma.
这样计算出来的模板有两种形式:小数和整数。
小数形式的模板,就是直接计算得到的值,没有经过任何的处理;
整数形式的,则需要进行归一化处理,将模板左上角的值归一化为1,下面会具体介绍。使用整数的模板时,需要在模板的前面加一个模板系数和的倒数。

高斯滤波
void GaussianBlur(InputArray src,OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, intborderType=BORDER_DEFAULT )

ksize.width和ksize.height可以不同,但他们都必须为正数和奇数。或者,它们可以是零的,它们都是由sigma计算而来。若sigmaY为零,就将它设为sigmaX,如果sigmaX和sigmaY都是0,那么就由ksize.width和ksize.height计算出来。最好是把第三个参数Size,第四个参数sigmaX和第五个参数sigmaY全部指定到。

高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到,消除高斯噪声。高斯滤波最有用的滤波操作,但是效率往往不是最高的。也用于计算机视觉算法中的预先处理阶段,以增强图像在不同比例大小下的图像效果(参见尺度空间表示以及尺度空间实现)。高斯平滑滤波器对于抑制服从正态分布的噪声非常有效。对图像进行平滑的同时,同时能够更多的保留图像的总体灰度分布特征。

高斯滤波的重要两步就是先找到高斯模板然后再进行卷积。
因此可以总结:
(1)在核大小固定的情况下,sigma值越大,权值分布越平缓。生成的模板的各个系数相差就不是很大,比较类似均值模板,对图像的平滑效果比较明显。
(2)在核大小固定的情况下,sigma值越小,权值分布越突起。因此,邻域各个点的值对输出值的影响越小,图像变化也越小。假如中心点权值为1,其他点权值为0,那么最终结果是图像没有任何变化。
(3)sigma固定时,核越大图像越模糊。
(4)sigma固定时,核越小图像变化越小。

2.1.4 非局部均值去噪声

与常用的双线性滤波、中值滤波等利用图像局部信息来滤波不同的是,它利用了整幅图像来进行去噪,以图像块为单位在图像中寻找相似区域,再对这些区域求平均,能够比较好地去掉图像中存在的高斯噪声。在提出这个算法的文献中,这个区域是整幅图像!与我们以前学习的平滑技术相比这种算法要消耗更多的时间,但是结果很好。对于彩色图像,要先转换到 CIELAB 颜色空间,然后对 L 和 AB 成分分别去噪。

//使用对象为灰度图
CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, float h = 3,
                                        int templateWindowSize = 7, int searchWindowSize = 21);
 
 src   //  必须为U8
 h     // Weight decay parameter
 templateWindowSize = 7, // Size of patches used for comparison
 searchWindowSize   = 21 // Maximum patch distance to consider

//使用对象为彩色图 
CV_EXPORTS_W void fastNlMeansDenoisingColored( InputArray src, OutputArray dst,
                                               float h = 3, float hColor = 3,
                                               int templateWindowSize = 7, int searchWindowSize = 21);
 
   src   // Input image 必须为U8C3
   h                  = 3, // Luminosity weight decay parameter
   hColor             = 3, // Color weight decay parameter

//适用于短时间的图像序列(灰度图像)  
CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, OutputArray dst,
                                             int imgToDenoiseIndex, int temporalWindowSize,
                                             float h = 3, int templateWindowSize = 7, int searchWindowSize = 21);
 
  srcImgs// 噪声帧的列表
  imgToDenoiseIndex,      // 设定那些帧需要去噪
  temporalWindowSize,     // 设置用于去噪的相邻帧的数目,它应该是一个奇数,中间的帧就是要去噪的帧
  h                  = 3, // Weight decay parameter
  templateWindowSize = 7, // Size of comparison patches
  searchWindowSize   = 21 // Maximum patch distance
//适用于短时间的图像序列(彩色图像)  
CV_EXPORTS_W void fastNlMeansDenoisingColoredMulti( InputArrayOfArrays srcImgs, OutputArray dst,
                                                    int imgToDenoiseIndex, int temporalWindowSize,
                                                    float h = 3, //决定过滤器强度。h 值高可以很好的去除噪声,但也会把图像的细节抹去。(取 10 的效果不错) 
                                                    float hColor = 3,
                                                    int templateWindowSize = 7, int searchWindowSize = 21);
 
hColor             = 3, // Weight decay param for color

2.1.5 中值滤波

对噪声不是那么敏感,能够较好的消除对于斑点噪声和椒盐噪声,又能保留图像边缘细节,但是容易导致图像的不连续性。但是中值滤波花费的时间是均值滤波的5倍以上。

void medianBlur( InputArray src, OutputArray dst, int ksize );

一般采用奇数点的邻域来计算中值,但如果像素点数为偶数时,中值就取排序像素中间两点的平均值

2.2 边缘保留滤波

无论是均值还是高斯都是属于模糊卷积,它们都有一个共同的特点就是模糊之后图像的边缘信息不复存在,受到了破坏。我们今天介绍的滤波方法有能力通过卷积处理实现图像模糊的同时对图像边缘不会造成破坏,滤波之后的输出完整的保存了图像整体边缘(轮廓)信息,我们称这类滤波算法为边缘保留滤波算法(EPF)

2.2.1 高斯双边滤波

结合图像的空间领近度和像素值相似度的一种折中处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。具有简单、非迭代、局部的特点,可以做边缘保存(edge preserving),拥有着美颜的效果。缺点是,保存了过多的高频信息,对彩色图像里的高频噪声,不能够干净的滤掉,只能够对于低频信息进行较好的滤波。双边滤波器的效率不是太高,花费的时间相较于其他滤波器而言也比较长。
高斯模糊是考虑图像空间位置对权重的影响,但是它没有考虑图像像素分布对图像卷积输出的影响,双边模糊考虑了像素值分布的影响,对像素值空间分布差异较大的进行保留从而完整的保留了图像的边缘信息。
在这里插入图片描述
权重系数w(i,j,k,l)是定义域核和值域核的乘积
在这里插入图片描述
定义域核由几何空间距离决定滤波器系数,是高斯模板
在这里插入图片描述
其中(xi,yi)为当前点位置,(xc,yc)为中心点的位置,sigma为空间域标准差。
值域核,是以灰度级的差值作为函数系数生成的模板
在这里插入图片描述
其中gray(xi,yi)为当前点灰度值,gray(xc,yc)为中心点灰度值,sigma为值域标准差。
在图像的平坦区域,像素值变化很小,对应的像素范围域权重接近于1,此时空间域权重起主要作用,相当于进行高斯模糊;在图像的边缘区域,像素值变化很大,像素范围域权重变大,从而保持了边缘的信息。
opencv(十)-图像滤波_第2张图片

void bilateralFilter( InputArray src, OutputArray dst, 
int d,//过滤过程中每个像素领域的直径,如果这个值是非正数,则函数会从第五个参数sigmaSpace计算该值。
double sigmaColor, //颜色空间滤波器的sigma值。这个参数越大,表明该像素领域内有更宽广的颜                  色会被混合到一起,产生较大的半相等颜色区域
double sigmaSpace,//坐标空间中滤波器的sigma值,坐标空间的标注方差。这个数值越大,表明越远的像素会相互影响,从而使更大的区域足够相似的颜色获取相同的颜色。当d>0时,d指定了邻域大小且与sigmaSpace无关,否则d正比于sigmaSpace.
int borderType=BORDER_DEFAULT );

对于简单的滤波而言,可以将两个sigma值设置成相同的值,如果值<10,则对滤波器影响很小,如果值>150则会对滤波器产生较大的影响,会使图片看起来像卡通。

参数选择

空间域sigma选取:其中核大小通常为sigma的6sigma + 1。因为离中心点3sigma大小之外的系数与中点的系数只比非常小,可以认为此之外的点与中心点没有任何联系,及权重系数为0.OpenCV参考文档内容如下:“对应高斯参数的 Gaussian sigma (标准差). 如果为零,则标准差由下面的核尺寸计算: sigma = (n/2 - 1)*0.3 + 0.8, 其中 n=param1 对应水平核,n=param2对应垂直核.”
值域sigma选取:灰度差△g = abs(gray(xi,yi)- gray(xc,yc)),忽略常数的影响,因此其函数可以简化为:
在这里插入图片描述
Sigma越大,边缘越模糊,极限情况为simga无穷大,值域系数近似相等(忽略常数时,将近为exp(0)= 1),与高斯模板(空间域模板)相乘后可认为等效于高斯滤波。
Sigma越小,边缘越清晰,极限情况为simga无限接近0,值域系数近似相等(接近exp(-∞) = 0),与高斯模板(空间域模板)相乘后,可近似为系数皆相等,等效于源图像。
opencv(十)-图像滤波_第3张图片

2.2.2 均值迁移模糊(mean-shift blur)

均值迁移模糊是图像边缘保留滤波算法中一种,经常用来在对图像进行分水岭分割之前去噪声,可以大幅度提升分水岭分割的效果。均值迁移模糊的主要思想如下:
就是在图像进行开窗的时候同样,考虑像素值空间范围分布,只有符合分布的像素点才参与计算,计算得到像素均值与空间位置均值,使用新的均值位置作为窗口中心位置继续基于给定像素值空间分布计算均值与均值位置,如此不断迁移中心位置直到不再变化位置(dx=dy=0),但是在实际情况中我们会人为设置一个停止条件比如迁移几次,这样就可以把最后的RGB均值赋值给中心位置。

opencv(十)-图像滤波_第4张图片

以输入图像上src上任一点P0为圆心,建立物理空间上半径为sp,色彩空间上半径为sr的球形空间,物理空间上坐标为x、y,色彩空间上坐标为R、G、B(或HSV),构成一个5维的向量空间。
其中物理空间的范围x和y是图像的长和宽,色彩空间的范围R、G、B分别是0~255。
类比于3 x 3卷积窗口的默认值为[-1, 0, 1],我们可以对图像的空间窗口和颜色值窗口计算均值,得到dx和dy,以及新的RGB颜色值。
opencv(十)-图像滤波_第5张图片

pyrMeanShiftFiltering(	
InputArray 	src,
OutputArray 	dst,
double 	sp,
double 	sr,
int 	maxLevel = 1,
TermCriteria  termcrit = 
TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 5, 1) 
)

2.2.3 局部均方差模糊

https://blog.csdn.net/lz0499/article/details/77148182

2.2.4 edgePreservingFilter

opencv(十)-图像滤波_第6张图片
高斯双边与mean shift均值在计算时候使用五维向量是其计算量大速度慢的根本原因,无法实时实现图像边缘保留滤波,限制了它们的使用场景,OpenCV中还实现了一种快速的边缘保留滤波算法,通过等价变换到低纬维度空间,实现了数据降维与快速计算。

void cv::edgePreservingFilter(
InputArray src,
OutputArray dst,
int flags = 1,
float sigma_s = 60,
float sigma_r = 0.4f 
)		
//其中sigma_s的取值范围为0~200, sigma_r的取值范围为0~1
//当sigma_s取值不变时候,sigma_r越大图像滤波效果越明显
//当sigma_r取值不变时候,窗口sigma_s越大图像模糊效果越明显
//当sgma_r取值很小的时候,窗口sigma_s取值无论如何变化,图像双边滤波效果都不好!

2.2 锐化滤波(边缘检测)

锐化滤波去除低频分量,强化边缘、细节与周围的对比度,检测边缘特征。边缘检测的目的是标识数字图像中亮度变化明显的点,图像属性中的显著变化通常反映了属性的重要事件和变化。这些包括:深度上的不连续,表面方向的不连续,物质属性变化和场景照明变化。边缘检测是图像处理和计算机视觉中,尤其是特征提取中的一个研究领域。

在实际的图像分割中,往往只用到一阶和二阶导数,虽然原理上,可以用更高阶的导数,但是因为噪声的影响,在纯粹二阶的导数操作中就会出现对噪声的敏感现象,三阶以上的导数信息往往失去了应用价值。二阶导数还可以说明灰度突变的类型。在某些情况下,如灰度变化均匀的图像,只利用一阶导数可能找不到边界,此时二阶导数就能提供很有用的信息。二阶导数对噪声也比较敏感,解决的方法是先对图像进行平滑滤波,消除部分噪声,再进行边缘检测。不过,利用二阶导数信息的算法是基于过零检测的,因此得到的边缘点数比较少,有利于后继的处理和识别工作。获取一幅图像的梯度转化为:模板(Roberts、Prewitt、Sobel、Lapacian算子)对原图像进行卷积。
边缘类型:简单分为四种类型,阶跃型,屋脊型,斜坡型,脉冲型,其中阶跃型和斜坡型是类似的,只是变化的快慢不同。

边缘检测是图像处理中的一个难题,由于实际景物图像的边缘往往是各种类型的边缘及它们模糊化后结果的组合,且实际图像信号存在着噪声。噪声和边缘都属于高频信号,很难用频带做取舍。这就需要边缘检测来进行解决的问题了。边缘检测的基本方法有很多,对比如下:

  1 一阶微分算子
      1.1  Roberts交叉梯度算子
      1.2  Prewitt算子
      1.3  Sobel算子
      1.4  Isotropic Sobel算子
      1.5  Scharr算子
    2 二阶微分算子
        2.1  Laplacian算子
        2.2  LOG算子
     3 非微分边缘检测算子——Canny算子

opencv(十)-图像滤波_第7张图片

2.2.1 Roberts交叉梯度算子

Roberts 算子又称为交叉微分算子,它是基于交叉差分的梯度算法,通过局部差分计算检测边缘线条。常用来处理具有陡峭的低噪声图像,当图像边缘接近于正 45 度或负 45 度时,该算法处理效果更理想。其缺点是对边缘的定位不太准确,提取的边缘线条较粗。
图像可以看着是二维离散函数,对于图像的一阶微分其计算公式如下:
在x方向,∂f/∂x=f(x+1)−f(x).
在y方向,∂f/∂y=f(y+1)−f(y).

对于二阶微分有:
在x方向,∂2f/∂x2=f(x+1)+f(x−1)−2f(x).
在y方向,∂2f/∂y2=f(y+1)+f(y−1)−2f(y)

梯度:
在这里插入图片描述
平方和平方根需要大量的计算开销,所以使用绝对值来近似梯度幅值:
在这里插入图片描述
方向与 α (x, y) 正交:
在这里插入图片描述

对于 图像边缘处的灰度值来说,通常有两种突变形式:
边缘两边图像灰度差异较大,这就形成了灰度台阶。在台阶处,一阶微分和二阶微分的值都不为0.
边缘两边图像灰度变化不如台阶那么剧烈,会形成一个缓慢变换的灰度斜坡。在斜坡的起点和终点一阶微分和二阶微分的值都不为0,但是沿着斜坡一阶微分的值不为0,而二阶微分的值为0.
对于图像的边缘来说,通常会形成一个斜坡过度。一阶微分在斜坡处的值不为0,那么用其得到的边缘较粗;而二阶微分在斜坡处的值为0,但在斜坡两端值不为0,且值得符号不一样,这样二阶微分得到的是一个由0分开的一个像素宽的双边缘。也就说,二阶微分在增强图像细节方面比一阶微分好得多,并且在计算上也要比一阶微分方便。
一阶微分得到的图像边缘较粗,二阶微分得到的是较细的双边缘,所以在图像的边缘增强方面二阶微分算子的效果较好。
opencv(十)-图像滤波_第8张图片
OpenCV中并没有提供具体的函数,不过可以利用filter2D函数来实现
opencv(十)-图像滤波_第9张图片22 大小的模板在概念上很简单,但是他们对于用关于中心点对称的模板来计算边缘方向不是很有用,其最小模板大小为33, 3*3模板考虑了中心点对段数据的性质,并携带有关于边缘方向的更多信息。

void robert_grad(const Mat& src, Mat &dst)
{
    Mat grad_x, grad_y;

    Mat kernel_x = (Mat_<float>(2, 2) << -1, 0,0,1);
    Mat kernel_y = (Mat_<float>(2, 2) << 0, -1, 1, 0);
    
    filter2D(src, grad_x, CV_32F, kernel_x);
    filter2D(src, grad_y, CV_32F, kernel_y);

    //convertScaleAbs(grad_x, grad_x);
    //convertScaleAbs(grad_y, grad_y);
    //addWeighted(grad_x, 1, grad_y, 1, 0, dst);
    magnitude(grad_x, grad_y, dst);
    convertScaleAbs(dst, dst);
}

2.2.2 Prewitt算子

Prewitt 是一种图像边缘检测的微分算子,其原理是利用特定区域内像素灰度值产生的差分实现边缘检测。由于 Prewitt 算子采用 33 模板对区域内的像素值进行计算,而Robert算子的模板是 22,故 Prewitt 算子的边缘检测结果在水平方向和垂直方向均比 Robert 算子更加明显,Prewitt算子适合用来识别噪声较多,灰度渐变的图像。

opencv(十)-图像滤波_第10张图片

该算子与Sobel算子类似,只是权值有所变化,但两者实现起来功能还是有差距的,据经验得知Sobel要比Prewitt更能准确检测图像边缘。

2.2.3 sobel滤波器

Sobel算子是一种用于边缘检测的离散微分算子,它结合了高斯平滑和微分求导。该算子用于计算图像明暗程度近似值。根据图像边缘旁边明暗程度把该区域内超过某个数的特定点记为边缘。Sobel 算子在Prewitt算子的基础上增加了权重的概念,认为相邻点的距离远近对当前像素点的影响是不同的,距离越近的像素点对应当前像素的影响越大,从而实现图像锐化并突出边缘轮廓。
Sobel算子的边缘定位更准确,常用于噪声较多,灰度渐变的图像。Sobel算子是滤波算子的形式来提取边缘,X,Y方向各用一个模板,两个模板组合起来构成一个梯度算子。X方向模板对垂直边缘影响最大,Y方向模板对水平边缘影响最大。
Sobel算子算法的优点是计算简单,速度快。但是由于只采用了2个方向的模板,只能检测水平和垂直方向的边缘,因此这种算法对于纹理较为复杂的图像,其边缘检测效果就不是很理想。核比较小的时候准确度不高,对于3*3,Scharr滤波器同Sobel滤波器一样快,但精度更高。
以z5为对称中心(表示图像中的任一像素),有
opencv(十)-图像滤波_第11张图片
大核对导数有更好的逼近,因为小核对噪声更敏感。

void sobel_grad(const Mat &src, Mat &dst)
{
    Mat grad_x, grad_y;
    Sobel(src, grad_x, CV_32F, 1, 0);//如果src是8位的,那么dst至少是CV_16S保证不溢出
    Sobel(src, grad_y, CV_32F, 0, 1);
    //convertScaleAbs(grad_x, grad_x);
    //convertScaleAbs(grad_y, grad_y);
    //addWeighted(grad_x, 0.5, grad_y, 0.5, 0, dst);
    magnitude(grad_x, grad_y, dst);
    convertScaleAbs(dst, dst);//将图像类型转换为CV_8U
}

2.2.4 Isotropic Sobel算子

Sobel算子另一种形式是(Isotropic Sobel)算子,加权平均算子,权值反比零点与中心店的距离,当沿不同方向检测边缘时梯度幅度一致,就是通常所说的各向同性Sobel(Isotropic Sobel)算子。模板也有两个,一个是检测水平边沿的 ,另一个是检测垂直平边沿的 。各向同性Sobel算子和普通Sobel算子相比,它的位置加权系数更为准确,在检测不同方向的边沿时梯度的幅度一致。

2.2.5 Scharr算子

Scharr算子与Sobel算子的不同点是在平滑部分,这里所用的平滑算子是 1/16 [3, 10, 3],相比于 1/4[1, 2, 1],中心元素占的权重更重,这可能是相对于图像这种随机性较强的信号,领域相关性不大,所以邻域平滑应该使用相对较小的标准差的高斯函数,也就是更瘦高的模板。

由于Sobel算子在计算相对较小的核的时候,其近似计算导数的精度比较低,比如一个33的Sobel算子,当梯度角度接近水平或垂直方向时,其不精确性就越发明显。Scharr算子同Sobel算子的速度一样快,但是准确率更高,尤其是计算较小核的情景,所以利用33滤波器实现图像边缘提取更推荐使用Scharr算子。

Scharr算子又称为Scharr滤波器,也是计算x或y方向上的图像差分,在OpenCV中主要配合Sobel算子的运算而存在的,下面对比一下Sobel算子和scharr算子的核函数对比:
  opencv(十)-图像滤波_第12张图片
当内核大小为 3 时, 以上Sobel内核可能产生比较明显的误差(毕竟,Sobel算子只是求取了导数的近似值)。 为解决这一问题,OpenCV提供了 Scharr 函数,但该函数仅作用于大小为3的内核。该函数的运算与Sobel函数一样快,但结果却更加精确

void Scharr(InputArray src, OutputArray dst, int ddepth, int dx, int dy, double scale=1, double delta=0, intborderType=BORDER_DEFAULT )

等同于
在这里插入图片描述
注意:在进行Scharr算子处理之后,也需要调用convertScaleAbs() 函数计算绝对值,并将图像转换为8位图像进行显示。原因是sobel算子求导的话,白到黑是正数,但是黑到白就是负数了,所有的负数都会被截断为0,所以要取绝对值。

2.2.6 Laplacian滤波器

Laplace算子是一种各向同性算子,二阶微分算子,具有旋转不变性。在只关心边缘的位置而不考虑其周围的象素灰度差值时比较合适。Laplace算子对孤立象素的响应要比对边缘或线的响应要更强烈,因此只适用于无噪声图象。存在噪声情况下,使用Laplacian算子检测边缘之前需要先进行低通滤波。所以,通常的分割算法都是把Laplacian算子和平滑算子结合起来生成一个新的模板。
二阶微分算子Laplace得到的边缘则较细,并且边缘是双边缘
opencv(十)-图像滤波_第13张图片
如果在图像中一个较暗的区域中出现了一个亮点,那么用拉普拉斯运算就会使这个亮点变得更亮。因为图像中的边缘就是那些灰度发生跳变的区域,所以拉普拉斯锐化模板在边缘检测中很有用。一般增强技术对于陡峭的边缘和缓慢变化的边缘很难确定其边缘线的位置。但此算子却可用二次微分正峰和负峰之间的过零点来确定,对孤立点或端点更为敏感,因此特别适用于以突出图像中的孤立点、孤立线或线端点为目的的场合。同梯度算子一样,拉普拉斯算子也会增强图像中的噪声,有时用拉普拉斯算子进行边缘检测时,可将图像先进行平滑处理。
由于Laplace算子对噪声敏感,会得到双边,并且并不能检测边缘的方向,其通常不用于直接的边缘检测,只是起到辅助作用。检测某像素实在边缘的亮的一侧还是暗的一侧,利用“零跨越”确定边缘的位置。
opencv(十)-图像滤波_第14张图片
这个滤波器实现了拉普拉斯算子,以90°为增量进行旋转的一个各向同性结果。要实现45°增幅的结果也是各向同性,需要变换。
opencv(十)-图像滤波_第15张图片
将原图像和拉普拉斯图像叠加在一起的简单方法,可以复原背景特性并保持拉普拉斯锐化处理的效果。
如果所使用的模板定义有负的中心系数,那么必须将原图像减去经拉普拉斯变换后的图像,而不是加上他,从而得到锐化后的结果。
由于拉普拉斯图像中即有正值又有负值,并且所有负值在显示时都被修剪为0,所以变换后的图像大部分都是黑色的。
拉式算子用来改善因扩散效应的模糊特别有效,因为它符合降制模型。扩散效应是成像过程中经常发生的现象。

  Laplacian算子一般不以其原始形式用于边缘检测,因为其作为一个二阶导数,Laplacian算子对噪声具有无法接受的敏感性;同时其幅值产生算边缘,这是复杂的分割不希望有的结果;最后Laplacian算子不能检测边缘的方向;所以Laplacian在分割中所起的作用包括:(1)利用它的零交叉性质进行边缘定位;(2)确定一个像素是在一条边缘暗的一面还是亮的一面;一般使用的是高斯型拉普拉斯算子(Laplacian of a Gaussian,LoG),由于二阶导数是线性运算,利用LoG卷积一幅图像与首先使用高斯型平滑函数卷积改图像,然后计算所得结果的拉普拉斯是一样的。所以在LoG公式中使用高斯函数的目的就是对图像进行平滑处理,使用Laplacian算子的目的是提供一幅用零交叉确定边缘位置的图像;图像的平滑处理减少了噪声的影响并且它的主要作用还是抵消由Laplacian算子的二阶导数引起的逐渐增加的噪声影响。

图像锐化处理的作用是使灰度反差增强,从而使模糊图像变得更加清晰。图像模糊的实质就是图像受到平均运算或积分运算,因此可以对图像进行逆运算,如微分运算能够突出图像细节,使图像变得更为清晰。由于拉普拉斯是一种微分算子,它的应用可增强图像中灰度突变的区域,减弱灰度的缓慢变化区域。因此,锐化处理可选择拉普拉斯算子对原图像进行处理,产生描述灰度突变的图像,再将拉普拉斯图像与原始图像叠加而产生锐化图像。

void cv::Laplacian  (  InputArray     src,
                           OutputArray     dst,
                           int     ddepth,
                           int     ksize = 3,//getDerivKernels()
                           double     scale = 1,
                           double     delta = 0,
                           int     borderType = BORDER_DEFAULT  )

注意,Laplacian算子其实主要是利用Sobel算子的运算,通过加上Sobel算子运算出的图像x方向和y方向上的导数,得到输入图像的图像锐化结果。同时,在进行Laplacian算子处理之后,还需要调用convertScaleAbs()函数计算绝对值,并将图像转换为8位图进行显示。
opencv(十)-图像滤波_第16张图片

2.2.7 LOG算子

    LOG算子首先对图像做高斯滤波,然后再求其拉普拉斯(Laplacian)二阶导数,根据二阶导数的锅零点来检测图像的边界,即通过检测滤波结果的零交叉(Zero  crossings)来获得图像或物体的边缘。

LOG算子综合考虑了对噪声的抑制和对边缘的检测两个方向,并且把Gauss平滑滤波器和Laplacian锐化滤波器结合了起来,先平滑掉噪声,再进行边缘检测,所以效果会更好。该算子与视觉生理中的数学模型相似,因此在图像处理领域中得到了广泛的应用。它具有抗干扰能力强,边界定位精度高,边缘连续性好,能有效提取对比度弱的边界等特点。
opencv(十)-图像滤波_第17张图片

# 先通过高斯滤波降噪
gaussian = cv2.GaussianBlur(img, (3, 3), 0)
 
# 再通过拉普拉斯算子做边缘检测
dst = cv2.Laplacian(gaussian, cv2.CV_16S, ksize=3)
LOG = cv2.convertScaleAbs(dst)

2.2.8 Unsharpen Mask

这种锐化的方法就是对原图像先做一个高斯模糊,然后用原来的图像减去一个系数乘以高斯模糊之后的图像,然后再把值Scale到0~255的RGB像素值范围之内。基于USM锐化的方法可以去除一些细小的干扰细节和噪声,比一般直接使用卷积锐化算子得到的图像锐化结果更加真实可信。

USM锐化公式表示如下:
(源图像– w*高斯模糊)/(1-w);其中w表示权重(0.1~0.9),默认为0.6

Mat blur_img, usm;
	GaussianBlur(src, blur_img, Size(0, 0), 25);
	addWeighted(src, 1.5, blur_img, -0.5, 0, usm);
	imshow("mask image", usm);

2.3 非微分边缘检测算子——Canny算子

https://www.cnblogs.com/wj-1314/p/9800272.html
Canny边缘检测是一种比较新的边缘检测算子,具有很好地边缘检测性能,该算子功能比前面几种都要好,但是它实现起来较为麻烦,Canny算子是一个具有滤波,增强,检测的多阶段的优化算子,其目标是找到一个最优的边缘检测解或找寻一幅图像中灰度强度变换最强的位置。最优边缘检测主要通过低错误率,高定位性和最小响应三个标准进行评价。Canny算子的实现步骤如下:
step1: 用高斯滤波器平滑图象;
step2: 计算图像中每个像素点的梯度强度和方向(用一阶偏导的有限差分来计算梯度的幅值和方向);
step3: 对梯度幅值进行非极大值抑制(Non-Maximum Suppression),以消除边缘检测带来的杂散响应;
step4: 用双阈值算法(Double-Threshold)检测来确定真实和潜在的边缘,通过抑制孤立的弱边缘最终完成边缘检测;

边缘检测通常是在保留原有图像属性的情况下,对图像数据规模进行缩减,提取图像边缘轮廓的处理方式。
(1)图象边缘检测必须满足两个条件:一能有效地抑制噪声;二必须尽量精确确定边缘的位置。
(2)根据对信噪比与定位乘积进行测度,得到最优化逼近算子。这就是Canny边缘检测算子。
(3)类似与Marr(LoG)边缘检测方法,也属于先平滑后求导数的方法。

3.形态学滤波

4.自定义滤波器

void cv::filter2D  ( InputArray  src,  
  OutputArray  dst,  
  int  ddepth,  
  InputArray  kernel,  
  Point  anchor = Point(-1,-1),  
  double  delta = 0,  
  int  borderType = BORDER_DEFAULT  
 )  

5.频域滤波

5.1频率域滤波器平滑图像

5.1.1 理想低通滤波器

5.1.2 巴特沃思低通滤波器

5.1.3 高斯低通滤波器

5.2 频率域滤波器锐化图像

https://blog.csdn.net/on2way/article/details/46981825
1)在空间域滤波中,平滑滤波器算法简单,处理速度快,但在降噪同时使图像产生模糊,特别是在边缘和细节处。中值滤波器对椒盐噪声抑制效果比较好,但对点、线等细节较多的图像却不太合适。低通滤波器对椒盐噪声过滤效果差,图像较为模糊。空间域滤波算法简单,处理速度较快,在锐化方面效果明显,线条突出。

2)在频域滤波中,去噪同时将会导致边缘信息损失,使图像边缘模糊,并且产生振铃效果。页域滤波算法复杂,计算速度慢,有微量振铃效果,图像平缓。
频域滤波较空域而言更为直观,频域下滤波器表达了一系列空域处理(平滑、锐化等)的本质,即对高于/低于某一特定频率的灰度变化信息予以滤除,而对其他的灰度变化息基本持.不变。这种直观性增加了频域滤波器设计的合理性,使得我们更容易设计出针对特定问题的频域。而想直接在空域中设计出一个能够完成滤波任务的滤波器(卷积模板)是相当困难的。

为了得到合适的空域滤波器,我们很自然地想到可以首先设计频域滤波器H(u,v)而后根据卷积定理,将H(u,v)反变换至空域后就得到了空域中滤波使用的卷积模板h(x,y),从而解决空域滤波器的设计难题。然而,直接反变换得到的空域卷积模板h(x,y)同H(u,v)等大,要计算这样大的模板与图像的卷积将是非常低效的。利用以全尺寸的空域滤波器h(x,y)为指导设计出的形状与之类似的小空域卷积模板,同样可以取得类似于频域滤波器H(u,v)的滤波效果。这就为从频域出发,最终设计出具有实用价值的空域模板提供了一种完美的解决方案。

http://ishero.net/OpenCV%E7%A6%BB%E6%95%A3%E5%82%85%E9%87%8C%E5%8F%B6%E5%8F%98%E6%8D%A2.html
https://blog.csdn.net/C2681595858/article/details/84487617
https://www.cnblogs.com/phoenixdsg/p/6949575.html?utm_source=itdadao&utm_medium=referral
https://zhuanlan.zhihu.com/p/148503348

参考

1.原文链接:https://blog.csdn.net/qq_30815237/article/details/86690190
2.原文链接:https://blog.csdn.net/poem_qianmo/article/details/22745559
3.原文链接:https://blog.csdn.net/piaoxuezhong/article/details/78302920?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-1&spm=1001.2101.3001.4242
4.原文链接:https://blog.csdn.net/Jfuck/article/details/8932978
5.原文链接:https://blog.csdn.net/zqx951102/article/details/82967360
6.原文链接:https://blog.csdn.net/lovetobelove/article/details/86618324
7.https://blog.csdn.net/cyf15238622067/article/details/87859887
8.https://www.cnblogs.com/wj-1314/p/9800272.html

你可能感兴趣的:(学习Opencv4.4.0)