OpenCV:以毫米为单位测量两个球之间的距离——如何提高精度

标签 opencv

我还在 opencv.org 的问答论坛上发布了这个主题,但我不知道这里有多少专家正在阅读这个论坛 - 所以请原谅我也在这里尝试。

我目前正在学习 OpenCV,我目前的任务是测量平放在盘子上的两个球之间的距离。我的下一步是比较几个相机和分辨率,以了解分辨率、噪声、失真等的重要性以及这些参数对精度的影响程度。如果社区对结果感兴趣,我很乐意在结果准备好后与大家分享!使用广角镜头将相机放置在板上方。板的宽度和高度 (1500 x 700 mm) 以及球的半径 (40 mm) 是已知的。

到目前为止我的步骤:

  1. 相机校准
  2. 消除图像失真(由于广角镜头,失真度很高)
  3. findHomography:我使用板的角点作为输入(未失真图像中以像素为单位的 4 个点)和以毫米为单位的角点(从左下角的 0,0 开始,到 1500,700右上角)
  4. 使用 HoughCircles 在未失真的图像中找到球
  5. 在圆心点上应用 perspectiveTransform => 圆心点现在以毫米为单位
  6. 计算两个中心点的距离:d = sqrt((x1-x2)^2+(y1-y2)^2)

结果:距离 300 毫米时误差约为 4 毫米,距离 1000 毫米时误差约为 25 毫米但如果我测量的是打印在印版上的矩形,则误差小于 0.2 毫米,所以我猜校准和不失真效果很好。

我想了想,找出了三个可能的原因:

  1. findHomography 应用于直接位于板上的点,而球的中心点应在赤道高度进行测量 => 如何更改 findHomography 的结果以更改此结果,即“移动”飞机?以毫米为单位的半径已知。
  2. 随着球与光学中心的距离增加,误差会增加,因为相机不会从顶部看到球,因此图像 2D 投影的中心点与 3D 世界中的中心点不同 - 我我们将进一步投影到图像的边界。 => 是否可以对找到的中心应用任何几何操作来更正值?
  3. 在去失真过程中可能会丢失信息,因为我生成了一个新的未失真图像并返回到像素精度,尽管我在失真矩阵中有很多浮点值。 是否应该在失真图像中搜索球并仅使用失真矩阵变换中心点?但是我不知道这个任务的代码是什么。

我希望有人可以帮助我改进这一点,我希望这个话题对其他 OpenCV 入门者来说很有趣。

谢谢并致以最诚挚的问候!

最佳答案

这里有一些想法可以帮助您……但绝不是“答案”。

首先是一个简单的。如果您在距离为 D 的特定平面上以毫米为单位校准了图像,则 r 更近的点将显得比实际大。要从测量坐标到实际坐标,您可以使用

Actual = measured * (D-r)/D

因此,由于球体的中心在平面上方的半径为 r,因此上面的公式应该可以回答您问题的第 1 部分。

关于第二个问题:如果你仔细想想,即使你从一个角度看,你看到的球心应该在“球心所在的平面内”的正确位置。给自己画一幅画,让自己相信这是事实。

第三个问题:如果你在扭曲的图像中找到球体的坐标,你应该能够使用 perspectiveTransform 将它们转换为校正后的图像。 .这可能会稍微提高准确性 - 但我对您看到的错误大小感到惊讶。最大距离(1000mm)的单个像素有多大?

编辑

您问的是椭圆投影等。基本上,如果您将相机的光心视为光源,并将球在平面上的影子视为您的“2D 图像”,则可以绘制一幅图刚好击中球两侧的光线,并确定不同的角度:

enter image description here

很容易看出P(A和B的中点)和C(球心的投影)不一样。多一点三角将告诉您错误 C - (A+B)/2 随着 x 的增加而增加,随着 D 的增加而减少。如果您知道 A 和 B,则可以根据以下公式计算出 C(给定 D)的正确位置:

C = D * tan( (atan(B/D) + atan(A/D)) / 2 )

D 越小和/或 x 越大,误差越大。注D为镜头到物平面的垂直(最短)距离。

这仅在相机像“真正的镜头”一样工作时才有效 - 换句话说,没有枕形失真,并且图像平面中的矩形映射到传感器上的矩形。以上结合您自己的想法以适应未校正的(“像素”)空间,然后转换使用 perspectiveTransform 找到的中心,应该可以让您一路到达那里。

看看你能用它做什么!

关于OpenCV:以毫米为单位测量两个球之间的距离——如何提高精度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16378497/

相关文章:

python - 如何从图像中找到各种颜色而不给出颜色范围

OpenCV GpuMat 用法

opencv - 在树莓派上使用cmake构建opencv时出错

opencv - 如何加载具有 4 个 channel 的 png 图像?

opencv背景减法

c++ - 如何从 OpenCV c++ 中的矩阵向​​量创建 4D 矩阵

python - 如何检测一个简单但半透明的形状的存在?

c++ - Opencv cv::findchessboardCorners

python - img [y:y + h,x:x + w]坐标系的工作方式

c++ - OpenCV 将 3D 坐标投影到 2d 相机坐标