You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Open3D渲染场景中点光源无法正常工作的问题排查

问题

使用Open3D显示STL模型时,尝试添加额外点光源以突出模型边缘,但渲染器与光源函数无法正常工作。当前代码如下:

import open3d as o3d
import open3d.visualization.gui as gui
import open3d.visualization.rendering as rendering
import time
import numpy as np
count = 1

def capture_img(vis):
    global count
    time.sleep(3)
    #vis.capture_screen_image(f'test{count}.png', True)
    count += 1
    ctr.rotate(30.0, 0.0)
    return False


mesh = o3d.io.read_triangle_mesh("cad/Plug01_simplified_detailed2.STL")
mesh = mesh.compute_vertex_normals()
mesh.paint_uniform_color([1, 0, 0])

vis = o3d.visualization.Visualizer()
vis.create_window()
vis.add_geometry(mesh)


print(vis.get_window_name())

ctr = vis.get_view_control()
ctr.change_field_of_view(step=-90)  # drastically reduced perspective effect
vis.register_animation_callback(capture_img)

renderer = o3d.visualization.rendering.Renderer
scene = o3d.visualization.rendering.Scene
color = np.array([1., 1., 0.], dtype=np.float32)
position = np.array([3., 3., 0.], dtype=np.float32)
scene.add_point_light('light', color, position, 1e8, 1e2, True)


vis.run()
vis.destroy_window()

收到的错误提示:

add_point_light(): incompatible function arguments. The following argument types are supported:
    1. (self: open3d.cpu.pybind.visualization.rendering.Scene, name: str, color: numpy.ndarray[numpy.float32[3, 1]], position: numpy.ndarray[numpy.float32[3, 1]], intensity: float, falloff: float, cast_shadows: bool) -> bool

Invoked with: 'light', array([1., 1., 0.], dtype=float32), array([3., 3., 0.], dtype=float32), 100000000.0, 100.0, True

疑问:renderer和scene对象定义是否正确?是否存在参数数据类型错误?尝试用gui对象替代visualizer也无法正常运行。

解决方案

问题根源

  1. Scene和Renderer未创建实例:直接引用Scene和Renderer类,而非从当前Visualizer窗口获取实际场景实例,导致调用add_point_light时缺少正确的self对象。
  2. 数组形状不匹配:错误提示要求color和position为形状(3,1)的列向量,但传入的是形状(3,)的一维数组。

修正后的代码

import open3d as o3d
import time
import numpy as np

count = 1

def capture_img(vis):
    global count
    time.sleep(3)
    # vis.capture_screen_image(f'test{count}.png', True)
    count += 1
    ctr.rotate(30.0, 0.0)
    return False

# 加载并处理模型
mesh = o3d.io.read_triangle_mesh("cad/Plug01_simplified_detailed2.STL")
mesh.compute_vertex_normals()
mesh.paint_uniform_color([1, 0, 0])

# 初始化Visualizer并添加模型
vis = o3d.visualization.Visualizer()
vis.create_window()
vis.add_geometry(mesh)

# 调整视角
ctr = vis.get_view_control()
ctr.change_field_of_view(step=-90)
vis.register_animation_callback(capture_img)

# 获取当前Visualizer的渲染器和场景实例
renderer = vis.get_renderer()
scene = renderer.get_scene()

# 构造符合要求的列向量(形状(3,1))
color = np.array([[1.], [1.], [0.]], dtype=np.float32)
position = np.array([[3.], [3.], [0.]], dtype=np.float32)

# 添加点光源
scene.add_point_light('light', color, position, 1e8, 1e2, True)

vis.run()
vis.destroy_window()

关键修改说明

  • 获取正确场景实例:通过vis.get_renderer().get_scene()获取当前Visualizer窗口正在使用的场景,而非直接操作Scene类。
  • 调整数组形状:将color和position改为二维列向量(用[[1.], [1.], [0.]]构造,或对原数组调用reshape(3,1)),匹配函数要求的numpy.ndarray[numpy.float32[3, 1]]类型。
  • 移除无用导入:删除未使用的open3d.visualization.gui和rendering直接导入,简化代码。

关于GUI窗口的补充

如果想用gui模块创建窗口,核心逻辑一致:先创建Application实例,再创建窗口并获取SceneWidget的场景对象添加光源。示例片段:

app = gui.Application.instance
app.initialize()

window = app.create_window("STL Viewer", 1024, 768)
widget = gui.SceneWidget()
widget.scene = rendering.Scene(window.renderer)
widget.scene.add_geometry("mesh", mesh, rendering.MaterialRecord())

# 添加光源
color = np.array([[1.], [1.], [0.]], dtype=np.float32)
position = np.array([[3.], [3.], [0.]], dtype=np.float32)
widget.scene.add_point_light('light', color, position, 1e8, 1e2, True)

window.add_child(widget)
app.run()

内容的提问来源于stack exchange,提问作者Felix N

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 19:23:22