注意需要专业版,这个可以上网搜索,很简单。
由于该模型之后所需依赖包含torch-1.8.0+cu111和torchvision-0.9.0+cu111,建议在配置虚拟环境时,python设置为3.9及以下,否则后续会出现无法查询和安装相应版本的torch和torchvision。
samus的readme.md中提到的提前安装pythorch和torchvision建议不要使用最新版本,否则会与python3.9版本冲突。
直接运行pip install -r requirement.txt可能会出现无法下载segment anything,这个时候建议单独下载,因为segment anything本身过大,很难一起下载。
不同python版本的虚拟环境只能下载特定版本的torch和torchvision,由于SAMUS的requirement.txt中要求的torch和torchvision版本会有些老,所以建议刚开始的python版本下载3.9及以下的,否则后续无法下载。
以下是torch和python版本对号对应
https://blog.csdn.net/shiwanghualuo/article/details/122860521?fromshare=blogdetail&sharetype=blogdetail&sharerId=122860521&sharerefer=PC&sharesource=Tartaglia_&sharefrom=from_link
建议使用国内源
pip install torch==1.8.0+cu111 torchvision==0.9.0+cu111 -f https://mirrors.aliyun.com/pytorch-wheels/cu111
网络上下载的CAMUS基本上都是以.nii.gz结尾的,没有处理过的。
不过,github上有专门处理该数据集的程序,链接:GitHub - atlan-antillia/CAMUS_public-ImageMask-Dataset:CAMUS_public Segmentatioin 的 ImageMask 数据集 --- GitHub - atlan-antillia/CAMUS_public-ImageMask-Dataset: CAMUS_public ImageMask Dataset for Segmentatioin
原数据链接:Human Heart Project
处理过的数据链接:https://drive.google.com/file/d/1ckzga8X5Zmjl_PDQNf1ni8-3GhrcDlIo/view?usp=sharing
不过数据还是有问题,这位给出处理后的数据是jpg,但是SAMUS只能处理png,所以大家别忘了转换一下,这个代码可以问ai
下载链接:https://drive.google.com/file/d/1reHyY5eTZ5uePXMVMzFOq5j3eFOSp50F/view?usp=sharing
链接内包含该三种数据集
下载链接:Dataset | Aly Fahmy
由于UDIAT数据集需要申请,所以这里只列出申请链接:MH Yap - Datasets/Software
HMC-QU数据集,下载链接:HMC-QU 数据集_数据集-飞桨AI Studio星河社区
不过下载得到的img是.avi,并且mask是.mat格式,因此需要进行转换,我参考了这篇文章的代码,链接如下:数据处理——avi视频数据转png图片格式代码,mat转png图片格式代码,图片裁剪成固定大小代码。_hmc-qu数据集-CSDN博客
不过相对于下载的数据,这些代码还需要更改,因此我在这里上传了更改后的代码和HMC-QU.excel,建议大家复制一份原版,然后保存一份我的版本,方便中间出现问题后恢复。
关于该数据集的整理,我没有进行图片裁剪,自行考虑是否需要。
首先是.avi转png,注意更改路径
import os
import cv2
import pandas as pd
# 输入文件夹路径
folder_path = '../pyProject/plus/HMC-QU//HMC-QU Echos'
# 输出文件夹路径
output_folder = '../pyProject/plus/HMC-QU/Img'
if not os.path.exists(output_folder):
print(f"no output folder")
os.makedirs(output_folder)
# 读取Excel文件
excel_path = 'HMC_QU.xlsx'
df = pd.read_excel(excel_path)
def format_numbers(start, end, width=3):
return [f"{num:0{width}}" for num in range(start, end + 1)]
# 遍历文件夹下所有avi文件
total = 0
for filename in os.listdir(folder_path):
if filename.endswith(".avi"):
video_path = os.path.join(folder_path, filename)
cap = cv2.VideoCapture(video_path)
# 检查视频是否成功打开
if not cap.isOpened():
print(f"Error: Could not open video {filename}")
continue
# 获取视频帧数
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# 获取对应视频在Excel中的信息
video_info = df[df['ECHO'] == filename.split(".")[0]]
#print(video_info)
#print(video_info.columns) # 打印出所有列名
if video_info.empty:
print(f"No frame indices found for video {filename} in the Excel file.")
continue
# folder = os.path.join(output_folder, filename.split(".")[0])
# os.makedirs(folder)
start_frame = int(video_info['Reference Frame'].iloc[0])
end_frame = int(video_info['End of Cycle'].iloc[0])
# 检查索引是否在视频帧数范围内
if start_frame < 1 or end_frame > frame_count or start_frame >= end_frame:
print(f"Invalid frame indices for video {filename}. Skipping...")
continue
# 设置视频读取位置到起始帧
cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame - 1)
# 创建输出文件夹
# 读取视频帧并保存为图片
frame_num = start_frame
while frame_num <= end_frame:
ret, frame = cap.read()
print(type(frame), frame.shape)
new_name=filename.split(".")[0]
# 检查视频是否读取完毕
# if not ret:
# break
# # 将视频帧保存为图片
img_name = f"{new_name}.png"
#img_name = f"{save_id[frame_num-start_frame]}.png"
img_path = os.path.join(output_folder, img_name)
cv2.imwrite(img_path, frame)
# # 打印进度
print(f"Frame {frame_num} of {filename} saved")
# 更新帧计数器
frame_num += 1
total += 1
# # 释放资源
cap.release()
print("All videos processed successfully!")
print(total)
下面是.mat转png,注意更改路径
'''
Descripttion:
Result:
Author: Philo
Date: 2024-04-24 10:18:47
LastEditors: Philo
LastEditTime: 2024-04-24 10:41:32
'''
# 生成的数据放在各自的文件夹中
import scipy.io as scio
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import os
# 根据自己任务指定文件夹的前缀和范围
folder_prefix = "../pyProject/plus/HMC-QU/LV Ground-truth Segmentation Masks"
folders_name = os.listdir(folder_prefix)
# 输出文件夹路径
output_folder = '../pyProject/plus/HMC-QU/Mask'
if not os.path.exists(output_folder):
print(f"no output folder")
os.makedirs(output_folder)
# 生成图片名称,因为mat数据格式都有顺序
# 从1-100和从001到100的命名方式对图片的影响不同
def format_numbers(start, end, width=3):
return [f"{num:0{width}}" for num in range(start, end + 1)]
# 生成png的名字id
save_id = format_numbers(1, 1000, 4)
# 二值数据转到0-255范围(可见)
def MatrixToImage(data):
data = data * 255
new_im = Image.fromarray(data.astype(np.uint8))
return new_im
sum = 0
for tt in folders_name:
rename = tt.split(".")[0]
name = os.path.join(folder_prefix, rename)
path = name
mat_data = scio.loadmat(path)
data = mat_data["predicted"] # 这里是根据自己mat文件中提取数值
for j in range(data.shape[0]):
sum += 1
new_im = MatrixToImage(data[j])
save_name = rename
new_im.save(f"{output_folder}/{save_name}.png")
print(sum)
更改后的excel表格和处理后的数据在下面链接中,可自行下载。
链接: https://pan.baidu.com/s/1o8VZGfMRlAvcqmKjW96QzA?pwd=pha8 提取码: pha8
由于是本人自行制作,不保证完全无错,谨慎使用。
下面是转变后图片
这个是掩码
由于没有申请UDIAT数据集,因此我整理的数据集不包含这个,大家自行整理。
按照SAMUS提供的example_of_required_dataset_format,大致框架可以分为
/ # 数据集名称(如 Breast-BUSI)
├── MainPatient/ # 患者数据根目录
│ ├── train.txt # 训练集文件目录
│ ├── val.txt # 验证集文件列表
│ └── test.txt # 测试集文件列表(可选)
├── Img/ # 图像文件目录
│ ├── image1.png # 图像文件
│ └── image2.png # 图像文件
├── label/ # 标注文件目录
│ ├── image1_mask.png # 标注文件
│ └── image2_mask.png # 标注文件
此外,按照./utils/config.py可以得出
dataset/SAMUS
├─── / # 数据集名称(Breast-BUSI,ThyroidNodule-TN3K,
│ │ Echocardiography-CAMUS,和US30K)
│ ├─── MainPatient/ # 患者数据根目录
│ │ ├── train.txt # 训练集文件目录
│ │ ├── val.txt # 验证集文件列表
│ │ └── test.txt # 测试集文件列表(可选)
│ ├─── Img/ # 图像文件目录
│ │ ├── image1.png # 图像文件
│ │ └── image2.png # 图像文件
│ └── label/ # 标注文件目录
│ ├── image1_mask.png # 标注文件
│ └── image2_mask.png # 标注文件
│……
│……
│
└─── MainPatient/
├───…………
├─── test.txt
├───…………
├─── train.txt
├───…………
└─── val.txt
按照要求,只整理了这三个数据集,并且按照格式进行填写。
注意路径!!!
./utils/config.py中关于数据集的路径别忘了更改。
{
"Breast-BUSI": 2,
"Breast-UDIAT": 2,
"Echocardiography-CAMUS": 4,
"Echocardiography-HMCQU": 2,
"ThyroidNodule-DDTI": 2,
"ThyroidNodule-TG3K": 2,
"ThyroidNodule-TN3K": 2
}
根据我目前的理解,这些数字代表的是类别,以CAMUS为例,4种类别是因为得到的图片包含2CH_DH,2CH_DS,4CH_DH和4CH_DS,所以在进行整合的时候,可以根据图片本身的名称进行分类。注意要从0开始标记,否则后续的evolation阶段会出现错误。
注意class.json必不可缺!!!
论文链接:https://arxiv.org/pdf/2309.06824.pdf
论文中提到,相较于SAM,SAMUS的主要改进在图像编码器部分——代码的image_encoder.py部分。
(1)class ImageEncoderViT中
self.cnn_embed = SingleCNNEmbed(patchsize=patch_size, in_chans=3, embed_dim=embed_dim) # new to sam
self.patch_embed = PatchEmbed0(kernel_size=(patch_size, patch_size),stride=(patch_size, patch_size),in_chans=3,embed_dim=embed_dim,)
多尺度特征提取,SingleCNNEmbed,PatchEmbed0。SAMUS:引入了 SingleCNNEmbed 模块,通过卷积层提取图像特征,并将其与 ViT 的特征结合,PatchEmbed0是根据SAM更改的
self.post_pos_embed = PostPosEmbed(embed_dim=embed_dim, ori_feature_size=1024//16, new_feature_size=img_size//patch_size) # new to sam
位置编码,PostPosEmbed。SAMUS:引入了 PostPosEmbed 模块,用于对位置编码进行下采样,使其与输入分辨率匹配。
self.input_Adapter = Adapter(embed_dim)
(2)class ParaBlock
# ------------------ new to sam----------------------
if self.window_size == 0:
self.MLP_Adapter = Adapter(dim, skip_connect=False) # new to sam, MLP-adapter, no skip connection
self.Space_Adapter = qkvAttention(dim=dim, num_heads=num_heads) # with skip connection
self.refine_Adapter = SingleConv(in_channels=dim, out_channels=dim)
self.scale = 0.5
# ---------------------------------------------------
self.dim = dim
self.depth = depth
MLP_Adapter,Space_Addapter,refine_Adapter适配器:
1.MLP_Adapter:一个 MLP 适配器模块,用于增强特征表示。
2.Space_Adapter:一个空间注意力模块,用于捕捉空间特征,qkvAttention,与 Attention 类似,但允许外部传入查询、键和值(q, k, v),用于更灵活的特征融合。
3.refine_Adapter:一个卷积模块,用于细化特征,SingleCNNEmbed与 CNNEmbed 类似,但使用更简单的卷积和下采样模块(SingleConv 和 SingleDown)
(3)各种类
SAMUS新添加的类DoubleConv、Down、SingleDown、SingleConv、CNNEmbed、SingleCNNEmbed、PostPosEmbed、PatchEmbed0
多尺度特征提取SingleCNNEmbed,PatchEmbed0是根据SAM更改的,且SingleCNNEmbed模块中引用SingleConv和SingleDown通常是简化的特征处理模块。它们的核心作用与之前的 DoubleConv/Down 有显著区别。
位置适配器,PostPosEmbed
特征适配器,MLP_Adapter
跨分支注意力模块:Space_Adapter,用于捕捉空间特征,qkvAttention,与 Attention 类似,但允许外部传入查询、键和值(q, k, v),用于更灵活的特征融合。
并行的CNN 分支图像编码器CNNEmbed,且该class中引用DoubleConv、Down两个模块,分别承担特征提取和空间下采样功能。