【问题标题】:Blender creates screenshot using python script but not when running in backgroundBlender 使用 python 脚本创建屏幕截图,但在后台运行时不会
【发布时间】:2017-12-09 18:34:04
【问题描述】:

我是疯了还是这个功能有一些错误(使用 python 脚本和后台运行的搅拌机)?

1/ 在 Blender 中复制/粘贴以下代码(来自 screenshot.py)(切换到脚本视图),它会截取屏幕截图,但是...

2/ 从命令行调用此脚本:(这样您就可以在使用脚本修改场景时自动进行屏幕截图...用于您的博客、教程等)

blender --background --python screenshot.py

而且它会崩溃而不给出上下文中“不正确”的信息

screenshot.py:

import os, sys

#FIXME: Blender creates screenshot using python but not when running in background
#
# Same result from Ubuntu stock version (2.76) and from ppa (2.78)
#
# Within Blender : unable to fix this last warning but screenshot is generated !
#
#Traceback (most recent call last):
#  File "/usr/share/blender/2.78/scripts/startup/bl_ui/space_text.py", line 32, in draw
#    text = st.text
#AttributeError: 'SpaceView3D' object has no attribute 'text'
#
# From command line (crash) : blender --background --python screenshot.py
# Unable to determine what's wrong in the context
#
#Traceback (most recent call last):
#(...)
#File "/usr/share/blender/2.78/scripts/modules/bpy/ops.py", line 187, in __call__
#    ret = op_call(self.idname_py(), C_dict, kw, C_exec, C_undo)
#RuntimeError: Operator bpy.ops.screen.screenshot.poll() failed, context is incorrect

def screenshot(P_filename, P_path = None):
  import bpy

  L_saveAs = P_filename
  L_saveAs = os.path.join(P_path, L_saveAs) if P_path else os.path.join("/tmp", L_saveAs)
  print("Scene saved in " + L_saveAs)

  #XXX: switching to 3D full view = maximize scene in main window
  #bpy.context.window.screen = bpy.data.screens['3D View Full']
  for window in bpy.context.window_manager.windows:
    screen = window.screen
    print("Window : " + str(window.width) + "x" + str(window.height) + ":" + str(window.x) + "," + str(window.y))
    print("Screen : " + str(screen.name) + ", Scene : " + str(screen.scene.name))
    #for area in bpy.context.screen.areas:
    for area in screen.areas:
      print("Area   : " + str(area.type))
      if area.type == 'VIEW_3D':
        for space in area.spaces:
          print("Space  : " + str(space.type))
          if space.type == 'VIEW_3D':
            #space.viewport_shade = 'RENDERED'
            for region in area.regions:
              print("Region  : " + str(region.type))
              if region.type == 'WINDOW':
                L_altBpyCtx = {                        # defining alternative context (allowing modifications without altering real one)
                  'area'      : area                   # our 3D View (first found)
                , 'blend_data': bpy.context.blend_data # just to suppress PyContext warning, doesn't seem to have any effect
                #, 'edit_text' : bpy.context.edit_text  # just to suppress PyContext warning, doesn't seem to have any effect
                , 'region'    : None                   # just to suppress PyContext warning, doesn't seem to have any effect
                #, 'scene'     : bpy.context.scene
                , 'scene'     : screen.scene
                , 'space'     : space
                , 'screen'    : window.screen
                #, 'window'    : bpy.context.window     # current window, could also copy context
                , 'window'    : window                 # current window, could also copy context
                }
                bpy.ops.screen.screenshot(L_altBpyCtx, filepath = L_saveAs, full = False)
                break #XXX: limit to the window of the 3D View
            break #XXX: limit to the corresponding space (3D View)
        break #XXX: limit to the first 3D View (area)

screenshot("screenshot.png", ".")

3/ 顺便说一下,在没有“--background”参数的情况下调用它,它将生成一个空屏幕截图(窗口大小,全是灰色)。同时,取消注释

#bpy.context.window.screen = bpy.data.screens['3D View Full']

和/或

#space.viewport_shade = 'RENDERED'

