Имитировать виртуальную камеру, которая сохраняет информацию о цвете

У меня есть виртуальный сканер, который создает 2,5-мерное представление облака точек (т. е. 2D-проекцию трехмерного облака точек) в зависимости от положения камеры. Я использую vtkCamera.GetProjectionTransformMatrix(), чтобы получить матрицу преобразования из мировых/глобальных координат в координаты камеры.

Однако, если входное облако точек имеет информацию о цвете для точек, я хотел бы сохранить ее.

Вот соответствующие строки:

boost::shared_ptr<pcl::visualization::PCLVisualizer> vis; // camera location, viewpoint and up direction for vis were already defined before
vtkSmartPointer<vtkRendererCollection> rens = vis->getRendererCollection();
vtkSmartPointer<vtkRenderWindow> win = vis->getRenderWindow();

win->SetSize(xres, yres); // xres and yres are predefined resolutions
win->Render();

float dwidth = 2.0f / float(xres),
    dheight = 2.0f / float(yres);

float *depth = new float[xres * yres];
win->GetZbufferData(0, 0, xres - 1, yres - 1, &(depth[0]));

vtkRenderer *ren = rens->GetFirstRenderer();
vtkCamera *camera = ren->GetActiveCamera();
vtkSmartPointer<vtkMatrix4x4> projection_transform = camera->GetProjectionTransformMatrix(ren->GetTiledAspectRatio(), 0, 1);

Eigen::Matrix4f mat1;
for (int i = 0; i < 4; ++i)
    for (int j = 0; j < 4; ++j)
        mat1(i, j) = static_cast<float> (projection_transform->Element[i][j]);

mat1 = mat1.inverse().eval();

Теперь mat1 используется для преобразования координат в вид из камеры:

pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud;

int ptr = 0;
for (int y = 0; y < yres; ++y)
{
    for (int x = 0; x < xres; ++x, ++ptr)
    {
        pcl::PointXYZ &pt = (*cloud)[ptr];

        if (depth[ptr] == 1.0)
        {
            pt.x = pt.y = pt.z = std::numeric_limits<float>::quiet_NaN();
            continue;
        }

        Eigen::Vector4f world_coords(dwidth  * float(x) - 1.0f,
            dheight * float(y) - 1.0f,
            depth[ptr],
            1.0f);
        world_coords = mat1 * world_coords;

        float w3 = 1.0f / world_coords[3];
        world_coords[0] *= w3;
        world_coords[1] *= w3;
        world_coords[2] *= w3;

        pt.x = static_cast<float> (world_coords[0]);
        pt.y = static_cast<float> (world_coords[1]);
        pt.z = static_cast<float> (world_coords[2]);
    }
}

Я хочу, чтобы виртуальный сканер возвращал pcl::PointXYZRGB облака точек с информацией о цвете.

Любая помощь в реализации этого от кого-то, кто имеет опыт работы с VTK, сэкономит мне время.

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


person mf27    schedule 09.10.2017    source источник


Ответы (1)


Если я правильно понимаю, что вы хотите получить цвет, в котором точка была визуализирована в win RenderWindow, вы должны иметь возможность получить данные из буфера рендеринга, вызвав

float* pixels = win->GetRGBAPixelData(0, 0, xres - 1, yres - 1, 0/1).

Это должно дать вам каждый пиксель буфера рендеринга в виде массива в формате [R0, G0, B0, A0, R1, G1, B1, A1, R2....]. Последний параметр, который я написал как 0/1, должен ли данные браться из переднего или заднего буфера opengl. Я предполагаю, что по умолчанию должна быть включена двойная буферизация, поэтому вы хотите читать из заднего буфера (используйте «1»), но я не уверен.

Получив это, вы можете получить цвет во втором цикле для всех пикселей, принадлежащих точкам (depth[ptr] != 1.0), как:

pt.R = pixels[4*ptr];
pt.G = pixels[4*ptr + 1];
pt.B = pixels[4*ptr + 2];

Вы должны позвонить win->ReleaseRGBAPixelData(pixels), когда закончите с этим.

person tomj    schedule 10.10.2017
comment
Это то, что я хотел, да! Я установил последний параметр (спереди) на 1, работает нормально. При экспорте значений в pcl::PointCloud<pcl::PointXYZRGB> их следует (вероятно) умножить на 255. Спасибо! - person mf27; 10.10.2017