반응형
Open3D에서 주어진 mesh의 normal을 얻어내는 방법은 쉽다. Document에서도 이 기능만 설명한다.
import open3d as o3d
mesh = o3d.io.read_triangle_mesh(MESH_PATH)
mesh.compute_vertex_normals() # vertex normals are filled in
mesh.compute_triangle_normals() # face normals are filled in
그런데 normal map 즉 2D 형태로 얻는 방법은 명확히 없다. normal rendering을 하는 방법이 뚜렷하지 않다.
vis = o3d.visualization.Visualizer()
vis.create_window(visible=True)
opt = vis.get_render_option()
opt.mesh_color_option = o3d.visualization.MeshColorOption.Normal # core
위와 같이 visualizer의 색상 옵션을 normal로 변경하면 normal 이미지를 만들어 주긴 하지만 RGB값이 normal vector (nx, ny, nz)와 어떻게 대응되는지 알 수 없어서 값을 변환해서 쓸 수 없다.
nx = 2*R-1 # R 0-1
ny = 2*G-1 # G 0-1
nz = 2*B-1 # B 0-1
보통 위와 같이 변환하는데, 그대로 해보면 normal vector가 mesh face에 수직한 방향이 아니라 나란한 방향으로 나온다. (축이 어딘가 다르다는 뜻. RGB가 Combination(XYZ) 중 어떤 조합으로 계산되는지는 모른다.) 게다가 크기도 1로 normalized되어 있는 값이 아니어서 RGB만 보고 normal vector를 계산할 수 없다.
우회법
어떻게 normal map을 렌더링하느냐? 방법은 생각보다 간단하다. RGB 렌더링 모드를 그대로 사용하는데 vertex color 부분에 vertex normals을 채워넣는 방법이다.
mesh = o3d.io.read_triangle_mesh(MESH_PATH)
mesh.compute_vertex_normals()
vertex_normals = np.asarray(mesh.vertex_normals) * 0.5 + 0.5
mesh.vertex_colors = o3d.utility.Vector3dVector(vertex_normals)
#with
opt.mesh_color_option = o3d.visualization.MeshColorOption.Color
-1~1 범위의 normal 값들을 0~1 범위의 RGB 크기에 맞춰 scale+trans 해준 뒤, vertex_colors에 채워넣고 그대로 렌더링하면 된다.
렌더링 하는 방법은 이전 글 참고.
반응형
'Knowhow > Vision' 카테고리의 다른 글
SMPLX uv mapping/coordinate 사용 시 유의점 (0) | 2024.11.22 |
---|---|
BFM 모델 vertex index / uv unwrap coordinates (0) | 2024.11.19 |
Opencv camera index 찾기, device index 찾기 (0) | 2024.10.29 |
Facescape 모델 68 keypoint/landmark index (0) | 2024.08.28 |
obj 파일 v, vt, f 등 직접 저장하기, obj save (0) | 2024.08.28 |