我在世界上有一套三维点 . 使用OpenCV我已经校准了相机的外部参数 .
所以现在我能够将3-D点映射到2-D图像中的相应像素 .
即[X Y Z]我在图像中有相应的[u v] .
在OpenGL中,我已经对世界三维点进行了规范化并定义了一个表面,我想要完成纹理映射 .
The 3-D surface obtained from the code looks like in the figure below.
It is a bowl shaped surface .
现在我想将图像中的纹理映射到OpenGL中的三维点 .
我有的信息:
1. 3-D co-ordinates of a parabolic surface in openGL obtained from world points.
2. Corresponding 2-D Image coordinates and R-G-B colour info of pixels.
我该怎么做呢
Here is my code snippet for getting the 3-D points lying on the model surface shown in the link, using real world coordinates
Also it stores the corresponding (u v) pixel coordinate's RGB colour info in image for rendering :
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);
}
}
}
}
This is my rendering code snippet
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();
}
QUESTIIONS
- 如何使用图像填充曲面 .
I am aware that only a part of the surface is going to be filled based on the 3-D and the corresponding 2-D image coordinates.
- 另外如果我给顶点赋予颜色,我该如何在空隙中插入颜色 . OpenGL插入已知形状,如三角形和四边形 .
但这几乎是一个随机点 Cloud ,我想在最近的像素之间进行插值 .
我该怎么做呢 .
2 回答
我假设纹理图像的形状类似于您要将其绘制到的表面,例如应用于3D半球的人脸?
首先,将表面定义为曲面,而不是点 Cloud . 您已经为曲面上的点生成顶点坐标,因此只需将它们链接到三角形网格中即可 . (GL_TRIANGLE_STRIP)
其次,不要将颜色应用于曲面的顶点 . 改为设置纹理坐标 . (在OpenGL中,它们通常被称为s,而不是u,v但其含义是相同的 . )顶点颜色应该只是纯白色 . 使用glTexture2D将图像传递给OpenGL .
通过这种方式,您可以让GPU查找纹理坐标,插入并填充表面,而不是编写自己的代码 .
哦,你正在使用非常老式的glBegin..glEnd块 . 在其他人做之前,你真的需要学习如何使用顶点数组或最好是OpenGL 4 VBO .
希望这可以帮助 .
如果要在实时搜索基于体素的密集映射时执行此操作,可以使用不同的技术 . 如果性能不是主要问题,并且您希望在opengl应用程序中执行此操作,则可以使用delnauy三角测量等算法对点 Cloud 进行三角测量,然后使用uv进行纹理映射 . 如果您希望它是离线过程,您可以使用meshlab,如软件导出到三维的三维格式并在opengl应用程序中加载它 .