美文网首页CgTd
Nuke Python Metadata

Nuke Python Metadata

作者: N景波 | 来源:发表于2016-11-22 11:50 被阅读0次

    这章介绍如何读写Metadata。

    读取metadata

    函数metadata() 返回一个字典,包含了特点指定节点的metadata:

    node = nuke.toNode( 'Read1' )
    print node.metadata()
    
    # Result:
    {'exr/displayWindow': [0, 0, 2047, 1555], 'input/width': 2048, 'exr/nuke/camera/vaperture': '18.672', 'input/bitsperchannel': '16-bit half float', 'input/filereader': 'exr', 'nuke/node_hash': 'c82817f8e9526abe', 'input/mtime': '2011-04-11 16:47:54', 'exr/nuke/camera/haperture': '24.576', 'input/ctime': '2011-04-11 16:47:54', 'exr/nuke/camera/matrix': '[-0.30901703238487244, -0.16514922678470612, 0.93660777807235718, 9.5105648040771484, 0.0, 0.98480772972106934, 0.1736481785774231, 2.0, -0.95105648040771484, 0.05366024374961853, -0.30432236194610596, -3.0901703834533691, 0.0, 0.0, 0.0, 1.0]', 'input/filename': '/Volumes/ohufx/consulting/Foundry/PythonDevGuide/footage/metadata/renderWithMetadata.0003.exr', 'input/filesize': 193828, 'exr/screenWindowCenter': [0.0, 0.0], 'exr/dataWindow': [463, 417, 1518, 1435], 'exr/nuke/camera/focal': '50.0', 'exr/screenWindowWidth': 1.0, 'input/height': 1556, 'exr/pixelAspectRatio': 1.0}
    

    打印出来的结果太长没有可读性,用下面的代码增加可读性:

    node = nuke.toNode('Read1')
    for k,v in node.metadata().iteritems():
        print k,v
    

    结果

    # Result:
    exr/displayWindow [0, 0, 2047, 1555]
    input/width 2048
    exr/nuke/camera/vaperture 18.672
    input/bitsperchannel 16-bit half float
    input/filereader exr
    nuke/node_hash c82817f8e9526abe
    input/mtime 2011-04-11 16:47:54
    exr/nuke/camera/haperture 24.576
    input/ctime 2011-04-11 16:47:54
    exr/nuke/camera/matrix [-0.30901703238487244, -0.16514922678470612, 0.93660777807235718, 9.5105648040771484, 0.0, 0.98480772972106934, 0.1736481785774231, 2.0, -0.95105648040771484, 0.05366024374961853, -0.30432236194610596, -3.0901703834533691, 0.0, 0.0, 0.0, 1.0]
    input/filename /Volumes/ohufx/consulting/Foundry/PythonDevGuide/footage/metadata/renderWithMetadata.0003.exr
    input/filesize 193828
    exr/screenWindowCenter [0.0, 0.0]
    exr/dataWindow [463, 417, 1518, 1435]
    exr/nuke/camera/focal 50.0
    exr/screenWindowWidth 1.0
    input/height 1556
    exr/pixelAspectRatio 1.0
    
    设置metadata

    在流中创建自定义metadata,需要使用ModifyMetaData节点。想渲染自定义metadata,就要使用支持它的文件格式( 比如,exr)


    ModifyMetaData 节点接收表达式语法,意味着你可以使用TCL,有限扩展,python。在这个例子中,我们想要将camrea的焦距和
    光圈和其变换矩阵写入metadata。

    在此例中,camera的两个光圈范围使用tcl表达式。camera的焦距使用python. 变换矩阵使用python设置,自定义函数叫getTransform。
    写成代码就如下:

    def getTransform( frame ):
            cam = nuke.toNode( 'masterCam')
            m = []
            for i in range(16):
                m.append( cam['world_matrix'].valueAt( frame, i ))
            return m
    

    将上面的代码加入init.py 或 menu.py ( 或者 import进来 ),你可以让其在knob里面可以用,然后所有自定义部分添加到
    ModifyMetaData 节点。

    例子:
    createMetaDatCam

    此例中,先看一段代码,其根据exr文件中的metadata创建camera。


    开始一个新的函数,检查节点的metadata,如果有足够的信息就创建camera。想在流中的任何地方读取节点的metadata,请使用
    metadata方法:

    def createMetaDatcam( node ):
            mDat = node.metadata()
    

    接下来,收集我们想要在metadata中找到的项目,冠以group名最为前缀( 在metadata中获取全名):

    reqFields = ['exr/nuke/camera/%s' % i for i in ('focal', 'haperture', 'vaperture', 'matrix') ]
    

    检查所需数据是否为metadata的子集,如果不是,停止脚本:

    if not set(reqFiedls).issubset(mDat):
        print 'no metadata for camera found'
        return
    

    询问需要给camera的帧区间,将节点的帧区间作为默认值放入对话框:

    first = node.firstFrame()
    last = node.lastFrame()
    ret = nuke.getFramesAndViews(' Create Camera from Metadata', '%s-%s' %(first, last))
    

    nuke.getFramesAndViews返回一个列表,第一项为帧区间,第二项为所要求的视图。分离帧区间,并将其转换成帧区间对象。
    现在可以忽略视图:

    fRange = nuke.FrameRange( ret[0] )
    

    创建一个camera节点,将其useMatrix knob设置为True:

    cam = nuke.createNode( 'Camera2')
    cam['useMatrix'].setValue( True)
    

    遍历你所需的knob,并设置为动画:

    for k in ('force', 'haperture', 'vaperture', 'matrix'):
        cam[k].setAnimated()
    

    在遍历frame range设置keyframes前,创建一个进度条,用户可以在UI中取消操作。

    task = nuke.ProcessTask('Baking camera from meta data in %s' % node.name() )
    

    用enumerate来循环。其返回当前迭代器的索引,用来更新进度条(这个例子中,名为curTask)。在使用进度条时,要检测用户使用
    点击“取消”来停止循环:

    for curTask, frame in enumerate( fRange ):
        if task.isCancelled():
            break
    

    更新任务信息,告知我们进行到何处:

    task.setMessage('process frame %s' % frame)
    

    现在从metadata中抓取camera的当前帧的焦距和光圈值,转换成浮点值,就可以赋给knob了:

    for k in ('focal', 'haperture', 'vaperture'):
        val = float( node.metadata('exr/nuke/camera/%s', %k, frame))
    

    给knob赋值:

    cam[k].setValueAt( float(val), frame)
    

    这会处理投影参数,现在需要处理camera的变换。这种情况下,metadata保存的字符串仅是python的list,可以使用evaluate转变成list。

    matrixList = eval( node.metadata('exr/nuke/camera/matrix' ))
    

    迭代整个list并给当前帧的摄像机matrix赋值:

    for i,v in enumerate( matrixList ):
            cam['matrix'].setValueAt( v, frame, i)
    

    最后更新进度条,因此,我们就知道进行到哪了。

    task.setProgress( int(float(curTask)/fRange.frames()*100))
    

    全部代码如下:

    import nuke
    def createMetaDatCam( node ):
        '''
        create a camera node from meta data.
        This assumes the following keys in the given nodes meta data stream: 'focal', 'haperture', 'vaperture' and 'matrix',
        where 'matrix' carries the result of "[python nuke.toNode( 'Camera1' ).knob('world_matrix').valueAt( nuke.frame() )]"
        args:
           node  -  node to check for meta data
           ask   -  prompt before creating camera
        '''
        mDat = node.metadata()
        reqFields = ['exr/nuke/camera/%s' % i for i in ('focal', 'haperture', 'vaperture', 'matrix')]
        if not set( reqFields ).issubset( mDat ):
            print 'no metdata for camera found'
            return
    
        first = node.firstFrame()
        last = node.lastFrame()
        ret = nuke.getFramesAndViews( 'Create Camera from Metadata', '%s-%s' %( first, last )  )
        fRange = nuke.FrameRange( ret[0] )
    
        cam = nuke.createNode( 'Camera2' )
        cam['useMatrix'].setValue( True )
    
        for k in ( 'focal', 'haperture', 'vaperture', 'matrix'):
            cam[k].setAnimated()
    
        task = nuke.ProgressTask( 'Baking camera from meta data in %s' % node.name() )
    
        for curTask, frame in enumerate( fRange ):
            if task.isCancelled():
                break
            task.setMessage( 'processing frame %s' % frame )
    
            # GET ALL FRAMES
            for k in ( 'focal', 'haperture', 'vaperture' ):
                val = float( node.metadata( 'exr/nuke/camera/%s' % k, frame ) )
                cam[ k ].setValueAt(  float( val ), frame )
    
            # CONVERT STRING BACK TO LIST OBJECT AND ASSIGN
            matrixList = eval( node.metadata('exr/nuke/camera/matrix') )
            for i, v in enumerate( matrixList ):
                cam[ 'matrix' ].setValueAt( v, frame, i)
            # UPDATE PROGRESS BAR
            task.setProgress( int( float(curTask) / fRange.frames() *100) )
    

    相关文章

      网友评论

        本文标题:Nuke Python Metadata

        本文链接:https://www.haomeiwen.com/subject/bumppttx.html