DICOM та Python — Частина 2: Аналіз біомедичних зображень для клінічних застосувань

pic

Створено за допомогою DALL·E ©

У цій статті ми розглянемо основи обробки та аналізу медичних (або біомедичних) зображень. З моменту появи перших рентгенівських зображень (які спочатку називалися рентгенівськими променями) та розробки першого комп'ютерного томографа (КТ) Сіром Годфрі Хаунсфілдом у 1972 році різні системи зображень здійснили революцію в медицині, дозволивши безопераційно візуалізувати внутрішні структури тіла.

Аналіз цих даних є центральним інструментом для діагностики та планування терапії в сучасній медицині, метою якого є отримання значущої інформації про анатомію, фізіологію та патологію людини з зображень. Анатомія досліджує склад та структуру людського тіла — органи, тканини та клітини — а також їх просторове розташування та зв'язки. Фізіологія займається процесами в тілі, аналізуючи, як різні органи та системи працюють разом. Патологія описує причини, розвиток та наслідки хвороб, досліджуючи анатомічні та фізіологічні зміни в організмі.

Для створення цих зображень потрібні різні пристрої, але обмін даними регулюється універсальним інтерфейсом — стандартом DICOM (Цифрові зображення та комунікації в медицині), який включає зберігання медичних зображень, а також супутніх метаданих. Це забезпечує безперешкодну інтеграцію та сумісність між різними пристроями зображень і програмними системами.

[

DICOM і Python — Частина 1: Дослідження інформації, що перевищує медичні зображення

medium.com

](/@dr.markus.bach/dicom-and-python-part-1-exploring-information-beyond-medical-images-2f35d56d7ec3?source=post_page-----19b0f0c563c5--------------------------------)

Ми почнемо з вивчення ключових аспектів обробки зображень за допомогою програмних прикладів: читання файлів DICOM і вилучення даних з зображень, визначення регіонів інтересу (ROI), виконання реєстрацій між двома модальностями зображень, автоматичне визначення та візуалізація сегментів, а також створення PDF-звіту з відповідними метриками.

Далі ми поєднаємо ці елементи в клінічному застосунку для автоматичної оцінки узгодженості калібрувань КТ, забезпечуючи правильну якість зображень і точність пристрою.

Основи аналізу медичних зображень

Аналіз зображень залежить від базової системи зображень. Спочатку ми розглянемо найбільш поширені системи, їх функціональність та медичну значимість.

Рентген та комп'ютерна томографія (КТ)

Рентгенівські зображення та комп'ютерна томографія — це основні методи зображення, які використовують рентгенівські промені для відображення радіоденсних властивостей тканин. Рентгенівські зображення представлені в градаціях сірого, де кісткові структури з'являються білими, а м'які тканини темніші. Це робить рентген особливо корисним для зображення кісток, суглобів та грудної клітки, а також для виявлення переломів, артриту та пневмонії.

КТ розширює ці можливості, створюючи детальні тривимірні серії зображень. Комбінуючи кілька рентгенівських зображень з різних кутів, КТ дозволяє більш точно аналізувати структури тіла. Це особливо цінно для діагностики пухлин, кровотеч, інфарктів та травм, оскільки КТ дає вищу точність деталей, ніж звичайні рентгенівські зображення. Крім того, КТ підтримує як анатомічні, так і патологічні дослідження, надаючи комплексну структурну інформацію. Деякі сканування також повторюються через короткі інтервали (також звані 4D, де час є четвертим виміром поряд із трьома просторовими напрямами) для захоплення функцій легень або серця.

Магнітно-резонансна томографія (МРТ)

Магнітно-резонансна томографія (МРТ) використовує сильні магнітні поля та радіохвилі для створення детальних зображень м'яких тканин. Це робить МРТ особливо корисним для зображення складних структур, таких як мозок, м'язи, зв'язки та внутрішні органи.
В анатомії МРТ дозволяє точно візуалізувати просторове розташування та зв'язки різних типів тканин.

У патології МРТ незамінне для виявлення пухлин, запалень, ушкоджень нервової системи та захворювань суглобів. Крім того, функціональна МРТ (fMRI) надає уявлення про фізіологію, вимірюючи активність мозку та кровообіг. Ці функціональні дані допомагають краще зрозуміти динамічні процеси та активність органів, що є важливим для неврологічних досліджень і вивчення функцій мозку.

Позитронно-емісійна томографія (ПЕТ)

Позитронно-емісійна томографія (ПЕТ) — це передова техніка зображення, яка вивчає функціональні аспекти тіла. Використовуючи радіоактивні мітки, що накопичуються в активних тканинах, ПЕТ може візуалізувати метаболізм і функціональну активність органів. Це особливо цінно в онкології для виявлення пухлин та моніторингу, оскільки ракові клітини часто проявляють підвищену метаболічну активність.

Окрім патології, ПЕТ дозволяє проводити фізіологічні дослідження, надаючи уявлення про метаболічні процеси та активність різних органів. Зазвичай ПЕТ комбінується з КТ (ПЕТ-КТ), щоб отримати як структурну, так і функціональну інформацію, що дозволяє здійснити більш комплексну діагностику та лікування. Візуалізація представлена як комбінація градації сірого для КТ та кольорове відображення функціональної активності ПЕТ. Обидві модальності зображення реєструються внутрішньо, щоб окремі ділянки збігалися на накладеному зображенні.

Ультразвук (сонографія)

Ультразвук (сонографія) використовує високочастотні звукові хвилі для відображення тканинних структур, що є перевагою, оскільки метод неінвазивний і не використовує радіацію. Це робить ультразвук особливо безпечним для вагітних жінок і підходить для повторних досліджень. В анатомії ультразвук дозволяє візуалізувати органи черевної порожнини, серце (ехокардіографія), кровоносні судини та проводити огляди під час вагітності.

У патології ультразвук допомагає виявляти кісти, пухлини, дефекти серця та стенози судин. Крім того, він дозволяє досліджувати функцію серця та динаміку кровотоку в фізіології, що є важливим для оцінки серцево-судинного здоров'я та діагностики серцевих захворювань.

Оптичні методи зображення та мікроскопічні техніки

Оптичне зображення включає методи, такі як оптична когерентна томографія (ОКТ), яка дозволяє створювати високоякісні зображення шарів тканин. Особливо в офтальмології ОКТ використовується для дослідження сітківки, генеруючи мікроскопічно детальні перерізи. Ця техніка є важливою як в анатомії, так і в патології, оскільки вона виявляє структурні зміни та патологічні процеси в тканинах.

Окрім макроскопічних методів зображення, мікроскопічні техніки відіграють важливу роль у вивченні клітинних структур і зразків тканин. У гістології клітинні структури аналізуються детально, в той час як патологія використовує мікроскопічні методи для ідентифікації та розуміння патологічних змін у клітинах. Ці методи незамінні для діагностики та розуміння захворювань на клітинному рівні.

Взаємодія дисциплін та методів зображення

Комбінація методів зображення дозволяє досягти комплексного розуміння людської анатомії, патології та фізіології. В той час як анатомія отримує користь від таких методів, як рентген, КТ, МРТ та ультразвук, які надають детальну структурну інформацію, патологія використовує методи, такі як ПЕТ, СКТ, МРС та мікроскопічні техніки для виявлення патологічних змін та їх причин. Фізіологія досліджується за допомогою функціональних методів зображення, таких як fMRI та ПЕТ, які надають уявлення про динамічні процеси та активність органів.

Інтеграція цих технологій, підтримувана стандартом DICOM, дозволяє здійснювати точну діагностику, ефективне лікування та глибоке розуміння складних біологічних процесів у людському тілі.
Часто кілька методів комбінуються для отримання повної картини анатомічних структур, патологічних змін і фізіологічних процесів, формуючи основу для комплексної медичної допомоги.

Робочий процес обробки зображень: від захоплення до постобробки

Процес обробки медичних зображень охоплює кілька етапів для забезпечення того, щоб захоплені зображення були точними і мали значення для діагностичних цілей або досліджень. Нижче ці етапи пояснено та доповнено програмними прикладами, де це доречно. Особливу увагу слід приділяти тому, щоб модифікації мінімально або зовсім не змінювали оригінальні дані зображення, особливо якщо в подальшому потрібно буде проводити кількісні оцінки.

Захоплення (Захоплення зображень)

