我在世界上有一组 3-D 点。我使用 OpenCV 校准了相机的外部参数。
现在我可以将 3-D 点映射到 2-D 图像中的相应像素。
即对于 [X Y Z],我在图像中有相应的 [u v]。
在 OpenGL 中,我已经标准化了世界 3-D 点并定义了一个表面,我希望在其中完成纹理映射。
从代码中获得的 3-D 表面如下图所示。
它是一个碗状的表面。
现在我想将图像中的纹理映射到 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();
}
问题
- 如何用图像填充表面。
我知道只有一部分表面会根据 3-D 和相应的 2-D 图像坐标进行填充。
- 此外,如果我为顶点赋予颜色,我该如何在间隙中插入它。 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/