当前位置: 首页 > news >正文

图像梯度-Sobel算子、scharrx算子和lapkacian算子

文章目录

    • 一、认识什么是图像梯度和Sobel算子
    • 二、Sobel算子的具体使用
    • 三、scharrx算子与lapkacian(拉普拉斯)算子

一、认识什么是图像梯度和Sobel算子

图像的梯度是指图像亮度变化的空间导数,它描述了图像在不同方向上的强度变化。在图像处理和计算机视觉中,梯度通常用来检测边缘,因为边缘往往是亮度变化最显著的地方。图像梯度可以用多种方式来计算,常见的方法包括:一阶导数(Sobel算子)、二阶导数(Laplacian算子)、Prewitt算子、Canny算子。

Sobel算子是一种在图像处理和计算机视觉领域广泛使用的边缘检测算子。Sobel算子使用两个3x3的核(kernel)来分别计算图像在水平和垂直方向上的梯度。这两个核通常被称为Sobel核。水平方向(Gx)的Sobel核与垂直方向(Gy)的Sobel核的具体如下:

在这里插入图片描述

dst = cv2.Sobel(src, ddepth, dx, dy, ksize) 是 OpenCV 库中用于计算图像的 Sobel 导数的函数。这个函数实现了 Sobel 算子,用于边缘检测。其中:
src:输入图像,可以是灰度图像或彩色图像。
ddepth:输出图像的深度。通常使用 cv2.CV_64F 表示64位浮点数,这可以避免计算过程中的溢出。
dx:指定求导的阶数,用于x方向。如果为1,则计算一阶导数;如果为2,则计算二阶导数。
dy:指定求导的阶数,用于y方向。如果为1,则计算一阶导数;如果为2,则计算二阶导数。
ksize:Sobel 核的大小。默认值为3,但也可以使用5或7。

二、Sobel算子的具体使用

  • x轴方向

在水平方向上,Sobel算子一般都是右边减去左边得到梯度值,并且如果求得的梯度值是负数的话,会进行截取为0的操作,也可以通过绝对值来进行修正参数。
拿下面这个圆来做例子,计算边缘的梯度(就例如红点位置的梯度):
在这里插入图片描述

# 导入OpenCV库,用于图像处理
import cv2
# 导入matplotlib的pyplot模块,用于图像显示
import matplotlib.pyplot as plt
# 导入numpy库,用于数值计算
import numpy as np# 使用cv2.imread()函数读取位于指定路径的图像文件
img = cv2.imread("E:\\XUEXI\\Python_learn\\tupian\\4.jpg")# 定义一个函数cv_show,用于显示图像
def cv_show(name, img):# 使用cv2.imshow()函数显示图像,名称为namecv2.imshow(name, img)# 使用cv2.waitKey(0)函数等待,直到用户按下任意键cv2.waitKey(0)# 使用cv2.destroyAllWindows()函数关闭所有OpenCV创建的窗口cv2.destroyAllWindows()# 使用cv2.Sobel()函数计算图像的Sobel算子
# cv2.CV_64F指定输出图像的深度为64位浮点数
# 第三个参数1表示对x方向求导,第四个参数0表示对y方向不求导
# ksize=3指定Sobel算子的大小为3x3
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)# 调用cv_show函数显示Sobel算子处理后的图像
cv_show("sobelx", sobelx)

运行结果:
在这里插入图片描述
可以看到上面只是显示了半圆的值。这是因为右减去左的原因,当白减去黑为正数,所以显示出了边界值。当右边是黑,左边是白的时候,右减去左的结果为负数,截取为0,所以显示黑色。(具体参考下图)

在这里插入图片描述

通过sobelx = cv2.convertScaleAbs(sobelx)可计算绝对值。cv2.convertScaleAbs:这个函数用于将输入数组的元素类型转换为 8 位无符号整数(uint8)。它首先将输入数组的每个元素乘以一个比例因子(默认为 1),然后加上一个偏移量(默认为 0)。最后,它计算结果的绝对值,并将其转换为 8 位无符号整数。

