C++ openCV图像的卷积与滤波

文章目录

  • 图像的滤波
    • 均值滤波
    • 高斯滤波
    • 中值滤波
    • 双边滤波
  • 图像的卷积与算子
    • 自定义卷积核卷积
    • 常用算子
    • Sobel算子
    • 拉普拉斯算子

图像的滤波

滤波与卷积区别:卷积中称卷积核,滤波中称滤波器。卷积需要将卷积核翻转180度在卷积,而滤波不需要;在opencv中或者深度学习卷积层中,由于卷积核通常对称,因此并未翻转。如果不对称,卷积需要手动翻转卷积核。

在不考虑卷积核翻转下,两者是一样的。
卷积的实现过程:
1) 将核的锚点(中心点)放在要计算像素上,卷积核剩余的部分对应在图像相应的像素上。
2) 用卷积核中的系数和图像中相应的像素值相乘,并求和。
3) 将最终结果赋值给锚点对应的像素。
4) 通过将核在整个图像滑动,重复以上计算过程直到处理完所有的像素。
链接: 卷积算子的实现

滤波器、卷积核的大小都是奇数,如 3 , 5 ,7,没有偶数大小的卷积核,无法选取合适的锚点,计算十分困难。

使用的命名空间

#pragma once
#include 
#include 

using namespace std;
using namespace cv;

均值滤波

C++ openCV图像的卷积与滤波_第1张图片

src : 输入图像
dst : 输出图像,与输入相同尺寸、通道数
ksize : 均值模糊核的大小,通常3×3
anchor : 锚点,默认为核的中心
borderType : 图像外部的像素模式,一般不手动修改

测试代码:

//均值滤波
Mat m1 = imread(path3, 1);
Mat m2(m1.size(), m1.type());
//核大小为三,锚点为中心点
blur(m1, m2, Size(3,3) , Point(-1, -1));
namedWindow("truth image",WINDOW_FREERATIO);
namedWindow("blur image", WINDOW_FREERATIO);
//调整窗口大小
resizeWindow("truth image", 600, 400);
resizeWindow("blur image", 600, 400);
imshow("truth image", m1);
imshow("blur image", m2);
waitKey(0);

测试效果:(图像来源于网络,侵权请告知即删除)
C++ openCV图像的卷积与滤波_第2张图片


高斯滤波

C++ openCV图像的卷积与滤波_第3张图片

src : 输入图像
dst : 输出图像,与输入相同尺寸、通道数
kszie : 高斯核大小
sigmaX : X方向的高斯核标准偏差。
sigmaY :Y方向高斯核标准差;如果sigmaY为零,则设置为等于sigmaX;如果两个SIGMA都为零,则根据ksize计算。
borderType :使用默认值

//高斯滤波
Mat m3 = imread(path4, 1);
Mat m4(m3.size(), m3.type());
Mat m5(m3.size(), m3.type());
//X轴上更为模糊
GaussianBlur(m3, m4, Size(11,11), 8, 1);
//Y轴上更为模糊
GaussianBlur(m3, m5, Size(11,11), 1, 8);
namedWindow("truth image",WINDOW_FREERATIO);
namedWindow("GaussianBlur image X", WINDOW_FREERATIO);
namedWindow("GaussianBlur image Y", WINDOW_FREERATIO);
//调整窗口大小
resizeWindow("truth image", 600, 400);
resizeWindow("GaussianBlur image X", 600, 400);
resizeWindow("GaussianBlur image Y", 600, 400);
imshow("truth image", m3);
imshow("GaussianBlur image X", m4);
imshow("GaussianBlur image Y", m5);
waitKey(0);

测试效果:(图像来源于网络,侵权请告知即删除)


中值滤波

C++ openCV图像的卷积与滤波_第4张图片

src :输入图像
dst :输出图像,与输入相同尺寸、通道数
ksize :int类型,模糊的大小

使用与之前类似,模糊效果有所区别,不在赘述。

双边滤波

高斯滤波是一种低通滤波器,在滤除高频噪声的同时,也会将边缘(也是高频信息)模糊,结果为图像整体变得模糊。双边滤波则可以滤除高斯噪声的同时,保留图像的边缘信息。
链接: 双边滤波原理.
C++ openCV图像的卷积与滤波_第5张图片

src : 输入图像
dst : 输出图像,与输入相同尺寸、通道数
d : 过滤时像素的邻域直径,小于等于0时由sigmaSpace决定
sigmaColor : 在颜色空间中的过滤sigma。该参数的值越大,意味着像素邻域内的更多颜色将混合在一起,从而产生更大的半等色区域。值越大,图像越平滑、模糊。
sigmaSpace : 参数的值越大,意味着更远的像素会相互影响。

测试代码:

sigma的取值小于10几乎没有效果,大于150,效果明显。
双边滤波速度很慢。

Mat m6 = imread(path5, 1);
	Mat m7(m6.size(), m6.type());
	bilateralFilter(m6, m7, 0, 50, 60);
	imshow("truth image", m6);
	imshow("bilateralFilter image", m7);
	waitKey(0);

测试效果:(图像来源于网络,侵权请告知即删除)

高斯、均值滤波为线性滤波
中值、双边非线性
都为低通滤波,滤除高频噪声
滤波器尺寸越大图像越模糊


图像的卷积与算子

自定义卷积核卷积

