paint-brush
Python'da Tıbbi Verileri (MR, CT, X-Ray) Açabilir ve Yapay Zekayla Tümörleri Bulabilir misiniz?! Belkiile@thebojda
3,811 okumalar
3,811 okumalar

Python'da Tıbbi Verileri (MR, CT, X-Ray) Açabilir ve Yapay Zekayla Tümörleri Bulabilir misiniz?! Belki

ile Laszlo Fazekas8m2024/04/23
Read on Terminal Reader

Çok uzun; Okumak

Bir programcı tıbbi verilerin işlenmesini duyduğunda bunun ciddi bir şey olduğunu, yalnızca üniversitelerin ve araştırma enstitülerinin halledebileceği bir şey olduğunu düşünebilir (en azından ben öyle düşündüm). Gördüğünüz gibi işlenmesi çok kolay ve sinir ağı işleme gibi şeyler için ideal olan basit gri tonlamalı görüntülerden bahsediyoruz.
featured image - Python'da Tıbbi Verileri (MR, CT, X-Ray) Açabilir ve Yapay Zekayla Tümörleri Bulabilir misiniz?! Belki
Laszlo Fazekas HackerNoon profile picture
0-item


Birkaç gün önce MR taramasına girdim. Beni büyük bir tüpün içine kaydırdılar ve 15 dakika boyunca etrafımdaki makine vızıldadı, mırıldandı ve tıkladı. İncelemenin sonunda verileri içeren bir CD aldım. İyi bir geliştirici böyle bir durumda ne yapar? Elbette eve varır varmaz verileri incelemeye başlıyorlar ve onu Python kullanarak nasıl çıkarabileceklerini düşünmeye başlıyorlar.


CD'de bir sürü DLL, bir EXE ve Windows görüntüleyici için Linux'ta işe yaramayan birkaç ek dosya vardı. İşin özü DICOM adlı bir klasördeydi. Sekiz klasörde bir dizi uzantısız dosya barındırıyordu. ChatGPT, DICOM'un genellikle MRI, CT ve X-ışını görüntülerini depolamak için kullanılan standart bir format olduğunu anlamama yardımcı oldu. Temel olarak, bazı meta verilerle birlikte gri tonlamalı görüntüler içeren basit bir paketleme formatıdır.


Aşağıdaki kod, dosyaları kolayca PNG formatında dışa aktarmanıza olanak tanır:


 import os import pydicom from PIL import Image import sys def save_image(pixel_array, output_path): if pixel_array.dtype != 'uint8': pixel_array = ((pixel_array - pixel_array.min()) / (pixel_array.max() - pixel_array.min()) * 255).astype('uint8') img = Image.fromarray(pixel_array) img.save(output_path) print(f"Saved image to {output_path}") def process_dicom_directory(dicomdir_path, save_directory): if not os.path.exists(save_directory): os.makedirs(save_directory) dicomdir = pydicom.dcmread(dicomdir_path) for patient_record in dicomdir.patient_records: if 'PatientName' in patient_record: print(f"Patient: {patient_record.PatientName}") for study_record in patient_record.children: if 'StudyDate' in study_record: print(f"Study: {study_record.StudyDate}") for series_record in study_record.children: for image_record in series_record.children: if 'ReferencedFileID' in image_record: file_id = list(map(str, image_record.ReferencedFileID)) file_id_path = os.path.join(*file_id) print(f"Image: {file_id_path}") image_path = os.path.join(os.path.dirname(dicomdir_path), file_id_path) modified_filename = '_'.join(file_id) + '.png' image_save_path = os.path.join(save_directory, modified_filename) try: img_data = pydicom.dcmread(image_path) print("DICOM image loaded successfully.") save_image(img_data.pixel_array, image_save_path) except FileNotFoundError as e: print(f"Failed to read DICOM file at {image_path}: {e}") except Exception as e: print(f"An error occurred: {e}") if __name__ == "__main__": if len(sys.argv) < 3: print("Usage: python dicomsave.py <path_to_DICOMDIR> <path_to_save_images>") sys.exit(1) dicomdir_path = sys.argv[1] save_directory = sys.argv[2] process_dicom_directory(dicomdir_path, save_directory)


Kod iki parametre bekliyor. Birincisi DICOMDIR dosyasının yolu, ikincisi ise görüntülerin PNG formatında kaydedileceği dizindir.


DICOM dosyalarını okumak için Pydicom kütüphanesini kullanıyoruz. Yapı, meta verilerin (hastanın adı gibi) ve görüntüleri içeren çalışmaların çıkarılabileceği pydicom.dcmread işlevi kullanılarak yüklenir. Görüntü verileri dcmread ile de okunabilir. Ham verilere, save_image işlevinin PNG'ye dönüştürdüğü pikselarray alanı aracılığıyla erişilebilir. Çok karmaşık değil.


Sonuç, daha sonra kolayca kullanılabilecek birkaç kare (tipik olarak 512x512) gri tonlamalı görüntüdür.


