Uso de TensorFlow Lite con Google Coral TPU en Raspberry Pi 4

Las aplicaciones que utilizan el aprendizaje automático suelen requerir una gran potencia informática. Los cálculos suelen tener lugar en la GPU de la tarjeta gráfica. El Raspberry Pi no está necesariamente diseñado para ejecutar aplicaciones de computación intensiva. ¡El acelerador USB Coral de Google proporciona ayuda aquí! Con la ayuda de este dispositivo, podemos usar cálculos en tiempo real como el reconocimiento de objetos en videos.

En este tutorial, veremos cómo podemos integrar y usar Google Coral en Raspberry Pi. Luego crearemos la detección de objetos en vivo en una transmisión de video desde la cámara Raspberry Pi.

Acelerador USB Coral

Piezas de hardware requeridas

He usado las siguientes partes de hardware en este tutorial. Muchos de los componentes que ya hemos usado en tutoriales anteriores.

  • raspberry pi
  • Edge TPU: Acelerador USB Google Coral
  • Módulo de cámara oficial de Raspberry Pi
  • Objetos simples para el reconocimiento (objetos de oficina, frutas, etc.)
  • Óptimo: un estuche con enfriadores para Pi y el acelerador USB (también se puede imprimir en 3D).

El acelerador USB Google Coral es más pequeño que el Raspberry Pi 4 y debe conectarse a través del puerto USB 3.0.

¿Para qué se utiliza el acelerador USB Google Coral?

El acelerador USB Coral de Google contiene un procesador especializado para cálculos en redes neuronales. Este procesador se llama Edge-TPU (Unidad de procesamiento de tensor).

En el siguiente video se puede encontrar una muy buena explicación de las redes neuronales, qué son exactamente y por qué lee sobre ellas con tanta frecuencia en relación con el aprendizaje automático:

Entonces, una de las tareas principales es resolver estas redes neuronales (en forma de matrices) y esto se hace particularmente bien con Edge TPU. Google proporciona bibliotecas especiales para que podamos beneficiarnos de las propiedades del Acelerador Coral USB.

Instalación de TPU de Google Coral Edge en Raspberry Pi

Entonces, para usar el poder de procesamiento de Coral Edge TPU, necesitamos instalar algunos paquetes. Para ello, seguimos principalmente los pasos de la web de la TPU. Para hacer esto, abra una terminal (o conéctese a través de SSH) y escriba lo siguiente:

echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | sudo tee /etc/apt/sources.list.d/coral-edgetpu.list curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - sudo apt-get update

Después de eso, podemos instalar Edge TPU Runtime:

sudo apt-get install libedgetpu1-std

Nota: si desea instalar un tiempo de ejecución «más rápido» (es decir, con mayor frecuencia), use este comando en su lugar: sudo apt-get install libedgetpu1-max Tenga en cuenta, sin embargo, que no debe tener ambas versiones instaladas al mismo tiempo. Además, la temperatura de funcionamiento aumentará con la variante de mayor frecuencia, por lo que solo debe usarla con una refrigeración suficientemente buena.

Después de la instalación, puede conectar el Acelerador USB a la Raspberry Pi (preferiblemente a un puerto USB 3.0 azul). Si ya estaba conectado antes de la instalación, retírelo brevemente y vuelva a conectarlo.

Ahora instalamos los paquetes de Python. El siguiente comando es suficiente para esto:

sudo apt-get install python3-pycoral  --yes

Instalación de TensorFlow Lite

También necesitaremos TensorFlow Lite. Primero, comprobamos la versión:

pip3 show tflite_runtime

Para mí, el resultado se ve así:

Name: tflite-runtime Version: 2.5.0 Summary: TensorFlow Lite is for mobile and embedded devices. Home-page: https://www.tensorflow.org/lite/ Author: Google, LLC Author-email: packages@tensorflow.org License: Apache 2.0 Location: /usr/lib/python3/dist-packages Requires: Required-by: pycoral

Si aún no ha instalado TensorFlow, puede hacerlo de la siguiente manera y luego ejecutar el comando nuevamente:

echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | sudo tee /etc/apt/sources.list.d/coral-edgetpu.list curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - sudo apt-get update sudo apt-get install python3-tflite-runtime

Reconocimiento de objetos en videos usando Google Coral y Raspberry Pi Camera

A continuación, nos gustaría activar la detección de objetos en vivo en una transmisión de video. Los cálculos se ejecutan en Edge TPU. Para mostrar la imagen, tenemos varias opciones. Podemos usar por ejemplo paquetes como PyGame, PiCamera u OpenCV. Prefiero OpenCV porque nos permite usar muchas más funciones del campo de la visión artificial.

En primer lugar, conectamos la cámara Raspberry Pi a través de CSI o una cámara web a través de USB. La mayoría de las cámaras web se detectan automáticamente.

Entonces, comencemos con un proyecto de muestra. Abre la terminal de nuevo:

mkdir google-coral && cd google-coral git clone https://github.com/google-coral/examples-camera --depth 1

En el siguiente paso, cargamos los modelos pre-entrenados. En su lugar, también puede utilizar sus propios modelos entrenados. En nuestro ejemplo simple, sin embargo, cargamos solo el modelo MobileNet SSD300, que ya puede reconocer muchos objetos.

cd examples-camera sh download_models.sh

El proceso tarda unos minutos. Después de eso, cambiamos a la carpeta OpenCV e instalamos las dependencias (si quieres usar otro ejemplo, tienes la posibilidad aquí).

cd opencv bash install_requirements.sh

Ahora podemos iniciar la aplicación de muestra. Necesita un entorno de escritorio para esto. Si no está trabajando directamente en Raspberry Pi, le recomiendo una conexión de escritorio remoto.

python3 detect.py

Esto abre una nueva ventana con la transmisión de video. En él, los objetos detectados están marcados con rectángulos. También puede ver la probabilidad calculada (en porcentaje) con la que se detectó el objeto (la probabilidad de que sea este objeto, según el algoritmo).

Ahora echemos un vistazo más de cerca al código para entender lo que sucede:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

dieciséis

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

sesenta y cinco

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

# Derechos de autor 2019 Google LLC

#

# Con licencia de Apache License, Versión 2.0 (la «Licencia»);

# no puede usar este archivo excepto de conformidad con la Licencia.

# Puede obtener una copia de la Licencia en

#

# https://www.apache.org/licenses/LICENSE-2.0

#

# A menos que lo exija la ley aplicable o se acuerde por escrito, el software

# distribuido bajo la Licencia se distribuye «TAL CUAL»,

# SIN GARANTÍAS NI CONDICIONES DE NINGÚN TIPO, ya sean expresas o implícitas.

# Consulte la Licencia para conocer el idioma específico que rige los permisos y

# limitaciones bajo la Licencia.

«»»Una demostración que ejecuta la detección de objetos en marcos de cámara usando OpenCV.

TEST_DATA=../todos_los_modelos

Ejecutar modelo de detección de rostros:

python3 detectar.py

–modelo €{TEST_DATA}/mobilenet_ssd_v2_face_quant_postprocess_edgetpu.tflite

Ejecutar coco modelo:

python3 detectar.py

–model €{TEST_DATA}/mobilenet_ssd_v2_coco_quant_postprocess_edgetpu.tflite

–etiquetas €{TEST_DATA}/coco_labels.txt

«»»

importar análisis de argumentos

importar cv2

importar sistema operativo

de pycoral.adapters.common import input_size

de pycoral.adapters.detect importar get_objects

desde pycoral.utils.dataset import read_label_file

desde pycoral.utils.edgetpu importar make_interpreter

de pycoral.utils.edgetpu importar run_inference

def principal():

default_model_dir = ‘../todos_los_modelos’

modelo_predeterminado = ‘mobilenet_ssd_v2_coco_quant_postprocess_edgepu.tflite’

etiquetas_predeterminadas = ‘etiquetas_de_coco.txt’

analizador = argparse.ArgumentParser()

parser.add_argument(‘–model’, help=’.tflite model path’,

default=os.path.join(dir_modelo_predeterminado, modelo_predeterminado))

parser.add_argument(‘–labels’, help=’ruta del archivo de etiquetas’,

default=os.path.join(dir_modelo_predeterminado, etiquetas_predeterminadas))

analizador.add_argument(‘–top_k’, type=int, default=3,

help=’número de categorías con la puntuación más alta para mostrar’)

parser.add_argument(‘–camera_idx’, type=int, help=’Índice de qué fuente de video usar.’, predeterminado = 0)

parser.add_argument(‘–threshold’, type=float, default=0.1,

help=’umbral de puntuación del clasificador’)

argumentos = analizador.parse_args()

print(‘Cargando {} con {} etiquetas.’.format(args.model, args.labels))

interprete = make_interpreter(args.modelo)

intérprete.asignar_tensores()

etiquetas = read_label_file(args.labels)

tamaño_inferencia = tamaño_entrada(intérprete)

tapa = cv2.VideoCapture(args.camera_idx)

mientras que cap.isOpened():

ret, cuadro = cap.read()

si no ret:

descanso

cv2_im = cuadro

cv2_im_rgb = cv2.cvtColor(cv2_im, cv2.COLOR_BGR2RGB)

cv2_im_rgb = cv2.resize(cv2_im_rgb, inference_size)

run_inference(intérprete, cv2_im_rgb.tobytes())

objs = get_objects(intérprete, args.threshold)[:args.top_k]

cv2_im = append_objs_to_img(cv2_im, tamaño_inferencia, objs, etiquetas)

cv2.imshow(‘marco’, cv2_im)

si cv2.waitKey(1) & 0xFF == ord(‘q’):

descanso

cap.liberar()

cv2.destroyAllWindows()

def append_objs_to_img(cv2_im, inference_size, objs, etiquetas):

alto, ancho, canales = cv2_im.shape

scale_x, scale_y = ancho / inference_size[0]altura / inference_size[1]

para obj en objs:

bbox = obj.bbox.escala(escala_x, escala_y)

x0, y0 = int(bbox.xmin), int(bbox.ymin)

x1, y1 = int(bbox.xmax), int(bbox.ymax)

porcentaje = int(100 * puntuación obj.)

etiqueta = ‘{}% {}’.format(porcentaje, etiquetas.obtener(obj.id, obj.id))

cv2_im = cv2.rectangle(cv2_im, (x0, y0), (x1, y1), (0, 255, 0), 2)

cv2_im = cv2.putText(cv2_im, etiqueta, (x0, y0+30),

cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 2)

devolver cv2_im

si __nombre__ == ‘__principal__’:

principal()

  • En primer lugar, se incluyen las bibliotecas PyCoral requeridas.
  • En la función principal, se definen argumentos que se pueden pasar desde la línea de comando (especificando el modelo, etc.)
  • El modelo se carga con sus etiquetas y las dimensiones se determinan en función del modelo (aquí: 300×300)
  • Luego se abrirá la transmisión de video (cap = cv2.VideoCapture(args.camera_idx))
  • La parte interesante sucede aquí:
    objs = get_objects(interpreter, args.threshold)[:args.top_k]

    Los 3 elementos con el “puntaje de clasificación” más alto (por encima de un valor umbral) se determinan en el proceso.

  • Posteriormente, cada objeto detectado se marca en la imagen.

Respondiendo a Objetos Específicos

¿Qué hacemos ahora si queremos desencadenar una acción tan pronto como un determinado objeto ha sido detectado (por ejemplo, una persona)?

Para hacer esto, primero echemos un vistazo al valor de retorno de la get_objects función:

[   Object(id=16, score=0.5, bbox=BBox(xmin=-2, ymin=102, xmax=158, ymax=296)),    Object(id=0, score=0.16015625, bbox=BBox(xmin=6, ymin=114, xmax=270, ymax=300)),    Object(id=61, score=0.12109375, bbox=BBox(xmin=245, ymin=166, xmax=301, ymax=302)) ]

Vemos que cada objeto detectado contiene una identificación, una puntuación y un cuadro delimitador con coordenadas. Para determinar qué objeto se detectó, echamos un vistazo a las etiquetas:

{0: 'person', 1: 'bicycle', 2: 'car', 3: 'motorcycle', 4: 'airplane', 5: 'bus',  6: 'train', 7: 'truck', 8: 'boat', 9: 'traffic light', 10: 'fire hydrant', 1 2: 'stop sign', 13: 'parking meter', 14: 'bench', 15: 'bird', 16: 'cat', 17: 'dog',  18: 'horse', 19: 'sheep', 20: 'cow', 21: 'elephant', 22: 'bear', 23: 'zebra',  24: 'giraffe', 26: 'backpack', 27: 'umbrella', 30: 'handbag', 31: 'tie',  32: 'suitcase', 33: 'frisbee',  34: 'skis', 35: 'snowboard', 36: 'sports ball',  37: 'kite', 38: 'baseball bat', 39: 'baseball glove', 40: 'skateboard',  41: 'surfboard', 42: 'tennis racket', 43: 'bottle', 45: 'wine glass', 46: 'cup',  47: 'fork', 48: 'knife', 49: 'spoon', 50: 'bowl', 51: 'banana', 52: 'apple',  53: 'sandwich', 54: 'orange', 55: 'broccoli', 56: 'carrot', 57: 'hot dog',  58: 'pizza', 59: 'donut', 60: 'cake', 61: 'chair', 62: 'couch', 63: 'potted plant',  64: 'bed', 66: 'dining table', 69: 'toilet', 71: 'tv', 72: 'laptop', 73: 'mouse',  74: 'remote', 75: 'keyboard', 76: 'cell phone', 77: 'microwave', 78: 'oven',  79: 'toaster', 80: 'sink', 81: 'refrigerator', 83: 'book', 84: 'clock', 85: 'vase',  86: 'scissors', 87: 'teddy bear', 88: 'hair drier', 89: 'toothbrush'}

Entonces, en mi caso, se reconocieron los objetos Gato (id=16), Persona (id=0) y Silla (id=61).

En caso de que se esté preguntando de dónde provienen todas las etiquetas: estas fueron entrenadas en el modelo y, por lo tanto, están incluidas. Si crea su propio modelo, también puede incluir solo uno o solo algunos objetos que sean importantes para usted. También sería posible, por ejemplo, reconocer su propia cara.

Si está interesado en un tutorial sobre cómo entrenar un modelo de este tipo en Raspberry Pi con el acelerador USB Google Coral, no dude en preguntar al respecto en los comentarios.

En el ejemplo anterior, queremos activar una acción tan pronto como se detecte un determinado objeto (por ejemplo, un bus con ID=5). Para ello, primero buscamos el ID. A continuación, debemos verificar si se encontró un objeto con esta ID. También podemos agregar un valor de umbral (por ejemplo, 0,8) para la puntuación. El pseudocódigo se vería así:

found_scores = [o.score for o in objs if o.id == 5] if len(found_scores) > 0 and max(found_scores) >= 0.8:   # do something

Como ves, reaccionar es muy sencillo. Después de eso, podemos guardar la foto, por ejemplo.

Conclusión

El Edge TPU de Google ofrece una gran oportunidad para todos aquellos para los que la capacidad de cómputo de la Raspberry Pi no es suficiente. El acelerador USB también es muy económico en comparación con las tarjetas gráficas de gama alta. Estos cuestan más de mil euros en promedio.

La detección de objetos funciona muy bien con una resolución de 300x300px. También es posible una resolución más alta, pero hay que prestar atención a la temperatura del dispositivo. Recomiendo un ventilador adicional para un funcionamiento continuo.

Google también ofrece otros repositorios con contenido de aprendizaje. Para otros casos de uso con Coral, este repositorio sigue siendo interesante y, entre otras cosas, está equipado con ejemplos para el reconocimiento de imágenes.

Por cierto, también podemos crear nuestro propio modelo de reconocimiento de objetos con TensorFlow. Para esto, primero debemos anotar las imágenes y luego entrenar un modelo. Si está interesado, un tutorial seguirá en el futuro.

¿Qué otras aplicaciones de aprendizaje automático y casos de uso le interesan? Había pensado en proyectos como el reconocimiento automático de matrículas y similares, pero estoy ansioso por escuchar más sugerencias creativas para Raspberry Pi con Google Coral TPU.