图像梯度与Sobel滤波器---OpenCV-Python开发指南(20)

简介: 图像梯度与Sobel滤波器---OpenCV-Python开发指南(20)

图像梯度


图像梯度计算的是图像变化的速度。对于图像的边缘部分,其灰度值变化较大,梯度值也较大;相反,对于图像中比较平滑的部分,其灰度值变化较小,相应的梯度值也较小。一般情况下,图像的梯度计算是图像的边缘信息。


其实梯度就是导数,但是图像梯度一般通过计算像素值的差来得到梯度的近似值,也可以说是近似导数。该导数可以用微积分来表示。


在微积分中,一维函数的一阶微分的基本定义是这样的:


而图像是一个二维函数f(x,y),其微分当然就是偏微分。因此有:


因为图像是一个离散的二维函数,ϵ不能无限小,我们的图像是按照像素来离散的,最小的ϵ就是1像素。因此,上面的图像微分又变成了如下的形式(ϵ=1):


这分别是图像在(x, y)点处x方向和y方向上的梯度,从上面的表达式可以看出来,图像的梯度相当于2个相邻像素之间的差值。


那么,这个梯度(或者说灰度值的变化率)如何增强图像的清晰度呢?


我们先考虑下x方向,选取某个像素,假设其像素值是100,沿x方向的相邻像素分别是90,90,90,则根据上面的计算其x方向梯度分别是10,0,0。这里只取变化率的绝对值,表明变化的大小即可。


我们看到,100和90之间亮度相差10,并不是很明显,与一大群90的连续灰度值在一起,轮廓必然是模糊的。我们注意到,如果相邻像素灰度值有变化,那么梯度就有值,如果相邻像素灰度值没有变化,那么梯度就为0。如果我们把梯度值与对应的像素相加,那么灰度值没有变化的,像素值不变,而有梯度值的,灰度值变大了。


我们看到,相加后的新图像,原图像像素点100与90亮度只相差10,现在是110与90,亮度相差20了,对比度显然增强了,尤其是图像中物体的轮廓和边缘,与背景大大加强了区别,这就是用梯度来增强图像的原理。


上面只是说了x方向,y方向是一样的。那么能否将x方向和y方向的梯度结合起来呢?当然是可以的。x方向和y方向上的梯度可以用如下式子表示在一起:


这里又是平方,又是开方的,计算量比较大,于是一般用绝对值来近似平方和平方根的操作,来降低计算量:


原理了解后,我们来了解一些OpenCV提供了哪些梯度滤波器?


在OpenCV中,它给我们提供了三种不同的梯度滤波器,或者说高通滤波器:Sobel,Scharr 和Laplacian。什么叫高通呢?其实就是和图像模糊相反。图像模糊是让低频通过,阻挡高频,这样就可以去除噪点,让锐利的边缘变平滑。高通滤波器就是让高频通过,阻挡低频,可以让边缘更加明显,增强图像。


Sobel滤波器


Sobel滤波器是一种离散的微分算子,该算子结合了高斯平滑和微分求导运算。该算子利用局部差分寻找边缘,计算所得的是一个梯度的近似值。


具体的原理如下:


将Sobel滤波器与原始图像进行卷积计算,可以计算水平方向上的像素值变化情况。例如,当Sobel滤波器的大小为3*3时,水平方向偏导数的计算方式如下:


如果需要计算P5水平方向偏导数(梯度),则公式如下:


P5x=(P3-P1)+2*(P6-P4)+(P9-P7)


如果需要计算P5垂直方向偏导数(梯度),则公式如下:


P5y=(P7-P1)+2*(P8-P2)+(P9-P3)


在OpenCV中,它给我们提供cv2.Sobel()函数实现Sobel滤波器,其函数定义如下:

def Sobel(src, ddepth, dx, dy, dst=None, ksize=None, scale=None, delta=None, borderType=None):

src:原始图像


ddepth:输出图像的深度,详细取值如下表:


输入图像深度

输出图像深度
cv2.CV_8U -1/cv2.CV_16S/cv2.CV_32F/cv2/CV_64F
cv2.CV_16U/cv2.CV_16S -1/cv2.CV_32F/cv2.CV_64F
cv2.CV_32F -1/cv2.CV_32F/cv2.CV_64F
cv2.CV_64F -1/cv2.CV_64F

