5

Я использую планшет google tango для получения данных облачных точек и изображений RGB-камеры. Я хочу создать 3D-сканирование комнаты. Для этого мне нужно отображать пиксели 2D-изображения в точку облачной точки. Я буду делать это с большим количеством точечных облаков и соответствующих изображений. Поэтому мне нужно написать сценарий кода, который имеет два входа: 1. облако точек и 2. изображение, взятое из той же точки в том же направлении, и сценарий должен выводить цветную точку облако. Как я должен подойти к этому &, какие платформы будут очень просты в использовании?Как цветное облако точки с пикселей изображения?

ответ

5

Вот математика для отображения 3D точек v в 2D пространства пикселей в изображении камеры (при условии, что v уже включает в себя внешнюю позицию и ориентацию камеры, см примечания внизу *):

// Project to tangent space. 
vec2 imageCoords = v.xy/v.z; 

// Apply radial distortion. 
float r2 = dot(imageCoords, imageCoords); 
float r4 = r2*r2; 
float r6 = r2*r4; 
imageCoords *= 1.0 + k1*r2 + k2*r4 + k3*r6; 

// Map to pixel space. 
vec3 pixelCoords = cameraTransform*vec3(imageCoords, 1); 

Где cameraTransform матрица 3х3:

[ fx 0 cx ] 
[ 0 fy cy ] 
[ 0 0 1 ] 

с fx, fy, cx, cy, k1, k2, k3 от TangoCameraIntrinsics.

pixelCoords объявлен vec3, но на самом деле 2D в однородных координатах. Третья координата всегда 1 и поэтому может быть проигнорирована для практических целей.

Обратите внимание, что если вы хотите координаты текстуры вместо координат пикселей, это просто еще одно линейное преобразование, которое можно предварительно умножить на cameraTransform раньше (как и любая обратная связь по строкам сверху вниз или снизу вверх) ,

Что касается какой «платформы» (который я свободно интерпретировать как «язык») является простейшим, то native API, кажется, самый простой способ получить ваши руки на пикселы, хотя кажется, люди также удалось с Unity и Java.


* Очки доставляемых TangoXYZij уже включают глубину камеру внешнего преобразования. Технически, поскольку текущий планшет разработчика разделяет одно и то же оборудование между приобретением глубины и цвета, вы не сможете получить цветное изображение, которое точно соответствует, если ваше устройство и ваша сцена не будут неподвижными. К счастью на практике, большинство приложений, вероятно, могут предположить, что ни камера, ни сцена не изменяются достаточно в течение одного кадра, чтобы существенно повлиять на поиск цвета.

2

Этот ответ не является оригинальным, он просто предназначен для удобства пользователей Unity, которые хотели бы, чтобы правильный ответ, предоставленный компанией @rhashimoto, был разработан для них. Мой вклад (надеюсь) дает код, который уменьшает нормальные 16 умножений и 12 добавлений (при условии, что Unity только делает матрицы 4x4) до 2 умножений и 2 добавляет, вычеркивая все нулевые результаты. Я проверил немного меньше миллиона очков через тест, проверяя каждый раз, когда мои расчеты согласуются с основными вычислениями матрицы - определяется как абсолютная разница между двумя результатами меньше, чем машинный эпсилон. Мне так комфортно с этим, что я могу зная, что @rhashimoto может появиться и просунуть в него гигантское отверстие :-)

Если вы хотите переключиться туда и обратно, помните, что это C#, поэтому определение USEMATRIXMATH должно появиться в начале файла.

Учитывая есть только один Tango устройство прямо сейчас, и я предполагаю, что встроенные функции постоянны во всех устройствах, я просто сбрасывали их в качестве констант, так что

fx = 1042.73999023438 
fy = 1042.96997070313 
cx = 637.273986816406 
cy = 352.928985595703 
k1 = 0.228532999753952 
k2 = -0.663019001483917 
k3 = 0.642908990383148 

Да, они могут быть сброшены в качестве констант, что сделает вещи более читабельными, а C#, вероятно, достаточно умен, чтобы оптимизировать его - однако, я потратил слишком много времени на жизнь Агнера Фогга и всегда будет параноидальным.

Прокомментированный код внизу предназначен для проверки разницы, если вы хотите. Вам придется раскомментировать некоторые другие вещи и прокомментировать их, если вы хотите проверить результаты.

Моя благодарность снова @rhashimoto, это далеко не намного лучше, чем то, что я имел

Я остался верен своей логике, помните эти пиксельные координаты, не UV-координаты - он правильно, что вы можете предварительного умножения преобразования, чтобы получить нормированные значения УФ, но так как он обучен меня на это раз уже, я буду придерживаться именно математику он представил, прежде чем я возиться с слишком много :-)

static public Vector2 PictureUV(Vector3 tangoDepthPoint) 
    { 
     Vector2 imageCoords = new Vector2(tangoDepthPoint.x/tangoDepthPoint.z, tangoDepthPoint.y/tangoDepthPoint.z); 
     float r2 = Vector2.Dot(imageCoords, imageCoords); 
     float r4 = r2*r2; 
     float r6 = r2*r4; 
     imageCoords *= 1.0f + 0.228532999753952f*r2 + -0.663019001483917f*r4 + 0.642908990383148f*r6; 
     Vector3 ic3 = new Vector3(imageCoords.x,imageCoords.y,1); 

#if USEMATRIXMATH 
     Matrix4x4 cameraTransform = new Matrix4x4(); 
     cameraTransform.SetRow(0,new Vector4(1042.73999023438f,0,637.273986816406f,0)); 
     cameraTransform.SetRow(1, new Vector4(0, 1042.96997070313f, 352.928985595703f, 0)); 
     cameraTransform.SetRow(2, new Vector4(0, 0, 1, 0)); 
     cameraTransform.SetRow(3, new Vector4(0, 0, 0, 1)); 
     Vector3 pixelCoords = cameraTransform * ic3; 
     return new Vector2(pixelCoords.x, pixelCoords.y); 
#else 
     //float v1 = 1042.73999023438f * imageCoords.x + 637.273986816406f; 
     //float v2 = 1042.96997070313f * imageCoords.y + 352.928985595703f; 
     //float v3 = 1; 
     return new Vector2(1042.73999023438f * imageCoords.x + 637.273986816406f,1042.96997070313f * imageCoords.y + 352.928985595703); 
#endif 

     //float dx = Math.Abs(v1 - pixelCoords.x); 
     //float dy = Math.Abs(v2 - pixelCoords.y); 
     //float dz = Math.Abs(v3 - pixelCoords.z); 
     //if (dx > float.Epsilon || dy > float.Epsilon || dz > float.Epsilon) 
     // UnityEngine.Debug.Log("Well, that didn't work"); 
     //return new Vector2(v1, v2); 
    } 

Как один последнее замечание сделать, обратите внимание код, который он предоставил, - это GLSL - если вы просто используете это для хороших фотографий, используйте его - это для тех, которые на самом деле нужно выполнить. эталонная обработка.