Progreso mayo 2024 - RoboticsURJC/tfg-dcampoamor GitHub Wiki

Progreso mayo 2024

SEMANA 47 (29/04/2024-05/05/2024)

SEMANA 48 (06/05/2024-12/05/2024)

SEMANA 49 (13/05/2024-19/05/2024)

SEMANA 50 (20/05/2024-26/05/2024

SEMANA 51 (27/05/2024-02/06/2024

SEMANA 47 (29/04/2024-05/05/2024)

  • Pruebas con otro script para calcular las coordenadas del mundo real a partir de coordenadas de imagen utilizando una única cámara calibrada basada en geometría analítica mediante un visualizador de puntos en vídeo

    Dados los resultados, y viendo que a pesar de las pruebas realizadas, no se conseguía sacar nada en claro, y que los resultados experimentales obtenidos aún distaban bastante de los reales, se decidió seguir los pasos del repositorio de Julia López, que basaba sus pruebas en el script pinhole.py.

    Se ajustaron los parámetros necesarios para el uso del script con nuestro caso, entre los cuales se encontraban las variables globales, como el ancho y largo de la imagen, o la distancia focal y centro óptico de la cámara, junto con el ángulo que se encuentra rotado para el cálculo de la matriz de rotación y la altura de la cámara sobre la mesa para el cálculo de la matriz de traslación.

    Variables globales pinhole Valores de matrices a modificar pinhole

    También se cambió el rango de detección, para que, al ejecutar el script, se detectase el color amarillo del post-it sobre la cartulina blanca situada encima de la mesa, y que de este modo facilitase la detección.

    Deteccion amarillo

    Se supuso el origen del sistema de coordenadas mundo en la proyección vertical de la cámara sobre la mesa, y a partir de este origen, se intentaron llevar a cabo distintas pruebas, variando tanto el signo del ángulo de rotación de la cámara como el signo de la distancia de la cámara a la mesa, con tal de averiguar la orientación de los ejes para este script, y ver si los resultados obtenidos se asemejaban a la realidad.

    Para empezar a tomar resultados, se utilizó una regla sobre la cual se iba variando la posición del post-it amarillo para ver la evolución de los datos obtenidos al respecto, y que se supuso que estaba situada sobre el eje X (dada la rotación de la cámara, se midió desde el origen de coordenadas hasta un punto en el que la regla empezaba a ser visible, de ahí los valores reales de las medidas)

    Pruebas pinhole unico eje

    Pruebas pinhole unico eje Z positiva Pruebas pinhole unico eje Z negativa

    Tras estas pruebas, también se fijo una posición en el que, en un principio, se había supuesto eje X del sistema de coordenadas mundo, para poder comprobar el eje restante.

    Pruebas pinhole ambos ejes Pruebas pinhole ambos ejes Z positiva Pruebas pinhole ambos ejes Z negativa

    Con estos resultados, se puede observar, que la distancia (altura) a la que se encuentre la cámara sobre el plano suelo, deberá introducirse en negativo junto con el ángulo de rotación sobre el eje Y de la cámara en positivo, para que los resultados cuadren y que cuanto más se aleje el post-it amarillo, la distancia sea mayor, ya que lo que no puede variar es el origen del sistema de coordenadas, que se supuso en la vertical de la posición de la cámara.

SEMANA 48 (06/05/2024-12/05/2024)

  • Pruebas con otro script para calcular las coordenadas del mundo real a partir de coordenadas de imagen utilizando una única cámara calibrada basada en geometría analítica mediante un visualizador de puntos en vídeo

    Habiendo comprobado esto, se puede deducir que la representación del sistema de coordenadas mundo podría ser la siguiente:

    Esquema disposicion pruebas EJE Z POV camara pinhole

    Siendo lo que muestra la siguiente imagen lo que se puede ver a través de cámara. Estas diferencias a la hora de percibir las imágenes, ocurren debido a la forma en que la cámara captura y procesa la imagen. Esto sucede porque la cámara registra la escena con una rotación de 180º desde su propia perspectiva, entonces, cuando te mueves hacia la derecha desde tu punto de vista, desde la perspectiva de la cámara, parecerá que te estás moviendo hacia la izquierda.

    Vista de camara pinhole wiki

    Sin embargo, a pesar de definir los ejes, los resultados seguían sin ser buenos, por lo que se optó por basarse en los comentarios del script pinhole.py en los que se especificaba junto a los ángulos requeridos para calcular la matriz de rotación, que estos ángulos son representados "considerando que la camara (en vertical) está rotada 90º sobre eje Y" . Tomando esto en cuenta se representó como sería el sistema de coordenadas de la cámara sin esta rotación posterior de 90º.

    Esquema de rotacion camara

    Rotando sobre el eje Y de la cámara, y utilizando el ángulo que resultaba de restar estos 90º de rotación menos el ángulo que se estaba utilizando hasta ahora (ángulo que forma la horizontal con la dirección de la lente) se volvió a ejecutar el script para ver los resultados que se obtenían al respecto con esta rotación de 65º aproximadamente.

    Esquema rotacion sobre EJE Y camara

    Resultados mediciones pinhole 65 Rotacion

SEMANA 49 (13/05/2024-19/05/2024)

  • Estimación de la distancia para su uso en el script pinhole.py

    Estos resultados obtenidos en el apartado anterior se pueden considerar buenos dada su similitud con las medidas reales, por lo que se procedió a incluir el parámetro del cálculo de la distancia en el script a partir de las coordenadas 3D del punto, y a comprobar si esta también se aproximaba a la distancia real.

    Para ello se creó la función calcular_distancia_3d, tal y como se muestra a continuación:

    # Función para calcular la distancia euclidiana
    def calcular_distancia_3d(x_cam, y_cam, z_cam, x_punto, y_punto, z_punto):
        distancia = np.sqrt((x_punto - x_cam)**2 + (y_punto - y_cam)**2 + (z_punto - z_cam)**2)
        return distancia
    

    Para posteriormente hacer la llamada dentro de la función getPoints y poder mostrar por pantalla junto a las coordenadas 3D esta distancia calculada:

    # Coordenadas aproximadas del punto en 3D
          x_punto = pixelOnGround3D.x
          y_punto = pixelOnGround3D.y
          z_punto = pixelOnGround3D.z
    
          # Coordenadas aproximadas de la cámara en 3D
          x_cam = myCamera.position.x
          y_cam = myCamera.position.y
          z_cam = myCamera.position.z
    
          # Calcular distancia euclidiana
          distancia = calcular_distancia_3d(x_cam, y_cam, z_cam, x_punto, y_punto, z_punto)
          
          # Mostrar la distancia debajo de las coordenadas 3D aproximadas
          print(f"Distancia al punto: {distancia:.2f} milímetros")
    
    

    Todo esto puede verse detalladamente en el script completo modificado pinhole.py. Después de llevar a cabo estas modificaciones en el programa, se ejecutó para comprobar su correcto funcionamiento, pudiendo dar por buenos también los resultados debido a la similitud entre los resultados reales y los obtenidos.

    Deteccion de puntos y distancia EJE X Distancia al post-it

    Distancia al punto

  • Vídeos de prueba del uso y los resultados del script pinhole.py

    Para probar el uso y los resultados de la última versión modificada del script pinhole.py, se grabaron varios vídeos en los que se muestra su ejecución y cómo se detecta el centroide del post-it, y que si se mueve tanto a lo largo del eje X como muestra el vídeo Detección de puntos en EJE X.mp4 como a lo largo del eje Y o entre los dos ejes combinados (Detección de puntos EJE Y.mp4) , este se detecta, variando en función del cambio las coordenadas en 3D de ese centroide y la distancia desde la cámara a él.

  • Introducción a OpenGL

    Con el fin de reproducir una línea recta en 2D en base a una línea real dibujada sobre el plano, coincidente con lo detectado por la cámara web, se realizó el "Hello World" de esta librería que será la utilizada para poder llevar esto a cabo. Previa ejecución de los scripts de introducción a OpenGL, se instalaron los paquetes PyOpenGL y PyOpenGL_accelerate mediante el comando:

    pip install PyOpenGL PyOpenGL_accelerate
    

    Instalacion paquetes OpenGL

    Como resultado, se obtuvo el dibujo de un polígono blanco (rectángulo) con las esquinas en (0.25, 0.25, 0) y (0.75, 0.75, 0) sobre un fondo negro:

    Rectangulo HW OpenGL

    Se pueden encontrar los archivos utilizados para reproducir el "Hello World" en la carpeta openglhw, así como el vídeo en el que se muestra el proceso de ejecución y el resultado de estos en Vídeo Hello World OpenGL.

    Tras esta primera aproximación a OpenGL, se modificó el archivo openglhw.py para probar distintas cosas, como el cambio de color de la figura representada así como la forma geométrica de esta, dando como resultado el script introopengl.py, a lo que posteriormente se le añadió la representación de sus vértices y coordenadas de estos en introopengl_vertices.py, para finalmente probar a dibujar una línea recta a partir de dos puntos conocidos en introopengl_linea.py.

    Como resultado de esta secuencia de cambios en los scripts para probar distintos aspectos, se obtuvieron los siguientes resultados gráficos:

    introopengl.py introopengl_vertices.py introopengl_linea.py

    En estos scripts se cambiaron distintos parámetros de unos a otros, como el ancho de la ventana en la que se mostraban los resultados, pero generalmente, se puede diferenciar la siguiente estructura:

    Clase IntroduccionOpenGL: Que se encarga de la configuración de la ventana y la inicialización de los parámetros de OpenGL, y que incluye las siguientes funciones, que variarán dependiendo del script:

    • __init__: Se encarga de inicializar una instancia de esta clase, configurando específicamente la ventana de OpenGL donde se realizarán los dibujos.
    • init_gl: Que inicializa parámetros básicos de OpenGL como el color de fondo y el test de profundidad.
    • display: Se encarga de renderizar (dibujar) la escena cada vez que es necesario.
    • draw_vertices: Dibuja los puntos de los vértices y sus coordenadas como texto.
    • draw_text: Dibuja texto en la pantalla en la posición especificada, y que en el script introopengl_vertices.py serán las coordenadas de los vértices de las figuras.
    • run: Inicia el bucle principal de GLUT.

SEMANA 50 (20/05/2024-26/05/2024)

  • Pruebas con otro criterio para ubicar la cámara en el script pinhole.py

    Con el fin de averiguar el motivo por el cual la percepción del EJE Y a través de la cámara es la contraria a la real, tal y como se mostraba anteriormente en la SEMANA 48, se probó a rotar la cámara 180º mediante software a través del propio script pinhole.py, tal y como venía predefinido para el script dada la utilización de una Pi Camera para Raspberry Pi como uso inicial de este script.

    Codigo para rotar la camara por SW 180

    En esta imagen se muestra como se queda comentado el código utilizado para que esta rotación de 180º no tenga lugar, que es tal y como se ha considerado hasta ahora para toda la toma de datos.

    Al ejecutar el script con esta rotación se muestra lo siguiente a través de la ventana para la detección:

    POV Camara 180 rotada

    Tras comprobar esto, se volvieron a llegar a cabo las pruebas para corroborar si variando este parámetro junto con el criterio seguido para ubicar la cámara (signo de la distancia de la cámara a la mesa y signo del ángulo de rotación de la cámara) se conseguían datos aproximados a los reales.

    En primer lugar, se ejecutó el script considerando la distancia de la cámara positiva y el ángulo de rotación negativo, siendo este ángulo el mismo que se había obtenido al restar a 90º de rotación el ángulo que se estaba utilizando hasta ahora (ángulo que forma la horizontal con la dirección de la lente).

    Resultados pinhole con Z positiva y angulo negativo

    Y probando a rotar 180º mediante software la cámara con estas consideraciones:

    Ejecucion pinhole con 180 rotados Resultados pinhole con Z positiva y angulo negativo rotado 180

    Posteriormente, basándome de nuevo en los comentarios del script pinhole.py en los que se especificaba junto a los ángulos requeridos para calcular la matriz de rotación, que estos ángulos son representados "considerando que la cámara (en vertical) está rotada 90º sobre eje Y", y tomando en consideración el ángulo de rotación negativo, se consideró utilizar el ángulo en negativo según el esquema:

    Suma de angulos

    Y obteniendo los siguientes resultados tanto rotando 180º la cámara como sin esta rotación, sabiendo que el valor de alfa es -25º, y por tanto el valor total del ángulo utilizado con estas suposiciones es de -115º:

    Resultados pinhole con Z positiva angulo total y rotado 180

    Resultados pinhole con Z positiva y angulo negativo total EJE Y

    CONCLUSIONES: Después de elaborar todos estas pruebas, se puede apreciar que los únicos resultados que se pueden considerar similares a las medidas reales son los obtenidos con un valor positivo de la distancia en el eje Z de la cámara a la mesa y un valor negativo del ángulo total (-115º) utilizado para el cálculo de la matriz de rotación, a pesar de presentar el signo opuesto en las medidas sobre el EJE X, es decir, obteniéndose para este criterio de parámetros un resultado similar en cuanto a valores numéricos en valor absoluto, pero siendo negativos en lugar de positivos como deberían ser, dadas las suposiciones del sistema de coordenadas para este eje, y siendo similares en signo y magnitud para los resultados estudiados a lo largo del EJE Y. Esto supondría que la disposición del sistema de coordenadas para este criterio fuera el mostrado en la siguiente imagen, pero sería distinto al supuesto en un principio, y pese a haber considerado la distancia de en el eje Z de la cámara a la mesa de trabajo positiva, según los ejes de coordenadas, debería ser negativa.

    Sistema de coordenadas eje z hacia el suelo

    De igual manera, los resultados obtenidos con el criterio de uso del valor positivo de la distancia en el eje Z de la cámara a la mesa y un valor negativo del ángulo (-65º) utilizando el ángulo que resultaba de restar estos 90º de rotación menos el ángulo que se estaba utilizando hasta ahora (ángulo que forma la horizontal con la dirección de la lente) y una rotación de la cámara de 180º impuesta mediante software en el propio script pueden observarse que, pese a guardar la relación en cuanto al sistema de coordenadas, aumentando su valor en el EJE X cuanto más se alejaba en este eje, los valores obtenidos distan de parecerse a los obtenidos con la disposición contraria en cuanto a criterio (Z de la cámara negativa y mismo ángulo pero en positivo), los cuales se consideran más similares a los valores reales.

  • Pruebas con otra inclinación de cámara en el script pinhole.py para calcular las coordenadas del mundo real a partir de coordenadas de imagen utilizando una única cámara calibrada basada en geometría analítica mediante un visualizador de puntos en vídeo

    Después de llevar a cabo estas pruebas, se volvió al criterio que se había seguido en semanas anteriores, obteniendo los primeros resultados válidos, pero esta vez se varió la inclinación de la cámara, para comprobar si esta criterio era consistente y con una inclinación distinta.

    Ergonautas 16 grados

    En esta ocasión, el valor del ángulo alfa, es decir, del ángulo que forman la horizontal con la cámara, era de aproximadamente 16º, lo que daba como resultado un ángulo total para el su uso en la matriz de rotación de 74º (90º - 16º = 74º), y con el cual se obtenían los siguientes resultados:

    Resultados pinhole angulo distinto

    Lo cuál refleja que el cálculo del ángulo en esta ocasión fue más certero, puesto que los resultados obtenidos se acercaron bastante más a los reales que en la anterior ocasión, con el ángulo de aproximadamente 25º de inclinación de la cámara, y demostrando que los valores obtenidos son buenos tanto a lo largo del EJE X como a lo largo del EJE Y, como se muestra en las tablas y en el vídeo Prueba de pinhole con otro angulo en EJE Y.mp4, que muestra cómo se detecta el post-it a lo largo del EJE Y, y los resultados que se obtienen en las distintas posiciones, que son los reflejados en las tablas.

  • Modificaciones en el script pinhole para mostrar la reconstrucción de la figura geométrica detectada a partir de varios puntos

    Para poder unificar los scripts con los cuales se calcula la distancia a los puntos detectados (pinhole.py) y en el cual se utiliza OpenGL para generar figurar geométricas a partir de puntos obtenidos (introopengl_linea.py), se elaboró el scrip pinhole_modificado.py.

    Para ello, en primer lugar, se modificó el hecho de que se detectase únicamente un punto simultáneamente y se mostrase por pantalla, para que se detectasen todos aquellos puntos que cumplieran con la premisa del color, modificando la función detect_color para que devolviera todos los centroides de los contornos detectados, procesándolos para calcular sus coordenadas 3D y la distancia a la cámara, y dibujando todos los puntos y sus distancias en el frame.

    Lo siguiente que se llevó a cabo fue diferenciar varias detecciones, de tal manera que al mostrarse a la vez por pantalla, se pudieran identificar con letras y números, siguiendo estas etiquetas la siguiente nomenclatura: P1, P2...

    Para combinar el procesamiento de detección de puntos con OpenCV y la visualización de figuras geométricas usando OpenGL, se usó PyOpenGL para manejar la visualización de OpenGL en conjunto con OpenCV para la detección de puntos, quedando el script estructurado de la siguiente manera:

    • Configuración de OpenGL: Se inicializa una ventana OpenGL usando glutInit, y se configuran los parámetros de visualización como el color de fondo y las matrices de proyección y modelo.

    • Detección y Agrupamiento de Puntos: La función getPoints se encarga de detectar los puntos, agruparlos y transformarlos a coordenadas 3D. Estos puntos se almacenan en points_to_draw.

    • Visualización con OpenGL: La función display se encarga de dibujar los puntos y las líneas que los conectan en la ventana de OpenGL. Los puntos detectados se dibujan como puntos y se conectan con líneas.

    • Bucle Principal: En el bucle principal, se capturan los frames de la cámara, se detectan los puntos, se agrupan y se transforman, y se actualiza la ventana de OpenGL.

    Sin embargo, al ejecutar el script y probar a poner tres puntos, estos sí que eran detectados y diferenciados, pero no se conseguía dibujar nada en la ventana destinada a esto con OpenGL.

    Prueba triangulo pinhole modificado

SEMANA 51 (27/05/2024-02/06/2024)

  • Pruebas con OpenGL y generación de figuras geométricas mediante puntos

    Dado el problema que se daba a la hora de intentar modificar el programa pinhole.py para que en el mismo script también se reprodujeran las formas detectadas de un color definido en OpenGL, se optó por probar a elaborar en primer lugar un script en python que se denominó OpenGL_Unificado.py, que utilizaba OpenGL y en el que se muestran las figuras geométricas que se formaban a partir de una serie de puntos recibidos (simulando los detectados).

    Pruebas OpenGL_Unificado

    Pruebas OpenGL_Unificado.mp4 es el video en el que se muestra el funcionamiento de este script, y en el cual se puede apreciar como en función de los puntos aleatorios que se generen, se genera de igual forma una figura geométrica distinta.