当将纹理映射到网格时,Vtk在节点之间插入不正确的颜色 [英] Vtk inserts incorrect color between nodes when mapping texture to mesh

查看:426
本文介绍了当将纹理映射到网格时,Vtk在节点之间插入不正确的颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Mayavi和vtk的Python绑定将纹理映射到3d网格.我正在可视化.obj波前.该obj是一张脸的3D照片.纹理图像是三张2D照片的合成.

Hi I am trying to map a texture to 3d mesh using Mayavi and Python bindings of vtk. I am visualising an .obj wavefront. This obj is 3D photograph of a face. The texture image is a composite of three 2D photographs.

网格中的每个节点在图像中都有一个(uv)坐标,用于定义其颜色.网格的不同区域从图像的不同部分绘制颜色.为了说明这一点,我将实际的纹理图像替换为以下图像:

Each node in the mesh has an (uv) co-ordinate in the image, which defines its color. Different regions of the mesh draw their colours from different sections of the image. To illustrate this I have replaced the actual texture image with this one:

并将其映射到网格.

我的问题在鼻子周围显示出来.在红色和绿色之间的边界处,有蓝色的轮廓.线框模式下对该区域的仔细检查显示,uv映射不是问题,而是vtk如何在两个节点之间插值颜色.由于某种原因,它在两个节点之间添加了一块蓝色,其中一个是红色,一个是绿色.

The problem I am having is illustrated around the nose. At the border between red and green there is an outline of blue. Closer inspection of this region in wireframe mode shows that it is not a problem with the uv mapping, but with how vtk is interpolating colour between two nodes. For some reason it is adding a piece of blue in between two nodes where one is red and one is green.

这在使用真实纹理进行可视化时会导致严重的问题

This causes serious problems when visualising using the real texture

是否有一种方法可以强制vtk为它们之间的颜色选择一个或另一个相邻节点的颜色?我尝试打开边缘夹紧"功能,但没有成功.

Is there a way to force vtk to choose the colour of one or the other neighbouring nodes for the colour between them? I tried turning "edge-clamping" on, but this did not achieve anything.

我正在使用的代码如下,您可以从此处访问有问题的文件 https://www.dropbox.com/sh/ipel0avsdiokr10/AADmUn1-qmsB3vX7BZObrASPa?dl=0 但我希望这是一个简单的解决方案.

The code that I am using is below and you can access the files in question from here https://www.dropbox.com/sh/ipel0avsdiokr10/AADmUn1-qmsB3vX7BZObrASPa?dl=0 but I hope this is a simple solution.

from numpy import *
from mayavi import mlab
from tvtk.api import tvtk
import os
from vtk.util import numpy_support

def  obj2array(f):
    """function for reading a Wavefront obj"""
    if type(f)==str:
            if os.path.isfile(f)==False:
                    raise ValueError('obj2array: unable to locate file ' + str(f))
            f =open(f)

    vertices = list()
    connectivity = list()
    uv = list()
    vt = list()


    fcount = 0


    for l in f:
                line = l.rstrip('\n')

                data = line.split()
                if len(data)==0:
                        pass
                else:

                        if data[0] == 'v':
                            vertices.append(atleast_2d(array([float(item) for item in data[1:4]])))

                        elif data[0]=='vt':
                            uv.append(atleast_2d(array([float(item) for item in data[1:3]])))


                        elif data[0]=='f':

                            nverts = len(data)-1 # number of vertices comprising each face

                            if fcount == 0:    #on first face establish face format

                                fcount = fcount + 1
                                if data[1].find('/')==-1:  #Case 1
                                    case = 1

                                elif data[1].find('//')==True:
                                    case = 4
                                elif len(data[1].split('/'))==2:
                                    case = 2
                                elif len(data[1].split('/'))==3:
                                    case = 3



                            if case == 1:
                                f = atleast_2d([int(item) for item in data[1:len(data)]])
                                connectivity.append(f)

                            if case == 2:
                                splitdata = [item.split('/') for item in data[1:len(data)]]
                                f = atleast_2d([int(item[0]) for item in splitdata])

                                connectivity.append(f)

                            if case == 3:
                                splitdata = [item.split('/') for item in data[1:len(data)]]
                                f = atleast_2d([int(item[0]) for item in splitdata])
                                connectivity.append(f)


                            if case == 4:
                                splitdata = [item.split('//') for item in data[1:len(data)]]
                                f = atleast_2d([int(item[0]) for item in splitdata])

                                connectivity.append(f)


    vertices = concatenate(vertices, axis = 0)
    if len(uv)==0:
        uv=None
    else:
        uv = concatenate(uv, axis = 0)

    if len(connectivity) !=0:
            try:
                    conarray = concatenate(connectivity, axis=0)
            except ValueError:
                    if triangulate==True:
                            conarray=triangulate_mesh(connectivity,vertices)

                    else:
                            raise ValueError('obj2array: not all faces triangles?')
            if conarray.shape[1]==4:
                    if triangulate==True:
                            conarray=triangulate_mesh(connectivity,vertices)



    return vertices, conarray,uv



# load texture image
texture_img = tvtk.Texture(interpolate = 1,edge_clamp=1)
texture_img.input = tvtk.BMPReader(file_name='HM_1_repose.bmp').output

#load obj
verts, triangles, uv = obj2array('HM_1_repose.obj')

# make 0-indexed
triangles = triangles-1

surf = mlab.triangular_mesh(verts[:,0],verts[:,1],verts[:,2],triangles)

tc=numpy_support.numpy_to_vtk(uv)

pd = surf.mlab_source.dataset._vtk_obj.GetPointData()
pd.SetTCoords(tc)
surf.actor.actor.mapper.scalar_visibility=False
surf.actor.enable_texture = True
surf.actor.actor.texture = texture_img
mlab.show(stop=True)

推荐答案

您可以关闭所有插值功能(在示例中将interpolate = 1更改为interpolate = 0),但是没有一种方法可以仅在可以在纹理的子图像之间进行插值的位置-至少在没有编写自己的片段着色器的情况下如此.这看起来可能很粗糙.

You can turn off all interpolation (change interpolate = 1 to interpolate = 0 in your example), but there is not a way to turn off interpolation at just the places where it would interpolate across sub-images of the texture – at least not without writing your own fragment shader. This will likely look crude.

另一种解决方案是在不属于演员脸部的每个位置创建3个带有透明纹理像素的纹理图像.然后,使用相同的纹理坐标渲染相同的几何体,但每次渲染不同的图像(即,使3个角色具有相同的多数据,但纹理图像不同).

Another solution would be to create 3 texture images with transparent texels at each location that is not part of the actor's face. Then render the same geometry with the same texture coordinates but a different image each time (i.e., have 3 actors each with the same polydata but a different texture image).

这篇关于当将纹理映射到网格时,Vtk在节点之间插入不正确的颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