基于C++的OpenCV4入门基础–图像梯度图

不管现实多么惨不忍睹,都要持之以恒地相信,这只是黎明前短暂的黑暗而已。不要惶恐眼前的难关迈不过去,不要担心此刻的付出没有回报,别再花时间等待天降好运。真诚做人,努力做事!你想要的,岁月都会给你。基于C++的OpenCV4入门基础–图像梯度图,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

1,空间域锐化滤波(高通滤波)
图像模糊通过平滑(加权平均)来实现,类似于积分运算。图像锐化则通过微分运算(有限差分)实现,使用一阶微分或二阶微分都可以得到图像灰度的变化值。

图像锐化的目的是增强图像的灰度跳变部分,使模糊的图像变得清晰。图像锐化也称为高通滤波,通过和增强高频,衰减和抑制低频。图像锐化常用于电子印刷、医学成像和工业检测。

图像梯度提取方法简单直接,能够有效的描述图像的原始状态,因此发展出多种图像梯度算子:Roberts、Prewitt、Sobel、Laplacian、Scharr。

2,图像梯度
思考,清晰图像和模糊图像之间的差别是什么?
从逻辑上考虑,图像模糊是因为图像中物体的轮廓不明显,轮廓边缘灰度变化不强烈,层次感不强造成的,那么反过来考虑,轮廓边缘灰度变化明显些,层次感强些是不是图像就更清晰些呢。
那么,这种灰度变化明显不明显怎样去定义呢?
我们学过微积分,知道微分就是求函数的变化率,即导数(梯度),那么对于图像来说,可不可以用微分来表示图像灰度的变化率呢,当然是可以的,图像就是函数嘛。
在这里插入图片描述
3,常见梯度算子
Sobel算子:

CV_EXPORTS_W void Sobel( InputArray src, OutputArray dst, int ddepth,
                         int dx, int dy, int ksize = 3,
                         double scale = 1, double delta = 0,
                         int borderType = BORDER_DEFAULT );

参数说明:
src:输入图像,灰度图像,不适用彩色图像
dst:输出图像,大小和类型与 src 相同
ddepth:输出图片的数据深度,由输入图像的深度进行选择
dx:x 轴方向导数的阶数,1 或 2
dy:y 轴方向导数的阶数,1 或 2
ksize:Sobel 卷积核的大小,可选的取值为:1/3/5/7,ksize=-1 时使用 Scharr 算子运算
scale:缩放比例因子,可选项,默认值为 1
delta:输出图像的偏移量,可选项,默认值为 0
borderType:边界扩充的类型,注意不支持对侧填充(BORDER_WRAP)

Sobel 算子是一种离散的微分算子,是高斯平滑和微分求导的联合运算,抗噪声能力强。
Sobel 梯度算子利用局部差分寻找边缘,计算得到梯度的近似值。先计算水平、垂直方向的梯度 G x = k x ∗ s r c , G y = k y ∗ s r c 再求总梯度 $ G = \sqrt{G_x2+G_y2}$ 。编程实现时,可以用绝对值近似平方根: G = ∣ G x ∣ + ∣ G y ∣
Sobel 梯度算子是由平滑算子和差分算子卷积得到,Sobel 梯度算子的卷积核为:
在这里插入图片描述
此外,为了处理微分运算导致的数据异常(超出 [0,255]),OpenCV 提供了 cv.convertScaleAbs 进行饱和运算(saturate): dst=saturate(src∗α+beta)。
函数说明:

cv.convertScaleAbs(src, dst, alpha, beta)

参数说明:
src:输入图像,可以是灰度图像,也可以是多通道的彩色图像
dst:输出图像,大小和类型与 src 相同
alpha:调节系数,可选项,默认值为 1
beta:亮度调节,可选项,默认值为 0

Scharr算子:(可以看做Sobel增强)

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

在这里插入图片描述
Robot算子:
在这里插入图片描述
图像梯度:(L2和L1)
在这里插入图片描述
在这里插入图片描述
各种算子的应用,选择方法:
(1)Robot算子是轻量级的,当我们需要提取的图像边缘质量较好,而且主要是想提取主要边缘的时候适用;
(2)Sobel算子是比Robot稍好的算子;
(3)Scharr算子是更强烈的算子,当我们需要提取的图像边缘质量不佳的时候适用

3,代码示例参考

	Mat src = imread("F:/code/images/ttt.png");
	if (src.empty()) {
		printf("fail to read");
		return -1;
	}
	namedWindow("input", WINDOW_AUTOSIZE);
	imshow("input", src);

	// robot gradient 计算
	Mat robot_x = (Mat_<int>(2, 2) << 1, 0, 0, -1);
	Mat robot_y = (Mat_<int>(2, 2) << 0, 1, -1, 0);

	Mat grad_x, grad_y;
	filter2D(src, grad_x, CV_32F, robot_x, Point(-1, -1), 0, BORDER_DEFAULT);
	filter2D(src, grad_y, CV_32F, robot_y, Point(-1, -1), 0, BORDER_DEFAULT);
	convertScaleAbs(grad_x, grad_x);
	convertScaleAbs(grad_y, grad_y);
	Mat result;
	add(grad_x, grad_y, result);//L1梯度
	imshow("robot gradient", result);

	// sobel and scharr
	Sobel(src, grad_x, CV_32F, 1, 0);
	Sobel(src, grad_y, CV_32F, 0, 1);
	convertScaleAbs(grad_x, grad_x);
	convertScaleAbs(grad_y, grad_y);
	Mat result2;
	addWeighted(grad_x, 0.5, grad_y, 0.5, 0, result2);
	imshow("sobel gradient", result2);


	Scharr(src, grad_x, CV_32F, 1, 0);
	Scharr(src, grad_y, CV_32F, 0, 1);
	convertScaleAbs(grad_x, grad_x);
	convertScaleAbs(grad_y, grad_y);
	Mat result3;
	addWeighted(grad_x, 0.5, grad_y, 0.5, 0, result3);
	imshow("scharr gradient", result3);

在这里插入图片描述
在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/182011.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!