InstantMesh渲染代码

Instantmesh数据集渲染代码

最近在看到一篇论文,Instantmesh,本来想复现代码,但是论文的作者并没有给出渲染数据集的代码,但是最近看到github上面有作者发布了一个渲染代码,具体看这个链接。然后有幸联系到了这个作者,并且交流了一下。也推荐大家去看看做这个github和它的CSDN,蛮多干货的。
废话不多说,写这篇文章主要是因为在调作者的代码的时候,遇到一些问题,可能是我的blender版本,或者是环境问题,导致并没有呈现出理想的深度图和法线图的效果,所以做了一些修改,在这里分享一下。

‘bpy_prop_collection[key]: key “Depth” not found’

首先第一个问题就是,如果你们在跑作者代码的时候遇到了’bpy_prop_collection[key]: key “Depth” not found’这个问题,这个是因为代码的setup_compositor_nodes函数里面在构造blender的渲染合成树的时候,代码里面创建了一个Renderlayer结点,就是下图
在这里插入图片描述
反映到代码里面就是rl = tree.nodes.new(type=‘CompositorNodeRLayers’)这个语句。但是在后面的links.new(rl.outputs[‘Depth’], depth.inputs[0])这句中,使用了outputs[‘Depth’]。但是在我的blender中,这个结点一开始是没有这个Depth属性的,也就是上图中的引脚是没有depth,想要让它顺利执行,就得先执行bpy.context.scene.view_layers[“ViewLayer”].use_pass_z = True这条语句,相当于在blender中开启Z通道,运行后的节点就会多一个deoth引脚,就像下面一样,
在这里插入图片描述
然后语句就能顺利执行,同理对于normal,也是一样,要提前执行bpy.context.scene.view_layers[“ViewLayer”].use_pass_normal = True这条语句才行。不然links.new(rl.outputs[‘Normal’], normal_save.inputs[‘Image’])也会报错。

渲染深度图和法线图不正确

然后运行后还有一个问题就是深度图和法线图跟RGB图一样的问题,我一开始调通后生成的深度图和法线图是这样的
在这里插入图片描述
在这里插入图片描述
感觉跟RGB没啥区别。后面仔细研究,猜测是blender输出的是多通道,并没有把深度图和法线图单独的输出,所以我就采用了Fileoutput结点,输出单独的通道。就是下面这个:
在这里插入图片描述
具体的直接上代码。

def save_images(object_file: str) -> None:
    os.makedirs(args.output_dir, exist_ok=True)
    reset_scene()
    load_object(object_file)
    object_uid = os.path.basename(object_file).split(".")[0]
    normalize_scene(box_scale=2)
    add_lighting(option='random')
    camera, cam_constraint = setup_camera()

    empty = bpy.data.objects.new("Empty", None)
    scene.collection.objects.link(empty)
    cam_constraint.target = empty

    img_dir = os.path.join(args.output_dir, object_uid)
    os.makedirs(img_dir, exist_ok=True)

    # Prepare to save camera parameters
    cam_params = {
        "intrinsics": get_calibration_matrix_K_from_blender(camera.data, return_principles=True),
        "poses": []
    }

    #setup_compositor_nodes()
    bpy.context.scene.use_nodes = True
    tree = bpy.context.scene.node_tree
    links = tree.links

    for n in tree.nodes:
        tree.nodes.remove(n)
    bpy.context.scene.view_layers["ViewLayer"].use_pass_normal = True
    bpy.context.scene.view_layers["ViewLayer"].use_pass_z = True
    rl = tree.nodes.new(type='CompositorNodeRLayers')
    # Z = tree.nodes.new(type='CompositorNodeZ')
    composite = tree.nodes.new(type='CompositorNodeComposite')
    # depth_out = tree.nodes.new(type='CompositorNodeComposite')
    links.new(rl.outputs['Image'], composite.inputs['Image'])
    # links.new(Z.outputs[0], depth_out.inputs[0])

    image_save = tree.nodes.new(type="CompositorNodeOutputFile")
    links.new(rl.outputs['Image'], image_save.inputs['Image'])
    # 设置深度节点
    depth = tree.nodes.new(type="CompositorNodeMapValue")
    depth.offset = [-0.7]
    depth.size = [0.7]
    depth.use_min = True
    depth.min = [0]
    depth.use_max = True
    depth.max = [255]
    links.new(rl.outputs['Depth'], depth.inputs[0])

    depth_out = tree.nodes.new(type="CompositorNodeComposite")
    links.new(depth.outputs[0], depth_out.inputs[0])
    depth_save = tree.nodes.new(type="CompositorNodeOutputFile")
    links.new(rl.outputs['Depth'], depth_save.inputs['Image'])

    # 设置法线节点
    normal = tree.nodes.new(type="CompositorNodeNormalize")
    links.new(rl.outputs['Normal'], normal.inputs[0])
    normal_out = tree.nodes.new(type="CompositorNodeComposite")
    links.new(normal.outputs[0], normal_out.inputs[0])
    normal_save = tree.nodes.new(type="CompositorNodeOutputFile")
    links.new(rl.outputs['Normal'], normal_save.inputs['Image'])
    for i in range(args.num_images):
        render_path = os.path.join(img_dir, f"{i:03d}.png")
        image_save.base_path = img_dir
        image_save.file_slots[0].path=f"{i:03d}_image"
        image_save.format.file_format='PNG'

        depth_save.base_path = img_dir
        depth_save.file_slots[0].path = f"{i:03d}_depth"
        depth_save.format.file_format = 'PNG'

        normal_save.base_path = img_dir
        normal_save.file_slots[0].path = f"{i:03d}_normal"
        normal_save.format.file_format = 'PNG'

        # Set the camera position
        camera_option = 'random' if i > 0 else 'front'
        camera = set_camera_location(camera, option=camera_option)
        bpy.ops.render.render(write_still=True)

       
    for filename in os.listdir(img_dir):
        # 检查是否为文件
        if os.path.isfile(os.path.join(img_dir, filename)):
            name, extension = os.path.splitext(filename)

            # 获取新文件名,去掉文件名部分的最后三个字符
            new_name = name[:-4]

            # 构建完整的新文件名
            new_filename = new_name + extension

            # 构建完整的旧文件路径和新文件路径
            old_filepath = os.path.join(img_dir, filename)
            new_filepath = os.path.join(img_dir, new_filename)

            # 重命名文件
            shutil.move(old_filepath, new_filepath)

    # Save camera intrinsics and poses
    np.savez(os.path.join(img_dir, 'camera.npz'), **cam_params)

