AI-医学影像分割方法与流程

AI医学影像分割方法与流程–基于低场磁共振影像的病灶识别

– 作者:coder_fang
AI框架:PaddleSeg

  1. 数据准备,使用MedicalLabelMe进行dcm文件标注,产生同名.json文件。在这里插入图片描述

  2. 编写程序生成训练集图片,包括掩码图。

  3. 代码如下:

def doCvt(labelDir):outdir=labelDir+"\\output";if os.path.exists(outdir):shutil.rmtree(outdir)os.makedirs(outdir+"\\images") #原始图os.makedirs(outdir + "\\masks1") #可视掩码图,只包含0,255os.makedirs(outdir + "\\masks2") #训练掩码图,只包含0,1start=0files=glob.glob(labelDir+'\\*.json')for f in files:fname=os.path.basename(f)jsondata = json.load(open(labelDir+"\\"+ fname, encoding="utf-8"))imagePath = os.path.join(labelDir, jsondata.get("image_path"))ds = pydicom.read_file(imagePath)  # 读取.dcm文件img = ds.pixel_array  # 提取图像信息img = (img * (255/img.max())).astype(np.uint8)pathout ="{}\\images\\{:05d}.png".format(outdir,start)result=cv2.bilateralFilter(img,11,64,128) #对低场图片进行去噪声cv2.imwrite(pathout, result)label_name_to_value = {'_background_': 0,'H':1}for shape in jsondata.get("frames")[0].get("shapes"):label_name = shape['label']if label_name in label_name_to_value:label_value = label_name_to_value[label_name]else:label_value = len(label_name_to_value)label_name_to_value[label_name] = label_valuemask = np.zeros(img.shape ,dtype=np.uint8)  # 假设图片是灰度图,调整dtype为np.uint8# 遍历所有形状并绘制到掩码上for shape in jsondata.get("frames")[0].get("shapes"):# 获取形状的类型和坐标点shape_type = shape['shape_type']points = shape['points']if shape_type == 'polygon':# 绘制多边形掩码cv2.fillPoly(mask, [np.array(points).reshape((-1, 1, 2)).astype(np.int32)], 1)elif shape_type == 'rectangle':# 绘制矩形掩码(转换为多边形)x, y, w, h = pointspts = np.array([[x, y], [x + w, y], [x + w, y + h], [x, y + h]])cv2.fillPoly(mask, [pts.reshape((-1, 1, 2)).astype(np.int32)], 1)# 可以根据需要添加其他形状的处理方式,如圆形等。# 保存可视掩码图像(例如PNG格式)pathout = "{}\\masks1\\{:05d}.png".format(outdir, start)cv2.imwrite(pathout, (mask * 255).astype(np.uint8))# 保存训练掩码图像(例如PNG格式)pathout = "{}\\masks2\\{:05d}.png".format(outdir, start)cv2.imwrite(pathout, mask.astype(np.uint8))lbl_viz = imgviz.label2rgb(mask, img)start+=1

效果如图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  1. 使用PaddlePaddle 2.6.2版本,单独下载PaddleSeg2.8.1版本进行编译,2.8以前版本会有问题。
  2. 生成训练数据和验证数据集对应列表:
def create_list(data_path):image_path = os.path.join(data_path, 'images')label_path = os.path.join(data_path, 'masks2')data_names = os.listdir(image_path)random.shuffle(data_names)  # 打乱数据with open(os.path.join(data_path, 'train_list.txt'), 'w') as tf:with open(os.path.join(data_path, 'val_list.txt'), 'w') as vf:for idx, data_name in enumerate(data_names):img = os.path.join('images', data_name)lab = os.path.join('masks2', data_name)if idx % 9 == 0:  # 90%的作为训练集vf.write(img + ' ' + lab + '\n')else:tf.write(img + ' ' + lab + '\n')print('数据列表生成完成')data_path = 'work/output'
create_list(data_path)  # 生成数据列表
  1. 基于列表生成数据集并进行验证:
# 构建训练集
train_transforms = [T.RandomHorizontalFlip(),#水平翻转    T.RandomVerticalFlip(),T.RandomNoise(),T.Resize(),T.Normalize()  # 归一化
]
train_dataset = Dataset(transforms=train_transforms,dataset_root='work/output',num_classes=2,img_channels=1,mode='train',train_path='work/output/train_list.txt',separator=' ',
)
# 构建验证集
val_transforms = [T.Resize(),T.Normalize()
]
val_dataset = Dataset(transforms=val_transforms,dataset_root='work/output',num_classes=2,img_channels=1,mode='val',val_path='work/output/val_list.txt',separator=' ',
)#随机抽取训练集数据进行可视化验证
import matplotlib.pyplot as plt
import numpy as np
plt.figure(figsize=(10,16))
for i in range(1,6,2): _,img,label,_= train_dataset[random.randint(0,100)].items()print(img[1].shape)img = np.transpose(img[1], (1,2,0))img = img*0.5 + 0.5plt.subplot(3,2,i),plt.imshow(img,'gray'),plt.title('img'),plt.xticks([]),plt.yticks([])plt.subplot(3,2,i+1),plt.imshow(label[1],'gray'),plt.title('label'),plt.xticks([]),plt.yticks([])plt.show

在这里插入图片描述

  1. 构建训练网络并训练:
#可以尝试PaddelSeg中多种分割模型,这里目前测试的BiSeNetV2均衡了效果和训练验证速度,表现还可以
model = BiSeNetV2(num_classes=2,#二分类分割in_channels=1,#单通道lambd=0.25,align_corners=False,pretrained='OutDir/best_model/model.pdparams')base_lr = 0.0005
lr = paddle.optimizer.lr.PolynomialDecay(learning_rate=base_lr, decay_steps=1500, verbose=False)
optimizer = paddle.optimizer.Momentum(lr, parameters=model.parameters(), momentum=0.9, weight_decay=4.0e-
losses = {}
losses['types'] = [CrossEntropyLoss()] *5
losses['coef'] = [0.8,0.2]*5from paddleseg.core import train
train(model=model,train_dataset=train_dataset,val_dataset=val_dataset,optimizer=optimizer,save_dir='OutDir',iters=3000,batch_size=8,save_interval=200,log_iters=20,num_workers=0,losses=losses,use_vdl=True)#开始训练,这里最好使用GPU训练
  1. 验证数据,并将预测结果融合到原始图中
#测试结果 transforms = T.Compose([T.Resize(target_size=(512, 512)),T.Normalize()
])#显示图片时调整合适的窗宽窗位
def wwwl(im,window_width,window_level):# 计算最大值和最小值min_val = window_level - window_width / 2max_val = window_level + window_width / 2           #im = ((im - min_val) / (max_val - min_val)) * 255im=np.clip(im,min_val,max_val).astype(np.uint8)return im#加载模型
model = BiSeNetV2(num_classes=2,    in_channels=1,)model_path = 'OutDir/best_model/model.pdparams'
para_state_dict = paddle.load(model_path)
model.set_dict(para_state_dict)import matplotlib.pyplot as plt
import numpy as np#testimg里放置一些病灶图片,尽量不是训练集里数据
files = glob.glob('work/testimg/*.png')
row=(int)(len(files))
plt.figure(figsize=(16,row*8))
i=1;
for f in files:#读取数据    im = cv2.imread(f, 0).astype('float32')im=F.normalize(im,0.5,0.5)h,w = im.shapedata = np.expand_dims(im,axis=0).repeat(1,axis=0)data = data[np.newaxis, ...]data = paddle.to_tensor(data)predata=model(data)output = predata[0].numpy()output = np.argmax(output,axis=1)output = np.squeeze(output)#输入模型预测的时候缩放到(512,512),现在要缩放到原始数据的大小output = cv2.resize(output, (h, w), interpolation=cv2.INTER_NEAREST)output = output.astype(np.uint8)*128#归到255im=(im*0.5+0.5)*255im=wwwl(im,128,60)max_val = np.max(im)im=im*(255/max_val)imgori=cv2.cvtColor(im.astype(np.uint8), cv2.COLOR_GRAY2BGR);imgpre=cv2.cvtColor(output, cv2.COLOR_GRAY2BGR);imgpre[:,:,1]= 0imgpre[:,:,2]= 0mask_img=cv2.addWeighted(imgpre, 0.2, imgori, 0.5, 0)plt.subplot(row,2,i),plt.imshow(mask_img,'gray'),plt.title('img'),plt.xticks([]),plt.yticks([])i+=1plt.show

在这里插入图片描述

  1. 基于上述模型持续优化并训练,如需模型工程化,可使用paddleseg 中的export.py ,将模型进行转换,转换后可将其集成到python或c++工程使用,转换命令如下:
python export.py --model_path OutDir/best_model/model.pdparams --input_shape 1 1 512 512 --save_dir OutDir/Saved --config work/config.yml 

完!

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

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

相关文章

【Python】09、字典

文章目录 1. 字典简介2. 字典的使用2.1 字典创建2.2 字典值获取2.3 字典值修改2.4 字典的删除 3. 字典的遍历 1. 字典简介 字典(dict)属于一种新的数据结构,称为映射(mapping)。 字典的作用和列表类似,但是查询性能比列表好;在字典中每个元…

【贪心算法4】

力扣452.用最少数量的剪引爆气球 链接: link 思路 这道题的第一想法就是如果气球重叠得越多那么用箭越少,所以先将气球按照开始坐标从小到大排序,遇到有重叠的气球,在重叠区域右边界最小值之前的区域一定需要一支箭,这道题有两…

SGMEA: Structure-Guided Multimodal Entity Alignment

3 Method 3.1 Problem Definition 3.2 Framework Description 总体框架如图2所示,由三个主要部分组成:初始嵌入采集模块、结构引导模块和模态融合模块。 3.3 Initial Embedding Acquisition 3.3.1 Structural Embedding 3.3.2 Relation, Attribute, …

KY-038 声音传感器如何工作以及如何将其与 ESP32 连接

想为您的项目赋予声音感!然后跟着做,因为在这个项目中,我们将连接一个声音传感器,用它构建一些有趣的项目。我们使用的 KY-038 声音传感器使用电容式麦克风来检测声波,这为我们提供了稳定性和可靠性的完美平衡。因此,在本文中,我们决定将 KY-038 传感器与 ESP32 连接,并…

《基于超高频RFID的图书馆管理系统的设计与实现》开题报告

一、研究背景与意义 1.研究背景 随着信息化时代的到来,运用计算机科学技术实现图书馆的管理工作已成为优势。更加科学地管理图书馆会大大提高工作效率。我国的图书管理体系发展经历了三个阶段:传统图书管理模式、现代图书管理模式以及基于无线射频识别&…

[local-file-system]基于服务器磁盘的本地文件存储方案

[local-file-system]基于服务器磁盘的本地文件存储方案 仅提供后端方案 github 环境 JDK11linux/windows/mac 应用场景 适用于ToB业务,中小企业的单体服务,仅使用磁盘存储文件的解决方案 仅使用服务器磁盘存储 与业务实体相结合的文件存储方案&…

P5708 【深基2.习2】三角形面积(洛谷—python)

题目描述 一个三角形的三边长分别是 a、b、c,那么它的面积为 p(p−a)(p−b)(p−c)​,其中 p21​(abc)。输入这三个数字,计算三角形的面积,四舍五入精确到 1 位小数。 输入格式 第一行输入三个实数 a,b,c,以空格隔开…

智慧加油站小程序数据库设计文档

智慧加油站系统 - 数据库与API设计文档 1. 数据库设计 1.1 ER模型 系统的核心实体关系如下&#xff1a; 用户(User) ---< 订单(Order) ---< 加油记录(RefuelRecord)| | || | vv v …

C++博客分享

本周的一些 C视频分享, 或许后续会做一些内容总结. 博客 Polymorphic, Defaulted EqualityConstexpr factors_ofC26: Removing language featuresBypassing the branch predictor Meeting C 2024 Clean CMake for C (library) developers - Kerstin KellerAn Introduction …

【蓝桥杯每日一题】3.16

&#x1f3dd;️专栏&#xff1a; 【蓝桥杯备篇】 &#x1f305;主页&#xff1a; f狐o狸x 目录 3.9 高精度算法 一、高精度加法 题目链接&#xff1a; 题目描述&#xff1a; 解题思路&#xff1a; 解题代码&#xff1a; 二、高精度减法 题目链接&#xff1a; 题目描述&…

vue 仿deepseek前端开发一个对话界面

后端&#xff1a;调用deepseek的api&#xff0c;所以返回数据格式和deepseek相同 {"model": "DeepSeek-R1-Distill-Qwen-1.5B", "choices": [{"index": 0, "delta": {"role": "assistant", "cont…

SpringMVC(五)拦截器

目录 拦截器基本概念 一 单个拦截器的执行 1 创建拦截器 2 SpringMVC配置&#xff0c;并指定拦截路径。 3 运行结果展示&#xff1a; 二 多个拦截器的执行顺序 三 拦截器与过滤器的区别 拦截器基本概念 SpringMVC内置拦截器机制&#xff0c;允许在请求被目标方法处理的…

Hive SQL 精进系列:PERCENTILE_APPROX 搞定分位数

目录 一、引言二、percentile_approx 函数基础2.1 基本语法参数解释返回值简单示例 三、应用场景3.1 数据分析与报告3.2 数据清洗与异常值检测3.3 性能监控与优化 四、使用注意事项4.1 数据类型要求4.2 精度与性能平衡4.3 空值处理 五、总结 一、引言 百分位数作为一种常用的统…

pytorch快速入门——手写数字分类GPU加速

&#x1f451;主页&#xff1a;吾名招财 &#x1f453;简介&#xff1a;工科学硕&#xff0c;研究方向机器视觉&#xff0c;爱好较广泛… ​&#x1f4ab;签名&#xff1a;面朝大海&#xff0c;春暖花开&#xff01; pytorch快速入门——手写数字分类GPU加速 一、tensor1&#…

【开源免费】基于SpringBoot+Vue.JS电商应用系统(JAVA毕业设计)

本文项目编号 T 242 &#xff0c;文末自助获取源码 \color{red}{T242&#xff0c;文末自助获取源码} T242&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

经历过的IDEA+Maven+JDK一些困惑

注意事项&#xff1a;由于使用过程中是IDEA绑定好另外2个工具&#xff0c;所以报错统一都显示在控制台&#xff0c;但要思考和分辨到底是IDEA本身问题导致的报错&#xff0c;还是maven导致的 使用前的配置 编辑期 定义&#xff1a;指的是从open projects开始&#xff0c;到执行…

【推理】大模型ReasonGraph:推理路径的可视化论文及代码分析

ReasonGraph:推理路径的可视化 ReasonGraph demo http://192.168.50.197:5001/ 作者的其他论文 ** ** LLM推理方法的相关工作

学习路之TP6 --重写vendor目录下的文件(服务覆盖command---优点:命令前后一致)

学习路之TP6 --重写vendor目录下的文件 一、新建命令文件&#xff1a;二、复制修改&#xff1a;Server.php三、新建服务类&#xff1a;WorkmanService.php四、注册服务五、运行效果 有需求要重写vendor\topthink\think-worker\src\command\Server.php 以实现修改代码 一、新建命…

【蓝图使用】绘制mesh顶点的法线

文章目录 绘制法线Normal准备工作UE5资源制作蓝图制作 参考 绘制法线Normal 参考[1]打算用蓝图走一遍渲染管线&#xff0c;还是可以的 准备工作 Blender制作一个三个顶点的模型 要不要材质无所谓&#xff0c;就一个三个顶点的mesh即可&#xff0c;参考[2] 找到一个法线贴…

【算法学习之路】10.二叉树

二叉树 前言一.简介二.题目123 前言 我会将一些常用的算法以及对应的题单给写完&#xff0c;形成一套完整的算法体系&#xff0c;以及大量的各个难度的题目&#xff0c;目前算法也写了几篇&#xff0c;题单正在更新&#xff0c;其他的也会陆陆续续的更新&#xff0c;希望大家点…