Захоплення зображень є основою будь-якого медичного зображення, а інформація зберігається у вигляді файлів DICOM. Крім самих зображень, цей етап також включає внутрішні налаштування, які можуть бути зафіксовані в заголовку. Сучасні пристрої сьогодні забезпечують захоплення зображень, що відповідають найвищим стандартам. Наша програма в кінці цього етапу перевірить результати внутрішніх процесів за допомогою незалежного робочого процесу, щоб забезпечити надійність даних зображень.

Попередня обробка та покращення

Попередня обробка спочатку відокремлює сирі зображення від заголовка DICOM для кожного набору даних, що дозволяє нам зосередитись на обробці зображень і аналізі окремих зображень. Формат — це двовимірний (NumPy) масив, який ми можемо обробляти як матрицю.

Загальним етапом обробки є зменшення шуму, наприклад, за допомогою фільтрів Гауса або медіанних фільтрів для видалення небажаного шуму без втрати важливих деталей зображення. Перші методи цифрової обробки зображень були розроблені ще в 1960-х роках для зменшення шуму в супутникових зображеннях — техніка, яка сьогодні є такою ж важливою в медичних зображеннях.

Геометричні корекції виправляють спотворення або артефакти, що виникли під час захоплення зображення, забезпечуючи точне відображення анатомічних структур. Ці кроки є необхідними для багатьох додатків, щоб оптимізувати якість зображень для подальших методів аналізу.

Ми використовуємо лише імпорт і базове представлення загальної та специфічної для зображень інформації для нашої програми.

%pip install pydicom  
import pydicom  
import numpy as np  
import pandas as pd  
import matplotlib.pyplot as plt  

def split_dicom(dicom_path):  
 dicom = pydicom.dcmread(dicom_path)  
 header = dicom  
 if 'PixelData' in dicom:  
 image = dicom.pixel_array.astype(np.float32)  
 intercept = getattr(dicom, 'RescaleIntercept', 0.0)  
 slope = getattr(dicom, 'RescaleSlope', 1.0)  
 image = image * slope + intercept  
 else:  
 raise ValueError("The DICOM file does not contain pixel data.")  
 return header, image  

def dicom_stats_df(image, header):  
 image_stats_df = pd.DataFrame()  
 image_stats_df["PatientName"] = [header.PatientName]  
 image_stats_df["Modality"] = [header.Modality]  
 image_stats_df["StudyDate"] = [header.StudyDate]  
 image_stats_df["Shape"] = [image.shape]  
 image_stats_df["Min"] = [int(round(image.min(), 0))]  
 image_stats_df["Max"] = [int(round(image.max(), 0))]  
 image_stats_df["Mean"] = [float(f"{image.mean():.2f}")]  
 image_stats_df = image_stats_df.transpose().reset_index()  
 image_stats_df.columns = ["Element", "Value"]  
 return image_stats_df  

def display_image(pixel_array,  
 title="", cmap="gray", should_display=True,  
 should_save=False, output_path="image.png"):  
 plt.imshow(pixel_array, cmap=cmap)  
 plt.title(title)  
 plt.axis('off')  
 if should_save:  
 plt.savefig(output_path, bbox_inches='tight', pad_inches=0)  
 if should_display:  
 plt.show()  

dicom_path = 'file1.dcm'  
header, image = split_dicom(dicom_path)  
image_stats_df = dicom_stats_df(image, header)  
print(image_stats_df)  
display_image(image, title="Original DICOM")

Фантом (ліворуч) та вирізка зображення, витягнута з DICOM (праворуч)

Покращення зображення оптимізує видимість і чіткість даних зображення.
Техніки, такі як покращення контрасту за допомогою рівняння гістограми, роблять слабо відображені структури більш видимими. Підвищення різкості контурів виділяє краї і переходи, полегшуючи розпізнавання структур і покращуючи точність діагностики.

Однак це змінює самі дані зображення, що часто ускладнює кількісні оцінки. Ми пропустимо цей крок, але надамо альтернативу в наступному розділі.

Візуалізація (Data Visualization)

Візуалізація даних зображень має не лише технічне значення, але й є надзвичайно важливою для інтерпретації лікарями та дослідниками. Часто здійснюється нормалізація зображень, коли яскравість і контраст налаштовуються для забезпечення рівномірного представлення інтенсивності зображення. Чітка та інтуїтивно зрозуміла візуалізація може стати вирішальною між правильним діагнозом та помилковим судженням. Сучасні методи візуалізації включають розподіли в градаціях сірого, які оптимізують контраст для конкретних типів тканин, а також 3D реконструкції, які яскраво зображують складні анатомічні структури.