这个就是我对作者发布的代码的主要修改,改的是blender——scriipt脚本里面的save_image函数。具体来讲,我注释掉了setup_compositor_nodes()这个函数,然后重写了生成渲染树的过程,在原本的渲染树上面新加了三个fileoutput结点分别为image_save,depth_save,normal_save,单独输出保存RGB,深度图,法线图。至于最后的一部分

for filename in os.listdir(img_dir):
        # 检查是否为文件
        if os.path.isfile(os.path.join(img_dir, filename)):
            name, extension = os.path.splitext(filename)

            # 获取新文件名,去掉文件名部分的最后三个字符
            new_name = name[:-4]

            # 构建完整的新文件名
            new_filename = new_name + extension

            # 构建完整的旧文件路径和新文件路径
            old_filepath = os.path.join(img_dir, filename)
            new_filepath = os.path.join(img_dir, new_filename)

            # 重命名文件
            shutil.move(old_filepath, new_filepath)

这个主要是因为我在运行的时候发现blender这个fileoutput结点输出的文件命名会遵循blender的文件命名,就是会加上帧号,这个我觉得怪怪的,所以就自己写了一个代码去掉最后的帧号。最后运行的结果如下:
在这里插入图片描述
已经有正常的法线和深度图,并且命名不带帧号。

以上就是我对作者代码的修改,也非常感谢作者提供的修改代码,亲测可用,大家都可以去下载试试看。是个很好的用python程序化渲染深度图和法线图的代码,再次感谢作者Mrgaunglei

  • 17
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在Cesium中,您可以使用`CustomDataSource`和`CustomRenderPrimitive`来自定义渲染代码。 `CustomDataSource`是一种特殊类型的`DataSource`,它允许您在场景中添加自定义的实体和几何图形。您可以使用`CustomRenderPrimitive`在场景中添加自定义的渲染图元,每个渲染图元都可以实现自己的渲染逻辑。 以下是一个简单的示例,演示如何使用`CustomDataSource`和`CustomRenderPrimitive`来自定义渲染代码: ```javascript // 创建Cesium Viewer var viewer = new Cesium.Viewer('cesiumContainer'); // 创建自定义数据源 var customDataSource = new Cesium.CustomDataSource('custom'); // 添加自定义实体 var entity = customDataSource.entities.add({ position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883), billboard: { image: 'path/to/image.png', scale: 2.0 } }); viewer.dataSources.add(customDataSource); // 创建自定义渲染图元 var customPrimitive = new Cesium.CustomRenderPrimitive({ geometryInstances: new Cesium.GeometryInstance({ geometry: new Cesium.RectangleGeometry({ rectangle: Cesium.Rectangle.fromDegrees(-75.0, 35.0, -125.0, 45.0) }), attributes: { color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED) } }), fragmentShaderSource: 'void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); }', vertexShaderSource: 'attribute vec3 position3DHigh;\ attribute vec3 position3DLow;\ attribute vec4 color;\ varying vec4 v_color;\ void main() {\ vec4 position = czm_computePosition();\ gl_Position = czm_viewProjection * position;\ v_color = color;\ }', renderState: { blending: Cesium.BlendingState.DISABLED, depthTest: { enabled: true, func: Cesium.DepthFunction.LESS }, depthMask: true, polygonOffset: { enabled: false, factor: 0.0, units: 0.0 } } }); viewer.scene.primitives.add(customPrimitive); ``` 在上面的代码中,我们首先创建了一个Cesium Viewer,并创建了一个自定义数据源。然后,我们向自定义数据源中添加了一个自定义实体,并将其添加到场景中。接下来,我们创建了一个自定义渲染图元,并将其添加到场景中。在自定义渲染图元中,我们使用了自定义的顶点着色器和片段着色器,并设置了渲染状态。 请注意,上面的示例仅用于演示目的。实际应用中,您可能需要更复杂的渲染逻辑和着色器代码
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值