Hagamos una web con IA y AR – Mobilenet y TensorFlow.js

Inteligencia Artificial y Realidad Aumentada de la mano con TensorFlow.js y MobileNet

Una imagen de color blanco con texto de color negro que dice: Clasificacion de imagenes con realidad aumentada. un recuadro que muestras una camara web activa mostrando el reconocimiento de objetos en realidad aumentada
IA y AR – Mobilenet y TensorFlow.js

Vamos directamente a la aplicación para que veas el funcionamiento y te animes a construir desde cero tu propia app de reconocimiento de objetos y realidad aumentada.

Este es el link: Clasificación de Imágenes con Realidad Aumentada (AR)

Creo que el futuro de las apps y el acceso a super herramientas está en el desarrollo web.

La web tiene mucho potencial y en este caso nos permite acceder a tecnologías como la inteligencia Artificial (IA) y la Realidad Aumentada (RA).

El día de hoy quiero compartir con ustedes este tutorial de una aplicación web que utiliza varias tecnologías:

  • Inteligencia Artificial – TensorFlow.js y Mobilenet.
  • Realidad Aumentada.
  • JavaScript asincrono
  • APIs del navegador
  • CSS

Ya hemos hablado en el blog de estas maravillas modernas, aquí te dejo unas entradas que te puedan interesar:

Reconocimiento de objetos usando TensorFlow.js y Keras

Inteligencia artificial en una app de realidad aumentada

Ventajas y desventajas de la realidad aumentada (RA)


Tecnologías Claves para este tutorial

  • TensorFlow.js: Es una biblioteca de código abierto de Google que permite entrenar y ejecutar modelos de aprendizaje directamente en el navegador.
  • Mobilenet: Un modelo de red neuronal convolucional pre-entrenado y optimizado para dispositivos móviles. Es de alta eficiencia lo que lo hace perfecto para trabajar en el navegador y en dispositivos móviles permitiendo una clasificación de imágenes casi que instantánea.
  • JavaScript asíncrono (async/await): lo utilizamos para manejar tareas que consumen mucho tiempo, como la carga del modelo o la inicialización de la cámara web.
  • APIs del navegador: Utilizamos navigator.mediaDevices.getUserMedia() para acceder a la cámara del dispositivo y requestAnimationFrame() que nos permite optimizar el bucle de predicción, asegurando que el análisis de imágenes ocurra en sincronía con los fotogramas del navegador web.
  • CSS y Tailwind CSS: Utilizado para el estilo y diseño de la interfaz.

Como funciona: El proceso paso a paso

La lógica de la app está definida de la siguiente manera:

  • Inicializacion: Al cargar la página, se inicia la función init(). Simultáneamente se solicita el acceso a la cámara y se carga el modelo IA de MobileNet.
  • Captura de video: La funcion startCamera() obtiene el stream de video de la cámara del dispositivo. Lo siguiente del código maneja la orientación, ajuste del contenedor de video y activa la cámara frontal.
  • Bucle de predicción: Una vez que el modelo y la cámara estén listos, se inicia un bucle de animación predictionLoop() que se ejecuta en cada frame del video.
  • Clasificación en tiempo real: En cada iteración del bucle de predicción, el modelo MobileNet clasifica la imagen del video. El resultado de la clasificacion (El nombre del objeto y su puntaje en porcentaje de confianza). se superpone sobre la imagen de la cámara creando el efecto de Realidad Aumentada.

Código JavaScript

 

  • Referencias del DOM y Variables de Estado

Este bloque de código inicializa las variables y referencias que el resto del código necesita para interactuar con los elementos HTML y para manejar el estado interno de la aplicación.

// Referencias a los elementos del DOM
const videoElement = document.getElementById('videoElement');
const statusElement = document.getElementById('status');
const videoContainer = document.getElementById('video-container');
const classNameElement = document.getElementById('className');
const confidenceScoreElement = document.getElementById('confidenceScore');
const predictionTextElement = document.getElementById('predictionText');
const switchCameraButton = document.getElementById('switchCameraButton');

let model;
// Estado de la cámara: 'user' para frontal, 'environment' para trasera
let currentFacingMode = 'user';
let isPredicting = false; // Nueva variable para controlar el bucle de predicción

document.getElementById(…): Estas líneas buscan los elementos HTML (el video, el texto de estado, los botones, etc.) y los almacenan en variables para que podamos manipularlos fácilmente con JavaScript.

let model;: Esta variable almacenará el modelo de IA de TensorFlow.js una vez que se haya cargado.

currentFacingMode: Esta variable guarda el estado actual de la cámara (‘user’ para la frontal y ‘environment’ para la trasera).

isPredicting: Es una bandera de control. Su valor (true o false) determina si el bucle de predicción debe ejecutarse o no. Esto es crucial para detener la clasificación cuando se cambia de cámara o si hay un error.

  • Función init()

Esta es la función principal que inicia toda la aplicación. Es el punto de entrada que se llama cuando la página termina de cargar.

async function init() {
try {
statusElement.textContent = 'Solicitando acceso a la cámara...';
await startCamera(currentFacingMode);

statusElement.textContent = 'Cámara lista. Cargando modelo de IA...';
model = await mobilenet.load();

statusElement.textContent = 'Modelo cargado. ¡Clasificando objetos!';
isPredicting = true;
predictionLoop();

} catch (error) {
console.error('Error al inicializar la aplicación:', error);
statusElement.textContent = `Error: No se pudo cargar la cámara. Revisa si diste permiso. (${error.name})`;
}
}

async function init(): La palabra clave async indica que esta función puede realizar operaciones asíncronas, como esperar a que la cámara o el modelo terminen de cargar.

try…catch: Este bloque de código es fundamental para el manejo de errores. Si algo falla durante el proceso (por ejemplo, el usuario niega el permiso de la cámara), el código dentro del bloque catch se ejecutará, evitando que la aplicación se rompa y mostrando un mensaje de error útil.

await startCamera(…): Llama a la función que inicia la cámara y espera a que termine. El programa se «pausa» en esta línea hasta que la cámara esté lista.

model = await mobilenet.load(): Carga el modelo de MobileNet y espera a que esté completamente listo para usarse.

predictionLoop(): Una vez que todo está cargado, esta función se llama para iniciar el proceso de clasificación en bucle.

  • Función startCamera()

Esta función se encarga de obtener el acceso a la cámara del dispositivo.

async function startCamera(facingMode) {
isPredicting = false;
if (videoElement.srcObject) {
videoElement.srcObject.getTracks().forEach(track => track.stop());
}

try {
const stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: facingMode } });
videoElement.srcObject = stream;

await new Promise((resolve) => {
videoElement.addEventListener('loadeddata', () => {
videoElement.play();
const videoRatio = videoElement.videoWidth / videoElement.videoHeight;
videoContainer.style.paddingTop = `${100 / videoRatio}%`;

if (facingMode === 'user') {
videoElement.style.transform = 'scaleX(-1)';
} else {
videoElement.style.transform = 'none';
}
resolve();
}, { once: true });
});

currentFacingMode = facingMode;
if (model) {
isPredicting = true;
predictionLoop();
}
} catch (error) {
console.error('Error al cambiar de cámara:', error);
statusElement.textContent = `Error al cambiar de cámara. (${error.name})`;
}
}

navigator.mediaDevices.getUserMedia(…): Esta es la API del navegador que solicita el stream de video de la cámara. Se le indica qué cámara usar (facingMode).

videoElement.srcObject = stream;: Asigna el stream de video a nuestro elemento <video>.

new Promise((resolve) => { … }): Esta Promesa es una técnica para esperar a que el video termine de cargarse antes de continuar.

videoElement.style.transform = ‘scaleX(-1)’;: Si se usa la cámara frontal, esta línea invierte horizontalmente la imagen para que el video parezca un espejo.

  • Función predictionLoop()

Este es el corazón de la aplicación, donde se produce la clasificación en tiempo real.