import cv2
import matplotlib.pyplot as plt
import numpy as npimg = cv2.imread("E:\\XUEXI\\Python_learn\\tupian\\4.jpg")def cv_show(name,img):cv2.imshow(name, img)cv2.waitKey(0)cv2.destroyAllWindows()sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
cv_show("sobelx", sobelx)

运行结果:
在这里插入图片描述

  • y轴方向
    在竖直方向上,是用下面减去上面来得到所求值。
import cv2
import matplotlib.pyplot as plt
import numpy as npimg = cv2.imread("E:\\XUEXI\\Python_learn\\tupian\\4.jpg")def cv_show(name,img):cv2.imshow(name, img)cv2.waitKey(0)cv2.destroyAllWindows()sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)
sobely = cv2.convertScaleAbs(sobely)
cv_show("sobely", sobely)

运行结果:
在这里插入图片描述

通常突出图片的边缘检测,一般使用分别计算x和y的sobel算子,再通过sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0) cv2.addWeighted 函数将两个图像 sobelx 和 sobely 按照指定的权重进行加权融合。

import cv2
import matplotlib.pyplot as plt
import numpy as npimg = cv2.imread("E:\\XUEXI\\Python_learn\\tupian\\4.jpg")def cv_show(name,img):cv2.imshow(name, img)cv2.waitKey(0)cv2.destroyAllWindows()sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)
cv_show("sobelxy", sobelxy)

运行结果:
在这里插入图片描述
可以看到边边上缺失的地方有一条浅浅的线条连在一起。

一般不建议直接计算sobelxy = cv2.Sobel(img,cv2.CV_64F, 1, 1,ksize=3),这种方法确实可以得到图像的梯度信息,但在某些应用中,分别计算水平和垂直梯度然后再组合它们可能会更有利。例如分别计算梯度可以帮助你确定边缘的方向。这对于某些应用,如形状分析或纹理分类,可能是有用的。

直接计算:

import cv2
import matplotlib.pyplot as plt
import numpy as npimg = cv2.imread("E:\\XUEXI\\Python_learn\\tupian\\4.jpg")def cv_show(name,img):cv2.imshow(name, img)cv2.waitKey(0)cv2.destroyAllWindows()sobelxy = cv2.Sobel(img,cv2.CV_64F, 1, 1,ksize=3)
sobelxy = cv2.convertScaleAbs(sobelxy)
cv_show("sobelxy", sobelxy)

运行结果:
在这里插入图片描述

由上图和x,y分别计算再组合在一起的对比,也可以效果没有分开计算的好。

用下图的照片来更直观观察分开计算和合起来计算的区别:

在这里插入图片描述

合起来计算:

import cv2
import matplotlib.pyplot as plt
import numpy as npimg = cv2.imread("E:\\XUEXI\\Python_learn\\tupian\\5.jpg")def cv_show(name,img):cv2.imshow(name, img)cv2.waitKey(0)cv2.destroyAllWindows()sobelxy = cv2.Sobel(img,cv2.CV_64F, 1, 1,ksize=3)
sobelxy = cv2.convertScaleAbs(sobelxy)
cv_show("sobelxy", sobelxy)

运行结果:

在这里插入图片描述

分别计算x,y方向的sobel算子再组合在一起:

import cv2
import matplotlib.pyplot as plt
import numpy as npimg = cv2.imread("E:\\XUEXI\\Python_learn\\tupian\\5.jpg")def cv_show(name, img):cv2.imshow(name, img)cv2.waitKey(0)cv2.destroyAllWindows()sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)
cv_show("sobelxy", sobelxy)

运行结果:

在这里插入图片描述

通过两种方法对比,明显分开计算x,y的边缘检测效果要更加的好!

三、scharrx算子与lapkacian(拉普拉斯)算子

scharrx算子

