opencv - OpenGL 中从图像到用户定义的一组点(点云)的纹理映射

标签 opencv opengl texture-mapping triangulation point-clouds

我在世界上有一组 3-D 点。我使用 OpenCV 校准了相机的外部参数。

现在我可以将 3-D 点映射到 2-D 图像中的相应像素。

即对于 [X Y Z],我在图像中有相应的 [u v]。

在 OpenGL 中,我已经标准化了世界 3-D 点并定义了一个表面,我希望在其中完成纹理映射。

从代码中获得的 3-D 表面如下图所示。

3-D SURFACE in OPENGL

它是一个碗状的表面

现在我想将图像中的纹理映射到 OpenGL 中的 3-D 点。

我掌握的信息:

<强>1。从世界点获得的 openGL 抛物面的 3-D 坐标。

<强>2。相应的二维图像坐标和像素的 R-G-B 颜色信息。

我该怎么做。

这是我的代码片段,用于获取位于链接中显示的模型表面上的 3-D 点,使用真实世界坐标

同时存储图像中对应的(u v)像素坐标的RGB颜色信息,用于渲染:

for (int z_3D = 0; z_3D < 30; z_3D+=1)
{
    for (int x_3D = 0; x_3D < 102; x_3D+=1)
    {
        for (int y_3D = 0; y_3D < 135.5; y_3D+=1)
        {

            //3-D point in real world(in cms)
            x = x_3D;
            y = y_3D;
            z = z_3D;
            object_point[0].x = x;
            object_point[1].y = y;
            object_point[2].z = z;


            //Project 3-D point to 2-D image and get the corresponding (u,v)
            //rvec and tvec Obtained using SolvPnP in openCV
            projectPoints(object_point, rvec_front, tvec_front, cameraMatrix_Front, distCoeffs_Front, check_front_image_pts);


            //Store colour information in the corresponding 2-D point
            //Points not lying on the surface is black
            rgb.r = 0;
            rgb.g = 0;
            rgb.b = 0;



            //Convert real world coordinates into openGl coordinates(-1 to +1)
            x = (x - CHART_WIDTH / 2) / (CHART_WIDTH / 2);
            y = -(y - CHART_LENGTH / 2) / (CHART_LENGTH / 2);
            z = z / CHART_HEIGHT;


            //Parabolic surface model
            float x_4 = x*x*x*x;
            float y_4 = y*y*y*y;


            if (x_4 + y_4 <  r_4)
            {           
                //Store 3-D point
                vertex_obj.vertex_x.push_back(x);
                vertex_obj.vertex_y.push_back(y);
                vertex_obj.vertex_z.push_back((x_4 + y_4) / (a_4));

                /**/
                //Store colour information in the corresponding 2-D point
                rgb.r = front.at<Vec3b>(check_front_image_pts[0].y, check_front_image_pts[0].x)[2];
                rgb.g = front.at<Vec3b>(check_front_image_pts[0].y, check_front_image_pts[0].x)[1];
                rgb.b = front.at<Vec3b>(check_front_image_pts[0].y, check_front_image_pts[0].x)[0];

                //printf("%f %f %f\n", rgb.r, rgb.g, rgb.b);


                vertex_obj.vertex_colour.push_back(rgb);

            }
            else if (sqrt((x_4 + y_4 - r_4)*(x_4 + y_4 - r_4)) < 0.0001)
            {

                //Store 3-D point
                vertex_obj.vertex_x.push_back(x);
                vertex_obj.vertex_y.push_back(y);
                //vertex_obj.vertex_z.push_back(1.0);
                vertex_obj.vertex_z.push_back((x_4 + y_4) / (a_4)+0.0001);

                /*
                //Store colour information in the corresponding 2-D point
                rgb.r = front.at<Vec3b>(check_front_image_pts[0].y, check_front_image_pts[0].x)[2];
                rgb.g = front.at<Vec3b>(check_front_image_pts[0].y, check_front_image_pts[0].x)[1];
                rgb.b = front.at<Vec3b>(check_front_image_pts[0].y, check_front_image_pts[0].x)[0];*/

                vertex_obj.vertex_colour.push_back(rgb);

            }

        }
    }
}

这是我的渲染代码片段

void render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


glLoadIdentity();                 // Reset the model-view matrix

glRotated(ph, 1, 0, 0);
glRotated(th, 0, 1, 0);

glBegin(GL_POINTS);

for (int i = 0; i < vertex_obj.vertex_x.size(); i++)
{
    //Give the colour info from the pixel in the image
    glColor3f(vertex_obj.vertex_colour[i].r/255.0, vertex_obj.vertex_colour[i].g/255.0, vertex_obj.vertex_colour[i].b/255.0);

    //Give the vertex of points lying on the surface defined
    glVertex3f(vertex_obj.vertex_x[i], vertex_obj.vertex_y[i], vertex_obj.vertex_z[i]);
}


//glColor3f(0, 0, 1);
//glVertex2f(1.0, -1.0);

glEnd();


glutSwapBuffers();

}

问题

  1. 如何用图像填充表面。

我知道只有一部分表面会根据 3-D 和相应的 2-D 图像坐标进行填充。

  1. 此外,如果我为顶点赋予颜色,我该如何在间隙中插入它。 OpenGL 对三角形和四边形等已知形状进行插值。

但这几乎是一个随机点云,我想在最近的像素之间进行插值。

我该怎么做。

最佳答案

我假设纹理图像的形状类似于您要将其绘制到的表面,例如应用于 3D 半球的人脸?

首先,将您的表面定义为表面,而不是点云。您已经为表面上的点生成了顶点坐标,因此只需将它们链接到三角形网格中即可。 (GL_TRIANGLE_STRIP)

其次,不要将颜色应用于曲面的顶点。改为设置纹理坐标。 (在 OpenGL 中它们通常被称为 s,t 而不是 u,v 但意思是一样的。)顶点颜色应该只是纯白色。使用 glTexture2D 将图像传递给 OpenGL。

通过这种方式,您可以让 GPU 查找纹理坐标、插值和填充表面,而不是编写您自己的代码。

哦,您使用的是非常老式的 glBegin..glEnd block 。在其他人之前,您确实需要学习如何使用顶点数组或最好是 OpenGL 4 VBO。

希望这对您有所帮助。

关于opencv - OpenGL 中从图像到用户定义的一组点(点云)的纹理映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45616224/

相关文章:

python - 如何使用变形网格扭曲图像

c++ - 如何通过简单的乘法将纹理颜色混合到其下面的颜色?

javascript - 如何使用 Three.js r67 将径向纹理应用到戒指上?

c++ - Opencv:EM算法训练缓慢

opencv - 合并两个或多个部分重叠的图像

python - 如何从图像中删除最大轮廓标记的对象并将其另存为单独的图像?

opengl - GLSL从modelviewmatrix和viewmatrix中提取modelmatrix

c++ - 我如何找到具体的 dll::GLUT 依赖项

opengl - 将立方体贴图的面渲染为四边形

iphone - 在 OpenGL ES 中将不规则形状或其他多边形(卡通、 Sprite )映射到三角形