Add draw_uv.ipynb for UV layout generation, including image processing and canvas creation. Updated find_cute_box_with_image.ipynb with new functions for 3D coordinate extraction and improved type annotations.
This commit is contained in:
@ -2,7 +2,7 @@
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 33,
|
||||
"execution_count": 77,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -29,7 +29,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 34,
|
||||
"execution_count": 78,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -42,7 +42,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 35,
|
||||
"execution_count": 79,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -54,7 +54,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 36,
|
||||
"execution_count": 80,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -66,7 +66,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 37,
|
||||
"execution_count": 81,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -88,7 +88,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 38,
|
||||
"execution_count": 82,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -121,7 +121,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 83,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -192,7 +192,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 43,
|
||||
"execution_count": 86,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -286,7 +286,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 46,
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -295,9 +295,98 @@
|
||||
" uv_points = marker.corners\n",
|
||||
" return interpolate_uvs_to_3d_trimesh(uv_points, mesh)\n",
|
||||
"\n",
|
||||
"results = [marker_to_3d_coords(marker, m) for marker in output_markers]\n",
|
||||
"id_to_3d_coords = {marker.id: result for marker, result in zip(output_markers, results)}\n",
|
||||
"# note that the glb is Y up (but in blender it's Z up)"
|
||||
"id_to_3d_coords = {marker.id: marker_to_3d_coords(marker, m) for marker in output_markers}\n",
|
||||
"# note that the glb is Y up\n",
|
||||
"# when visualizing with matplotlib, it's Z up\n",
|
||||
"# GLTF → Blender: (X, Y, Z) → (X, -Z, Y)\n",
|
||||
"OPEN_GL_TO_BLENDER = np.array([[1, 0, 0], [0, 0, -1], [0, 1, 0]])\n",
|
||||
"# Blender → GLTF: (X, Y, Z) → (X, Z, -Y)\n",
|
||||
"BLENDER_TO_OPEN_GL = np.array([[1, 0, 0], [0, 0, 1], [0, -1, 0]])\n",
|
||||
"display(np.linalg.inv(OPEN_GL_TO_BLENDER)) # should be the same"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 93,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# matplotlib default colors scheme\n",
|
||||
"colors: list[str] = plt.rcParams[\"axes.prop_cycle\"].by_key()[\"color\"]\n",
|
||||
"\n",
|
||||
"def hex_to_rgb(hex_color: str) -> tuple[float, float, float]:\n",
|
||||
" assert hex_color.startswith(\"#\")\n",
|
||||
" assert len(hex_color) == 7\n",
|
||||
" return tuple(int(hex_color[i:i+2], 16) / 255.0 for i in (1, 3, 5)) # type: ignore"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from functools import lru_cache\n",
|
||||
"\n",
|
||||
"@dataclass\n",
|
||||
"class Face:\n",
|
||||
" color: tuple[float, float, float]\n",
|
||||
" marker_ids: list[int]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# fmt: off\n",
|
||||
"layout:list[list[Optional[int]]] = [\n",
|
||||
" [None, None, 0, None, None],\n",
|
||||
" [None, None, 1, None, None],\n",
|
||||
" [None, 5, 2, 4, None],\n",
|
||||
" [None, None, 3, None, None],\n",
|
||||
"]\n",
|
||||
"# fmt: on\n",
|
||||
"\n",
|
||||
"faces = {\n",
|
||||
" \"bottom\": Face(color=hex_to_rgb(colors[0]), marker_ids=[0, 1, 2, 3]),\n",
|
||||
" \"back\": Face(color=hex_to_rgb(colors[1]), marker_ids=[4, 5, 6, 7]),\n",
|
||||
" \"top\": Face(color=hex_to_rgb(colors[2]), marker_ids=[8, 9, 10, 11]),\n",
|
||||
" \"front\": Face(color=hex_to_rgb(colors[3]), marker_ids=[12, 13, 14, 15]),\n",
|
||||
" \"right\": Face(color=hex_to_rgb(colors[4]), marker_ids=[16, 17, 18, 19]),\n",
|
||||
" \"left\": Face(color=hex_to_rgb(colors[5]), marker_ids=[20, 21, 22, 23]),\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"@lru_cache\n",
|
||||
"def get_face_by_marker_id(marker_id: int) -> Optional[Face]:\n",
|
||||
" for face in faces.values():\n",
|
||||
" if marker_id in face.marker_ids:\n",
|
||||
" return face\n",
|
||||
" return None\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# 3D Visualization (with flipped and fully valid data)\n",
|
||||
"fig = plt.figure(figsize=(8, 8))\n",
|
||||
"ax = fig.add_subplot(111, projection=\"3d\")\n",
|
||||
"\n",
|
||||
"for tag_id, corners in id_to_3d_coords.items():\n",
|
||||
" corners = np.array(corners)\n",
|
||||
" face = get_face_by_marker_id(tag_id)\n",
|
||||
" assert face is not None\n",
|
||||
" color = face.color\n",
|
||||
" for i in range(4):\n",
|
||||
" p1 = corners[i]\n",
|
||||
" p2 = corners[(i + 1) % 4]\n",
|
||||
" ax.plot(*zip(p1, p2), color=color)\n",
|
||||
" center = corners.mean(axis=0)\n",
|
||||
" ax.scatter(*center, color=color)\n",
|
||||
" ax.text(*center, str(tag_id), fontsize=9, color=\"black\") # type: ignore\n",
|
||||
"\n",
|
||||
"ax.set_box_aspect([1, 1, 1]) # type: ignore\n",
|
||||
"ax.set_title(\"ArUco Corners in 3D\")\n",
|
||||
"ax.set_xlabel(\"X\")\n",
|
||||
"ax.set_ylabel(\"Y\")\n",
|
||||
"ax.set_zlabel(\"Z\") # type: ignore\n",
|
||||
"\n",
|
||||
"# Set the viewing angle\n",
|
||||
"# ax.view_init(elev=60, azim=35) # type: ignore\n",
|
||||
"\n",
|
||||
"plt.show()"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user