1. cv2.Canny(src, thresh1, thresh2) 进行canny边缘检测
参数说明: src表示输入的图片, thresh1表示最小阈值,thresh2表示最大阈值,用于进一步删选边缘信息
Canny边缘检测步骤:
第一步:使用高斯滤波器进行滤波,去除噪音点
第二步:使用sobel算子,计算出每个点的梯度大小和梯度方向
第三步:使用非极大值抑制(只有最大的保留),消除边缘检测带来的杂散效应
第四步:应用双阈值,来确定真实和潜在的边缘
第五步:通过抑制弱边缘来完成最终的边缘检测
第一步:高斯滤波进行滤波操作
这是3*3的归一化后的高斯核,将当前核与图片中的9个位置对应位置求和,表示当前位置的像素值,进行平滑处理,去除一些噪声点的干扰
第二步:使用sobel算子,计算各个点的梯度大小和梯度方向
使用的sobel算子存在两个方向,即x轴和y轴方向,分别计算x轴的梯度为Gx, 计算y轴的梯度为Gy
当前点的梯度大小 = sqrt(Gx ^ 2 + Gy ^ 2)
梯度的方向:Θ = arctan(Gx / Gy)
第三步:使用非极大值抑制,消除杂散效应
非极大值抑制第一种方式,如图所示,g1表示的是坐上角一点的梯度值,g2为当前点上面一点的梯度值,斜线表示的是梯度的方向,我们需要计算出斜线与g1,g2交点的近似梯度值,使用线性差值表示:即M(dtmp1) = w*M(g2) + (1-w) * M(g1) w = distance(dtmp1, g2) / distance(g1, g2)
同理计算出M(dtmp2) 即斜线与g3,g4的交点的近似梯度值
将C点的梯度值与M(dtmp1) 和 M(dtmp2)的大小做一个比较,如果比两者都大就保留,否者就去除
非极大值抑制第二种方式,如图所示, 我们可以直接比较梯度方向的斜线与哪条直线比较接近,就与哪个方向上的梯度值进行比较,我们可以初步的知道角度的区间是
(30, 45, 60, 90) , 举例说明,如果斜线靠近45度角的斜线,那么就与对角线上的两个点的梯度做比较,如果都大于则保留,否者剔除
第四步:使用双阈值来获得真实边缘和潜在的边缘
进行进一步删选,如果当前梯度值大于给定的maxVal,判断为边界, 如果当前梯度值小于minval则舍弃,如果当前梯度值在给定的最大值和最小值之间,如果其周围的点是边界点,那么当前点保留,否者舍弃
从上图我们可以看出,当minval和maxval越小时,所保留的边缘信息更多
第一步:载入lena图片
第二步:使用两组阈值,对结果作图做比较
第三步:载入汽车的图
第四步: 使用两组阈值,对结果作图做比较
import cv2 import numpy as np img = cv2.imread('lena.jpg') v1 = cv2.Canny(img, 80, 150) v2 = cv2.Canny(img, 50, 100) ret = np.hstack((v1, v2)) cv2.imshow('img', ret) cv2.waitKey(0) cv2.destroyAllWindows()
在最大阈值和最小阈值都偏小的情况下,我们可以看出右边这幅图比左边这幅图拥有更多的轮廓信息,同样的也容易存在一些非边缘点的信息
car = cv2.imread('car.png') v1 = cv2.Canny(car, 120, 250) v2 = cv2.Canny(car, 50, 100) ret = np.hstack((v1, v2)) cv2.imshow('car', ret) cv2.waitKey(0) cv2.destroyAllWindows()
右边的图的边缘信息更多,左边的图很多房子的线条没有了