使用 Python 在灰度 CT 图像中隔离头部

Isolating the head in a grayscale CT image using Python

我正在处理包含患者头部以及 'shadows' 金属圆柱体的 CT 图像。

这些 'shadows' 可以出现在下方、左侧或右侧。在上图中,它仅出现在图像的下侧。在下图中,它出现在左右方向。我不知道图像中是否有圆柱体的阴影。我必须以某种方式检测并删除它。然后我可以继续分割出 skull/head.

为了创建一个可重现的示例,我想提供代表图像的 numpy 数组 (128x128),但我不知道如何将它上传到 Whosebug。

如何实现我的 objective?

我尝试使用 ndimage 和 scikit-image 进行分割,但它不起作用。我得到的细分太多了。



12张原始图片

二值化的 12 张图像

剥离的 12 个图像(膨胀、腐蚀 = 0.1、0.1)

红色标注的图片不禁做出了一个长方形的遮罩,将头骨包裹起来,这就是我的终极objective。

请注意,在算法应用过程中,我将无法一张一张地检查图像。

您可以结合使用侵蚀(使用适当的迭代次数)来移除薄细节,然后使用膨胀(也使用适当的迭代次数)将非薄细节恢复到大约原始大小.

在代码中,这看起来像:

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):

有人会看到这张图片 (strip_arr):

不同之处在于 (mask_arr ^ strip_arr):


编辑

(解决评论中提出的问题)

使用不同的输入图像,例如使用低得多的阈值对输入进行二值化,将有助于获得更大且不薄的头部细节,这些细节不会在侵蚀过程中消失。

或者,您可以通过将椭圆拟合到头部来获得更可靠的结果。

而不是 "pure" 图像处理,如上面的 Ander Biguri,我建议可能采用不同的方法(实际上是两种)。

这里的概念是不依赖于纯粹的算法图像处理,而是利用您所拥有的具体情况的知识:

1) 鉴于容器是金属的(如您所述),另一种可能更简单的方法是根据金属框架的特定 HU 编号进行阈值处理。

虽然您将图像显示为简单的灰度图像,但实际上 CT 图像是 16 位图像,当以 256 位灰度表示形式查看时 window 已调平 - 因此上面的图片不是真实的表示图像数据中可用的全部信息,实际上是 16 位。

金属框架的 HU 值可能明显不同于(高于)解剖结构中的任何值。如果是这种情况,那么简单的阈值处理然后减法删除它会更简单。

2) 另一种方法也将基于考虑您所拥有的特定情况的几何形状和属性:

在上面的图像中,您可以在图像中间(按列)向上查看垂直剖面以找到框架的位置 - 该位置是垂直剖面与 HU 的交叉点与框架匹配的值。

从那时起,您可以使用泛洪填充方法(例如 scikit flood_fill)在特定公差范围内找到所有连接点。

这还会为您提供一组与框架匹配的点(蒙版),您可以使用这些点将其从原始图像中删除。


我认为对于您提出的情况,这两种方法中的任何一种都会更快、更可靠。