En los últimos años, MEO BeachCam ha sido un lugar de referencia para la comunidad surfera. Este sitio web ofrece información detallada sobre el estado del mar, temperaturas y datos sobre las playas, incluyendo la retransmisión de video en tiempo real de distintas playas ubicadas en Portugal y, en menor medida, en España y Francia.

En el contexto actual, provocado por la pandemia global del Covid-19, es necesario mantener las medidas de precaución adecuadas, entre ellas la distancia de seguridad interpersonal, tanto en las playas como en otros espacios públicos.

La Agência Portuguesa do Ambiente (APA) ha decidido promover un proyecto en colaboración con BeachCam para realizar el cálculo de ocupación de las playas de Portugal y proporcionar a los ciudadanos información en tiempo real sobre esta, con el objetivo de evitar aglomeraciones y favorecer la distancia interpersonal en estos espacios.

De esta manera, ha sido posible aprovechar la infraestructura ya desplegada mediante el uso de técnicas de visión artificial y de aprendizaje automático.

Entre los desafíos del proyecto se encontraba el alcance y los plazos de ejecución ya que, planteándose a mediados de junio, se hacía necesario disponer de un modelo en producción que permitiese enviar datos de forma periódica a APA a mediados de julio (en temporada de verano).

Además de esto, ha sido necesario procesar 71 cámaras diferentes que presentan la particularidad de no capturar siempre la misma área de la playa, sino que siguen un recorrido programado, el ángulo de visión de la cámara varía entre unas cámaras y otras, además de poder incluir objetos cercanos o mostrar condiciones climáticas cambiantes.

Procesamiento de las imágenes

En Paradigma tenemos amplia experiencia en el desarrollo de productos digitales en la nube. Después de realizar un pequeño análisis decidimos que, dada la tipología de proyecto, una arquitectura “serverless” encajaría a la perfección y cuadraba, además, con las restricciones de tiempo y las expectativas económicas con respecto a la infraestructura.

Optamos por el stack de tecnologías pertenecientes a Amazon Web Services (AWS), debido a que tiene un buen número de herramientas que permiten desarrollar aplicaciones de forma rápida, favoreciendo la abstracción de todas las tareas de infraestructura y escalabilidad a los desarrolladores.

Además, esta tipología de tecnologías se ofrecen bajo la filosofía de “Function as a service” (FaaS), por lo que las aplicaciones suelen salir a producción bajo un precio muy competitivo.

Para desarrollar la solución se planteó la siguiente arquitectura:

Utilizamos CloudWatch para marcar el inicio del procesamiento que se realiza cada 10 minutos (teniendo una duración media de 10 segundos). Este evento es escuchado por una función lambda, encargada de obtener la configuración de todas las cámaras, mediante el procesamiento de un CSV de configuración.

Para cada configuración existente en el CSV se registra un mensaje en una cola SQS. El objetivo de esta función es el de desencadenar el procesamiento de la ocupación en paralelo para todas las playas.

De la cola SQS de AWS, se encuentra escuchando otra función lambda, responsable de realizar las capturas de las diferentes fotos de las playas, según la configuración asociada.

Por último esta función persiste la foto en un bucket de S3. La forma en que se toman las fotos de las distintas playas está influenciada por la configuración de la cámara.

Una vez persistidas las imágenes de las cámaras en S3, se calcula la ocupación con una nueva función lambda. Esta función escucha eventos producidos en el directorio de S3 donde se almacenan las imágenes, aplicando el modelo de aprendizaje automático.

Finalmente, se realiza una llamada POST, a la API proporcionada por el departamento de medio ambiente de Portugal, con el resultado de la ocupación y el identificador de la playa asociada.

La arquitectura planteada ofrece las ventajas de paralelizar el proceso de cómputo de ocupación y de tolerancia a fallos. Cada mensaje en la cola SQS implica el procesamiento de este con una instancia de la función lambda, encargada de almacenar las fotos en S3.

Si el procesamiento falla, el evento regresa a la cola y lo que desembocará en un nuevo intento, este proceso se repetirá hasta que se logre terminar de procesar o el evento tenga un tiempo de vida superior a 5 minutos, tras el cual se purgará de la cola.

Modelos de Machine Learning

Los modelos de Machine Learning permiten inferir la ocupación en las diferentes imágenes capturadas de las playas. Para hacer uso de estos, se utiliza Python con la librería PyTorch, requiriendo en algunos casos el uso de nVidia CUDA.

Teniendo en cuenta la duración y restricciones del proyecto, se ha optado por utilizar modelos open-source pre-entrenados con datasets públicos y reconocidos por la comunidad, como pueden ser ShanghaiTech, COCO o TinySet.

Después de analizar diferentes técnicas en el estado del arte de recuento de personas en imágenes, se decidió enfocar el proyecto en las dos técnicas más prometedoras, teniendo en cuenta el contexto del problema.

CrowdCounting

Se trata de un modelo de aprendizaje automático basado en redes neuronales convolucionales (CNN) que realiza una partición del espacio supervisada, siguiendo una aproximación basada en “divide y vencerás” (S-DC).

En cada iteración del algoritmo se aplica la extracción de componentes sobre la imagen original y a su vez sobre las diferentes áreas que contengan varias personas hasta alcanzar áreas con ocupación inferior a un número configurable, momento en el cual se aplica el recuento, basado en un modelo de regresión local.

