本文讲述医学图像配准中形变场的可视化,包括一种直接通过工具查看的方法和两种手工绘制的方法。

首先来介绍一下形变场,一个大小为[W,H]的二维图像对应的形变场的大小是[W,H,2],其中第三个维度的大小为2,分别表示在x轴和y轴方向的位移。同理,一个大小为[D,W,H]的三维图像对应的形变场的大小是[D,W,H,3],其中第三个维度的大小为3,分别表示在x轴、y轴和z轴方向的位移。下图是一个二维脑部图像配准后得到的形变场。

如一开始所说,下面介绍3中方式来将形变场可视化。

1. 使用ITK-Snap可视化形变场

这种方式是最便捷也是我认为效果最好的,但是只适用于三维的形变场。首先将形变场保存为".nii"图像,用ITK-Snap工具打开,首先在下图红框的位置悬停一段时间,出现下图中的图标后点击,选择“Multi-Component Display”下面的“Grid”,就可以看到下图所示的效果。

2. 毛毛大神的方法

具体思路请看毛毛大神的文章plt.contour 绘制图像形变场(Deformation Field)。其实具体思路我没有完全看懂,大约是先产生一个规则的网格,然后加上形变场后展示出来。但是如果网格是[W,H]大小的,但是形变场是[W,H,2]大小的,所以只能选择一个维度相加,感觉有点奇怪。代码如下:

import matplotlib.pyplot as plt
import SimpleITK as sitk
import numpy as npdef grid2contour(grid, title):'''grid--image_grid used to show deform fieldtype: numpy ndarray, shape: (h, w, 2), value range:(-1, 1)'''assert grid.ndim == 3x = np.arange(-1, 1, 2.0 / grid.shape[1])y = np.arange(-1, 1, 2.0 / grid.shape[0])X, Y = np.meshgrid(x, y)Z1 = grid[:, :, 0] + 2  # remove the dashed lineZ1 = Z1[::-1]  # vertical flipZ2 = grid[:, :, 1] + 2plt.figure()plt.contour(X, Y, Z1, 15, levels=50, colors='k') #改变levels的值,可以改变形变场的密集程度plt.contour(X, Y, Z2, 15, levels=50, colors='k')plt.xticks(()), plt.yticks(())  # remove x, y ticksplt.title(title)plt.show()def show_grid():img = sitk.ReadImage("./2D1.nii")img_arr = sitk.GetArrayFromImage(img)img_shape = img_arr.shape# 起点、终点、步长(可为小数)x = np.arange(-1, 1, 2 / img_shape[1])y = np.arange(-1, 1, 2 / img_shape[0])X, Y = np.meshgrid(x, y)regular_grid = np.stack((X, Y), axis=2)grid2contour(regular_grid, "regular_grid")rand_field = np.random.rand(*img_shape[:2], 2)  # 参数前加*是以元组形式导入rand_field_norm = rand_field.copy()rand_field_norm[:, :, 0] = rand_field_norm[:, :, 0] * 2 / img_shape[1]rand_field_norm[:, :, 1] = rand_field_norm[:, :, 1] * 2 / img_shape[0]sampling_grid = regular_grid + rand_field_normgrid2contour(sampling_grid, "sampling_grid")img_arr[..., 0] = img_arr[..., 0] * 2 / img_shape[1]img_arr[..., 1] = img_arr[..., 1] * 2 / img_shape[0]img_grid = regular_grid + img_arrgrid2contour(img_grid, "img_grid")if __name__ == "__main__":show_grid()print("end")

在代码的第20行,改变levels的值,可以改变形变场中网格的密集程度。

3. 先生成规则网格,再用空间变换网络进行变形

这种方式是配准群里的一位朋友提出的,自己进行实现。思路是先生成规则网格并保存为图片,再用空间变换网络进行变形。代码如下:

import numpy as np
import SimpleITK as sitk
import matplotlib.pyplot as pltimport torch
import torch.nn as nn
import torch.nn.functional as F# 空间转换网络
class SpatialTransformer(nn.Module):# 1.生成网格grid;2.new_grid=grid+flow,即旧网格加上一个位移;3.将网格规范化到[-1,1];4.根据新网格对原图进行采样def __init__(self, size, mode='bilinear'):"""Instiatiate the block:param size: size of input to the spatial transformer block:param mode: method of interpolation for grid_sampler"""super(SpatialTransformer, self).__init__()# Create sampling gridvectors = [torch.arange(0, s) for s in size]grids = torch.meshgrid(vectors)grid = torch.stack(grids)  # y, x, zgrid = torch.unsqueeze(grid, 0)  # add batchgrid = grid.type(torch.FloatTensor)self.register_buffer('grid', grid)self.mode = modedef forward(self, src, flow):"""Push the src and flow through the spatial transform block:param src: the original moving image:param flow: the output from the U-Net"""new_locs = self.grid + flowshape = flow.shape[2:]# Need to normalize grid values to [-1, 1] for resamplerfor i in range(len(shape)):new_locs[:, i, ...] = 2 * (new_locs[:, i, ...] / (shape[i] - 1) - 0.5)if len(shape) == 2:new_locs = new_locs.permute(0, 2, 3, 1)  # 维度置换,变为0,2,3,1new_locs = new_locs[..., [1, 0]]elif len(shape) == 3:new_locs = new_locs.permute(0, 2, 3, 4, 1)new_locs = new_locs[..., [2, 1, 0]]return F.grid_sample(src, new_locs, mode=self.mode)# 生成网格图片
def create_grid(size, path):num1, num2 = (size[0] + 10) // 10, (size[1] + 10) // 10  # 改变除数(10),即可改变网格的密度x, y = np.meshgrid(np.linspace(-2, 2, num1), np.linspace(-2, 2, num2))plt.figure(figsize=((size[0] + 10) / 100.0, (size[1] + 10) / 100.0))  # 指定图像大小plt.plot(x, y, color="black")plt.plot(x.transpose(), y.transpose(), color="black")plt.axis('off')  # 不显示坐标轴# 去除白色边框plt.gca().xaxis.set_major_locator(plt.NullLocator())plt.gca().yaxis.set_major_locator(plt.NullLocator())plt.subplots_adjust(top=1, bottom=0, left=0, right=1, hspace=0, wspace=0)plt.margins(0, 0)plt.savefig(path)  # 保存图像# plt.show()if __name__ == "__main__":out_path = r"C:\Users\zuzhiang\Desktop\new_img.jpg"  # 图片保存路径# 读入形变场phi = sitk.ReadImage("./2D1.nii")  # [324,303,2]phi_arr = torch.from_numpy(sitk.GetArrayFromImage(phi)).float()phi_shape = phi_arr.shape# 产生网格图片create_grid(phi_shape, out_path)img = sitk.GetArrayFromImage(sitk.ReadImage(out_path))[..., 0]img = np.squeeze(img)[np.newaxis, np.newaxis, :phi_shape[0], :phi_shape[1]]# 用STN根据形变场对网格图片进行变形STN = SpatialTransformer(phi_shape[:2])phi_arr = phi_arr.permute(2, 0, 1)[np.newaxis, ...]warp = STN(torch.from_numpy(img).float(), phi_arr)# 保存图片warp_img = sitk.GetImageFromArray(warp[0, 0, ...].numpy().astype(np.uint8))sitk.WriteImage(warp_img, out_path)print("end")

需要一提的是,由于不能精确的决定网格图片的大小,所以在生成的时候多生成了10个像素,然后在读取的时候再进行裁剪。改变上述代码中第57行的除数(10)可以改变网格线的密集程度。

感觉这种方式更优雅一点,但是效果和第二种是差不多的,第二种和第三种方法的效果如下图所示:

医学图像配准之形变场可视化(绘制形变场)相关推荐

  1. python 网格形变_医学图像配准之形变场可视化(绘制形变场)

    本文讲述医学图像配准中形变场的可视化,包括一种直接通过工具查看的方法和两种手工绘制的方法. 首先来介绍一下形变场,一个大小为[W,H]的二维图像对应的形变场的大小是[W,H,2],其中第三个维度的大小 ...

  2. 弹性变形与采样,旋转,形变场可视化

    文章目录 采样 (更新)旋转 变形场可视化 变形与可视化实例 STN(Spatial Transformer Network) Dense Deformation(Elastic deformatio ...

  3. 基于深度学习的单模医学图像配准综述(附VoxelMorph配准实例)

    本文是基于深度学习的单模态医学图像配准的综述,除了介绍配准任务.配准过程之外,还会从实际操作出发,以经典的VoxelMorph为例做详细介绍.如果有什么讲的不清楚的地方欢迎大家留言讨论,如果有什么错误 ...

  4. 医学图像配准中的深度学习综述论文解读

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 来源:https://zhuanlan.zhihu.com/p/9 ...

  5. 【论文笔记】AVSM:结合了仿射配准和vSVF配准的医学图像配准模型

    本文是论文<Networks for Joint Affine and Non-parametric Image Registration>的阅读笔记. 文章提出了一个名为AVSM(Aff ...

  6. 文献阅读:医学图像配准的深度学习方法综述

    本文介绍了医学图像配准在疾病诊断.手术引导和疾病治疗跟踪等方面具有重要应用价值.将深入介绍基于深度学习的医学图像配准现状和现存的配准方法技术,包括监督变换估计.无监督变换估计和使用生成对抗网络的配准方 ...

  7. 学习笔记:医学图像配准简介—附voxelmorph模型

    VoxelMorph官方代码:GitHub - voxelmorph/voxelmorph: Unsupervised Learning for Image Registrationb 官方代码讲解: ...

  8. 医学图像配准软件 ANTs(Advanced Normalization Tools)的安装和使用说明

    本文是关于医学图像配准软件 ANTs(Advanced Normalization Tools)的安装和使用说明. ANTs ANTs 是 Advanced Normalization Tools 的 ...

  9. ICCV 2019 | 微软开源无监督学习的医学图像配准方法:递归级联网络

    点击我爱计算机视觉标星,更快获取CVML新技术 编者按:目前,深度学习正广泛应用于医学图像配准领域.无监督机器学习方法能够广泛利用临床中产生的大量原始.无标注医学图像,然而现有算法对于变形大.变化复杂 ...

最新文章

  1. 正确使用Core Data多线程的3种方式
  2. VTK:简单操作之ProjectPointPlane
  3. springboot 单测加入参数_Spring Boot集成Elasticsearch实战分享
  4. Java面向对象部分小结
  5. 3-1:HTTP协议之应用层协议了解
  6. oracle有没有稀疏列,稀疏 BLAS - Oracle® Developer Studio 12.5:性能库用户指南
  7. 程序员工资为什么普遍很高,原来是因为这个...
  8. android 图标错误的是什么,如何修复:android.app.RemoteServiceException:从包中发布的错误通知*:无法创建图标:StatusBarIcon...
  9. 无根树的同构:Hash最小表示法(bzoj 4337: BJOI2015 树的同构)
  10. div标签清除float浮动样式方法
  11. 数据库工具-DBeaver工具
  12. 实现excel在线打印
  13. 永中office linux卸载,永中office Linux版
  14. 常见(MySQL)面试题(含答案)
  15. 深度学习涉及到的线性代数知识点总结(二)
  16. 文本挖掘带你分析 “苏轼” 的一生!(附视频)
  17. python函数的调用顺序,python 函数调用顺序
  18. 两个IP组播综合配置示例
  19. 【场景化解决方案】OA付款审批同步到金蝶KIS
  20. Vue3 suspense

热门文章

  1. 群晖从windows迁移到esxi+直通踩坑历险记
  2. 20175316盛茂淞 2018-2019-2《Java程序设计》第4周学习总结
  3. 新型开源语音编码器Lyra最新进展
  4. Ubuntu下配置apache的默认首页
  5. ::细细品味ASP.NET (二)::
  6. 深度解析物联网和大数据分析的渊源和应用
  7. 7-1 构造方法 (5 分)-java
  8. 接地电阻的测量方法和规范要求
  9. 大脑的信息获取特点与记忆模式
  10. Vue3封装Video.js组件(基于video.js)