图像的边缘检测 -- 利用 OpenCV 的 Sobel 函数
OpenCV gradients
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('dave.jpg',0)
laplacian = cv2.Laplacian(img,cv2.CV_64F)
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize = 5)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize = 5)
plt.subplot(2, 2, 1)
plt.imshow(img, cmap = 'gray')
plt.title('Original')
plt.xticks([])
plt.yticks([])
plt.subplot(2, 2, 2)
plt.imshow(laplacian, cmap = 'gray')
plt.title('Laplacian')
plt.xticks([])
plt.yticks([])
plt.subplot(2, 2, 3)
plt.imshow(sobelx, cmap = 'gray')
plt.title('Sobel X')
plt.xticks([])
plt.yticks([])
plt.subplot(2, 2, 4)
plt.imshow(sobely, cmap = 'gray')
plt.title('Sobel Y')
plt.xticks([])
plt.yticks([])
plt.show()
sobel 就是用一个 n * n 的 kernel 去对图像做卷积,算出各种梯度之类等等。
sobel 是带有方向的,我们可以用一个 kernel 计算在 x 轴方向上的梯度,也可以用另外一个 kernel 计算在 y 轴 方向上的梯度。 当然也可以算出梯度的绝对值,同时也计算出两者的向量和的绝对值。还可以算出梯度的方向。
def dir_threshold(img, sobel_kernel=3, thresh=(0, np.pi/2)):
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
absgraddir = np.arctan2(np.absolute(sobely), np.absolute(sobelx))
binary_output = np.zeros_like(absgraddir)
binary_output[(absgraddir >= thresh[0]) & (absgraddir <= thresh[1])] = 1
return binary_output
下面有个简单的练习,我们如何在以下图片中把车道线找出来的
最终我们得到的图片应该是这个样子的:
def abs_sobel_thresh(img, orient='x', thresh_min=0, thresh_max=255):
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
if orient == 'x':
abs_sobel = np.absolute(cv2.Sobel(gray, cv2.CV_64F, 1, 0))
if orient == 'y':
abs_sobel = np.absolute(cv2.Sobel(gray, cv2.CV_64F, 0, 1))
scaled_sobel = np.uint8(255*abs_sobel/np.max(abs_sobel))
binary_output = np.zeros_like(scaled_sobel)
binary_output[(scaled_sobel >= thresh_min) & (scaled_sobel <= thresh_max)] = 1
return binary_output
def mag_thresh(image, sobel_kernel=3, mag_thresh=(0, 255)):
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize = sobel_kernel)
sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize = sobel_kernel)
grad_mag = np.sqrt(soblex ** 2 + sobely ** 2)
# rescale to 8 bit
scale_factor = np.max(gradmag) / 255
grad_mag = (grad_mag / scale_factor).astype(np.uint8)
mag_binary = np.zeros_like(sobel)
mag_binary[(grad_mag > mag_thresh[0] ) & (grad_mag < mag_thresh[1]) ]
return mag_binary
def dir_threshold(image, sobel_kernel=3, thresh=(0, np.pi/2)):
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize = sobel_kernel)
sobelx = np.absolute(sobelx)
sobely = cv2.Sobel(gray, cv2.CV_64F, 0 ,1, ksize = sobel_kernel)
sobely = np.absolute(sobely)
direction = np.arctan2(sobely, sobelx)
binary_output = np.zeros_like(direction)
binary_output[(direction >= thresh[0]) & (direction <= thresh[1])] = 1
return binary_output
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize = sobel_kernel)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize = sobel_kernel)
return dir_binary
# Choose a Sobel kernel size
ksize = 3 # Choose a larger odd number to smooth gradient measurements
# Apply each of the thresholding functions
gradx = abs_sobel_thresh(image, orient='x', sobel_kernel=ksize, thresh=(0, 255))
grady = abs_sobel_thresh(image, orient='y', sobel_kernel=ksize, thresh=(0, 255))
mag_binary = mag_thresh(image, sobel_kernel=ksize, mag_thresh=(0, 255))
dir_binary = dir_threshold(image, sobel_kernel=ksize, thresh=(0, np.pi/2))