Los resultados parciales de las diferentes áreas son agregados para obtener el recuento global de ocupación en la imagen.

Tras portar el modelo SDC-Net al problema del cálculo de ocupación en playas, se ha observado que este modelo presenta los mejores resultados de error en el recuento para escenarios donde las personas son captadas más de cerca en la imagen.

El resultado de este modelo es un recuento numérico que, extrapolado al problema de ocupación de las playas, es catalogado como alto, medio, o bajo en base a unos umbrales preestablecidos.

TinyPeople

Se trata de un modelo alternativo que aplica también redes neuronales convolucionales (CNN) para la detección de personas en imágenes.

Este modelo está especialmente diseñado para analizar tomas lejanas donde las personas ocupan un área significativamente pequeña en la imagen. Para ello, se hace uso de FPN (feature pyramide networks), donde se busca detectar objetos en una pirámide de imágenes con diferentes escalas de la misma.

Este modelo genera como resultado bounding boxes de las áreas ocupadas por personas en la imagen aunque muestra dificultades cuando aparecen objetos cercanos que pueden ser detectados erróneamente.

Una de las ventajas que presenta este modelo es su auditabilidad, ya que las áreas donde supuestamente se encuentran personas pueden ser representadas sobre la imagen original mediante el uso de OpenCV.

La ocupación de las playas se calcula en este caso como la suma del área ocupada por las diferentes áreas de personas (bounding boxes) sobre el área total.

Se han estudiado algunas posibles optimizaciones para este modelo entre las que se incluye descartar cajas demasiado grandes que puedan ser debidas a objetos cercanos mal interpretados (comparando el área de cada caja con el área mediana y filtrando las que excedan determinados umbrales) o descontar el área ocupada por el mar del área total de la foto para intentar estandarizar el cálculo de ocupación, en un entorno donde la proporción de la playa en la imagen completa puede variar.

Área de la playa

Determinar el área de la playa en las imágenes es importante para poder calcular la ocupación relativa (área ocupada/área disponible).

La función inRange de OpenCV permite filtrar pixels de la imagen cuyos valores HSV se encuentren en un determinado rango de colores. Aplicando una máscara es posible conocer la proporción que ocupa el agua sobre el área total.

# Read image in HSV format
hsv_img = cv.imread(beach_location, cv.COLOR_RGB2HSV)

# Mask for blue colors (sea/sky)
blue0 = np.array([175, 50, 2])
blue1 = np.array([255, 255, 255])
mask_blue = cv.inRange(hsv_img, blue0, blue1)

# Mask covering all colors
mask_total = cv.inRange(hsv_img, np.array([0, 0, 0]), np.array([255, 255, 255]))

sea_area = cv.countNonZero(mask_blue)
t_area = cv.countNonZero(mask_total)

total_area = (img.shape[1] * img.shape[0])
valid_area = (t_area - sea_area) / t_area

print(f"Valid area = {valid_area}")
Valid area = 0.481160714285714
Valid area = 0.481160714285714

Determinar el rango de colores es importante ya que, según las condiciones climáticas, el color del mar y el cielo pueden variar entre colores verdosos, azules vivos o grisáceos.

Originalmente se planteó utilizar esta técnica para contar la cantidad de pixels de arena como un indicador de ocupación aunque, después de analizar esta alternativa en diferentes escenarios, se ha comprobado que no generaliza demasiado bien, aunque puede ayudar a ponderar el área total de la imagen como complemento a otras alternativas como las ya mencionadas.

Monitorización

Se utilizan los paneles de Cloudwatch para verificar los datos del recuento de ocupación y estado enviados a APA. De esta manera, se permite analizar de forma interactiva los logs de la función lambda de cálculo de ocupación, recogiendo los datos en el rango de fechas establecido por el usuario.

La ocupación de las playas va evolucionando a lo largo del día entre los valores bajo, medio y alto según los datos proporcionados por el modelo de Machine Learning.

Conclusiones

Después de realizar pruebas con ambos modelos de recuento de personas, se ha optado por poner en producción el modelo de CrowdCounting, ya que encaja mejor con la arquitectura del sistema que se planteó originalmente.

En el caso del modelo de TinyPeople, la necesidad de disponer de una máquina con tecnología CUDA para poder aplicar la inferencia sobre las imágenes, ha implicado el uso de una máquina EC2 dedicada cuyo coste es significativamente más elevado que el de las funciones lambda de AWS.

Como posible continuación del proyecto, se plantea la posibilidad de integrar este desarrollo mediante el uso de un microservicio Flask que fuese implementado en la máquina EC2, permitiendo la generación de predicciones de ocupación bajo demanda sobre imágenes enviadas desde la función lambda de cálculo de ocupación, combinando los resultados de ambos modelos para realizar las predicciones de ocupación.

Ambos modelos presentan ventajas y desventajas. Utilizándolos en el contexto adecuado permiten realizar el cálculo de ocupación de las playas que, integrado con APA ayudará a proporcionar información actualizada a los ciudadanos, para que estos puedan disfrutar de las playas con seguridad.

Referencias

BeachCams

CrowdCounting (S-DCNet)

TinyBenchmark

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete

Estamos comprometidos.

Tecnología, personas e impacto positivo.