【自动驾驶】摄像头单目测距原理及实现
原文鏈接:攝像頭單目測距原理及實現
可以觀看這個視頻,了解針孔相機和透鏡。
攝像頭單目測距原理及實現
一.測距原理
空間的深度或距離等數據的攝像頭。
人的眼睛長在頭部的前方,兩只眼的視野范圍重疊,兩眼同時看某一物體時,產生的視覺稱為雙眼視覺。
雙眼視覺的優點是可以彌補單眼視野中的盲區缺損,擴大視野,并產生立體視覺。
也就是說,假如只有一只眼睛,失去立體視覺后,人判斷距離的能力將會下降。
這也就是單目失明的人不能考取駕照的原因。
單純的單目視覺測距,必須已知一個確定的長度。
f為攝像頭的焦距,c為鏡頭光心。物體發出的光經過相機的光心,然后成像于圖像傳感器或者也可以說是像平面上,如果設物體所在平面與相機平面的距離為d,物體實際高度為H,在傳感器上的高度為h,H一定要是已知的,我們才能求得距離d。
下面的相機焦距f并不是透鏡的焦距,而是焦距+z0,這個我們必須要清楚。因為成像是在像平面,并不是成像在焦平面,焦平面的距離才是f,但是我們下面的模型不需要知道實際的f,所以就使用了像平面的距離焦距f+z0作為相機焦距f。
由相似三角形,可以得到:
hH=fd\color{red}\frac{h}{H}=\frac{f}ozvdkddzhkzdHh?=df?
第一步,求相機焦距:
對于蠟燭,我們可以:
- 1.測量蠟燭的高度 H\color{red}HH,作為先驗知識;
- 2.測量蠟燭到相機光心的距離 d\color{red}dd;
- 3.通過相機拍攝的這一幀蠟燭圖像,可以得到蠟燭在圖像中的高度所占像素個數 h\color{red}hh;
知道了H,h,d\color{red}H,h,dH,h,d這三個量,就可以求出相機的焦距f\color{red}ff,即:
f=h?dH\color{red}f=\frac{h*d}{H}f=Hh?d?
需要注意,相機的焦距是個固定值,只要使用該方法求出焦距后,以后就不用再求了。但是,可能需要多次測量求平均值。
第二步,求物體距離相機的實際距離:
得到了相機焦距f\color{red}ff,對于放在其他位置的任意物體,就可以根據:
- 1.該物體的先驗值高度 H\color{red}HH;
- 2.統計出該物體在該幀圖像中的高度所占像素個數 h\color{red}hh;
- 3.前面求出來的相機焦距固定值 f\color{red}ff;
得到物體距離相機的實際距離d\color{red}dd:
d=H?fh\color{red}d=\frac{H*f}{h}d=hH?f?
同理,你也可以通過測量蠟燭的寬度來求相機的焦距f\color{red}ff。
假設我們有一個寬度為 W 的目標或者物體。然后我們將這個目標放在距離我們的相機為d 的位置。我們用相機對物體進行拍照并且測量物體的像素寬度w 。這樣我們就得出了相機焦距的公式:f=w?dW\color{red}f = \frac{w *d}{ W}f=Ww?d?
例如,假設現在我們有一張A4紙(8.27in x 11.69in), in代表英寸,1in = 25.4mm。
紙張寬度W=11.69in,相機距離紙張的距離d = 32in。
此時拍下的照片中A4紙的像素寬度為w=192px(我的相機實際測量得到的值)。
此時我們可以算出焦距f=(192?30)/11.69\color{red} f=(192*30)/11.69f=(192?30)/11.69
當我們將攝像頭遠離或者靠近A4紙時,就可以用相似三角形得到相機距離物體的距離。
此時的距離: d′=W′?fw′\color{red}d' = \frac{W' * f } {w'}d′=w′W′?f?
注意:這里測量的距離是相機到物體的垂直距離,產生夾角,測量的結果就不準確了。為什么?下圖說明結果并不會不準確啊?
二.測距步驟:
- 1.使用攝像機采集道路前方的圖像;
- 2.在道路區域對物體進行檢測,通過矩形框將物體形狀框出來。
- 3.結合矩形框信息,找到該矩形框底邊的兩個像平面坐標,分別記為(u1,v1)和(u2,v2);
- 4.使用幾何關系推導法,由像平面坐標點(u1, v1)、(u2, v2)推導出道路平面坐標(x1,y1)、(x2, y2);(投影到地面上,z軸為0)
- 5.通過歐氏距離公式計算出d。
三.難點整理:
- 1.圖像畸變矯正模型的理解;
(標定參數,內參矩陣,畸變矩陣,外參矩陣(平移、旋轉向量矩陣))
- 2.像素坐標與世界坐標公式的推導及驗證;
- 3.測距方法,對于檢測物體在攝像頭前方、左側、右側的判別思路;(為什么?)
- 4.弄清反畸變;對于畸變矯正后的圖像中的檢測框中的點進行反畸變處理。
四.相機鏡頭畸變矯正–>得到相機的內外參數、畸變參數矩陣
1. 外參數矩陣。世界坐標經過旋轉和平移,然后落到另一個現實世界點(攝像機坐標)上。
2. 內參數矩陣。告訴你上述那個點在1的基礎上,是如何繼續經過攝像機的鏡頭、并通過針孔成像和電子轉化而成為像素點的。
3. 畸變矩陣。告訴你為什么上面那個像素點并沒有落在理論計算該落在的位置上,還產生了一定的偏移和變形.
五.實現代碼
#!/usr/bin/python3# -- coding: utf-8 --# Date: 18-10-29import numpy as np # 導入numpy庫import cv2 # 導入Opencv庫KNOWN_DISTANCE = 32 # 這個距離自己實際測量一下KNOWN_WIDTH = 11.69 # A4紙的寬度KNOWN_HEIGHT = 8.27IMAGE_PATHS = [“Picture1.jpg”, “Picture2.jpg”, “Picture3.jpg”] # 將用到的圖片放到了一個列表中# 定義目標函數def find_marker(image):gray_img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 將彩色圖轉化為灰度圖gray_img = cv2.GaussianBlur(gray_img, (5, 5), 0) # 高斯平滑去噪edged_img = cv2.Canny(gray_img, 35, 125) # Canny算子閾值化cv2.imshow(“降噪效果圖”, edged_img) # 顯示降噪后的圖片# 獲取紙張的輪廓數據img, countours, hierarchy = cv2.findContours(edged_img.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)# print(len(countours))c = max(countours, key=cv2.contourArea) # 獲取最大面積對應的點集rect = cv2.minAreaRect? # 最小外接矩形return rect# 定義距離函數def distance_to_camera(knownWidth, focalLength, perWidth):return (knownWidth * focalLength) / perWidth# 計算攝像頭的焦距(內參)def calculate_focalDistance(img_path):first_image = cv2.imread(img_path) # 這里根據準備的第一張圖片,計算焦距# cv2.imshow(‘first image’, first_image)marker = find_marker(first_image) # 獲取矩形的中心點坐標,長度,寬度和旋轉角度focalLength = (marker[1][0] * KNOWN_DISTANCE) / KNOWN_WIDTH # 獲取攝像頭的焦距# print(marker[1][0])print('焦距(focalLength) = ', focalLength) # 打印焦距的值return focalLength# 計算攝像頭到物體的距離def calculate_Distance(image_path, focalLength_value):image = cv2.imread(image_path)# cv2.imshow(“原圖”, image)marker = find_marker(image) # 獲取矩形的中心點坐標,長度,寬度和旋轉角度, marke[1][0]代表寬度distance_inches = distance_to_camera(KNOWN_WIDTH, focalLength_value, marker[1][0])box = cv2.boxPoints(marker)# print("Box = ", box)box = np.int0(box)print("Box = ", box)cv2.drawContours(image, [box], -1, (0, 255, 0), 2) # 繪制物體輪廓cv2.putText(image, “%.2fcm” % (distance_inches * 2.54), (image.shape[1] - 300, image.shape[0] - 20),cv2.FONT_HERSHEY_SIMPLEX, 2.0, (0, 255, 0), 3)cv2.imshow(“單目測距”, image)if name == “main”:img_path = “Picture1.jpg”focalLength = calculate_focalDistance(img_path)for image_path in IMAGE_PATHS:calculate_Distance(image_path, focalLength)cv2.waitKey(0)cv2.destroyAllWindows()
總結
以上是生活随笔為你收集整理的【自动驾驶】摄像头单目测距原理及实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【自动驾驶】视觉里程计
- 下一篇: 【自动驾驶】定位方式:RTK定位与激光融