本文共 1791 字,大约阅读时间需要 5 分钟。
1,图像梯度的概念
梯度简单来说就是求导,在图像上表现出来的就是提取图像的边缘(无论是横向的、纵向的、斜方向的等等),所需要的是一个核模板。模板的不同结果也不同。所以能够看到,全部的这些个算子函数,归结究竟都能够用函数cv2.filter2D()来表示,不同的方法给予不同的核模板,然后演化为不同的算子。在微积分中,一维函数的一阶微分的基本定义是这样的:
而图像是一个二维函数f(x,y),其微分当然就是偏微分。因此有: 因为图像是一个离散的二维函数,ϵ不能无限小,我们的图像是按照像素来离散的,最小的ϵ就是1像素。因此,上面的图像微分又变成了如下的形式(ϵ=1): 这分别是图像在(x, y)点处x方向和y方向上的梯度,从上面的表达式可以看出来,图像的梯度相当于2个相邻像素之间的差值。x方向和y方向上的梯度可以用如下式子表示在一起: 这里又是平方,又是开方的,计算量比较大,于是一般用绝对值来近似平方和平方根的操作,来降低计算量: 2,经典的图像梯度算法 经典的图像梯度算法考虑图像的每个像素的某个邻域内的灰度变化,利用边缘临近的一阶或二阶导数变化规律,对原始图像中像素某个邻域设置梯度算子,通常我们用小区域模板进行卷积来计算,OpenCV提供了三种不同的梯度滤波器,或者说高通滤波器:Sobel,Scharr和Lapacian。Sobel,Scharr其实就是求一阶或二阶导。Scharr是对Sobel的部分优化。Laplacian是求二阶导。 假如对一幅数字图像,求出M之后与原来每个像素点对应值相加,则图像边缘将被大大加强,轮廓更加明显,是一个很典型的sharp filter的效果。关于Sobel算子与Scharr算子:
关于拉普拉斯(Laplacian)算子:
源代码示例:import cv2 as cvimport numpy as npdef lapalian_demo(image): #dst = cv.Laplacian(image, cv.CV_32F)#默认为4领域拉普拉斯算子 #lpls = cv.convertScaleAbs(dst) kernel = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]])#自定义的8领域拉普拉斯算子 dst = cv.filter2D(image, cv.CV_32F, kernel=kernel) lpls = cv.convertScaleAbs(dst) cv.imshow("lapalian_demo", lpls)def sobel_demo(image): #grad_x = cv.Sobel(image, cv.CV_32F, 1, 0) #grad_y = cv.Sobel(image, cv.CV_32F, 0, 1) grad_x = cv.Scharr(image, cv.CV_32F, 1, 0)#cv.Sobel的增强版,对噪声比较敏感 grad_y = cv.Scharr(image, cv.CV_32F, 0, 1) gradx = cv.convertScaleAbs(grad_x) #求绝对值并转化为8位的图像上 grady = cv.convertScaleAbs(grad_y) cv.imshow("gradient-x", gradx) cv.imshow("gradient-y", grady) gradxy = cv.addWeighted(gradx, 0.5, grady, 0.5, 0) cv.imshow("gradient", gradxy)src = cv.imread("F:/images/lena.png")cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)cv.imshow("input image", src)sobel_demo(src)lapalian_demo(src)cv.waitKey(0)cv.destroyAllWindows()
运行结果:
关于canny边缘检測算子,细究的话比较的复杂,将在下一篇文章中具体介绍。转载地址:http://wahwi.baihongyu.com/