医学图像处理 利用pytorch实现的可用于反传的Radon变换和逆变换

医学图像处理 利用pytorch实现的可用于反传的Radon变换和逆变换

  • 前言
  • 代码
  • 实现思路
  • 实验结果

前言

Computed Tomography(CT,计算机断层成像)技术作为如今医学中重要的辅助诊断手段,也是医学图像研究的重要主题。如今,随着深度学习对CT重建、CT分割的研究逐渐深入,论文开始越来越多的利用CT的每一个环节,来扩充Feature或构造损失函数。

但是每到这个时候,一个问题就出现了,如果我要构造损失函数,我势必要保证这个运算中梯度不会断掉,否则起不到优化效果。而Radon变换目前好像没有人直接用其当作损失函数的一部分,很奇怪,故在此实现pytorch版本的Radon变换,已经验证可以反传(但是反传的对不对不敢保证,只保证能计算出反传的值)。希望能帮到需要的同学。

参考了这两篇博文,在此十分感谢这位前辈。
Python实现离散Radon变换
Python实现逆Radon变换——直接反投影和滤波反投影

代码

from typing import Optional
import numpy as np
import matplotlib.pyplot as plt
import math
import torch as th
import torch.nn as nn
import torch.nn.functional as F
import SimpleITK as sitk#两种滤波器的实现
def RLFilter(N, d):filterRL = np.zeros((N,))for i in range(N):filterRL[i] = - 1.0 / np.power((i - N / 2) * np.pi * d, 2.0)if np.mod(i - N / 2, 2) == 0:filterRL[i] = 0filterRL[int(N/2)] = 1 / (4 * np.power(d, 2.0))return filterRLdef SLFilter(N, d):filterSL = np.zeros((N,))for i in range(N):filterSL[i] = - 2 / (np.pi**2.0 * d**2.0 * (4 * (i - N / 2)**2.0 - 1))return filterSLdef IRandonTransform(image:'th.Tensor|np.array', steps:Optional[int]=None):'''Inverse Radon Transform(with Filter, FBP)Parameters:image: (B, C, W, H)'''# 定义用于存储重建后的图像的数组channels = image.shape[-1]B, C, W, H = image.shapeif steps == None:steps = channelsorigin = th.zeros((B, C, steps, channels, channels), dtype=th.float32)filter_kernal = th.tensor(SLFilter(channels, 1)).unsqueeze(0).unsqueeze(0).float()Filter = nn.Conv1d(C, C, (channels), padding='same',bias=False)Filter.weight = nn.Parameter(filter_kernal) for i in range(steps):# 传入的图像中的每一列都对应于一个角度的投影值# 这里用的图像是上篇博文里得到的Radon变换后的图像裁剪后得到的projectionValue = image[:, :, :, i]projectionValue = Filter(projectionValue)# 这里利用维度扩展和重复投影值数组来模拟反向均匀回抹过程projectionValueExpandDim = projectionValue.unsqueeze(2)projectionValueRepeat = projectionValueExpandDim.repeat((1, 1, channels, 1))origin[:,:, i] = rotate(projectionValueRepeat, (i / steps) * math.pi)#各个投影角度的投影值已经都保存在origin数组中,只需要将它们相加即可iradon = th.sum(origin, axis=2)return iradondef rotate(image:th.Tensor, angle):'''Rotate the image in any angles(include negtive).angle should be pi = 180'''B= image.shape[0]transform_matrix = th.tensor([[math.cos(angle),math.sin(-angle),0],[math.sin(angle),math.cos(angle),0]], dtype=th.float32).unsqueeze(0).repeat(B,1,1)grid = F.affine_grid(transform_matrix, # 旋转变换矩阵image.shape).float()	# 变换后的tensor的shape(与输入tensor相同)rotation = F.grid_sample(image, # 输入tensor,shape为[B,C,W,H]grid, # 上一步输出的gird,shape为[B,C,W,H]mode='nearest') # 一些图像填充方法,这里我用的是最近邻return rotationdef DiscreteRadonTransform(image:'th.Tensor|np.array', steps:Optional[int]=None):'''Radon TransformParameters:image : (B, C, W, H)'''channels = image.shape[-1] # img_sizeB, C, W, H = image.shaperes = th.zeros((B, channels, channels), dtype=th.float32)if steps == None:steps = channelsfor s in range(steps):angle = (s / steps) * math.pirotation = rotate(image, -angle)res[:, :,s] = th.sum(rotation, dim=2)return res.unsqueeze(1)if __name__ == '__main__':origin = sitk.ReadImage('/hy-tmp/data/LIDC/CT/0001.nii.gz')t_origin = sitk.GetArrayFromImage(origin)t_origin = th.tensor(t_origin)t_origin = t_origin[40].unsqueeze(0).unsqueeze(0)a = nn.Parameter(th.ones_like(t_origin))t_origin = t_origin * aret = DiscreteRadonTransform(t_origin) # (B, 1, H, W)b = th.ones_like(ret)lf = nn.MSELoss()loss = lf(b, ret)loss.backward() # pytorch不会报错,并能返回gradrec = IRandonTransform(ret)ret = ret.squeeze(0)rec = rec.squeeze(0)plt.imsave('test.png', (t_origin.squeeze(0).squeeze(0)).data.numpy(), cmap='gray')plt.imsave('test2.png', (ret.squeeze(0)).data.numpy(), cmap='gray')plt.imsave('test3.png', (rec.squeeze(0)).data.numpy(), cmap='gray')