async function predictionLoop() {
if (model && isPredicting) {
const predictions = await model.classify(videoElement);

if (predictions && predictions.length > 0) {
const topPrediction = predictions[0];
const className = topPrediction.className;
const confidence = Math.round(topPrediction.probability * 100);

classNameElement.textContent = className;
confidenceScoreElement.textContent = `${confidence}% de confianza`;
predictionTextElement.classList.add('opacity-100');
predictionTextElement.classList.remove('opacity-0');
} else {
predictionTextElement.classList.remove('opacity-100');
predictionTextElement.classList.add('opacity-0');
}
}

requestAnimationFrame(predictionLoop);
}

model.classify(videoElement): Esta es la línea clave donde el modelo de TensorFlow.js analiza el fotograma actual del video y devuelve una lista de predicciones.

predictions[0]: El modelo devuelve las predicciones ordenadas de mayor a menor confianza. [0] siempre nos da la predicción más probable.

className y confidence: Se extrae el nombre de la clase y el porcentaje de confianza para mostrarlos en la pantalla.

requestAnimationFrame(predictionLoop): Esta es la parte más importante para la fluidez. En lugar de usar un bucle infinito que congelaría el navegador, esta función le dice al navegador: «Por favor, vuelve a ejecutar predictionLoop justo antes del próximo repintado de pantalla». Esto asegura que el bucle solo se ejecute cuando el navegador esté listo para renderizar un nuevo fotograma, lo que garantiza un rendimiento óptimo.

  • Event Listeners y Punto de Entrada

Aquí se definen las interacciones del usuario y se inicia la aplicación.

// Event listener para el botón de cambio de cámara
switchCameraButton.addEventListener('click', () => {
const newFacingMode = currentFacingMode === 'user' ? 'environment' : 'user';
startCamera(newFacingMode);
});

// Inicia la aplicación al cargar la página.
window.onload = init;

switchCameraButton.addEventListener(‘click’, …): Este código escucha cuando el usuario hace clic en el botón «Cambiar Cámara». Cuando sucede, cambia el valor de currentFacingMode y llama a la función startCamera() para cambiar la cámara.

window.onload = init;: Esta línea es el punto de partida. Le dice al navegador que, cuando toda la página y sus recursos estén completamente cargados, debe ejecutar la función init(), dando comienzo a toda la aplicación.

Resultados y Pensamientos

El reconocimiento «perfecto» en tiempo real es un desafío incluso para los sistemas de IA más avanzados.

La perfección es muy difícil de alcanzar debido a las variaciones en la iluminación, el ángulo de los objetos, y el ruido en las imágenes.

Sin embargo, podemos mejorar significativamente la precisión y la exactitud de la aplicación. Aquí te explico cómo:

Entrena tu propio modelo especializado
Esta es la forma más efectiva de obtener un reconocimiento preciso. En lugar de usar MobileNet, que está entrenado para 1000 categorías generales, puedes entrenar tu propio modelo con solo las categorías que necesitas (por ejemplo, «perro», «gato», «pelota»).

¿Por qué funciona? Un modelo especializado no tiene que adivinar entre miles de objetos. Se enfoca en aprender las características únicas de las cosas que te importan, lo que lo hace mucho más exacto.

¿Cómo se hace? Se utiliza un proceso llamado transfer learning. Comienzas con un modelo existente (como MobileNet) y lo «re-entrenas» con tus propias imágenes de los objetos que quieres clasificar.

Mejora la calidad de la cámara y del entorno
La calidad del video que la IA recibe tiene un impacto directo en el resultado.

Iluminación: Asegúrate de que los objetos estén bien iluminados. La sombra o la poca luz pueden ocultar detalles cruciales que el modelo necesita para hacer una predicción.

Claridad de la imagen: Evita el desenfoque. Un video nítido le da al modelo más información para trabajar.

Considera modelos más grandes y potentes
Si tu aplicación no necesita ejecutarse en dispositivos móviles y puede usar más recursos, puedes cambiar el modelo por uno más complejo que sea más preciso. Existen modelos de IA más grandes que ofrecen una mayor exactitud, pero a cambio requieren más potencia de procesamiento.

En resumen, la clave no es buscar la perfección, sino la especialización. Al entrenar un modelo con tus propios datos, lograrás que la aplicación reconozca los objetos que te interesan con una precisión mucho mayor y de manera confiable.

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Scroll al inicio
0
Would love your thoughts, please comment.x
()
x