Scharr算子是一种用于边缘检测的图像处理算子,它是Sobel算子的改进版本。Scharr算子在计算图像梯度时,提供了更高的精度,尤其是在使用3x3的核时。这使得Scharr算子在检测图像边缘时更为敏感,能够捕捉到更细小的边缘特征。Scharr算子的卷积核与Sobel算子不同,它在平滑部分给予了中心元素更大的权重,相当于使用了标准差更小的高斯函数,从而使得算子更加敏感。

Scharr算子能更加细致地描绘出细节,能够注意到更多细节。

Scharr算子的卷积核如下:
在这里插入图片描述

lapkacian(拉普拉斯)算子

拉普拉斯算子(Laplacian),在图像处理中通常称为Laplacian算子,是一种用于边缘检测的二阶导数算子。它用于增强图像中的快速强度变化,这些变化通常对应于图像中的边缘。拉普拉斯算子可以用于检测图像中的边缘和纹理。

拉普拉斯算子对于一些噪音点会更加敏感,该算子显示的细节相对较少,但是拉普拉斯算子一般都是配合其他工具一块使用的。

在这里插入图片描述

通过以下照片来更直观观察三种算子之间的差距:

在这里插入图片描述

#不同算子的差异
import cv2
import matplotlib.pyplot as plt
import numpy as npimg = cv2.imread("E:\\XUEXI\\Python_learn\\tupian\\5.jpg")def cv_show(name, img):cv2.imshow(name, img)cv2.waitKey(0)cv2.destroyAllWindows()sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)scharrx = cv2.Scharr(img,cv2.CV_64F, 1, 0)
scharry = cv2.Scharr(img,cv2.CV_64F, 0, 1)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.convertScaleAbs(scharry)
scharrxy = cv2.addWeighted(scharrx , 0.5,scharry,0.5,0)laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)res = np.hstack((sobelxy,scharrxy,laplacian))
cv_show("res", res)

运行结果:

在这里插入图片描述

其中第一幅是sobel算子,第二幅是scharrx算子,第三幅是lapkacian算子。

可以看到scharrx算子能够更加细腻的展示出照片的细节,是sobel算子的升级版。而lapkacian算子描绘的细节就更加的少,一般lapkacian算子是搭配其他工具一块使用的。


http://www.mrgr.cn/news/53950.html

相关文章:

  • 浅谈数据库选型
  • ford面试准备
  • 视频网站开发:Spring Boot框架的高效实现
  • Linux小知识2 系统的启动
  • 光伏行业如何借助ERP领跑绿色经济?
  • hadoop 重启异常,找不到DN块文件
  • 逆向工程入门02.if语句分析
  • 如何用联想电脑滚动截图
  • stablediffusion ControlNet选不了模型/报错/无效 的解决方法
  • 【Linux网络编程】Socket编程--UDP(第一弹):实现客户端和服务器互相发送消息
  • 14.归一化——关键的数据预处理方法
  • 【C++ 算法进阶】算法提升四
  • 【C++训练营】现代C++编程(隐藏)
  • 【Mysql】-锁机制-GAP锁
  • 2024年【N2观光车和观光列车司机】及N2观光车和观光列车司机模拟考试题
  • 【Hive】2-Apache Hive概述、架构、组件、数据模型
  • 好的口才是做领导的第一要务
  • SpringMVC一个拦截器和文件上传下载的完整程序代码示例以及IDEA2024部署报错 找不到此 Web 模块的 out\artifacts\..问题
  • CMOS晶体管的串联与并联
  • 【含文档】基于Springboot+Vue的地方特色美食分享管理系统(含源码+数据库+lw)
  • webAPI中的节点操作、高级事件
  • 在 Spring MVC 应用程序中使用 WebMvcTest 注释有什么用处?
  • 学习eNSP后,有哪些具体的就业方向?
  • 「数学::快速幂」矩阵快速幂运算|快速斐波那契数列 / LeetCode 509(C++)
  • 双十一有啥好用的物品可以推荐购买?2024不可错过的必囤好物清单!
  • 填充与步幅