一:中值滤波
原理与作用:
前面一节实现的是均值滤波,是取卷积计算后的平均值,而中值滤波是取卷积计算的中间值,中值滤波的好处是对图像的椒盐噪声有很好的抑制作用,因为图像的椒盐噪点,是图像某一片区域像素的极大值或者极小值,使用中值滤波可以过滤掉这些噪点。
示例:
下图是一个 6* 8 的像素矩阵,卷积和为黄色部分 3*3大小。
卷积核的窗口所覆盖下的像素值:
211,109,233,234,111,189,178,191,230。九个值,所以中值就是 191这个像素值(9个像素的中间值),然后把它赋值给红色坐标位置。
尔均值就是:(211+109+233+234+111+189+178+191+230)/9=187.33
卷积的方法也是在源图上从上到下,从左到右,进行线性卷积。
中值滤波可以看出是对像素值统计排序,然后获取中间值,也称做统计排序滤波器。
也可以取最大值或者最小值进行滤波处理,叫做 :最大值滤波或最小值滤波。
二:双边滤波
原理与作用:
- 均值滤波无法克服边缘像素信息丢失的缺陷,原因均值滤波是基于平均权重的滤波处理。
- 高斯滤波克服了该缺陷,但是也无法完全避免,因为没有考虑像素值的不同。
- 高斯双边模糊(滤波) – 是边缘保留的滤波方法,避免了边缘的信息丢失,保留了图像的原有轮廓不不变。
(a ) 输入的图像 经过中间的(高斯)卷积核 卷积后输出(d),实现平滑效果。
卷积核有分为 (b)空域核: 就是卷积核中每个对应点上的权重,所有权重的和应该为1。(c)值域核 :要区分卷积的像素值,就是在某个像素值范围之外进行卷积计算,如果相差太大就不做处理,这样能保留图像的差异化,图像反应的信息特征更好的保留了。从输出(b)可以看出,高象素值和低像素值得到了平滑处理,而中间的差异化也得到了保留。
三:API
中值滤波:
//
// 摘要:
// Smoothes image using median filter
//
// 参数:
// src: 源图像
// The source 1-, 3- or 4-channel image. When ksize is 3 or 5, the image depth should
// be CV_8U , CV_16U or CV_32F. For larger aperture sizes it can only be CV_8U
//
// dst: 输出图像
// The destination array; will have the same size and the same type as src
//
// ksize: 卷积核 必须大于1 且是奇数
// The aperture linear size. It must be odd and more than 1, i.e. 3, 5, 7 ...
public static void MedianBlur(InputArray src, OutputArray dst, int ksize);
高斯双边滤波:
//
// 摘要:
// Applies bilateral filter to the image
//
// 参数:
// src: 源图像
// The source 8-bit or floating-point, 1-channel or 3-channel image
//
// dst: 输出图像
// The destination image; will have the same size and the same type as src
//
// d: 计算半径,在半径范围内的像素都会纳入计算,如果输入-1则根据sigmaSpace取值 《空域》
// The diameter of each pixel neighborhood, that is used during filtering. If it
// is non-positive, it's computed from sigmaSpace
//
// sigmaColor: 决定多少差值之内的像素会被计算 《值域》
// Filter sigma in the color space. Larger value of the parameter means that farther
// colors within the pixel neighborhood will be mixed together, resulting in larger
// areas of semi-equal color
//
// sigmaSpace: 如果 d 的值大于0则无效,否则根据它来计算 d 值
// Filter sigma in the coordinate space. Larger value of the parameter means that
// farther pixels will influence each other (as long as their colors are close enough;
// see sigmaColor). Then d>0 , it specifies the neighborhood size regardless of
// sigmaSpace, otherwise d is proportional to sigmaSpace
//
// borderType:
public static void BilateralFilter(InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, BorderTypes borderType = BorderTypes.Reflect101);
代码:
/// <summary>
/// 中值模糊和双边模糊
/// </summary>
private static void TheMedianAndBilateralFuzzy(string path)
{
using (src = new Mat(path, ImreadModes.AnyColor | ImreadModes.AnyDepth))
using (Mat dst = new Mat())
{
Mat gs = new Mat(src.Size(),src.Type());
//中值模糊
//参数 1: 输入 2:输出 3:ksize必须大于1且是奇数
Cv2.MedianBlur(src, dst, 5);
//高斯双边模糊
//参数 1:输入 2:输出 3:计算的半径,半径之内的像数都会被纳入计算,如果提供-1 则根据sigma space参数取值
//4:sigma color 决定多少差值之内的像素会被计算
//5:sigma space 如果d的值大于0则声明无效,否则根据它来计算d值
Cv2.BilateralFilter(src, gs, 15, 100, 5);
//InputArray kernel = InputArray.Create<float>( new float[3, 3]{ { 0,-1,0}, { -1,5,-1}, { 0,-1,0} });
//Cv2.Filter2D(gs, dst, -1, kernel, new Point(-1, -1), 0);
using(new Window("BilateralFilter Image", WindowMode.Normal,gs))
using (new Window("MedianBlur Image", WindowMode.Normal, dst))
using (new Window("SRC Image", WindowMode.Normal, src))
{
Cv2.WaitKey(0);
}
}
}