<p>为了获得真正的准确度,你需要校准相机。下面的结果对于一阶近似就足够了。在</p>
<p>下面的图像描述了我将在这个响应中使用的图像坐标系(Xi,Yi)</em>和相机坐标系(Xc,Yc,Zc)</em>它们是OpenCV使用的坐标系。它还显示两个图像点<em>p1</em>和<em>p2</em>,这可能是您感兴趣对象的图像的边界,并且相应的光线<em>r1</em>和<em>r2</em>将它们投影到相机中心。在</p>
<p><a href="https://i.stack.imgur.com/YMRk8.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/YMRk8.png" alt="Image axes"/></a></p>
<p>首先,让我们将焦距镜头转换为像素以简化计算。在4.8 um点距时,传感器的宽度为4.8*1280 um=6.14 mm。因此,按比例,f_pix:8 mm=1280 pix:6.14 mm,因此f_pix=1667像素。我们现在可以写出最简单的针孔摄像机矩阵,假设摄像机的焦轴与图像正交,并与图像中心相交。用纽比的符号:</p>
<pre><code>K = np.array([[1667, 0, 640], [0, 1667, 512], [0, 0, 1]])
</code></pre>
<p>给定该矩阵,且摄像机坐标中的任何3D点<em>p=(X,Y,Z)</em>,其投影到图像上的图像坐标<em>(X,Y)</em>计算如下:</p>
^{pr2}$
<p>相反,给定一对像素坐标<em>(x,y)</em>,则将该像素反向投影到3D空间的3D光线<em>r</em>由下式给出:</p>
<pre><code>Ki = np.linalg.inv(K)
r = Ki.dot([x, y, 1.0])
</code></pre>
<p>这是一条“射线”,在这个意义上,所有3D点<em>R=s*R</em>将位于穿过相机中心和像素<em>(x,y)</em>的同一条线上。在</p>
<p>因此,给定边界图像点<em>p1=(x1,y1)</em>和<em>p2=(x2,y2)</em>,您可以如上所述计算射线<em>r1</em>和<em>r2</em>将它们反向投影到三维空间中。它们之间的角度可以通过点积公式轻松计算:</p>
<pre><code>cos_angle = r1.dot(r2) / (np.linalg.norm(r1) * np.linalg.norm(r2))
angle_radians = np.acos(cos_angle)
</code></pre>
<p>重申一下,以上公式只是一个近似值。一个真正的相机会有一些非线性的镜头失真,你必须纠正这些失真才能得到准确的结果,并且会有一个相对于图像稍微偏离中心的焦轴。所有这些问题都是通过校准摄像机来解决的。在</p>