Python 如何在没有深入学习的情况下改进肺部分割
我的目标是使用快速常规方法从肺部3D CT扫描中获得每个体素沿切片轴的肺ROI逻辑OR 我尝试过使用不同的方法,如阈值和形态学和分水岭, 但是结果并不像你在下面的图片中看到的那样完美 我将每个体素的整个遮罩的逻辑OR与操作的结果输出进行比较,并根据切片轴的体素标准偏差提取ROI 我的问题是: 在逻辑OR之后,如何使结果看起来非常接近遮罩 使用的数据集(图像和遮罩)为 在下面的代码中,尝试将阈值和形态学结合起来,但问题是:Python 如何在没有深入学习的情况下改进肺部分割,python,image-processing,image-segmentation,scikit-image,medical,Python,Image Processing,Image Segmentation,Scikit Image,Medical,我的目标是使用快速常规方法从肺部3D CT扫描中获得每个体素沿切片轴的肺ROI逻辑OR 我尝试过使用不同的方法,如阈值和形态学和分水岭, 但是结果并不像你在下面的图片中看到的那样完美 我将每个体素的整个遮罩的逻辑OR与操作的结果输出进行比较,并根据切片轴的体素标准偏差提取ROI 我的问题是: 在逻辑OR之后,如何使结果看起来非常接近遮罩 使用的数据集(图像和遮罩)为 在下面的代码中,尝试将阈值和形态学结合起来,但问题是: # import necessary libraries import o
# import necessary libraries
import os
import numpy as np
import matplotlib.pyplot as plt
# plt.switch_backend('Qt5Agg')
import glob
import nibabel as nib
from skimage.io import imsave
from skimage.filters import threshold_otsu
from skimage.transform import resize
import skimage.morphology as morph
from skimage import measure, exposure , segmentation
from scipy import ndimage
#---------------------------------------------------------------
# Images
path = 'Nifti_DataSet/COVID-19-CT-Seg_20cases'
Dataset = glob.glob( os.path.join(path, '*.gz') )
# Masks
masks_path = 'Nifti_DataSet/Lung_and_Infection_Mask'
masks_Dataset = glob.glob( os.path.join(masks_path, '*.gz') )
#---------------------------------------------------------------
# Source: https://www.kaggle.com/threedb/improved-lung-segmentation-using-watershed
#---------------------------------------------------------------
def generate_markers(image,thr):
#Creation of the internal Marker
marker_internal = (image < thr*image.max()).reshape(image.shape)
marker_internal
marker_internal = segmentation.clear_border(marker_internal)
marker_internal_labels = measure.label(marker_internal)
areas = [r.area for r in measure.regionprops(marker_internal_labels)]
areas.sort()
if len(areas) > 2:
for region in measure.regionprops(marker_internal_labels):
if region.area < areas[-2]:
for coordinates in region.coords:
marker_internal_labels[coordinates[0], coordinates[1]] = 0
marker_internal = marker_internal_labels > 0
#Creation of the external Marker
external_a = ndimage.binary_dilation(marker_internal, iterations=10)
external_b = ndimage.binary_dilation(marker_internal, iterations=55)
marker_external = external_b ^ external_a
#Creation of the Watershed Marker matrix
marker_watershed = np.zeros((512, 512), dtype=np.int)
marker_watershed += marker_internal * 255
marker_watershed += marker_external * 128
return marker_internal, marker_external, marker_watershed
#================================================================================
def get_best_th(image):
seg = np.zeros_like(image)
for th in range(10):
th = th/10
m_internal,m_external, _ = generate_markers(image,th)
if( (np.sum(m_external) > np.sum(m_internal)) and (np.sum(m_internal) > np.sum(seg))):
seg = m_internal
#print(th)
return seg
#=====================================
def generate_watershed_segmentation(img):
img2 = exposure.equalize_hist(img)
segm = get_best_th(img2)
segm = np.array(segm)
segm = np.clip(segm,0,255)
return segm
#===============================================================
#
# Set a Counter
ctr = 1
#---------------------------------------------------------------
for image in Dataset:
# Load the images as nd-arrays
images = nib.load(image).get_fdata()
# Resize the images
masks = resize(images, (256,256))
# Load the masks as nd-arrays
masks = nib.load(os.path.join(masks_path,os.path.basename(image))).get_fdata()
# Resize the masks
masks = resize(masks, (256,256))
# make logical or for all the masks along slices axis
masks = masks.any(axis=2)
# print(masks.shape)
# Take the Std Deviation for all the images along slices axis
std = np.std(images, axis=2)
stdcp = std.copy()
# suppress the low values
std[std < 0.1 * np.max(std)] = 0.0
# Normalize The Output
image = 1. * std / np.max(std)
# Threshold the result
val = threshold_otsu(image-std)
image2 = (image-std) < val
# Threshold again after masking with the previous result
val2 = threshold_otsu(image2*image*(image-std))
result = (image2*image*(image-std)) < val2
#-------------------------------------------
# Morphology Part
#===========================================
# Structuring Element
radius = 5
# SE = morph.disk(radius)
SE = morph.star(radius)
# SE = morph.diamond(radius)
#-------------------------------------------
# Morphological Operations
#-------------------------------------------
res2 = morph.binary_erosion(result,selem=SE)
res2 = morph.remove_small_objects(res2)
# res2 = morph.binary_opening(res2,selem=SE)
res2 = morph.label(res2)
#---------Largest Connected Component--------------------
lab = np.argmax(np.unique(res2,return_counts=True)[1][1:])
lab +=1
res2[res2!=lab] = 0
res2 = res2.astype(np.uint8)
# ----More Morphological operations---------
res2 = morph.remove_small_holes(res2)
#-------------------------------------------
res3 = generate_watershed_segmentation(stdcp)
#-------------------------------------------
# Visualize the Results
#-------------------------------------------
plt.figure(num='image_%d'%ctr)
plt.subplot('221')
plt.imshow(masks)
plt.title('masks after Logical OR')
plt.axis('off')
plt.subplot('222')
plt.imshow(result)
plt.title('after first stage')
plt.axis('off')
plt.subplot('223')
plt.imshow(res2)
plt.title('Result')
plt.axis('off')
plt.subplot('224')
plt.imshow(res3)
plt.title('watershed')
plt.axis('off')
# figManager = plt.get_current_fig_manager()
# figManager.window.showMaximized()
plt.show()
#-----------------
# Increase the counter
ctr+=1
#导入必要的库
导入操作系统
将numpy作为np导入
将matplotlib.pyplot作为plt导入
#plt.switch_后端(“Qt5Agg”)
导入glob
将nibabel作为nib导入
从skimage.io导入imsave
从skimage.filters导入阈值\u otsu
从skimage.transform导入调整大小
将skimage.形态学导入为变形
从撇渣进口衡量、风险敞口、细分
从scipy导入ndimage
#---------------------------------------------------------------
#图像
路径='Nifti_数据集/COVID-19-CT-Seg_20例'
Dataset=glob.glob(os.path.join(path,*.gz'))
#面具
掩码\u路径='Nifti\u数据集/肺部\u和感染\u掩码'
masks_Dataset=glob.glob(os.path.join(masks_path,*.gz'))
#---------------------------------------------------------------
#资料来源:https://www.kaggle.com/threedb/improved-lung-segmentation-using-watershed
#---------------------------------------------------------------
def生成_标记(图像,thr):
#创建内部标记
marker_internal=(image2:
对于测量中的区域。区域属性(标记\u内部\u标签):
如果region.area<区域[-2]:
对于region.coords中的坐标:
标记\u内部\u标签[坐标[0],坐标[1]]=0
标记\u内部=标记\u内部\u标签>0
#创建外部标记
外部\u a=nImage.二进制\u膨胀(标记\u内部,迭代次数=10)
外部\u b=nImage.二进制\u膨胀(标记\u内部,迭代次数=55)
标记器\u外部=外部\u b^外部\u a
#流域标记矩阵的创建
marker_流域=np.zeros((512,512),dtype=np.int)
标记_流域+=标记_内部*255
标记_分水岭+=标记_外部*128
返回标记\内部、标记\外部、标记\分水岭
#================================================================================
def get_best_th(图像):
seg=np.类零(图)
对于范围(10)内的th:
th=th/10
m_内部,m_外部,u=生成标记(图像,th)
如果((np.sum(m_外部)>np.sum(m_内部))和(np.sum(m_内部)>np.sum(seg)):
seg=m_内部
#印刷品(th)
返回段
#=====================================
def生成流域分割(img):
img2=曝光。均衡历史(img)
segm=获得最佳值(img2)
segm=np.数组(segm)
segm=np.夹子(segm,0255)
返回segm
#===============================================================
#
#设置计数器
ctr=1
#---------------------------------------------------------------
对于数据集中的图像:
#将图像作为nd数组加载
images=nib.load(image.get_fdata()
#调整图像大小
遮罩=调整大小(图像,(256256))
#将掩码加载为nd数组
masks=nib.load(os.path.join(masks\u path,os.path.basename(image))).get\u fdata()
#调整遮罩的大小
遮罩=调整大小(遮罩,(256256))
#为沿轴的所有遮罩设置逻辑或
遮罩=遮罩。任意(轴=2)
#打印(遮罩.形状)
#取沿切片轴的所有图像的标准偏差
标准=np.std(图像,轴=2)
stdcp=标准副本()
#抑制低值
标准[标准<0.1*np.最大值(标准)]=0.0
#规范化输出
图像=1。*标准/净功率最大值(标准)
#阈值结果
val=阈值_大津(图像标准)
图像2=(图像标准)