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

还是实验课内容,数据是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.youkuaiyun.com/weixin_39771351/article/details/111293632
【2】https://blog.youkuaiyun.com/qq_31225201/article/details/95619527
【3】https://blog.youkuaiyun.com/qq_37851620/article/details/100642566
【4】https://www.jianshu.com/p/03ed963eb51a
【5】https://blog.youkuaiyun.com/lly1122334/article/details/88535217
【6】https://blog.youkuaiyun.com/weixin_44520259/article/details/89917026

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值