Il caso è piuttosto comune: avete utilizzato uno dei tanti strumenti disponibili per rimuovere lo sfondo da una foto ma il risultato ottenuto appare imperfetto. Purtroppo, intorno alle aree più difficili da scontornare lo sfondo si vede ancora, e la sua presenza resta evidente. C’è un modo per eliminare i colori da un’immagine in modo automatico, concentrandosi soltanto su quelli che per tonalità sono vicini al colore fornito in input?
Posto che è possibile raggiungere l’obiettivo usando applicazioni come Photoshop, GIMP, LunaPic e Photopea, avreste mai detto di essere in grado di rimuovere i colori indesiderati da una foto utilizzando un semplice script Python?
Python può essere installato su qualunque piattaforma, non necessariamente sui sistemi Linux. Gli utenti Windows, ad esempio, possono installarlo usando il pacchetto ufficiale oppure, meglio ancora, avvalendosi di WSL (Windows Subsystem for Linux) ovvero della possibilità di eseguire Linux in finestra senza abbandonare la piattaforma Microsoft.
Rimuovere colori da un’immagine con un semplice script Python
Ipotizzando di aver già installato Python e che sia possibile richiamare il gestore di pacchetti pip, è necessario aggiungere due librerie essenziali:
pip install numpy
pip install opencv-python
La libreria NumPy è utilizzata per gestire array e operazioni numeriche mentre OpenCV arricchisce Python con una vasta gamma di strumenti per l’elaborazione delle immagini.
Il codice Python che presentiamo di seguito utilizza la libreria OpenCV per manipolare immagini e colori. L’obiettivo principale è identificare e rimuovere tutte le varianti di un colore specificato all’interno di una foto. Il colore “target” è definito fornendo in ingresso il corrispondente codice HTML (HTML hex). Tale espressione è convertita automaticamente in un altro spazio di colore per essere utilizzato nelle successive elaborazioni.
Per usare il nostro codice Python, è sufficiente copiarlo negli appunti quindi digitare nano rimuovi-colori.py
e infine cliccare con il tasto destro per incollarlo nell’editor di testo.
import cv2 import numpy as np # Specificare il colore con il suo codice HTML # e l'immagine da elaborare: color_hex = '#068AB1' image = cv2.imread('testimage.png', cv2.IMREAD_UNCHANGED) # Converte l'HTML hex in valori RGB (da esadecimale a decimale) r = int(color_hex[1:3], 16) g = int(color_hex[3:5], 16) b = int(color_hex[5:7], 16) # Converte RGB in BGR (poiché OpenCV usa BGR) color_bgr = np.uint8([[[b, g, r]]]) # Converte il colore specificato in spazio colore HSV color_hsv = cv2.cvtColor(color_bgr, cv2.COLOR_BGR2HSV) hue = color_hsv[0][0][0] # Estrae la tonalità (Hue) # Controlla se l'immagine ha un canale alpha (trasparenza) if image.shape[2] == 4: # Se ha un canale alpha, separalo b, g, r, a = cv2.split(image) img_bgr = cv2.merge((b, g, r)) # Combina solo i canali BGR else: img_bgr = image # Converti l'immagine in spazio colore HSV hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV) # Definisci un intervallo di colore ampio per il colore specificato lower_bound = np.array([hue - 10, 50, 50]) upper_bound = np.array([hue + 10, 255, 255]) # Crea una maschera per catturare tutte le varianti del colore mask = cv2.inRange(hsv, lower_bound, upper_bound) # Rimuovi tutte le varianti del colore dall'immagine result = cv2.bitwise_and(img_bgr, img_bgr, mask=~mask) # Se l'immagine originale aveva un canale alpha, aggiungi il canale alpha al risultato if image.shape[2] == 4: result = cv2.merge((result, a)) # Salva il risultato come PNG cv2.imwrite('testimage-MOD.png', result)
Come funziona lo script e quali modifiche effettuare
Per usare lo script, è sufficiente indicare al posto di testimage.png
il nome dell’immagine da elaborare (salvata nella stessa directory in cui risiede il codice Python). L’immagine elaborata è salvata come file testimage-MOD.png
: cambiare il nome del file come si preferisce.
Al posto di #068AB1
, invece, si deve specificare il codice HTML del colore da rimuovere. Tale colore è automaticamente convertito nelle sue componenti RGB (red, green, blue). Tali valori sono poi riorganizzati in formato BGR, utilizzato da OpenCV.
Lo script provvede a convertire il colore BGR nello spazio colore HSV (Hue, Saturation, Value), estraendo poi la componente di tonalità (hue). Il flag cv2.IMREAD_UNCHANGED
garantisce che, se l’immagine contiene un canale alpha (trasparenza), cosa comune con i file PNG, questo sia preservato.
L’immagine BGR è convertita in spazio colore HSV per poter confrontare i colori in base alla loro tonalità. Con la successiva definizione di un intervallo di colore, lo script definisce un range di tonalità per catturare tutte le varianti presenti nell’immagine.
La maschera (mask) appositamente creata, evidenzia tutte le aree dell’immagine che rientrano nell’intervallo di colore specificato. I colori specificati sono quindi rimossi dall’immagine invertendo la maschera (~mask
) e applicandola all’immagine BGR. Se l’immagine originale aveva un canale alpha, questo è aggiunto di nuovo al risultato finale.
Come avviare la modifica dell’immagine
Dopo aver fatto le opportune modifiche (nomi dei file e codice HTML del colore da rimuovere), si può premere CTRL+O
per salvare lo script Python con l’editor nano quindi CTRL+X
per uscire.
A questo punto è tutto pronto per effettuare un test: basta copiare l’immagine nella cartella dello script rimuovi-colori.py
, quindi invocare il seguente comando:
python3 rimuovi-colori.py
Ad elaborazione conclusa si troverà l’immagine risultante nella medesima directory. Se si utilizza WSL in Windows, si può premere Windows+R
, digitare \\WSL$
, selezionare la distribuzione Linux installata quindi la cartella home
seguita dal nome dell’utente.
Come potete verificare nell’immagine di esempio, un’eccellente applicazione Web per la rimozione dello sfondo ha lasciato una parte del background blu originariamente presente (immagine originale su Unsplash) tra i capelli della modella. Specificando il codice HTML #068AB1
(un celeste spento) in ingresso, ed eseguito lo script Python, l’immagine risultante è quella a destra. Meglio, no?
Qualora lo si desiderasse, è possibile migliorare lo script facendo in modo che gestisca il nome dell’immagine da elaborare, il nome dell’immagine da ottenere in output e il codice HTML come argomenti trasferiti dalla riga di comando.
Credit immagine in apertura: iStock.com – gorodenkoff