Intelligenza artificiale

PYTHON + OPENCV + DEEP NEURAL NETWORKS = OBJECT RECOGNITION

In questo post tratteremo un argomento su cui si sta facendo molta luce ultimamente, grazie alla potenza di calcolo delle CPU/GPU e in generale dei calcolatori nella fascia di mercato consumer/prosumer. Parleremo di Object Recognition su immagini (ma il discorso si può tranquillamente applicare ad un flusso video, con un po’ di accorgimenti anche in tempo reale).

Vi sono più metodi per effettuare il riconoscimento di oggetti in una scena, noi ci concentreremo sull’ultilizzo delle reti neurali, in particolare delle DNN (Deep Neural Network, ovvero Reti Neurali Profonde, o Dense).

Nello specifico, i principali metodi di Object Recognition che utilizzano DNN sono 3:

  1. Faster R-CNNs
  2. YOLO (You Only Look Once)
  3. SSDs (Single Shot Detectors)

Le reti R-CNN (Convoluzionali) probabilmente costituiscono il metodo più “primordiale” mai esistito per l’Object Recognition, ma la learning curve può essere piuttosto ostica per chi si avvicina a questo mondo, soprattutto per quanto rigurda il training del modello. Inoltre, anche lavorando bene ed essendo scrupolosi, le performance dell’algoritmo possono essere piuttosto deludenti (difficilmente si superano i 7 FPS).

YOLO è di gran lunga superiore in termine di performances, può arrivare anche a 155 FPS utilizzando GPU evolute, il suo problema però è l’accuratezza, che lascia molto a desiderare.

SSDs, che è un metodo sviluppato originariamente da Google, fa da anello di congiunzione tra R-CNNs e YOLO, inoltre costituisce un ottimo “entry point” per chi si avvicina al mondo del machine/deep learning. Le sue performances variano dai 22 ai 46 FPS.

Le architetture convenzionali, come VGG o ResNet utilizzano delle pipelines molto “pesanti”, si parla dell’ordine dei 200-500Mb, che non è proprio un vero affare in termini di ottimizzazione (e di performances)

MobileNets (spin-off Google) ci consente invece di semplificare l’ordine delle matrici di analisi, al fine di ottimizzare le performances, utilissimo sui dispositivi mobili dove l’ottimizzazione delle risorse è una keyword sacrosanta (da cui “Mobile”).

MobileNets e la sua pipeline prevedono:

  • Una matrice di convoluzione densa 3×3
  • Un vettore di convoluzione 1×1 (magic happens here)

Questo sacrifica sicuramente l’accuratezza del nostro sistema, che però diventa appannaggio dell’efficienza della nostra infrastruttura, specie su devices con una modesta potenza di calcolo.

UTILIZZARE MOBILENET SSD + MODULO DNN DI OPENCV

Dopo questo “bunch of theory”, passiamo al sodo: utilizzeremo Python, OpenCV ed il suo modulo dnn per creare il nostro Object Detector. In questo articolo utilizzeremo il nostro model (OpenCV supporta modelli pre-trained con Caffe, TensorFlow e PyTorch al momento) di cui il pre-training esula dallo scopo di questo articolo (niente paura: more to come!)

# importo i packages necessari
import numpy as np
import argparse
import cv2



# costruisco l'argument-parsing
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True,
	help="percorso immagine")
ap.add_argument("-p", "--prototxt", required=True,
	help="percorso del file prototxt del modello Caffe")
ap.add_argument("-m", "--model", required=True,
	help="percorso del modello Caffe pre-trained")
ap.add_argument("-c", "--confidence", type=float, default=0.2,
	help="soglia di tolleranza per le predizioni")
args = vars(ap.parse_args())

Nulla di che, ci preoccupiamo di effettuare un paio di import essenziali al nostro scopo e di utilizzare argparse al fine di dotare il nostro script della possibilità di accettare parametri. Un parametro interessante è la “confidence threshold (0.1 ~ 1.0)”, che indica la soglia sotto la quale non terremo conto della predizione effettuata per quel particolare oggetto. in pratica inserendo 0.99 appariranno solo le predizioni degli oggetti delle quali il sistema sarà davvero sicurissimo.

# inizializzo la lista delle classi, modello di esempio MobileNet SSD
# pre-trained da Google
CLASSES = ["background", "aeroplane", "bicycle", "bird", "boat",
	"bottle", "bus", "car", "cat", "chair", "cow", "diningtable",
	"dog", "horse", "motorbike", "person", "pottedplant", "sheep",
	"sofa", "train", "tvmonitor"]
COLORS = np.random.uniform(0, 255, size=(len(CLASSES), 3))

Costruisco lista delle Classi (appartenenti al pre-training effettuato da Google, per velocità di dimostrazione) e dei Colori (apparirà un box colorato che attornerà ogni oggetto detectato). Il codice utilizzato è davvero triviale e penso non necessiti di ulteriori commenti.

# carichiamo il modello dal disco
print("[INFO] carico il modello...")
net = cv2.dnn.readNetFromCaffe(args["prototxt"], args["model"])

Carichiamo il nostro modello dal disco

# carichiamo la nostra immagine e creiamo un blob per la nostra dnn
# effettuiamo un resize 300x300 e normalizziamo
image = cv2.imread(args["image"])
(h, w) = image.shape[:2]
blob = cv2.dnn.blobFromImage(cv2.resize(image, (300, 300)), 0.007843,
	(300, 300), 127.5)

Ci occupiamo di caricare la nostra immagine e di effettuare un Resize (300 * 300) seguito da una normalizzazione, al fine di rendere omogeneo il nostro input con quello che si aspetta la nostra DNN.

A questo punto siamo pronti per effettuare il forward del nostro blob nella rete neurale, al fine di ottenere le predizioni desiderate. Questo passo potrebbe richiedere un po’ di tempo, a seconda della potenza di calcolo dell’elaboratore su cui si esegue lo script.

print("[INFO] eseguo le predizioni...")
net.setInput(blob)
detections = net.forward()

Ora non ci resta che iterare nell’array delle predizioni al fine di determinare quali oggettisono presenti nella scena e dove sono ubicati.

# itero
for i in np.arange(0, detections.shape[2]):
	# estraggo la confidence della predizione i-esima
	confidence = detections[0, 0, i, 2]
 
	# filtro, accettando la predizione se è maggiore 
	# della confidence threshold in input
	if confidence > args["confidence"]:
		# estraggo l'indice della classe dalla lista delle predizioni
		# in più ho cura di salvare le coordinate (x,y)
		# per disegnare un box attorno all'oggetto
		idx = int(detections[0, 0, i, 1])
		box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
		(startX, startY, endX, endY) = box.astype("int")
 
		# stampo la predizione nell'output del terminale
		# e disegno il box attorno all'oggetto
		label = "{}: {:.2f}%".format(CLASSES[idx], confidence * 100)
		print("[INFO] {}".format(label))
		cv2.rectangle(image, (startX, startY), (endX, endY),
			COLORS[idx], 2)
		y = startY - 15 if startY - 15 > 15 else startY + 15
		cv2.putText(image, label, (startX, y),
			cv2.FONT_HERSHEY_SIMPLEX, 0.5, COLORS[idx], 2)

A questo punto, prompto in output l’immagine, provvista di box di predizione attorno.

cv2.imshow("Output", image)
cv2.waitKey(0)

Per eseguire lo script:

$ python object_detection.py \
	--prototxt MobileNetSSD_deploy.prototxt.txt \
	--model MobileNetSSD_deploy.caffemodel --image images/example_01.jpg 
[INFO] carico immagine...
[INFO] carico il modello...
[INFO] effettuo le predizioni...
[INFO] person: 99.82%
[INFO] bottle: 90.85%
</div>



<img class="alignnone size-full wp-image-1072" src="https://mrbildo.devoloop.com/wp-content/uploads/2017/11/Schermata-2017-11-26-alle-23.23.39.png" alt="" width="500" height="386" srcset="https://mrbildo.devoloop.com/wp-content/uploads/2017/11/Schermata-2017-11-26-alle-23.23.39.png 500w, https://mrbildo.devoloop.com/wp-content/uploads/2017/11/Schermata-2017-11-26-alle-23.23.39-300x232.png 300w, https://mrbildo.devoloop.com/wp-content/uploads/2017/11/Schermata-2017-11-26-alle-23.23.39-480x371.png 480w, https://mrbildo.devoloop.com/wp-content/uploads/2017/11/Schermata-2017-11-26-alle-23.23.39-230x178.png 230w, https://mrbildo.devoloop.com/wp-content/uploads/2017/11/Schermata-2017-11-26-alle-23.23.39-350x270.png 350w" sizes="(max-width: 500px) 100vw, 500px" />


 

 

 

 

 

 

 

 

 

Happy Coding!

PYTHON + OPENCV + DEEP NEURAL NETWORKS = OBJECT RECOGNITION ultima modifica: 2017-11-27T16:19:13+00:00 da Mr Bildo
PYTHON + OPENCV + DEEP NEURAL NETWORKS = OBJECT RECOGNITION ultima modifica: 2017-11-27T16:19:13+00:00 da Mr Bildo

Lascia un commento