python-opencv 边缘检测

Canny边缘检测

Canny边缘检测器是一种被广泛使用的算法,并被认为是边缘检测最优的算法,该方法使用了比高斯差分算法更复杂的技巧,如多向灰度梯度和滞后阈值化

步骤

平滑图像:使用高斯滤波器与图像进行卷积,平滑图像,以减少边缘检测器上明显的噪声影响

计算图像的梯度和方向:图像中的边缘可以指向各个方向,这里计算图像的梯度,并将梯度分类为垂直、水平和斜对角。

非最大值抑制:利用上一步计算出来的梯度方向,检测某一像素在梯度的正方向和负方向上是否是局部最大值,如果是,则该像素点保留为边缘点,否则该像素点将被抑制。

双阈值算法检测和连接边缘:仍然存在由于噪声和颜色变化引起的一些边缘像素。为了解决这些杂散响应,必须用弱梯度值过滤边缘像素,并保留具有高梯度值的边缘像素,可以通过选择高低阈值来实现

核心语句

canny = cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient ]]]) 
参数:
第一个参数 处理的原图像,该图像必须为单通道的灰度图;
第二个参数 最小阈值;
第三个参数 最大阈值。

代码实现

import os
import cv2
img = cv2.imread('1.jpg', 0)#转化为灰度图
img_color = img
blur = cv2.GaussianBlur(img, (3, 3), 0)  # 用高斯滤波处理原图像降噪
canny = cv2.Canny(blur, 50, 150)  # 50是最小阈值,150是最大阈值
cv2.namedWindow("canny",0);#可调大小
cv2.namedWindow("1",0);#可调大小
cv2.imshow('1', img)
cv2.imshow('canny', canny)
cv2.waitKey(0)
cv2.destroyAllWindows()

效果对比

python-opencv 边缘检测_第1张图片
参考
https://blog.csdn.net/qq_40962368/article/details/81416954
https://www.cnblogs.com/techyan1990/p/7291771.html

soble边缘检测

Sobel边缘检测算法比较简单,实际应用中效率比canny边缘检测效率要高,但是边缘不如Canny检测的准确,Sobel算子是高斯平滑与微分操作的结合体,所以其抗噪声能力很强,用途较多。尤其是效率要求较高,而对细纹理不太关系的时候,对于一个彩色图要先把它转换为灰度图

原理

python-opencv 边缘检测_第2张图片

python-opencv 边缘检测_第3张图片

核心语句

Sobel_x_or_y = cv2.Sobel(src, ddepth, dx, dy, dst, ksize, scale, delta, borderType)
参数:
第一个参数是需要处理的图像;
第二个参数是图像的深度,-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度;
dx和dy表示的是求导的阶数,0表示这个方向上没有求导,一般为012

代码实现

# Sobel边缘检测算子
import os
import cv2
img = cv2.imread('1.jpg', 0)#转化为灰度图
x = cv2.Sobel(img, cv2.CV_16S, 1, 0)
y = cv2.Sobel(img, cv2.CV_16S, 0, 1)
# cv2.convertScaleAbs(src[, dst[, alpha[, beta]]])
# 可选参数alpha是伸缩系数,beta是加到结果上的一个值,结果返回uint类型的图像
Scale_absX = cv2.convertScaleAbs(x)  # convert 转换  scale 缩放
Scale_absY = cv2.convertScaleAbs(y)
result = cv2.addWeighted(Scale_absX, 0.5, Scale_absY, 0.5, 0)
cv2.namedWindow("result",0);#可调大小
cv2.namedWindow("1",0);#可调大小
cv2.imshow('1', img)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

效果对比

python-opencv 边缘检测_第4张图片
在Sobel函数的第二个参数这里使用了cv2.CV_16S。因为OpenCV文档中对Sobel算子的介绍中有这么一句:“in the case of 8-bit input images it will result in truncated derivatives”。即Sobel函数求完导数后会有负值,还有会大于255的值。而原图像是uint8,即8位无符号数,所以Sobel建立的图像位数不够,会有截断。因此要使用16位有符号的数据类型,即cv2.CV_16S。

在经过处理后,别忘了用convertScaleAbs()函数将其转回原来的uint8形式。否则将无法显示图像,而只是一副灰色的窗口。

result = cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]])

其中alpha是第一幅图片中元素的权重,beta是第二个的权重,gamma是加到最后结果上的一个值。

参考:
https://blog.csdn.net/qq_40962368/article/details/81416954

你可能感兴趣的:(python)