目录
边缘检测
边缘检测:边缘检测指的是灰度发生剧烈变化的位置,边缘检测的目的是制作一个线图,在不会损害图像内容的情况下,大大减少图像的数据量,提供对图像数据的合适概述。
Sobel算子
其中Gx表示x方向的Sobel算子,用于检测y方向的边缘; Gy表示y方向的Sobel算子,用于检测x方向的边缘(边缘方向和梯度方向垂直)。
原型
Sobel算子依然是一种过滤器,只是其是带有方向的。在OpenCV-Python中,使用Sobel的算子的函数原型如下:
Sobel_x_or_y = cv2.Sobel(src, ddepth, dx, dy, dst, ksize, scale, delta, borderType)
参数:
第一个参数是需要处理的图像;
第二个参数是图像的深度,-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度;
dx和dy表示的是求导的阶数,0表示这个方向上没有求导,一般为0、1、2。
代码
import os
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('./image/lena_50.jpg') # 读取图像
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图
blur = cv2.GaussianBlur(img_gray, (3, 3), 0) # 高斯滤波处理原图像降噪
x = cv2.Sobel(blur, cv2.CV_16S, 1, 0) # Sobel函数求完导数后会有负值,还有会大于255的值
y = cv2.Sobel(blur, cv2.CV_16S, 0, 1) # 使用16位有符号的数据类型,即cv2.CV_16S
Scale_absX = cv2.convertScaleAbs(x) # 转回uint8
Scale_absY = cv2.convertScaleAbs(y)
sobel_image = cv2.addWeighted(Scale_absX, 0.5, Scale_absY, 0.5, 0)
cv2.imshow('lena_50', img)
# cv2.imshow("absX_process", Scale_absX)
# cv2.imshow("absY_process", Scale_absY)
cv2.imshow('sobel_xy_process', sobel_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
在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形式。否则将无法显示图像,而只是一副灰色的窗口。convertScaleAbs()的原型为:
结果
原图:
Sobel算子处理后得到图像:
canny算子
流程
Canny边缘检测算法可以分为以下5个步骤:
- 使用高斯滤波器,以平滑图像,滤除噪声。
- 计算图像中每个像素点的梯度强度和方向。
- 应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应。
- 应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。
- 通过抑制孤立的弱边缘最终完成边缘检测。
具体原理细节可参考:边缘检测之Canny
原型
canny = cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient ]]])
参数:
第一个参数 处理的原图像,该图像必须为单通道的灰度图;
第二个参数 最小阈值;
第三个参数 最大阈值。
代码
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('./image/lena_50.jpg') # 读取图像
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图
blur = cv2.GaussianBlur(img_gray, (3, 3), 0) # 高斯滤波处理原图像降噪
canny_image = cv2.Canny(blur, 50, 150)
cv2.imwrite('./image/canny_image.jpg', canny_image)
cv2.imshow('lena_50', img)
cv2.imshow('canny_process', canny_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果
原图:
Sobel算子处理后得到图像: