Files
ChArUcoBoardExp/calculate_box_face_coord_naive.ipynb

2222 lines
49 KiB
Plaintext

{
"cells": [
{
"cell_type": "code",
"execution_count": 55,
"metadata": {},
"outputs": [],
"source": [
"from dataclasses import dataclass\n",
"import numpy as np\n",
"from matplotlib import pyplot as plt\n",
"import plotly.graph_objects as go\n",
"\n",
"NDArray = np.ndarray"
]
},
{
"cell_type": "code",
"execution_count": 56,
"metadata": {},
"outputs": [],
"source": [
"# Order of detection result\n",
"# 0, 1, 2, 3\n",
"# TL, TR, BR, BL\n",
"# RED, GREEN, BLUE, YELLOW\n",
"\n",
"\n",
"@dataclass\n",
"class DiamondBoardParameter:\n",
" marker_leghth: float\n",
" \"\"\"\n",
" the ArUco marker length in meter\n",
" \"\"\"\n",
" chess_length: float\n",
" \"\"\"\n",
" the length of the chess board in meter\n",
" \"\"\"\n",
" border_length: float = 0.01\n",
" \"\"\"\n",
" border_length in m, default is 1cm\n",
" \"\"\"\n",
"\n",
" @property\n",
" def marker_border_length(self):\n",
" assert self.chess_length > self.marker_leghth\n",
" return (self.chess_length - self.marker_leghth) / 2\n",
"\n",
" @property\n",
" def total_side_length(self):\n",
" assert self.chess_length > self.marker_leghth\n",
" return self.marker_border_length * 2 + self.chess_length * 3\n",
"\n",
"\n",
"# 9mm + 127mm + 127mm (97mm marker) + 127mm + 10mm\n",
"# i.e. marker boarder = 127mm - 97mm = 30mm (15mm each side)\n",
"Point2D = tuple[float, float]\n",
"Quad2D = tuple[Point2D, Point2D, Point2D, Point2D]\n",
"\n",
"\n",
"class ArUcoMarker2D:\n",
" id: int\n",
" _corners: NDArray\n",
"\n",
" def __init__(self, id: int, corners: Quad2D):\n",
" self.id = id\n",
" tmp = np.array(corners, dtype=np.float32)\n",
" assert tmp.shape == (4, 2)\n",
" self._corners = tmp\n",
"\n",
" @property\n",
" def corners(self):\n",
" return self._corners\n",
" \n",
" @property\n",
" def center(self):\n",
" return np.mean(self.corners, axis=0)\n",
"\n",
"\n",
"class ArUcoMarker3D:\n",
" id: int\n",
" _corners: NDArray\n",
"\n",
" def __init__(self, id: int, corners: NDArray):\n",
" self.id = id\n",
" tmp = np.array(corners, dtype=np.float32)\n",
" assert tmp.shape == (4, 3)\n",
" self._corners = tmp\n",
"\n",
" @staticmethod\n",
" def from_2d(marker2d: ArUcoMarker2D, z: float = 0.0):\n",
" return ArUcoMarker3D(\n",
" marker2d.id, np.column_stack((marker2d.corners, np.full((4,), z)))\n",
" )\n",
"\n",
" @property\n",
" def corners(self):\n",
" return self._corners\n",
"\n",
" @property\n",
" def center(self):\n",
" return np.mean(self.corners, axis=0)\n",
"\n",
" def normal(self, length: float = 1):\n",
" \"\"\"\n",
" return (2, 3)\n",
" \"\"\"\n",
" x, y, _ = self.center\n",
" return np.array([(x, y, 0), (x, y, length)])\n",
"\n",
"\n",
"# let's let TL be the origin\n",
"def generate_diamond_corners(\n",
" ids: tuple[int, int, int, int], params: DiamondBoardParameter\n",
"):\n",
" \"\"\"\n",
" A diamond chess board, which could be count as a kind of ChArUco board\n",
"\n",
" C | 0 | C\n",
" ---------\n",
" 1 | C | 2\n",
" ---------\n",
" C | 3 | C\n",
"\n",
" where C is the chess box, and 0, 1, 2, 3 are the markers (whose ids are passed in order)\n",
"\n",
" Args:\n",
" ids: a tuple of 4 ids of the markers\n",
" params: DiamondBoardParameter\n",
" \"\"\"\n",
"\n",
" def tl_to_square(tl_x: float, tl_y: float, side_length: float) -> Quad2D:\n",
" return (\n",
" (tl_x, tl_y),\n",
" (tl_x + side_length, tl_y),\n",
" (tl_x + side_length, tl_y + side_length),\n",
" (tl_x, tl_y + side_length),\n",
" )\n",
"\n",
" tl_0_x = params.border_length + params.chess_length + params.marker_border_length\n",
" tl_0_y = params.border_length + params.marker_border_length\n",
"\n",
" tl_1_x = params.border_length + params.marker_border_length\n",
" tl_1_y = params.border_length + params.chess_length + params.marker_border_length\n",
"\n",
" tl_2_x = (\n",
" params.border_length + params.chess_length * 2 + params.marker_border_length\n",
" )\n",
" tl_2_y = tl_1_y\n",
"\n",
" tl_3_x = params.border_length + params.chess_length + params.marker_border_length\n",
" tl_3_y = (\n",
" params.border_length + params.chess_length * 2 + params.marker_border_length\n",
" )\n",
" return (\n",
" ArUcoMarker2D(\n",
" ids[0],\n",
" tl_to_square(tl_0_x, tl_0_y, params.marker_leghth),\n",
" ),\n",
" ArUcoMarker2D(\n",
" ids[1],\n",
" tl_to_square(tl_1_x, tl_1_y, params.marker_leghth),\n",
" ),\n",
" ArUcoMarker2D(\n",
" ids[2],\n",
" tl_to_square(tl_2_x, tl_2_y, params.marker_leghth),\n",
" ),\n",
" ArUcoMarker2D(\n",
" ids[3],\n",
" tl_to_square(tl_3_x, tl_3_y, params.marker_leghth),\n",
" ),\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": 57,
"metadata": {},
"outputs": [],
"source": [
"params = DiamondBoardParameter(0.097, 0.127)\n",
"markers = generate_diamond_corners((16, 17, 18, 19), params)"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.plotly.v1+json": {
"config": {
"plotlyServerURL": "https://plot.ly"
},
"data": [
{
"mode": "lines+markers",
"name": "Marker 16",
"type": "scatter",
"x": [
0.152,
0.249,
0.249,
0.152,
0.2005
],
"y": [
0.025,
0.025,
0.122,
0.122,
0.0735
]
},
{
"mode": "lines+markers",
"name": "Marker 17",
"type": "scatter",
"x": [
0.025,
0.122,
0.122,
0.025,
0.0735
],
"y": [
0.152,
0.152,
0.249,
0.249,
0.2005
]
},
{
"mode": "lines+markers",
"name": "Marker 18",
"type": "scatter",
"x": [
0.279,
0.376,
0.376,
0.279,
0.3275
],
"y": [
0.152,
0.152,
0.249,
0.249,
0.2005
]
},
{
"mode": "lines+markers",
"name": "Marker 19",
"type": "scatter",
"x": [
0.152,
0.249,
0.249,
0.152,
0.2005
],
"y": [
0.279,
0.279,
0.376,
0.376,
0.3275
]
}
],
"layout": {
"height": 600,
"template": {
"data": {
"bar": [
{
"error_x": {
"color": "#2a3f5f"
},
"error_y": {
"color": "#2a3f5f"
},
"marker": {
"line": {
"color": "#E5ECF6",
"width": 0.5
},
"pattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
}
},
"type": "bar"
}
],
"barpolar": [
{
"marker": {
"line": {
"color": "#E5ECF6",
"width": 0.5
},
"pattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
}
},
"type": "barpolar"
}
],
"carpet": [
{
"aaxis": {
"endlinecolor": "#2a3f5f",
"gridcolor": "white",
"linecolor": "white",
"minorgridcolor": "white",
"startlinecolor": "#2a3f5f"
},
"baxis": {
"endlinecolor": "#2a3f5f",
"gridcolor": "white",
"linecolor": "white",
"minorgridcolor": "white",
"startlinecolor": "#2a3f5f"
},
"type": "carpet"
}
],
"choropleth": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"type": "choropleth"
}
],
"contour": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "contour"
}
],
"contourcarpet": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"type": "contourcarpet"
}
],
"heatmap": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "heatmap"
}
],
"heatmapgl": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "heatmapgl"
}
],
"histogram": [
{
"marker": {
"pattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
}
},
"type": "histogram"
}
],
"histogram2d": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "histogram2d"
}
],
"histogram2dcontour": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "histogram2dcontour"
}
],
"mesh3d": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"type": "mesh3d"
}
],
"parcoords": [
{
"line": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "parcoords"
}
],
"pie": [
{
"automargin": true,
"type": "pie"
}
],
"scatter": [
{
"fillpattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
},
"type": "scatter"
}
],
"scatter3d": [
{
"line": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scatter3d"
}
],
"scattercarpet": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scattercarpet"
}
],
"scattergeo": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scattergeo"
}
],
"scattergl": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scattergl"
}
],
"scattermapbox": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scattermapbox"
}
],
"scatterpolar": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scatterpolar"
}
],
"scatterpolargl": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scatterpolargl"
}
],
"scatterternary": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scatterternary"
}
],
"surface": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "surface"
}
],
"table": [
{
"cells": {
"fill": {
"color": "#EBF0F8"
},
"line": {
"color": "white"
}
},
"header": {
"fill": {
"color": "#C8D4E3"
},
"line": {
"color": "white"
}
},
"type": "table"
}
]
},
"layout": {
"annotationdefaults": {
"arrowcolor": "#2a3f5f",
"arrowhead": 0,
"arrowwidth": 1
},
"autotypenumbers": "strict",
"coloraxis": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"colorscale": {
"diverging": [
[
0,
"#8e0152"
],
[
0.1,
"#c51b7d"
],
[
0.2,
"#de77ae"
],
[
0.3,
"#f1b6da"
],
[
0.4,
"#fde0ef"
],
[
0.5,
"#f7f7f7"
],
[
0.6,
"#e6f5d0"
],
[
0.7,
"#b8e186"
],
[
0.8,
"#7fbc41"
],
[
0.9,
"#4d9221"
],
[
1,
"#276419"
]
],
"sequential": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"sequentialminus": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
]
},
"colorway": [
"#636efa",
"#EF553B",
"#00cc96",
"#ab63fa",
"#FFA15A",
"#19d3f3",
"#FF6692",
"#B6E880",
"#FF97FF",
"#FECB52"
],
"font": {
"color": "#2a3f5f"
},
"geo": {
"bgcolor": "white",
"lakecolor": "white",
"landcolor": "#E5ECF6",
"showlakes": true,
"showland": true,
"subunitcolor": "white"
},
"hoverlabel": {
"align": "left"
},
"hovermode": "closest",
"mapbox": {
"style": "light"
},
"paper_bgcolor": "white",
"plot_bgcolor": "#E5ECF6",
"polar": {
"angularaxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
},
"bgcolor": "#E5ECF6",
"radialaxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
}
},
"scene": {
"xaxis": {
"backgroundcolor": "#E5ECF6",
"gridcolor": "white",
"gridwidth": 2,
"linecolor": "white",
"showbackground": true,
"ticks": "",
"zerolinecolor": "white"
},
"yaxis": {
"backgroundcolor": "#E5ECF6",
"gridcolor": "white",
"gridwidth": 2,
"linecolor": "white",
"showbackground": true,
"ticks": "",
"zerolinecolor": "white"
},
"zaxis": {
"backgroundcolor": "#E5ECF6",
"gridcolor": "white",
"gridwidth": 2,
"linecolor": "white",
"showbackground": true,
"ticks": "",
"zerolinecolor": "white"
}
},
"shapedefaults": {
"line": {
"color": "#2a3f5f"
}
},
"ternary": {
"aaxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
},
"baxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
},
"bgcolor": "#E5ECF6",
"caxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
}
},
"title": {
"x": 0.05
},
"xaxis": {
"automargin": true,
"gridcolor": "white",
"linecolor": "white",
"ticks": "",
"title": {
"standoff": 15
},
"zerolinecolor": "white",
"zerolinewidth": 2
},
"yaxis": {
"automargin": true,
"gridcolor": "white",
"linecolor": "white",
"ticks": "",
"title": {
"standoff": 15
},
"zerolinecolor": "white",
"zerolinewidth": 2
}
}
},
"width": 600,
"yaxis": {
"autorange": "reversed"
}
}
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig = go.Figure()\n",
"for marker in markers:\n",
" corners = marker.corners\n",
" center = marker.center\n",
" corners = np.append(corners, [center], axis=0)\n",
" fig.add_trace(go.Scatter(x=corners[:, 0], y=corners[:, 1], mode='lines+markers', name=f\"Marker {marker.id}\"))\n",
"\n",
"# set the aspect ratio as 1:1\n",
"fig.update_layout(\n",
" width=600,\n",
" height=600,\n",
")\n",
"fig.update_yaxes(autorange=\"reversed\")\n",
"fig.show()"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.plotly.v1+json": {
"config": {
"plotlyServerURL": "https://plot.ly"
},
"data": [
{
"line": {
"width": 2
},
"marker": {
"size": 2
},
"mode": "lines+markers+text",
"name": "Marker 16",
"text": "16",
"textposition": "top center",
"type": "scatter3d",
"x": [
0.152,
0.249,
0.249,
0.152
],
"y": [
0.025,
0.025,
0.122,
0.122
],
"z": [
0,
0,
0,
0
]
},
{
"line": {
"width": 2
},
"mode": "lines",
"name": "Normal 16",
"type": "scatter3d",
"x": [
0.2004999965429306,
0.2004999965429306
],
"y": [
0.07349999994039536,
0.07349999994039536
],
"z": [
0,
0.1
]
},
{
"line": {
"width": 2
},
"marker": {
"size": 2
},
"mode": "lines+markers+text",
"name": "Marker 17",
"text": "17",
"textposition": "top center",
"type": "scatter3d",
"x": [
0.025,
0.122,
0.122,
0.025
],
"y": [
0.152,
0.152,
0.249,
0.249
],
"z": [
0,
0,
0,
0
]
},
{
"line": {
"width": 2
},
"mode": "lines",
"name": "Normal 17",
"type": "scatter3d",
"x": [
0.07349999994039536,
0.07349999994039536
],
"y": [
0.2004999965429306,
0.2004999965429306
],
"z": [
0,
0.1
]
},
{
"line": {
"width": 2
},
"marker": {
"size": 2
},
"mode": "lines+markers+text",
"name": "Marker 18",
"text": "18",
"textposition": "top center",
"type": "scatter3d",
"x": [
0.279,
0.376,
0.376,
0.279
],
"y": [
0.152,
0.152,
0.249,
0.249
],
"z": [
0,
0,
0,
0
]
},
{
"line": {
"width": 2
},
"mode": "lines",
"name": "Normal 18",
"type": "scatter3d",
"x": [
0.32749998569488525,
0.32749998569488525
],
"y": [
0.2004999965429306,
0.2004999965429306
],
"z": [
0,
0.1
]
},
{
"line": {
"width": 2
},
"marker": {
"size": 2
},
"mode": "lines+markers+text",
"name": "Marker 19",
"text": "19",
"textposition": "top center",
"type": "scatter3d",
"x": [
0.152,
0.249,
0.249,
0.152
],
"y": [
0.279,
0.279,
0.376,
0.376
],
"z": [
0,
0,
0,
0
]
},
{
"line": {
"width": 2
},
"mode": "lines",
"name": "Normal 19",
"type": "scatter3d",
"x": [
0.2004999965429306,
0.2004999965429306
],
"y": [
0.32749998569488525,
0.32749998569488525
],
"z": [
0,
0.1
]
}
],
"layout": {
"scene": {
"yaxis": {
"autorange": "reversed"
}
},
"template": {
"data": {
"bar": [
{
"error_x": {
"color": "#2a3f5f"
},
"error_y": {
"color": "#2a3f5f"
},
"marker": {
"line": {
"color": "#E5ECF6",
"width": 0.5
},
"pattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
}
},
"type": "bar"
}
],
"barpolar": [
{
"marker": {
"line": {
"color": "#E5ECF6",
"width": 0.5
},
"pattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
}
},
"type": "barpolar"
}
],
"carpet": [
{
"aaxis": {
"endlinecolor": "#2a3f5f",
"gridcolor": "white",
"linecolor": "white",
"minorgridcolor": "white",
"startlinecolor": "#2a3f5f"
},
"baxis": {
"endlinecolor": "#2a3f5f",
"gridcolor": "white",
"linecolor": "white",
"minorgridcolor": "white",
"startlinecolor": "#2a3f5f"
},
"type": "carpet"
}
],
"choropleth": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"type": "choropleth"
}
],
"contour": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "contour"
}
],
"contourcarpet": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"type": "contourcarpet"
}
],
"heatmap": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "heatmap"
}
],
"heatmapgl": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "heatmapgl"
}
],
"histogram": [
{
"marker": {
"pattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
}
},
"type": "histogram"
}
],
"histogram2d": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "histogram2d"
}
],
"histogram2dcontour": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "histogram2dcontour"
}
],
"mesh3d": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"type": "mesh3d"
}
],
"parcoords": [
{
"line": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "parcoords"
}
],
"pie": [
{
"automargin": true,
"type": "pie"
}
],
"scatter": [
{
"fillpattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
},
"type": "scatter"
}
],
"scatter3d": [
{
"line": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scatter3d"
}
],
"scattercarpet": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scattercarpet"
}
],
"scattergeo": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scattergeo"
}
],
"scattergl": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scattergl"
}
],
"scattermapbox": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scattermapbox"
}
],
"scatterpolar": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scatterpolar"
}
],
"scatterpolargl": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scatterpolargl"
}
],
"scatterternary": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scatterternary"
}
],
"surface": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "surface"
}
],
"table": [
{
"cells": {
"fill": {
"color": "#EBF0F8"
},
"line": {
"color": "white"
}
},
"header": {
"fill": {
"color": "#C8D4E3"
},
"line": {
"color": "white"
}
},
"type": "table"
}
]
},
"layout": {
"annotationdefaults": {
"arrowcolor": "#2a3f5f",
"arrowhead": 0,
"arrowwidth": 1
},
"autotypenumbers": "strict",
"coloraxis": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"colorscale": {
"diverging": [
[
0,
"#8e0152"
],
[
0.1,
"#c51b7d"
],
[
0.2,
"#de77ae"
],
[
0.3,
"#f1b6da"
],
[
0.4,
"#fde0ef"
],
[
0.5,
"#f7f7f7"
],
[
0.6,
"#e6f5d0"
],
[
0.7,
"#b8e186"
],
[
0.8,
"#7fbc41"
],
[
0.9,
"#4d9221"
],
[
1,
"#276419"
]
],
"sequential": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"sequentialminus": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
]
},
"colorway": [
"#636efa",
"#EF553B",
"#00cc96",
"#ab63fa",
"#FFA15A",
"#19d3f3",
"#FF6692",
"#B6E880",
"#FF97FF",
"#FECB52"
],
"font": {
"color": "#2a3f5f"
},
"geo": {
"bgcolor": "white",
"lakecolor": "white",
"landcolor": "#E5ECF6",
"showlakes": true,
"showland": true,
"subunitcolor": "white"
},
"hoverlabel": {
"align": "left"
},
"hovermode": "closest",
"mapbox": {
"style": "light"
},
"paper_bgcolor": "white",
"plot_bgcolor": "#E5ECF6",
"polar": {
"angularaxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
},
"bgcolor": "#E5ECF6",
"radialaxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
}
},
"scene": {
"xaxis": {
"backgroundcolor": "#E5ECF6",
"gridcolor": "white",
"gridwidth": 2,
"linecolor": "white",
"showbackground": true,
"ticks": "",
"zerolinecolor": "white"
},
"yaxis": {
"backgroundcolor": "#E5ECF6",
"gridcolor": "white",
"gridwidth": 2,
"linecolor": "white",
"showbackground": true,
"ticks": "",
"zerolinecolor": "white"
},
"zaxis": {
"backgroundcolor": "#E5ECF6",
"gridcolor": "white",
"gridwidth": 2,
"linecolor": "white",
"showbackground": true,
"ticks": "",
"zerolinecolor": "white"
}
},
"shapedefaults": {
"line": {
"color": "#2a3f5f"
}
},
"ternary": {
"aaxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
},
"baxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
},
"bgcolor": "#E5ECF6",
"caxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
}
},
"title": {
"x": 0.05
},
"xaxis": {
"automargin": true,
"gridcolor": "white",
"linecolor": "white",
"ticks": "",
"title": {
"standoff": 15
},
"zerolinecolor": "white",
"zerolinewidth": 2
},
"yaxis": {
"automargin": true,
"gridcolor": "white",
"linecolor": "white",
"ticks": "",
"title": {
"standoff": 15
},
"zerolinecolor": "white",
"zerolinewidth": 2
}
}
}
}
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"markers_3d = [ArUcoMarker3D.from_2d(m) for m in markers]\n",
"fig = go.Figure()\n",
"for m in markers_3d:\n",
" fig.add_trace(\n",
" go.Scatter3d(\n",
" x=m.corners[:, 0],\n",
" y=m.corners[:, 1],\n",
" z=m.corners[:, 2],\n",
" mode=\"lines+markers+text\",\n",
" marker=dict(size=2),\n",
" line=dict(width=2),\n",
" textposition=\"top center\",\n",
" text=m.id,\n",
" name=f\"Marker {m.id}\",\n",
" )\n",
" )\n",
" n = m.normal(0.1)\n",
" fig.add_trace(\n",
" go.Scatter3d(\n",
" x=n[:, 0],\n",
" y=n[:, 1],\n",
" z=n[:, 2],\n",
" mode=\"lines\",\n",
" line=dict(width=2),\n",
" name=f\"Normal {m.id}\",\n",
" )\n",
" )\n",
"# note that the Y axis is reversed\n",
"fig.update_layout(scene=dict(yaxis_autorange=\"reversed\"))\n",
"fig.show()"
]
}
],
"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.8"
}
},
"nbformat": 4,
"nbformat_minor": 2
}