3D空间中的激光投影仪校准 [英] Laser Projector Calibration in 3D Space

查看:172
本文介绍了3D空间中的激光投影仪校准的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am working on a solution for calibrating a laser projector in the real world. There are a few goals for this project.

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.

示例:

一个矩形平板在每个角上都有一个目标.目标物在空中的一角由垫片抬高50mm(〜2英寸).仅仅因为目标升高了50mm,我不希望我的投影表面倾斜.我想考虑高度,但仍将最终产品投影在平面Z = 0的平面上.现实世界中这些目标的坐标如下所示(值均以毫米为单位):

A rectangular flat table has a target on each corner. One of the corners the target is raised in the air by a shim by 50mm (~2 inches). Just because the target is raised 50mm, I do not want my projection surface to be skewed. I want to account for the height and still project the final product on a flat Z = 0 plane. The coordinates for these targets in real world space are shown below (values are all in millimeters):

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

The laser coordinates range from -32000 to 32000, they use photosensors to capture the targets in the real world and when captured return values in the laser coordinate system. The Coordinates captured are shown below. (values range from -32000 to 32000 and their units are unknown to me).

目标:

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

Determine if the laser coordinates captured correctly represent the real world coordinates provided (if not, determine a deviation from those coordinates) and then provide a transformation matrix or some other method of transforming points in 3d real world space accurately to 2d laser space.

我尝试过的事情:

我尝试实施一些不同的透视校正解决方案.一个来自OpenCvSharp3,另一个来自代码项目线程.两者均能很好地工作,但都存在问题.

I have tried implementing a few different perspective correction solutions. One from OpenCvSharp3, and one from a code project thread. Both of these work equally well but both have problems.

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.

如果任何人以前曾尝试/解决/遇到过此问题,并且有可能提出任何见解,将不胜感激.

If anyone has attempted/solved/come across this problem before and could shed any insight it would be greatly appreciated.

提前谢谢!

推荐答案

以下示例代码显示所需的正确计算.想象一下,您的真实桌子X,Y是X水平的,图片和Y都在上升.为方便起见,样本的原点是0,0,0.然后,第二个图像将适当的X,Y想象为X轴向下并且Y右侧向右旋转(-90度旋转)的左上角.不用担心以后可以轻松调整它.下面的快速示例中的注释说明了每一行的功能以及为何存在该行.

Here a sample code that show the proper calculation required. Imagine you real table X,Y is X horizontal with the picture and Y going up. The origin being 0,0,0 for convenience and easier sample to follow. Then the second image imagine the proper X,Y to be the top left corner where X axis is going down and Y going right (-90 degree rotation ish). Don't worry about that it's easily adjustable later. The comments in the quick sample below explain what every line does and why it's there.

// 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},这几乎是激光矩阵中的死点.

So here you have it. The sample center point on the real table translated to {12203,5947,0} using this code which is pretty much dead center in the laser matrix.

现在是歪斜部分.这也很简单.这行:

Now for the skew part. This is also pretty simple. this line :

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

这就是您需要更改的所有内容.您一直想将左上角作为原点,因此,您所要做的就是想象一条向右的直线(在激光图像上),并且您想找出这个完美的X轴之间的夹角是多少(向量(1,0,0))和左下角点的向量(在这种情况下略大于90度)(可能在-91到-95度之间).您想弄清楚Z的角度来实现它.使用的公式返回+270度而不是-90度并不重要,因为它是矩阵,它会给出相同的结果.

It's all you need to change. What you want is always consider that top left corner is the origin so all you want to do is imagine a straight line going toward the right (on you laser image) and you want to figure out what is the angle between this perfect X axis (vector(1,0,0)) and the vector of the bottom left point which in this case is slightly more than 90 degree (probably between -91 to -95 degree). You want to figure out the angle in Z to achieve it. It doesn't matter if the formula you use return +270 degree instead of -90 degree since it's a matrix it will give the same results.

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

Here a method that comput angle in degree between 2 vector based of a rotation axis given

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度.

This checks the angle between a perfect X vector and perfect Y vector relative to a perfect Z vector which will give you 90 degree.

这篇关于3D空间中的激光投影仪校准的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