Computer Vision: Librerie, Tecniche Avanzate ed Esempi Pratici in Python
- Mattia Gatto
- 6 nov 2024
- Tempo di lettura: 10 min
1.Introduzione alla Computer Vision
La Computer Vision (CV) è una branca dell'intelligenza artificiale (AI) che si concentra sulla comprensione e l'interpretazione delle immagini da parte dei computer. Questo campo mira a fornire alle macchine una "visione" simile a quella umana, che consenta loro di analizzare immagini e video, estrarre informazioni e prendere decisioni automatizzate. Dalla guida autonoma alle diagnosi mediche assistite, la Computer Vision è diventata cruciale in molte applicazioni.

1.1. Le Origini e le Esigenze della Computer Vision
L'evoluzione di questo campo ha portato a complessi algoritmi in grado di riconoscere volti, oggetti e persino di segmentare immagini intere in base a contesti e significati. La segmentazione semantica, il rilevamento di oggetti e il riconoscimento ottico dei caratteri (OCR) sono esempi di problemi risolti quotidianamente grazie alla CV moderna. La crescita esponenziale di dati digitali, unita al progresso nell’hardware e alla disponibilità di librerie, ha permesso ai ricercatori di spingersi verso modelli di deep learning, come le Convolutional Neural Network (CNN), ottimizzati per l’elaborazione delle immagini.
Negli anni '60, la Computer Vision era ancora agli albori e la tecnologia si concentrava su compiti semplici come l'identificazione di forme geometriche di base (ad esempio, cerchi, quadrati e triangoli) all'interno di immagini bidimensionali. Questi primi tentativi utilizzavano algoritmi basati su semplici regole matematiche e tecniche di filtraggio delle immagini piuttosto che su reti neurali o modelli di apprendimento automatico.
Un esempio tipico del riconoscimento delle forme geometriche in quel periodo è il rilevamento dei bordi, utilizzato per evidenziare le linee e i contorni di un'immagine. Una tecnica classica è il filtro di Sobel, sviluppato negli anni '60. Questo filtro analizza i gradienti di intensità nei pixel dell'immagine e li utilizza per individuare cambiamenti rapidi (cioè i bordi) che spesso rappresentano i contorni di oggetti.
1.1.2. Esempio di Rilevamento dei Bordi con il Filtro di Sobel in Python
Oggi, possiamo simulare questo approccio storico utilizzando **OpenCV** per applicare il filtro di Sobel su un’immagine e identificare forme di base. Questo esempio emula i primi tentativi di CV per identificare i contorni e, di conseguenza, le forme all'interno di un’immagine.
1.1.2.1. Codice Esempio ( Python )
import cv2
import numpy as np
import matplotlib.pyplot as plt
# Carica l'immagine in scala di grigi
image = cv2.imread('path_to_image.jpg', cv2.IMREAD_GRAYSCALE)
# Applica il filtro di Sobel per rilevare i bordi in direzione x e y
sobel_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=5) # Gradienti in direzione x
sobel_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=5) # Gradienti in direzione y
# Combina i gradienti per ottenere l'intensità del bordo
edges = cv2.magnitude(sobel_x, sobel_y)
# Mostra i bordi
plt.imshow(edges, cmap='gray')
plt.title("Rilevamento dei Bordi con Filtro di Sobel")
plt.axis('off')
plt.show()
1.1.3. Come Funziona il Filtro di Sobel
Il filtro di Sobel è un operatore di derivata che calcola il gradiente di intensità dell'immagine separatamente nelle direzioni orizzontale (x) e verticale (y). Un cambiamento rapido di intensità in queste direzioni indica la presenza di un bordo. Combinando i gradienti, possiamo ottenere una mappa di bordi che evidenzia i contorni presenti nell'immagine. Negli anni '60, questa tecnica era usata per cercare di "interpretare" i contorni e dedurre forme geometriche di base.
Estensione: Riconoscimento di Forme Geometriche
Con questa mappa di bordi, è possibile utilizzare tecniche aggiuntive per riconoscere forme specifiche. Ad esempio, l'algoritmo di Hough Transform può rilevare linee e cerchi, aiutando a identificare, per esempio, un quadrato (composto da quattro linee) o un cerchio. Negli anni '60, queste tecniche rappresentavano lo stato dell'arte e costituivano la base delle applicazioni più avanzate dell'epoca.
2.Librerie Principali per la Computer Vision in Python
Python è oggi il linguaggio di riferimento per la Computer Vision, grazie alla sua sintassi semplice e alla vasta gamma di librerie:
OpenCV: una delle librerie open-source più complete per l'elaborazione di immagini e video. Supporta una vasta gamma di algoritmi di CV e funzionalità di trasformazione delle immagini.
TensorFlow e Keras: principalmente utilizzate per costruire e addestrare modelli di deep learning, comprese le CNN, con una sintassi intuitiva per costruire reti complesse.
PyTorch: è particolarmente apprezzato per la sua flessibilità e facilità di debug. Viene spesso utilizzato nella ricerca, specialmente in ambienti accademici.
scikit-image: estensione di scikit-learn, offre algoritmi di elaborazione di immagini come filtraggio, segmentazione e trasformazioni.
Tesseract-OCR: sviluppata originariamente da Google, è la libreria principale per estrarre testo da immagini (OCR).
2.1. Reti Neurali Convoluzionali (CNN) e il loro Ruolo nella Computer Vision
Le Convolutional Neural Network (CNN) rappresentano un passo fondamentale nella Computer Vision poiché sono progettate specificamente per elaborare immagini e dati visivi, simulando parzialmente la struttura della corteccia visiva del cervello umano. A differenza delle reti neurali completamente connesse (fully connected), le CNN operano attraverso strati convoluzionali che riducono la complessità dell'elaborazione mantenendo le caratteristiche principali di un'immagine. Questi strati sono composti da filtri o "kernel" che si spostano sull'immagine in modo sequenziale e localizzato, riducendo la dimensione del dato e catturando informazioni essenziali.
2.1.1. Perché usare una CNN rispetto a una rete neurale densa?
Riduzione della Complessità e Sparsità dei Connessioni: Nelle reti neurali completamente connesse, ogni neurone è collegato a tutti i neuroni dello strato successivo, rendendo l'architettura pesante in termini di parametri da addestrare e poco efficiente per immagini di grandi dimensioni. Una CNN, invece, usa piccoli kernel che analizzano solo piccole sezioni di un'immagine per volta. Questo approccio permette di ridurre drasticamente il numero di parametri, rendendo più veloce e meno costoso il processo di addestramento e consentendo alla rete di concentrarsi sulle caratteristiche locali più importanti (ad esempio, bordi o texture) prima di passare alla comprensione delle caratteristiche globali.
Invariabilità Traslazionale: Le CNN sono progettate per riconoscere pattern anche se questi si trovano in posizioni diverse dell'immagine. Questa invariabilità traslazionale è dovuta alla presenza di strati di pooling (solitamente max pooling) che riducono la risoluzione dell'immagine, condensando le informazioni principali. A differenza delle reti dense, le CNN possono quindi riconoscere un oggetto indipendentemente dalla sua posizione nell’immagine, rendendole estremamente efficaci per il riconoscimento di oggetti.
Prestazioni su Immagini e Robustezza alle Variazioni: La struttura locale dei kernel consente alle CNN di apprendere e riconoscere pattern robusti rispetto a variazioni di luminosità, contrasto o altre condizioni ambientali. In pratica, le CNN possono identificare le caratteristiche distintive di un oggetto anche in condizioni diverse da quelle di addestramento, un vantaggio critico per problemi visivi come il riconoscimento facciale o la segmentazione semantica.
2.2. Struttura di una CNN: Strati Principali
Le CNN sono costituite da una serie di strati distinti, ognuno con un ruolo specifico:
Strato Convoluzionale: È lo strato principale, in cui i filtri (kernel) convolvono sull'immagine per estrarre pattern locali, come contorni o texture. Ogni filtro cattura un aspetto diverso dell’immagine.
Strato di Pooling: Dopo la convoluzione, uno strato di pooling riduce la dimensionalità dell'immagine mantenendo le caratteristiche rilevanti. Il Max Pooling, ad esempio, prende il valore massimo da una finestra di pixel, riducendo il numero di parametri e introducendo invariabilità a piccole traslazioni.
Strati Completamente Connessi: Nella parte finale della CNN, uno o più strati completamente connessi aggregano le informazioni estratte dai livelli precedenti e le usano per classificare l'immagine in base alle caratteristiche apprese.
Strato di Attivazione (ReLU): Viene utilizzato dopo ogni strato convoluzionale per introdurre non linearità, fondamentale per apprendere pattern complessi. La funzione di attivazione ReLU (Rectified Linear Unit) è una delle più comuni, che lascia invariati i valori positivi e porta i valori negativi a zero, riducendo così il problema della scomparsa del gradiente.
2.3. Esempio di Applicazione in Python: Classificazione delle Immagini
Utilizziamo Keras con TensorFlow per implementare un semplice modello CNN in grado di classificare immagini. Questo esempio è applicabile a dataset come CIFAR-10, che contiene immagini di oggetti comuni in 10 categorie.
2.3.1.Codice Esempio
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense
# Creazione del modello CNN
model = Sequential([
Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)), # Primo strato convoluzionale
MaxPooling2D(pool_size=(2, 2)), # Primo strato di pooling
Conv2D(64, (3, 3), activation='relu'), # Secondo strato convoluzionale
MaxPooling2D(pool_size=(2, 2)), # Secondo strato di pooling
Flatten(), # Appiattimento
Dense(128, activation='relu'), # Strato completamente connesso
Dense(10, activation='softmax') # Strato di output per classificazione
])
# Compilazione del modello
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# Visualizza l'architettura del modello
model.summary()
In questo modello, abbiamo due strati convoluzionali con dimensioni di kernel di 3x3, ciascuno seguito da uno strato di Max Pooling per ridurre la dimensionalità. Lo strato di appiattimento (Flatten) prepara l'output per gli strati completamente connessi finali, che forniscono la classificazione.
2.3.2. Spiegazione dei Vari Strati del Modello Sequential
Il modello Sequential è una struttura semplice e lineare in Keras, perfetta per costruire modelli "strato per strato". Ecco una descrizione dei vari livelli usati nel modello di esempio:
Conv2D (Strato Convoluzionale): Il primo livello Conv2D applica filtri convoluzionali all'immagine di input per estrarre caratteristiche come bordi e texture. Il parametro (32, (3, 3)) specifica 32 filtri, ciascuno di dimensioni 3x3, che scorreranno su tutta l’immagine (o su una parte della rappresentazione, negli strati successivi). L’attivazione relu introduce non linearità, fondamentale per l'apprendimento di pattern complessi. Il primo strato convoluzionale riceve un input con una forma (32, 32, 3), cioè un’immagine con risoluzione 32x32 pixel e tre canali di colore (RGB).
MaxPooling2D (Strato di Pooling): Subito dopo ogni strato convoluzionale c'è uno strato di pooling, in questo caso MaxPooling2D. Questo livello riduce la dimensionalità dell'immagine, diminuendo la risoluzione spaziale dei dati (preservando però le caratteristiche principali). Usare una finestra di pooling 2x2 consente di ridurre il numero di parametri e il carico computazionale, oltre a rendere il modello più robusto alle traslazioni minori nell’immagine.
Secondo Strato Conv2D e MaxPooling2D: Questa seconda combinazione di Conv2D e MaxPooling2D consente di estrarre caratteristiche ancora più complesse e astratte. Mentre il primo strato può identificare elementi semplici (come bordi), il secondo riesce a riconoscere combinazioni più sofisticate (come parti di oggetti). Aumentare il numero di filtri (64) aiuta il modello a catturare una varietà maggiore di pattern.
Flatten (Appiattimento): Dopo aver passato i dati attraverso strati convoluzionali e di pooling, viene utilizzato lo strato Flatten, che appiattisce l'output tridimensionale degli strati precedenti in un vettore unidimensionale. Questo passaggio è essenziale per collegare l'output delle caratteristiche estratte alla parte finale del modello, ovvero gli strati completamente connessi. L'appiattimento converte la mappa delle caratteristiche in un vettore di input per il livello denso.
Dense (Strato Completamente Connesso): Lo strato Dense è uno strato completamente connesso in cui ogni neurone è collegato a ogni neurone dello strato successivo. Il livello Dense(128, activation='relu') ha 128 neuroni ed è progettato per apprendere combinazioni complesse delle caratteristiche estratte dagli strati precedenti. La funzione di attivazione relu rende il modello in grado di apprendere pattern non lineari.
Strato di Output Dense: L'ultimo strato Dense(10, activation='softmax') ha 10 neuroni, uno per ogni classe del dataset CIFAR-10. La funzione di attivazione softmax converte l’output in probabilità per ciascuna classe, rendendo il modello adatto alla classificazione multiclass. In questo modo, il modello assegna una probabilità a ciascuna delle 10 classi, e la classe con la probabilità più alta rappresenta la previsione del modello per quell’immagine.
Questi strati, combinati in sequenza, permettono al modello di passare dall'elaborazione di caratteristiche basilari alla classificazione finale, rendendo il modello CNN capace di riconoscere e distinguere diverse categorie di immagini.
3.Segmentazione delle Immagini: Un Intuito sui Pixel
La segmentazione è un processo di divisione di un'immagine in regioni o segmenti, associando un'etichetta a ciascun pixel. Esistono due principali tipi di segmentazione:
Segmentazione Semantica: ogni pixel viene assegnato a una classe specifica (ad esempio, cielo, strada, persona), senza distinguere i singoli oggetti.
Segmentazione Instance-based: oltre alla classe, distingue anche tra istanze diverse dello stesso oggetto (ad esempio, due persone diverse).
La segmentazione è cruciale in settori come la diagnostica medica, dove può essere utilizzata per delineare strutture anomale nei tessuti, o nella guida autonoma, per identificare corsie, veicoli e pedoni. Per realizzare una segmentazione accurata, si utilizzano modelli avanzati come le CNN e architetture specializzate come U-Net e VGG-16.

3.1. Esempio di Segmentazione Semantica con CNN e Keras
In questo esempio, costruiremo una CNN di base per la segmentazione utilizzando Keras. Se il nostro obiettivo è segmentare gli oggetti in una scena, useremo una CNN in combinazione con maschere di segmentazione.
3.1.1. Caricamento dell'Immagine e Pre-elaborazione
import cv2
import numpy as np
import matplotlib.pyplot as plt
# Carica e ridimensiona l'immagine
image = cv2.imread('path_to_image.jpg')
image = cv2.resize(image, (128, 128))
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
plt.imshow(image)
plt.title("Immagine originale")
plt.show()
3.1.2. Definizione della CNN per la Segmentazione
La CNN può essere costruita con livelli convoluzionali e di pooling per ridurre la dimensionalità dell’immagine e quindi applicare la segmentazione.
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, UpSampling2D, Input
# Definizione del modello di base
model = Sequential([
Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(128, 128, 3)),
MaxPooling2D((2, 2)),
Conv2D(64, (3, 3), activation='relu', padding='same'),
MaxPooling2D((2, 2)),
Conv2D(128, (3, 3), activation='relu', padding='same'),
UpSampling2D((2, 2)),
Conv2D(64, (3, 3), activation='relu', padding='same'),
UpSampling2D((2, 2)),
Conv2D(3, (3, 3), activation='sigmoid', padding='same')
])
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
model.summary()
Questa rete include passaggi di upsampling e convoluzioni che aiutano a preservare le informazioni spaziali utili per la segmentazione.
3.2. Esempio di OCR Avanzato con Tesseract
Il riconoscimento ottico dei caratteri (OCR) mira a convertire testi in immagini in testo digitale. Usando pytesseract, possiamo estrarre il testo con un semplice script:
import pytesseract
from PIL import Image
# Carica l'immagine contenente testo
img = Image.open('path_to_text_image.jpg')
# Esegui OCR
text = pytesseract.image_to_string(img)
print("Testo Estratto:", text)
Questo codice è utile per applicazioni come la digitalizzazione di documenti o la lettura automatizzata di numeri da fotografie.
3.3. VGG-16 e le sue Varianti: Una Panoramica
La VGG-16 è un'architettura di rete neurale convoluzionale profonda, sviluppata dal Visual Geometry Group (VGG) dell'Università di Oxford, che si è affermata come una delle strutture di riferimento per la classificazione e segmentazione di immagini. La particolarità della VGG-16 risiede nella sua semplicità ed efficacia: è composta da 16 strati di convoluzione e pooling, seguiti da tre strati completamente connessi. Ogni strato convoluzionale utilizza kernel di dimensioni 3x3 e stride (passo) di 1, permettendo di catturare dettagli a diversi livelli di astrazione. Questa configurazione contribuisce a mantenere un’alta risoluzione delle caratteristiche apprese, risultando ideale per compiti che richiedono precisione visiva, come la segmentazione.

3.3.1. Varianti della VGG
Oltre alla VGG-16, esistono altre varianti come:
VGG-11: Una versione più leggera, con meno strati convoluzionali, adatta per applicazioni in cui sono disponibili meno dati di addestramento.
VGG-19: Una versione più profonda rispetto alla VGG-16, con 19 strati convoluzionali, che cattura ancora più dettagli ma richiede maggiore capacità computazionale.
VGG-Face: Un modello specializzato per il riconoscimento facciale, addestrato su immagini di volti umani e ottimizzato per applicazioni di riconoscimento e verifica dell’identità.
3.3.2. Esempio di Utilizzo della VGG-16 per la Segmentazione di Immagini in Python
La VGG-16 può essere impiegata come base per modelli di segmentazione, per esempio utilizzando pre-addestramenti come backbone in un modello U-Net. Grazie alle sue caratteristiche, il modello può essere caricato con pesi pre-addestrati su ImageNet e adattato a scopi di segmentazione fine attraverso l’aggiunta di livelli di upsampling.
Ecco un esempio di come utilizzare VGG-16 come base di una rete di segmentazione:
import tensorflow as tf
from tensorflow.keras.applications import VGG16
from tensorflow.keras.layers import Conv2D, UpSampling2D, concatenate
from tensorflow.keras.models import Model
# Caricamento del modello VGG-16 pre-addestrato
base_model = VGG16(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
# Estrazione delle feature map dal modello base
layer_outputs = [base_model.get_layer(name).output for name in ["block5_conv3", "block4_conv3", "block3_conv3"]]
# Aggiunta dei livelli di upsampling per segmentazione
x = layer_outputs[0]
x = UpSampling2D((2, 2))(x)
x = concatenate([x, layer_outputs[1]])
x = UpSampling2D((2, 2))(x)
x = concatenate([x, layer_outputs[2]])
x = Conv2D(1, (1, 1), activation='sigmoid')(x)
# Creazione del modello finale
segmentation_model = Model(inputs=base_model.input, outputs=x)
# Visualizzazione del modello
segmentation_model.summary()
In questo esempio, la VGG-16 è utilizzata per estrarre caratteristiche visive avanzate dai livelli finali (block5_conv3, block4_conv3, e block3_conv3). Questi strati vengono quindi combinati con operazioni di upsampling e concatenazione per costruire un modello di segmentazione. Questo approccio consente di ottenere una segmentazione dettagliata sfruttando la struttura profonda e accurata della VGG-16.
4.Conclusioni
La Computer Vision ha un impatto significativo su numerosi settori e offre enormi possibilità per innovare. Grazie a strumenti potenti e accessibili come CNN e librerie Python come OpenCV e PyTorch, i data scientist e gli ingegneri possono sviluppare applicazioni complesse che trasformano la percezione visiva delle macchine. La segmentazione, l’OCR e le reti convoluzionali sono solo l'inizio: con il continuo sviluppo della ricerca, il potenziale della CV è praticamente illimitato.
Comentários