paint-brush
क्या आप पाइथन में मेडिकल डेटा (एमआर, सीटी, एक्स-रे) खोल सकते हैं और एआई के साथ ट्यूमर ढूंढ सकते हैं?! शायदद्वारा@thebojda
3,819 रीडिंग
3,819 रीडिंग

क्या आप पाइथन में मेडिकल डेटा (एमआर, सीटी, एक्स-रे) खोल सकते हैं और एआई के साथ ट्यूमर ढूंढ सकते हैं?! शायद

द्वारा Laszlo Fazekas8m2024/04/23
Read on Terminal Reader

बहुत लंबा; पढ़ने के लिए

जब कोई प्रोग्रामर मेडिकल डेटा प्रोसेसिंग के बारे में सुनता है, तो उन्हें लगता है कि यह कोई गंभीर बात है, ऐसा कुछ जिसे केवल विश्वविद्यालय और शोध संस्थान ही संभाल सकते हैं (कम से कम, मुझे तो यही लगा)। जैसा कि आप देख सकते हैं, हम सरल ग्रेस्केल इमेज के बारे में बात कर रहे हैं, जिन्हें प्रोसेस करना बहुत आसान है और न्यूरल नेटवर्क प्रोसेसिंग जैसी चीज़ों के लिए आदर्श हैं।
featured image - क्या आप पाइथन में मेडिकल डेटा (एमआर, सीटी, एक्स-रे) खोल सकते हैं और एआई के साथ ट्यूमर ढूंढ सकते हैं?! शायद
Laszlo Fazekas HackerNoon profile picture
0-item


कुछ दिन पहले, मेरा MRI स्कैन हुआ था। उन्होंने मुझे एक बड़ी ट्यूब में डाला, और 15 मिनट तक, मेरे आस-पास की मशीन भिनभिनाती रही, गुनगुनाती रही, और क्लिक करती रही। जांच के अंत में, मुझे डेटा वाली एक सीडी मिली। ऐसी स्थिति में एक अच्छा डेवलपर क्या करता है? बेशक, जैसे ही वे घर पहुंचते हैं, वे डेटा की जांच करना शुरू कर देते हैं और सोचते हैं कि वे इसे पायथन का उपयोग करके कैसे निकाल सकते हैं।


सीडी में कई DLL, एक EXE और विंडोज व्यूअर के लिए कुछ अतिरिक्त फ़ाइलें थीं, जो स्पष्ट रूप से लिनक्स पर बेकार हैं। मुख्य बात DICOM नामक फ़ोल्डर में थी। इसमें आठ फ़ोल्डरों में एक्सटेंशन-रहित फ़ाइलों की एक श्रृंखला थी। ChatGPT ने मुझे यह समझने में मदद की कि DICOM एक मानक प्रारूप है जिसका उपयोग आम तौर पर MRI, CT और X-रे छवियों को संग्रहीत करने के लिए किया जाता है। अनिवार्य रूप से, यह एक सरल पैकेजिंग प्रारूप है जिसमें कुछ मेटाडेटा के साथ ग्रेस्केल छवियां शामिल हैं।


निम्नलिखित कोड आपको फ़ाइलों को PNG प्रारूप में आसानी से निर्यात करने की अनुमति देता है:


 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)


कोड दो पैरामीटर की अपेक्षा करता है। पहला DICOMDIR फ़ाइल का पथ है, और दूसरा वह निर्देशिका है जहाँ छवियाँ PNG प्रारूप में सहेजी जाएँगी।


DICOM फ़ाइलों को पढ़ने के लिए, हम Pydicom लाइब्रेरी का उपयोग करते हैं। संरचना को pydicom.dcmread फ़ंक्शन का उपयोग करके लोड किया जाता है, जिससे मेटाडेटा (जैसे कि रोगी का नाम) और छवियों वाले अध्ययन निकाले जा सकते हैं। छवि डेटा को dcmread के साथ भी पढ़ा जा सकता है। कच्चे डेटा को पिक्सेलएरे फ़ील्ड के माध्यम से एक्सेस किया जा सकता है, जिसे save_image फ़ंक्शन PNG में बदल देता है। यह बहुत जटिल नहीं है।


परिणाम स्वरूप कुछ वर्गाकार (आमतौर पर 512x512) ग्रेस्केल छवियां प्राप्त होती हैं, जिनका बाद में आसानी से उपयोग किया जा सकता है।


