কয়েকদিন আগে, আমি একটি এমআরআই স্ক্যান করিয়েছি। তারা আমাকে একটি বড় টিউবে স্লাইড করে, এবং 15 মিনিটের জন্য, আমার চারপাশের মেশিনটি গুঞ্জন, গুনগুন করে এবং ক্লিক করে। পরীক্ষা শেষে তথ্য সম্বলিত একটি সিডি পেলাম। এমন পরিস্থিতিতে একজন ভালো ডেভেলপার কী করবেন? অবশ্যই, তারা বাড়িতে পৌঁছানোর সাথে সাথে, তারা ডেটা পরীক্ষা করা শুরু করে এবং কীভাবে তারা পাইথন ব্যবহার করে এটি বের করতে পারে তা নিয়ে ভাবতে শুরু করে।
সিডিতে একগুচ্ছ ডিএলএল, একটি EXE এবং উইন্ডোজ ভিউয়ারের জন্য কয়েকটি অতিরিক্ত ফাইল রয়েছে, যা লিনাক্সে স্পষ্টতই অকেজো। ক্রাক্সটি DICOM নামে একটি ফোল্ডারে ছিল। এটি আটটি ফোল্ডার জুড়ে এক্সটেনশন-হীন ফাইলগুলির একটি সিরিজ ধারণ করেছে। ChatGPT আমাকে বুঝতে সাহায্য করেছে যে DICOM হল একটি স্ট্যান্ডার্ড ফরম্যাট যা সাধারণত MRI, CT এবং এক্স-রে ছবি সংরক্ষণের জন্য ব্যবহৃত হয়। মূলত, এটি একটি সাধারণ প্যাকেজিং বিন্যাস যাতে কিছু মেটাডেটা সহ গ্রেস্কেল চিত্র রয়েছে।
নিম্নলিখিত কোডটি আপনাকে সহজেই 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 ফরম্যাট ব্যবহার করে আমার অ্যাডভেঞ্চার সম্পর্কে এই ছোট গল্পটি লিখতে কেন আমি মনে করি? যখন একজন প্রোগ্রামার মেডিকেল ডেটা প্রক্রিয়াকরণের কথা শুনেন, তখন তারা মনে করতে পারে এটি গুরুতর কিছু, এমন কিছু যা শুধুমাত্র বিশ্ববিদ্যালয় এবং গবেষণা প্রতিষ্ঠানগুলি পরিচালনা করতে পারে (অন্তত, আমি যা ভেবেছিলাম)। আপনি দেখতে পাচ্ছেন, আমরা সাধারণ গ্রেস্কেল চিত্রগুলির কথা বলছি, যেগুলি প্রক্রিয়া করা খুব সহজ এবং নিউরাল নেটওয়ার্ক প্রক্রিয়াকরণের মতো জিনিসগুলির জন্য আদর্শ৷
এটি খোলার সম্ভাবনাগুলি বিবেচনা করুন। একটি সাধারণ টিউমার ডিটেক্টরের মতো কিছুর জন্য, আপনার যা প্রয়োজন তা হল একটি অপেক্ষাকৃত সহজবোধ্য কনভোল্যুশনাল নেটওয়ার্ক এবং পর্যাপ্ত সংখ্যক নমুনা। বাস্তবে, কাজটি চিত্রগুলিতে কুকুর বা বিড়াল সনাক্ত করার থেকে খুব বেশি আলাদা নয়।
এটি কতটা সত্য তা বোঝাতে, আমি একটি উদাহরণ দিই। কাগলের উপর একটি সংক্ষিপ্ত অনুসন্ধানের পরে, আমি একটি নোটবুক পেয়েছি যেখানে মস্তিষ্কের টিউমারগুলি এমআরআই ডেটা (গ্রেস্কেল চিত্র) এর উপর ভিত্তি করে শ্রেণীবদ্ধ করা হয়েছে। ডেটাসেট চিত্রগুলিকে চারটি গ্রুপে শ্রেণীবদ্ধ করে: তিন ধরণের মস্তিষ্কের টিউমার এবং একটি সুস্থ মস্তিষ্কের চিত্র সহ চতুর্থ বিভাগ। নেটওয়ার্কের আর্কিটেকচার নিম্নরূপ:
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ ┃ 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 _________________________________________________________________
এটা স্পষ্ট যে আমরা একই স্থাপত্যের সাথে কাজ করছি, শুধুমাত্র সামান্য ভিন্ন প্যারামিটারের সাথে, তাই এমআরআই ছবিতে মস্তিষ্কের টিউমার সনাক্ত করা ছবিতে বিড়াল বা কুকুর সনাক্ত করার চেয়ে বেশি কঠিন নয়। উপরন্তু, উল্লিখিত Kaggle নোটবুক 99% কার্যকারিতা সহ টিউমার শ্রেণীবদ্ধ করতে সক্ষম!
আমি শুধু উল্লেখ করতে চাই যে নির্দিষ্ট কিছু ক্ষেত্রে মেডিকেল ডেটা বের করা এবং প্রক্রিয়া করা কতটা সহজ হতে পারে এবং কীভাবে জটিল বলে মনে হয়, যেমন মস্তিষ্কের টিউমার শনাক্ত করা, প্রায়শই সহজ, ঐতিহ্যগত সমাধানগুলির মাধ্যমে বেশ কার্যকরভাবে সমাধান করা যেতে পারে।
অতএব, আমি সবাইকে মেডিকেল ডেটা থেকে লজ্জা না পেতে উত্সাহিত করব। আপনি দেখতে পাচ্ছেন, আমরা তুলনামূলকভাবে সহজ ফরম্যাট নিয়ে কাজ করছি, এবং তুলনামূলকভাবে সহজ, সু-প্রতিষ্ঠিত প্রযুক্তি (কনভোলিউশনাল নেটওয়ার্ক, ভিশন ট্রান্সফরমার ইত্যাদি) ব্যবহার করে এখানে একটি উল্লেখযোগ্য প্রভাব অর্জন করা যেতে পারে। আপনি যদি শুধুমাত্র একটি শখ হিসাবে আপনার অতিরিক্ত সময়ে একটি ওপেন-সোর্স স্বাস্থ্যসেবা প্রকল্পে যোগদান করেন এবং ব্যবহৃত নিউরাল নেটওয়ার্কে এমনকি সামান্য উন্নতি করতে পারেন, তাহলে আপনি সম্ভাব্য জীবন বাঁচাতে পারেন!