Helpers - компьютеры, интернет, программирование

Как правильно установить проекционные и модельные матрицы в OpenGL, используя параметры камеры

У меня есть набор точек (3D), снятых со сканера дальности. Примеры данных можно найти здесь: http://pastebin.com/RBfQLm56.

У меня также есть следующие параметры для сканера:

camera matrix
[3871.88184, 0, 950.736938;
  0, 3871.88184, 976.1383059999999;
  0, 0, 1]



distortion coeffs
[0.020208003; -1.41251862; -0.00355229038; -0.00438868301; 6.55825615]



camera to reference point (transform)

[0.0225656671, 0.0194614234, 0.9995559233, 1.2656986283;

  -0.9994773883, -0.0227084301, 0.0230060289, 0.5798922567;

  0.0231460759, -0.99955269, 0.0189388219, -0.2110195758;

  0, 0, 0, 1]

Я пытаюсь правильно отобразить эти точки с помощью opengl, но рендеринг выглядит неправильно. Как правильно установить проекцию openGL и матрицу просмотра модели? Это то, что я сейчас делаю -

znear = 0.00001
zfar =  100
K = array([[3871.88184, 0, 950.736938],[0, 3871.88184, 976.1383059999999],[0, 0, 1]])
Rt =array([[0.0225656671, 0.0194614234, 0.9995559233, 1.2656986283],[-0.9994773883, -0.0227084301, 0.0230060289, 0.5798922567],[0.0231460759, -0.99955269, 0.0189388219, -0.2110195758]])
ren.set_projection(K,zfar,znear)
ren.set_projection_from_camera(Rt)

Используемые функции:

def set_projection(self,K,zfar,znear):
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    f_x = K[0,0]
    f_y = K[1,1]
    c_x = K[0,2]
    c_y = K[1,2]
    fovY = 1/(float(f_x)/height * 2);
    aspectRatio = (float(width)/height) * (float(f_y)/f_x);
    near = zfar
    far = znear
    frustum_height = near * fovY;
    frustum_width = frustum_height * aspectRatio;
    offset_x = (width/2 - c_x)/width * frustum_width * 2;
    offset_y = (height/2 - c_y)/height * frustum_height * 2;
    glFrustum(-frustum_width - offset_x, frustum_width - offset_x, -frustum_height - offset_y, frustum_height - offset_y, near, far);


def set_modelview_from_camera(self,Rt):
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    Rx = array([[1,0,0],[0,0,-1],[0,1,0]])
    R = Rt[:,:3]
    U,S,V = linalg.svd(R)
    R = dot(U,V)
    R[0,:]=-R[0,:]
    t=Rt[:,3]
    M=eye(4)
    M[:3,:3]=dot(R,Rx)
    M[:3,3]=t
    M=M.T
    m=M.flatten()
    glLoadMatrixf(m)

Затем я просто отображаю точки (вставка фрагмента):

def renderLIDAR(self,filename):
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
    glPushMatrix();

    glEnable(GL_DEPTH_TEST)
    glClear(GL_DEPTH_BUFFER_BIT)
    glPointSize(1.0)
    f = open(filename,'r')
    f.readline() #Contains number of particles
    for line in f:
        line = line.split(' ')
        glBegin(GL_POINTS)
        glColor3f (0.0,1.0,0.0); 
        x = float(line[0])
        y = float(line[1])
        z = float(line[2])
        glVertex3f(x,y,z)
        #print x,y,z
        glEnd()

    glPopMatrix();

Ответы:


1

Матрицы, которые вы возвращаете, особенно последняя в вашем вопросе, - это то, что в OpenGL представляет собой композицию проекции и представления модели, также называемую проекцией представления модели, т.е.

МВП = П · М

Пока вы не заинтересованы в выполнении вычислений освещения, вы можете использовать только это в вершинном шейдере, т.е.

#version 330

uniform mat4 MVP;
in vec3 position;

void main()
{
    gl_Position = MVP * vec4(position, 1);
}

Кстати, OpenGL и, возможно, библиотека, которую вы используете, используют основной порядок столбцов, т.е. порядок элементов в памяти

0 4 8 c
1 5 9 d
2 6 a e
3 7 b f

