作用: 在进行图像处理之前的预处理,降低图像的噪点,提高图像的平滑度。
公式:数学卷积
图像的各个像素点是一个离散的数据,然而数学卷积是一种线性连续的操作(求和动作),所以有叫做线性滤波。
g ( i , j ) = ∑ k , j f ( i + k , j + l ) h ( k , j ) g(i,j) = \sum_{k,j}{f(i+k,j+l)h(k,j)} g(i,j)=k,j∑f(i+k,j+l)h(k,j)
说明: i , j i,j i,j 表示图像的行和列 , f ( i , j ) f(i,j) f(i,j)就表示一幅图像。 k , j k,j k,j表示卷积核, h ( k , j ) h(k,j) h(k,j)表示卷积算子函数(或者叫掩膜);卷积核在图像上进行卷积操作其中卷积核中心位置坐标就是 ( i , j ) (i,j) (i,j),然后求卷积和与图像对应坐标点像素的乘积再进行相加求和(范围在 k , j k,j k,j)之间,产生一个新的像素值。 k , j k,j k,j 有称作卷积窗口大小,然后再将值再赋给 g g g 对应的坐标点( i , j i,j i,j) 得到一副新的图像。
卷积操作是在图像上从上到下,从左到右,依次进行线性卷积计算。
图例:
假设灰色区域是 6 X 6 的像素矩阵,黄色是 3 X 3 的卷积核。
卷积核在图像上从上到下,从左到右,进行卷积操作:
(卷积和覆盖下的每个像素值乘以它对应的卷积核系数,本例中卷积核有9个系数,则有9个乘积,把这9个乘积相加后得到的值除于9得到平均值赋给中心点(红色区域)),
每一次得到新的值赋给中心点的红色坐标点,然后移动一个像素位置进行下一卷积运算,再把值赋给中心红色的位置。整幅图像依次类推。
有一个问题是 3 X 3 的卷积核 边缘有一个像素处理不到,5 X 5 的卷积核就会有两个,7 X 7 就会有3个 … … 但是 OpenCv中有另外的边缘处理方法。
原理:1归一化盒子滤波(均值滤波):
K = 1 K w ⋅ K h [ 1 1 ⋯ 1 1 1 ⋯ 1 1 1 ⋯ 1 ⋮ ⋮ ⋱ ⋮ 1 1 ⋯ 1 ] K= \dfrac{1 }{K_w\cdot K_h}\begin{bmatrix} {1_{}}&{1_{}}&{\cdots}&{1_{}}\\ {1_{}}&{1_{}}&{\cdots}&{1_{}}\\ {1_{}}&{1_{}}&{\cdots}&{1_{}}\\ {\vdots}&{\vdots}&{\ddots}&{\vdots}\\ {1_{}}&{1_{}}&{\cdots}&{1_{}}\\ \end{bmatrix} K=Kw⋅Kh1⎣⎢⎢⎢⎢⎢⎡111⋮1111⋮1⋯⋯⋯⋱⋯111⋮1⎦⎥⎥⎥⎥⎥⎤
原理:2高斯滤波:
G 0 ( x , y ) = e − ( x − μ x ) 2 2 σ x 2 + − ( y − μ y ) 2 2 σ y 2 G_0(x,y)=e \dfrac{-(x-\mu_x)^2}{2\sigma_x^2} +\dfrac{-(y-\mu_y)^2}{2\sigma_y^2} G0(x,y)=e2σx2−(x−μx)2+2σy2−(y−μy)2
σ x , σ y : \sigma_x ,\sigma_y : σx,σy:用来调节高斯正太分布情况
均值模糊:
//
// 摘要:
// Smoothes image using normalized box filter
//
// 参数:
// src:
// The source image 源图像
//
// dst:
// The destination image; will have the same size and the same type as src 输出图像
//
// ksize:
// The smoothing kernel size 卷积核
//
// anchor:
// The anchor point. The default value Point(-1,-1) means that the anchor is at
// the kernel center 卷积核中心点位置 (-1,-1)是默认值也是中心点
//
// borderType:
// The border mode used to extrapolate pixels outside of the image 边缘处理类型
public static void Blur(InputArray src, OutputArray dst, Size ksize, Point? anchor = null, BorderTypes borderType = BorderTypes.Reflect101);
高斯模糊:
//
// 摘要:
// Blurs an image using a Gaussian filter.
// 使用高斯滤波器模糊图像
// 参数:
// src:
// input image; the image can have any number of channels, which are processed independently,
// but the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
// 源图像 通带任意 深度应该是CV_8U、CV_16U、CV_16S、CV_32F或CV_64F。
// dst:
// output image of the same size and type as src.
// 输出图像
// ksize:
// Gaussian kernel size. ksize.width and ksize.height can differ but they both must
// be positive and odd. Or, they can be zero’s and then they are computed from sigma*
// 卷积核 size(x,y):x,y必须是奇数且是正数
//
// sigmaX:
// Gaussian kernel standard deviation in X direction.
// X方向上的高斯核标准差。
// sigmaY:
// Gaussian kernel standard deviation in Y direction; if sigmaY is zero, it is set
// to be equal to sigmaX, if both sigmas are zeros, they are computed from ksize.width
// and ksize.height, respectively (see getGaussianKernel() for details); to fully
// control the result regardless of possible future modifications of all this semantics,
// it is recommended to specify all of ksize, sigmaX, and sigmaY.
// Y方向高斯核标准差;如果sigmaY为零,则设置它
// 要等于sigmaX,如果两个sigmas都是零,它们是从ksize.width计算出来的
// 和ksize。高度,分别(详见getGaussianKernel();完全
// 控制结果,而不考虑所有这些语义将来可能的修改,
// 建议指定所有的ksize、sigmaX和sigmaY。
// borderType:
// pixel extrapolation method 边缘类型处理方法
public static void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY = 0, BorderTypes borderType = BorderTypes.Reflect101);
static void Main(string[] args)
{
string imagePath = @"C:\Users\whx\Desktop\opcvImage\mmm.jpg";
TheMeanOfFuzzyAndGaussian(imagePath);
}
///
/// 均值模糊和高斯模糊
///
private static void TheMeanOfFuzzyAndGaussian(string path)
{
using (src = new Mat(path, ImreadModes.AnyColor | ImreadModes.AnyDepth))
using (Mat dst = new Mat())
{
Mat gauss = new Mat();
//注意:size 参数一定要是奇数 (均值模糊)
Cv2.Blur(src, dst, new Size(5,5), new Point(-1, -1));
//using(new Window("Gaussian Image",WindowMode.Normal,gauss))
using(new Window("DST Image",WindowMode.AutoSize,dst))
using (new Window("SRC Image", WindowMode.AutoSize, src))
{
Cv2.WaitKey(0);
}
}
}
上面使用均值模糊,卷积核大小:Size(5,5), 卷积核越大模糊程度越强。
还可以对 X 轴 或 Y轴方向指定模糊:
private static void TheMeanOfFuzzyAndGaussian(string path)
{
using (src = new Mat(path, ImreadModes.AnyColor | ImreadModes.AnyDepth))
using (Mat dst = new Mat())
{
Mat gauss = new Mat();
//注意:size 参数一定要是奇数 (均值模糊) Y 轴模糊
Cv2.Blur(src, dst, new Size(1,15), new Point(-1, -1));
//using(new Window("Gaussian Image",WindowMode.Normal,gauss))
using(new Window("DST Image",WindowMode.AutoSize,dst))
using (new Window("SRC Image", WindowMode.AutoSize, src))
{
Cv2.WaitKey(0);
}
}
}
private static void TheMeanOfFuzzyAndGaussian(string path)
{
using (src = new Mat(path, ImreadModes.AnyColor | ImreadModes.AnyDepth))
using (Mat dst = new Mat())
{
Mat gauss = new Mat();
//注意:size 参数一定要是奇数 (均值模糊)
Cv2.Blur(src, dst, new Size(11,11), new Point(-1, -1));
//高斯模糊
Cv2.GaussianBlur(src, gauss, new Size(11, 11), 11, 11);
using (new Window("Gaussian Image", WindowMode.Normal, gauss))
using (new Window("Blur Image", WindowMode.Normal, dst))
using (new Window("SRC Image", WindowMode.Normal, src))
{
Cv2.WaitKey(0);
}
}
}
高斯滤波应该比均值滤波处理更精细一点,但是我感觉在视觉上差不多!
自定义卷积核:
private static void TheMeanOfFuzzyAndGaussian(string path)
{
using (src = new Mat(path, ImreadModes.AnyColor | ImreadModes.AnyDepth))
using (Mat dst = new Mat())
{
//Mat gauss = new Mat();
////注意:size 参数一定要是奇数 (均值模糊)
//Cv2.Blur(src, dst, new Size(11,11), new Point(-1, -1));
////高斯模糊
//Cv2.GaussianBlur(src, gauss, new Size(11, 11), 11, 11);
//using (new Window("Gaussian Image", WindowMode.Normal, gauss))
InputArray arr = InputArray.Create(new float[3, 3] { { 0, -1, 0 }, { -1, 5, -1 }, { 0, -1, 0 } });
Cv2.Filter2D(src, dst, -1, arr, new Point(-1, -1), 0);
using (new Window("DST Image", WindowMode.Normal, dst))
using (new Window("SRC Image", WindowMode.Normal, src))
{
Cv2.WaitKey(0);
}
}
}