Hola a todos!
Después de escribir la
primera parte, que no
era muy grave ni particularmente útil en términos prácticos, mi conciencia me tragó un poco. Y decidí terminar lo que comencé. Es decir, elegir la misma implementación de una red neuronal para que se ejecute en Rasperry Pi Zero W en tiempo real (por supuesto, tanto como sea posible en dicho hardware). Para expulsarla de los datos de la vida real e iluminar los resultados en Habré.
Precaución Hay un código viable y algunos gatos más debajo del corte que en la primera parte. En la imagen, cuna y bacalao, respectivamente.
¿Qué red elegir?
Recuerdo que debido a la debilidad del hierro de frambuesa, la elección de las realizaciones de la red neuronal es pequeña. A saber:
1. SqueezeNet.
2. YOLOv3 Tiny.
3. MobileNet.
4. ShuffleNet.
¿Cuán correcta fue la elección a favor de SqueezeNet en la
primera parte ? ... Ejecutar cada una de las redes neuronales mencionadas anteriormente en su hardware es un evento bastante largo. Por lo tanto, atormentado por vagas dudas, decidí buscar en Google si alguien había hecho esa pregunta antes que yo. Resultó que se lo preguntó y lo investigó en detalle. Los que lo deseen pueden consultar la
fuente . Me limitaré a una sola imagen:

De la imagen se deduce que el tiempo de procesamiento para una imagen para diferentes modelos entrenados en el conjunto de datos ImageNet es el menor con SqueezeNet v.1.1. Tomaremos esto como una guía de acción. YOLOv3 no se incluyó en la comparación, pero, por lo que recuerdo, YOLO es más caro que MobileNet. Es decir También debería ser inferior en velocidad a SqueezeNet.
Implementación de la red seleccionada.
Los pesos y la topología de SqueezeNet entrenados en el conjunto de datos ImageNet (marco Caffe) se pueden encontrar en
GitHub . Por si acaso, descargué ambas versiones para que luego se puedan comparar. ¿Por qué ImageNet? Este conjunto de todos los disponibles tiene el número máximo de clases (1000 piezas), por lo que los resultados de la red neuronal prometen ser bastante interesantes.
Esta vez veremos cómo el Raspberry Zero trata con el reconocimiento de fotogramas de la cámara. Aquí está, nuestro humilde trabajador del post de hoy:

Tomé el código fuente del blog de Adrian Rosebrock mencionado en la
primera parte como la base del código, es decir,
de aquí . Pero tuve que ararlo significativamente:
1. Reemplace su modelo con MobileNetSSD en SqueezeNet.
2. La implementación de la Cláusula 1 ha llevado a la expansión del número de clases a 1000. Pero al mismo tiempo, la función de resaltar objetos con marcos multicolores (SSD funcional), por desgracia, se había eliminado.
3. Eliminar la recepción de argumentos a través de la línea de comando (por alguna razón, esa entrada de parámetros me molesta).
4. Elimine el método VideoStream y con él la biblioteca imutils que Adrian ama. Inicialmente, el método se utilizó para obtener la transmisión de video de la cámara. Pero con mi cámara conectada al Raspberry Zero, estúpidamente no funcionó, dando algo así como "instrucción ilegal".
5. Agregue la velocidad de fotogramas (FPS) a la imagen reconocida, vuelva a escribir el cálculo de FPS.
6. Haga marcos de guardado para escribir esta publicación.
En la frambuesa con Rapbian Stretch OS, Python 3.5.3 e instalado a través de pip3 install OpenCV 3.4.1, resultó lo siguiente y comenzó:
Codigo aquiimport picamera from picamera.array import PiRGBArray import numpy as np import time from time import sleep import datetime as dt import cv2
Resultados
El código se muestra en la pantalla del monitor conectado a la Frambuesa, el siguiente marco reconocido en este formulario. En la parte superior del cuadro, solo se muestra la clase más probable.

Entonces, un mouse de computadora fue identificado como un mouse con una probabilidad muy alta. Al mismo tiempo, las imágenes se actualizan a una frecuencia de 0,34 FPS (es decir, aproximadamente cada tres segundos). Es un poco molesto sostener la cámara y esperar a que se procese el siguiente cuadro, pero puedes vivir. Por cierto, si elimina el marco de guardado en la tarjeta SD, la velocidad de procesamiento aumentará a 0.37 ... 0.38 FPS. Seguramente, hay otras formas de dispersarse. Esperaremos y veremos, en cualquier caso, dejaremos esta pregunta para las próximas publicaciones.
Por separado, me disculpo por el balance de blancos. El hecho es que la cámara IR con la luz de fondo encendida estaba conectada a Rapberry, por lo que la mayoría de los cuadros se ven bastante extraños. Pero cuanto más valioso es cada golpe de la red neuronal. Obviamente, el balance de blancos en el conjunto de entrenamiento fue más correcto. Además, decidí insertar solo los cuadros sin formato, para que el lector los vea de la misma manera que ven la red neuronal.
Primero, comparemos el trabajo de SqueezeNet versiones 1.0 (en el marco izquierdo) y 1.1 (en el derecho):

