obj文件、mtl文件和png文件转换成一个obj文件

obj文件、mtl文件和png文件转换成一个obj文件

在进行毕设的时候需要对三维重建的效果进行展示,于是准备使用gradio包来展示。但是在展示的时候发现,gradio三维展示模块读取的.obj类型的三维模型是没有颜色的。原因是三维重建系统会生成三个文件mesh.obj, mesh.mtl, texture.png。其中.obj负责mesh的几何形状,.mtl是一些纹理定义,.png是贴图。其中.obj会在文件的内容里引用.mtl文件,.ntl文件又会引用.png贴图。在本地使用meshlab这类的软件,只要这三个文件在同一目录下,就可以一起打开这三个文件来得到有颜色的模型,而gradio是不支持这样一起打开多个文件的。

于是为了在gradio演示的时候正确打开有颜色的模型,需要对这三个文件处理成一个文件。看了一些其他项目的gradio网页和他们加载的obj模型,发现由于obj文件有不同的格式,可以将原来三个文件转换为一个.obj文件。这样就可以直接在gradio上面展示了。

具体转换的过程如下:

1 转换前obj文件的格式

原obj 格式主要有以下 4 种关键字:

  1. v顶点

v 1.000000 -1.000000 -1.000000

v表示顶点位置,值分别为 x、y、z,即每个顶点在 X、Y、Z 轴的坐标。

  1. vt顶点的纹理坐标

vt 0.748573 0.750412

意义:绘制模型的三角面片时,每个顶点取像素点时对应的纹理图片上的坐标。纹理图片的坐标指的是,纹理图片如果被放在屏幕上显示时,以屏幕左下角为原点的坐标。

  1. f面

f 5/1 1/2 4/3

格式为f v/vt v/vt v/vt。即表示第5行v的颜色为第1行vt坐标对应的颜色,即表示第1行v的颜色为第2行vt坐标对应的颜色,即表示第4行v的纹理为第3行vt坐标对应的颜色。而这三个点组成一个三角面。

2 转换后obj文件 格式

  1. v顶点

v 1.000000 -1.000000 -1.000000 0.748573 0.750412 0.750412

v表示顶点位置,值分别为 x、y、z,R, G, B即每个顶点在 X、Y、Z 轴的坐标和其RGB值。

这里小数是将RGB/255得到

  1. f面

f 5 1 4

第5行的v、第1行的v、第4行的v组成一个三角面

3 转换的代码

v = []
vt = []
f = []
vt_rgb = []

with open(objpath, mode='r', encoding='utf-8') as file_obj:
    temp = file_obj.readlines()

for line in temp:
    if(line.startswith('v ')):
        v.append(line.split(' ')[1:-1])
    elif(line.startswith('vt ')):
        vt.append(map(float, line.split(' ')[1:-1]))
    elif(line.startswith('f ')):
        f.append(line.split(' ')[1:-1])

#print(len(v),len(vt))
img = cv2.imread(os.path.join(os.path.dirname(objpath),'albedo.png'))
height,width,bgra = img.shape

for i in range(len(vt)):
    temp_vt = list(vt[i])
    h = temp_vt[0] * height
    w = temp_vt[1] * width
    #邻近过滤 uv方向需要倒过来
    color = img[width - int(w)-1][int(h)-1]
    red = float(color[2]/255)
    green = float(color[1]/255)
    blue = float(color[0]/255)
    vt_rgb.append([red, green, blue])

f_out = []
for i, fi in enumerate(f):
    for j in range(3):
        tem = fi[j].split('/')
        t = []
        vi, vti = int(tem[0])-1, int(tem[1])-1
        if len(v[vi]) == 3:
            v[vi].append(str(vt_rgb[vti][0]))
            v[vi].append(str(vt_rgb[vti][1]))
            v[vi].append(str(vt_rgb[vti][2]))
        t.append(str(vi+1))
    f_out.append(t)

 with open(os.path.dirname(objpath)+'/output.obj', mode='w', encoding='utf-8') as file_obj:
    for i in range(len(v)):
        line = 'v ' + v[i][0] + ' ' + v[i][1] + ' ' + v[i][2] + ' ' + v[i][3] + ' ' + v[i][4] + ' ' + v[i][5] + ' ' '\n'
        file_obj.write(line)

    for i in range(len(f_out)):
        line = 'f ' + f_out[i][0] + ' ' + f_out[i][1] + ' ' + f_out[i][2] + '\n'
        file_obj.write(line)

  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值