基于Python的Opencv图像梯度处理

图像梯度直观反应其实就是图像当中各物体的轮廓,而在像素点上的体现其实就是相邻像素点之间的差值,差值越大,轮廓就会越清晰(可用于图像增强),而Opencv提供了以下三种算子来进行图像的梯度处理,跟在之前的博客中提到的cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel)函数其实很类似,都能够得到图像的轮廓。而Opencv也提供了以下三种算子来进行图像的梯度处理。

sobel算子

先看到Gx,这里的算子其实很像是卷积核,而靠近中间的像素乘以+2和-2,稍远的四个角则乘以+1和-1是为了实现类似加权的效果,这一点跟上篇博客的高斯滤波很像,都是进行加权,而如果这个范围内的像素点值都是一样的,那么两边相加完之后其实就是0,中间的像素点会是一个黑点,而一片像素点值接近甚至相等的区域,经过计算之后会是一片黑色的区域,则表示图像在这个位置没有梯度,这也符合我们宏观上说的没有轮廓。相反如果图像在该位置像素值大小差异明显,则经过计算所得到的中间点会是一个接近于白色的点,如果有一整行的话,那么它就是一条l轮廓线。而Gx这个卷积核的设定只能够计算水平横轴上的差值,而竖直方向上因为都是0,所以竖直方向上的梯度会被忽略,我们还需要Gy来计算竖直方向上的梯度。

注意:由于在进行梯度计算的过程中会出现负值,而Opencv没有读取负值像素这一说,因此如果出现负数,Opencv会直接进行截断操作,将它们默认为0,因此我们还需要将处理之后的图像像素值转化为绝对值。函数如下

sobely = cv2.convertScaleAbs(sobely):在括号内写入要进行绝对值转化的图片即可。

相关函数

sobelx = cv2.Sobel(test1,cv2.CV_64F,0,1,ksize = 3):test是传入的要进行处理的图像,cv2.CV_64F是一种保存数值的类型,能够保存负数,0表示先不计算水平方向的梯度,1表示计算竖直方向的梯度,当然,我们也可以将参数改为1,1以同时计算竖直方向和水平方向的梯度,但是分开计算再融合图片所得到的效果要更好一些,这里的ksize表示卷积核的范围大小。

代码实例

import cv2
import numpy as np
import matplotlib.pyplot as plt
def cv2_imshow(name,img):#定义展示图像的函数
    cv2.imshow(name,img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
pie = cv2.imread("pie.png")#读入pie图像
cv2.imshow("pie",pie)#展示读入的图像
cv2.waitKey(0)
cv2.destroyAllWindows()
sobelx = cv2.Sobel(pie,cv2.CV_64F,1,0,ksize = 3)#只计算横轴
cv2_imshow("sobelx",sobelx)
sobelx = cv2.convertScaleAbs(sobelx)#取绝对值
cv2_imshow("sobelx",sobelx)#展示图像
sobely = cv2.Sobel(pie,cv2.CV_64F,0,1,ksize = 3)#只计算竖轴
sobely = cv2.convertScaleAbs(sobely)#取绝对值           
cv2_imshow("sobely",sobely)#展示图像
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)#融合两张图像
cv2_imshow("sobelxy",sobelxy)#展示融合后的图像
sobelxy = cv2.Sobel(pie,cv2.CV_64F,1,1,ksize = 3)#同时计算横轴和竖轴
sobelxy = cv2.convertScaleAbs(sobelxy)#转化为绝对值
cv2_imshow("sobelxy",sobelxy)#展示图像
test1 = cv2.imread("test1.png")#读入彩色图像
cv2_imshow("test1",test1)#展示原图
sobelx = cv2.Sobel(test1,cv2.CV_64F,0,1,ksize = 3)#梯度处理彩色图像,只处理水平方向
sobelx = cv2.convertScaleAbs(sobelx)#转化为绝对值
cv2_imshow("sobelx",sobelx)#显示图像
sobely = cv2.Sobel(test1,cv2.CV_64F,1,0,ksize = 3)#梯度处理彩色图像,只处理竖直方向
sobely = cv2.convertScaleAbs(sobely)#转化为绝对值
cv2_imshow("sobely",sobely)#显示图像
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)#将两者图片融合
cv2_imshow("sobelxy",sobelxy)#显示融合后的图像
All = np.hstack((sobelx,sobely,sobelxy))#拼接三幅彩色图像进行对比

运行结果

原图 

只处理横轴得到的图像,可以看到在圆的顶部和底部出现了缺口,这是由于只计算了水平方向的梯度,因此对于竖直方向上的梯度将会被 抵消忽略掉。

 只处理竖轴得到的图像,跟上图相反,这是左右两边出现了缺口,这是由于值处理了竖轴方向上的梯度造成的。

将两张图像融合后即可得到圆的完整轮廓(即完整梯度)如下图

 但如果同时处理横轴和竖轴后展示图像,效果会比单独处理要差,如下图

 当然,我们也可以处理彩色的图像,读入的原图如下(上面有一些噪音点,后面有用)

进行水平方向的梯度处理后得到下图,我们可以清楚的看到她的轮廓,但是我们对比原图可以看到,她竖轴方向上的梯度并没有被体现出来,比如图片右边的竖直的头发就不见了,还有鼻子也不明显(对比下一张图可能会更清楚一些)。

进行竖直方向的梯度计算后得到下图(可以跟上图对比,看看都有啥区别) 

融合得到最终轮廓

三张图像的横向对比 

 scharr算子

scharr算子sobel算子 原理相同,用法也相同,只是scharr算子对梯度更为敏感,原因是在卷积核中,它将乘数扩大到了10和3,相当于将梯度扩大了10被和3倍,这样所得到的梯度图像将会更加的细致。

相关函数

scharrx = cv2.Scharr(test1_gray,cv2.CV_64F,0,1):只改变了函数名,函数用法和参数作用与sobel算子一样

代码示例

import cv2
import numpy as np
import matplotlib.pyplot as plt
test1_gray = cv2.imread("test1.png",cv2.IMREAD_GRAYSCALE)#读入灰度图像
scharrx = cv2.Scharr(test1_gray,cv2.CV_64F,0,1)#scharr算子梯度处理灰度图像,只处理水平方向
scharry = cv2.Scharr(test1_gray,cv2.CV_64F,1,0)#scharr算子梯度处理灰度图像,只处理竖直方向
scharrx= cv2.convertScaleAbs(scharrx)#将像素值转化为绝对值
scharry = cv2.convertScaleAbs(scharry)#将像素值转化为绝对值
scharrxy = cv2.addWeighted(scharrx,0.5,scharry,0.5,0)#融合图像

运行效果

可以看到,使用scharr算子得到深度图像明显比使用sobel算子得到的要更加细致。

laplacian算子

 laplacian算子是一个二阶算子,它可以直接计算出图像的边界,但缺点是对噪音点敏感,一般不会单独使用,需要配合其他函数处理图像。

相关函数

laplacian = cv2.Laplacian(test1_gray,cv2.CV_64F):传如要进行处理的图像和数据保存类型即可。

代码示例

import cv2
import numpy as np
import matplotlib.pyplot as plt
def cv2_imshow(name,img):#定义展示图像的函数
    cv2.imshow(name,img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
test1_gray = cv2.imread("test1.png",cv2.IMREAD_GRAYSCALE)#读入灰度图像
#laplacian算子处理梯度图像,对梯度变化速率更敏感,类似于二阶导
laplacian = cv2.Laplacian(test1_gray,cv2.CV_64F)#laplacian算子梯度处理灰度图像
laplacian = cv2.convertScaleAbs(laplacian)#将像素值转化为绝对值
cv2_imshow("laplacian",laplacian)#显示处理后的图像

运行效果

可以看到,用laplacian算子得到的图像受噪音点影响更大 

以下是三种算子处理的对比图

从左至右依次为:sobel算子,scharr算子,laplacian算子 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

念980

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值