【问题标题】:Laser Projector Calibration in 3D Space3D 空间中的激光投影仪校准
【发布时间】:2019-03-07 23:36:05
【问题描述】:

我正在研究一种在现实世界中校准激光投影仪的解决方案。这个项目有几个目标。

1. Take in a minimum of four points measured in the real world in 3d space that represent the projection surface. 
2. Take in coordinates from the laser that are equivalent to the points received in part 1
3. Determine if the calibration file matches the real world captured points and show a deviation between the coordinate spaces
4. Using the data from the previous steps, take coordinates in 3d real world space and translate them to laser coordinates.

示例:

矩形平桌的每个角落都有一个目标。目标的其中一个角被垫片抬高 50 毫米(约 2 英寸)。仅仅因为目标被抬高了 50 毫米,我不希望我的投影面倾斜。我想考虑高度,并且仍然将最终产品投影在平坦的 Z = 0 平面上。这些目标在现实世界空间中的坐标如下所示(数值均以毫米为单位):

激光坐标范围从-32000到32000,它们使用光电传感器捕捉现实世界中的目标,并在激光坐标系中捕捉到返回值。捕获的坐标如下所示。 (值范围从 -32000 到 32000,我不知道它们的单位)。

目标:

确定捕获的激光坐标是否正确代表所提供的真实世界坐标(如果不是,则确定与这些坐标的偏差),然后提供变换矩阵或其他方法,将 3d 真实世界空间中的点准确地变换到 2d 激光空间.

我尝试过的:

我已尝试实施几种不同的透视校正解决方案。一个来自 OpenCvSharp3,一个来自代码项目线程。这两种方法同样有效,但都有问题。

1. I cannot determine a deviation from the real world. The points are perfectly mapped to the perspective representation so I cannot determine if they are misaligned from the real world expectation
2. I cannot represent source points in a 3d space. Targets may be placed arbitrarily in the Z-direction, and with perspective mapping I cannot seem to account for that Z Direction.

如果有人之前尝试过/解决过/遇到过这个问题并且可以提供任何见解,我们将不胜感激。

提前谢谢你!

【问题讨论】:

  • 您目前有 2 架飞机,但没有一架。 3d 世界中的 2 个三角形是 {0,597,0}, {0,0,0}, {902,0,50} 和 {0,597,0}, {902,0,50}, {902,597,0}
  • @Franck 目标可以任意定位在不同的高度,但由于我知道高度,我想将它们考虑在内,并在 Z = 0 平面上创建一个可投影的 2d 表面。所以本质上,一旦校准 2d 投影表面将由 {0,0,0},{0,597,0},{902,597,0},{902,0,0} 50 仅与注意位置相关目标。
  • 我强硬你的意思是你想得到正确的矩阵,但我看错了。现在我明白了这个问题。解决方案非常简单。您需要创建 2 个在两个世界中都匹配的平面。现在您知道激光平面与现实世界相比是 RotZ -90°。您只需将激光平面重叠到现实世界的平面上,然后将 3d 点从一个平面投影到另一个平面。然后该点需要针对单位因子进行校正。在 X 中,您的对象是 902,在激光中是 36,000。因子约为 40(使用您检测到的点计算)并将其应用于 X、Y 投影。
  • @Franck 我尝试制作比例、旋转和平移矩阵来移动坐标系之间的点,但它不允许我考虑一个校准点是提高。为了做到这一点,我相信第一步是计算投影仪在现实世界坐标中的位置,但我不知道如何开始。如果我可能误解了您在说什么,并且您认为您的解决方案可行,请将其格式化为答案,以便我可以尝试并将其标记为正确(如果可行)。谢谢:)
  • 是您的真实表面始终平坦。我的意思是无论参考点位置如何,您都想投影到哪里

标签: c# opencv image-processing camera-calibration homography


【解决方案1】:

这里有一个示例代码,显示了所需的正确计算。想象一下你真正的桌子 X,Y 是 X 水平的图片和 Y 向上。原点为 0,0,0 是为了方便和更容易跟踪样本。然后第二个图像将正确的 X,Y 想象为 X 轴向下且 Y 向右(-90 度旋转)的左上角。不用担心它以后很容易调整。下面的快速示例中的 cmets 解释了每一行的作用以及它存在的原因。

// compute from the points the table height and width
var realTableDimX = 902d;
var realTableDimY = 597d;

// the real table matrix is 0,0,0 on bottom corner
// so matrix is identity (our source)
var realTableMatrix = new Matrix3D();

// the laser is rotated 90 degree and position at the top left based compared to the realTablematrix
var laserMatrix = new Matrix3D();

// rotate and translate the laser matrix into position
// 90 degree doesnt account for the little skew (see comment outside code for explaination on how to fix that)
laserMatrix.Rotate(new Quaternion(new Vector3D(0, 0, 1), -90d)); 
laserMatrix.Translate(new Vector3D(0, realTableDimY, 0d));

