您當前的位置:首頁 > 攝影

使用OpenCV實現攝像頭測距

作者:由 程式設計師阿德 發表于 攝影時間:2019-04-20

原文連結:

攝像頭測距就是計算照片中的目標物體到相機的距離。可以使用相似三角形(triangle similarity)方法實現,或者使用更復雜但更準確的相機模型的內參來實現這個功能。

使用相似三角形計算物體到相機的距離

假設物體的寬度為 W,將其放到離相機距離為 D 的位置,然後對物體進行拍照。在照片上量出物體的畫素寬度 P,於是可以得出計算相機焦距 F 的公式:

F = (P \cdot D) / W

比如我在相機前 24 英寸距離(D=24 inches)的位置橫著放了一張 8。5 x 11 英寸(W=11 inches)的紙,拍照後透過影象處理得出照片上紙的畫素寬度 P=248 pixels。

所以焦距 F 等於:

F = (P \cdot D) / W =  (248px \cdot 24in) / 11in = 543.45px

此時移動相機離物體更近或者更遠,我們可以應用相似三角形得到計算物體到相機的距離的公式:

D

原理大概就是這樣,接下來使用 OpenCV 來實現。

獲取目標輪廓

# import the necessary packages

from

imutils

import

paths

import

numpy

as

np

import

imutils

import

cv2

def

find_marker

image

):

# convert the image to grayscale, blur it, and detect edges

gray

=

cv2

cvtColor

image

cv2

COLOR_BGR2GRAY

gray

=

cv2

GaussianBlur

gray

5

5

),

0

edged

=

cv2

Canny

gray

35

125

# find the contours in the edged image and keep the largest one;

# we‘ll assume that this is our piece of paper in the image

cnts

=

cv2

findContours

edged

copy

(),

cv2

RETR_LIST

cv2

CHAIN_APPROX_SIMPLE

cnts

=

imutils

grab_contours

cnts

c

=

max

cnts

key

=

cv2

contourArea

# compute the bounding box of the of the paper region and return it

return

cv2

minAreaRect

c

定義一個

find_marker

函式,接收一個引數

iamge

,用來找到要計算距離的物體。

這裡我們用一張 8。5 x 11 英寸的紙作為目標物體。

第一個任務是在圖片中找到目標物體。

下面這三行是先將圖片轉換為灰度圖,並進行輕微模糊處理以去除高頻噪聲,然後進行邊緣檢測。

gray

=

cv2

cvtColor

image

cv2

COLOR_BGR2GRAY

gray

=

cv2

GaussianBlur

gray

5

5

),

0

edged

=

cv2

Canny

gray

35

125

做了這幾步後圖片看起來是這樣的:

使用OpenCV實現攝像頭測距

現在已經可以清晰地看到這張紙的邊緣,接下來需要做的是找出這張紙的輪廓。

cnts

=

cv2

findContours

edged

copy

(),

cv2

RETR_LIST

cv2

CHAIN_APPROX_SIMPLE

cnts

=

imutils

grab_contours

cnts

c

=

max

cnts

key

=

cv2

contourArea

cv2。findContours

函式找到圖片中的眾多輪廓,然後獲取其中面積最大的輪廓,並假設這是目標物體的輪廓。

這種假設只適用於我們這個場景,在實際使用時,在圖片中找出目標物體的方法與應用場景有很大關係。

我們這個場景用簡單的邊緣檢測並找出最大的輪廓就可以了。當然為了使程式更具有魯棒性,也可以用輪廓近似,並剔除不是四個點的輪廓(紙張是一個有四個點的矩形),然後再找出面積最大,具有四個點的輪廓。

注意: 關於這個方法,詳情可以檢視這篇文章,用於構建一個移動文字掃描工具。

我們也可以根據

顏色特徵

在圖片中找到目標物體,因為目標物體和背景的顏色有著很明顯的不同。還可以應用關鍵點檢測(keypoint detection),區域性不變性描述子(local invariant descriptors)和關鍵點匹配(keypoint matching)來尋找目標。

但是這些方法不在本文的討論範圍內,而且高度依賴具體場景。

我們現在得到目標物體的輪廓了,

find_marker

函式最後返回的是包含輪廓 (x, y) 座標、畫素長度和畫素寬度的邊框,

計算距離

接下來該使用相似三角形計算目標到相機的距離。

def

distance_to_camera

knownWidth

focalLength

perWidth

):

# compute and return the distance from the maker to the camera

return

knownWidth

*

focalLength

/

perWidth

distance_to_camera

函式傳入目標的實際寬度,計算得到的焦距和圖片上目標的畫素寬度,就可以透過相似三角形公式計算目標到相機的距離了。

下面是呼叫

distance_to_camera

函式之前的準備:

# initialize the known distance from the camera to the object, which

# in this case is 24 inches

KNOWN_DISTANCE

=

24。0

# initialize the known object width, which in this case, the piece of

# paper is 12 inches wide

KNOWN_WIDTH

=

11。0

# load the furst image that contains an object that is KNOWN TO BE 2 feet

# from our camera, then find the paper marker in the image, and initialize

# the focal length

image

=

cv2

imread

“images/2ft。jpg”

marker

=

find_marker

image

focalLength

=

marker

1

][

0

*

KNOWN_DISTANCE

/

KNOWN_WIDTH

首先是測量目標物體的寬度,和目標物體到相機的距離,並根據上面介紹的方法計算相機的焦距。

其實這些並不是真正的攝像機標定。真正的攝像機標定包括攝像機的內參,相關知識可以可以檢視這裡。

使用

cv2。imread

函式從磁碟載入圖片,然後透過

find_marker

函式得到圖片中目標物體的座標和長寬資訊,最後根據相似三角形計算出相機的焦距。

現在有了相機的焦距,就可以計算目標物體到相機的距離了。

# loop over the images

for

imagePath

in

sorted

paths

list_images

“images”

)):

# load the image, find the marker in the image, then compute the

# distance to the marker from the camera

image

=

cv2

imread

imagePath

marker

=

find_marker

image

inches

=

distance_to_camera

KNOWN_WIDTH

focalLength

marker

1

][

0

])

# draw a bounding box around the image and display it

box

=

cv2

cv

BoxPoints

marker

if

imutils

is_cv2

()

else

cv2

boxPoints

marker

box

=

np

int0

box

cv2

drawContours

image

box

],

-

1

0

255

0

),

2

cv2

putText

image

%。2f

ft”

%

inches

/

12

),

image

shape

1

-

200

image

shape

0

-

20

),

cv2

FONT_HERSHEY_SIMPLEX

2。0

0

255

0

),

3

cv2

imshow

“image”

image

cv2

waitKey

0

使用 for 迴圈遍歷每個圖片,計算每張圖片中目標物件到相機的距離。

在結果中,我們根據得到的輪廓資訊將方框畫了出來,並顯示出了距離。

下面是得到的幾個結果圖:

使用OpenCV實現攝像頭測距

使用OpenCV實現攝像頭測距

總結

透過這篇文章,我們學會了使用相似三角形計算圖片中一個已知物體到相機的距離。

需要先測量出目標物體的實際寬度和目標物體到相機的距離,然後使用影象處理的方法自動計算圖片中目標物體的畫素寬度,並使用相似三角形計算出相機的焦距。

根據相機的焦距就可以計算圖片中的目標物體到相機的距離。

標簽: cv2  Image  相機  Marker  物體