Diagnosi di polmonite con OpenCV
Articolo in lingua originale di Sandy M
La polmonite è una grave malattia respiratoria causata da un’infezione che, soprattutto nei gruppi a rischio, può avere complicazioni pericolose per la vita. È fondamentale diagnosticare e trattare la polmonite il prima possibile per massimizzare le possibilità di recupero del paziente. Il processo di diagnosi non è semplice e richiede alcuni strumenti di laboratorio medico e competenze mediche avanzate, ma possiamo utilizzare il deep learning e la computer vision per costruire uno strumento facile e veloce che aiuterà i medici a individuare la polmonite.
Le applicazioni per l’analisi di immagini e video, come i risultati delle radiografie, possono essere create utilizzando la libreria software open-source di computer vision e machine learning nota come OpenCV (Open Source Computer Vision). OpenCV è una libreria open-source per la computer vision, il machine learning e l’elaborazione delle immagini. In questa lezione scopriremo come utilizzare OpenCV per identificare la polmonite nelle immagini radiografiche del torace.
Installare OpenCV
L’installazione di OpenCV è la fase iniziale. Esistono vari metodi per installare OpenCV a seconda del sistema operativo. Ecco alcune scelte molto popolari:
Windows: sul sito principale di OpenCV utilizzare i percorsi pre-costruiti
Linux: OpenCV può essere installato utilizzando il manager dei pacchetti incluso nel proprio Linux distro.
Serve eseguire il seguente codice nel terminale, ad esempio in Ubuntu:
Install libopencv-dev with sudo apt-get
MacOS: OpenCV può essere installato utilizzando Homebrew, il codice sottostante va inserito nel terminale
Brew install opencv
Una volta che OpenCV è caricato, si può utilizzare il seguente codice Python per verificare che funzioni correttamente
import cv2 print(cv2.__version__)
Dovreste vedere il numero di versione stampato nel terminale se OpenCV è stato correttamente installato.
Scaricare il dataset
Il dataset che verrà utilizzato per addestrare un algoritmo per identificare la polmonite può essere ora scaricato. In questo caso, utilizzeremo un dataset di immagini di radiografie al torace di pazienti affetti da polmonite preso da Kaggle. Nel dataset ci sono 5856 immagini totali di radiografie al torace, divise in due categorie: polmonite e soggetti sani.
Per ottenere il dataset, è necessario iscriversi a Kaggle creando un account e aderire ai termini e condizioni del dataset. Una volta che l’avete fatto, digitate il seguente comando nel terminale per ottenere il dataset:
kaggle datasets download -d paultimothymooney/chest-xray-pneumonia
Un file ZIP contenente le informazioni verrà scaricato. create una sottocartella sul vostro computer locale in cui estrarre la ZIP.
Preparare i dati
I dati devono quindi essere preparati per l’addestramento del nostro modello di riconoscimento della polmonite. Per creare più campioni di training a partire da quelli attuali, utilizzeremo un metodo chiamato data augmentation. Questo metodo serve ad aumentare le prestazioni del modello e ad aiutarlo a costruirsi più velocemente. Per creare versioni diverse della stessa immagine, l’aumento dei dati comporta l’applicazione di trasformazioni casuali alle immagini, come la rotazione, il ridimensionamento e il capovolgimento.
Per preparare i dati creeremo due cartelle: una per le immagini di addestramento e una per le immagini di validazione. L’80% delle immagini sarà utilizzato per l’addestramento e il 20% per la validazione.
Ecco il codice per preparare i dati:
import os import shutil import random # Define the paths input_dir = 'path/to/input/dir' train_dir = 'path/to/train/dir' val_dir = 'path/to/val/dir' # Create the directories os.makedirs(train_dir, exist_ok=True) os.makedirs(val_dir, exist_ok=True) # Get the list of images image_paths = [] for root, dirs, files in os.walk(input_dir): for file in files: if file.endswith('.jpeg'): image_paths.append(os.path.join(root, file)) # Shuffle the images random.shuffle(image_paths) # Split split_idx = int(0.8 * len(image_paths)) train_image_paths = image_paths[:split_idx] val_image_paths = image_paths[split_idx:]
Ora copiate le immagini nelle cartelle. Cambiate “path/to/input/dir” con il percorso della cartella in cui sono state estratte le informazioni in questo codice. I percorsi delle cartelle in cui si desidera conservare le immagini di addestramento e di validazione devono essere sostituiti da “path/to/train/dir” e “path/to/val/dir”.
Addestrare il modello
Attraverso le immagini di training create nello step precedente, possiamo ora addestrare il modello di identificazione della polmonite. Il nocciolo del nostro modello sarà una rete neurale convoluzionale (CNN) pre-addestrata, ovvero la VGG16. L’architettura di questa CNN molto famosa è diventata lo stato dell’arte di numerosi task di riconoscimento delle immagini dopo essere stata addestrata su un notevole set di immagini.
Ecco il codice per addestrare il modello:
from tensorflow.keras.models import Model from tensorflow.keras.layers import Dense, GlobalAveragePooling2D from tensorflow.keras.applications import VGG16 from tensorflow.keras.preprocessing.image import ImageDataGenerator # Define the input shape of the images input_shape = (224, 224, 3) # Load the VGG16 model base_model = VGG16(weights='imagenet', include_top=False, input_shape=input_shape) # Add a global average pooling layer x = base_model.output x = GlobalAveragePooling2D()(x) # Add a fully connected layer x = Dense(128, activation='relu')(x) # Add the output layer output = Dense(1, activation='sigmoid')(x) # Define the model model = Model(inputs=base_model.input, outputs=output) # Freeze the layers of the VGG16 model for layer in base_model.layers: layer.trainable = False # Compile the model model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) # Define the data generators for training and validation train_datagen = ImageDataGenerator(rescale=1./255, rotation_range=10, width_shift_range=0.1, height_shift_range=0.1, shear_range=0.1, zoom_range=0.1, horizontal_flip=True, fill_mode='nearest') val_datagen = ImageDataGenerator(rescale=1./255) train_generator = train_datagen.flow_from_directory(train_dir, target_size=input_shape[:2], batch_size=32, class_mode='binary') val_generator = val_datagen.flow_from_directory(val_dir, target_size=input_shape[:2], batch_size=32, class_mode='binary') # Train the model model.fit(train_generator, steps_per_epoch=len(train_generator), epochs=10, validation_data=val_generator, validation_steps=len(val_generator))
Innanzitutto, abbiamo caricato i pesi già addestrati con il dataset di ImageNet. Abbiamo incluso anche un output layer con una funzione di attivazione sigmoide, un layer completamente connesso con 128 neuroni e un GAP (global average pooling) layer. I layer del modello della VGG16 vengono congelati e l’algoritmo Adam insieme alla binary cross-entropy vengono utilizzati per costruire il modello. Successivamente, vengono specificati generatori di dati per i set di training e validation che aumentino i dati e riscalino i pixel nel range [0, 1].
Utilizzando l’approccio fit e i generatori di dati per il training e il validation, addestriamo il modello per 10 epoche.
Valutazione del modello
Per determinare la generalizzazione del modello a nuovi dati dopo l’addestramento, dobbiamo valutare le sue prestazioni su un set di test. Per valutare il modello, utilizzeremo la collezione di test del dataset. Inoltre, mostreremo alcune illustrazioni di immagini classificate correttamente e non correttamente.
Utilizzate il codice seguente per valutare il modello e visualizzare alcune istanze.
import numpy as np import matplotlib.pyplot as plt # Define the path to the test directory test_dir = 'path/to/input/dir/chest_xray/test' # Define the data generator for test test_datagen = ImageDataGenerator(rescale=1./255) test_generator = test_datagen.flow_from_directory(test_dir, target_size=input_shape[:2], batch_size=32, class_mode='binary', shuffle=False) # Evaluate the model on the test set loss, accuracy = model.evaluate(test_generator, steps=len(test_generator)) print(f'Test accuracy: {accuracy:.2f}') # Get the predictions and true labels predictions = model.predict(test_generator, steps=len(test_generator)) predictions = np.squeeze(predictions) true_labels = test_generator.labels # Get the image filenames filenames = test_generator.filenames # Find the indices of the correctly and incorrectly classified images correct_indices = np.where((predictions >= 0.5) == true_labels)[0] incorrect_indices = np.where((predictions >= 0.5) != true_labels)[0] # Plot some correctly classified images plt.figure(figsize=(10, 10)) for i, idx in enumerate(correct_indices[:9]): plt.subplot(3, 3, i+1) img = plt.imread(os.path.join(test_dir, filenames[idx])) plt.imshow(img, cmap='gray') plt.title('PNEUMONIA' if predictions[idx] >= 0.5 else 'NORMAL') plt.axis('off') # Plot some incorrectly classified images plt.figure(figsize=(10, 10)) for i, idx in enumerate(incorrect_indices[:9]): plt.subplot(3, 3, i+1) img = plt.imread(os.path.join(test_dir, filenames[idx])) plt.imshow(img, cmap='gray') plt.title('PNEUMONIA' if predictions[idx] >= 0.5 else 'NORMAL') plt.axis('off') plt.show()
In questo codice, abbiamo creato un generatore di dati di test e di valutazione per valutare il modello. Otteniamo anche le previsioni e le label vere per il set di test e troviamo gli indici delle immagini classificate correttamente e di quelle classificate in modo errato. Quindi, utilizzando Matplotlib, riportiamo alcuni casi di immagini classificate correttamente e scorrettamente.
Conclusione
In questo tutorial abbiamo costruito un modello di individuazione della polmonite utilizzando OpenCV e TensorFlow. Abbiamo letto, elaborato e visualizzato le immagini utilizzando OpenCV e abbiamo addestrato e testato il modello utilizzando TensorFlow. Il modello è riuscito a classificare la maggior parte delle immagini del set di test con un alto grado di precisione.
La Computer Vision può essere una grande risorsa per la diagnostica medica. Pur non sostituendo gli operatori sanitari qualificati, possono ridurre i tempi di diagnosi e migliorare l’accuratezza diagnostica. Qui è possibile vedere altri casi d’uso medico del CV in azione.