// compute the laser dimensions (i used your points you found out)
var laserDimX = 20392d - (-16300d);
var laserDimY = 12746 - (-11409d);

// calculate the ratio to factor in to displace the point to the real value onto the laser matrix
var laserXRatio = laserDimX / realTableDimX;
var laserYRatio = laserDimY / realTableDimY;

// since matrix are 1 to 1 when you compute if you have an equal ratio of 40 in X and 40 in Y then the point at 10,10,0 on
// the real table is correcponding to the point 400,400,0 on the laser matrix. But since it's rotated 90 degree you
// will need to apply the Y ration to the X point after the transform and the X ratio to the Y point to get the actual point.

// sample point on table. Logic can be flipped with laser matrix to do it the other way
var sampleRealTablePoint = new Point3D(450, 300, 0); // roughly centered

// transform the point from one UCS to another is simply multiplying by it's current UCS (matrix it's in)
// to transform it to world UCS then multiply by the inverse of other UCS we want it in (the other matrix)
var sampleRealTablePointWorld = realTableMatrix.Transform(sampleRealTablePoint);

// convert that point into the laser matrix but first create and inverted matrix of the laser matrix
// we copy a matrix to not modify the current one when inverting it
var laserInvertedMatrix = new Matrix3D() * laserMatrix;
laserInvertedMatrix.Invert();

// get the sample point in the world of the laser matrix
var sampleRealTablePointToLaserMatrix = laserInvertedMatrix.Transform(sampleRealTablePointWorld);

// not adjust the X and Y like said earlier
var finalAdjustedPoint = new Point3D(sampleRealTablePointToLaserMatrix.X * laserXRatio, sampleRealTablePointToLaserMatrix.Y * laserYRatio, 0d);

 // this is if you want the point in the world of the laser matrix and not it's offset from the 0,0,0
 // the vector here is the top left corner of your laser matrix (x, y, z)
 var laserWorldFinalPoint = finalAdjustedPoint + new Vector3D(-11409d, -16155d, 0d);

所以你有它。使用此代码将真实桌子上的样本中心点转换为{12203,5947,0},这几乎是激光矩阵的死点。

现在是倾斜部分。这也很简单。这一行:

laserMatrix.Rotate(new Quaternion(new Vector3D(0, 0, 1), -90d));

这就是你需要改变的一切。你想要的是始终认为左上角是原点,所以你要做的就是想象一条向右的直线(在你的激光图像上),你想弄清楚这个完美的 X 轴之间的角度是多少( vector(1,0,0)) 和左下点的向量,在这种情况下略大于 90 度(可能在 -91 到 -95 度之间)。你想弄清楚 Z 中的角度来实现它。如果您使用的公式返回 +270 度而不是 -90 度也没关系,因为它是一个矩阵,它会给出相同的结果。

这是一种根据给定的旋转轴计算 2 个向量之间角度的方法

public double AngleToInDegree(Vector3D v, Vector3D vector, Vector3D normal)
{
    var dotNormal = Vector3D.DotProduct(normal, Vector3D.CrossProduct(v, vector));

    var dotVector = Vector3D.DotProduct(v, vector);

    var angle = Math.Atan2(dotNormal, dotVector);

    return angle * 180d / Math.PI;
}

一个可用的样本是:

var angle = AngleToInDegree(new Vector3D(1,0,0), new Vector3D(0,1,0), new Vector3D(0,0,1));

这会检查完美 X 向量和完美 Y 向量相对于完美 Z 向量之间的角度,该角度将为您提供 90 度。

【讨论】:

  • 我遵循了你的逻辑,并使用了你的确切数字。我在投影面上准确测量了 300,450(准确测量为 450,300)。然后,我尝试在 {12203,5947,0}(以及 {5947,12203,0} 进行良好测量)进行投影,并且投影点没有落在测量点附近的任何地方:(
  • 我刚刚纠正了最后的转换错误和正确的中心点。我把它们混在一起,试图在特定点做相反的事情。不要忘记激光矩阵是旋转的,结果最终点是相对于它的 0,0,0 即{-11409,-16155,0} 所以如果最终点结果是{1000,0,0} 并假设它没有倾斜点意味着{-10409,-16155,0}它在矩阵的 X 中移动,因此向 X 轴移动。您可以简单地将左上角的 X 和 Y 添加到结果中,并根据需要获取实际值
  • @Kikootwo 我添加了一条线,它可以为您提供激光矩阵中的世界点,而不仅仅是偏移量。
猜你喜欢
  • 2011-03-12
  • 2013-11-09
  • 2014-04-12
  • 1970-01-01
  • 2021-05-27
  • 2017-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多