Files
ChArUcoBoardExp/draw_uv.ipynb

132 lines
3.9 KiB
Plaintext

{
"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
}