3d 如何在python中获得dicom切片的三维重建?
我有一个目录,其中包含一次扫描的.dcm文件。我能够获得2D视图(我与其他dicom查看器进行了交叉检查)。但我无法让3D视图正常工作。我尝试使用3d 如何在python中获得dicom切片的三维重建?,3d,vtk,dicom,pydicom,3d,Vtk,Dicom,Pydicom,我有一个目录,其中包含一次扫描的.dcm文件。我能够获得2D视图(我与其他dicom查看器进行了交叉检查)。但我无法让3D视图正常工作。我尝试使用vtkDICOMImageReader类,但它无法读取文件。因此,我尝试从3D numpy数组中获取一个体积对象,并使用vtkplotter显示它。得出的观点显然是错误的。我认为3D阵列需要一些处理 import time import glob import pydicom import numpy as np from vtkplotter imp
vtkDICOMImageReader
类,但它无法读取文件。因此,我尝试从3D numpy数组中获取一个体积对象,并使用vtkplotter
显示它。得出的观点显然是错误的。我认为3D阵列需要一些处理
import time
import glob
import pydicom
import numpy as np
from vtkplotter import Volume
import sys, os
def main(folderPath):
st = time.time()
my_glob = glob.glob1(folderPath, "*")
numFiles = 0
rejected = 0
# return if empty directory
if len(my_glob) == 0:
return False
# get all readable dicom files in array
tem = []
for file in list(my_glob):
try:
data_item = pydicom.dcmread(os.path.join(folderPath, file))
if hasattr(data_item, 'SliceLocation'):
tem.append(data_item)
numFiles += 1
else:
rejected += 1
print(file)
except Exception as e:
pass
print("read done %s | %d files | %d rejected" % (time.time() - st, numFiles, rejected))
if len(tem) <= 0:
return False
tem.sort(key=lambda x: x.InstanceNumber)
# make 3d np array from all slices
unset = True
for i in range(len(tem)):
arr = tem[i].pixel_array.astype(np.float32)
if unset:
imShape = (arr.shape[0], arr.shape[1], len(tem))
scaledIm = np.zeros(imShape)
pix_spacing = tem[i].PixelSpacing
dist = 0
for j in range(2):
cs = [float(q) for q in tem[j].ImageOrientationPatient]
ipp = [float(q) for q in tem[j].ImagePositionPatient]
parity = pow(-1, j)
dist += parity*(cs[1]*cs[5] - cs[2]*cs[4])*ipp[0]
dist += parity*(cs[2]*cs[3] - cs[0]*cs[5])*ipp[1]
dist += parity*(cs[0]*cs[4] - cs[1]*cs[3])*ipp[2]
z_spacing = abs(dist)
slope = tem[i].RescaleSlope
intercept = tem[i].RescaleIntercept
unset = False
scaledIm[:, :, i] = arr
# convert to hounsfield units
scaledIm = slope*scaledIm + intercept
pix_spacing.append(z_spacing)
wl = 300 # window parameters for Angio
ww = 600
windowed = np.zeros(imShape, dtype=np.uint8)
# allImages[scaledIm <= (wl-0.5-(ww-1)/2.0)] = 0
k = np.logical_and(scaledIm > (wl-0.5-(ww-1)/2.0), scaledIm <= (wl-0.5+(ww-1)/2.0))
windowed[k] = ((scaledIm[k] - (wl-0.5))/(ww-1)+0.5)*255
windowed[scaledIm > (wl-0.5+(ww-1)/2.0)] = 255
# windowed image (in 2D) is correct i checked visually in other DICOM viewers
print("arrays made %s" % (time.time() - st))
# Volume(scaledIm, spacing=pix_spacing).show(bg="black")
Volume(windowed, spacing=pix_spacing).show(bg="black")
# X, Y, Z = np.mgrid[:30, :30, :30]
# scalar_field = ((X-15)**2 + (Y-15)**2 + (Z-15)**2)/225
# Volume(scalar_field, spacing=pix_spacing).show(bg="black") # looks good on this example
if __name__ == '__main__':
folder = sys.argv[1]
main(folder)
导入时间
导入glob
导入pydicom
将numpy作为np导入
从vtkplotter导入卷
导入系统,操作系统
def主(文件夹路径):
st=时间。时间()
my_glob=glob.glob1(folderPath,“*”)
numFiles=0
拒绝=0
#如果目录为空,则返回
如果len(my_glob)==0:
返回错误
#获取数组中的所有可读dicom文件
tem=[]
对于列表中的文件(my_glob):
尝试:
data_item=pydicom.dcmread(os.path.join(folderPath,file))
如果hasattr(数据项“切片位置”):
附加项(数据项)
numFiles+=1
其他:
拒绝+=1
打印(文件)
例外情况除外,如e:
通过
打印(“读取完成%s |%d个文件|%d个已拒绝”%(time.time()-st,numFiles,已拒绝))
如果len(tem)我无法再现该问题,因为我从pydicom收到一条错误消息:
AttributeError:“FileDataset”对象没有属性“RescaleSlope”
无论如何,您可以尝试以下方法:
- 更新至最新提交
pip-install-git+https://github.com/marcomusy/vtkplotter.git
- 将
卷
实例化修改为:
#请注意,pix_间距[0]和pix_间距[2]可能是反向的
体积=体积(带窗口,间距=像素间距)
第二卷,第1卷,第0卷,镜像(“y”)
卷展(bg=“黑色”)
你也可以退房
- 另一种可能是使用
load(mydicomdir,threshold=False)
直接加载目录,这将返回一个卷
- 请随时打开一个问题