三维体素图绘制实验与教程

还是实验课内容,数据是Transunet的标签数据存成了npy格式,想把多器官分割结果用立体的方式表现出来,完整代码在最后,前面主要是搞的一些测试。体素的绘图具体参考了链接【1】,主要工具是python matplotlib包。matplotlib的一大主要问题就是大数据画图慢,因而下面体素的流程演示的数据采用【1】中的随机数生成。

xyzvalues = np.random.choice(range(0,10), size=(10,10,10))

首先结论是在大数据量时,散点图是绝对优于体素的,核心原因就是快,而在数据较少时,通常体素图画着比较快乐,散点图可能会分层。
另外勾线细一点比较好看。

三维器官效果展示

  • 体素:
    在这里插入图片描述
  • 散点:
    在这里插入图片描述
    在这里插入图片描述

详细流程

1.体素绘图

  • 核心命令:
fig = plt.figure(figsize=(7, 4.5))
ax = fig.gca(projection='3d')
ax.voxels(xyzvalues, facecolors=colorsvalues, edgecolor='k',shade=False,)

结果图如下,voxels的更详细用法见【4】:
在这里插入图片描述
edgecolor=None时效果如下:
在这里插入图片描述

  • 颜色表选取
mycolormap = plt.get_cmap('coolwarm')
xyzmaxvalue=xyzvalues.max()
relativevalue=np.round(xyzvalues/xyzmaxvalue,1)

plt提供了多种颜色表,具体见链接【5】
在这里插入图片描述
另外注意用于生成颜色表的数据必须归一化,不然会变成这样:
在这里插入图片描述

  • 不透明颜色表生成
colorsvalues=mycolormap(relativevalue)
  • 透明颜色表生成
sizeall=xyzvalues.size
zt=np.reshape(relativevalue,(sizeall,))
alpha=0.5
colorsvalue=np.array([(mycolormap(i)[0],mycolormap(i)[1],mycolormap(i)[2],alpha) for i in zt])
colorsvalues=np.reshape(colorsvalue,(d,w,h,4))

增加透明度,减轻遮挡,效果如下:
在这里插入图片描述

2.散点绘图
因为体素画着太慢,在此基础上我们尝试散点绘图.散点绘图速度快了许多,而且能鼠标拖动转了,就是有些时候效果非常的诡异。

  • 核心代码
ax.scatter(YL,XL,ZL,s=5, c=ZTL, cmap='coolwarm',edgecolors="k",linewidth=0.3,depthshade=True,alpha=0.3)

这个没什么能讲的,主要注意的是画黑边,大半径比较好看,透明度点多的时候其实没什么效果

  • 坐标变换
    先把数据的深度提到第三维里:
lab=np.load("TransUNet/testre/case0001_predicyion.npy")
labb=np.transpose(lab,(2,1,0))

提取绘图范围:

xlim=[200,320]
ylim=[180,300]
zlim=[95,105]

xyzvalues=labb[xlim[0]:xlim[1],ylim[0]:ylim[1],zlim[0]:zlim[1]]

生成坐标:

x=np.linspace(xlim[0],xlim[1]-1,-xlim[0]+xlim[1])
y=np.linspace(ylim[0],ylim[1]-1,-ylim[0]+ylim[1])
z=np.linspace(zlim[0],zlim[1]-1,-zlim[0]+zlim[1])
ZALL=zlim[1]-zlim[0]

XX,YY=np.meshgrid(x,y)
X=np.repeat(XX, ZALL,axis=1)
X=np.reshape(X,(d,w,h))
Y=np.repeat(YY, ZALL,axis=1)
Y=np.reshape(Y,(d,w,h))
zzz=np.ones((d,w,h))
Z=zzz*z

X=np.reshape(X,(-1,))
Y=np.reshape(Y,(-1,))
Z=np.reshape(Z,(-1,))

与体素不同,散点需要把没有标签的数据剔除,不然也会上色。

XL=[];YL=[];ZL=[];ZTL=[]
for i in range(sizeall):
    if zt[i]>0:
        XL.append(X[i])
        YL.append(Y[i])
        ZL.append(Z[i])
        ZTL.append(zt[i])

这部分代码写得时候太困了,应该有简化版本,但是懒了.jpg。

  • 不同大小的点的诡异效果:
    在选取的点数量较少的时候,散点图绘制会出现一些问题,首先看一眼体素效果:
    在这里插入图片描述
    小半径散点:
    在这里插入图片描述
    大半径散点:
    在这里插入图片描述
    所以说这种画法存在一个问题,小半径z轴连不起来,很明显一层一层的,大半径又膨胀太厉害。应当是因为z轴的刻度大,xy刻度小引起的,理论上应当可以通过改变坐标轴显示范围和刻度间隔来缓解,或者干脆选点的时候选成立方体范围。

完整代码

1.体素式绘图

lab=np.load("TransUNet/testre/case0001_predicyion.npy")
labb=np.transpose(lab,(2,1,0))
xlim=[200,320]
ylim=[180,300]
zlim=[95,105]
xyzvalues=labb[xlim[0]:xlim[1],ylim[0]:ylim[1],zlim[0]:zlim[1]]