# Визначені вікна для легені, кісток та м'яких тканин  
lung_window = {'center': -600, 'width': 1500}  
bone_window = {'center': 300, 'width': 1500}  
soft_tissue_window = {'center': 40, 'width': 400}  

def apply_window(image, window):  
 window_center = window['center']  
 window_width = window['width']   
 lower = window_center - (window_width / 2)  
 upper = window_center + (window_width / 2)  
 windowed_image = np.clip(image, lower, upper)  
 windowed_image = (windowed_image - lower) / (upper - lower)  
 windowed_image = (windowed_image * 255).astype(np.uint8)  
 return windowed_image  
window_image = apply_window(image, lung_window)  
display_image(window_image, "Lung Window Applied")

Отримане зображення можна знайти на початку статті (праворуч)

Реєстрація (Image Registration)

Реєстрація зображень — це процес точного вирівнювання декількох наборів зображень з різних модальностей або в різний час. Це дозволяє порівнювати і виявляти зміни в розвитку захворювань. Трансформації, такі як зсуви, обертання або нелінійні трансформації, застосовуються для оптимального вирівнювання даних зображень.

Однак знаходження трансформацій на практиці досить складне і часто вимагає компромісів, оскільки точна реєстрація рідко досяжна.

Історичним етапом була перша успішна реєстрація зображень КТ та МРТ в 1980-х роках, що дозволило більш точно ставити діагнози. Сьогодні реєстрація зображень є незамінним інструментом в онкології, де вона допомагає точно відслідковувати зміни пухлин під час терапії.

Як приклад, ми застосовуємо зсуви (переміщення) та обертання за допомогою нашого коду. Структурна подібність (SSIM) є мірою для оцінки подібності між двома зображеннями. На відміну від простих метрик, таких як середня квадратична похибка (MSE) або пікове відношення сигнал/шум (PSNR), які враховують лише різниці в окремих значеннях пікселів, SSIM бере до уваги сприйману візуальну якість, аналізуючи структурну інформацію, яскравість і контраст.
Крім того, ми створюємо візуалізацію різниць шляхом віднімання двох наборів даних зображень і вибору колірної карти, яка відображає збіги зеленим кольором, а відмінності червоним або синім.

from skimage.metrics import structural_similarity as ssim  
from scipy.ndimage import shift, rotate  

def transform_image(image, shift_x=0, shift_y=0, angle=0):  
 """Повертає та зміщує зображення відповідно до заданих параметрів."""  
 # Спершу повертаємо  
 transformed = rotate(image, angle=angle, reshape=False, mode='nearest', order=1)  
 # Потім зміщуємо  
 transformed = shift(transformed, shift=(shift_y, shift_x), mode='nearest', order=1)  
 return transformed  
def evaluate_match(image1, image2, should_print=False):  
 """Обчислює значення SSIM для двох зображень."""  
 data_range = image1.max() - image1.min()  
 score, _ = ssim(image1, image2, full=True, data_range=data_range)  
 if should_print:  
 print(f"SSIM Score: {score:.4f}")  
 return score  
dicom_path = 'file2.dcm'  
header, image2 = split_dicom(dicom_path)  
evaluate_match(image, image2, should_print=True)  
transformed = transform_image(image2, 30, -30, 5)  
evaluate_match(image, transformed, should_print=True)  
display_image(image - transformed, "Difference Plot", cmap="jet")

Отримане зображення можна знайти на початку статті (внизу зліва).

Область інтересу (Region of Interest, RoI), сегментація зображення та вилучення ознак

Сегментація зображення – це процес ідентифікації та виділення релевантних структур або органів на зображенні. Оскільки цей пошук (як і інші складні алгоритми) часто є тривалим, спочатку ми обмежуємо область інтересу зображення. Цей фрагмент називається областю інтересу (Region of Interest, RoI) і може бути визначений різними способами. Ми задаємо нову висоту та ширину, а також центр області RoI (якщо його явно не вказано, за замовчуванням використовується центр зображення). Крім того, функція генерує значення для візуалізації (matplotlib використовує нижній лівий кут замість центру).

