OpenCV Canny边缘检测(学习笔记) 电脑版发表于:2024/1/15 15:03 ![](https://img.tnblog.net/arcimg/hb/3c9a034e352c4476b4ec6d8cc07a0263.png) >#OpenCV Canny边缘检测(学习笔记) [TOC] ## Canny边缘检测 tn2>Canny边缘检测主要是按照如下步骤来进行的边缘检测: 1.使用高斯滤波器,以平滑图像,滤除噪声。(降噪) 2.计算图像中每个像素点的梯度强度和方向。(使用sobel算子) 3.应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应。 4.应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。 5.通过抑制孤立的弱边缘最终完成边缘检测。 ### 高斯滤波器 tn2>边缘检测易受噪声影响,所以使用高斯滤波器平滑图像,降低噪声。 ### 计算梯度大小 tn2>使用sobel算子计算图像中每个像素点的梯度大小和方向。 ![](https://img.tnblog.net/arcimg/hb/f02ad929b44e49d4a269fd416dd599c1.png) tn2>通过的sobel求导得出`3*3`的卷积核,通过上面两个公式得出对应的梯度。 接着我们通过下面的公式进行计算梯度的大小和方向。 ![](https://img.tnblog.net/arcimg/hb/3692ced255524651a7515c316b99a151.png) tn2>基本的方向就那标志的8种方向。 ### 非极大值抑制 tn2>遍历图像中的所有的像素点,判断当前像素点是否是周围像素点中具有相同方向梯度的最大值。 举例:在下图中,第一列方向都是向上,只取最大梯度值`7`;第二列方向也都是向上,取最大梯度值`8`; ![](https://img.tnblog.net/arcimg/hb/827be5a5e73345a7a3bd3af0eeaad395.png) tn>保留黄色背景的像素点,其他的归为`0`。 ### 双阈值处理 tn2>指定两个值`minVal`和`maxVal`,设定最小的阈值和最大的阈值。 规则如下: 1.梯度值>maxVal:则处理为边界。 2.minVal<梯度值<maxVal:连有边界则保留,否则舍弃 3.梯度值<minVal:则舍弃 举例: ![](https://img.tnblog.net/arcimg/hb/396cc04cebb54306a06e6ce9e4f33bb7.png) tn2>`B`线条虽然在`minVal`与`maxVal`之间,但是没有高于`maxVal`的线条作为连接,所以直接舍弃。 `C`线条虽然也在此区间,但是它有`A`线条的连接所以它可以保留。 ## 代码实践 tn2>接下来我们使用`canny`对`lena.jpg`图片进行边缘处理,分别展示阈值在`80-150`和`50-100`之间的区别。 ```python import cv2 #opencv读取的格式是BGR import numpy as np import matplotlib.pyplot as plt#Matplotlib是RGB %matplotlib inline # 展示图片 def cv_show(img,name): cv2.imshow(name,img) cv2.waitKey() cv2.destroyAllWindows() img=cv2.imread("lena.jpg",cv2.IMREAD_GRAYSCALE) v1=cv2.Canny(img,80,150) v2=cv2.Canny(img,50,100) res = np.hstack((v1,v2)) cv_show(res,'res') ``` ![](https://img.tnblog.net/arcimg/hb/557b846e30fb4c75935d36aa539e1f2d.png) tn2>我们发现阈值在`50-100`区间更细。 再对一张`car.png`的图片做例子: ```python img=cv2.imread("car.png",cv2.IMREAD_GRAYSCALE) v1=cv2.Canny(img,120,250) v2=cv2.Canny(img,50,100) res = np.hstack((v1,v2)) cv_show(res,'res') ``` ![](https://img.tnblog.net/arcimg/hb/e77d286da21c49489c47b649a6bb3e4d.png)