mycolormap = plt.get_cmap('viridis')
xyzminvalue=xyzvalues.min()
xyzmaxvalue=xyzvalues.max()

relativevalue=np.round(xyzvalues/xyzmaxvalue,1)
colorsvaluesr = np.empty(xyzvalues.shape, dtype=object)
alpha=0.5
d,w,h=xyzvalues.shape
sizeall=xyzvalues.size
zt=np.reshape(relativevalue,(sizeall,))



colorsvalue=np.array([(mycolormap(i)[0],mycolormap(i)[1],mycolormap(i)[2],alpha) for i in zt])
colorsvalues=np.reshape(colorsvalue,(d,w,h,4))


fig = plt.figure(figsize=(7, 4.5))
ax = fig.gca(projection='3d')
pos=ax.voxels(xyzvalues, facecolors=colorsvalues, edgecolor='k',linewidth=0.3,shade=False,)



ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('3D Voxel Map')

plt.show()

2.散点式绘图

lab=np.load("TransUNet/testre/case0001_predicyion.npy")
labb=np.transpose(lab,(2,1,0))
xlim=[200,320]
ylim=[180,300]
zlim=[95,105]
xyzvalues=labb[xlim[0]:xlim[1],ylim[0]:ylim[1],zlim[0]:zlim[1]]

xyzminvalue=xyzvalues.min()
xyzmaxvalue=xyzvalues.max()

relativevalue=np.round(xyzvalues/xyzmaxvalue,1)
alpha=0.5
d,w,h=xyzvalues.shape
sizeall=xyzvalues.size
zt=np.reshape(relativevalue,(sizeall,))

fig = plt.figure(figsize=(7, 4.5))# Make a figure and axes with dimensions as desired.
ax = fig.gca(projection='3d')

x=np.linspace(xlim[0],xlim[1]-1,-xlim[0]+xlim[1])
y=np.linspace(ylim[0],ylim[1]-1,-ylim[0]+ylim[1])
z=np.linspace(zlim[0],zlim[1]-1,-zlim[0]+zlim[1])
ZALL=zlim[1]-zlim[0]

XX,YY=np.meshgrid(x,y)
X=np.repeat(XX, ZALL,axis=1)
X=np.reshape(X,(d,w,h))
Y=np.repeat(YY, ZALL,axis=1)
Y=np.reshape(Y,(d,w,h))
zzz=np.ones((d,w,h))
Z=zzz*z

X=np.reshape(X,(-1,))
Y=np.reshape(Y,(-1,))
Z=np.reshape(Z,(-1,))
XL=[];YL=[];ZL=[];ZTL=[]
for i in range(sizeall):
    if zt[i]>0:
        XL.append(X[i])
        YL.append(Y[i])
        ZL.append(Z[i])
        ZTL.append(zt[i])
ax.scatter(YL,XL,ZL,s=5, c=ZTL, cmap='coolwarm',edgecolors="k",linewidth=0.3,depthshade=True,alpha=0.3)

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('3D Voxel Map')

plt.show()

参考

【1】https://blog.csdn.net/weixin_39771351/article/details/111293632
【2】https://blog.csdn.net/qq_31225201/article/details/95619527
【3】https://blog.csdn.net/qq_37851620/article/details/100642566
【4】https://www.jianshu.com/p/03ed963eb51a
【5】https://blog.csdn.net/lly1122334/article/details/88535217
【6】https://blog.csdn.net/weixin_44520259/article/details/89917026

  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DICOM像的三维重建算法主要有面绘制算法和体绘制算法两种。面绘制算法中最常用的是Marching Cubes算法,它通过构建物体表面的面来进行三维重建。而体绘制算法则是直接绘制物体的三维体素,将离散的三维空间数据转换为立体像。在体绘制算法中,光线投射算法(Ray-casting)是最重要和通用的方法。 光线投射算法的原理是从像平面的每个像素点沿着视线方向发射一条射线,穿过体数据集,并按一定步长进行采样。通过内插计算每个采样点的颜色值和不透明度,并由前向后或由后向前逐点计算累计的颜色值和不透明度值,直至光线完全被吸收或穿过物体。光线投射算法能够很好地反映物质边界的变化,并使用Phong模型来实现镜面反射、漫反射和环境反射,从而获得良好的光照效果。在医学上,光线投射算法可以展示各种组织器官的性质属性、形状特征以及它们之间的层次关系,从而丰富了像的信息。 除了光线投射算法,体绘制算法还包括错切-变形算法(Shear-warp)、频域体绘制算法(Frequency Domain)和抛雪球算法(Splatting)。但光线投射算法是最为重要和通用的体绘制算法。 总之,面绘制算法和体绘制算法是DICOM三维重建中基于两种不同思路的算法,面绘制算法通过构建物体表面的面来绘制三维模型的轮廓,而体绘制算法直接绘制三维数据的每一个像素点,从而构建出包含内部空间信息的三维立体模型。详细的算法解析可以参考文献中的链接。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [DICOM像的三维重建算法——面绘制算法和体绘制算法](https://blog.csdn.net/weixin_42352178/article/details/109201572)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值