MRI(脑肿瘤)图像处理与分割,颅骨切除

Erk*_*rko 4 python image-processing object-detection image-segmentation

我需要图像分割方面的帮助。我有一张脑部肿瘤的 MRI 图像。我需要从 MRI 中取出颅骨(头骨),然后仅分割肿瘤对象。我怎么能在python中做到这一点?与图像处理。我试过制作轮廓,但我不知道如何找到并去除最大的轮廓,只得到没有头骨的大脑。非常感谢。

def get_brain(img):
  row_size = img.shape[0]
  col_size = img.shape[1]

  mean = np.mean(img)
  std = np.std(img)
  img = img - mean
  img = img / std

 middle = img[int(col_size / 5):int(col_size / 5 * 4), int(row_size / 5):int(row_size / 5 * 4)]
  mean = np.mean(middle)
  max = np.max(img)
  min = np.min(img)


  img[img == max] = mean
  img[img == min] = mean

  kmeans = KMeans(n_clusters=2).fit(np.reshape(middle, [np.prod(middle.shape), 1]))
  centers = sorted(kmeans.cluster_centers_.flatten())
  threshold = np.mean(centers)
  thresh_img = np.where(img < threshold, 1.0, 0.0)  # threshold the image


  eroded = morphology.erosion(thresh_img, np.ones([3, 3]))
  dilation = morphology.dilation(eroded, np.ones([5, 5]))
Run Code Online (Sandbox Code Playgroud)

这些图像与我正在查看的图像相似:

头骨 + 大脑

头骨 + 大脑 2

感谢您的回答。

Ric*_*ard 7

预赛

一些初步代码:

%matplotlib inline
import numpy as np
import cv2
from matplotlib import pyplot as plt
from skimage.morphology import extrema
from skimage.morphology import watershed as skwater

def ShowImage(title,img,ctype):
  plt.figure(figsize=(10, 10))
  if ctype=='bgr':
    b,g,r = cv2.split(img)       # get b,g,r
    rgb_img = cv2.merge([r,g,b])     # switch it to rgb
    plt.imshow(rgb_img)
  elif ctype=='hsv':
    rgb = cv2.cvtColor(img,cv2.COLOR_HSV2RGB)
    plt.imshow(rgb)
  elif ctype=='gray':
    plt.imshow(img,cmap='gray')
  elif ctype=='rgb':
    plt.imshow(img)
  else:
    raise Exception("Unknown colour type")
  plt.axis('off')
  plt.title(title)
  plt.show()
Run Code Online (Sandbox Code Playgroud)

作为参考,这是您链接到的大脑 + 头骨之一:

#Read in image
img           = cv2.imread('brain.png')
gray          = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ShowImage('Brain with Skull',gray,'gray')
Run Code Online (Sandbox Code Playgroud)

带头骨的大脑

提取掩码

如果图像中的像素可以分为两个不同的强度类别,即如果它们具有双峰直方图,则可以使用Otsu 的方法将它们阈值化为二值掩码。让我们检查一下这个假设。

#Make a histogram of the intensities in the grayscale image
plt.hist(gray.ravel(),256)
plt.show()
Run Code Online (Sandbox Code Playgroud)

直方图

好的,数据是很好的双峰。让我们应用阈值,看看我们如何做。

#Threshold the image to binary using Otsu's method
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_OTSU)
ShowImage('Applying Otsu',thresh,'gray')
Run Code Online (Sandbox Code Playgroud)

有门槛的大脑+头骨

如果我们将蒙版覆盖到原始图像上,事情会更容易看到

colormask = np.zeros(img.shape, dtype=np.uint8)
colormask[thresh!=0] = np.array((0,0,255))
blended = cv2.addWeighted(img,0.7,colormask,0.1,0)
ShowImage('Blended', blended, 'bgr')
Run Code Online (Sandbox Code Playgroud)

面具覆盖在大脑+头骨上

提取大脑

大脑(以红色显示)与面具的重叠非常完美,我们就到此为止。为此,让我们提取连接的组件并找到最大的组件,即大脑。

ret, markers = cv2.connectedComponents(thresh)

#Get the area taken by each component. Ignore label 0 since this is the background.
marker_area = [np.sum(markers==m) for m in range(np.max(markers)) if m!=0] 
#Get label of largest component by area
largest_component = np.argmax(marker_area)+1 #Add 1 since we dropped zero above                        
#Get pixels which correspond to the brain
brain_mask = markers==largest_component

brain_out = img.copy()
#In a copy of the original image, clear those pixels that don't correspond to the brain
brain_out[brain_mask==False] = (0,0,0)
ShowImage('Connected Components',brain_out,'rgb')
Run Code Online (Sandbox Code Playgroud)

用连接成分提取的大脑

考虑第二大脑

用你的第二张图片再次运行这个会产生一个有很多洞的面具:

第二大脑

我们可以使用闭合变换来闭合许多这样的洞:

brain_mask = np.uint8(brain_mask)
kernel = np.ones((8,8),np.uint8)
closing = cv2.morphologyEx(brain_mask, cv2.MORPH_CLOSE, kernel)
ShowImage('Closing', closing, 'gray')
Run Code Online (Sandbox Code Playgroud)

孔闭合的脑罩

我们现在可以提取大脑:

brain_out = img.copy()
#In a copy of the original image, clear those pixels that don't correspond to the brain
brain_out[closing==False] = (0,0,0)
ShowImage('Connected Components',brain_out,'rgb')
Run Code Online (Sandbox Code Playgroud)

具有更好面具的第二大脑

(请注意,如果您将其用于学术目的,则学术诚信需要适当的署名。请与我联系以获取详细信息。)