113 lines
4.1 KiB
Python
113 lines
4.1 KiB
Python
# demo_final_beautiful.py
|
||
# 最终美化版:无图例,专注焊缝模型本身的高质量渲染。
|
||
# 运行:python demo_final_beautiful.py
|
||
|
||
import numpy as np
|
||
import open3d as o3d
|
||
from typing import Dict
|
||
|
||
|
||
def get_final_ideal_ground_truth() -> Dict:
|
||
"""
|
||
使用你提供的最终版理想坐标。
|
||
"""
|
||
print("--- Using your final provided ideal coordinates. ---")
|
||
final_3_seams = {
|
||
'bottom_left': {
|
||
'start_3d': np.array([-142.2 + 8.9, 0.0, 0.0]),
|
||
'end_3d': np.array([-2.7, 0.0, 0.0])
|
||
},
|
||
'middle': {
|
||
'start_3d': np.array([0.0, 0.0, 0.0]),
|
||
'end_3d': np.array([0.0, -50.3, 0.0])
|
||
},
|
||
'top_left': {
|
||
'start_3d': np.array([0.0, 0.0, 5.2]),
|
||
'end_3d': np.array([0.0, 0.0, 142.5])
|
||
}
|
||
}
|
||
return final_3_seams
|
||
|
||
|
||
def rotation_matrix_from_vectors(vec_from: np.ndarray, vec_to: np.ndarray) -> np.ndarray:
|
||
"""计算从 vec_from 到 vec_to 的旋转矩阵。"""
|
||
a = vec_from / (np.linalg.norm(vec_from) + 1e-12)
|
||
b = vec_to / (np.linalg.norm(vec_to) + 1e-12)
|
||
v = np.cross(a, b)
|
||
c = np.clip(np.dot(a, b), -1.0, 1.0)
|
||
s = np.linalg.norm(v)
|
||
if s < 1e-12:
|
||
return np.eye(3) if c > 0.0 else -np.eye(3)
|
||
kmat = np.array([[0, -v[2], v[1]], [v[2], 0, -v[0]], [-v[1], v[0], 0]], dtype=float)
|
||
return np.eye(3) + kmat + kmat @ kmat * ((1.0 - c) / (s ** 2))
|
||
|
||
|
||
def visualize_beautiful_model(seams: Dict):
|
||
"""
|
||
【最终美化版】可视化:
|
||
- 使用PBR材质,增加金属质感。
|
||
- 增加灯光,增强立体感。
|
||
- 设置一个好的初始视角。
|
||
"""
|
||
print("\n--- Visualizing Final Target Model (High Quality Render) ---")
|
||
colors = {'bottom_left': [0.8, 0.1, 0.1], 'middle': [0.1, 0.8, 0.1], 'top_left': [0.1, 0.1, 0.8]}
|
||
geoms = []
|
||
|
||
# 1. 绘制焊缝主体 (圆柱体)
|
||
radius = 0.5 # 适中的粗细
|
||
for name, data in seams.items():
|
||
start, end = np.asarray(data['start_3d']), np.asarray(data['end_3d'])
|
||
direction = end - start
|
||
length = np.linalg.norm(direction)
|
||
if length < 1e-6: continue
|
||
|
||
cyl = o3d.geometry.TriangleMesh.create_cylinder(radius=radius, height=length, resolution=64)
|
||
cyl.compute_vertex_normals() # 法线对于光照计算至关重要
|
||
R = rotation_matrix_from_vectors(np.array([0.0, 0.0, 1.0]), direction)
|
||
cyl.rotate(R, center=(0, 0, 0)).translate((start + end) / 2.0)
|
||
cyl.paint_uniform_color(colors[name])
|
||
geoms.append(cyl)
|
||
|
||
# 2. 移动坐标轴到不遮挡的位置
|
||
all_points = [p for data in seams.values() for p in data.values()]
|
||
bbox = o3d.geometry.AxisAlignedBoundingBox.create_from_points(o3d.utility.Vector3dVector(all_points))
|
||
axis_size = max(30.0, np.linalg.norm(bbox.get_extent()) * 0.2)
|
||
axis_origin = bbox.get_min_bound() - np.array([axis_size * 1.5, axis_size * 0.5, 0])
|
||
frame = o3d.geometry.TriangleMesh.create_coordinate_frame(size=axis_size, origin=axis_origin)
|
||
geoms.append(frame)
|
||
|
||
# 3. 可视化
|
||
vis = o3d.visualization.Visualizer()
|
||
vis.create_window(window_name="Final Target Model (High Quality)", width=1280, height=720)
|
||
|
||
for g in geoms:
|
||
vis.add_geometry(g)
|
||
|
||
# --- 渲染和视角设置 ---
|
||
opt = vis.get_render_option()
|
||
opt.background_color = np.asarray([0.1, 0.1, 0.1]) # 深灰色背景,突出主体
|
||
opt.mesh_show_back_face = False
|
||
opt.light_on = True # 确保灯光已开启
|
||
|
||
# 获取视图控制器并设置相机位置
|
||
view_ctl = vis.get_view_control()
|
||
# 这个函数会自动计算一个能看全所有物体的合适视角
|
||
vis.reset_view_point(True)
|
||
# 你可以进一步手动调整相机参数以获得特定角度
|
||
# view_ctl.set_zoom(0.8)
|
||
# view_ctl.rotate(x=100, y=100) # 旋转视角
|
||
|
||
print("Visualization ready. You can rotate the view. Press 'Q' to close.")
|
||
vis.run()
|
||
vis.destroy_window()
|
||
|
||
|
||
if __name__ == '__main__':
|
||
seams = get_final_ideal_ground_truth()
|
||
|
||
print("--- Final Ideal Seam Coordinates ---")
|
||
for n, p in seams.items():
|
||
print(f"{n}: start={np.around(p['start_3d'], 1)}, end={np.around(p['end_3d'], 1)}")
|
||
|
||
visualize_beautiful_model(seams)
|