{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "a70a0eab-b03f-4f66-895f-42d77eea39a9",
   "metadata": {},
   "source": [
    "# Introducción a Realidad Aumentada en Python y OpenCV\n",
    "## Semana de las Ciencias de Información Geoespacial 2022\n",
    "### Centro de Investigación en Ciencias de Información Geoespacial, A.C."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c06948c6-7d47-4384-9da6-6a61f716de48",
   "metadata": {},
   "source": [
    "## ¿Que es la Realidad Aumentada?\n",
    "La *realidad aumentada* (AR) o realidad mixta es la integración en tiempo real de información digital con el ambiente en el que se encuentra el usuario. A diferencia de la *realidad virtual* (VR) en dodne se crea un mundo completamente virtual, con la realidad aumentada el usuario experimenta un mundo real con información sobrepuesta en el. Esta información sobrepuesta o aumentada puede ser visual, sonora o táctil; generada a través de dispositivos como teléfonos, tabletas, lentes o proyectores entre otros. \n",
    "\n",
    "La realidad aumentada tiene tres componentes principales: una **combinación de mundos reales y virtuales**, **interacción en tiempo real** y la **superposición tridimensional** precisa de de los objetos virtuales y reales. Para lograr esto la realidad aumentada incorpora diversas disciplinas y tecnologías, como visión por computadora o sensores digitales como giroscopios y acelerómetros, \n",
    "\n",
    "Es usada en diferentes áreas como juegos, educación, arquitectura, urbanismo, ingeniería, geointeligencia, manufactura y artes visuales entre muchas otras. \n",
    "\n",
    "![Realidad Aumentada](../resources/img/ar_screen1.jpg) ![Realidad Aumentada](../resources/img/ar_screen2.jpg)\\\n",
    "![Realidad Aumentada](../resources/img/ar_glasses1.jpg) ![Realidad Aumentada](../resources/img/ar_glasses2.jpg)\\\n",
    "![Realidad Aumentada](../resources/img/ar_projection1.jpg) ![Realidad Aumentada](../resources/img/ar_projection2.jpg)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d6288dc7-f680-4a60-9d15-c03251c1dcdc",
   "metadata": {},
   "source": [
    "# Ejemplo Básico de Realidad Aumentada\n",
    "Este pequeño curso introductorio presenta un ejemplo básico de realidad aumentada basado en visión por computadora. En este ejemplo se utiliza un patrón de referencia y una imagen de una escena en la cual se encuentra este patrón y se despliega un objeto tridimensional en la imagen de la escena sobre el marcador de referencia.\n",
    "En este ejemplo utilizaremos OpenCV y NumPy para la parte de visión por computadora siguiendo los siguientes pasos:\n",
    "1. **Leer Datos**\n",
    "3. **Reconocer Marcadores**\n",
    "4. **Obtener Homografía**\n",
    "5. **Estimación de Pose**\n",
    "5. **Desplegar Resultado**\n",
    "\n",
    "![diagrama curso](../resources/img/diagrama.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dc60cfa2-7169-41cf-9092-c6cdd56bec85",
   "metadata": {},
   "outputs": [],
   "source": [
    "#Dependencias\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dc900423-496c-48d4-ac35-52e8ffdde1a9",
   "metadata": {},
   "outputs": [],
   "source": [
    "#Dependencias\n",
    "import cv2\n",
    "import numpy as np\n",
    "import os\n",
    "import glob\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "79d0174c-0ec4-47a7-8154-bfec2576e00b",
   "metadata": {},
   "source": [
    "## Imagen de Referencia"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b798ff1e-b9d9-446c-beb6-1c6d7d4e89bb",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Imagen de refencia\n",
    "referenceImage = cv2.imread('../resources/img/patron.png', 0)\n",
    "referenceImage_rgb = cv2.imread('../resources/img/patron.png', 1)\n",
    "\n",
    "# Mostrar Imagen\n",
    "plt.imshow( cv2.cvtColor(referenceImage_rgb, cv2.COLOR_BGR2RGB))\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1a8e1483-5b8d-4bd4-a140-3062f25c4183",
   "metadata": {},
   "source": [
    "## Imagen de la escena"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7c24b780-ef95-41d4-9852-3b6f942ba175",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Imagen de la escena\n",
    "sourceImage = cv2.imread('../resources/img/escena0.jpg', 0)\n",
    "sourceImage_rgb = cv2.imread('../resources/img/escena0.jpg', 1)\n",
    "\n",
    "# Mostrar Imagen\n",
    "plt.imshow(cv2.cvtColor(sourceImage_rgb, cv2.COLOR_BGR2RGB))\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "90f41d30-8577-4010-ab50-bfde55957557",
   "metadata": {},
   "source": [
    "## Detección del patrón de referencia en la escena\n",
    "El primer paso para crear nuestra escena de realidad aumentada, es encontrar el patrón de referencia en la imagen de la escena, para esto utilizaremos técnicas de visión por computadora para el reconocimiento y detección de objetos. Esto involucra los siguientes pasos:\n",
    "\n",
    "1. Detección de características.\n",
    "2. Descripción de características. \n",
    "3. Correspondencia de caracteristicas. \n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b0fb2b5b-ad28-4b97-98c8-a1e081c9a799",
   "metadata": {},
   "source": [
    "## Detección y Descripción de Características\n",
    "La detección de características es un procesamiento de bajo nivel en donde **cada píxel se examina para determinar si existen características relevantes** en esa posición. Un uso de la detección de características es encontrar correspondencias entre diferentes imágenes, en nuestro ejemplo deseamos encontrar el patrón de referencia en la imagen de la escena. \n",
    "Existen varias técnicas para detectar características, como detección de contornos, de esquinas, textura y regiones entre otras. Después de la detección se utiliza un descriptor para codificar la información al rededor del píxel de interés.\n",
    "\n",
    "En nuestro ejemplo utilizamos el algoritmo [ORB](https://docs.opencv.org/3.4/d1/d89/tutorial_py_orb.html) el cual es una mezcla entre el algoritmo [FAST](https://link.springer.com/chapter/10.1007/11744023_34) y [BRIEFF](https://ieeexplore.ieee.org/abstract/document/6081878).\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0ed1f79c-097a-493e-b4ae-ee23ccb5f0b3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Inizializar detector ORB.\n",
    "orb = cv2.ORB_create()\n",
    "\n",
    "# Encontrar puntos de inters con ORB.\n",
    "referenceImagePts = orb.detect(referenceImage, None)\n",
    "sourceImagePts = orb.detect(sourceImage, None)\n",
    "\n",
    "# Utilizar n descriptor par los puntos de inters con ORB.\n",
    "referenceImagePts, referenceImageDsc = orb.compute(referenceImage, referenceImagePts)\n",
    "sourceImagePts, sourceImageDsc = orb.compute(sourceImage, sourceImagePts)\n",
    "\n",
    "# Dibujar los puntos de interes sobre la imagen de referencia y la imagen de la escena.\n",
    "referenceImageFeatures = cv2.drawKeypoints(referenceImage_rgb, referenceImagePts, None, color=(0,255,0), flags=0)\n",
    "sourceImageFeatures = cv2.drawKeypoints(sourceImage_rgb, sourceImagePts, None, color=(0,255,0), flags=0)\n",
    "\n",
    "# Mostrar Imagen\n",
    "plt.figure(figsize=(10, 5))\n",
    "plt.subplot(1, 2, 1)\n",
    "plt.axis(\"off\")\n",
    "\n",
    "plt.imshow(cv2.cvtColor(referenceImageFeatures, cv2.COLOR_BGR2RGB))\n",
    "plt.title('Caracteristicas en la imagen de referencia')\n",
    "plt.subplot(1, 2, 2)\n",
    "plt.axis(\"off\")\n",
    "plt.imshow(cv2.cvtColor(sourceImageFeatures, cv2.COLOR_BGR2RGB))\n",
    "plt.title('Caracteristicas en la imagen de la escena')\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9bcc2e63-c948-42d1-aa4f-08d14bcc2a66",
   "metadata": {},
   "source": [
    "## Correspondencia de Características\n",
    "Una vez que se encontraron las características en la de ambas imágenes y se generó sus descriptores, se procede a encontrar las correspondencias entre ellas. Para eso utilizamos el algoritmo de OpenCV [Brute-Force Matcher](https://docs.opencv.org/4.x/d3/da1/classcv_1_1BFMatcher.html#details) el cual compara cada descriptor en la imagen de referencia con todos los descriptores de la imagen de la escena para encontrar la mejor correspondencia. \n",
    "\n",
    "Después de encontrar las correspondencias entre las dos imagenes, para decidir si el patrón de referencia se encuentra o no en la imagen de la escena comparamos el numero total de correspondencias encontradas con un umbral fijado previamente."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f419bae2-eef1-44f9-9ef8-0434812210f2",
   "metadata": {},
   "outputs": [],
   "source": [
    "MIN_MATCHES = 30\n",
    "            \n",
    "# Crear objeto brute force  matcher\n",
    "bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)\n",
    "\n",
    "# Encontrar puntos de interes y generar descriptores\n",
    "referenceImagePts, referenceImageDsc = orb.detectAndCompute(referenceImage, None)\n",
    "sourceImagePts, sourceImageDsc = orb.detectAndCompute(sourceImage, None)\n",
    "\n",
    "# Encontrar correspondencias entre puntos de interes\n",
    "matches = bf.match(referenceImageDsc, sourceImageDsc)\n",
    "matches = sorted(matches, key=lambda x: x.distance)\n",
    "\n",
    "if len(matches) > MIN_MATCHES:\n",
    "    idxPairs = cv2.drawMatches(referenceImage_rgb, referenceImagePts, sourceImage_rgb, sourceImagePts, matches[:MIN_MATCHES], 0, flags=2)\n",
    "    # Mostrar Resultado\n",
    "    plt.figure(figsize=(12, 6))\n",
    "    plt.axis('off')\n",
    "    plt.imshow(cv2.cvtColor(idxPairs, cv2.COLOR_BGR2RGB))\n",
    "    plt.title('Matching between features')\n",
    "    plt.show()\n",
    "    \n",
    "else:\n",
    "    print(\"Not enough matches have been found - %d/%d\" % (len(matches), MIN_MATCHES))\n",
    "    matchesMask = None"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4cf14948-3e37-482d-98ea-fd40c51eb20e",
   "metadata": {},
   "source": [
    "## Estimación de Pose (Matriz de la Cámara)\n",
    "El paso clave en una aplicación de realidad aumentada con visión por computadora, es reconstruir la geometría de la escena, esto es encontrar la ubicación de la cámara en la escena, su translación y rotación relativos al plano en donde se encuentra el patrón de referencia. Esto permite poder mezclar las imagenes generadas por la computadora con la escena real de forma que tengan la perspectiva y tamaño adecuadas. Para lograr esto utilizaremos varios conceptos de álgebra lineal. \n",
    "\n",
    "Matemáticamente los parámetros anteriores (camara, translación y rotación), también conocidos como la geometría de la escena, están dados por:\n",
    "1. La matriz de calibración de la cámara $\\mathbf{K} \\in \\mathbb{R}^{3x3}$\n",
    "2. La matriz de rotación de la cámara $\\mathbf{R} \\in \\mathbb{R}^{3x3}$\n",
    "3. El vector de translación de la cámara $\\mathbf{t} \\in \\mathbb{R}^{3}$\n",
    "\n",
    "La geometría de la escena puede ser representada por una única matriz $\\mathbf{P}$ conocida como matriz de la cámara: \n",
    "$$\\mathbf{P}=\\mathbf{K} \\cdot \\left[\\mathbf{R}|\\mathbf{t}\\right]$$\n",
    "\n",
    "La matriz de calibración de la cámara $\\mathbf{K}$ contiene los parámetros internos de la cámara, los cual por el momento asumiremos que conocemos, el resto de los parámetros, la rotación y la translación, son conocidos como parámetros externos y pueden ser encontrados con las correspondencias entre la imagen de referencia y el patrón en la escena. \n",
    "\n",
    "![Camara](../resources/img/cameramodel.png)\n",
    "\n",
    "### Homógrafa\n",
    "La homógrafa $\\mathbf{H}$ es una transformación proyectiva que pemrite proyectar puntos de un plano a otro plano, en nuestro caso nos permite proyectar puntos del plano de la cámara al plano en la escena donde se encuentra el patrón de referencia. Por medio del algoritmo [DLT](https://docs.opencv.org/3.4/d9/dab/tutorial_homography.html#tutorial_homography_What_is_the_homography_matrix) o métodos mas robustos como [RANSAC (Random sample consensus)](https://dl.acm.org/doi/abs/10.1145/358669.358692) podemos obtener la matrix de homógrafa utilizando al menos 4 correspondencias entre puntos en la imagen de referencia y la imagen de la escena. \n",
    "\n",
    "\n",
    "$$ \\mathbf{x}'=\\mathbf{H}\\cdot \\mathbf{x}$$\n",
    "\n",
    "$$ \\begin{bmatrix} x' \\\\  y' \\\\  z' \\end{bmatrix} =  \\begin{bmatrix} h_1 & h_2 & h_3 \\\\  h_4 & h_5 & h_6 \\\\ \n",
    "h_7 & h_8 & h_9 \\end{bmatrix}  \\begin{bmatrix} x \\\\  y \\\\  z \\end{bmatrix} $$\n",
    "\n",
    "Finalmente la rotación y la traslacion pueden ser encontrados con la homografía por medio de :\n",
    "\n",
    "$$[\\mathbf{r}_1, \\mathbf{r}_2, \\mathbf{t}] = \\frac{\\mathbf{K}^{-1} \\mathbf{H} }{\\| \\mathbf{K}^{-1} \\mathbf{H}\\|}$$\n",
    "![Camara](../resources/img/homography.png)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5fc219c1-68c2-4b8a-85b2-474079db34ff",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Aplicar Homografia\n",
    "if len(matches) > MIN_MATCHES:\n",
    "    # Obtener posicion de los puntos de interes\n",
    "    sourcePoints = np.float32([referenceImagePts[m.queryIdx].pt for m in matches]).reshape(-1, 1, 2)\n",
    "    destinationPoints = np.float32([sourceImagePts[m.trainIdx].pt for m in matches ]).reshape(-1, 1, 2)\n",
    "\n",
    "    #Obtener la matriz de Homografia\n",
    "    homography, mask = cv2.findHomography(sourcePoints, destinationPoints, cv2.RANSAC, 5.0)\n",
    "    matchesMask = mask.ravel().tolist()\n",
    "\n",
    "    # Aplicar la transformacion proyectiva a las esquinas de la imagen de referncia\n",
    "    h, w = referenceImage.shape\n",
    "    corners = np.float32([[0, 0], [0, h - 1], [w - 1, h - 1], [w - 1, 0]]).reshape(-1, 1, 2)\n",
    "    transformedCorners = cv2.perspectiveTransform(corners, homography)\n",
    "\n",
    "    #Dibujar poligono uniendo las esquinas proyectadas\n",
    "    sourceImageMarker = sourceImage_rgb.copy()    \n",
    "    sourceImageMarker = cv2.polylines(sourceImageMarker, [np.int32(transformedCorners)], True, (255,0,0), 5, cv2.LINE_AA)\n",
    "    \n",
    "else:\n",
    "    print(\"Not enough matches are found - %d/%d\" % (len(matches), MIN_MATCHES))\n",
    "    matchesMask = None\n",
    "\n",
    "# Dibujar Correspondencias\n",
    "drawParameters = dict(matchColor=(0, 255, 0), singlePointColor=None,matchesMask=matchesMask, flags=2)\n",
    "result = cv2.drawMatches(referenceImage_rgb, referenceImagePts, sourceImageMarker, sourceImagePts, matches, None, **drawParameters)\n",
    "print(type(result))\n",
    "# Mostrar Imagen\n",
    "plt.figure(figsize=(12, 6))\n",
    "plt.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB))\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f81f970a-f00c-4c10-8045-274caf5c86b6",
   "metadata": {},
   "outputs": [],
   "source": [
    "def projection_matrix(camera_parameters, homography):\n",
    "    \n",
    "    homography = homography * (-1)\n",
    "    rot_and_transl = np.dot(np.linalg.inv(camera_parameters), homography)\n",
    "    col_1 = rot_and_transl[:, 0]\n",
    "    col_2 = rot_and_transl[:, 1]\n",
    "    col_3 = rot_and_transl[:, 2]\n",
    "    \n",
    "    # normalise vectors\n",
    "    l = math.sqrt(np.linalg.norm(col_1, 2) * np.linalg.norm(col_2, 2))\n",
    "    rot_1 = col_1 / l\n",
    "    rot_2 = col_2 / l\n",
    "    translation = col_3 / l\n",
    "    \n",
    "    # compute the orthonormal basis\n",
    "    c = rot_1 + rot_2\n",
    "    p = np.cross(rot_1, rot_2)\n",
    "    d = np.cross(c, p)\n",
    "    rot_1 = np.dot(c / np.linalg.norm(c, 2) + d / np.linalg.norm(d, 2), 1 / math.sqrt(2))\n",
    "    rot_2 = np.dot(c / np.linalg.norm(c, 2) - d / np.linalg.norm(d, 2), 1 / math.sqrt(2))\n",
    "    rot_3 = np.cross(rot_1, rot_2)\n",
    "    \n",
    "    # finally, compute the 3D projection matrix from the model to the current frame\n",
    "    projection = np.stack((rot_1, rot_2, rot_3, translation)).T\n",
    "    \n",
    "    return np.dot(camera_parameters, projection)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "19ff515a-0715-4963-9347-2420a934cb72",
   "metadata": {},
   "outputs": [],
   "source": [
    "from objloader_simple import *\n",
    "import math\n",
    "# Matriz de calibracion de la camara\n",
    "camera_parameters = np.array([[852,    0, 387],\n",
    "                              [   0,852, 294],\n",
    "                              [   0,    0,   1]])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f2ce8459-f12a-427a-a0d7-f6d7b5a2621e",
   "metadata": {},
   "outputs": [],
   "source": [
    "def render(img, obj, projection, model, color=False):\n",
    "\n",
    "    vertices = obj.vertices\n",
    "    scale_matrix = np.eye(3) * 6\n",
    "    h, w = model.shape\n",
    "\n",
    "    for face in obj.faces:\n",
    "        face_vertices = face[0]\n",
    "        points = np.array([vertices[vertex - 1] for vertex in face_vertices])\n",
    "        points = np.dot(points, scale_matrix)\n",
    "        # render model in the middle of the reference surface. To do so,\n",
    "        # model points must be displaced\n",
    "        points = np.array([[p[0] + w / 2, p[1] + h / 2, p[2]] for p in points])\n",
    "        dst = cv2.perspectiveTransform(points.reshape(-1, 1, 3), projection)\n",
    "        imgpts = np.int32(dst)\n",
    "        img = cv2.fillConvexPoly(img, imgpts, (80, 27, 211))\n",
    "    return img"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a1ffec76-975c-401b-adc3-8a83072b48cf",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Apply the homography transformation if we have enough good matches\n",
    "from object_module import *\n",
    "\n",
    "if len(matches) > MIN_MATCHES:\n",
    "    # Get the good key points positions\n",
    "    sourcePoints = np.float32([referenceImagePts[m.queryIdx].pt for m in matches]).reshape(-1, 1, 2)\n",
    "    destinationPoints = np.float32([sourceImagePts[m.trainIdx].pt for m in matches ]).reshape(-1, 1, 2)\n",
    "\n",
    "    # Obtain the homography matrix\n",
    "    homography, _ = cv2.findHomography(sourcePoints, destinationPoints, cv2.RANSAC, 5.0)\n",
    "    matchesMask = mask.ravel().tolist()\n",
    "    img_ag = sourceImage_rgb.copy()\n",
    "\n",
    "    # Apply the perspective transformation to the source image corners\n",
    "    h, w = referenceImage.shape\n",
    "    corners = np.float32([[0, 0], [0, h - 1], [w - 1, h - 1], [w - 1, 0]]).reshape(-1, 1, 2)\n",
    "    transformedCorners = cv2.perspectiveTransform(corners, homography)\n",
    "\n",
    "    # Draw a polygon on the second image joining the transformed corners\n",
    "    img_ag = cv2.polylines(img_ag, [np.int32(transformedCorners)], True, 255, 3, cv2.LINE_AA)\n",
    "    \n",
    "    # obtain 3D projection matrix from homography matrix and camera parameters\n",
    "    projection = projection_matrix(camera_parameters, homography)  \n",
    "    # project cube or model\n",
    "    #img_ag = render(img_ag, obj1, projection, referenceImage, False)\n",
    "    projection = projection_matrix(camera_parameters, homography)  \n",
    "    obj2 = three_d_object('../resources/fox/fox.obj', '../resources/fox/texture.png')\n",
    "    agumented = sourceImage_rgb.copy()\n",
    "    augmented =augment(agumented, obj2, projection, referenceImage, scale=3) #flipped for better control\n",
    "    plt.figure(figsize=(12, 6))\n",
    "    plt.imshow(cv2.cvtColor(augmented, cv2.COLOR_BGR2RGB))\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "32a0f346-0ed6-4390-bffa-50cc3ec66f02",
   "metadata": {},
   "outputs": [],
   "source": [
    "def getHomography(referenceImage, sourceImage):\n",
    "    MIN_MATCHES = 30\n",
    "    # Inizializar detector ORB.\n",
    "    orb = cv2.ORB_create()\n",
    "    # create brute force  matcher object\n",
    "    bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)\n",
    "    # Compute model keypoints and its descriptors\n",
    "    referenceImagePts, referenceImageDsc = orb.detectAndCompute(referenceImage, None)\n",
    "    # Compute scene keypoints and its descriptors\n",
    "    sourceImagePts, sourceImageDsc = orb.detectAndCompute(sourceImage, None)\n",
    "    # Match frame descriptors with model descriptors\n",
    "    matches = bf.match(referenceImageDsc, sourceImageDsc)\n",
    "    if len(matches) > MIN_MATCHES:\n",
    "        # Get the good key points positions\n",
    "        sourcePoints = np.float32([referenceImagePts[m.queryIdx].pt for m in matches]).reshape(-1, 1, 2)\n",
    "        destinationPoints = np.float32([sourceImagePts[m.trainIdx].pt for m in matches ]).reshape(-1, 1, 2)\n",
    "\n",
    "        # Obtain the homography matrix\n",
    "        homography, _ = cv2.findHomography(sourcePoints, destinationPoints, cv2.RANSAC, 5.0)\n",
    "\n",
    "\n",
    "        return True, homography\n",
    "    else:\n",
    "        return False, None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0570f318-b424-492f-b41c-3c74dbc004f0",
   "metadata": {},
   "outputs": [],
   "source": [
    "from object_module import *\n",
    "obj_fox = three_d_object('../resources/fox/fox.obj', '../resources/fox/texture.png')\n",
    "col=3\n",
    "fig = plt.figure(figsize=(12, 7))\n",
    "\n",
    "nImages = 9\n",
    "for i in (range(nImages)):\n",
    "    sourceImage_i = cv2.imread('../resources/img/escena_'+str(i+1).rjust(3,\"0\")+'.jpg', 0)\n",
    "    sourceImage_rgb_i = cv2.imread('../resources/img/escena_'+str(i+1).rjust(3,\"0\")+'.jpg', 1)\n",
    "\n",
    "    row = nImages// col\n",
    "    if (nImages % col != 0):\n",
    "        row += 1\n",
    "    ret, homography_i = getHomography(referenceImage, sourceImage_i)\n",
    "    if ret:\n",
    "        projection_i = projection_matrix(camera_parameters, homography_i)  \n",
    "        agumented = sourceImage_rgb_i.copy()\n",
    "        augmented =augment(agumented, obj_fox, projection_i, referenceImage, scale=3) #flipped for better control\n",
    "\n",
    "        a=fig.add_subplot(row, col, i + 1)\n",
    "        plt.imshow(cv2.cvtColor(augmented, cv2.COLOR_BGR2RGB))\n",
    "        plt.axis('off')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6a53adc4-29e2-480f-9b17-5778bf38733e",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
