0%

opencv_9_图像梯度

Sobel算子

纵向算子

横向算子

参数ddepth

在实际操作中,计算梯度值可能会出现负数。如果处理的图像是8位图类型,则在ddepth的参数值为-1时,意味着指定运算结果也是8位图类型,那么所有负数会自动截断位0,发生了信息丢失。

为了避免信息丢失,在计算时要先使用更高的数据类型cv2.CV_64F,再通过取绝对值将其映射为cv2.CV_8U(8位图)类型。所以,通常要将函数cv2.Sobel()内参数ddepth的值设置为“cv2.CV_64F”。

1
2
3
import cv2
import numpy as np
from get_show_img import get_show
1
img = np.random.randint(-256, 256, size=[4, 5])
1
img
array([[ -39,   94,   94, -143,  -75],
       [-131,  -60,   -5,  162, -148],
       [ -68,   22,  234,   84, -242],
       [ 111,  117,  115, -120,  -52]])
1
rst = cv2.convertScaleAbs(img)  # 对像素取绝对值
1
rst
array([[ 39,  94,  94, 143,  75],
       [131,  60,   5, 162, 148],
       [ 68,  22, 234,  84, 242],
       [111, 117, 115, 120,  52]], dtype=uint8)

方向

计算x方向边缘(梯度) dx=1, dy=0

1
src = cv2.imread('data/sobel4.bmp')
1
2
dst = cv2.Sobel(src, -1, 1, 0)
get_show(dst)

9output_12_0

1
2
3
dst = cv2.Sobel(src,cv2.CV_64F, 1, 0)
dst = cv2.convertScaleAbs(dst) # 对像素取绝对值
get_show(dst)

9output_13_0

计算y方向边缘(梯度) dx=0, dy=1

1
2
dst = cv2.Sobel(src, -1, 0, 1)
get_show(dst)

9output_15_0

1
2
3
dst = cv2.Sobel(src,cv2.CV_64F, 0, 1)
dst = cv2.convertScaleAbs(dst) # 对像素取绝对值
get_show(dst)

9output_16_0

dx和dy方向边缘(梯度) dx=1, dy=1

1
2
dst = cv2.Sobel(src, -1, 1, 1)
get_show(dst)

9output_18_0

1
2
3
dst = cv2.Sobel(src,cv2.CV_64F, 1, 1)
dst = cv2.convertScaleAbs(dst) # 对像素取绝对值
get_show(dst)


9output_19_0

计算x方向和y方向的边缘叠加

1
2
3
4
dx = cv2.Sobel(src, -1, 1, 0)
dy = cv2.Sobel(src, -1, 0, 1)
dst = cv2.addWeighted(dx, 0.5, dy, 0.5, 0)
get_show(dst)


9output_21_0

1
2
3
4
5
6
dx = cv2.Sobel(src, cv2.CV_64F, 1, 0)
dy = cv2.Sobel(src, cv2.CV_64F, 0, 1)
dx = cv2.convertScaleAbs(dx) # 对像素取绝对值
dy = cv2.convertScaleAbs(dy) # 对像素取绝对值
dst = cv2.addWeighted(dx, 0.5, dy, 0.5, 0)
get_show(dst)


9output_22_0

1
np.unique(dst)
array([  0, 128, 255], dtype=uint8)

针对具体图像

1
2
3
4
5
6
7
8
9
src = cv2.imread('data/dog1.jpg', 0)
dx = cv2.Sobel(src, cv2.CV_64F, 1, 0)
dy = cv2.Sobel(src, cv2.CV_64F, 0, 1)
dx = cv2.convertScaleAbs(dx) # 对像素取绝对值
dy = cv2.convertScaleAbs(dy) # 对像素取绝对值
dst = cv2.addWeighted(dx, 0.5, dy, 0.5, 0)
dst1 = cv2.Sobel(src,cv2.CV_64F, 1, 1)
dst1 = cv2.convertScaleAbs(dst1)
get_show(src, dst, dst1)


9output_25_0

Scharr算子

纵向算子

横向算子

计算x方向边缘(梯度) dx=1, dy=0

1
src = cv2.imread('data/sobel4.bmp')
1
2
3
dst = cv2.Scharr(src, cv2.CV_64F, 1, 0)
dst = cv2.convertScaleAbs(dst)
get_show(dst)


9output_29_0

计算y方向边缘(梯度) dx=0, dy=1

1
2
3
dst = cv2.Scharr(src, cv2.CV_64F, 0, 1)
dst = cv2.convertScaleAbs(dst)
get_show(dst)


9output_31_0

计算x方向和y方向的边缘叠加

1
2
3
4
5
6
dx = cv2.Scharr(src, cv2.CV_64F, 1, 0)
dy = cv2.Scharr(src, cv2.CV_64F, 0, 1)
dx = cv2.convertScaleAbs(dx) # 对像素取绝对值
dy = cv2.convertScaleAbs(dy) # 对像素取绝对值
dst = cv2.addWeighted(dx, 0.5, dy, 0.5, 0)
get_show(dst)


9output_33_0

Sobel算子和Scharr算子叠加

Sobel算子的缺点是,当其核结构较小时,精确度不高,而Scharr算子具有更高的精度。

1
rst = cv2.imread('data/dog1.jpg', 0)
1
2
3
4
5
6
7
8
9
10
sobelx = cv2.Sobel(rst, cv2.CV_64F, 1, 0, ksize=3)
sobely = cv2.Sobel(rst, cv2.CV_64F, 0, 1, ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)
scharrx = cv2.Scharr(rst, cv2.CV_64F, 1, 0)
scharry = cv2.Scharr(rst, cv2.CV_64F, 0, 1)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.convertScaleAbs(scharry)
scharrxy = cv2.addWeighted(scharrx, 0.5, scharry, 0.5, 0)
1
get_show(rst, sobelxy, scharrxy)


9output_38_0

Laplacian(拉普拉斯)算子

1
2
laplacian = cv2.Laplacian(rst, cv2.CV_64F, ksize=3)
laplacian = cv2.convertScaleAbs(laplacian)
1
get_show(rst, laplacian)


9output_41_0

-------------本文结束感谢您的阅读-------------