Ho provato ad integrare il modello dei rifiuti su spiaggia visto qui e qui in Tensorflow lite per girare su Coral Mini Dev Board (basato su questo esempio)
Per prima cosa ho scaricato i dati in formato Pascal VOC (quindi con le annotations in formato xml)
L'albero dei folder e' del tipo
--------------------------------------------------------------------------
dataset
-train
--images (solo jpg)
--annotations (solo xml)
-test
--images
--annotations
-validation
--images
--annotations
--------------------------------------------------------------------------
Per questo motivo ho dovuto dividere i file rispetto al file zip scaricato da roboflow sono xml e jpg sono tutti nello stesso folder
Per fare il retrain ho usato il TF Lite Model Maker . Il problema e' che non ne vuole sapere di girare in Colab ed ho tirato su un Docker con il seguente Dockerfile
Inoltre TF Lite Model Maker effettua il retrain di modelli destinati a funzionare on edge e su mobile, in particolare usando EffiecientDet Lite
--------------------------------------------------------------------------
FROM tensorflow/tensorflow:2.13.0-gpu
RUN apt-get update && \
apt-get install -y libusb-1.0-0 libusb-1.0-0-dev
RUN pip install tflite-model-maker
RUN pip install pycocotools
--------------------------------------------------------------------------
lanciandolo con il comando
docker build -t litegpu .
docker run --gpus all -it -p -v $PWD:/tmp -w /tmp litegpu bash
A questo punto si passa alla creazione vera e propria del modello con lo script python. Rispetto all'esempio di Colab, ho dovuto abbassare la batch size a 2 e rimuovere la validazione del modello altrimenti lo script satura tutta la memoria GPU
--------------------------------------------------------------------------
import numpy as np
import os
from tflite_model_maker.config import ExportFormat
from tflite_model_maker import model_spec
from tflite_model_maker import object_detector
import tensorflow as tf
assert tf.__version__.startswith('2')
tf.get_logger().setLevel('ERROR')
from absl import logging
logging.set_verbosity(logging.ERROR)
label_map = {1: 'Glass', 2: 'Metal',3: 'Net',4: 'null',5: 'PET_Bottle',6: 'Plastic_Buoy',7: 'Plastic_Buoy_China',8: 'Plastic_ETC',9: 'Rope',10: 'Styrofoam_Box',11: 'Styrofoam_Buoy',12: 'Styrofoam_Piece'}
train_images_dir = 'dataset/train/images'
train_annotations_dir = 'dataset/train/annotations'
val_images_dir = 'dataset/validation/images'
val_annotations_dir = 'dataset/validation/annotations'
test_images_dir = 'dataset/test/images'
test_annotations_dir = 'dataset/test/annotations'
train_data = object_detector.DataLoader.from_pascal_voc(train_images_dir, train_annotations_dir, label_map=label_map)
validation_data = object_detector.DataLoader.from_pascal_voc(val_images_dir, val_annotations_dir, label_map=label_map)
test_data = object_detector.DataLoader.from_pascal_voc(test_images_dir, test_annotations_dir, label_map=label_map)
print(f'train count: {len(train_data)}')
print(f'validation count: {len(validation_data)}')
print(f'test count: {len(test_data)}')
spec = object_detector.EfficientDetLite0Spec()
model = object_detector.create(train_data=train_data,
model_spec=spec,
validation_data=validation_data,
epochs=10,
batch_size=2,
train_whole_model=True)
#model.evaluate(test_data)
TFLITE_FILENAME = 'efficientdet-lite-litter.tflite'
LABELS_FILENAME = 'litter-labels.txt'
model.export(export_dir='.', tflite_filename=TFLITE_FILENAME, label_filename=LABELS_FILENAME,
export_format=[ExportFormat.TFLITE, ExportFormat.LABEL])
model.evaluate_tflite(TFLITE_FILENAME, test_data)
--------------------------------------------------------------------------
con risultato finale
659 - loss: 0.8730 - learning_rate: 2.5257e-05 - gradient_norm: 5.0130 - val_det_loss: 0.6480 - val_cls_loss: 0.3706 - val_box_loss: 0.0055 - val_reg_l2_loss: 0.0659 - val_loss: 0.7139
Si potrebbe anche usare il modello 1 cambiando la linea
spec = object_detector.EfficientDetLite1Spec()
ma la mia scheda grafica non ha abbastanza memoria
Per verificare se il modello funziona si puo' all'interno del docker installare tramite pip
python3 -m pip install --extra-index-url https://google-coral.github.io/py-repo/ pycoral
e poi lanciare il comando lo script
--------------------------------------------------------------------------
from PIL import ImageDraw
from PIL import ImageFont
import PIL
import tflite_runtime.interpreter as tflite
from pycoral.adapters import common
from pycoral.adapters import detect
from pycoral.utils.dataset import read_label_file
def draw_objects(draw, objs, scale_factor, labels):
"""Draws the bounding box and label for each object."""
COLORS = np.random.randint(0, 255, size=(len(labels), 3), dtype=np.uint8)
for obj in objs:
bbox = obj.bbox
color = tuple(int(c) for c in COLORS[obj.id])
draw.rectangle([(bbox.xmin * scale_factor, bbox.ymin * scale_factor),
(bbox.xmax * scale_factor, bbox.ymax * scale_factor)],
outline=color, width=3)
font = ImageFont.truetype("LiberationSans-Regular.ttf", size=15)
draw.text((bbox.xmin * scale_factor + 4, bbox.ymin * scale_factor + 4),
'%s\n%.2f' % (labels.get(obj.id, obj.id), obj.score),
fill=color, font=font)
# Load the TF Lite model
labels = read_label_file('./e0/litter-labels.txt')
interpreter = tflite.Interpreter('./e0/efficientdet-lite-litter.tflite')
interpreter.allocate_tensors()
# Resize the image for input
image = Image.open('./e0/1.jpg')
_, scale = common.set_resized_input(
interpreter, image.size, lambda size: image.resize(size, PIL.Image.Resampling.LANCZOS))
# Run inference
interpreter.invoke()
objs = detect.get_objects(interpreter, score_threshold=0.4, image_scale=scale)
# Resize again to a reasonable size for display
display_width = 500
scale_factor = display_width / image.width
height_ratio = image.height / image.width
image = image.resize((display_width, int(display_width * height_ratio)))
draw_objects(ImageDraw.Draw(image), objs, scale_factor, labels)
image.save("output.jpg")
--------------------------------------------------------------------------
il risultato e' l'immagine di apertura del post
A questo punto si compilano i modelli per poter girare su Coral Dev Mini Board installando il compilatore sul PC
wget -O- https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/coral-edgetpu.gpg
apt-get update
apt-get install edgetpu-compiler
e poi lanciando la compilazione con
edgetpu_compiler efficientdet-lite-litter.tflite -d --num_segments=1
a questo punto si copiano i file del modello sulla Dev Board
scp efficientdet-lite-litter_edgetpu.tflite mendel@192.168.100.2:/home/mendel
e si lancia
python3 detect_image.py --model efficientdet-lite-litter_edgetpu.tflite --labels litter-labels.txt --input CD_10196_jpg.rf.4a2b1adf824f2a18a7eea764b9012f36.jpg --output output.jpg
----INFERENCE TIME----
Note: The first inference is slow because it includes loading the model into Edge TPU memory.
347.37 ms
182.40 ms
181.49 ms
178.24 ms
182.33 ms
-------RESULTS--------
Styrofoam_Piece
id: 11
score: 0.453125
bbox: BBox(xmin=248, ymin=132, xmax=279, ymax=171)
PET_Bottle
id: 4
score: 0.4375
bbox: BBox(xmin=274, ymin=206, xmax=299, ymax=246)
Attenzione che la versione del runtime del compilatore deve essere compatibile con le librerie sulla Dev Board. In una prima prova avevo avuto l'errore
RuntimeError: Failed to prepare for TPU. Failed precondition: Package
requires runtime version (14), which is newer than this runtime version
(13).Node number 7 (EdgeTpuDelegateForCustomOp) failed to prepare.
ed infatti il comando edgetpu_compiler --version rispondeva
Edge TPU Compiler version 16.0.384591198
mentre la runtime version era
python3 -c "import pycoral.utils.edgetpu; print(pycoral.utils.edgetpu.get_runtime_version())"
BuildLabel(COMPILER=6.3.0 20170516,DATE=redacted,TIME=redacted), RuntimeVersion(13)
Questo era dovuto al fatto che apt non scaricava gli aggiornamenti a causa della firma GPG scaduta dei repository Google Coral
Il problema si e' risolto con
wget -O- https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/coral-edgetpu.gpg