blender 命令行渲染

基础环境配置

最新的方法感觉很简单

就直接在这里下载2.93 , 使用的时候好像不需要Xvfb?
为内置python下载一些东西

blender_path=blender-2.93.15-linux-x64 # 自己写
blender_python_path=$blender_path/2.93/python/bin/python3.9

export PATH="$blender_path:$PATH"

#blender --background --version
#blender --background --python-expr "import sys; print('\nThe version of python is '+sys.version.split(' ')[0])"

#blender --background --python-expr "import sys; import os; print('\nThe path to the installation of python of blender can be:'); print('\n'.join(['- '+x.replace('/lib/python', '/bin/python') for x in sys.path if 'python' in (file:=os.path.split(x)[-1]) and not file.endswith('.zip')]))"

# 注意检查 python 版本
$blender_python_path -m ensurepip --upgrade

for e in pytest-shutil matplotlib tqdm hydra-core six shortuuid moviepy natsort
do
    $blender_python_path -m pip install $e #--user --upgrade
done

安装及资料

apt-get install blender

Blender 2.91 参考手册

运行python脚本

Blender python 初步文档

有关渲染的样例

虚拟桌面 Xvfb

在服务器上想要运行blender需要建立虚拟桌面,挺简单的就

apt-get install Xvfb

使用的时候,首先开启虚拟桌面到后台,然后就可以运行 blender 了

export DISPLAY=:6
Xvfb -ac :6 -screen 0 640x480x24 & # 1920x1080x24
blender -b --render-output tmp/res -f 0

blender 内置 python 修改 packages

找了半天至今不知道 blender 到底是调用的哪里的 python ,不过我猜测它可能把 python 给直接编译进去了,所以后期我们应该是换不了这个python的。所以就直接 sys 中替换加载变量的路径就行。

具体就是先运行

blender -b -P ck_bpy.py

ck_bpy.py 就写一个 print(sys.path)
获得路径,然后自己的 python 也打印一下,把路径拿出来,插入到指定位置就行。

内置blender 安装库

看到这里也可以考虑把 anaconda 的环境装到这里

cd D:/program/BlenderFoundation/Blender2.93/2.93/python/bin
 ./python -m pip install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple
cd D:/program/BlenderFoundation/Blender2.93/2.93/python/Scripts
./pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple
./pip install Pillow -i https://pypi.tuna.tsinghua.edu.cn/simple
./pip install scipy -i https://pypi.tuna.tsinghua.edu.cn/simple

编译 blender (别看了)

svn 太慢,wget 下载的方法如下

wget -P download -r -p -np https://svn.blender.org/svnroot/bf-blender/trunk/lib/linux_centos7_x86_64 -o res.log

初步尝试杂记

渲染

用默认的blend,调用脚本渲染

blender -b -P tmp/test.py -o tmp/res -f 0
import bpy
for e in bpy.data.objects:
    print(e.name)
bpy.ops.render.render()
bpy.data.images['Render Result'].save_render(filepath='tmp/res/example.png')

直接命令行指定渲染
https://blenderartists.org/t/animating-rotation-using-keyframes-in-python/590243

blender -b --render-output tmp/res -f 0

计算

ob.matrix_world = Matrix.Translation(ob.location) * Matrix.Rotation(radians(45), 4, 'Z')

自己的一些代码

(未整理)

打印(print)到控制台

直接print 调用脚本时看不到

from bpy import context
import builtins as __builtin__

def console_print(*args, **kwargs):
    for a in context.screen.areas:
        if a.type == 'CONSOLE':
            c = {}
            c['area'] = a
            c['space_data'] = a.spaces.active
            c['region'] = a.regions[-1]
            c['window'] = context.window
            c['screen'] = context.screen
            s = " ".join([str(arg) for arg in args])
            for line in s.split("\n"):
                bpy.ops.console.scrollback_append(c, text=line)

def print(*args, **kwargs):
    """Console print() function."""

    console_print(*args, **kwargs) # to py consoles
    __builtin__.print(*args, **kwargs) # to system console

基本渲染设置

