{"id":32034,"date":"2025-01-31T16:05:00","date_gmt":"2025-01-31T15:05:00","guid":{"rendered":"https:\/\/inlab.fib.upc.edu\/?p=32034"},"modified":"2025-02-05T10:28:32","modified_gmt":"2025-02-05T09:28:32","slug":"31878","status":"publish","type":"post","link":"https:\/\/inlab.fib.upc.edu\/es\/articulos\/31878","title":{"rendered":"Visi\u00f3n por computador a Unreal Engine: Un reto del inLab FIB"},"content":{"rendered":"\n<p>Imaginemos por un momento que se nos plantea la elaboraci\u00f3n de un software muy especial. Se trata de un proyecto en el que la representaci\u00f3n debe ser apta para su visualizaci\u00f3n en p\u00fablico.<\/p>\n\n\n\n<p>Este fue precisamente el reto con el que nos encontramos en <strong>inLab FIB<\/strong>: un proyecto que combinaba renderizaci\u00f3n 3D con visi\u00f3n por computador y unas restricciones de tiempo de c\u00e1lculo muy exigentes.<\/p>\n\n\n\n<p>Con esta tarea por delante, en <strong>inLab FIB<\/strong> nos embarcamos en el desarrollo de este producto con un equipo formado por cuatro personas.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Elecci\u00f3n de la Tecnolog\u00eda Adecuada<\/strong><\/h3>\n\n\n\n<p>El primer paso fue seleccionar la tecnolog\u00eda con la que \u00edbamos a trabajar, bas\u00e1ndonos en los requisitos establecidos. Por motivos de confidencialidad, no revelaremos los detalles concretos del problema a tratar, pero s\u00ed podemos decir que se requer\u00eda:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Un detector de personas capaz de procesar seis im\u00e1genes en 10 ms.<\/li>\n\n\n\n<li>Un sistema de renderizado con iluminaci\u00f3n moderna.<\/li>\n\n\n\n<li>La aplicaci\u00f3n de varias t\u00e9cnicas tradicionales de visi\u00f3n por computador, tambi\u00e9n dentro del mismo l\u00edmite de 10 ms.<\/li>\n<\/ul>\n\n\n\n<p>Frente a este desaf\u00edo, evaluamos diversas tecnolog\u00edas. Uno de los primeros aspectos que tuvimos que considerar fue c\u00f3mo detectar personas en las im\u00e1genes. En este \u00e1mbito, decidimos utilizar un modelo de IA llamado <strong>YOLO<\/strong>, concretamente la versi\u00f3n 8. Este modelo es independiente de la plataforma, pero habitualmente se implementa a trav\u00e9s de una API en Python combinada con un ejecutor de modelos.<\/p>\n\n\n\n<p>Sin embargo, Python presenta problemas de rendimiento, lo que nos llev\u00f3 a descartarlo casi inmediatamente. La otra opci\u00f3n viable para utilizar YOLO era <strong>C++<\/strong>, un lenguaje que, a pesar de los retos en la gesti\u00f3n de memoria, es uno de los m\u00e1s eficientes disponibles. Para ponerlo en contexto, <strong>C++ se ha convertido en el lenguaje predominante en la industria del videojuego y en cualquier aplicaci\u00f3n con altos requisitos de c\u00e1lculo<\/strong>.<\/p>\n\n\n\n<p>Una vez resuelto el problema de la IA, necesit\u00e1bamos una forma de realizar c\u00e1lculos de visi\u00f3n por computador. Dado que ya hab\u00edamos elegido C++, la decisi\u00f3n natural fue utilizar <strong>OpenCV<\/strong>, una de las bibliotecas m\u00e1s populares para el procesamiento de im\u00e1genes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Renderizaci\u00f3n y Representaci\u00f3n 3D<\/strong><\/h3>\n\n\n\n<p>Para la visualizaci\u00f3n del sistema, una de las opciones que consideramos fue el uso de un motor de videojuegos. Aunque nuestro proyecto no ten\u00eda una finalidad l\u00fadica, su naturaleza compart\u00eda muchas similitudes con la industria del entretenimiento. En este contexto, evaluamos dos alternativas: <strong>Unity3D<\/strong> y <strong>Unreal Engine 5<\/strong>.<\/p>\n\n\n\n<p>Unity3D cuenta con un sistema de scripting en <strong>C#<\/strong> y permite la creaci\u00f3n de plugins en varios lenguajes, principalmente en C++. Aunque dispone de un sistema de iluminaci\u00f3n muy potente, la integraci\u00f3n entre la l\u00f3gica del plugin y la escena 3D presentaba dificultades, especialmente en la conversi\u00f3n de datos. Uno de los principales inconvenientes es que <strong>Unity-C# utiliza un sistema de garbage collector<\/strong>, mientras que en C++ la gesti\u00f3n de la memoria es manual.<\/p>\n\n\n\n<p>Adem\u00e1s, hay que tener en cuenta que el entorno 3D y todos los elementos del motor est\u00e1n implementados en C#, por lo que era necesario crear una API de comunicaci\u00f3n con el plugin en C++. Estas API suelen tener muchas limitaciones y, en general, se recomienda que sean sencillas, justo lo contrario de lo que nosotros pretend\u00edamos hacer.<\/p>\n\n\n\n<p>Ante estas consideraciones, la mejor opci\u00f3n result\u00f3 ser <strong>Unreal Engine 5<\/strong>. Aunque pueda parecer una elecci\u00f3n por descarte, presentaba varias ventajas clave:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Su scripting es en C++, lo que permit\u00eda la integraci\u00f3n directa con nuestro c\u00f3digo.<\/li>\n\n\n\n<li>Su sistema de renderizaci\u00f3n es uno de los mejores disponibles actualmente.<\/li>\n\n\n\n<li>Su modelo de licencias se ajustaba perfectamente a las necesidades del cliente.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Garantizando una Arquitectura Modular<\/strong><\/h3>\n\n\n\n<p>Aunque elegimos <strong>Unreal Engine<\/strong>, una de las cosas que ten\u00edamos claras en <strong>inLab FIB<\/strong> era que el dise\u00f1o de nuestro sistema deb\u00eda ser independiente del motor. En otras palabras, el c\u00f3digo de renderizaci\u00f3n 3D pod\u00eda conocer la existencia del dominio de c\u00e1lculo, pero no al rev\u00e9s.<\/p>\n\n\n\n<p>Para lograrlo, dividimos el sistema en dos capas:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>La capa \u00abUnreal\u00bb<\/strong>, responsable de mostrar informaci\u00f3n al usuario y adquirir datos de la interfaz de usuario.<\/li>\n\n\n\n<li><strong>La capa de \u00abl\u00f3gica\u00bb<\/strong>, encargada de procesar toda la informaci\u00f3n y capturar im\u00e1genes de las seis c\u00e1maras.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Optimizaci\u00f3n del Rendimiento GPU<\/strong><\/h3>\n\n\n\n<p>Uno de los grandes riesgos era que tanto Unreal Engine como los motores de IA hacen un uso intensivo de la GPU. Trabaj\u00e1bamos con un backend basado en <strong>CUDA [1]<\/strong> sobre una <strong>tarjeta gr\u00e1fica RTX 3090<\/strong>. Aunque en teor\u00eda este hardware era suficiente, en la pr\u00e1ctica no pudo procesar las seis im\u00e1genes y renderizar la escena en los 10 ms requeridos.<\/p>\n\n\n\n<p>Afortunadamente, los eventos deportivos del cliente se desarrollaban en pistas peque\u00f1as con superficies lisas e iluminaci\u00f3n controlada. La soluci\u00f3n, por tanto, fue desactivar <strong>Nanite [2]<\/strong> en Unreal Engine y utilizar un modelo de renderizaci\u00f3n basado en <strong>light maps [4]<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Implementaci\u00f3n de la UI<\/strong><\/h3>\n\n\n\n<p>Adem\u00e1s de la representaci\u00f3n 3D, el cliente necesitaba una interfaz de usuario (UI) para controlar el evento en tiempo real y gestionar las diversas c\u00e1maras. Crear esta UI con <strong>UMG [5]<\/strong> de Unreal Engine represent\u00f3 un reto significativo.<\/p>\n\n\n\n<p>Como no hab\u00eda alternativas mejores, decidimos incorporar un desarrollador especializado para esta tarea.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Conclusi\u00f3n<\/strong><\/h3>\n\n\n\n<p>Elegir <strong>Unreal Engine<\/strong> para este proyecto fue una decisi\u00f3n acertada, a pesar de los retos que supuso. El hecho de que nuestro algoritmo tuviera que competir con el motor por los recursos de la GPU fue un obst\u00e1culo importante. Sin embargo, contar con un motor tan potente nos proporcion\u00f3 herramientas \u00fatiles y una velocidad de desarrollo superior a la esperada.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Referencias<\/strong><\/h3>\n\n\n\n<p>[1] <strong><a href=\"https:\/\/developer.nvidia.com\/cuda-toolkit\">CUDA Toolkit &#8211; NVIDIA<\/a><\/strong><br>[2] <strong><a href=\"https:\/\/dev.epicgames.com\/documentation\/en-us\/unreal-engine\/nanite-virtualized-geometry-in-unreal-engine\">Nanite &#8211; Geometr\u00eda Virtualizada en Unreal Engine<\/a><\/strong><br>[3] <strong><a href=\"https:\/\/github.com\/ocornut\/imgui\">ImGui &#8211; Biblioteca de Interfaz de Usuario<\/a><\/strong><br>[4] <strong><a href=\"https:\/\/dev.epicgames.com\/documentation\/en-us\/unreal-engine\/understanding-lightmapping-in-unreal-engine\">Comprensi\u00f3n del Lightmapping en Unreal Engine<\/a><\/strong><br>[5] <strong><a href=\"https:\/\/dev.epicgames.com\/documentation\/en-us\/unreal-engine\/umg-ui-designer?application_version=4.27\">UMG &#8211; Dise\u00f1ador de Interfaz de Usuario en Unreal Engine<\/a><\/strong><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Imaginemos por un momento que se nos plantea la elaboraci\u00f3n de un software muy especial. Se trata de un proyecto en el que la representaci\u00f3n debe ser apta para su visualizaci\u00f3n en p\u00fablico. Este fue precisamente el reto con el que nos encontramos en inLab FIB: un proyecto que combinaba renderizaci\u00f3n 3D con visi\u00f3n por [&hellip;]<\/p>\n","protected":false},"author":1273,"featured_media":32020,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[496],"tags":[],"experteses":[],"class_list":["post-32034","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-articulos"],"acf":[],"_links":{"self":[{"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/posts\/32034","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/users\/1273"}],"replies":[{"embeddable":true,"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/comments?post=32034"}],"version-history":[{"count":1,"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/posts\/32034\/revisions"}],"predecessor-version":[{"id":32035,"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/posts\/32034\/revisions\/32035"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/media\/32020"}],"wp:attachment":[{"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/media?parent=32034"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/categories?post=32034"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/tags?post=32034"},{"taxonomy":"experteses","embeddable":true,"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/experteses?post=32034"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}