поэтому то, что написано в исходном коде, следует рассматривать как «транспонированное» (конечно, это не так). Поскольку матрица, которую вы написали, следует той же схеме, вы можете просто поместить ее в униформу как есть. Единственный вопрос, который остается, - это границы пространства NDC, используемого сканером дальности. Но об этом можно было бы позаботиться, применив дополнительную матрицу. OpenGL использует диапазон [-1, 1] ^ 3, поэтому худшее, что может случиться, это то, что если он находится в другом популярном диапазоне NDC [0, 1] ^ 3, вы увидите, что ваша геометрия просто втиснута в верхний левый угол. угол вашего окна и, возможно, вывернутый «наизнанку», если ось Z идет в другом направлении. Просто попробуйте, я бы сказал, что он уже соответствует OpenGL.

В любом случае, если вы хотите использовать его с освещением, вы должны разложить его на часть проекции и модельного вида. Легче сказать, чем сделать, но хорошей отправной точкой является ортонормирование верхней левой подматрицы 3×3, которая дает вращательную часть представления модели «M». Затем вам нужно найти матрицу P, которая при умножении слева на M дает исходную матрицу. Это переопределенный набор линейных уравнений, поэтому схема Гаусса-Джордана может это сделать. И если я не совсем ошибаюсь, то, что вы уже получили в виде этой матрицы камеры, это либо разложенный M, либо P (я бы выбрал M).

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

11.02.2013
  • Большое спасибо, datenwolf. Что касается матриц, матрица камеры (первая) является внутренним параметром камеры, третья (камера для ссылки) является внешним параметром камеры. Я предполагаю, что с фиксированным конвейером openGL, как проще всего установить матрицы? Я полагаю, что один из вариантов — умножить их в шейдере, но что, если с подсветкой? 12.02.2013
  • Если вам нужно рабочее освещение, вы должны разложить матрицы, как описано выше. У вас есть документация об этих матрицах, которую я мог бы прочитать? Технически, чтобы освещение работало, вам просто нужно извлечь ортонормированный верхний левый угол 3×3, чтобы преобразовать нормали. К сожалению, это работает только с программируемым конвейером, так как фиксированный конвейер функций делает определенные предположения о матрицах. Поэтому для конвейера с фиксированной функцией вы должны разложить его. Ортонормированная часть — это то, что затем входит в представление модели, а дополняющая часть — это проекция. 12.02.2013
  • Также отсутствуют правильно установленные ближняя и дальняя плоскости отсечения. 12.02.2013
  • После разложения вроде нормально работает. Спасибо за вашу помощь 12.02.2013
  • Новые материалы

    Интуитивное понимание тензоров в машинном обучении
    Тензор является важной концепцией во многих научных областях, таких как математика, физика, обработка сигналов и компьютерное зрение, и это лишь некоторые из них. В математике тензор — это..

    Использование машинного обучения для диагностики болезни Альцгеймера, часть 4
    Маркеры семантической согласованности для ранней диагностики болезни Альцгеймера (arXiv) Автор: Давиде Колла , Маттео Дельсанто , Марко Агосто , Бенедетто Витиелло , Даниэле Паоло Радичони..

    Почему объяснимость так важна прямо сейчас?
    По мере того, как системы искусственного интеллекта и инструменты на основе машинного обучения распространяются в нашей повседневной жизни, как практики, так и критики все чаще заявляют о..

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

    Создание простого слайдера изображений с помощью JavaScript
    Узнайте, как создать базовый слайдер изображений с помощью HTML, CSS и JavaScript. Введение В этом уроке мы создадим удобный слайдер изображений, используя JavaScript, HTML и CSS. Ползунок..

    Создание базы данных с помощью супергероя «Python»
    В этом посте мы узнаем, как создать «базу данных SQLite с помощью модуля python sqlite3, создав простую функцию входа и регистрации. Готовы ли вы к этому путешествию? Если да , давайте приступим..

    ИИ для чайников: руководство для начинающих по пониманию будущего технологий
    Вы чувствуете, что остались позади в мире ИИ? Не волнуйтесь, вы не одиноки! Со всей этой шумихой вокруг искусственного интеллекта может быть трудно понять, с чего начать. Но не позволяйте сленгу..