def f2_render_bones_video():
    FPS = 15 # 60
    smpl2skeleton = Cls_smpl2skeleton( fsmpl2rig, fparents, frot_mp )
    pms = smpl2skeleton.example( fpm )
    params.pms = pms
    params.parents = smpl2skeleton.parents
    params.NJ = smpl2skeleton.NJ

    ob = bpy.data.objects["smpl_skeleton"]
    bpy.app.handlers.frame_change_pre.clear()
    bpy.app.handlers.frame_change_pre.append(frame_change_pre)
    bpy.context.view_layer.objects.active = ob #相当于鼠标左键选中
    bpy.ops.object.mode_set(mode='POSE') #切换为pose更改模式
    arr = []
    bones = []
    for i in range(24):
        bone=ob.pose.bones[f'Bone{i}']
        bone.rotation_mode = 'AXIS_ANGLE' #'XYZ'
        bones.append( bone )
        if i==0:
            arr.append( bone.location.copy() )
        arr.append( bone.rotation_axis_angle )  # tuple arr
    #print( [ e[:] for e in arr ] )
    params.T_pose = arr
    params.bones = bones
    set_render_engine()
    if isdbg:
        #set_scene( 30  )
        set_scene( 3  )
    else:
        set_scene( len(params.pms)  )
    set_render_for_video( fv, fps=FPS )

    bpy.ops.wm.save_mainfile( filepath = fblend )

def frame_change_pre(scene):
    rcnt = scene.frame_current
    NJ = params.NJ
    bones = params.bones
    bones[0].location = params.T_pose[ 0 ].copy()
    for i in range(params.NJ):
        #if i==0:
        #    print(111, params.T_pose[ i+1 ][:], bones[i].rotation_axis_angle[:])
        bones[i].rotation_axis_angle = params.T_pose[ i+1 ]

    pm = params.pms[rcnt]
    for i in range(NJ-1, -1, -1):
        a = 3+i*4
        #if i==0:
        #    print( pm[a:a+4], bones[i].rotation_axis_angle[:] )
        bones[i].rotation_axis_angle = tuple(pm[a:a+4].tolist())
    bones[0].location = pm[:3]


def set_render_engine():
    for scene in bpy.data.scenes:
        scene.render.engine = 'BLENDER_EEVEE'

    scene = bpy.context.scene
    eevee = scene.eevee

    eevee.use_soft_shadows = True

    eevee.use_ssr = True
    eevee.use_ssr_refraction = True

    eevee.use_gtao = True
    eevee.gtao_distance = 1

    eevee.use_volumetric_shadows = True
    eevee.volumetric_tile_size = '2'

def set_scene( full_frame ):
    bpy.context.scene.frame_end = full_frame
    #bpy.context.scene.camera = bpy.data.objects['camera']

def set_render_for_video(fv, fps=30, w=640, h=360 ):
    r = bpy.context.scene.render
    r.filepath = fv
    #scene.render.image_settings.file_format = 'PNG' # set output format to .png
    r.image_settings.file_format = 'FFMPEG' # set output format to .png
    r.ffmpeg.format = 'MPEG4'
    r.fps = fps
    r.resolution_x = w
    r.resolution_y = h

    bpy.ops.render.render(animation=True)

    #r.image_settings.file_format = 'PNG'
    #r.color_mode = 'RGBA'
    #bpy.types.FFmpegSettings.codec = "PNG"
    #bpy.types.FFmpegSettings.pix_fmt = "RGBA"

def set_render_for_picture(fimg, w=640, h=360 ):
    r = bpy.context.scene.render
    r.filepath = fimg
    r.image_settings.file_format = 'PNG'
    r.resolution_x = w
    r.resolution_y = h
    bpy.ops.render.render(write_still=True)

骨骼驱动的一些心得 【!!! 重要】

骨骼的正确驱动包括几个因素:

  1. 骨骼设计
  2. 蒙皮权重
  3. 代码与骨骼的对应

比如基于SMPL样式的骨架有下面两种
1)完全符合 SMPL 系数的骨架
在这里插入图片描述
2)符合直觉的骨架
在这里插入图片描述

这两种骨架会导致使用smpl系数时写代码以及自动绑定的难易。

  1. 第一种骨骼:与SMPL系数几乎直接对应(可能需要坐标变换),但是如果使用blender的自动绑定权重会非常不合理,需要手动刷权重。
  2. 第二种骨骼:需要根据骨骼局部坐标轴,确定变换矩阵。(就需要写code时推导一下)

一些总结@9-2

  1. 在坐标系转换中,最终考虑的是点变换,但是我们一般直接看坐标系得到的变换其实是坐标系变换,与点变换互逆
  2. 由1 可知我们实际得到标准坐标系到骨骼局部坐标系的变换 M: A->B, 而点变换是M.T
  3. 执行坐标系变换夹杂旋转变换时时要考虑一个点,最终可以得到 M_.T x R x M_ x p , 前三个组成了最终的旋转变换,注意如果使用2,则M_=M.T
  4. blender 中显示的是骨骼的局部坐标系,如果想要变成统一的骨骼,那么骨骼都是竖直朝上的,这样写程序好些,但是自动绑定的时候蒙皮会有很大的问题。

