opencv 图像梯度

 

'''
原理
梯度简单来说就是求导。
OpenCV 提供了三种不同的梯度滤波器 或者说是高通滤波器:Sobel,  Scharr 和 Laplacian。
Sobel Scharr 其实就是求一阶或二阶导数。
Scharr 是对 Sobel (使用小的卷积核求解 梯度角度时 )的优化。
Laplacian 是求二阶导数。

Sobel 算子是高斯平滑与微分操作的结合体 所以它的抗噪声能力很好。
你可以设定求导的方向 xorder 或 yorder 。
可以设定使用的卷积核的大小ksize 。
如果 ksize=-1 会使用 3x3 的 Scharr 滤波器
Laplacian 算子
拉普拉斯算子可以使用二阶导数的形式定义 ,可假设其离散实现类似于二阶Sobel 导数
事实上 OpenCV 在 算拉普拉斯算子时直接 用 Sobel 算子
'''

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('img1.png', 0)
# cv2.CV_64F 出图像的深度 数据类型 可以使用 -1, 与原图像保持一致 np.uint8
laplacian = cv2.Laplacian(img, cv2.CV_64F)
# 参数 1,0 为只在 x 方向求一阶导数 最大可以求二阶导数。
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5)
# 参数 0,1 为只在 y 方向求一阶导数 最大可以求二阶导数。
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5)

plt.subplot(2, 2, 1), plt.imshow(img, cmap='gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])

plt.subplot(2, 2, 2), plt.imshow(laplacian, cmap='gray')
plt.title('Laplacian'), plt.xticks([]), plt.yticks([])

plt.subplot(2, 2, 3), plt.imshow(sobelx, cmap='gray')
plt.title('Sobel X'), plt.xticks([]), plt.yticks([])

plt.subplot(2, 2, 4), plt.imshow(sobely, cmap='gray')
plt.title('Sobel Y'), plt.xticks([]), plt.yticks([])

plt.show()

图像深度

图像深度是指存储每个像素值所用的位数,例如cv2.CV_8U,指的是8位无符号数,取值范围为0~255,超出范围则会被截断(截断指的是,当数值大于255保留为255,当数值小于0保留为0,其余不变)。

具体还有:CV_16S(16位无符号数),CV_16U(16位有符号数),CV_32F(32位浮点数),CV_64F(64位浮点数)

import cv2
import numpy as np
#载入灰度原图,图像深度为CV_8U
img_original=cv2.imread('img1.png',0)
#原图归一化,实际图像深度已经变为CV_64F
img_standard=img_original/255
#采用灰度原图求X方向梯度
original_gradient_X_64F=cv2.Sobel(img_original,cv2.CV_64F,1,0)
#先计算数组绝对值,后转化为8位无符号数
original_gradient_X_64Fto8U=cv2.convertScaleAbs(original_gradient_X_64F)
#采用归一化的图像求X方向梯度
standard_gradient_X=cv2.Sobel(img_standard,-1,1,0)
#图像显示
cv2.imshow('original  original_gradient_X_64Fto8U standard_gradient_X ',np.hstack((img_original,original_gradient_X_64Fto8U,standard_gradient_X)))
cv2.imwrite('image.png',np.hstack((img_original,original_gradient_X_64Fto8U,standard_gradient_X)))
cv2.waitKey()
cv2.destroyAllWindows()

 

"""
当我们可以  参 数 -1 来 定 出图像的深度(数据类型)与原图像保持一致
但是我们在代码中使用的却是 cv2.CV_64F。 是为什么呢 ?
想象一下一个从黑到白的边界的导数是整数,而一个从白到黑的边界点导数却是负数。
如果原图像的深度是 np.int8 时 所有的负值会截断变成 0,换句话就是把边界丢失掉。
所以如果 两种边界你 想检测到
最好的的办法就是将输出的数据类型 设置的更高,比如 cv2.CV_16S cv2.CV_64F 等。
取绝对值然后再把它 回 到 cv2.CV_8U。
下面的示例演示了输出图片的深度不同造成的不同效果。
"""
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('img1.png', 0)

# Output dtype = cv2.CV_8U
sobelx8u = cv2.Sobel(img, cv2.CV_8U, 1, 0, ksize=5)
# Output dtype = cv2.CV_64F. Then take its absolute and convert to cv2.CV_8U
sobelx64f = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5)

abs_sobel64f = np.absolute(sobelx64f)
sobel_8u = np.uint8(abs_sobel64f)

plt.subplot(1, 3, 1), plt.imshow(img, cmap='gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(1, 3, 2), plt.imshow(sobelx8u, cmap='gray')
plt.title('Sobel CV_8U'), plt.xticks([]), plt.yticks([])
plt.subplot(1, 3, 3), plt.imshow(sobel_8u, cmap='gray')
plt.title('Sobel abs(CV_64F)'), plt.xticks([]), plt.yticks([])

plt.show()

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一壶浊酒..

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

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

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

打赏作者

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

抵扣说明:

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

余额充值