Files
ChArUcoBoardExp/draw_uv.ipynb
T

191 lines
41 KiB
Plaintext

{
"cells": [
{
"cell_type": "code",
"execution_count": 23,
"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": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{1: PosixPath('board/aruco_600x600/aruco_board_600x600_border75_m450_face1_id22_DICT_APRILTAG_36h11.png'),\n",
" 4: PosixPath('board/aruco_600x600/aruco_board_600x600_border75_m450_face4_id25_DICT_APRILTAG_36h11.png'),\n",
" 3: PosixPath('board/aruco_600x600/aruco_board_600x600_border75_m450_face3_id24_DICT_APRILTAG_36h11.png'),\n",
" 2: PosixPath('board/aruco_600x600/aruco_board_600x600_border75_m450_face2_id23_DICT_APRILTAG_36h11.png'),\n",
" 5: PosixPath('board/aruco_600x600/aruco_board_600x600_border75_m450_face5_id26_DICT_APRILTAG_36h11.png'),\n",
" 0: PosixPath('board/aruco_600x600/aruco_board_600x600_border75_m450_face0_id21_DICT_APRILTAG_36h11.png')}"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"TILE_SIZE = 1650 # in pixels\n",
"# NOTE: TILE_SIZE \n",
"BORDER_SIZE = 200 # in pixels\n",
"BORDER_COLOR = (255, 255, 255)\n",
"BACKGROUND_COLOR = (255, 255, 255)\n",
"IMAGE_DIR = Path(\"board/aruco_600x600\")\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, 4, 2, 5, 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": 25,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x124178550>"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAbIAAAGiCAYAAACCpUOHAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAMXtJREFUeJzt3Xt0lNW9//HPhJBJuEwu0MwQTSJay6UCKmiMItWSRYJUUTmngqlSmwOtBlvFQzHnCCq1DUKPohahdnkQT0WtaxVaOUgbwyVaYsBgQC5N0YOEopO0xEwIl9xm//7oyvNzJCCpE2Z2eL/W2msxz/7OzHfnCfNhZjYzLmOMEQAAloqJdAMAAHwZBBkAwGoEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqUR1kS5cu1QUXXKD4+HhlZWVp69atkW4JABBlojbIXn31Vc2ePVsPP/ywtm/frlGjRik3N1d1dXWRbg0AEEVc0fqhwVlZWbriiiv0i1/8QpIUDAaVnp6ue++9Vw8++GCEuwMARIvYSDfQmZaWFlVWVqqoqMg5FhMTo5ycHJWXl3d6nebmZjU3NzuXg8Gg6uvrNWDAALlcrm7vGQAQXsYYHTlyRGlpaYqJOfULiFEZZH//+9/V3t4ur9cbctzr9erPf/5zp9cpLi7Wo48+ejbaAwCcRQcPHtT5559/yvmoDLJ/RlFRkWbPnu1cDgQCysjI0MGDB+XxeCLYGQDgn9HY2Kj09HT179//tHVRGWQDBw5Ur169VFtbG3K8trZWPp+v0+u43W653e6Tjns8HoIMACz2RW8PReWuxbi4OI0ePVqlpaXOsWAwqNLSUmVnZ0ewMwBAtInKZ2SSNHv2bE2fPl1jxozRlVdeqSVLlujo0aO66667It0aACCKRG2Q3Xbbbfrb3/6m+fPny+/369JLL9X69etP2gACADi3Re3/I/uyGhsblZiYqEAgwHtkAGChM30cj8r3yAAAOFMEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqBBkAwGphD7Li4mJdccUV6t+/v1JTU3XzzTeruro6pObEiRMqLCzUgAED1K9fP02ZMkW1tbUhNTU1NZo0aZL69Omj1NRUzZkzR21tbeFuFwBgubAH2ebNm1VYWKh33nlHJSUlam1t1YQJE3T06FGn5v7779frr7+u1157TZs3b9bHH3+sW2+91Zlvb2/XpEmT1NLSoi1btmjlypV64YUXNH/+/HC3CwCwnelmdXV1RpLZvHmzMcaYhoYG07t3b/Paa685NXv37jWSTHl5uTHGmHXr1pmYmBjj9/udmmXLlhmPx2Oam5vP6H4DgYCRZAKBQBhXAwA4W870cTy2u4MyEAhIklJSUiRJlZWVam1tVU5OjlMzdOhQZWRkqLy8XFdddZXKy8s1YsQIeb1epyY3N1d33323du/ercsuu+yk+2lublZzc7NzubGxsbuW1K2MMWpvb5cxJtKtAOghXC6XevXqJZfLFelWukW3BlkwGNR9992na665Rpdccokkye/3Ky4uTklJSSG1Xq9Xfr/fqflsiHXMd8x1pri4WI8++miYV3D2tbe368EHH9SOHTsi3QqAHmLMmDF67LHH1KtXr0i30i26NcgKCwu1a9cuvf322915N5KkoqIizZ4927nc2Nio9PT0br/fcAsGg9q+fbs2btwY6VYA9BCxsbE9+lWebguyWbNmae3atSorK9P555/vHPf5fGppaVFDQ0PIs7La2lr5fD6nZuvWrSG317GrsaPm89xut9xud5hXAQCIdmHftWiM0axZs7R69Wpt2LBBgwcPDpkfPXq0evfurdLSUudYdXW1ampqlJ2dLUnKzs7W+++/r7q6OqempKREHo9Hw4cPD3fLAACLhf0ZWWFhoVatWqXf/e536t+/v/OeVmJiohISEpSYmKiCggLNnj1bKSkp8ng8uvfee5Wdna2rrrpKkjRhwgQNHz5cd9xxhxYtWiS/36+HHnpIhYWFPOsCAIQK93ZJSZ2OFStWODXHjx8399xzj0lOTjZ9+vQxt9xyi/nkk09Cbuejjz4yEydONAkJCWbgwIHmgQceMK2trWfch63b75ubm831119/yp8jg8FgdHXk5eV16fEzWkRs+705gzcU4+PjtXTpUi1duvSUNZmZmVq3bl04WwMA9EB81iIAwGoEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqBBkAwGoEGQDAagQZAMBqsZFuALCN1+tVnz59It2G2tvbdejQIbW3t0e6FfXt21epqamRbiOqBINBHTp0SG1tbZFupccjyIAuiImJ0RNPPKHc3NxItyK/369vfvObqquri3QrysvL0/Lly+VyuSLdStSor6/XN7/5Tf31r3+NdCs9HkEGdIHL5VL//v01YMCASLeiEydOKCYmOt4dcLvdSklJiZp+okEwGOTncZbwUwYAWI0gAwBYjSADAFiNIAMAWK3bg2zhwoVyuVy67777nGMnTpxQYWGhBgwYoH79+mnKlCmqra0NuV5NTY0mTZqkPn36KDU1VXPmzGEbKwDgJN0aZNu2bdMvf/lLjRw5MuT4/fffr9dff12vvfaaNm/erI8//li33nqrM9/e3q5JkyappaVFW7Zs0cqVK/XCCy9o/vz53dkuAMBC3RZkTU1Nys/P169+9SslJyc7xwOBgJ5//nk98cQT+uY3v6nRo0drxYoV2rJli9555x1J0h//+Eft2bNHv/71r3XppZdq4sSJ+slPfqKlS5eqpaWl0/trbm5WY2NjyAAA9HzdFmSFhYWaNGmScnJyQo5XVlaqtbU15PjQoUOVkZGh8vJySVJ5eblGjBghr9fr1OTm5qqxsVG7d+/u9P6Ki4uVmJjojPT09G5YFQAg2nRLkL3yyivavn27iouLT5rz+/2Ki4tTUlJSyHGv1yu/3+/UfDbEOuY75jpTVFSkQCDgjIMHD4ZhJQCAaBf2T/Y4ePCgfvSjH6mkpETx8fHhvvlTcrvdcrvdZ+3+AADRIezPyCorK1VXV6fLL79csbGxio2N1ebNm/X0008rNjZWXq9XLS0tamhoCLlebW2tfD6fJMnn8520i7HjckcNAABSNwTZ+PHj9f7776uqqsoZY8aMUX5+vvPn3r17q7S01LlOdXW1ampqlJ2dLUnKzs7W+++/H/JhqCUlJfJ4PBo+fHi4WwYAWCzsLy32799fl1xyScixvn37asCAAc7xgoICzZ49WykpKfJ4PLr33nuVnZ2tq666SpI0YcIEDR8+XHfccYcWLVokv9+vhx56SIWFhbx8CAAIEZFPv3/yyScVExOjKVOmqLm5Wbm5uXr22Wed+V69emnt2rW6++67lZ2drb59+2r69OlasGBBJNoFAESxsxJkmzZtCrkcHx+vpUuXaunSpae8TmZmptatW9fNnQEAbMdnLQIArEaQAQCsRpABAKxGkAEArEaQAQCsRpABAKxGkAEArEaQAQCsRpABAKxGkAEArEaQAQCsRpABAKxGkAEArEaQAQCsRpABAKxGkAEArEaQAQCsdla+IRp28ng8mjx5suLi4iLdiqqrq/X2229Hug0Fg0GVlpbq8OHDkW5FLS0tuuWWW9TS0hLpVpSamqqVK1fK5XJFuhVde+21uuiiiyLdBs4iggyn5PV69dRTTykpKSnSrej555+PiiAzxuipp56KdBuSpPT0dG3dulVerzfSrejVV19Vfn6+gsFgRPuIiYnRypUrCbJzDEGG03K5XFHxr2yczBgTVefHGBPpFqKiB5x9vEcGALAaQQYAsBpBBgCwGkEGALAaQQYAsBpBBgCwGkEGALAaQQYAsBpBBgCwGkEGALAaQQYAsBpBBgCwGkEGALBatwTZoUOH9J3vfEcDBgxQQkKCRowYoXfffdeZN8Zo/vz5GjRokBISEpSTk6N9+/aF3EZ9fb3y8/Pl8XiUlJSkgoICNTU1dUe7AACLhT3IPv30U11zzTXq3bu33njjDe3Zs0f/9V//peTkZKdm0aJFevrpp7V8+XJVVFSob9++ys3N1YkTJ5ya/Px87d69WyUlJVq7dq3Kyso0c+bMcLcLALBc2L+P7PHHH1d6erpWrFjhHBs8eLDzZ2OMlixZooceekiTJ0+WJL344ovyer1as2aNpk6dqr1792r9+vXatm2bxowZI0l65plndMMNN+jnP/+50tLSwt02AMBSYX9G9vvf/15jxozRv/7rvyo1NVWXXXaZfvWrXznz+/fvl9/vV05OjnMsMTFRWVlZKi8vlySVl5crKSnJCTFJysnJUUxMjCoqKjq93+bmZjU2NoYMAEDPF/Yg+7//+z8tW7ZMF198sf7whz/o7rvv1g9/+EOtXLlSkuT3+yXppK9n93q9zpzf71dqamrIfGxsrFJSUpyazysuLlZiYqIz0tPTw700AEAUCnuQBYNBXX755frZz36myy67TDNnztSMGTO0fPnycN9ViKKi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",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"tile = Image.open(images[0])\n",
"plt.imshow(tile)"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"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",
" ## note: not sure why did I did that\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": 27,
"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.13.12"
}
},
"nbformat": 4,
"nbformat_minor": 2
}