diff --git a/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/Lab-camera-calibration.pdf b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/Lab-camera-calibration.pdf new file mode 100644 index 00000000..feb3b7f1 Binary files /dev/null and b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/Lab-camera-calibration.pdf differ diff --git a/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/Rubiks.jpg b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/Rubiks.jpg new file mode 100644 index 00000000..212e1235 Binary files /dev/null and b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/Rubiks.jpg differ diff --git a/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/camera_P.m b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/camera_P.m new file mode 100644 index 00000000..e4943cf5 --- /dev/null +++ b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/camera_P.m @@ -0,0 +1,190 @@ +close all +clear all +clc + +filename = "rubiks2.jpg" +num_points = 24; % Set number of points + + +% Prompt user to load data or select points manually +choice = menu('Do you want to load points from the workspace_variables.mat file?', 'Yes', 'No'); + +if choice == 1 + % Load points from .mat file + load('workspace_variables.mat'); + + % Ensure the necessary variables exist in the loaded file + if exist('image_points', 'var') && exist('world_points', 'var') + disp('Points successfully loaded from workspace_variables.mat'); + else + error('The loaded file does not contain the required variables "image_points" and "world_points".'); + end +else + % Proceed with manual selection if user chooses "No" + + % Load and display the image + img = imread(filename); % Replace with your image file path + imshow(img); % Display the image + hold on; % Keep the image displayed while adding markers + + % Initialize matrices to store 2D and 3D homogeneous coordinates + image_points = zeros(num_points, 3); % For 2D image points in homogeneous coordinates + world_points = zeros(num_points, 4); % For 3D world points in homogeneous coordinates + + disp('Click on the image to select 96 points and enter their 3D world coordinates.'); + + for i = 1:num_points + % Use ginput to get one imJKJKJJKJKJage point at a time + [x, y] = ginput(1); + + % Store the 2D image coordinates in homogeneous form + image_points(i, :) = [x, y, 1]; + + % Plot the selected point on the image + plot(x, y, 'r+', 'MarkerSize', 8, 'LineWidth', 1.5); + + % Display the current point number for reference + text(x, y, sprintf(' %d', i), 'Color', 'yellow', 'FontSize', 10, 'FontWeight', 'bold'); + + % GUI prompt for 3D world coordinates + prompt = sprintf('Enter the 3D world coordinates for point %d (X, Y, Z):', i); + title = '3D World Coordinate Input'; + dims = [1]; % Set single row dimension for the input dialog + default_input = {'0', '0', '0'}; % Default values for input fields + answer = inputdlg({'X:', 'Y:', 'Z:'}, title, dims, default_input); + + % Convert input to numeric values and store in homogeneous form + if ~isempty(answer) + world_coords = str2double(answer); % Convert cell array of strings to numeric array + world_points(i, :) = [world_coords', 1]; % Store in homogeneous form [X Y Z 1] + else + error('3D coordinate input was canceled.'); % Handle case if input is canceled + end + end + + % Release the hold on the image display + hold off; +end + +% Construct the matrix A for solving P using SVD +A = []; +for i = 1:num_points + X = world_points(i, :); % Homogeneous 3D coordinates [X Y Z 1] + x = image_points(i, 1); % x-coordinate of the 2D image point + y = image_points(i, 2); % y-coordinate of the 2D image point + + % Build the two rows for each point + row1 = [zeros(1, 4), -X, y * X]; + row2 = [X, zeros(1, 4), -x * X]; + + % Append the rows to A + A = [A; row1; row2]; +end + +% Compute the camera projection matrix P using SVD +[~, ~, V] = svd(A); +P = reshape(V(:, end), 4, 3)'; % Reshape the last column of V into a 3x4 matrix + +% Compute the camera center as the null space of P +[~, ~, V_P] = svd(P); +camera_center_h = V_P(:, end); % Last column of V +camera_center = camera_center_h(1:3) / camera_center_h(4); % Convert from homogeneous + +% Decompose P into K and R using QR decomposition on the first 3x3 part +M = P(:, 1:3); % The 3x3 submatrix of P +[Q, R] = qr(inv(M)); % Use QR decomposition +K = inv(R); % Intrinsic matrix +K = K / K(3,3); % Normalize K so that K(3,3) is 1 +R = inv(Q); % Rotation matrix + +% Display computed matrices +disp('Computed camera matrix P:'); +disp(P); +disp('Intrinsic matrix K:'); +disp(K); +disp('Rotation matrix R:'); +disp(R); +disp('Camera center (in world coordinates):'); +disp(camera_center); + +% Visualization in 3D +figure 1; +scatter3(world_points(:,1), world_points(:,2), world_points(:,3), 'bo'); % Plot 3D points +hold on; +scatter3(camera_center(1), camera_center(2), camera_center(3), 'ro', 'filled'); % Plot camera center +quiver3(camera_center(1), camera_center(2), camera_center(3), -R(3,1), -R(3,2), -R(3,3), 10, 'r'); % Plot principal axis +%title('3D Points, Camera Center, and Principal Axis'); +xlabel('X'); +ylabel('Y'); +zlabel('Z'); +legend('3D Points', 'Camera Center', 'Principal Axis'); +grid on; +hold off; + +% Back-project the 3D points onto the 2D image using the camera matrix P +projected_points = P * world_points'; + +% Convert from homogeneous coordinates to 2D by normalizing +projected_points = projected_points ./ projected_points(3, :); + +% Display the original image and overlay the back-projected points + +% Assuming P is already computed and available + +% Define the points at infinity along the axes +D_x = [1; 0; 0; 0]; % Point at infinity along X-axis +D_y = [0; 1; 0; 0]; % Point at infinity along Y-axis +D_z = [0; 0; 1; 0]; % Point at infinity along Z-axis +D_o = [0; 0; 0; 1]; % World origin + +% Project these points using the camera projection matrix P +image_point_infinity_x = P * D_x; +image_point_infinity_y = P * D_y; +image_point_infinity_z = P * D_z; +image_point_origin = P * D_o; + +% Normalize the projected points to get 2D coordinates +image_point_infinity_x = image_point_infinity_x ./ image_point_infinity_x(3); +image_point_infinity_y = image_point_infinity_y ./ image_point_infinity_y(3); +image_point_infinity_z = image_point_infinity_z ./ image_point_infinity_z(3); +image_point_origin = image_point_origin ./ image_point_origin(3); + + +% Display the original image and overlay the points at infinity +figure(2); +imshow(img); +hold on; + +% Plot the actual image points in red +scatter(image_points(:, 1), image_points(:, 2), 'ro', 'filled', 'DisplayName', 'Actual Image Points'); + +% Plot back-projected points in green +scatter(projected_points(1, :), projected_points(2, :), 'gx', 'filled', 'DisplayName', 'Back-Projected 3D Points'); + +% Plot points at infinity with different markers and colors +scatter(image_point_infinity_x(1), image_point_infinity_x(2), 'bx', 'LineWidth', 2, 'DisplayName', 'Point at Infinity (X-axis)'); +scatter(image_point_infinity_y(1), image_point_infinity_y(2), 'gx', 'LineWidth', 2, 'DisplayName', 'Point at Infinity (Y-axis)'); +scatter(image_point_infinity_z(1), image_point_infinity_z(2), 'mx', 'LineWidth', 2, 'DisplayName', 'Point at Infinity (Z-axis)'); +scatter(image_point_origin(1), image_point_origin(2), 'ko', 'filled', 'DisplayName', 'World Origin'); + +% Draw vanishing lines from world origin to points at infinity +plot([image_point_origin(1), image_point_infinity_x(1)], ... + [image_point_origin(2), image_point_infinity_x(2)], ... + 'b--', 'LineWidth', 1.5, 'DisplayName', 'Vanishing Line (X-axis)'); + +plot([image_point_origin(1), image_point_infinity_y(1)], ... + [image_point_origin(2), image_point_infinity_y(2)], ... + 'g--', 'LineWidth', 1.5, 'DisplayName', 'Vanishing Line (Y-axis)'); + +% Draw a line connecting points at infinity in X and Y directions +plot([image_point_infinity_x(1), image_point_infinity_y(1)], ... + [image_point_infinity_x(2), image_point_infinity_y(2)], ... + 'm--', 'LineWidth', 1.5, 'DisplayName', 'Line Between Infinity Points'); + +% Add title + +% Create legend +%legend show; % Show legend to display all categories + +hold off; + diff --git a/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/assignment.pdf b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/assignment.pdf new file mode 100644 index 00000000..16794c4f Binary files /dev/null and b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/assignment.pdf differ diff --git a/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/assignment.tex b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/assignment.tex new file mode 100644 index 00000000..b29ab5a3 --- /dev/null +++ b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/assignment.tex @@ -0,0 +1,130 @@ +%! TeX program = lualatex +\documentclass[a4paper]{article} + +% packages +\usepackage{microtype} % Slightly tweak font spacing for aesthetics +\usepackage[english]{babel} % Language hyphenation and typographical rules +\usepackage[final, colorlinks = true, urlcolor = black, linkcolor = black]{hyperref} +\usepackage{changepage} % adjust margins on the fly + +\usepackage{fontspec} +\setmainfont{EB Garamond} +\setmonofont[Scale=MatchLowercase]{Deja Vu Sans Mono} + +\usepackage{minted} +\usemintedstyle{algol_nu} +\usepackage{xcolor} + +\usepackage{pgfplots} +\pgfplotsset{width=\textwidth,compat=1.9} + +\usepackage{caption} +\newenvironment{code}{\captionsetup{type=listing}}{} +\captionsetup[listing]{skip=0pt} +\setlength{\abovecaptionskip}{5pt} +\setlength{\belowcaptionskip}{5pt} + +\usepackage[yyyymmdd]{datetime} +\renewcommand{\dateseparator}{--} + +\usepackage{titlesec} +% \titleformat{\section}{\LARGE\bfseries}{}{}{}[\titlerule] +% \titleformat{\subsection}{\Large\bfseries}{}{0em}{} +% \titlespacing{\subsection}{0em}{-0.7em}{0em} +% +% \titleformat{\subsubsection}{\large\bfseries}{}{0em}{$\bullet$ } +% \titlespacing{\subsubsection}{1em}{-0.7em}{0em} + +% margins +\addtolength{\hoffset}{-2.25cm} +\addtolength{\textwidth}{4.5cm} +\addtolength{\voffset}{-3.25cm} +\addtolength{\textheight}{5cm} +\setlength{\parskip}{0pt} +\setlength{\parindent}{0in} +% \setcounter{secnumdepth}{0} + +\begin{document} +\hrule \medskip +\begin{minipage}{0.295\textwidth} + \raggedright + \footnotesize + \begin{tabular}{@{}l l} % Define a two-column table with left alignment + Name: & Andrew Hayes \\ + Student ID: & 21321503 \\ + \end{tabular} +\end{minipage} +\begin{minipage}{0.4\textwidth} + \centering + \vspace{0.4em} + \LARGE + \textsc{ct404} \\ +\end{minipage} +\begin{minipage}{0.295\textwidth} + \raggedleft + \footnotesize + \begin{tabular}{@{}l l} % Define a two-column table with left alignment + Name: & Maxwell Maia \\ + Student ID: & 21236277 \\ + \end{tabular} +\end{minipage} +\smallskip +\hrule +\begin{center} + \normalsize + Lab Assignment 1: Camera Callibration +\end{center} +\hrule + +\section{\textit{P}-Matrix Estimation Using Provided Code} +\begin{figure}[H] + \centering + \includegraphics[width=\textwidth]{./images/1.1.png} + \caption{ Command window output showing he computed camera matrix $P$, the intrinsic matrix $K$, \& the rotation matrix $R$ } +\end{figure} + +\begin{figure}[H] + \centering + \includegraphics[width=\textwidth]{./images/1.2.png} + \caption{ The 3D plot showing the camera center, the world points, \& the principal axis } +\end{figure} + +\begin{figure}[H] + \centering + \includegraphics[width=\textwidth]{./images/1.3.png} + \caption{ The image with projected 3D points \& vanishing lines } +\end{figure} + +\section{Using Your Own Image from Your Camera for \textit{P}-Matrix Estimation} +\begin{figure}[H] + \centering + \includegraphics[width=\textwidth]{./images/2.1.png} + \caption{ Command window output showing he computed camera matrix $P$, the intrinsic matrix $K$, \& the rotation matrix $R$ } +\end{figure} + +\begin{figure}[H] + \centering + \includegraphics[width=\textwidth]{./images/2.2.png} + \caption{ The 3D plot showing the camera center, the world points, \& the principal axis } +\end{figure} + +\begin{figure}[H] + \centering + \includegraphics[width=\textwidth]{./images/2.3.png} + \caption{ The image with projected 3D points \& vanishing lines } +\end{figure} + +\section{Experiment \& Reflect} +\subsection{How does increasing the number of points affect the accuracy \& stability of the \textit{P}-matrix estimation?} +As the number of control points increased, the accuracy and stability of the estimated P Matrix improved. With 12 points, we observed discrepancies in the back-projected 3D points, while results with 40 points were far more consistent. The intrinsic and rotation matrices derived from the P Matrix appeared less sensitive to noise with more points, enhancing the reliability of the calibration. + +\subsection{Is there a noticeable difference in the accuracy of the back-projection when using fewer points versus more points?} +Using fewer points (e.g., 12) resulted in higher deviations in back-projected points compared to their actual image locations. With 40 points, the back-projection closely matched the real-world setup, minimizing errors. + +\subsection{What challenges did you encounter when manually selecting points \& entering 3D world coordinates?} +The primary challenge that we faced when manually entering selecting the points was the precision: it was extremely difficult to precisely select the correct points due to the imprecision of the mouse as a selection device, human error, and a lack of fine-grain zoom control in the MATLAB UI. +\\\\ +We also found the process of manually entering the points very time-consuming and error-prone. +If we mis-clicked a point or accidentally entered in the wrong world coordinate, it would greatly damage the accuracy of the entire calibration and we would be forced to start over again. + +\end{document} diff --git a/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/images/1.1.png b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/images/1.1.png new file mode 100644 index 00000000..19181186 Binary files /dev/null and b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/images/1.1.png differ diff --git a/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/images/1.2.png b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/images/1.2.png new file mode 100644 index 00000000..1d5cf537 Binary files /dev/null and b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/images/1.2.png differ diff --git a/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/images/1.3.png b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/images/1.3.png new file mode 100644 index 00000000..7297b5b3 Binary files /dev/null and b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/images/1.3.png differ diff --git a/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/images/2.1.png b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/images/2.1.png new file mode 100644 index 00000000..e361e302 Binary files /dev/null and b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/images/2.1.png differ diff --git a/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/images/2.2.png b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/images/2.2.png new file mode 100644 index 00000000..a66dae37 Binary files /dev/null and b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/images/2.2.png differ diff --git a/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/images/2.3.png b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/images/2.3.png new file mode 100644 index 00000000..230f5466 Binary files /dev/null and b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/latex/images/2.3.png differ diff --git a/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/output1.ofig b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/output1.ofig new file mode 100644 index 00000000..733f41b3 Binary files /dev/null and b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/output1.ofig differ diff --git a/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/output2.ofig b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/output2.ofig new file mode 100644 index 00000000..abb71328 Binary files /dev/null and b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/output2.ofig differ diff --git a/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/rubiks.jpg b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/rubiks.jpg new file mode 100644 index 00000000..aa3bf16d Binary files /dev/null and b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/rubiks.jpg differ diff --git a/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/rubiks2.jpg b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/rubiks2.jpg new file mode 100644 index 00000000..75c71f76 Binary files /dev/null and b/year4/semester1/CT404: Graphics & Image Processing/assignments/lab1/rubiks2.jpg differ