def define_roi(image, height, width, image_center=None):  
 if not image_center:  
 image_center = (image.shape[0] // 2, image.shape[1] // 2)  
 roi_start = (image_center[0] - height // 2,  
 image_center[1] - width // 2)  
 roi_extent = (height, width)  
 roi = image[roi_start[0] : roi_start[0] + height,  
 roi_start[1] : roi_start[1] + width]  
 return roi, roi_start, roi_extent  


def display_overlay(image, roi_start, roi_extent):  
 roi = image[roi_start[0]:roi_start[0] + roi_extent[0],  
 roi_start[1]:roi_start[1] + roi_extent[1]]  
 fig, axes = plt.subplots(figsize=(6, 6))  
 axes.imshow(image, cmap='gray')  
 axes.add_patch(plt.Rectangle((roi_start[1], roi_start[0]),  
 roi_extent[1], roi_extent[0],  
 edgecolor='red', facecolor='none'))  
 plt.title("Region of Interest")  
 plt.axis("off")  
 plt.show()  


roi, roi_start, roi_extent = define_roi(image, 120, 120)  
display_overlay(image, roi_start, roi_extent)

Отримане зображення можна знайти на початку статті (вгорі зліва).

Для фактичної сегментації використовуються такі методи, як розширення регіонів (region growing) і порогове значення (thresholding), щоб відокремити цікаві області на основі інтенсивності або інших ознак. Сучасні підходи застосовують машинне навчання (Machine Learning), зокрема згорткові нейронні мережі (Convolutional Neural Networks, CNN), для точного сегментування складних анатомічних структур. Ці алгоритми в деяких випадках досягли точності, порівнянної з досвідом досвідчених радіологів.

Тут ми використовуємо класичний метод із заздалегідь визначеними кольорами та налаштовуваним порогом.
Ми також визначаємо мінімальний розмір і вимірюємо індивідуальні сегменти.

from skimage import filters, measure  

COLOR_MAP = {  
 "red": (255, 0, 0),  
 "green": (0, 255, 0),  
 "blue": (0, 0, 255),  
 "yellow": (255, 255, 0),  
 "cyan": (0, 255, 255),  
 "magenta": (255, 0, 255),  
 "orange": (255, 165, 0),  
 "purple": (128, 0, 128),  
 "lime": (191, 255, 0),  
 "pink": (255, 105, 180),  
 "brown": (139, 69, 19)  
}  
def segment_image(image, sensitivity=1, min_area=20):  
 otsu_threshold = filters.threshold_otsu(image)  
 adjusted_threshold = otsu_threshold * sensitivity  
 binary_image = image > adjusted_threshold  
 labels = measure.label(binary_image)  
 cleaned_labels = []  
 cleaned_segment_stats = []  
 for region in measure.regionprops(labels, intensity_image=image):  
 if region.area >= min_area:  
 color_name, rgb_value = get_color_by_label(region.label)  
 cleaned_labels.append(region.label)  
 cleaned_segment_stats.append({  
 "Label": region.label,  
 "Color": color_name,  
 "Pixel Count": int(round(region.area, 0)),  
 "Min": int(round(region.min_intensity, 0)),  
 "Max": int(round(region.max_intensity, 0)),  
 "Mean": round(region.mean_intensity, 2),  
 "Pos X": region.centroid[1],  
 "Pos Y": region.centroid[0],  
 "RGB": rgb_value  
 })  
 final_labels = np.where(np.isin(labels, cleaned_labels), labels, 0)  
 return final_labels, cleaned_segment_stats  
def get_color_by_label(label):  
 color_names = list(COLOR_MAP.keys())  
 chosen_color_name = color_names[label % len(color_names)]  
 return chosen_color_name, COLOR_MAP[chosen_color_name]  
def apply_custom_colormap(label_image, segment_stats):  
 colored_image = np.zeros((*label_image.shape, 3), dtype=np.uint8)  
 for segment in segment_stats:  
 label_val = segment["Label"]  
 rgb_value = segment["RGB"]  
 colored_image[label_image == label_val] = rgb_value  
 return colored_image  
def display_segments(labels, stats, title="", cmap="gray"):  
 fig, axes = plt.subplots(figsize=(6, 6))  
 colored_segments = apply_custom_colormap(labels, stats)  
 axes.imshow(colored_segments)  
 axes.set_title(title)  
 axes.axis("off")  
 plt.show()  
labels, segment_stats = segment_image(roi)  
segment_image = display_segments(labels, segment_stats)  
segment_stats_df = pd.DataFrame(segment_stats)  
print(segment_stats_df)

Отримане зображення можна знайти на початку статті (внизу справа).

Аналіз ознак досліджує сегментовані області для визначення характерних властивостей. Сюди входить аналіз текстури (Texture Analysis), який досліджує поверхневі властивості та візерунки тканин. Визначаються характеристики форми та розміру, такі як площа, периметр і об'єм, для отримання діагностичних висновків. Аналіз гістограми (Histogram Analysis) досліджує розподіл інтенсивності, щоб охарактеризувати типи тканин або клітин, що є особливо корисним для розрізнення здорових та уражених тканин.

Приклад із практики: в онкології ці ознаки використовуються для вимірювання розмірів пухлин та моніторингу реакції на терапію. Завдяки точному аналізу ознак лікарі можуть розробляти персоналізовані плани лікування та уважно відстежувати успішність терапії.

Наш DataFrame (див. нижче) містить статистичні значення для окремих сегментів, часова динаміка яких може використовуватися для перевірки узгодженості (consistency over time).

Постобробка

Постобробка включає ефективне зберігання та стискання оброблених даних зображень із збереженням важливої інформації. Це не лише економить місце на носіях, а й пришвидшує доступ до даних. Крім того, створюються звіти та візуалізації для клінічних чи дослідницьких цілей. Ці звіти слугують для документування діагнозів або представлення результатів досліджень.

З розвитком цифровізації та мереж у сфері охорони здоров'я постобробка набуває все більшого значення.
Хмарні рішення (Cloud-based solutions) дозволяють безпечно обмінюватися та ділитися даними зображень між різними установами, що значно покращує співпрацю та передачу знань.

from matplotlib.backends.backend_pdf import PdfPages  

def add_page(pdf, image, df, cmap='gray', title=""):  
 fig = plt.figure(figsize=(8.27, 11.69)) # DIN A4 portrait  
 grid = fig.add_gridspec(2, 1, height_ratios=[2, 1])  
 # Image on top  
 ax1 = fig.add_subplot(grid[0])  
 ax1.imshow(image, cmap=cmap)  
 ax1.set_title(title)  
 ax1.axis("off")  
 # Table below  
 ax2 = fig.add_subplot(grid[1])  
 ax2.axis("tight")  
 ax2.axis("off")  
 table = ax2.table(cellText=df.values,  
 colLabels=df.columns,  
 loc="center")  
 table.auto_set_font_size(False)  
 table.set_fontsize(10)  
 # Save the combined page  
 pdf.savefig(fig)  
 plt.close(fig)  


with PdfPages('report.pdf') as pdf:  
 add_page(pdf, image, image_stats_df, title="Original DICOM")

Увесь процес обробки медичних зображень — від отримання (Acquisition) до попередньої обробки (Preprocessing), візуалізації (Visualization), реєстрації (Registration), сегментації (Segmentation), покращення (Enhancements), вилучення ознак (Feature Extraction) та до постобробки (Postprocessing) — є складною взаємодією сучасних технологій та інноваційних методів. Кожен етап сприяє максимізації якості та інформативності даних зображень, що зрештою призводить до точніших діагнозів та ефективніших методів терапії. Завдяки постійним дослідженням і технологічним досягненням обробка медичних зображень продовжуватиме відігравати центральну роль у сфері охорони здоров'я.

Приклад застосування: перевірка якості та тестування на узгодженість

У повсякденній клінічній практиці пристрої для візуалізації мають регулярно перевірятися на узгодженість і правильність налаштувань. Спеціальні фантоми (тестові об'єкти) скануються та оцінюються за допомогою стандартних процедур. Автоматизований аналіз зображень значно спрощує та прискорює цей процес, забезпечуючи точні та відтворювані результати. Це є критично важливим для підтримки стабільності якості зображень та точності діагностики, тим самим гарантується надійність результатів.

Нижче ми представляємо повний код прикладного робочого процесу, який відображає описані вище етапи. Програма розділена на сім взаємопов’язаних секцій. Частини коду знайомі з наведених вище прикладів. Цей робочий процес може виконуватися в середовищах розробки, таких як Jupyter Notebook або безпосередньо в Google Colab. Додаткові пояснення наводяться в кінці.

Пояснення використаних бібліотек та функцій

У цьому підрозділі ми детальніше розглядаємо найважливіші бібліотеки та функції, щоб зрозуміти їхню роль у цьому робочому процесі.

  • pydicom — це бібліотека Python, яка дозволяє читати, записувати та редагувати файли DICOM. У нашій функції split_dicom() ми читаємо файл і відокремлюємо заголовок від даних зображення.
  • OpenCV (cv2) — широко використовувана бібліотека для обробки зображень та комп'ютерного зору (Computer Vision). Ми використовуємо її, зокрема, для нормалізації та обчислення афінних перетворень у identify_transformation() (використовуючи функцію cv2.findTransformECC).
  • NumPy (np) — основна бібліотека для чисельних обчислень у Python. Ми використовуємо її для створення масивів, виконання математичних операцій і представлення зображень (наприклад, pixel_array.astype(np.float32) у split_dicom()).
  • Pandas (pd) — забезпечує зручне управління даними у вигляді DataFrame. Ми зберігаємо інформацію про зображення, сегменти та статистику збігів у DataFrame і використовуємо їх для створення звітів.
  • matplotlib та matplotlib.backends.backend_pdf — використовуються для створення графіків і діаграм. matplotlib.pyplot є високорівневим інтерфейсом, наприклад, для plt.imshow(). Крім того, ми використовуємо PdfPages, щоб створювати PDF-звіти, які об’єднують зображення та таблиці.
  • skimage (scikit-image) надає безліч функцій для обробки зображень, таких як обчислення порогу Оцу (filters.threshold_otsu) або функції сегментації (measure.label).
    Крім того, skimage.metrics використовується для вимірювання структурної подібності (SSIM).
  • scipy.ndimage застосовується для реєстрації або трансформації зображень. Ми використовуємо функції shift і rotate, щоб зміщувати або обертати зображення.

Користувацькі функції

  • split_dicom(dicom_path):
    Зчитує файл DICOM, витягує заголовок і конвертує піксельний масив у одиниці Гаунсфілда (CT-діапазон).
  • define_roi(image, height, width, image_center=None):
    Обрізає область інтересу (Region of Interest, ROI) із зображення.
  • dicom_stats_df(image, header):
    Створює Pandas DataFrame із важливою інформацією про зображення та заголовок (наприклад, PatientName, Min/Max значення, Mean тощо).
  • Функції відображення та побудови графіків (display_image(), display_overlay(), display_segments()):
    Полегшують візуалізацію оригінальних зображень, накладання рамок (ROI) і сегментованих областей.
  • best_match(ref_image, test_image):
    Поєднує кроки реєстрації зображень (через identify_transformation) і порівнює значення SSIM до та після реєстрації.
  • Функції сегментації (segment_image(), apply_custom_colormap()):
    Функція segment_image() виконує сегментацію методом Оцу (Otsu segmentation) і повертає інформацію про мітки, тоді як apply_custom_colormap() візуалізує результати в кольорі.
  • add_page():
    Використовує matplotlib і PdfPages для розміщення зображень разом із статистичними таблицями на сторінці PDF.

Підсумок та перспективи

У цій статті ми розглянули основні аспекти обробки та аналізу біомедичних даних зображень і протестували їх за допомогою Python-коду. На основі цих прикладів можна адаптувати індивідуальні вимоги, такі як оцінювання специфічних калібрувальних фантомів, розрахунок додаткових параметрів зображення або впровадження додаткових (з підтримкою AI) аналізів ознак. Автоматизація — наприклад, регулярний імпорт і аналіз нових DICOM-файлів — також відносно легко реалізується за допомогою Python.

Будь ласка, надсилайте свої запитання та пропозиції: [email protected]

Бажаю успіхів в експериментах і подальшій розробці!

Перекладено з: DICOM and Python — Part 2: Biomedical Image Analysis for Clinical Applications

Leave a Reply

Your email address will not be published. Required fields are marked *