मुझे क्यों लगा कि DICOM प्रारूप का उपयोग करके अपने साहसिक कार्य के बारे में यह छोटी कहानी लिखना महत्वपूर्ण है? जब कोई प्रोग्रामर मेडिकल डेटा को प्रोसेस करने के बारे में सुनता है, तो उन्हें लगता है कि यह कुछ गंभीर बात है, कुछ ऐसा जिसे केवल विश्वविद्यालय और शोध संस्थान ही संभाल सकते हैं (कम से कम, मुझे तो यही लगा)। जैसा कि आप देख सकते हैं, हम सरल ग्रेस्केल छवियों के बारे में बात कर रहे हैं, जिन्हें प्रोसेस करना बहुत आसान है और न्यूरल नेटवर्क प्रोसेसिंग जैसी चीज़ों के लिए आदर्श हैं।


इस बात पर विचार करें कि इससे क्या संभावनाएँ खुलती हैं। एक साधारण ट्यूमर डिटेक्टर जैसी चीज़ के लिए, आपको बस एक अपेक्षाकृत सरल कन्वोल्यूशनल नेटवर्क और पर्याप्त संख्या में नमूनों की आवश्यकता होती है। वास्तव में, यह कार्य छवियों में कुत्तों या बिल्लियों को पहचानने से बहुत अलग नहीं है।


यह समझाने के लिए कि यह कितना सच है, मैं एक उदाहरण देता हूँ। कागल पर एक संक्षिप्त खोज के बाद, मुझे एक नोटबुक मिली जिसमें मस्तिष्क ट्यूमर को MRI डेटा (ग्रेस्केल इमेज) के आधार पर वर्गीकृत किया गया है। डेटासेट छवियों को चार समूहों में वर्गीकृत करता है: तीन प्रकार के मस्तिष्क ट्यूमर और स्वस्थ मस्तिष्क की छवियों वाली चौथी श्रेणी। नेटवर्क की संरचना इस प्रकार है:


 ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ ┃ 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 │ └─────────────────────────────────┴────────────────────────┴───────────────┘


जैसा कि आप देख सकते हैं, पहली कुछ परतों में एक कन्वोल्यूशन और मैक्स पूलिंग सैंडविच शामिल है, जो ट्यूमर के पैटर्न को निकालता है, उसके बाद दो सघन परतें होती हैं जो वर्गीकरण करती हैं। यह बिल्कुल वही आर्किटेक्चर है जिसका उपयोग TensorFlow के CNN सैंपल कोड में किया गया है जो CIFAR-10 डेटासेट का उपयोग करता है। मुझे यह अच्छी तरह याद है, क्योंकि यह मेरे सामने आने वाले पहले न्यूरल नेटवर्क में से एक था। CIFAR-10 डेटासेट में 60,000 छवियां हैं जिन्हें दस वर्गों में वर्गीकृत किया गया है, जिसमें कुत्तों और बिल्लियों के लिए दो वर्ग शामिल हैं, जैसा कि मैंने पहले उल्लेख किया था। नेटवर्क की वास्तुकला इस तरह दिखती है:


 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 _________________________________________________________________


यह स्पष्ट है कि हम एक ही आर्किटेक्चर के साथ काम कर रहे हैं, बस थोड़े अलग मापदंडों के साथ, इसलिए एमआरआई छवियों में मस्तिष्क ट्यूमर को पहचानना वास्तव में तस्वीरों में बिल्लियों या कुत्तों की पहचान करने से ज्यादा मुश्किल नहीं है। इसके अलावा, उल्लिखित कागल नोटबुक 99% प्रभावशीलता के साथ ट्यूमर को वर्गीकृत करने में सक्षम है!


मैं केवल यह बताना चाहता हूं कि कुछ मामलों में चिकित्सा डेटा निकालना और उसका प्रसंस्करण करना कितना सरल हो सकता है और मस्तिष्क ट्यूमर का पता लगाने जैसी जटिल प्रतीत होने वाली समस्याओं को अक्सर सरल, पारंपरिक समाधानों से काफी प्रभावी ढंग से हल किया जा सकता है।


इसलिए, मैं सभी को चिकित्सा डेटा से दूर न रहने के लिए प्रोत्साहित करूँगा। जैसा कि आप देख सकते हैं, हम अपेक्षाकृत सरल प्रारूपों से निपट रहे हैं, और अपेक्षाकृत सरल, अच्छी तरह से स्थापित तकनीकों (कन्वल्यूशनल नेटवर्क, विज़न ट्रांसफॉर्मर, आदि) का उपयोग करके, यहाँ एक महत्वपूर्ण प्रभाव प्राप्त किया जा सकता है। यदि आप अपने खाली समय में किसी ओपन-सोर्स हेल्थकेयर प्रोजेक्ट में सिर्फ़ एक शौक के तौर पर शामिल होते हैं और इस्तेमाल किए जाने वाले न्यूरल नेटवर्क में थोड़ा सा भी सुधार कर सकते हैं, तो आप संभावित रूप से जान बचा सकते हैं!