今天实现了一个从kinect得到的三维人脸模型赋上彩色纹理的工作。实现该功能的思路如下:
首先我们拥有两个资源:1,去噪后的三维人脸模型
2, 同样是从kinect得到的人脸彩色图片
现在要做的是为三维人脸模型中的每个顶点找到他们在彩色纹理图片上的对应像素点及rgb色彩信息。这样我们在用opengl绘制模型的时候只要在指定顶点的三维坐标时同时制定顶点的纹理坐标即可。
那么怎么样才能找到模型上的每个顶点在彩色图片上的像素呢?我们可以用固定鼻尖点的方法来实现。
首先,我们标记下彩色图片上鼻尖上点在图像上的坐标,图像以左上角为原点,本例子中是(358.157,291.093),即为下图中的圆圈的点:
同时,我们也标记出在三维模型中鼻尖的那个顶点,本例子中是第39285号顶点(顶点从1开始编号),如下图:
然后,我们分别手动在3dmax和图片查看器中找出三维人脸和彩色图片中人脸区域的宽度Model_FaceWidth,Model_FaceHeight,Image_FaceWidth,Image_FaceHeight;
这样我们就能够通过下面这个公式计算出所有模型中的点对应的纹理坐标了,公式如下:
model->texcoords[v*2] = (Texture_Centre_x + (mtx-mx)*(Image_FaceWidth/Model_FaceWidth) / FimageWidth;
model->texcoords[v*2+1] = (Texture_Centre_y + -1.0 * (mty-my)*(Image_FaceHeight/Model_FaceHeight)) / FimageHeight;
上述公式中,model->texcoords[v*2]为第v号顶点的纹理坐标的x分量,model->texcoords[v*2+1]为第v号顶点的纹理坐标的y分量;Texture_Centre_x 为纹理图片中鼻尖像素点的x坐标,即 358.157,Texture_Centre_y为纹理图片中鼻尖像素点的y坐标,即
291.093; mtx为第v号顶点的x坐标,mty为第v号顶点的y坐标,mx为模型中鼻尖那个顶点的x坐标,my为模型中鼻尖那个顶点的y坐标。 FimageWidth为纹理图片的宽度,FimageHeight为纹理图片的高度。
上述公式的思想是,分别计算模型中的顶点距离鼻尖顶点在x,y方向上的距离,然后将这个距离按比例(即Image_FaceWidth/Model_FaceWidth和Image_FaceHeight/Model_FaceHeight)放大缩小到纹理图片的坐标空间中,接着将这个距离加上纹理图片中鼻尖像素点的x,y方向上的坐标。这样就得到了模型中的顶点在纹理图片上对应的像素的坐标了。
这里有一点要强调的是:opengl中的纹理坐标范围是在(0,1)之间的,所以我们计算出模型中的顶点在纹理图片上的像素的坐标之后还需要将他们的x,y分量分别除以纹理图片的宽度和高度,以使他们的值处在(0,1)之间。这个问题使我调了好久的代码!