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:
131
draw_uv.ipynb
Normal file
131
draw_uv.ipynb
Normal file
@ -0,0 +1,131 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 38,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from PIL import Image, ImageOps\n",
|
||||
"from pathlib import Path\n",
|
||||
"from typing import Optional\n",
|
||||
"from matplotlib import pyplot as plt\n",
|
||||
"import logging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"TILE_SIZE = 1650 # in pixels\n",
|
||||
"BORDER_SIZE = 200 # in pixels\n",
|
||||
"BORDER_COLOR = (255, 255, 255)\n",
|
||||
"BACKGROUND_COLOR = (255, 255, 255)\n",
|
||||
"IMAGE_DIR = Path(\"board\")\n",
|
||||
"\n",
|
||||
"# Define the layout grid (rows of indices, None for empty)\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",
|
||||
"\n",
|
||||
"\n",
|
||||
"# charuco_410x410_3x3_s133_m105_face3_no_12_DICT_7X7_1000\n",
|
||||
"# xxxxxxx_<phy_size>_<grid_size>_<checker_size>_<marker_space>_face<face_idx>_no_<no_idx>_DICT_<dict_size>\n",
|
||||
"# 0 1 2 3 4 5 6 7 8\n",
|
||||
"def parse_filename_to_face_idx(filename: str):\n",
|
||||
" parts = filename.split(\"_\")\n",
|
||||
" return int(parts[5][len(\"face\") :])\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"image_pathes = list(IMAGE_DIR.glob(\"*.png\"))\n",
|
||||
"image_indice = map(lambda p: parse_filename_to_face_idx(p.stem), image_pathes)\n",
|
||||
"images = {k: v for k, v in zip(image_indice, image_pathes)}\n",
|
||||
"display(images)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Create blank canvas\n",
|
||||
"rows = len(layout)\n",
|
||||
"cols = len(layout[0])\n",
|
||||
"canvas = Image.new(\"RGB\", (cols * TILE_SIZE, rows * TILE_SIZE), BACKGROUND_COLOR)\n",
|
||||
"\n",
|
||||
"# Paste tiles\n",
|
||||
"for y, row in enumerate(layout):\n",
|
||||
" for x, idx in enumerate(row):\n",
|
||||
" if idx is not None:\n",
|
||||
" path = images.get(idx)\n",
|
||||
" if path is not None:\n",
|
||||
" tile = Image.open(path)\n",
|
||||
" # for the face index 4, rotate the tile 180 degrees\n",
|
||||
" if idx == 4:\n",
|
||||
" tile = tile.rotate(180)\n",
|
||||
" canvas.paste(tile, (x * TILE_SIZE, y * TILE_SIZE))\n",
|
||||
" else:\n",
|
||||
" logging.warning(f\"Missing: {idx}\")\n",
|
||||
"\n",
|
||||
"# Calculate canvas size (before border)\n",
|
||||
"canvas_width = cols * TILE_SIZE\n",
|
||||
"canvas_height = rows * TILE_SIZE\n",
|
||||
"\n",
|
||||
"# Determine target size to make it square after padding\n",
|
||||
"target_size = max(canvas_width, canvas_height)\n",
|
||||
"extra_padding = target_size - canvas_height\n",
|
||||
"top_pad = extra_padding // 2\n",
|
||||
"bottom_pad = extra_padding - top_pad\n",
|
||||
"\n",
|
||||
"# First add vertical padding to center the layout\n",
|
||||
"canvas_with_border = ImageOps.expand(\n",
|
||||
" canvas,\n",
|
||||
" border=(0, top_pad, 0, bottom_pad), # (left, top, right, bottom)\n",
|
||||
" fill=BACKGROUND_COLOR,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"plt.imshow(canvas_with_border)\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 41,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"canvas_with_border.save(\"merged_uv_layout.png\")"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.12.10"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
Reference in New Issue
Block a user