Imaginem per un moment que se’ns planteja l’elaboració d’un programari molt especial. Es tracta d’un projecte La representació havia de ser apta per a la seva visualització en públic.
Aquest va ser precisament el repte amb què ens vam trobar a inLab FIB: un projecte que combinava renderització 3D amb visió per computador i unes restriccions de temps de càlcul molt exigents.
Amb aquesta tasca al davant, a inLab FIB ens vam embarcar en el desenvolupament d’aquest producte amb un equip format per quatre persones.
Elecció de la Tecnologia Adequada
El primer pas va ser seleccionar la tecnologia amb què havíem de treballar, basant-nos en els requisits establerts. Per motius de confidencialitat, no revelarem els detalls concrets del problema a tractar, però sí que podem dir que es requeria:
- Un detector de persones capaç de processar sis imatges en 10 ms.
- Un sistema de renderitzat amb il·luminació moderna.
- L’aplicació de diverses tècniques tradicionals de visió per computador, també dins del mateix límit de 10 ms.
Davant d’aquest repte, vam avaluar diverses tecnologies. Un dels primers aspectes que vam haver de considerar va ser com detectar les persones a les imatges. En aquest àmbit, vam decidir utilitzar un model d’IA anomenat YOLO, concretament la versió 8. Aquest model és independent de la plataforma, però habitualment s’implementa a través d’una API de Python combinada amb un executor de models.
Tanmateix, Python presenta problemes de rendiment, fet que va portar a descartar-lo gairebé immediatament. L’altra opció viable per utilitzar YOLO era C++, un llenguatge que, malgrat els reptes en la gestió de la memòria, és un dels més eficients disponibles. Per posar-ho en context, C++ s’ha convertit en el llenguatge predominant en la indústria dels videojocs i en qualsevol aplicació amb alts requisits de càlcul.
Un cop resolt el problema de la IA, necessitàvem una manera de realitzar càlculs de visió per computador. Atès que ja havíem triat C++, la decisió natural va ser utilitzar OpenCV, una de les biblioteques més populars per al processament d’imatges.
Renderització i Representació 3D
Per a la visualització del sistema, una de les opcions que vam considerar va ser l’ús d’un motor de videojocs. Tot i que el nostre projecte no tenia una finalitat lúdica, la seva naturalesa compartia moltes similituds amb la indústria de l’entreteniment. En aquest context, vam avaluar dues alternatives: Unity3D i Unreal Engine 5.
Unity3D compta amb un sistema de scripting en C# i permet la creació de plugins en diversos llenguatges, principalment en C++. Tot i que disposa d’un sistema d’il·luminació molt potent, la integració entre la lògica del plugin i l’escena 3D presentava dificultats, especialment en la conversió de dades. Un dels principals inconvenients és que Unity-C# utilitza un sistema de garbage collector, mentre que en C++ la gestió de la memòria és manual.
A més, cal tenir en compte que l’entorn 3D i tots els elements del motor estan implementats en C#, i per tant era necessari crear una API de comunicació amb el plugin en C++. Aquestes API solen tenir moltes limitacions i, en general, es recomana que siguin senzilles—just el contrari del que nosaltres preteníem fer.
Davant d’aquestes consideracions, la millor opció va resultar ser Unreal Engine 5. Tot i semblar una elecció per descart, presentava diversos avantatges clau:
- El seu scripting és en C++, fet que permetia la integració directa del nostre codi.
- El seu sistema de renderització és un dels millors disponibles actualment.
- El seu model de llicència s’ajustava perfectament a les necessitats del client.
Assegurant una Arquitectura Modular
Encara que vam triar Unreal Engine, una de les coses que teníem clares a inLab FIB era que el disseny del nostre sistema havia de ser independent del motor. En altres paraules, el codi de renderització 3D podia conèixer l’existència del domini de càlcul, però no a l’inrevés.
Per aconseguir-ho, vam dividir el sistema en dues capes:
- La capa “Unreal”, responsable de mostrar informació a l’usuari i adquirir dades de la interfície d’usuari.
- La capa de “lògica”, encarregada de processar tota la informació i capturar imatges de les sis càmeres.
Optimització del Rendiment GPU
Un dels grans riscos era que tant Unreal Engine com els motors d’IA fan un ús intensiu de la GPU. Treballàvem amb un backend basat en CUDA [1] sobre una targeta gràfica RTX 3090. Tot i que en teoria aquest maquinari era suficient, en la pràctica no va poder processar les sis imatges i renderitzar l’escena en els 10 ms requerits.
Afortunadament, els esdeveniments esportius del client es desenvolupaven en pistes petites amb superfícies llises i il·luminació controlada. La solució, per tant, va ser desactivar Nanite [2] a Unreal Engine i utilitzar un model de renderització basat en light maps [4].
Implementació de la UI
A més de la representació 3D, el client necessitava una interfície d’usuari (UI) per controlar l’esdeveniment en temps real i gestionar les diverses càmeres. Crear aquesta UI amb UMG [5] d’Unreal Engine va representar un repte significatiu.
Com no hi havia alternatives millors, vam decidir incorporar un desenvolupador especialitzat per a aquesta tasca.
Conclusió
Triar Unreal Engine per a aquest projecte va ser una decisió encertada, tot i els reptes que va suposar. El fet que el nostre algorisme hagués de competir amb el motor pels recursos de la GPU va ser un obstacle important. No obstant això, comptar amb un motor tan potent ens va proporcionar eines útils i una velocitat de desenvolupament superior a l’esperada.