实现思路

这份代码实际上是参考前文提到的前辈的代码修改而来,具体而言就是把各种numpy实现的地方修改为pytorch的对应实现,其中pytorch没有对应的API来实现矩阵的Rotate,因此还参考了网上其它人实现的手写旋转的pytorch版本。并将其写作Rotate函数,在其它任务中也可以调用,这里需要注意,调用时,矩阵需要是方阵,否则会出现旋转后偏移中心的问题。

实验结果

原始图像:
请添加图片描述
Radon变换的结果:
请添加图片描述
重建结果:
请添加图片描述
这些图像可以下载下来,自己试试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/590063.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【WebSocket】快速入门 springboot中使用

WebSocket 介绍 WebSocket缺点: 服务器长期维护长连接需要一定的成本 各个浏览器支持程度不一 WebSocket 是长连接,受网络限制比较大,需要处理好重连 结论: WebSocket并不能完全取代HTTP,它只适合在特定的场景下使用…

C++ 2024-4-2 作业

1.模板类实现顺序栈 #include <iostream> #define MAX 8 using namespace std; template<typename T> class stack {T data[MAX];int top; public:stack():top(-1){}bool empty_stack();bool full_stack();void push_stack(T data);void pop_stack();void show();…

Phpstorm配置Xdebug

步骤 1、先去官网找到对应的php xdebug的版本 2、配置phpstorm断点调试 网址&#xff1a;https://xdebug.org/ 查看php对应的xdebug版本&#xff1a;Xdebug: Support — Tailored Installation Instructions 1.1查看对应php xdebug版本 全选&#xff0c;复制到目标网址 我…

Flutter中setState函数的使用注意事项

文章目录 Flutter中setState函数的使用注意事项只能在具有State对象的类中使用不要在build方法中使用将状态更新逻辑放在setState方法内部避免频繁调用使用回调函数更新状态 Flutter中setState函数的使用注意事项 setState()函数是Flutter中非常重要的一个函数&#xff0c;它用…

antd/x6-graph——实现流程图绘制功能——技能提升

效果图&#xff1a; 解决步骤1&#xff1a;安装"antv/x6": "^1.35.0" npm install antv/x61.35.0安装指定版本的antv/x6插件 解决步骤2&#xff1a;配置tools文件 在assets/js中新增一个graphTools.js文件 内容如下&#xff1a; /* antv x6图谱相关…

基于深度学习的吸烟检测系统(网页版+YOLOv8/v7/v6/v5代码+训练数据集)

摘要&#xff1a;本文深入研究了基于YOLOv8/v7/v6/v5等深度学习模型的吸烟行为检测系统&#xff0c;核心采用YOLOv8并整合了YOLOv7、YOLOv6、YOLOv5算法&#xff0c;进行性能指标对比&#xff1b;详述了国内外研究现状、数据集处理、算法原理、模型构建与训练代码&#xff0c;及…

目标跟踪——行人车辆数据集

一、重要性及意义 首先&#xff0c;目标跟踪对于个人和组织的目标实现至关重要。无论是个人职业发展、企业业务增长还是政府的社会发展&#xff0c;目标跟踪都能够帮助我们明确目标&#xff0c;并将其分解为可行的步骤和时间表。这有助于我们保持动力和专注&#xff0c;提高效…

WPF文本框TextEdit不以科学计数法显示

WPF文本框TextEdit不以科学计数法显示 一个float或者double类型的数值&#xff0c;如果小数点后0的个数≥4&#xff0c;在界面上就会自动以科学计数法显示&#xff0c; 比如&#xff1a;0.00003会显示成这样 但是很多时候我并不希望它这样显示&#xff0c;因为这样不方便编辑…

js手持小风扇

文章目录 1. 演示效果2. 分析思路3. 代码实现 1. 演示效果 2. 分析思路 先编写动画&#xff0c;让风扇先转起来。使用 js 控制动画的持续时间。监听按钮的点击事件&#xff0c;在事件中修改元素的animation-duration属性。 3. 代码实现 <!DOCTYPE html> <html lang…

[计算机效率] 格式转换工具:格式工厂

3.14 格式转换工具&#xff1a;格式工厂 格式工厂是一款功能强大的多媒体格式转换软件&#xff0c;可以实现音频、视频、图片等多种格式的转换。它支持几乎所有类型的多媒体格式&#xff0c;包括视频、音频、图片、字幕等&#xff0c;可以轻松实现格式之间的转换&#xff0c;并…

Python基础之pandas:字符串操作与透视表

文章目录 一、字符串操作备注&#xff1a;如果想要全部行都能输出&#xff0c;可输入如下代码 1、字符检索2、字符转换3、字符类型判断4、字符调整5、字符对齐与填充6、字符检索7、字符切割8、字符整理 二、透视表1、pd.pivot_table2、多级透视表 一、字符串操作 备注&#xf…

Flask Python:数据库多条件查询,flask中模型关联

前言 在上一篇Flask Python:模糊查询filter和filter_by&#xff0c;数据库多条件查询中&#xff0c;已经分享了几种常用的数据库操作&#xff0c;这次就来看看模型的关联关系是怎么定义的&#xff0c;先说基础的关联哈。在分享之前&#xff0c;先分享官方文档,点击查看 从文档…