之后发现一个事情
当blender中导入fbx 选择自动骨骼坐标系时,骨骼看起来会比较正常,但是传入的系数就必须改变
这里有几个后来分析得出的知识
1) bvh 默认就是 ogl 坐标系,和 smpl 的骨骼时一模一样的
2)blender 中 fbx 其实坐标系也是 ogl ,但是如果骨骼旋转,他会把这个旋转矩阵给记录下来,而这个matrix 就是坐标系变换
3)其他 maya motionbuilder 软件一打开就是正常的说明人间会自动根据子集和父级的关系给你连上线,但是保存的时候不会动你的 matrix
4)blender 中不像may,它不会自己改变骨骼帮你连,而且一旦改变了骨骼,这个matrix就存下来了,这样以后你给的系数就必须按照新的骨骼坐标系给。(所以需要有个坐标系变换 具体推导可以看一下这里的: 坐标系变换,对应旋转与平移形变
5)fbx 导入 blender 选择自动骨骼坐标系,操作完动画,然后转为 bvh, 然后用 bvh 的数据给到 原始的 fbx 依然可以得到正确的动画。 这说明那个matrix 的变换和动画的变换都合并了。

关键帧动画

def f4_test():
    set_render_engine()
    # useful shortcut
    scene = bpy.context.scene

    # this shows you all objects in scene
    scene.objects.keys()

    # when you start default Blender project, first object in scene is a Cube
    kostka = scene.objects[0]

    # you can change location of object simply by setting the values
    kostka.location = (1,2,0)

    # same with rotation
    kostka.rotation_euler = (45,0,0)

    # this will make object cease from current scene
    #scene.objects.remove(kostka)
    kostka.select_set(True)
    bpy.ops.object.delete()

    # clear everything for now
    scene.camera = None  
    for obj in scene.objects:  
        #scene.objects.remove(obj)
        obj.select_set(True)
        bpy.ops.object.delete()

    # create sphere and make it smooth
    bpy.ops.mesh.primitive_uv_sphere_add(location = (2,1,2), radius=0.5)  
    bpy.ops.object.shade_smooth()  
    kule = bpy.context.object

    # create new cube
    bpy.ops.mesh.primitive_cube_add(location = (-2,1,2))  
    kostka = bpy.context.object

    # create plane 
    bpy.ops.mesh.primitive_plane_add(location=(0,0,0))  
    plane = bpy.context.object  
    plane.dimensions = (20,20,0)

    # for every object add material - here represented just as color
    for col, ob in zip([(1, 0, 0, 0), (0,1,0,0), (0,0,1,0)], [kule, kostka, plane]):  
        mat = bpy.data.materials.new("mat_" + str(ob.name))
        mat.diffuse_color = col
        ob.data.materials.append(mat)

    # now add some light
    light_data = bpy.data.lights.new(name="light_2.80", type='POINT')
    light_data.energy = 30

    light_object = bpy.data.objects.new(name="light_2.80", object_data=light_data)

    # link light object
    bpy.context.collection.objects.link(light_object)
    
    # make it active 
    bpy.context.view_layer.objects.active = light_object
    light_object.location = (-3, 0, 12)
    
    # update scene, if needed
    #dg = bpy.context.evaluated_depsgraph_get() 
    #dg.update()

    # and now set the camera
    cam_data = bpy.data.cameras.new(name="cam")  
    cam_ob = bpy.data.objects.new(name="Kamerka", object_data=cam_data)  
    bpy.context.collection.objects.link(cam_ob)  
    cam_ob.location = (-3, 0, 5)  
    cam_ob.rotation_euler = (3.14/6,0,-0.3)  
    cam = bpy.data.cameras[cam_data.name]  
    cam.lens = 10
    scene.camera = cam_ob

    ### animation
    positions = (0,0,2),(0,1,2),(3,2,1),(3,4,1),(1,2,1)

    # start with frame 0
    number_of_frame = 0  
    for pozice in positions:

        # now we will describe frame with number $number_of_frame
        scene.frame_set(number_of_frame)

        # set new location for sphere $kule and new rotation for cube $kostka
        kule.location = pozice
        kule.keyframe_insert(data_path="location", index=-1)

        kostka.rotation_euler = pozice
        kostka.keyframe_insert(data_path="rotation_euler", index=-1)
        kostka.location = pozice
        kostka.keyframe_insert(data_path="location", index=-1)
        

        # move next 10 frames forward - Blender will figure out what to do between this time
        number_of_frame += 10

    set_scene( number_of_frame )
    set_render_for_video( fvabs, fps=params.FPS, w=params.width, h=params.height )

    bpy.ops.wm.save_mainfile( filepath = fblend )
    pass

