Изоляция головы в изображении CT в градациях серого с использованием Python - PullRequest
0 голосов
/ 06 октября 2019

Я имею дело с КТ-изображениями, на которых изображена голова пациента, а также «тени» металлического цилиндра.

enter image description here

Эти тени'может появиться вниз, влево или вправо. На изображении выше он появляется только на нижней стороне изображения. На изображении ниже оно появляется в левом и правом направлениях. Я не знаю, есть ли на изображении тень цилиндра. Я должен как-то обнаружить это и удалить это. Затем я могу приступить к сегментированию черепа / головы.

enter image description here

Чтобы создать воспроизводимый пример, я хотел бы предоставить массив numpy (128x128), представляющийизображение, но я не знаю, как загрузить его в stackoverflow.

Как мне достичь своей цели?

Я пробовал сегментацию с помощью ndimage и scikit-image, но она не работает. Я получаю слишком много сегментов.


enter image description here


12 Исходные изображения

enter image description here

12 бинаризованных изображений

enter image description here

12Полосатые изображения (с расширением, эрозия = 0,1, 0,1)

enter image description here

Изображения, отмеченные красным цветом, не могут помочь создать прямоугольную маску, котораяобвив череп, что является моей конечной целью.

Обратите внимание, что я не смогу просматривать изображения по одному во время применения алгоритма.

Ответы [ 2 ]

2 голосов
/ 07 октября 2019

Вы можете использовать комбинацию эрозии (с соответствующим количеством итераций), чтобы удалить тонкие детали, а затем расширение (также с соответствующим количеством итераций), чтобы восстановить не тонкие детали примерно до исходного размера.

В коде это будет выглядеть следующим образом:

import io
import requests

import numpy as np
import scipy as sp
import matplotlib as mpl
import PIL as pil

import scipy.ndimage
import matplotlib.pyplot as plt


# : load the data
url = 'https://i.stack.imgur.com/G4cQO.png'
response = requests.get(url)
img = pil.Image.open(io.BytesIO(response.content)).convert('L')
arr = np.array(img)
mask_arr = arr.astype(bool)

# : strip thin objects
struct = None
n_erosion = 6
n_dilation = 7
strip_arr = sp.ndimage.binary_dilation(
    sp.ndimage.binary_erosion(mask_arr, struct, n_erosion),
    struct, n_dilation)

plt.imshow(mask_arr, cmap='gray')
plt.imshow(strip_arr, cmap='gray')
plt.imshow(mask_arr ^ strip_arr, cmap='gray')

Начиная с этого изображения (mask_arr):

mask_arr

Можно получить к этому изображению (strip_arr):

strip_arr

Разница составляет (mask_arr ^ strip_arr):

xor_arr


РЕДАКТИРОВАТЬ

(решение вопросов, поднятых в комментариях)

Использование другого входного изображения, напримербинаризация входа с гораздо более низким порогом поможет иметь более крупные и не тонкие детали головки, которые не исчезнут при эрозии.

В качестве альтернативы, вы можете получить более надежные результаты, установив эллипс на головку.

0 голосов
/ 12 октября 2019

Вместо «чистой» обработки изображений, как Андер Бигури выше, я бы предложил, возможно, другой подход (на самом деле два).

Концепция здесь заключается не в том, чтобы полагаться на чисто алгоритмическую обработку изображений, а на использование рычагов. знание специфики вашей ситуации:

1) Учитывая, что контейнер металлический (как вы сказали), другой подход, который может быть намного проще, - это просто пороговая обработка, основанная на определенном числе HU для металлаframe.

Хотя вы показываете изображения в виде простых оттенков серого, на самом деле изображения CT представляют собой 16-разрядные изображения с выравниванием по окну при просмотре в 256-битном представлении в оттенках серого, поэтому изображения выше не являются истинным представлением полного изображения. информация, доступная в данных изображения, которая на самом деле составляет 16 бит.

Металлический каркас, скорее всего, будет иметь значение HU, которое значительно отличается от (выше, чем) чего-либо в анатомии. Если этов таком случае, тогда простое пороговое значение, то вычитание будет гораздо прощеy, чтобы удалить его.

2) Другой подход также будет основан на рассмотрении геометрии и свойств конкретной ситуации:

На изображениях выше вы можете посмотреть на вертикальный профильвверх по центру изображения (по столбцам), чтобы найти местоположение рамки - где точка является точкой, в которой вертикальный профиль переходит в значение HU, соответствующее кадру.

С этой точки выможет использовать подход заливки (например, scikit flood_fill ), чтобы найти все связанные точки в пределах определенного допуска.

Это также даст вам набор точек (маску), совпадающий с рамкой, который вы можете использовать для удаления его из исходного изображения.


Я думаю, что любой из этихподходы будут более быстрыми и более надежными для ситуации, которую вы предлагаете.

...