open3d로 mesh를 읽으면 가끔 vertex 개수가 잘못되어 있거나, face를 구성하는 vertex index가 다른 것을 볼 수 있다. 보통 후자는 앞의 vertex 개수가 바뀌면서 꼬인 것으로 연쇄적인 현상이다.
이유를 찾아보니 정말 버그였는데, read_triangle_mesh를 사용할 때 내부적으로 enable_post_processing=False가 동작을 안하도록 하드 코딩되어 있어서 파일을 자체적으로 한 번 수정하기 때문이었다.
(enable_post_processing=True로 하면 또 다르게 바뀌는 걸로 봐서 단순히 True/False 전환 문제라기 보다 어딘가에 하드코딩된게 있나보다. open3d를 직접 고칠 수는 없으니 기다리는 수 밖에)
https://github.com/isl-org/Open3D/issues/6137
따라서 해결법은 크게 없다. 꽤 오래 전부터 나왔던 이슈인데 아직도 해결되지 않은 것을 보면 무시되고 있거나 우선순위가 낮은 버그인 것 같다.
예시
Meshlab에서 42899개 vertex를 갖고 있는 mesh가 있는데 이를 open3d에서 읽으면 다음과 같이 읽힌다.
어디선가 1000개나 되는 vertex가 생겼고 덕분에 index가 다 꼬였다.
우회법
mesh를 읽을 때 trimesh로 읽고 open3d에 이식하는 방법 뿐이다. open3d 자체적으로 해결할 수 있는 방법은 아직 없다.
위 이슈에서 퍼온 코드인데, 아래와 같이 trimesh to open3d 함수를 써야 한다.
def read_triangle_mesh(avatar_name,enable_post_processing=False):
# EDIT: next 4 lines replace to maintain order even in case of degenerate and non referenced
# scene_patch = trimesh.load(avatar_name,process=enable_post_processing)
if enable_post_processing:
scene_patch = trimesh.load(avatar_name,process=True)
else:
scene_patch = trimesh.load(avatar_name,process=False,maintain_order=True)
mesh = o3d.geometry.TriangleMesh(
o3d.utility.Vector3dVector(scene_patch.vertices),
o3d.utility.Vector3iVector(scene_patch.faces)
)
if scene_patch.vertex_normals.size:
mesh.vertex_normals = o3d.utility.Vector3dVector(scene_patch.vertex_normals.copy())
if scene_patch.visual.defined:
# either texture or vertex colors if no uvs present.
if scene_patch.visual.kind == 'vertex':
mesh.vertex_colors = o3d.utility.Vector3dVector(scene_patch.visual.vertex_colors[:,:3]/255) # no alpha channel support
elif scene_patch.visual.kind == 'texture':
uv = scene_patch.visual.uv
if uv.shape[0] == scene_patch.vertices.shape[0]:
mesh.triangle_uvs = o3d.utility.Vector2dVector(uv[scene_patch.faces.flatten()])
elif uv.shape[0] != scene_patch.faces.shape[0] * 3:
assert False
else:
mesh.triangle_uvs = o3d.utility.Vector2dVector(uv)
if scene_patch.visual.material is not None and scene_patch.visual.material.image is not None:
if scene_patch.visual.material.image.mode == 'RGB':
mesh.textures = [o3d.geometry.Image(np.asarray(scene_patch.visual.material.image))]
else:
assert False
else:
assert False
return mesh
이렇게 읽으면 원래대로 vertex, face 그대로 읽힌다.
그냥 visualization용으로나 간단한 rendering용도로나 open3d 쓰고 vertex, face 갖고 뭔가 작업할 때는 trimesh나 pytorch3d 쓰는게 나을 것 같다.
'Trouble > Vision' 카테고리의 다른 글
pymeshlab decimation 안되는 버그 (0) | 2024.09.11 |
---|---|
Trimesh load_mesh, export 시 texture 제대로 안 읽히고 저장 안될 때 (0) | 2024.09.02 |
Open3D OBJ texture 안 보일 때, enable_post_processing=True로 해결 안 될 때, texture가 검정색으로 뜰 때 확인 사항 (0) | 2024.07.09 |
Opencv cornerSubPix empty array 문제 (0) | 2024.02.27 |
Python OpenCV solvePnP 이유 모를 type error (0) | 2024.02.22 |