一起做双目测距-USB_CAMERA检测人脸距离系列(1)--OpenCV打开双目摄像头

前言

说到双目测距这个东西,既然没有深度图,那就是要从两幅图的几何关系去求解这个深度,毕竟多了一只眼睛,总得有点用处吧?
(废话)
那到底怎么样去算啊?
别急,要了解双目相机,首先我们要做的是弄清楚单目相机,这里特指针孔相机的模型:

针孔相机模型

在这里插入图片描述
根据初中学过的相似三角形公式我们不难得到以下式子:
Z f = − X X ′ = − Y Y ′ (1) \frac{Z}{f}=-\frac{X}{X^{'}}=-\frac{Y}{Y^{'}} \tag{1} fZ=XX=YY(1)
负号表示在相机sensor上的成像是倒着的,如果我们把sensor放到光心前面来,那么相似三角形的关系依然是成立的,只是负号要去掉
Z f = X X ′ = Y Y ′ (2) \frac{Z}{f}=\frac{X}{X^{'}}=\frac{Y}{Y^{'}} \tag{2} fZ=XX=YY(2)
整理这个公式,把像素坐标 ( X ′ , Y ′ ) (X^{'},Y^{'}) (X,Y)表示如下:
X ′ = f X Z , Y ′ = f Y Z (3) X^{'}=f\frac{X}{Z}, Y^{'}=f\frac{Y}{Z} \tag{3} X=fZX,Y=fZY(3)
好了,到目前为止我们得到的都是真实的长度,不管是 ( X , Y ) (X,Y) (X,Y)还是 ( X ′ , Y ′ ) (X^{'},Y^{'}) (X,Y),都是实实在在的物理坐标,那么在一张图片中我们通常会用像素pixel去描述图像的大小,比如说1920x1080,或者640x480这里的像素是没有单位的,那么必然就存在一个将物理尺度转换为像素的比例系数,我们设为 α \alpha α β \beta β,之所以要用到两个尺度系数是为了对应图像的高和宽
另外,我们也必须要了解,像素的计算起点并不是在图像的中心,否则我们就会得到荒唐的负数像素,它在图像的左上角,因此存在一个以像素为单位的偏移量
好了,讲了这么多,应该看懂下面这个式子了

u = α X ′ + c x , v = β Y ′ + c y (4) u=\alpha X^{'}+c_{x},v=\beta Y^{'}+c_{y} \tag{4} u=αX+cx,v=βY+cy(4)
A step further,把(3)式代入(4)式:
u = α f X Z + c x = f x X Z + c x , v = β f Y Z + c y = f y Y Z + c y (4) u=\alpha f\frac{X}{Z}+c_{x} = f_{x}\frac{X}{Z}+c_{x},v=\beta f\frac{Y}{Z}+c_{y}=f_{y}\frac{Y}{Z}+c_{y} \tag{4} u=αfZX+cx=fxZX+cx,v=βfZY+cy=fyZY+cy(4)
写成紧凑的矩阵形式
( u v 1 ) = 1 Z ( f x 0 c x 0 f y c y 0 0 1 ) ( X Y Z ) = 1 Z K P (5) \left(\begin{array}{cccc} u \\ v \\ 1 \end{array}\right) =\frac{1}{Z}\left(\begin{array}{cccc} f_{x}&0&c_{x}\\ 0&f_{y}&c_{y}\\ 0&0&1 \end{array}\right)\left(\begin{array}{cccc} X\\ Y\\ Z \end{array}\right) =\frac{1}{Z}KP \tag{5} uv1=Z1fx000fy0cxcy1XYZ=Z1KP(5)
不难看出,知道 ( u , v ) (u,v) (u,v)和内参矩阵K并不能让你横行霸道,因为还有一位大佬叫 Z Z Z,不熟悉的人叫它z坐标的值,熟悉的人只管它叫深度,单目具有深度不确定性!
OK,Fine。。。。。

三角测量

那怎么样我才能知道Z呢?又或者说我怎么才能获得真实的坐标 ( X , Y , Z ) (X,Y,Z) (X,Y,Z)呢?
初高中数学物理里面重要的思想是解方程~
可我们只有(5)这一个式子啊?
那再想办法加一个式子呗!
各位客官请看下面这个图,有了单目的基础,暂且假定你能看懂这幅图的大致意思…