dx:代表X方向的求导阶数


dy:代表Y方向的求导阶数


ksize:Sobel核的大小,该值为-1时,则会使用Sobel滤波器进行运算


scale:计算导数值所采用的缩放因子,默认值为1,时没有缩放的


delta:加载目标图像上的值,该值可选,默认为0


borderType:边界样式,前面博文有详细介绍,这里不在赘述。


需要注意的是,如果将ddepth参数设置为-1,让处理结果与原图像保持一致,可以会得到错误的结果。实际上,这么做会导致梯度值可能出现负数。如果处理的是8位图像,意味着指定运算的结果也是8位图类型,那么所有的负数会自动截断为0,发生信息丢失。为了避免信息丢失,在计算时先使用更高的数据类型cv2.CV_64F,再通过取绝对值将其映射为cv2.CV_8U类型。所以,我们使用Sobel滤波器常常会将ddepth设置为cv2.CV_64F。


计算X方向梯度语法格式为:

cv2.Sobel(src,ddepth,1,0)

计算Y方向梯度语法格式为:

cv2.Sobel(src,ddepth,0,1)

计算XY方向梯度语法格式为:

cv2.Sobel(src,ddepth,1,1)

计算XY叠加梯度语法格式为:

dx=cv2.Sobel(src,ddepth,1,0)
dy=cv2.Sobel(src,ddepth,0,1)
dst=cv2.addWeighted(src1,alpha,src2,beta,gamma)


因为可能会出现负数,我们还需要使用另一个函数取绝对值,该函数为:cv2.convertScaleAbs(),其完整定义如下:

def convertScaleAbs(src, dst=None, alpha=None, beta=None):

alpha:调节系数,可选值,默认为1


beta:调节亮度值,默认为0


下面,我们来使用Sobel滤波器,获取图像水平方向的边缘信息,代码如下:

import cv2
img = cv2.imread("4.jpg", cv2.IMREAD_UNCHANGED)
sobel_x=cv2.Sobel(img,cv2.CV_64F,1,0)
result=cv2.convertScaleAbs(sobel_x)
cv2.imshow("img", img)
cv2.imshow("result", result)
cv2.waitKey()
cv2.destroyAllWindows()


运行之后,效果如下所示:

接着,我们来使用Sobel滤波器,获取图像垂直方向的边缘信息,代码如下:

import cv2
img = cv2.imread("4.jpg", cv2.IMREAD_UNCHANGED)
sobel_y=cv2.Sobel(img,cv2.CV_64F,0,1)#更改这一行就行
result=cv2.convertScaleAbs(sobel_y)
cv2.imshow("img", img)
cv2.imshow("result", result)
cv2.waitKey()
cv2.destroyAllWindows()


运行之后,效果如下:


接着,我们来计算XY方向梯度,代码如下:

import cv2
img = cv2.imread("4.jpg", cv2.IMREAD_UNCHANGED)
sobel_xy=cv2.Sobel(img,cv2.CV_64F,1,1)#都设置为1
result=cv2.convertScaleAbs(sobel_xy)
cv2.imshow("img", img)
cv2.imshow("result", result)
cv2.waitKey()
cv2.destroyAllWindows()


运行之后,效果如下:

最后,我们来计算其水平垂直两个方向的叠加边缘信息,代码如下:

import cv2
img = cv2.imread("4.jpg", cv2.IMREAD_UNCHANGED)
sobel_x=cv2.Sobel(img,cv2.CV_64F,1,0)
sobel_y=cv2.Sobel(img,cv2.CV_64F,0,1)
abx_x=cv2.convertScaleAbs(sobel_x)
abx_y=cv2.convertScaleAbs(sobel_y)
result=cv2.addWeighted(sobel_x,0.5,sobel_y,0.5,0)
cv2.imshow("img", img)
cv2.imshow("result", result)
cv2.waitKey()
cv2.destroyAllWindows()


运行之后,效果如下:

相关文章
|
计算机视觉
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
这篇文章详细介绍了OpenCV库中的图像二值化函数`cv2.threshold`,包括二值化的概念、常见的阈值类型、函数的参数说明以及通过代码实例展示了如何应用该函数进行图像二值化处理,并展示了运行结果。
4042 0
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
|
11月前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的【害虫识别】系统~卷积神经网络+TensorFlow+图像识别+人工智能
害虫识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了12种常见的害虫种类数据集【"蚂蚁(ants)", "蜜蜂(bees)", "甲虫(beetle)", "毛虫(catterpillar)", "蚯蚓(earthworms)", "蜚蠊(earwig)", "蚱蜢(grasshopper)", "飞蛾(moth)", "鼻涕虫(slug)", "蜗牛(snail)", "黄蜂(wasp)", "象鼻虫(weevil)"】 再使用通过搭建的算法模型对数据集进行训练得到一个识别精度较高的模型,然后保存为为本地h5格式文件。最后使用Djan
634 1
基于Python深度学习的【害虫识别】系统~卷积神经网络+TensorFlow+图像识别+人工智能
|
12月前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的【蘑菇识别】系统~卷积神经网络+TensorFlow+图像识别+人工智能
蘑菇识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了9种常见的蘑菇种类数据集【"香菇(Agaricus)", "毒鹅膏菌(Amanita)", "牛肝菌(Boletus)", "网状菌(Cortinarius)", "毒镰孢(Entoloma)", "湿孢菌(Hygrocybe)", "乳菇(Lactarius)", "红菇(Russula)", "松茸(Suillus)"】 再使用通过搭建的算法模型对数据集进行训练得到一个识别精度较高的模型,然后保存为为本地h5格式文件。最后使用Django框架搭建了一个Web网页平台可视化操作界面,
1173 11
基于Python深度学习的【蘑菇识别】系统~卷积神经网络+TensorFlow+图像识别+人工智能
|
机器学习/深度学习 人工智能 算法
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
宠物识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了37种常见的猫狗宠物种类数据集【'阿比西尼亚猫(Abyssinian)', '孟加拉猫(Bengal)', '暹罗猫(Birman)', '孟买猫(Bombay)', '英国短毛猫(British Shorthair)', '埃及猫(Egyptian Mau)', '缅因猫(Maine Coon)', '波斯猫(Persian)', '布偶猫(Ragdoll)', '俄罗斯蓝猫(Russian Blue)', '暹罗猫(Siamese)', '斯芬克斯猫(Sphynx)', '美国斗牛犬
637 29
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
|
算法 数据处理 Python
高精度保形滤波器Savitzky-Golay的数学原理、Python实现与工程应用
Savitzky-Golay滤波器是一种基于局部多项式回归的数字滤波器,广泛应用于信号处理领域。它通过线性最小二乘法拟合低阶多项式到滑动窗口中的数据点,在降噪的同时保持信号的关键特征,如峰值和谷值。本文介绍了该滤波器的原理、实现及应用,展示了其在Python中的具体实现,并分析了不同参数对滤波效果的影响。适合需要保持信号特征的应用场景。
1675 11
高精度保形滤波器Savitzky-Golay的数学原理、Python实现与工程应用
|
存储 JSON API
Python| 如何使用 DALL·E 和 OpenAI API 生成图像(1)
Python| 如何使用 DALL·E 和 OpenAI API 生成图像(1)
Python| 如何使用 DALL·E 和 OpenAI API 生成图像(1)
|
机器学习/深度学习 TensorFlow 算法框架/工具
利用Python和TensorFlow构建简单神经网络进行图像分类
利用Python和TensorFlow构建简单神经网络进行图像分类
389 3
|
JSON API 数据格式
Python| 如何使用 DALL·E 和 OpenAI API 生成图像(2)
Python| 如何使用 DALL·E 和 OpenAI API 生成图像(2)
Python| 如何使用 DALL·E 和 OpenAI API 生成图像(2)
|
5月前
|
数据采集 机器学习/深度学习 人工智能
Python:现代编程的首选语言
Python:现代编程的首选语言
453 102
|
5月前
|
数据采集 机器学习/深度学习 算法框架/工具
Python:现代编程的瑞士军刀
Python:现代编程的瑞士军刀
393 104

推荐镜像

更多