blender 命令行渲染
Posted 长虹剑
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了blender 命令行渲染相关的知识,希望对你有一定的参考价值。
文章目录
基础环境配置
安装及资料
apt-get install blender
虚拟桌面 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')
自己的一些代码
(未整理)
基本渲染设置
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'Bonei']
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)
骨骼驱动的一些心得 【!!! 重要】
骨骼的正确驱动包括几个因素:
- 骨骼设计
- 蒙皮权重
- 代码与骨骼的对应
比如基于SMPL样式的骨架有下面两种
1)完全符合 SMPL 系数的骨架
2)符合直觉的骨架
这两种骨架会导致使用smpl系数时写代码以及自动绑定的难易。
- 第一种骨骼:与SMPL系数几乎直接对应(可能需要坐标变换),但是如果使用blender的自动绑定权重会非常不合理,需要手动刷权重。
- 第二种骨骼:需要根据骨骼局部坐标轴,确定变换矩阵。(就需要写code时推导一下)
一些总结@9-2
- 在坐标系转换中,最终考虑的是点变换,但是我们一般直接看坐标系得到的变换其实是坐标系变换,与点变换互逆
- 由1 可知我们实际得到标准坐标系到骨骼局部坐标系的变换 M: A->B, 而点变换是M.T
- 执行坐标系变换夹杂旋转变换时时要考虑一个点,最终可以得到 M_.T x R x M_ x p , 前三个组成了最终的旋转变换,注意如果使用2,则M_=M.T
- 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))
以上是关于blender 命令行渲染的主要内容,如果未能解决你的问题,请参考以下文章