从Nuke的节点图中提取矢量图像或高分辨率图像



我是一名VFX教师,目前,当我想获取节点图的图像以在讲座幻灯片中使用时,我必须将节点图设置为全屏并进行屏幕捕获,但正如你所能想象的,对于较大的脚本,我必须缩小到有时无法识别的程度。

在我看来,当你放大和缩小时,Nuke的节点图的大小是一样的,这可能是一个隐藏在引擎盖下的矢量图像。我正在寻找一种方法,要么导出此图像,这样我就可以获得整个节点图的高分辨率版本。要么作为矢量,要么只是一个更高分辨率的光栅化图像。

有人知道Python是否有办法做到这一点吗?或者有什么外部脚本可以做到这一点?

我想要这个已经很长时间了,但你的问题让我对它有了更深的了解。

我不相信引擎盖下有真正的矢量图像(它是openGL(,但我也不明白为什么没有一种方法可以自动化全分辨率屏幕截图。

我已经写了一个脚本,它将检查节点图的大小,将缩放设置为100%,并截屏DAG的每一块,然后自动缝合。这需要几秒钟的时间,因为如果我尝试做得太快,就会因为线程而混淆,所以我不得不在每个屏幕截图之间引入人为的暂停。

您应该能够运行下面的代码。别忘了把你的路线设置在倒数第二行!

from PySide2 import QtWidgets, QtOpenGL, QtGui
from math import ceil
import time

def get_dag():
stack = QtWidgets.QApplication.topLevelWidgets()
while stack:
widget = stack.pop()
if widget.objectName() == 'DAG.1':
for c in widget.children():
if isinstance(c, QtOpenGL.QGLWidget):
return c
stack.extend(c for c in widget.children() if c.isWidgetType())
def grab_dag(dag, path):
dag.updateGL()  # This does some funky back and forth but function grabs the wrong thing without it
pix = dag.grabFrameBuffer()
pix.save(path)

class DagCapture(threading.Thread):
def __init__(self, path, margins=20, ignore_right=200):
self.path = path
threading.Thread.__init__(self)
self.margins = margins
self.ignore_right = ignore_right
def run(self):
# Store the current dag size and zoom
original_zoom = nuke.zoom()
original_center = nuke.center()
# Calculate the total size of the DAG
min_x = min([node.xpos() for node in nuke.allNodes()]) - self.margins
min_y = min([node.ypos() for node in nuke.allNodes()]) - self.margins
max_x = max([node.xpos() + node.screenWidth() for node in nuke.allNodes()]) + self.margins
max_y = max([node.ypos() + node.screenHeight() for node in nuke.allNodes()]) + self.margins
# Get the Dag Widget
dag = get_dag()
if not dag:
raise RuntimeError("Couldn't get DAG widget")
# Check the size of the current widget, excluding the right side (because of minimap)
capture_width = dag.width() - self.ignore_right
capture_height = dag.height()
# Calculate the number of tiles required to coveral all
image_width = max_x - min_x
image_height = max_y - min_y
horizontal_tiles = int(ceil(image_width / float(capture_width)))
vertical_tiles = int(ceil(image_height / float(capture_height)))
# Create a pixmap to store the results
pixmap = QtGui.QPixmap(image_width, image_height)
painter = QtGui.QPainter(pixmap)
painter.setCompositionMode(painter.CompositionMode_SourceOver)
# Move the dag so that the top left corner is in the top left corner, screenshot, paste in the pixmap, repeat
for xtile in range(horizontal_tiles):
left = min_x + capture_width * xtile
for ytile in range(vertical_tiles):
top = min_y + capture_height * ytile
nuke.executeInMainThread(nuke.zoom, (1, (left + (capture_width + self.ignore_right) / 2, top + capture_height / 2)))
time.sleep(.5)
nuke.executeInMainThread(grab_dag, (dag, self.path))
time.sleep(.5)
screengrab = QtGui.QImage(self.path)
painter.drawImage(capture_width * xtile, capture_height * ytile, screengrab)
painter.end()
pixmap.save(self.path)
nuke.executeInMainThread(nuke.zoom, (original_zoom, original_center))
print "Capture Complete"
t = DagCapture("C:\Users\erwan\Downloads\test.png")
t.start()

我相信这是可以改进的,但希望它能为你节省时间!

编辑:我现在已经改进了这个代码:https://github.com/herronelou/nuke_dag_capture

最新更新