C++ openCV图像的卷积与滤波_第6张图片

src : 输入图像
dst : 输出图像,与输入相同尺寸、通道数
ddepth : 输出图像深度,为负值时输出与原图像相同深度
kernel : 卷积核,
anchor : 锚点,默认卷积核中心
delta : 额外偏移,在卷积后直接与结果相加,默认0

Tips:
1.卷积需要翻转。opencv中的卷积不会翻转卷积核,而是直接进行卷积。如需翻转,需使用filp()函数翻转卷积核180度,在卷积或者滤波。
2.卷积核的大小最好为奇数,方便锚点定位。
3.卷积本身会缩小图像,但该函数根据边框选择方式,对边缘外部像素进行填充,卷积后图像大小不改变。
4.卷积后结果可能会溢出如大于255等,可在卷积前将卷积核归一化。

测试代码:

//2D卷积
	Mat m8 = imread(path4, 1);
	Mat m9;
	//自定义卷积核
	//[ 1 ,1 ,1 
	//  1 ,-8, 1
	// 1 ,1 ,1]
	Mat kernel = (Mat_<char>(3,3) << 1,1,1,1,-8,1,1,1,1 );
	cout << kernel;
	filter2D(m8, m9, -1, kernel,Point(-1,-1));
	namedWindow("truth image");
	namedWindow("filter image");
	imshow("truth image", m8);
	imshow("filter image", m9);
	waitKey(0);

测试效果:(图像来源于网络,侵权请告知即删除)

常用算子

Sobel算子计算图像的一阶导数(梯度),拉普拉斯算子计算图像的二阶导数。图像的像素变化越大,梯度越大,像素值不变化,梯度为0,算子可用于检测图像边缘。都为高通滤波器

Sobel算子

Sobel 算子是一种离散的微分算子,结合高斯平滑和微分求导运算。该算子利用局部差分寻找边缘(近似等于微分),计算所得的是一个梯度的近似值。可用于检测图像的边缘。
链接: Sobel算子原理
C++ openCV图像的卷积与滤波_第7张图片

src :输入图像
dst : 输出图像,与输入相同尺寸、通道数
ddepth : 输出图像的深度,负值时与原图像相同
dx : X轴方向的求导阶数,一阶导数即梯度
dy : Y轴方向的求导阶数
ksize : Sobel核的大小,必须为1,3,5或者7.
scale : 缩放因子,默认为1
delta :额外增量,默认为0

使用Sobel算子求图像的X和Y轴梯度时,可以直接将dx,dy设置为1,但效果较差;也可以如下分别求X和Y的梯度,在加权融合。

测试代码:

//Sobel
Mat m12 = imread(path, 1);
Mat m13 , m14;
//求X轴方向的梯度
Sobel(m12, m13, -1, 1, 0, 3);
//求Y轴方向的梯度
Sobel(m12, m14, -1, 0, 1, 3);
//将结果取绝对值
convertScaleAbs(m13 , m13);
convertScaleAbs(m14 , m14);
//X和Y轴梯度图像加权融合
Mat m15;
addWeighted(m13, 0.5, m14, 0.5, 0, m15, -1);
//显示
namedWindow("truth image");
namedWindow("sobel x image");
namedWindow("sobel y image");
namedWindow("sobel image");
imshow("truth image", m12);
imshow("sobel x image", m13);
imshow("sobel y image", m14);
imshow("sobel image", m15);
waitKey(0);

测试效果:(图像来源于网络,侵权请告知即删除)

openCV也提供Scharr()函数作为sobel改进版,他速度更快,更为精准,区别在于使用固定的卷积核,不在手动指定大小。

在这里插入图片描述

拉普拉斯算子

实现对图像的拉普拉斯变换,该函数使用Sobel算子计算X和Y的二阶导数。拉普拉斯算子是无方向性的,同时对X和Y检测,可用于检测图像边缘。拉普拉斯算子对图像中的噪声十分敏感,使用前最好使用高斯滤波滤除噪声,减少噪声干扰。

C++ openCV图像的卷积与滤波_第8张图片

src :输入图像
dst : 输出图像,与输入相同尺寸、通道数
ddepth : 输出图像的深度,负值时与原图像相同
ksize : 二阶导滤波器的大小,必须为正奇数
scale : 缩放因子,默认为1
delta :额外增量,默认为0

测试代码:未使用高斯滤波

//拉普拉斯
Mat m10 = imread(path, 1);
Mat m11;
Laplacian(m10, m11, -1, 3);
namedWindow("truth image");
namedWindow("laplace image");
imshow("truth image", m10);
imshow("laplace image", m11);
waitKey(0);

测试效果:(图像来源于网络,侵权请告知即删除)含有大量噪声

测试代码:先高斯滤波

//高斯+拉普拉斯
Mat m10 = imread(path, 1);
Mat m11G , m11P;
GaussianBlur(m10, m11G, Size(3, 3), 5, 0);
Laplacian(m11G, m11P, -1, 3);
namedWindow("truth image");
namedWindow("laplace image");
imshow("truth image", m10);
imshow("laplace image", m11P);
waitKey(0);

测试结果:使用高斯滤波在使用拉普拉斯算子,可以减少噪声的干扰

文章内容有误或可改正地方,可私信,会即使修改。

你可能感兴趣的:(OpenCV451,opencv,c++,计算机视觉)