智慧交通day03-车道线检测实现05:透视变换+代码实现
生活随笔
收集整理的這篇文章主要介紹了
智慧交通day03-车道线检测实现05:透视变换+代码实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
為了方便后續的直方圖滑窗對車道線進行準確的定位,我們在這里利用透視變換將圖像轉換成俯視圖,也可將俯視圖恢復成原有的圖像,代碼如下:
計算透視變換所需的參數矩陣:
def cal_perspective_params(img, points):offset_x = 330offset_y = 0img_size = (img.shape[1], img.shape[0])src = np.float32(points)# 俯視圖中四點的位置dst = np.float32([[offset_x, offset_y], [img_size[0] - offset_x, offset_y],[offset_x, img_size[1] - offset_y],[img_size[0] - offset_x, img_size[1] - offset_y]])# 從原始圖像轉換為俯視圖的透視變換的參數矩陣M = cv2.getPerspectiveTransform(src, dst)# 從俯視圖轉換為原始圖像的透視變換參數矩陣M_inverse = cv2.getPerspectiveTransform(dst, src)return M, M_inverse透視變換:
def img_perspect_transform(img, M):img_size = (img.shape[1], img.shape[0])return cv2.warpPerspective(img, M, img_size)下面我們調用上述兩個方法看下透視變換的結果:
在原始圖像中我們繪制道路檢測的結果,然后通過透視變換轉換為俯視圖。
img = cv2.imread("./test/straight_lines2.jpg") img = cv2.line(img, (601, 448), (683, 448), (0, 0, 255), 3) img = cv2.line(img, (683, 448), (1097, 717), (0, 0, 255), 3) img = cv2.line(img, (1097, 717), (230, 717), (0, 0, 255), 3) img = cv2.line(img, (230, 717), (601, 448), (0, 0, 255), 3) points = [[601, 448], [683, 448], [230, 717], [1097, 717]] M, M_inverse = cal_perspective_params(img, points) transform_img = img_perspect_transform(img, M) plt.figure(figsize=(20,8)) plt.subplot(1,2,1) plt.title('原始圖像') plt.imshow(img[:,:,::-1]) plt.subplot(1,2,2) plt.title('俯視圖') plt.imshow(transform_img[:,:,::-1]) plt.show()總結:
透視變換將檢測結果轉換為俯視圖。
代碼:
# encoding:utf-8 import cv2 import numpy as np import matplotlib.pyplot as plt #遍歷文件夾 import glob from moviepy.editor import VideoFileClip import sys reload(sys) sys.setdefaultencoding('utf-8')"""參數設置""" nx = 9 ny = 6 #獲取棋盤格數據 file_paths = glob.glob("./camera_cal/calibration*.jpg")# 繪制對比圖 def plot_contrast_image(origin_img, converted_img, origin_img_title="origin_img", converted_img_title="converted_img",converted_img_gray=False):fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 20))ax1.set_title = origin_img_titleax1.imshow(origin_img)ax2.set_title = converted_img_titleif converted_img_gray == True:ax2.imshow(converted_img, cmap="gray")else:ax2.imshow(converted_img)plt.show()#相機矯正使用opencv封裝好的api #目的:得到內參、外參、畸變系數 def cal_calibrate_params(file_paths):#存儲角點數據的坐標object_points = [] #角點在真實三維空間的位置image_points = [] #角點在圖像空間中的位置#生成角點在真實世界中的位置objp = np.zeros((nx*ny,3),np.float32)#以棋盤格作為坐標,每相鄰的黑白棋的相差1objp[:,:2] = np.mgrid[0:nx,0:ny].T.reshape(-1,2)#角點檢測for file_path in file_paths:img = cv2.imread(file_path)#將圖像灰度化gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#角點檢測rect,coners = cv2.findChessboardCorners(gray,(nx,ny),None)#若檢測到角點,則進行保存 即得到了真實坐標和圖像坐標if rect == True :object_points.append(objp)image_points.append(coners)# 相機較真ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(object_points, image_points, gray.shape[::-1], None, None)return ret, mtx, dist, rvecs, tvecs# 圖像去畸變:利用相機校正的內參,畸變系數 def img_undistort(img, mtx, dist):dis = cv2.undistort(img, mtx, dist, None, mtx)return dis#車道線提取 #顏色空間轉換--》邊緣檢測--》顏色閾值--》并且使用L通道進行白色的區域進行抑制 def pipeline(img,s_thresh = (170,255),sx_thresh=(40,200)):# 復制原圖像img = np.copy(img)# 顏色空間轉換hls = cv2.cvtColor(img,cv2.COLOR_RGB2HLS).astype(np.float)l_chanel = hls[:,:,1]s_chanel = hls[:,:,2]#sobel邊緣檢測sobelx = cv2.Sobel(l_chanel,cv2.CV_64F,1,0)#求絕對值abs_sobelx = np.absolute(sobelx)#將其轉換為8bit的整數scaled_sobel = np.uint8(255 * abs_sobelx / np.max(abs_sobelx))#對邊緣提取的結果進行二值化sxbinary = np.zeros_like(scaled_sobel)#邊緣位置賦值為1,非邊緣位置賦值為0sxbinary[(scaled_sobel >= sx_thresh[0]) & (scaled_sobel <= sx_thresh[1])] = 1#對S通道進行閾值處理s_binary = np.zeros_like(s_chanel)s_binary[(s_chanel >= s_thresh[0]) & (s_chanel <= s_thresh[1])] = 1# 結合邊緣提取結果和顏色通道的結果,color_binary = np.zeros_like(sxbinary)color_binary[((sxbinary == 1) | (s_binary == 1)) & (l_chanel > 100)] = 1return color_binary#透視變換-->將檢測結果轉換為俯視圖。 #獲取透視變換的參數矩陣【二值圖的四個點】 def cal_perspective_params(img,points):# x與y方向上的偏移offset_x = 330offset_y = 0#轉換之后img的大小img_size = (img.shape[1],img.shape[0])src = np.float32(points)#設置俯視圖中的對應的四個點 左上角 右上角 左下角 右下角dst = np.float32([[offset_x, offset_y], [img_size[0] - offset_x, offset_y],[offset_x, img_size[1] - offset_y], [img_size[0] - offset_x, img_size[1] - offset_y]])## 原圖像轉換到俯視圖M = cv2.getPerspectiveTransform(src, dst)# 俯視圖到原圖像M_inverse = cv2.getPerspectiveTransform(dst, src)return M, M_inverse#根據透視變化矩陣完成透視變換 def img_perspect_transform(img,M):#獲取圖像大小img_size = (img.shape[1],img.shape[0])#完成圖像的透視變化return cv2.warpPerspective(img,M,img_size)if __name__ == "__main__":#透視變換#獲取原圖的四個點img = cv2.imread('./test/straight_lines2.jpg')points = [[601, 448], [683, 448], [230, 717], [1097, 717]]#將四個點繪制到圖像上 (文件,坐標起點,坐標終點,顏色,連接起來)img = cv2.line(img, (601, 448), (683, 448), (0, 0, 255), 3)img = cv2.line(img, (683, 448), (1097, 717), (0, 0, 255), 3)img = cv2.line(img, (1097, 717), (230, 717), (0, 0, 255), 3)img = cv2.line(img, (230, 717), (601, 448), (0, 0, 255), 3)plt.figure()#反轉CV2中BGR 轉化為matplotlib的RGBplt.imshow(img[:, :, ::-1])plt.title("Original drawing")plt.show()#透視變換M,M_inverse = cal_perspective_params(img,points)if np.all(M != None):trasform_img = img_perspect_transform(img, M)plt.figure()plt.imshow(trasform_img[:, :, ::-1])plt.title("vertical view")plt.show()else:print("failed")效果圖:
?
?
總結
以上是生活随笔為你收集整理的智慧交通day03-车道线检测实现05:透视变换+代码实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构链表之栈——解决括号匹配问题和逆
- 下一篇: 智慧交通day02-车流量检测实现15: