v0.26 — Edizione 2026. Un percorso di 5 episodi sull'utilizzo di scikit-image v0.26 (Edizione 2026) come motore principale di image preprocessing e data augmentation nelle moderne pipeline di AI e deep learning.
Elaborazione delle ImmaginiScienza dei DatiVisione Artificiale
Scopri come scikit-image rappresenta le immagini come ndarrays di NumPy. Impara perché questo design lo rende il motore di preprocessing perfetto per framework di deep learning come PyTorch e TensorFlow.
4m 01s
2
Parlare la stessa lingua: Dtypes e OpenCV
Padroneggia i data types delle immagini per prevenire i bug silenziosi più comuni nella computer vision. Scopri come integrare perfettamente scikit-image con OpenCV e gli input delle reti neurali.
4m 48s
3
Contrasto, esposizione e robustezza dell'AI
Impara a utilizzare la regolazione del contrasto e l'equalizzazione dell'istogramma per standardizzare i dataset. Queste tecniche sono fondamentali per rendere i modelli di AI robusti alle diverse condizioni di illuminazione.
4m 10s
4
Trasformazioni geometriche per la data augmentation
Esplora come ridimensionare le immagini per adattarle agli input delle reti neurali e applicare trasformazioni affini. Essenziale per costruire pipeline di data augmentation robuste.
4m 00s
5
Segmentazione classica per il bootstrap dell'AI
Scopri come utilizzare la classica watershed segmentation per generare automaticamente maschere di addestramento pixel-perfect per i modelli di deep learning, risparmiando ore di etichettatura manuale.
3m 47s
Episodi
1
La pipeline di immagini per l'AI: NumPy al centro
4m 01s
Scopri come scikit-image rappresenta le immagini come ndarrays di NumPy. Impara perché questo design lo rende il motore di preprocessing perfetto per framework di deep learning come PyTorch e TensorFlow.
Ciao, sono Alex di DEV STORIES DOT EU. scikit-image: The AI Image Pipeline, episodio 1 di 5. Prima che un modello di deep learning possa riconoscere un volto, deve digerire una griglia di numeri. Se dai in pasto questa griglia nell'ordine sbagliato, il tuo modello non impara nulla e l'elaborazione rallenta drasticamente. The AI Image Pipeline: NumPy at the Core è la soluzione per strutturare correttamente questa griglia.
Quando carichi un'immagine usando scikit-image, non ottieni un oggetto immagine proprietario. Ottieni un array N-dimensionale standard, noto come ndarray. Un'immagine è semplicemente una matrice di pixel. Dato che è un semplice array NumPy, puoi usare qualsiasi operazione standard per fare slice, mask o manipolare direttamente i dati dell'immagine.
Ecco il punto chiave. Il modo in cui scikit-image indicizza questi array mette in difficoltà molti sviluppatori. Nella geometria standard usi le coordinate x e y, dove x è orizzontale e y è verticale. scikit-image abbandona questo approccio per la notazione a matrice. Il primo indice è la riga, che corrisponde alla posizione verticale. Il secondo indice è la colonna, che corrisponde alla posizione orizzontale. Se hai un'immagine a colori, il terzo indice è il channel del colore. Un'immagine a colori bidimensionale standard è in realtà un array tridimensionale ordinato come riga, colonna, channel.
Supponi di preparare un batch di immagini a colori da dare in pasto a una Convolutional Neural Network. La tua rete si aspetta una shape specifica. Se la tua immagine è alta 256 pixel e larga 256 pixel con i channel rosso, verde e blu, la shape di una singola immagine è 256, 256, 3. Ma un batch di queste immagini aggiunge una quarta dimensione all'inizio, che rappresenta il numero di immagini.
Quando applichi le funzioni di scikit-image a questi dati, la funzione deve sapere quale dimensione contiene i valori dei colori, in modo da non elaborarli come dati spaziali. Questo viene gestito dall'argomento channel axis. Impostando l'argomento channel axis a meno uno, dici alla funzione che i channel del colore si trovano sempre nell'ultima dimensione dell'array. Questo assicura che la funzione punti ai dati di colore corretti, indipendentemente dal fatto che tu le passi una singola immagine o un grande batch con dimensioni spaziali extra.
Questo ci porta alla memoria. Questa è la parte che conta per la velocità di elaborazione. Gli array NumPy vengono salvati in blocchi di memoria contigui, usando di default un ordine C-like. Questo significa che l'ultima dimensione nella shape dell'array cambia più velocemente nella memoria fisica. Per il nostro array di immagini standard fatto di riga, colonna, channel, i singoli channel di colore per un singolo pixel si trovano uno accanto all'altro nella tua RAM hardware.
Se scrivi codice custom per fare un loop su questi pixel, devi rispettare questo memory layout. La regola è assoluta: la dimensione più a destra del tuo array dovrebbe essere elaborata nel loop più interno. Iteri sulle righe nel loop esterno, poi sulle colonne, e infine sui channel all'interno. Se inverti questo ordine e fai un loop sulle righe all'interno, costringi la CPU a saltare avanti e indietro tra indirizzi di memoria frammentati. Questo distrugge la cache locality e fa girare il tuo codice molto più lentamente.
La cosa più critica da ricordare è che scikit-image non usa coordinate orizzontali e verticali; usa una rigida indicizzazione a matrice di riga, colonna e channel, e far combaciare i tuoi loop con quell'esatto ordine di memoria è ciò che mantiene veloce la tua data pipeline.
Se vuoi aiutare a portare avanti questo podcast, puoi supportare lo show cercando DevStoriesEU su Patreon. Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a sviluppare!
2
Parlare la stessa lingua: Dtypes e OpenCV
4m 48s
Padroneggia i data types delle immagini per prevenire i bug silenziosi più comuni nella computer vision. Scopri come integrare perfettamente scikit-image con OpenCV e gli input delle reti neurali.
Ciao, sono Alex di DEV STORIES DOT EU. scikit-image: La AI Image Pipeline, episodio 2 di 5. Il silent bug più comune nell'AI per la computer vision non è nell'architettura della rete neurale. È un mismatch del data type. Dai in pasto un'immagine a un modello, il codice gira senza lanciare errori, ma gli output sono spazzatura totale. Questo succede quando le tue librerie sono in totale disaccordo su come un pixel debba essere rappresentato numericamente. Oggi risolveremo questo problema parlando di Parlare la stessa lingua: Dtypes e OpenCV.
In scikit-image, le immagini sono salvate come array numpy standard. Ma i numeri all'interno di quegli array si comportano in modo diverso a seconda del loro esatto data type. Il formato di default delle webcam e dei file immagine standard è un intero senza segno a otto bit, conosciuto come uint8. Questi valori vanno da zero a 255, dove zero è il nero assoluto e 255 è l'intensità massima.
Tuttavia, le funzioni di image processing scientifico e i framework di deep learning preferiscono quasi sempre i numeri floating-point. In scikit-image, un'immagine float si aspetta che le intensità dei pixel siano scalate su un range rigoroso, di solito da zero a uno.
Ecco il punto chiave. Non usare il metodo astype di numpy per convertire le tue immagini uint8 in float. Se prendi un array uint8 e chiami semplicemente astype float, numpy cambia solo il tipo di memoria sottostante. Un valore di un pixel luminoso di 255 diventa semplicemente 255 punto zero. Non fa il rescale dei valori. Se passi quell'array a una funzione di scikit-image o a un modello PyTorch che si aspetta la luminosità massima a uno punto zero, la matematica esplode. I tuoi bianchi vengono improvvisamente trattati come se fossero 255 volte più luminosi del valore massimo possibile.
Invece, devi usare le funzioni di utility built-in di scikit-image. La più importante si chiama img_as_float. Questa funzione controlla il data type di input e gestisce automaticamente il rescale matematico. Comprime in modo sicuro un range uint8 da zero a 255 in un preciso range float da zero a uno punto zero.
I data type sono solo metà della battaglia. Devi anche allineare i canali colore, specialmente se stai catturando video. Se leggi un frame usando OpenCV, ti restituisce un array numpy uint8. Ma OpenCV ha una stranezza storica. Salva i canali colore nell'ordine Blue Green Red, conosciuto come BGR. scikit-image e la maggior parte dei modelli AI moderni si aspettano Red Green Blue, o RGB. Se ti dimentichi di scambiare i canali, le mele rosse sembrano blu e la pelle umana sembra completamente aliena.
Non hai bisogno di chiamare una pesante funzione di conversione colore di OpenCV per risolvere questo problema. Dato che l'immagine è solo un array numpy, puoi usare il semplice array slicing. Fai lo slicing dell'array attraverso le sue tre dimensioni. Prendi tutte le righe, tutte le colonne e poi, per la dimensione finale che rappresenta i canali colore, specifichi uno step di meno uno. Questo dice a numpy di andare all'indietro attraverso i canali, invertendo BGR in RGB istantaneamente in memoria.
Vediamo insieme una ingestion pipeline completa per un modello di deep learning. Per prima cosa, catturi un frame da un video stream di OpenCV, che ti dà un array BGR uint8. Poi, inverti i canali colore usando lo slicing di numpy per convertirlo in RGB. Dopodiché, passi quell'array a img_as_float. L'array ora è una matrice floating-point, perfettamente scalata tra zero e uno. Infine, converti questo array numpy pulito in un tensor PyTorch.
Una rete neurale non può dirti quando i suoi dati di input sono scalati in modo errato, semplicemente impara i pattern sbagliati o fallisce silenziosamente. Controllare i tuoi data type e l'ordine dei canali fin dallo step di ingestion assicura che la tua pipeline poggi su solide fondamenta matematiche.
Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a sviluppare!
3
Contrasto, esposizione e robustezza dell'AI
4m 10s
Impara a utilizzare la regolazione del contrasto e l'equalizzazione dell'istogramma per standardizzare i dataset. Queste tecniche sono fondamentali per rendere i modelli di AI robusti alle diverse condizioni di illuminazione.
Ciao, sono Alex di DEV STORIES DOT EU. scikit-image: The AI Image Pipeline, episodio 3 di 5. Le reti neurali sono eccezionali nell'individuare pattern, ma memorizzeranno felicemente l'illuminazione specifica di una stanza anziché l'oggetto che vuoi rilevare. Per risolvere questo problema, dobbiamo standardizzare la varianza nei nostri dataset tramite contrasto, esposizione e robustezza dell'AI.
Considera un dataset di radiografie mediche raccolte da una dozzina di ospedali diversi. Le scansioni provengono da macchinari diversi con calibrazioni estremamente variabili. Alcune immagini sono scure e impastate, mentre altre sono slavate e luminose. Se dai in pasto questi raw data a una rete neurale, probabilmente farà overfit sulle condizioni di illuminazione di scanner specifici, anziché imparare a identificare la patologia sottostante. Devi normalizzare l'esposizione prima che inizi il training.
Il primo passo in questa standardizzazione è spesso rimuovere le informazioni irrilevanti. Se la struttura è tutto ciò che conta, il colore è una distrazione. Puoi usare una funzione chiamata rgb to gray per convertire le immagini a colori in array grayscale a singolo canale. Questo riduce la dimensionalità dei tuoi dati e forza il modello a valutare la luminanza pura.
Una volta che lavori strettamente con la luminanza, devi allineare la luminosità di base in tutto il tuo dataset. È qui che entra in gioco rescale intensity. Questa funzione esegue uno stretch lineare sui dati della tua immagine. Prende il pixel più scuro e lo mappa al valore più basso possibile, come zero, e mappa il pixel più luminoso al valore più alto possibile, come duecentocinquantacinque. Ogni pixel intermedio viene scalato linearmente.
Ecco il punto chiave. Uno stretch semplice dal minimo al massimo è fragile. Un singolo pixel nero morto o un artefatto luminoso dovuto a un granello di polvere sul sensore detterà l'intera scala. Lo stretch comprimerà i tuoi dati anatomici reali in una banda di grigi stretta e inutile, solo per accomodare quell'unico outlier estremo.
Per risolvere questo problema, usi il percentile clipping. Invece di fare uno stretch dal minimo e massimo assoluti, calcoli il secondo e il novantottesimo percentile dei valori dei pixel nella tua immagine. Passi poi questi percentili alla funzione rescale intensity come tuo range di input. La funzione taglierà via il due percento estremo di pixel chiari e scuri, impostandoli a bianco puro e nero puro, e farà uno stretch lineare del restante novantasei percento dei dati. Questo garantisce che il grosso dei tuoi dati strutturali utilizzi l'intero range dinamico, ignorando completamente gli artefatti casuali.
A volte, uno stretch lineare non è sufficiente. Potresti avere una radiografia in cui i dati sono stati catturati, ma tutti i pixel sono raggruppati attorno a poche specifiche tonalità di grigio, rendendo l'immagine piatta e oscurando i dettagli. Per questo, usi equalize hist, che sta per histogram equalization.
L'histogram equalization è un processo non lineare. Invece di fare semplicemente uno stretch dei limiti, analizza la frequenza di ogni valore dei pixel nell'immagine. Poi distribuisce i valori di intensità più frequenti sull'intero spettro disponibile. Se una grande porzione della tua radiografia è intrappolata in una stretta banda di grigi scuri, l'histogram equalization separerà questi grigi, assegnando loro nuovi valori che spaziano dal nero al bianco. Questo aumenta artificialmente il contrasto locale, rivelando texture e contorni sottili che prima erano nascosti nelle aree impastate della scansione.
Standardizzare il tuo dataset con queste tecniche assicura che il tuo modello valuti la forma e la texture effettive del soggetto. Una pipeline robusta rimuove la varianza irrilevante della calibrazione hardware, forzando la rete neurale a imparare il segnale anziché il rumore. Grazie per aver passato qualche minuto con me. Alla prossima, stammi bene.
4
Trasformazioni geometriche per la data augmentation
4m 00s
Esplora come ridimensionare le immagini per adattarle agli input delle reti neurali e applicare trasformazioni affini. Essenziale per costruire pipeline di data augmentation robuste.
Ciao, sono Alex di DEV STORIES DOT EU. scikit-image: la Image Pipeline per l'IA, episodio 4 di 5. Una rete neurale convoluzionale potrebbe riconoscere un gatto alla perfezione. Ma capovolgi quel gatto, o spostalo di tre pixel a sinistra, e il modello diventa improvvisamente del tutto cieco. Risolvi questo problema con le trasformazioni geometriche per la Data Augmentation.
Prima di fare qualsiasi augmentation, dobbiamo preparare la baseline. Le reti neurali richiedono input shape fisse. Gestisci questa cosa usando la funzione resize in scikit-image. Le passi un'immagine e le tue dimensioni di output di destinazione, e lei allarga o restringe matematicamente l'array di pixel per adattarlo, interpolando automaticamente i nuovi valori dei pixel. Ma il solo resize lascia il tuo modello vulnerabile all'overfitting. Memorizzerà esattamente dove si trovano gli oggetti nel frame. Per evitarlo, costruisci una pipeline di data augmentation che applica trasformazioni casuali alle immagini di training on the fly.
In scikit-image, le trasformazioni spaziali manipolano lo spazio delle coordinate dell'immagine usando la matematica delle matrici. Spostare o ruotare un'immagine significa moltiplicare le sue coordinate dei pixel per una matrice di trasformazione. Ed ecco l'intuizione chiave. La traslazione, ovvero lo shift di un'immagine lungo l'asse x o y, non può essere calcolata usando la moltiplicazione standard di matrici due per due. La moltiplicazione di matrici gestisce lo scaling e la rotazione, ma lo shift richiede un'addizione.
Per risolvere questo problema, scikit-image usa le coordinate omogenee. Aggiungendo una terza coordinata dummy, un uno, a ogni punto bidimensionale, il sistema fa un upgrade della matematica. Questo permette di calcolare simultaneamente traslazioni, rotazioni e scaling con una singola moltiplicazione di matrici tre per tre.
Non devi scrivere manualmente queste matrici tre per tre. scikit-image fornisce delle classi di trasformazione che fanno i calcoli al posto tuo. Per la nostra pipeline anti-overfitting, usi la classe Euclidean transform. Una trasformazione euclidea preserva distanze e angoli, il che significa che gestisce solo rotazione e traslazione. La inizializzi passandole un angolo di rotazione e un vettore di traslazione. Se avessi bisogno di aggiungere uno shearing o cambiare la scala, passeresti a una Affine transform. Se dovessi simulare un cambio di prospettiva, useresti una Projective transform. Ma per rotazioni e shift casuali, la Euclidean è esattamente ciò che ti serve.
Una volta definita la tua matrice di trasformazione, devi applicarla alla tua immagine. Lo fai usando la funzione warp. Passi alla funzione warp la tua immagine di input e il tuo oggetto Euclidean transform.
È qui che la cosa si fa interessante. La funzione warp non calcola dove dovrebbero andare i pixel di input nella nuova immagine. Se spingi i pixel in avanti in una nuova griglia, la matematica della rotazione crea coordinate frazionarie. Quando queste vengono arrotondate al pixel intero più vicino, finisci con pixel mancanti, o buchi, sparsi per la tua immagine di output. Invece, warp lavora al contrario. Prende l'inversa della tua matrice di trasformazione. Guarda ogni coordinata di pixel vuota nell'immagine di output di destinazione, la mappa all'indietro nello spazio dell'immagine originale e interpola il valore di colore corretto. Questo inverse mapping garantisce un output solido e senza buchi.
Per la tua pipeline di augmentation, la logica è semplice. Genera un angolo casuale e un set casuale di shift. Passali a una Euclidean transform. Passa quella transform e la tua immagine di training alla funzione warp. L'output va dritto nella tua rete neurale. Le trasformazioni geometriche non si limitano a creare più dati di training; forzano il tuo modello a separare l'oggetto che deve riconoscere dalle coordinate arbitrarie che si trova a occupare.
Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a sviluppare!
5
Segmentazione classica per il bootstrap dell'AI
3m 47s
Scopri come utilizzare la classica watershed segmentation per generare automaticamente maschere di addestramento pixel-perfect per i modelli di deep learning, risparmiando ore di etichettatura manuale.
Ciao, sono Alex di DEV STORIES DOT EU. scikit-image: The AI Image Pipeline, episodio 5 di 5. I modelli di segmentation di deep learning sono incredibilmente potenti, ma sono anche incredibilmente affamati. Richiedono migliaia di mask disegnate a mano e perfette al pixel prima di poter imparare qualsiasi cosa. La segmentation classica per fare bootstrap dell'AI colma questa lacuna.
Stai addestrando una moderna U-Net per rilevare cellule o monete che si toccano. Hai bisogno di label di ground-truth. Disegnare a mano queste mask richiede settimane. Potresti provare a lanciare un semplice edge detector come Canny per automatizzare il processo. Canny è eccellente nel trovare transizioni nette, ma spesso non riesce a chiudere i loop. Ti restituisce contorni frammentati, non regioni solide. Un'AI addestrata su contorni interrotti restituirà in output contorni interrotti.
La segmentation region-based risolve questo problema. Nello specifico, l'algoritmo Watershed. Tratta la tua immagine come un paesaggio topografico. I valori alti dei pixel sono le montagne, e i valori bassi sono le valli. Ecco l'intuizione chiave. Invece di provare a connettere gli edge spezzati, Watershed inonda l'immagine da punti di partenza noti finché l'acqua non si incontra sulle creste più alte. Questo garantisce regioni chiuse e solide.
Per prima cosa, costruisci il terreno. Lo fai generando una elevation map usando un filtro Sobel. Il filtro Sobel calcola i gradienti spaziali, evidenziando gli edge. Quando lo applichi alla tua immagine, i bordi tra le tue monete sovrapposte diventano le creste alte nella tua mappa. Le superfici piatte delle monete e il background diventano le valli.
Dopodiché, posizioni i marker. Devi dire all'algoritmo da dove l'acqua dovrebbe iniziare a salire. Se salti questo passaggio, l'algoritmo inonderà tutto da ogni minuscolo minimo locale e frantumerà la tua immagine in centinaia di frammenti inutili. Crei un array di marker esattamente della stessa dimensione della tua immagine originale. Trovi il background definitivo selezionando i pixel sotto una specifica soglia di intensità e assegni loro un valore pari a uno. Poi, trovi il foreground definitivo, ovvero i centri solidi delle monete, selezionando i pixel sopra una soglia di intensità più alta. A questi assegni un valore pari a due.
Infine, inneschi l'inondazione. Passi la tua elevation map e il tuo array di marker alla funzione watershed dal modulo di segmentation di scikit-image. L'algoritmo riempie le regioni partendo dagli uno e dai due. Man mano che l'acqua simulata sale, le regioni si espandono. Quando finalmente si incontrano sulle creste alte della elevation map di Sobel, l'algoritmo costruisce un boundary.
La funzione restituisce un array di interi di regioni chiuse e con label perfette. Gli oggetti che si toccano vengono separati esattamente in corrispondenza del boundary. Ora hai un array di mask pulito in cui ogni moneta è un oggetto solido distinto. Puoi lanciare questa pipeline su tutto il tuo dataset senza label per generare automaticamente migliaia di mask. Poi dai in pasto queste mask direttamente alla tua U-Net come dati di training di ground-truth.
Fare il bootstrap di un'AI non richiede lavoro umano se sai come combinare la logica classica del terreno dell'image processing con le moderne architetture dei modelli. Ti incoraggio a esplorare la documentazione ufficiale di scikit-image e a provare a costruire una elevation map hands-on, e se hai un'idea per la nostra prossima serie, fai un salto su devstories.eu e fammelo sapere. Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a costruire!
Tap to start playing
Browsers block autoplay
Share this episode
Episode
—
Copy this episode in another language:
Questo sito non utilizza cookie. Il nostro fornitore di hosting potrebbe registrare il tuo indirizzo IP a fini statistici. Scopri di più.