O 1 O_{1} O1 O 2 O_{2} O2呢就是双目的光心了, I 1 I_{1} I1 I 2 I_{2} I2呢是相机的sensor平面拿到相机前面的结果了,在单目相机中我们就做了这样一个假设,现在假定世界坐标系下存在一个点 P P P,它在 I 1 I_{1} I1 I 2 I_{2} I2平面上的成像分别为 p 1 p_{1} p1 p 2 p_{2} p2
现在我们做一些专业性的假设:
1、极平面
O 1 O 2 P O_{1}O_{2}P O1O2P
2、极点
O 1 O 2 O_{1}O_{2} O1O2分别与 I 1 I_{1} I1 I 2 I_{2} I2的交点 e 1 e_{1} e1 e 2 e_{2} e2称为极点
3、基线
O 1 O 2 O_{1}O_{2} O1O2
4、极线
像素点与极点的连线,图中的 l 1 l_{1} l1 l 2 l_{2} l2

几何关系

假设 I 1 I_{1} I1 I 2 I_{2} I2之间的旋转平移变换分别为R和T,并且我们假设两个相机的内参矩阵都是K,我们不难得到以下公式
s 1 p 1 = K P s 2 p 2 = K ( R P + T ) (6) s_{1}p_{1}=KP \\ s_{2}p_{2}=K(RP+T) \tag{6} s1p1=KPs2p2=K(RP+T)(6)
这里的 s 1 s_{1} s1还有 s 2 s_{2} s2如果细心地话,读者会发现其实就是P分别对于两个相机的深度 Z 1 Z_{1} Z1 Z 2 Z_{2} Z2,也就是我们的主题,双目测距的距离

那么,有读者要问了,一共两个方程,可是有5个未知数啊???
纳尼?有五个未知数吗?
你看, s 1 s_{1} s1, s 2 s_{2} s2, R R R, T T T, P P P都是未知数啊
嗯,至少在我看来啊这里面只有一个未知数,那就是 s 1 s_{1} s1
至于为什么,我们往下看一下双目相机一般长啥样我们再讨论这个问题~

工具准备:

双目相机

实验用的的是USB的双目相机,它长酱紫:
在这里插入图片描述
首先,我们来解释一下为什么只有一个 s 1 s_{1} s1是未知的,两个相机生产的时候R,T已经是固定的,最简单的做法是直接把R设为 I I I,然后拿一把刻度尺去量一下两个相机的平移
如果你觉得这个做法太粗鲁难看了,往下面看,我们还有双目相机的标定系列~
其次,这两货的深度其实一样。。。也就意味着 s 1 = s 2 s_{1}=s_{2} s1=s2,这样一来好像就剩下 s 1 s_{1} s1未知了~
噢,我好想知道该怎么解这组方程了!
但是,我要说的是但是,这不是我们今天的主题,虽然你可以编程去把这个深度求出来(其实很简单),但有工具不用那不是小狗吗??
作为第一节课的末尾,我们需要教大家如何开启这双眼睛!拿起的USB线,勇敢的把它连在你的电脑上,然后打开你的代码IDE,Let‘s start!

在这里插入图片描述
一双看起来有智慧的双眼~
在这里插入图片描述

from imutils.video import VideoStream
import cv2
import time

vs = VideoStream(src=0, usePiCamera=False, resolution=(1280, 480),
		framerate=60).start()
time.sleep(2.0)

while True:
    frame = vs.read()
    cv2.imshow("Frame", frame)
    key = cv2.waitKey(1) & 0xFF
    if key == ord("q"):
        break
		

cv2.destroyAllWindows()

opencv的cv2就不多说了,imutils是Github上大神重写的opencv函数(就是觉得opencv太垃圾了,重新写了几个函数给自己用。。。)

pip3 install imutils

先把imutils安装一下就好了,另外默认的src=0是电脑摄像头,如果你的电脑有外接摄像头,可以尝试把src改成1,因为它不是0就是1(废话)
本系列全部代码,请移步 https://github.com/hitsz-zuoqi/Binoculars-tutorial
如果你感觉有用,star for me 是对我最大的鼓励

©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页