您会看到 Blender 界面受到影响(将视图的布局从“默认”切换到“3D 全视图”和/或视口阴影从默认的“实心”切换到“渲染”).. . 所以脚本实际上被解释了,但它不会生成屏幕截图!

无论如何,问题似乎来自直接从命令行使用“--python somescript.py”调用Blender

我可能错过了什么?!感谢您的帮助

【问题讨论】:

  • --background 选项在没有 UI 的情况下运行...那么您希望如何遍历 UI 元素来截取屏幕截图?
  • Blender process 在后台启动,UI 只是 未显示,但它仍然可用(故意,因此可以编写任务/渲染脚本/自动化)。 UI 组件,即使没有显示,也只是像其他组件一样被视为对象,因此您可以使用/修改/创建它们或使用 bpy.ops.someObject.doSomething 等运算符操作它们。尝试blender --background --python screenshot.py,您将看到脚本遍历 UI 树的每个组件(窗口 > 屏幕 > 场景 > 区域)。顺便说一句,试试blender --python screenshot.py,你会得到一个“空”的截图。
  • 为了更好地理解/完整解释:Blender Official tips and tricks此功能对于有兴趣控制(感谢多视图/逐步屏幕截图)编程建模/操作(使用开源软件:Blender 而不是其他有限的工具,如 OpenScad),让我们在 3D 打印环境中说。能够以编程方式截取屏幕截图而不是只看到最终结果,真的有助于“调试”!
  • 来自提示和技巧页面:“非交互式脚本最终可以更有效地不使用 Blenders 界面,而是在命令行上执行脚本。”关键词是“非交互式”——你可以渲染到一个文件中,但你不能对不在屏幕上的东西进行 screen 的拍摄。 UI 根本不呈现。 Blender 对象 和场景图可用,但 UI 元素不可用。为了使您的屏幕截图正常工作,您需要将 UI 呈现到一个文件中,我不知道有任何 UI 以这种方式工作。
  • 感谢 Dale 的帮助,但调用相同的命令行(第 3 点)不带“--background”,因此您现在有一个“完整”的 Blender UI 正在运行并且仍然屏幕截图没有达到预期的效果! (如果您取消注释前面指出的行,您可以看到脚本本身修改的界面)。您甚至可以在 bpy.ops.screen.screenshot 中设置 Full = True (因此 all 应该捕获 UI)......结果相同!我实际上可以在后台使用搅拌机从 python 渲染很多东西,但是这种方法是有限的,因为您必须逐个视图渲染视图并且看不到选择

标签: python screenshot blender


【解决方案1】:

从 Blender 的人那里得到了答案(感谢 sergey)。底线:这是一个限制,因为通过命令行参数传递的所有脚本都是在命令行处理时执行的,在任何 OpenGL 绘制完成之前

警告是由试图欺骗系统的脚本引起的,并且 覆盖上下文,该上下文可能处于不一致状态。 从界面运行屏幕截图时,您不需要覆盖 任何上下文。

通过命令行参数传递的所有脚本都在 命令行处理时间,在任何 OpenGL 绘制完成之前。这 屏幕截图操作员本身只是读取 OpenGL 缓冲区,m 没有 做任何实际的绘图(它不能画任何东西,因为那会是 不安全)。

在后台模式下运行搅拌机时,没有创建窗口, 这也意味着没有 OpenGL 上下文。您不能使用屏幕截图 在这样的配置中。

感谢您的报告,但这只是限制,不能 很容易绕过。

精确度:(因为提供的代码没有显示所有试图“欺骗”Blender 的尝试)

遗憾的是,如果您也/仍然对此类功能感兴趣,您将不得不在(Blender)框外思考!不要浪费时间尝试“欺骗”Blender,例如延迟脚本执行、使用应用程序处理程序、在文本编辑器中伪造脚本导入等......我已经为你做到了:它不起作用,可能出于非常相似的原因。

【讨论】:

  • 这在blender 2.8中仍然是一个问题吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-18
  • 2010-09-09
  • 2015-07-29
  • 1970-01-01
相关资源
最近更新 更多