OpenCV:如何使用图像计算相机和物体之间的距离?

46

我是OpenCV的新手。我正在使用以下公式来计算距离:

distance to object (mm) = focal length (mm) * real height of the object (mm) * image height (pixels)
                          ----------------------------------------------------------------
                                object height (pixels) * sensor height (mm)

OpenCV中是否有可以确定物体距离的函数?如果没有,有示例代码参考吗?


6
+1 寻找同样的解决方案,你找到任何解决方法了吗? - Mangesh
3个回答

62

如何计算已知大小物体的距离

你需要事先知道以下两件事之一

  • 焦距(以毫米和每毫米像素为单位)
  • 图像传感器的物理尺寸(以计算每毫米像素)

我将使用焦距,因为我不想为传感器数据表搜索谷歌。

校准相机

使用OpenCV的calibrate.py工具和提供在源代码中的棋盘格图案PNG生成校准矩阵。我从尽可能多的角度拍摄了大约两打棋盘格照片,并将文件导出到我的Mac。有关更多详细信息,请查看OpenCV相机校准文档

相机校准矩阵(iPhone 5S后置摄像头)

RMS: 1.13707201375
camera matrix:
[[  2.80360356e+03   0.00000000e+00   1.63679133e+03]
 [  0.00000000e+00   2.80521893e+03   1.27078235e+03]
 [  0.00000000e+00   0.00000000e+00   1.00000000e+00]]
distortion coefficients:  [ 0.03716712  0.29130959  0.00289784 -0.00262589 -1.73944359]
  • f_x = 2803,对应横向焦距
  • f_y = 2805,对应纵向焦距
  • c_x = 1637,图像中心点的横坐标
  • c_y = 1271,图像中心点的纵坐标

检查你拍摄的棋盘照片系列的细节,可以发现照片的本机分辨率(3264x2448),并且在它们的JPEG EXIF header中,可在iPhoto中找到焦距值(4.15mm)。这些项目应根据相机而异。

每毫米像素数

我们需要知道图像传感器上的像素每毫米(px/mm)。从相机重定位页面上得知,f_x和f_y是焦距乘以缩放因子。

f_x = f * m_x
f_y = f * m_y

由于每个公式都有两个变量,我们可以解出m_x和m_y的值。我只是将2803和2805取平均值得到了2804。

m = 2804px / 4.15mm = 676px/mm 

像素中的对象大小

我使用OpenCV(C++)来获取旋转矩形的点,并确定对象的大小为41px。请注意,我已经检索到了对象的角落,并要求边界矩形给出其大小。

cv::RotatedRect box = cv::minAreaRect(cv::Mat(points));

小皱纹

该物体在640x480的摄像机拍摄视频中为41像素。

在低分辨率下将px转换为mm

3264/676 = 640/x
x = 133 px/mm

所以,根据 41px/133px/mm 的比例,我们可以看出图像传感器上物体的大小为 0.308mm。

距离公式

distance_mm = object_real_world_mm * focal-length_mm / object_image_sensor_mm
distance_mm = 70mm * 4.15mm / .308mm
distance_mm = 943mm

这很不错。我测量了910毫米,通过一些改进,我可能可以减少误差。
欢迎反馈。
类似三角形方法
Adrian在pyimagesearch.com演示了使用类似三角形的不同技术。我们之前讨论过这个话题,他采用了类似三角形的方法,而我则采用了相机内参法。

非常好的解释。但是如果您无法校准相机,您是否也可以这样做?那么您会使用本机相机分辨率吗?在不纠正畸变的情况下,这有多可靠?如何仅使用本机分辨率应用此方法?对于这么多问题,我很抱歉 ;) - Sander
1
没有相机校准,你的测量结果会出现偏差。我想你可以使用传感器规格来获取测量数据,或者建立一个包含各种设备中相机信息的数据库。我们可以合理地假设所有 iPhone 5s 后置摄像头都在某些严格的公差范围内。此外,找出如何转储高通 Vuforia 库的相机校准数据库可能是某个人需要调查的任务。 - Cameron Lowell Palmer
@Sander 是的,这是唯一两种方法。祝你好运! - Cameron Lowell Palmer
有点晚了,但这与此处答案40基本相同:https://photo.stackexchange.com/questions/12434/how-do-i-calculate-the-distance-of-an-object-in-a-photo/12437#12437。只是讲述方式不同而已。但是内容是一样的 :) - decades
有一些改进的话,我可能可以减少误差。我很好奇你在考虑哪些改进。我猜你不是用平均值m,而是分别使用m_x和m_y。你会在计算中使用更多小数位数吗? - undefined
显示剩余5条评论

1

相机参数我一直保持不变,我已经知道它们。 - swapna

0
  1. 如果没有相机的先前信息,想要获得真实世界和相机之间的映射,您需要对相机进行校准...在这里您可以找到一些理论
  2. 为了计算深度,即相机与物体之间的距离,您需要至少使用两个不同相机拍摄同一物体的两张图像...这通常被称为立体视觉技术。

需要两个摄像头吗? - swapna
1
你所提供的公式是在相机的主轴垂直于物体平面的理想情况下...但如果相机的主轴倾斜于物体平面(这通常是真实世界的情况...),那么我们得到的是物体在图像中的投影...投影图像不能给出物体在现实世界中的正确尺寸...因此,如果你没有关于相机与物体方向的任何先前了解,使用一个相机就很困难。 - rotating_image
如果您已经知道摄像机的所有细节,您是否仍需要校准摄像机? - Crashalot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接