近年來,由于無人機、無人車等技術的不斷成熟,需要用到實時測距的場所也越來越多,如定位,避障,測速等,相比于其他測距方法,單目測距是利用一個攝像頭進行視頻拍攝,在影像中找到待測物體,這一系列動作,涉及到了物體的識別,相機的結構,坐標變換的一些知識,距離的獲取是一個很廣泛的課題,用攝像頭來測距是其中一個方向,包括單目測距、雙目測距、結構光測距等方法,
在這里,我們主要用一個攝像頭通過建立一定的模型來解決測距的問題,
1. 安裝包
python 3.7 或以上
pip install cvzone
pip install mediapipe
2.成像原理
單目攝像頭的模型可以近似考慮為針孔模型,如圖所示

- f: 焦距
- W: 目標物體的實際寬度
- w: 成像后的寬度
- d: 物體與相機之間的實際距離或深度
f 、d、w、W的之間的關系如下:
d
f
=
W
w
\frac{d}{f}=\frac{W}{w}
fd?=wW?
2.1 相機校準
我們的目標是計算出目標物體的距離d,但前提需要知道焦距f,焦距f的計算公式如下:
f
=
w
?
d
W
f=\frac{w*d}{W}
f=Ww?d?
我們可以將一個物體放在離攝像頭已知的距離d,同時我們知道實際物體的寬度W,以及呈像后的寬度w,從而上述公式計算出焦距f,
2.2 計算物體的距離d
相機校準后,焦距f的值即為已知,根據如下公式,可計算出目標物體的距離:
d
=
f
?
W
w
d=\frac{f*W}{w}
d=wf?W?
如果我們知道已知物體的W,和成像后的w,就可以實時計算出目標物體的距離d,
3 案例介紹

本文以人臉兩只眼睛的距離作為目標物體的W, 由于男性兩只眼睛距離為64cm,女性兩只眼睛距離為62cm ,我們這里取平均值63作為人臉眼睛的距離,因此計算人臉的距離,只需知道成像后的w,即可計算出人臉離攝像頭的距離d.
3.1 檢測人臉
import cv2
import cvzone
import cvzone.FaceMeshModule import FaceMeshDetector
# 檢測人臉
detector=FaceMeshDetector(maxFaces=1)
cap=cv2.VideoCapture(0)
while True:
success,img =cap.read()
img,faces=detector.findFaceMesh(img)
cv2.imshow("Image",img)
cv2.waitKey(1)

3.2 計算視頻中雙眼的距離
import cv2
import cvzone
import cvzone.FaceMeshModule import FaceMeshDetector
# 檢測人臉
detector=FaceMeshDetector(maxFaces=1)
cap=cv2.VideoCapture(0)
while True:
success,img =cap.read()
img,faces=detector.findFaceMesh(img)
if faces:
face =faces[0]
pointLeft=face[145] #左眼中心點坐標
pointRight=face[375] #右眼中心點坐標
# 繪制人眼中心點并連線
cv2.line(img,pointLeft,pointRight,(0,200,0),3)
cv2.circle(img,pointLeft,5,(255,0,255),cv2.FILLED)
cv2.circle(img,pointRight,5,(255,0,255),cv2.FILLED)
w,_=detector.findDistance(pointLeft,pointRight)
print(w)
cv2.imshow("Image",img)
cv2.waitKey(1)

3.3 相機標定:計算焦距f
```python
import cv2
import cvzone
import cvzone.FaceMeshModule import FaceMeshDetector
# 檢測人臉
detector=FaceMeshDetector(maxFaces=1)
cap=cv2.VideoCapture(0)
while True:
success,img =cap.read()
img,faces=detector.findFaceMesh(img)
if faces:
face =faces[0]
pointLeft=face[145] #左眼中心點坐標
pointRight=face[375] #右眼中心點坐標
# 繪制人眼中心點并連線
cv2.line(img,pointLeft,pointRight,(0,200,0),3)
cv2.circle(img,pointLeft,5,(255,0,255),cv2.FILLED)
cv2.circle(img,pointRight,5,(255,0,255),cv2.FILLED)
w,_=detector.findDistance(pointLeft,pointRight) #保持人臉到攝像頭50cm下測量
# Finding the Focal Length
W=6.3 # 真實人臉間距 6.3cm
d= 50 # 保持人臉到攝像頭50cm的距離
f=(w*d)/W
print(f)
cv2.imshow("Image",img)
cv2.waitKey(1)
3.4 計算人臉到相機的距離
根據上一步,相機標定的結果,假設計算出相機的焦距f
f =840 mm
根據公式:
d
=
f
?
W
w
d=\frac{f*W}{w}
d=wf?W?
即可計算出實時的人臉到攝像頭的距離
import cv2
import cvzone
import cvzone.FaceMeshModule import FaceMeshDetector
# 檢測人臉
detector=FaceMeshDetector(maxFaces=1)
cap=cv2.VideoCapture(0)
while True:
success,img =cap.read()
img,faces=detector.findFaceMesh(img)
if faces:
face =faces[0]
pointLeft=face[145] #左眼中心點坐標
pointRight=face[375] #右眼中心點坐標
# 繪制人眼中心點并連線
cv2.line(img,pointLeft,pointRight,(0,200,0),3)
cv2.circle(img,pointLeft,5,(255,0,255),cv2.FILLED)
cv2.circle(img,pointRight,5,(255,0,255),cv2.FILLED)
w,_=detector.findDistance(pointLeft,pointRight) #保持人臉到攝像頭50cm下測量
W=6.3 # 真實人臉間距 6.3cm
# Finding the Focal Length
# d= 50 # 保持人臉到攝像頭50cm的距離
# f=(w*d)/W
# print(f)
# Finding distance
f = 840 # 根據相機標定的結果
d = (W * f)/w
print(d)
cvzone.putTextRect(img,f'Depth:{int(d)}cm',(face[10][0]-100,face[10][1]-50),scale=2)
cv2.imshow("Image",img)
cv2.waitKey(1)

可以看到:人臉靠近相機d越來越小,遠離相機d越來越小,從而可以大致判斷出人臉離相機的距離,雖然達不到深度相機那么精確,但在某些場景中,該計算出的距離應用起來可以有不錯的效果
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/423700.html
標籤:AI
