概述:利用Sobel算子进行图像梯度计算
参数:
返回值:梯度图
1. 图像深度
图像深度是指存储每个像素值所用的位数,例如cv2.CV_8U,指的是8位无符号数,取值范围为0~255,超出范围则会被截断(截断指的是,当数值大于255保留为255,当数值小于0保留为0,其余不变)。
具体还有:CV_16S(16位无符号数),CV_16U(16位有符号数),CV_32F(32位浮点数),CV_64F(64位浮点数)等.
import cv2
#载入原图,图像深度为CV_8U
img_original=cv2.imread('E:\ShannonT\\notebook workspace\\images\\4.28.9.jpg',0)
#求X方向梯度,并且输出图像一个为CV_8U,一个为CV_64F
img_gradient_X_8U=cv2.Sobel(img_original,-1,1,0)
img_gradient_X_64F=cv2.Sobel(img_original,cv2.CV_64F,1,0)
#将图像深度改为CV_8U
img_gradient_X_64Fto8U=cv2.convertScaleAbs(img_gradient_X_64F)
#图像显示
cv2.imshow('X_gradient_8U',img_gradient_X)
cv2.imshow('X_gradient_64Fto8U',img_gradient_X_64Fto8U)
cv2.waitKey()
cv2.destroyAllWindows()
效果如下:
2. 函数cv2.convertScaleAbs()的使用
在上述案例案例中,我们使用了函数cv2.convertScaleAbs()将图像深度为CV_64F的梯度图像重新转化为CV_8U,这是由于函数cv2.imshow()的默认显示为8位无符号数,即[0,255]。先来看一下两者显示的差别(左图为8U,右图为64F):
可以发现当图像深度为CV_64F时,显示时有明显缺陷,具体原因可以参考:
有关函数cv2.imshow()处理不同图像深度时的数据转化问题.
函数cv2.convertScaleAbs(src[,alpha[,beta]])
概述:
先计算数组绝对值,后转化为8位无符号数
参数:
下面例子将一个numpy数组通过cv2.convertScaleAbs()转化
import numpy as np
test=np.array([[100,56.4,300],[-200,-280,-34.6]])
result=cv2.convertScaleAbs(test)
result
防止梯度大小被截断最简单的方法就是先将输入图像归一化(实际归一化的过程就已经实现了图像深度的转变),通过下面的例子实际说明
import cv2
import numpy as np
#载入灰度原图,图像深度为CV_8U
img_original=cv2.imread('E:\ShannonT\\notebook workspace\\images\\4.28.9.jpg',0)
#原图归一化,实际图像深度已经变为CV_64F
img_standard=img_original/255
#采用灰度原图求X方向梯度
original_gradient_X_64F=cv2.Sobel(img_original,cv2.CV_64F,1,0)
original_gradient_X_64Fto8U=cv2.convertScaleAbs(original_gradient_X_64F)
#采用归一化的图像求X方向梯度
standard_gradient_X=cv2.Sobel(img_standard,-1,1,0)
#图像显示
cv2.imshow('original',img_original)
cv2.imshow('original_X',original_gradient_X_64Fto8U)
cv2.imshow('standard_X',standard_gradient_X)
cv2.waitKey()
cv2.destroyAllWindows()
通过cv2.Sobel()我们可以轻松计算出X,Y方向的梯度大小,根据公式
可以求出梯度图像,实际操作时,为了简化运算,我们使用公式
求梯度图像,以下是代码实现,利用的函数为cv2.addWeighted(),有关函数更多信息可以参考:
Python-OpenCV 图像叠加or图像混合加权(cv2.addWeighted)
import cv2
import numpy as np
#载入灰度原图,并且归一化
img_original=cv2.imread('E:\ShannonT\\notebook workspace\\images\\4.28.9.jpg',0)/255
#分别求X,Y方向的梯度
grad_X=cv2.Sobel(img_original,-1,1,0)
grad_Y=cv2.Sobel(img_original,-1,0,1)
#求梯度图像
grad=cv2.addWeighted(grad_X,0.5,grad_Y,0.5,0)
cv2.imshow('gradient',grad)
cv2.waitKey()
cv2.destroyAllWindows()