Se puede ver que la versión 1.1 funciona dos veces y cuarto más rápido que 1.0 (0.34 FPS versus 0.15). La ganancia de velocidad es palpable. No vale la pena sacar conclusiones sobre la precisión del reconocimiento en este ejemplo, ya que la precisión depende en gran medida de la posición de la cámara con respecto al objeto, la iluminación, el resplandor, las sombras, etc.
En vista de una ventaja de velocidad tan importante v1.1 sobre v.1.0 en el futuro, solo se utilizó SqueezeNet v.1.1. Para evaluar el rendimiento del modelo, apunté la cámara a varios objetos que
vinieron a la mano y recibí los siguientes cuadros en la salida:

Un teclado es peor que un mouse. Quizás en el conjunto de entrenamiento, la mayoría de los teclados eran blancos.

Un teléfono celular está bastante bien definido si enciende la pantalla. Una celda con una pantalla apagada no cuenta una red neuronal como una celda.

Una taza vacía se define bastante tolerablemente como una taza de café. Hasta ahora, todo va bastante bien.

Las tijeras están peor; la red las define obstinadamente como una pinza para el cabello. Sin embargo, entrar en el manzano si no en la diana)
Vamos a complicar la tarea.
Tratemos de poner algo complicado en la red neuronal del
cerdo . Acabo de encontrar un juguete casero para niños. Creo que la mayoría de los lectores lo reconocen como un gato de juguete. Me pregunto qué será considerado por nuestra rudimentaria inteligencia artificial.

En el marco de la izquierda, la luz IR borró todas las tiras de la tela. Como resultado, el juguete se definió como una máscara de oxígeno con una probabilidad bastante decente. Por que no La forma del juguete realmente se parece a una máscara de oxígeno.
En el marco de la derecha, cubrí mis dedos con un reflector IR, por lo que las rayas aparecieron en el juguete y el balance de blancos se hizo más creíble. En realidad, este es el único marco que se ve más o menos normal en esta publicación. Pero la red neuronal tiene tanta abundancia de detalles en la imagen confundida. Ella identificó el juguete como una sudadera. Debo decir que esto tampoco parece un "dedo en el cielo". Golpea si no está en el "manzano", luego al menos en el huerto de manzanas).
Bueno, nos acercamos sin problemas al clímax de nuestra acción. El ganador destacado de la batalla, consagrado en detalle en el
primer puesto, entra al ring. Y saca fácilmente el cerebro de nuestra red neuronal desde los primeros fotogramas.

Es curioso que un gato prácticamente no cambie su posición, pero cada vez se determina de manera diferente. Y desde esta perspectiva, es más similar a una mofeta. En segundo lugar, se parece a un hámster. Intentemos cambiar el ángulo.

Sí, si fotografias al gato desde arriba, se determina correctamente, pero si cambias un poco la posición del cuerpo del gato en el marco, para la red neuronal se convierte en un perro, del husky siberiano y malamute (perro de trineo esquimal), respectivamente.

Y esta selección es hermosa ya que un perro de diferentes razas se define en cada marco separado de un gato. Y las razas no se repiten)

Por cierto, hay posturas en las que las redes neuronales se hacen obvias de que todavía es un gato, no un perro. Es decir, SqueezeNet v.1.1 todavía logró probarse incluso en un objeto tan difícil de analizar. Dado el éxito de la red neuronal al reconocer objetos al comienzo de la prueba y al reconocer a un gato como un gato al final, esta vez declaramos un sólido empate de combate)
Bueno eso es todo. Invito a todos a probar el código propuesto en su frambuesa y cualquier objeto que haya aparecido en la vista de objetos animados e inanimados. Estaré especialmente agradecido con aquellos que miden el FPS en el Rapberry Pi B +. Prometo incluir los resultados en esta publicación con referencia a la persona que envió los datos. ¡Creo que debería resultar significativamente más de 1 FPS!
Espero que parte de la información de esta publicación sea útil para fines de entretenimiento o educativos, y que alguien incluso pueda tener nuevas ideas.
¡Que tengas una buena semana laboral! Y hasta pronto)

UPD1: en el Raspberry Pi 3B +, el script anterior funciona a una frecuencia de 2 con un pequeño FPS.
UPD2: en RPi 3B + con Movidius NCS, el script se ejecuta a 6 FPS.