Nuke Python 获取图像数据

通过python有两种方式读取图像的像素数据:

  • 创建分析图像的节点(比如,MinColor, CurveTool),执行,然后读取其结果的knob数值
  • sample方法可以直接抽样节点的像素。


使用CurveTool

创建CurveTool节点,执行后删除,并显示其分析结果:

noise = nuke.createNode('Noise')
noise['zoffset'].setExpression( 'frame*100 ' )
ct = nuke.createNode('CurveTool')

nuke.execute( ct, nuke.frame(), nuke.frame() )

dat = ct['intensitydata'].value()

nuke.delete(ct)
nuke.message( 'average luminance is %s' % dat )
使用sample方法

创建Noise节点,在x=500,y=600抽样红色通道,并输出:

noise = nuke.createNode('Noise')
print noise.sample('red', 500, 600)

下面代码结果一样:

print nuke.sample(noise, 'red', 500, 600)


例子
getMinMax

此工具可以抽取通道中的最大最小值。最近nuke的python api中没有现成的方法,一般利用MinColor的功能来实现。因此工作流中创建一
些临时节点,在当前帧上执行(为我们计算),然后删除。

刚开始,先创建一个测试方案:创建Ramp节点,将Grade节点挂到上面。确保Grade的black clamp knob禁止,然后可以用任意值来测试lift和gain knob。


_images/getMinMax_01.png
_images/getMinMax_01.png

创建MinColor节点,挂到Grade节点,MinColor的channels knob设置成默认rgba就行,调整其他knob。当目标knob被设置为0时,在当前
帧执行。输入节点的rgba层的delta knob保存了最小值。delta knob的值和你在Grade节点的lift knob的值很接近,但为负的。


_images/getMinMax_02.png
_images/getMinMax_02.png

想获取最大值,那么反转图像先,使用MinColor节点再走一边上面的流程。


_images/getMinMax_03.png
_images/getMinMax_03.png

反转图像意味着像素值从1到1-x,需要给delta knob加上1才能获得原始图像的最大值(方法很多)
现在知道怎么获取最大最小值。删除MinColor,反转节点,写一段脚本来干此事。
先从DAG图中抓取Grade1节点,然后添加MinColor节点,其target knob通过python设置为0:

srcNode = nuke.toNode('Grade1')
nuke.nodes.MinColor( target=0 )

其toNode()可以直接获取DAG中的节点。nuke.nodes可以替代nuke.createNode()方法。不同之处在于createNode()和从菜单创建是一样
的。这意味着:

  • 将选择的焦点切换到新节点
  • 尝试链接新节点
  • 自动给新节点定位
  • 挂起当前视图缓冲区
  • 打开默认panel控制面板

nuke.nodes就不是手工操作了,创建节点后,啥也不改变。我们要创建临时节点,后面还要删除,这样用户的节点图就不会因为临时节点
改变。麻烦就是需要手工链接新节点:

srcNode = nuke.toNode('Grade1')
nuke.nodes.MinColor( target=0, inputs=[srcNode])

inputs参数接收一个列表,因为会有多输入。这样,可以一次将其全部链接。
现在需要赋一个参数来定义不需要分析的通道,同时我们不想限制到rgba上。将新节点赋值给变量,随后可以在代码中使用:

srcNode = nuke.toNode('Grade1')
channel = 'rgba.red'
MinColor = nuke.nodes.Mincolor( channels=channel, target=0, inputs=[srcNode])

上面的代码仅分析red通道。
现在创建新MinColor,并反转图像,确保链接对应的输入,并在对应的通道上工作(或许想删除前面的临时节点):

srcNode = nuke.toNode('Grade1')
channel = 'rgba.red'
MinColor = nuke.nodes.MinColor( channels = channel, target=0, inputs=[srcNode] )
Inv = nuke.nodes.Invert( channels = channel, inputs=[srcNode])
MaxColor = nuke.nodes.MinColor( channels = channel, target=0, inputs[Inv] )

结果如下:


images/getMinMax_04.png
images/getMinMax_04.png

现在,节点树已有,执行MinColor节点来获取我们所需。nuke.execute()来办事:

curFrame = nuke.frame()
nuke.execute( MinColor, curFrame, curFrame)

可以看到,需要给节点提供起始帧作为参数,可以用FrameRanges对象替代。在pixeldelta knob中可以找到最小颜色。记得取反才是正确值。

minV = -MinColor['pixeldelta'].value()

现在第二个MinColor干一样的事情,连接到Invert节点(我们存在了MaxColor里面),记得给结果加上1来取得真正的最大值:

nuke.execute(MaxColor, curFrame, curFrame)
maxV = MaxColor['pixeldelta'].value() + 1

现在是清理时间,让我们删除这些节点:

for n in ( MinColor, MaxColor, Inv ):
    nuke.delete(n)

完成代码如下:

srcNode = nuke.toNode(' Grade1')
channel = 'rgba.red'
MinColor = nuke.nodes.MinColor( channels=channel, target=0, inputs=[srcNode] )
Inv = nuke.nodes.Invert( channels = channel, inputs= [srcNode])
MaxColor = nuke.nodes.MinColor( channels =channel, target=0, inputs=[Inv] )

curFrame = nuke.frame()
nuke.execute( MinColor, curFrame, curFrame)
minV = -MinColor['pixeldelta'].value()

nuke.execute( MaxColor, curFrame, curFrame)
maxV = MaxColor['pixeldelta'].value + 1

for n in ( MinColor, MaxColor, Inv):
    nuke.delete(n)

将代码封装成函数,参数为node和channel,默认分析深度通道:

import nuke

def getMinMax( srcNode, channel='depth.Z' ):
    '''
    Return the min and max values of a given node's image as a tuple
    args:
       srcNode  - node to analyse
       channels  - channels to analyse. This can either be a channel or layer name
    '''
    MinColor = nuke.nodes.MinColor( channels=channel, target=0, inputs=[srcNode] )
    Inv = nuke.nodes.Invert( channels=channel, inputs=[srcNode])
    MaxColor = nuke.nodes.MinColor( channels=channel, target=0, inputs=[Inv] )

    curFrame = nuke.frame()
    nuke.execute( MinColor, curFrame, curFrame )
    minV = -MinColor['pixeldelta'].value()

    nuke.execute( MaxColor, curFrame, curFrame )
    maxV = MaxColor['pixeldelta'].value() + 1

    for n in ( MinColor, MaxColor, Inv ):
        nuke.delete( n )
    return minV, maxV

将次模块放到插件路径下,用black 和white点创建Grade节点,并设置为深度通道的最大最小值,其会自动归一化:

minV, maxV = getMinMax(nuke.selectedNode())
grade =nuke.createNode('Grade')
grade['blackpoint'].setValue(minV)
grade['whitepoint'].setValue(maxV)

更加简洁的做法:

nuke.createNode('Grade', 'channels depth.Z blackpoint %s whitepoint %s' % examples.getMinMax(nuke.selectedNode()))


使用Sample

下面是一个LUT的例子:

import nuke

def getLUT( size=1024 ):
    '''
    Get the current viewer process node and generate a simple lut from it
    args:
       size  -  size of resulting lut (default=1024)
    '''
    vpNode = nuke.ViewerProcess.node()
    vp = eval( 'nuke.nodes.%s()' % vpNode.Class() )
    _copyKnobsFromScriptToScript( vpNode, vp )

    ramp = nuke.nodes.Ramp()
    ramp['p0'].setValue( (0, 0) )
    ramp['p1'].setValue( (size, 0) )

    vp.setInput(0, ramp )

    saturation = nuke.nodes.Saturation( saturation = 0 )
    saturation.setInput(0, vp )
    lut = [ saturation.sample("rgba.red", i+.5, 0.5) for i in xrange( 0, size )]

    nuke.delete( saturation )
    nuke.delete( ramp )
    nuke.delete( vp )

    return lut

def createLutNode( lut ):
    '''
    Create a ColorLookup node to hold lut. The values are normalised.
    args:
        lut  -  list of floating point numbers
    '''
    lutNode = nuke.createNode( 'ColorLookup' )
    lutKnob = lutNode['lut']
    for i, y in enumerate( lut ):
        x = float(i) / len(lut)
        lutKnob.setValueAt( y, x )

def _copyKnobsFromScriptToScript( srcNode, trgNode):
    '''
    Copy knobs between nodes.
    This function can also be found in the default menu.py
    args:
       srcNode  -  node to copy values from
       trgNode  -  node to copy values to
    '''
    srcKnobs = srcNode.knobs()
    trgKnobs = trgNode.knobs()
    excludedKnobs = ["name", "xpos", "ypos"]
    intersection = dict([ (item, srcKnobs[ item ]) for item in srcKnobs.keys() if item not in excludedKnobs and trgKnobs.has_key( item ) ])
    for k in intersection.keys():
                trgNode[ k ].fromScript( srcNode[ k ].toScript() )
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容

  • 使用下文描述的nuke.add...()函数,当有变量事件(比如,创建节点,加载脚本)时就自动调用python函数...
    N景波阅读 2,589评论 0 1
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,099评论 18 139
  • 1 序 2016年6月25日夜,帝都,天下着大雨,拖着行李箱和同学在校门口照了最后一张合照,搬离寝室打车去了提前租...
    RichardJieChen阅读 5,016评论 0 12
  • 静谧的夜里,陈然躺在床上,就着床头旁柔和的灯光,捧着从苏荷那里拿来的书。陈然素不喜欢强烈的灯光,他卧室从来只开床旁...
    emilychan阅读 175评论 0 0
  • 差距固然存在,但并不令人遗憾,正是差距和为弥补差距所付出的努力,加强了生命的张力,使其更有层次更加多元。
    德米安的黑白键阅读 143评论 0 0