From bd4f5c0f1e1c8f397f8fef190c72d02abad6fa0a Mon Sep 17 00:00:00 2001 From: Jarno Ralli Date: Sat, 8 Nov 2025 12:57:50 +0200 Subject: [PATCH] Added link to the pinhole model documentation --- documentation/README.md | 6 +- .../visualize_coordinate_systems.ipynb | 151 ++++++++++++++++++ 2 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 documentation/visualize_coordinate_systems.ipynb diff --git a/documentation/README.md b/documentation/README.md index e544744..c876c18 100644 --- a/documentation/README.md +++ b/documentation/README.md @@ -1,13 +1,13 @@ # 1 Documentation -This folder contains documentation and other examples. +This folder contains documentation, Jupyter notebooks and other examples. ## 1.1 Contents * [pinhole_projection.ipynb](./pinhole_projection.ipynb) - * This Jupyter notebook describes the pinhole camera model, and the relationship between H-FOV and focal length. + * This Jupyter notebook describes the pinhole camera model, and the relationship between H-FOV and the focal length. * [fisheye_camera_models.ipynb](./fisheye_camera_models.ipynb) * This Jupyter notebook describes typical fisheye camera models. * [camera_pose_to_homography.ipynb](./camera_pose_to_homography.ipynb) - * This Jupyter notebook describes homography between a plane defined in a world coordinate frame and the camera. + * This Jupyter notebook describes homography between a plane defined in a world coordinate frame and a camera. diff --git a/documentation/visualize_coordinate_systems.ipynb b/documentation/visualize_coordinate_systems.ipynb new file mode 100644 index 0000000..c784891 --- /dev/null +++ b/documentation/visualize_coordinate_systems.ipynb @@ -0,0 +1,151 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "335fd6f0", + "metadata": {}, + "source": [ + "# Visualize Coordinate Systems" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e3c6c2d4", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import matplotlib.axes" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c3d1c6a5", + "metadata": {}, + "outputs": [], + "source": [ + "def draw_coordinate_frame(\n", + " ax: matplotlib.axes.Axes,\n", + " origin: np.ndarray,\n", + " R: np.ndarray,\n", + " label: str = '',\n", + " length: float = 1.0,\n", + " alpha: float = 1.0\n", + ") -> None:\n", + " \"\"\"\n", + " Draws a 3D coordinate frame with labeled X, Y, and Z axes.\n", + "\n", + " Parameters\n", + " ----------\n", + " ax : matplotlib.axes.Axes\n", + " A matplotlib 3D axes object where the frame will be drawn.\n", + " origin : np.ndarray\n", + " A (3,) array representing the origin of the coordinate frame.\n", + " R : np.ndarray\n", + " A (3, 3) rotation matrix where each column is a unit vector for\n", + " the X, Y, and Z axes respectively.\n", + " label : str, optional\n", + " A prefix for axis labels (e.g., 'cam' -> 'cam_x', 'cam_y', etc.), by default ''.\n", + " length : float, optional\n", + " Length of the axis vectors to be drawn, by default 1.0.\n", + " alpha : float, optional\n", + " Transparency level for the axis vectors (0.0–1.0), by default 1.0.\n", + "\n", + " Returns\n", + " -------\n", + " None\n", + " \"\"\"\n", + " colors = ['r', 'g', 'b']\n", + " directions = ['x', 'y', 'z']\n", + " for i in range(3):\n", + " vector = R[:, i] * length\n", + " ax.quiver(*origin, *vector, color=colors[i], alpha=alpha)\n", + " ax.text(*(origin + vector), f'{label}_{directions[i]}', color=colors[i])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9d746011", + "metadata": {}, + "outputs": [], + "source": [ + "#%matplotlib notebook\n", + "%matplotlib widget" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4642a69c", + "metadata": {}, + "outputs": [], + "source": [ + "# Camera coordinate frame (right-handed, Y down and increasing)\n", + "R_camera = np.array([\n", + " [1, 0, 0],\n", + " [0, 1, 0],\n", + " [0, 0, 1]\n", + "])\n", + "origin_camera = np.array([0, 0, 0])\n", + "\n", + "# Flip yz\n", + "Tyz = np.array([\n", + " [1, 0, 0, 1],\n", + " [0, -1, 0, 0],\n", + " [0, 0, -1, 0],\n", + " [0, 0, 0, 1]\n", + "])\n", + "\n", + "T = Tyz @ np.eye(4) @ Tyz\n", + "\n", + "# Apply transformation to camera frame\n", + "R_transformed = T[:3, :3] @ R_camera\n", + "origin_transformed = T[:3, 3]\n", + "\n", + "# Plot\n", + "fig = plt.figure(figsize=(8, 6))\n", + "ax = fig.add_subplot(111, projection='3d')\n", + "\n", + "draw_coordinate_frame(ax, origin_camera, R_camera, label='cam', alpha=1.0)\n", + "draw_coordinate_frame(ax, origin_transformed, R_transformed, label='T(cam)', alpha=0.9)\n", + "\n", + "# View and bounds\n", + "ax.set_xlim([-1, 4])\n", + "ax.set_ylim([-1, 4])\n", + "ax.set_zlim([-1, 4])\n", + "ax.set_xlabel('X')\n", + "ax.set_ylabel('Y')\n", + "ax.set_zlabel('Z')\n", + "\n", + "ax.set_title('Camera Frame and Transformed Frame')\n", + "plt.show()\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "3d-computer-vision", + "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.10.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}