OpenCV & Python – Image Thresholding

OpenCV & Python - Image Thresholding header

Tra le tecniche fondamentali dell’elaborazione delle immagini nel’Image Analysis vi è l’Image Thresholding. Questa tecnica elabora un’immagine in scala di grigi suddividendola in due aree: una bianca e una nera. Quali parti dell’immagine dovranno essere bianche o nere, dipenderanno da una serie di fattori, più o meno complessi a seconda della tecnica, tutti basati su un valore di soglia.

L’image Threasholding

L’Image Thresholding è una tecnica di elaborazione delle immagini che viene spesso utilizzata per convertire un’immagine in scala di grigi in un’immagine binaria. L’obiettivo è quello di separare l’immagine in regioni con intensità luminosa alta e bassa. Questo processo è utile in molte applicazioni, come il rilevamento di contorni, la segmentazione di oggetti e l’estrazione di caratteristiche.

Esistono diverse tecniche per applicare l’Image Thresholding. In questo articolo ne vedremo due:

  • Simple Thresholding
  • Adaptive Thresholding

che rappresentano degli ottimi esempi per comprendere al meglio questa tecnica. Alla fine vedremo un elenco di altre tecniche che effettuano l’Image Thresholding, con alcuni articoli di approfondimento dove potrete consultarle in dettaglio.

Simple Thresholding

Il Simple Thresholding è il metodo più diretto di image thresholding, in cui si fissa un valore soglia e i pixel dell’immagine che hanno intensità superiore a tale valore vengono considerati bianchi, mentre quelli inferiori diventano neri. Questo approccio è particolarmente utile quando l’immagine ha un buon contrasto e la distribuzione dei livelli di grigio è chiara.

La teoria di Simple Thresholding coinvolge alcuni concetti matematici di base. L’idea fondamentale è che si sceglie un valore soglia (T) e si classificano i pixel dell’immagine in due categorie: quelli al di sopra del valore soglia e quelli al di sotto del valore soglia.

L’immagine originale è rappresentata come una matrice di pixel, ognuno dei quali ha un valore di intensità luminosa (grigio) che può variare da 0 a 255. Un’immagine in scala di grigi può essere rappresentata come una funzione  f(x, y) , dove  x e  y sono le coordinate dei pixel. Si sceglie un valore soglia ( T ), che è un numero compreso tra 0 e 255. Questo valore separa i pixel in due categorie: quelli con intensità luminosa superiore a ( T ) e quelli con intensità inferiore a ( T ). Ogni pixel dell’immagine viene confrontato con il valore soglia. Se il valore del pixel  f(x, y) è superiore a ( T ), il pixel viene assegnato al gruppo sopra la soglia (ad esempio, diventa bianco), altrimenti viene assegnato al gruppo sotto la soglia (diventa nero).

Questo processo è rappresentato dalla seguente formula:

g(x, y) =\begin{cases}255 & \text{se } f(x, y) > T \0 & \text{altrimenti}\end{cases}

Dove  g(x, y) è il valore del pixel nella nuova immagine binaria.

Il risultato è un’immagine binaria, in cui i pixel al di sopra della soglia sono rappresentati da valori bianchi (ad esempio, 255) e i pixel al di sotto della soglia sono rappresentati da valori neri (ad esempio, 0).

Il Simple Thresholding con Python e OpenCV

Per quanto riguarda Python, è possibile utilizzare la libreria OpenCV attraverso la funzione cv2.threshold.La scelta del valore soglia è critica e può influenzare notevolmente l’efficacia del thresholding. In alcuni casi, è possibile utilizzare metodi più avanzati, come l’OTSU, per calcolare automaticamente il valore soglia ottimale.

Per prima cosa scegliamo un’immagine da sottoporre al processo di Simple Thresholding.

leaf-identification

Cliccate con il pulsante destro del mouse sull’immagine precedente e salvatela come leaf.jpg. Una volta scaricata potete usarla nel codice seguente.

import cv2
import numpy as np
from matplotlib import pyplot as plt

# Leggi l'immagine in scala di grigi
image = cv2.imread('leaf.jpg', cv2.IMREAD_GRAYSCALE)

# Applica il Simple Thresholding con un valore soglia arbitrario
ret, thresholded_image = cv2.threshold(image, 150, 255, cv2.THRESH_BINARY)

# Visualizza l'immagine originale e quella thresholded
plt.subplot(1, 2, 1), plt.imshow(image, cmap='gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])

plt.subplot(1, 2, 2), plt.imshow(thresholded_image, cmap='gray')
plt.title('Simple Thresholding'), plt.xticks([]), plt.yticks([])

plt.show()

Nel codice sopra, cv2.threshold prende in input l’immagine in scala di grigi (image), il valore soglia (150), il valore massimo (255, rappresenta il bianco nella nuova immagine binaria) e il tipo di soglia (cv2.THRESH_BINARY). Eseguendo il codice si ottiene il seguente risultato:

OpenCV & Python - Simple Thresholding

Puoi regolare il valore della soglia in base alla tua immagine specifica e alle esigenze del problema. L’efficacia del Simple Thresholding dipende molto dalla distribuzione dei livelli di grigio nell’immagine, ed è spesso utilizzato quando l’immagine è ben contrastata. Per comprendere al meglio questo concetto, modifichiamo l’esempio precedente controllando le diverse immagini prodotte dal Simple Thresholding, modificando il valore di 50 in 50 da 0 a 255 (intervallo di valori dal bianco al nero).

import cv2
import numpy as np
from matplotlib import pyplot as plt

# Leggi l'immagine in scala di grigi
image = cv2.imread('leaf.jpg', cv2.IMREAD_GRAYSCALE)

# Crea una griglia di subplot
plt.figure(figsize=(12, 8))

# Lista di valori soglia da testare
threshold_values = [50, 100, 150, 200]

# Itera attraverso i valori di soglia e visualizza le immagini risultanti
for i, threshold_value in enumerate(threshold_values):
    # Applica il Simple Thresholding
    ret, thresholded_image = cv2.threshold(image, threshold_value, 255, cv2.THRESH_BINARY)

    # Plot dell'immagine thresholded
    plt.subplot(2, 3, i + 1), plt.imshow(thresholded_image, cmap='gray')
    plt.title(f'Threshold = {threshold_value}'), plt.xticks([]), plt.yticks([])

# Aggiungi l'immagine originale alla griglia
plt.subplot(2, 3, 6), plt.imshow(image, cmap='gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])

# Mostra la griglia di subplot
plt.show()

Eseguendo si ottiene una serie di 4 immagini della foglia sottoposte al Simple Thresholding con le soglie di (50,100,150 e 200).

OpenCV & Python - Simple Thresholding 02

Adaptive Thresholding

L’Adaptive Thresholding è una tecnica di image thresholding che si adatta localmente alle variazioni di luminosità nell’immagine. A differenza del Simple Thresholding, dove viene utilizzato un valore fisso per tutta l’immagine, l’Adaptive Thresholding calcola la soglia in base alle regioni locali dell’immagine. Questo è particolarmente utile quando ci sono variazioni di illuminazione significative in diverse parti dell’immagine.

Il metodo più comune di Adaptive Thresholding è basato sulla media o sulla somma pesata della intensità dei pixel all’interno di una finestra locale (o blocco) centrata su ciascun pixel. La formula generale per il calcolo della soglia in Adaptive Thresholding può essere espressa come segue:

 T(x, y) = \text{{funzione}}(\text{{blocco}}(x, y) - C)

Dove:

  • T(x, y) è il valore di soglia calcolato per il pixel alla posizione ((x, y)),
  • \text{{funzione}} è una funzione che calcola la soglia utilizzando la media o la somma pesata dei pixel all’interno del blocco,
  • \text{{blocco}}(x, y) rappresenta la finestra locale centrata sul pixel ((x, y)),
  • C è una costante che può essere sottratta dalla soglia calcolata.

Le due funzioni principali utilizzate sono:

Media locale (Mean):

 \text{{funzione}}(\text{{blocco}}(x, y)) = \frac{1}{\text{{dimensione del blocco}}} \sum_{i} \sum_{j} \text{{blocco}}(x+i, y+j)

Media pesata locale (Gaussian):

 \text{{funzione}}(\text{{blocco}}(x, y)) = \frac{\sum_{i} \sum_{j} w(i, j) \cdot \text{{blocco}}(x+i, y+j)}{\sum_{i} \sum_{j} w(i, j)}

Dove w(i, j) è il peso assegnato al pixel nella posizione ((i, j)) all’interno del blocco. La dimensione del blocco e il valore di (C) possono essere regolati in base alle caratteristiche dell’immagine e alle esigenze specifiche.

L’Adaptive Thresholding aiuta a gestire le variazioni locali di luminosità o contrasto nelle immagini, migliorando la precisione nella segmentazione e nel rilevamento di oggetti. Scriviamo quindi un altro codice in cui applicheremo alla stessa immagine usata in precedenza l’Adaptive Thresholding e vedremo com varieranno i risultati rispetto al Simple Thresholding.

import cv2
import numpy as np
from matplotlib import pyplot as plt

# Leggi l'immagine in scala di grigi
image = cv2.imread('leaf.jpg', cv2.IMREAD_GRAYSCALE)

# Applica l'Adaptive Thresholding
adaptive_threshold = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
                                           cv2.THRESH_BINARY, 11, 2)

# Visualizza l'immagine originale e quella con Adaptive Thresholding
plt.subplot(1, 2, 1), plt.imshow(image, cmap='gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])

plt.subplot(1, 2, 2), plt.imshow(adaptive_threshold, cmap='gray')
plt.title('Adaptive Thresholding'), plt.xticks([]), plt.yticks([])

plt.show()

In questo esempio, cv2.adaptiveThreshold prende in input l’immagine in scala di grigi (image), il valore massimo (255, rappresenta il bianco nella nuova immagine binaria), il tipo di Adaptive Thresholding (cv2.ADAPTIVE_THRESH_MEAN_C che utilizza la media della zona locale), il tipo di soglia (cv2.THRESH_BINARY), la dimensione del blocco (11, specifica la dimensione della finestra locale per calcolare la soglia), e una costante (2, sottrae questa costante dalla media calcolata). Eseguendo il codice si ottiene il seguente risultato:

OpenCV & Python - Adaptive Thresholding

Come si vede rispetto al Simple Thresholding abbiamo un risultato completamente differente.

Altri tipologie di Thresholding

Sì, esistono diversi altri tipi di thresholding utilizzati in base alle esigenze specifiche dell’applicazione e alle caratteristiche dell’immagine. Alcuni di questi includono:

Otsu’s Binarization (OTSU): Questa tecnica è utilizzata per determinare automaticamente il valore ottimale della soglia, minimizzando la varianza intra-classe. In OpenCV, puoi utilizzare cv2.threshold con il flag cv2.THRESH_OTSU.

the Otsu Binarization OpenCV Python main

ARTICOLO DI APPROFONDIMENTO

La binarizzazione di Otsu

Binary Inverted Thresholding: Questo tipo di thresholding è l’opposto di quello binario standard. I pixel che superano la soglia diventano neri, mentre quelli al di sotto diventano bianchi.

Truncated Thresholding: In questa tecnica, i pixel che superano la soglia vengono impostati al valore massimo, mentre quelli al di sotto mantengono il loro valore originale.

Tozero Thresholding: I pixel al di sotto della soglia vengono impostati a zero, mentre quelli che la superano mantengono il loro valore originale.

Tozero Inverted Thresholding: Questa è l’inversione di Tozero Thresholding. I pixel al di sotto della soglia mantengono il loro valore originale, mentre quelli che la superano vengono impostati a zero.

Adaptive Mean Thresholding: Simile all’Adaptive Thresholding, ma utilizza la media ponderata della regione locale per calcolare la soglia.

Adaptive Gaussian Thresholding: Simile all’Adaptive Thresholding, ma utilizza una media pesata gaussiana per calcolare la soglia.

Yen’s Thresholding: Un altro metodo di thresholding basato sulla massimizzazione dell’entropia tra le classi.

Ogni tipo di thresholding ha le sue applicazioni e può essere scelto in base alle caratteristiche specifiche dell’immagine e agli obiettivi dell’analisi. Sperimentare con diversi approcci può essere utile per ottenere i risultati desiderati in contesti specifici.

Applicazioni possibili dell’Image Tresholding

L’Image Thresholding è una tecnica fondamentale nell’elaborazione delle immagini e ha diverse applicazioni in vari campi. Di seguito sono riportate alcune delle sue applicazioni comuni:

  • Segmentazione di Oggetti: L’Image Thresholding è spesso utilizzato per separare gli oggetti di interesse dallo sfondo o da altri oggetti nell’immagine. Questa segmentazione è utile in molte applicazioni, come il rilevamento di contorni, la misurazione degli oggetti e l’analisi degli oggetti in un’immagine.
  • Rilevamento di Contorni: La binarizzazione delle immagini mediante thresholding semplifica il processo di rilevamento di contorni. I contorni degli oggetti diventano più evidenti nella versione binaria, facilitando l’identificazione e l’estrazione di informazioni geometriche.
  • Riconoscimento di Caratteri OCR: Nell’Optical Character Recognition (OCR), l’Image Thresholding è utilizzato per convertire l’immagine del testo in binario, facilitando l’identificazione dei caratteri e migliorando le prestazioni del riconoscimento di caratteri.
  • Biometria: Nell’ambito della biometria, l’Image Thresholding può essere utilizzato per isolare le caratteristiche chiave, come impronte digitali, volti o iridi, facilitando la successiva analisi e confronto.
  • Elaborazione di Immagini Mediche: Nel campo delle immagini mediche, l’Image Thresholding è utilizzato per segmentare strutture anatomiche, identificare lesioni o tumori e migliorare la qualità delle immagini per ulteriori analisi diagnostiche.
  • Analisi di Immagini Satellite: Nell’analisi di immagini satellitari, l’Image Thresholding può essere applicato per rilevare caratteristiche specifiche del terreno, identificare cambiamenti ambientali e migliorare la comprensione delle immagini ottenute da satelliti.
  • Controllo Qualità in Linea: Nelle applicazioni industriali, l’Image Thresholding può essere utilizzato per ispezionare prodotti in linea di produzione, identificando difetti o anomalie basate sulle differenze di colore o luminosità.
  • Sicurezza e Sorveglianza: L’Image Thresholding può essere impiegato nel campo della sicurezza per la rilevazione di movimenti in telecamere di sorveglianza, consentendo di identificare eventi rilevanti e ridurre i falsi positivi.

Questi sono solo alcuni esempi delle molte applicazioni dell’Image Thresholding. La flessibilità di questa tecnica la rende uno strumento prezioso in vari settori, contribuendo al miglioramento delle analisi e delle interpretazioni delle immagini digitali.

Lascia un commento