Калибровка лазерного проектора в 3D пространстве - PullRequest
0 голосов
/ 02 октября 2018

Я работаю над решением для калибровки лазерного проектора в реальном мире.У этого проекта есть несколько целей.

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 и их единицы мне неизвестны).

Цель:

Определить, правильно ли зафиксированные лазерные координаты соответствуют представленным координатам реального мира(если нет, определите отклонение от этих координат) и затем предоставьте матрицу преобразования или какой-либо другой метод точного преобразования точек в трехмерном пространстве реального мира в двумерное лазерное пространство.

Что я пробовал:

Я попытался реализовать несколько различных решений для коррекции перспективы.Один из 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.

Если кто-то пытался / решил / столкнулся с этой проблемой раньше и мог бы пролить свет на это, это было бы очень признательно.

Заранее спасибо!

Real World Coordinates Laser Space Coordinates

1 Ответ

0 голосов
/ 03 октября 2018

Вот пример кода, который показывает требуемый расчет.Представьте, что вы настоящий стол X, Y - горизонтальный с изображением, а Y - вверх.Начало координат составляет 0,0,0 для удобства и облегчения подбора образца.Затем на втором изображении представьте, что надлежащий X, Y будет верхним левым углом, где ось X идет вниз, а Y идет вправо (угол поворота -90 градусов).Не беспокойтесь о том, что это легко настроить позже.Комментарии в кратком примере ниже объясняют, что делает каждая строка и почему она там есть.

// 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 (вектор (1,0,0)) и вектор нижней левой точки, который в этом случае составляет чуть более 90 градусов (вероятно, от -91 до -95 градусов).Вы хотите выяснить угол в Z для достижения этого.Не имеет значения, если формула, которую вы используете, возвращает +270 градусов вместо -90 градусов, так как это матрица, она даст те же результаты.

Здесь метод, который вычисляет угол в градусах между двумя векторами на основезадана ось вращения

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степень.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...