网上一些可以参考的代码

包含渲染的代码
https://github.com/DeepMotionEditing/deep-motion-editing
https://github.com/jonepatr/genea_visualizer

blender2.9 一些代码

复制物体

import bpy
xy=[[0,2],[0,4],[0,5],[0,7]]
xy_count=len(xy)
for i in range(xy_count):
    factor=3
    x=xy[i][0]*factor
    y=-xy[i][1]*factor
    z=0
    bpy.ops.object.select_all(action="DESELECT")
    bpy.data.objects["cube"].select_set(True)
    bpy.ops.object.duplicate_move(OBJECT_OT_duplicate={"mode":"TRANSLATION"},TRANSFORM_OT_translate={"value":(x,y,z)})
  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
### 回答1: 如果Blender命令行未响应,可能是由于多种原因引起的。以下是一些可能的解决方案: 1. 等待一段时间,看看是否会出现响应。有时,Blender需要一些时间来完成任务。 2. 检查您的系统资源是否足够。如果您的计算机内存不足或处理器速度较慢,可能会导致Blender未响应。 3. 确保您的Blender版本是最新的。有时候,旧版本可能会出现问题。 4. 检查您的文件是否有损坏或出现其他错误。您可以尝试打开其他文件,看看Blender是否能够响应。 5. 如果以上方法都不起作用,您可以尝试重新安装Blender。 希望以上解决方案能够帮助您解决Blender未响应的问题。 ### 回答2: 当使用Blender命令行时遇到未响应的情况,可以尝试以下方法来解决问题: 1. 检查系统要求:确保你的计算机满足Blender的系统要求,包括操作系统版本、处理器和内存等方面的要求。 2. 更新Blender版本:尝试更新Blender到最新的版本,因为新版本可能修复了一些已知的问题和错误。 3. 检查命令行输入:确保你正确输入了Blender命令行指令。检查命令语法和参数是否正确,以免导致Blender无法响应。 4. 减少负载:如果你的计算机正在运行其他占用大量CPU或内存资源的程序,尝试关闭它们,以便给Blender更多的系统资源。 5. 检查文件路径:确保你指定的文件路径是正确的,包括输入和输出文件路径等。如果路径是无效的或文件损坏,Blender可能无法响应。 6. 检查硬件问题:如果你的计算机存在硬件问题,如散热不良或内存损坏等,可能会导致Blender命令行无法响应。尽量保证计算机的硬件状态良好。 7. 联系支持:如果以上方法都无法解决问题,建议你联系Blender的官方支持团队,向他们报告你的问题并获取进一步的帮助和支持。 以上是一些常见的解决方法,但具体情况可能会有所不同,取决于具体的环境和问题。如果问题持续存在,最好寻求专业的技术支持来解决。 ### 回答3: 当Blender命令行未响应时,您可以尝试以下方法来解决问题: 1. 检查系统要求:确保您的计算机符合Blender所需的硬件和软件要求。检查您的操作系统版本、硬件配置和驱动程序更新是否符合Blender的要求。 2. 关闭多余的程序:关闭其他正在运行的程序,特别是占用大量系统资源的程序。这样可以释放计算机的资源,使Blender能够更好地运行。 3. 重新启动:尝试重新启动计算机,有时这可以解决临时的系统问题。 4. 检查文件:确保您正在使用的Blender文件没有损坏或出现其他问题。尝试打开其他文件,看看是否仍然出现命令行未响应的问题。 5. 更新和升级:检查Blender的最新版本,如果您正在使用的是旧版本,可以尝试下载并安装最新版本的Blender来解决一些已知的问题。 6. 清理缓存:Blender在运行过程中会产生临时文件和缓存,这些文件可能会导致命令行未响应。您可以尝试清理Blender的缓存并重新运行。 7. 寻求帮助:如果您尝试了上述方法仍然无法解决问题,建议前往Blender的官方支持社区或论坛寻求帮助。在那里,您可以向其他用户和开发者寻求指导和解决方案。 请注意,这些方法只是一些常见的解决方案,可能因个人情况或具体问题而有所不同。如果问题仍然存在,建议您联系Blender的技术支持团队或其他相关专业人士以获取更详细的帮助和支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值