0

我正在处理包含患者头部但也包含金属圆柱体“阴影”的 CT 图像。

在此处输入图像描述

这些“阴影”可以出现在下方、左侧或右侧。在上图中,它仅出现在图像的下侧。在下图中,它出现在左右方向。我没有任何关于图像中是否有圆柱体阴影的先验知识。我必须以某种方式检测并删除它。然后我可以继续分割头骨/头部。

在此处输入图像描述

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

我怎样才能实现我的目标?

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


在此处输入图像描述


12张原始图片

在此处输入图像描述

12张图片二值化

在此处输入图像描述

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

在此处输入图像描述

用红色标记的图像不能帮助创建一个矩形蒙版,将包围头骨,这是我的最终目标。

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

4

2 回答 2

2

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

在代码中,这看起来像:

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


编辑

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

使用不同的输入图像,例如具有低得多的阈值的输入的二值化将有助于获得在腐蚀过程中不会消失的头部更大和非细的细节。

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

于 2019-10-07T09:22:45.020 回答
0

而不是像上面的 Ander Biguri 那样“纯”图像处理,我建议可能采用不同的方法(实际上是两种)。

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

1)鉴于容器是金属的(如您所说),另一种可能更容易的方法只是阈值,基于金属框架的特定 HU 编号。

虽然您将图像显示为简单的灰度,但实际上 CT 图像是 16 位图像,当以 256 位灰度表示查看时,这些图像是窗口水平的 - 所以上面的图片并不是图像数据中可用完整信息的真实表示,它实际上是16位。

金属框架的 HU 值可能与解剖结构内的任何物体显着不同(高于)。 如果是这种情况,那么简单的阈值化然后减法将是一种更简单的去除方法。

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

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

从那时起,您可以使用洪水填充方法(例如scikit flood_fill)来查找特定容差内的所有连接点。

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


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

于 2019-10-12T02:50:40.933 回答