opencv学习(图像梯度)
目录
1.什么是图像梯度
2.常见4种算子对比
3.常见4种算子的代码示例
1.什么是图像梯度
在图像处理中,图像梯度(Image Gradient) 是描述图像中像素值变化率的概念,是理解图像中 “哪里发生变化” 以及 “变化有多剧烈” 的核心工具。从简单的 Sobel 算子到复杂的 Canny 算法,本质都是通过梯度分析实现边缘提取,是计算机视觉中处理图像结构的基础。
2.常见4种算子对比
水平 / 垂直
水平 / 垂直
对细节更敏感
)
较粗(易受噪声影响)
最细(非极大值抑制优化)
中等(自带轻微平滑)
中等(与 Sobel 类似)
弱(对噪声极敏感)
强(高斯模糊 + 双阈值)
低
低(与 Sobel 相同)
低
高(多阶段处理)
灰度图(边缘强度)
灰度图(边缘强度)
灰度图(边缘强度)
二值图(仅保留边缘)
3.常见4种算子的代码示例
import cv2import matplotlib.pyplot as pltimport numpy as np\'\'\'img=cv2.imread(\'persistence.jpg\')img1=cv2.resize(img,(0,0),fx=0.6,fy=0.5)cv2.imshow(\'img1\',img1)cv2.waitKey(0)cv2.destroyAllWindows()\'\'\'img = cv2.imread(\'persistence.jpg\',cv2.IMREAD_GRAYSCALE)#img = cv2.imread(\'persistence.jpg\')img1 = cv2.resize(img, (0, 0), fx=0.6, fy=0.5)def cv_show(name,img): cv2.imshow(name,img)#def函数中cv2.imshow函数的两个参数不是固定的参数,将选用的参数放在调用函数cv_show()中。 cv2.waitKey(0) cv2.destroyAllWindows()cv_show(\'persistence.jpg\',img1)#sobel算子\'\'\'Sobel 算子是一种常用的边缘检测算子,它通过计算图像梯度的近似值来识别图像中的边缘区域。Sobel 算子对噪声具有一定的平滑作用,同时能较好地保留边缘信息,因此在计算机视觉任务中被广泛应用。由于梯度计算可能产生负值(如边缘从亮到暗的过渡),ddepth需设为cv2.CV_64F以保留负值,否则会被截断为 0(丢失部分边缘)。后续需用cv2.convertScaleAbs()将结果转为uint8(0-255)以便正常显示。\'\'\'#水平方向是点的右边-点的左边#eq=cv2.equalizeHist(img1) #cv2.equalizeHist()用于灰度图中增强对比度sox=cv2.Sobel(img1,cv2.CV_64F,1,0,ksize=3)#ksize:Sobel 核的大小(必须为奇数,如 1、3、5、7,默认 3)sox=cv2.convertScaleAbs(sox)#cv2.convertScaleAbs取绝对值#cv_show(\'sox\',sox)#垂直方向是点的下边-点的上边soy=cv2.Sobel(img1,cv2.CV_64F,0,1,ksize=3)soy=cv2.convertScaleAbs(soy)#cv_show(\'soy\',soy)#dx+dy,求和(不能将dx和dy都变成1来进行求和计算)soxy=cv2.addWeighted(sox,0.5,soy,0.5,0)cv_show(\'soxy\',soxy)res1=np.hstack((sox,soy,soxy))cv_show(\'res1\',res1)#scharr算子(dx和dy的参数比sobel算子的参数大)scx=cv2.Scharr(img1,cv2.CV_64F,1,0)scx=cv2.convertScaleAbs(scx)scy=cv2.Scharr(img1,cv2.CV_64F,0,1)scy=cv2.convertScaleAbs(scy) #切记求绝对值scxy=cv2.addWeighted(scx,0.5,scy,0.5,0)cv_show(\'scxy\',scxy)#lapkacian算子(不区分dx和dy,中心点的斜对角都是0.中心点为-4,中心点的上下左右为1)lap=cv2.Laplacian(img1,cv2.CV_64F)lap=cv2.convertScaleAbs(lap)cv_show(\'lap\',lap)res2=np.hstack((img1,soxy,scxy,lap))#在没有给scharr算子和lapkacian算子进行cv2.convertScaleAbs操作时,soxy没有呈现出来res3=cv2.resize(res2,(0,0),fy=0.8,fx=0.8)cv_show(\'res3\',res3)\'\'\'对比维度 Sobel Scharr Laplacian Canny边缘方向性区分水平 / 垂直方向区分水平 / 垂直方向不区分方向(全向检测)不区分方向(全向检测)边缘粗细 较粗 较细(对细节更敏感) 较粗(易受噪声影响)最细(非极大值抑制优化)抗噪声能力中等(自带轻微平滑)中等(与 Sobel 类似) 弱(对噪声极敏感)强(高斯模糊 + 双阈值)计算复杂度 低 低(与 Sobel 相同) 低 高(多阶段处理)输出结果 灰度图(边缘强度) 灰度图(边缘强度) 灰度图(边缘强度) 二值图(仅保留边缘)\'\'\'#Canny边缘检测\'\'\'Canny边缘检测是一种多阶段边缘检测算法,其核心目标是检测出图像中真实、连续、定位准确的边缘,被广泛认为是 “最优边缘检测算法”。其理论基础结合了图像处理、信号处理和统计理论。具体有5个步骤:首先采用高斯滤波去模糊,再用Sobel算子进行图像梯度处理,在此过程中对梯度的大小和方向进行计算(大小就是求和计算,方向=arctan(Gy/Gx)方向通常被量化为 4 个角度:0°(水平)、45°(对角线)、90°(垂直)、135°(反对角线),便于后续处理。),之后进行非极大值抑制操作(沿梯度方向(垂直于边缘走向)检查当前像素是否为局部最大值,若不是则抑制(设为 0),仅保留梯度最强的像素。例如:若梯度方向为 90°(垂直边缘),则比较当前像素与上下相邻像素的梯度大小,只有当前像素是最大值时才保留。),之后进行双阈值筛选(梯度值>maxVal: 则处理为边界;minVal<梯度值<maxVal:连有边界则保留,否则舍弃;梯度值<minVal: 则舍弃),最后进行边缘链接。单方向梯度通常为 - 255~255,梯度大小(边缘强度)最大约 360,但实际应用中通过转换后,梯度会被处理为 0~255 的可视范围。这也是 Canny 边缘检测的阈值通常设置在 0~255 之间的原因。\'\'\'canny1=cv2.Canny(img1,50,150)#最大阈值通常是最小阈值的2-3倍,同时在理论上最大阈值不超过255canny2=cv2.Canny(img1,80,240)canny3=cv2.Canny(img1,200,350)res4=np.hstack((canny1,canny2,canny3))cv_show(\'res4\',res4)