Maceram hakkındaki bu kısa öyküyü DICOM formatını kullanarak yazmanın neden önemli olduğunu düşündüm? Bir programcı tıbbi verilerin işlenmesini duyduğunda bunun ciddi bir şey olduğunu, yalnızca üniversitelerin ve araştırma enstitülerinin halledebileceği bir şey olduğunu düşünebilir (en azından ben öyle düşündüm). Gördüğünüz gibi işlenmesi çok kolay ve sinir ağı işleme gibi şeyler için ideal olan basit gri tonlamalı görüntülerden bahsediyoruz.


Bunun açacağı olasılıkları düşünün. Basit bir tümör dedektörü gibi bir şey için ihtiyacınız olan tek şey, nispeten basit bir evrişimsel ağ ve yeterli sayıda örnektir. Gerçekte görev, görüntülerdeki köpekleri veya kedileri tanımaktan pek farklı değildir.


Bunun ne kadar doğru olduğunu göstermek için bir örnek vereyim. Kaggle'da kısa bir araştırma yaptıktan sonra beyin tümörlerinin MR verilerine (gri tonlamalı görüntüler) göre sınıflandırıldığı bir defter buldum . Veri seti, görüntüleri dört gruba ayırıyor: üç tür beyin tümörü ve sağlıklı beyin görüntülerinin yer aldığı dördüncü kategori. Ağın mimarisi aşağıdaki gibidir:


 ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ ┃ Layer (type) ┃ Output Shape ┃ Param # ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ │ conv2d (Conv2D) │ (None, 164, 164, 64) │ 1,664 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ max_pooling2d (MaxPooling2D) │ (None, 54, 54, 64) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ conv2d_1 (Conv2D) │ (None, 50, 50, 64) │ 102,464 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ max_pooling2d_1 (MaxPooling2D) │ (None, 16, 16, 64) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ conv2d_2 (Conv2D) │ (None, 13, 13, 128) │ 131,200 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ max_pooling2d_2 (MaxPooling2D) │ (None, 6, 6, 128) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ conv2d_3 (Conv2D) │ (None, 3, 3, 128) │ 262,272 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ max_pooling2d_3 (MaxPooling2D) │ (None, 1, 1, 128) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ flatten (Flatten) │ (None, 128) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense (Dense) │ (None, 512) │ 66,048 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense_1 (Dense) │ (None, 4) │ 2,052 │ └─────────────────────────────────┴────────────────────────┴───────────────┘


Gördüğünüz gibi, ilk birkaç katman, tümör modellerini çıkaran bir evrişim ve maksimum havuzlama sandviçinden ve ardından sınıflandırmayı gerçekleştiren iki yoğun katmandan oluşur. Bu , TensorFlow'un CIFAR-10 veri kümesini kullanan CNN örnek kodunda kullanılan mimarinin tamamen aynısıdır. Karşılaştığım ilk sinir ağlarından biri olduğu için bunu çok iyi hatırlıyorum. CIFAR-10 veri seti, daha önce de belirttiğim gibi köpekler ve kediler için iki sınıf dahil olmak üzere on sınıfa ayrılmış 60.000 görüntü içeriyor. Ağın mimarisi şuna benzer:


 Model: “sequential” _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d (Conv2D) (None, 30, 30, 32) 896 _________________________________________________________________ max_pooling2d (MaxPooling2D) (None, 15, 15, 32) 0 _________________________________________________________________ conv2d_1 (Conv2D) (None, 13, 13, 64) 18496 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 6, 6, 64) 0 _________________________________________________________________ conv2d_2 (Conv2D) (None, 4, 4, 64) 36928 _________________________________________________________________ flatten (Flatten) (None, 1024) 0 _________________________________________________________________ dense (Dense) (None, 64) 65600 _________________________________________________________________ dense_1 (Dense) (None, 10) 650 ================================================================= Total params: 122,570 Trainable params: 122,570 Non-trainable params: 0 _________________________________________________________________


Aynı mimariyle, yalnızca biraz farklı parametrelerle uğraştığımız açıktır; bu nedenle, MRI görüntülerindeki beyin tümörlerini tanımak, resimlerdeki kedileri veya köpekleri tanımlamaktan çok daha zor değildir. Üstelik bahsi geçen Kaggle dizüstü bilgisayar, tümörleri %99 verimlilikle sınıflandırabiliyor!


Sadece belirli durumlarda tıbbi verileri çıkarmanın ve işlemenin ne kadar basit olabileceğini ve beyin tümörlerini tespit etmek gibi karmaşık görünen sorunların basit, geleneksel çözümlerle ne kadar etkili bir şekilde çözülebileceğini belirtmek istiyorum.


Bu nedenle herkesi tıbbi verilerden çekinmemeye davet ediyorum. Gördüğünüz gibi nispeten basit formatlarla uğraşıyoruz ve nispeten basit, köklü teknolojiler (evrişimli ağlar, görüntü transformatörleri vb.) kullanarak burada önemli bir etki elde edilebilir. Boş zamanlarınızda açık kaynaklı bir sağlık projesine hobi olarak katılırsanız ve kullanılan sinir ağında ufak bir iyileştirme yapabilirseniz, potansiyel olarak hayat kurtarabilirsiniz!