[DISCLAIMER] La idea de este post es que lo entienda toda persona a la que le guste el tema de inteligencia artificial y que los que se dedican específicamente al desarrollo de software puedan también entender y usar el código que utilicé para este experimento. Espero poder cumplir con esas consignas (sino me avisan ;). [/DISCLAIMER]

Resulta que estoy haciendo el curso de Deep Learning para programadores de fast.ai y en la primer semana el ejercicio consiste en probar un script para detectar perros o gatos en diferentes imágenes.

Siempre es bueno aplicar lo que se aprende en un problema personal, por lo que se me ocurrió detectar si cada vehículo que pasa por mi balcón es un taxi o no.

Para aplicar Deep Learning a este problema se necesitan datos, que en este caso serían fotos de la calle sacadas desde mi balcón. Sacar las fotos manualmente no es una opción, ya que se necesitan muchas fotos para entrenar el modelo y no me resultaría muy conveniente estar varias horas haciendo eso.

La solución que se me ocurrió es utilizar un Raspberry Pi y conectarle una cámara web que tenía tirada por ahí. Para el que no sepa, Raspberry Pi prácticamente es una mini computadora con un tamaño similar al de un celular y es muy útil para proyectos como este. La cámara es bastante vieja y tiene mala resolución (640×480) y esto no es conveniente principalmente porque cada foto que captura tiene una cantidad de píxeles muy baja, afectando la precisión del modelo que vamos a entrenar. Pero bueno, es lo que hay por el momento.

El equipo:

Raspberry Pi cuenta con un sistema operativo similar a distribuciones Debian/Ubuntu y por lo tanto puede correr scripts de bash, que es lo que usé para tomar las imágenes:

#webcam.sh

#!/bin/bash DATE=$(date +"%Y-%m-%d_%H%M%S") fswebcam -r 640x480 --no-banner /home/pi/webcam/$DATE.jpg

Este script lo que hace es usar la cámara web para sacar una foto en 640×480 (la resolución máxima de la cámara que usé) y la guarda con la fecha de la captura.

#getpics.sh

#!/bin/bash while true do /home/pi/webcam.sh sleep 5 done

Ahora con este script lo que hacemos es ejecutar el script anterior que toma capturas cada 5 segundos.

$ nohup ./getpics.sh &

Y por último ejecutamos este comando para empezar las capturas.

Una vez capturadas las imágenes lo que hay que hacer es clasificarlas, o sea diferenciar manualmente entre fotos de taxis y fotos de no taxis y ubicar esos archivos en sus respectivas carpetas.

La carpeta “train” tiene que tener dentro las carpetas “notaxi” y “taxi”, y en cada una de esas carpetas deben incluirse las respectivas imágenes. Las imágenes de la carpeta “train” serán las utilizadas para entrenar al modelo de clasificación.

La carpeta “valid” debe cumplir con la misma estructura que la anterior. Las imágenes dentro de esta carpeta serán las utilizadas para validar la precisión del modelo de clasificación entrenado con las imágenes de la carpeta “train”.

Como ven en las imágenes, la cámara está capturando también los autos estacionados, lo que claramente no ayuda al entrenamiento del modelo porque mete ruido innecesario. Una solución muy simple que se puede aplicar es croppear (recortar) las imágenes, en este caso el rectángulo inferior que está molestando.



for i in *.jpg ; do convert -gravity South -chop 0x140 "$i" cropped/"${i%.*}.jpg" ; done



Por cada imagen con extensión “.jpg” que se encuentre en la carpeta desde donde se ejecuta el comando, hacer un recorte de 140 pixeles del eje vertical y guardar en la carpeta “cropped” la nueva imagen recortada.

Ejemplo del antes y después

Antes:

Después:

Y ahora sí, pasamos la etapa tediosa de obtener y limpiar el dataset y estamos listos para entrenar a nuestro modelo detector de taxis.

Para esto voy a utilizar el código del ejercicio del curso que mencioné arriba. Prácticamente usé el mismo código que el del curso, modificando obviamente la carpeta donde están las nuevas fotos. Lo puse todo en un repo para que quede más claro.

(Lo más recomendable es contar con una computadora/servidor con GPU)

En el repositorio hay una breve explicación de que significa cada línea de código y pueden leer algo más detallado directamente en el repositorio original del curso. Como verán si corren el código, el modelo alcanza una precisión bastante alta y este sería el resultado:

¿Qué sigue?

Se me ocurren un par de variantes que se podrían experimentar:

Identificar patrulleros, ambulancias o grúas en lugar de taxis. Esto es un poco más desafiante porque son vehículos que suelen verse con menos frecuencia y por lo tanto es más trabajoso armar el dataset.

Armar un script y correrlo en el Raspberry para enviar un email cada vez que se identifica un taxi, También se podría hacer un contador de taxis por día.

Recursos

Link al repositorio

Link a los datos (imágenes)