Chapter 6 opencv python edge detection (sharpening)

Edge detection
Two types
are based on search to detect the boundary by finding the maximum value in the first derivative of the image, and then use the calculation results to estimate the local direction of the edge, usually using the direction of the gradient, and use this direction to find the maximum value of the local gradient modulus Sobel operator and Scharr

	基于零穿越  过寻找图像二阶导数零穿越来寻找边界    Laplacian算子。拉普拉斯
				
	
Sobel检测算子
	优点:抗噪声能力很强,效率高
	原理:如果区域的像素是相同的不存在边界,卷积结果为0,
		Gx右边-左边,Gy下面-上面
	
	计算完成x方向上和y方向上的边缘,将得到的值进行非线性就和计算
	类似于代码上的 addweight()---最终得到的是图片总边界
		
		Sobel函数求完导数后会有负值,还有会大于255的值。而原图像是uint8,即8位无符号数,所以Sobel建立的图像位数不够,会有截断。因此要使用16位有符号的数据类型,即cv2.CV_16S。处理完图像后,再使用cv2.convertScaleAbs()函数将其转回原来的uint8格式,否则图像无法显示。
		Sobel算子是在两个方向计算的,最后还需要用cv2.addWeighted( )函数将其组合起来
利用OpenCV进行sobel边缘检测的API是:

Sobel_x_or_y = cv2.Sobel(src, ddepth, dx, dy, dst, ksize, scale, delta, borderType)
	参数:
		§ src:传入的图像
		§ ddepth: 图像的深度
		§ dx和dy: 指求导的阶数,0表示这个方向上没有求导,取值为0、1。
		§ ksize: 是Sobel算子的大小,即卷积核的大小,必须为奇数1、3、5、7,默认为3。

Note: If ksize=-1, it will evolve into a 3x3 Scharr operator.
§ scale: scaling constant of the derivative, the default is no scaling factor.
§ borderType: the mode of the image border, the default value is cv2.BORDER_DEFAULT.

代码,先计算x方向的边界,再计算y方向的边界,然后相加
	import cv2 as cv
	import numpy as np
	from matplotlib import pyplot as plt
	# 1 读取图像
	# img = cv.imread("opencv_learn\\sky.png",0)
	img = cv.imread('data\\torchvision_data\\Vicente_Fox\\Vicente_Fox_0001.jpg',0)
	# 2 计算Sobel卷积结果
	x = cv.Sobel(img, cv.CV_16S, 1, 0)
	y = cv.Sobel(img, cv.CV_16S, 0, 1)
	# 3 将数据进行转换
	Scale_absX = cv.convertScaleAbs(x)  # convert 转换  scale 缩放
	Scale_absY = cv.convertScaleAbs(y)
	# 4 结果合成
	result = cv.addWeighted(Scale_absX, 0.5, Scale_absY, 0.5, 0)
	# 5 图像显示
	plt.figure(figsize=(10,8),dpi=100)
	plt.subplot(121),plt.imshow(img,cmap=plt.cm.gray),plt.title('原图')
	plt.xticks([]), plt.yticks([])
	plt.subplot(122),plt.imshow(result,cmap = plt.cm.gray),plt.title('Sobel滤波后结果')
	plt.xticks([]), plt.yticks([])
	plt.show()

Summary
a. The principle of edge detection
§ Search-based: use the maximum value of the first-order derivative to obtain the boundary
§ Based on zero crossing: use the second-order derivative to be 0 to obtain the boundary
b. Sobel operator
Search-based method to obtain the boundary
cv.sobel()
cv .convertScaleAbs()
cv.addweights()
c. Laplacian operator
Obtain boundary based on zero crossing
cv.Laplacian()
d. Canny algorithm
Process:
§ Noise removal: Gaussian filter
§ Calculate image gradient: sobel operator, calculate gradient size and direction
§ Non-maximum value suppression: Use gradient direction pixels to determine whether the current pixel is a boundary point
§ Hysteresis threshold: Set two thresholds to determine the final boundary

Canny算法
	○ 噪声去除:高斯滤波
	○ 计算图像梯度:sobel算子,计算梯度大小和方向
	○ 非极大值抑制:利用梯度方向像素来判断当前像素是否为边界点
	○ 滞后阈值:设置两个阈值,确定最终的边界

	高斯滤波器-----噪声去除
		归一化
		高斯核卷积求和
		
		

	计算图像梯度
		求Gx,Gy
		
		求梯度的角度    角度越大代表的边界可能性越强
			
	非极大值抑制
		在获得梯度的方向和大小之后,对整幅图像进行扫描,去除那些非边界上的点。对每一个像素进行检查,看这个点的梯度是不是周围具有相同梯度方向的点中最大的
			A点位于图像的边缘,在其梯度变化方向,选择像素点B和C,用来检验A点的梯度是否为极大值,若为极大值,则进行保留,否则A点被抑制,最终的结果是具有“细边”的二进制图像。
			ABC点应该就是第一步计算的G点梯度值把???
		
	第四步:滞后阈值
	现在要确定真正的边界。 我们设置两个阈值: minVal 和 maxVal。 当图像的灰度梯度高于 maxVal 时被认为是真的边界, 低于 minVal 的边界会被抛弃。如果介于两者之间的话,就要看这个点是否与某个被确定为真正的边界点相连,如果是就认为它也是边界点,如果不是就抛弃。如下图:
	
	如上图所示,A 高于阈值 maxVal 所以是真正的边界点,C 虽然低于 maxVal 但高于 minVal 并且与 A 相连,所以也被认为是真正的边界点。而 B 就会被抛弃,因为低于 maxVal 而且不与真正的边界点相连。所以选择合适的 maxVal 和 minVal 对于能否得到好的结果非常重要。
	
	设置的阈值起点越低,得到的边缘特征信息更多
	
	import cv2 as cv
	import numpy as np
	import matplotlib.pyplot as plt
	img =cv.imread('opencv_learn/sky.png',cv.IMREAD_GRAYSCALE)
	print(img)
	v1 = cv.Canny(img,80,150)
	v2=cv.Canny(img,50,150)
	res = np.hstack((v1,v2))
	if True:
	    plt.figure(figsize=(10,8),dpi=100)
	    plt.subplot(121),plt.imshow(res,cmap=plt.cm.gray),plt.title('org')
	    plt.xticks([]), plt.yticks([])
	    plt.show()
	
	
	
Laplacian算子
API:
laplacian = cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])
参数:
• Src: 需要处理的图像,
• Ddepth: 图像的深度,-1表示采用的是原图像相同的深度,目标图像的深度必须大于等于原图像的深度;
• ksize:算子的大小,即卷积核的大小,必须为1,3,5,7。
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 1 读取图像
img = cv.imread('./image/horse.jpg',0)
# 2 laplacian转换
result = cv.Laplacian(img,cv.CV_16S)
Scale_abs = cv.convertScaleAbs(result)
# 3 图像展示
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img,cmap=plt.cm.gray),plt.title('原图')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(Scale_abs,cmap = plt.cm.gray),plt.title('Laplacian检测后结果')
plt.xticks([]), plt.yticks([])
plt.show()

效果

Guess you like

Origin blog.csdn.net/weixin_46124467/article/details/128521351