SAMUS代码尝试复现出现的问题

1.pycharm连接服务器

注意需要专业版,这个可以上网搜索,很简单。

2.虚拟环境创建的建议

由于该模型之后所需依赖包含torch-1.8.0+cu111和torchvision-0.9.0+cu111,建议在配置虚拟环境时,python设置为3.9及以下,否则后续会出现无法查询和安装相应版本的torch和torchvision。

samus的readme.md中提到的提前安装pythorch和torchvision建议不要使用最新版本,否则会与python3.9版本冲突。

3.requirement.txt安装时,segment anything下载出现问题

直接运行pip install -r requirement.txt可能会出现无法下载segment anything,这个时候建议单独下载,因为segment anything本身过大,很难一起下载。

4.torch-1.8.0+cu111版本下载问题

不同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

5.国内下载torch-1.8.0+cu111和torchvision-0.9.0+cu111过慢

建议使用国内源

pip install torch==1.8.0+cu111 torchvision==0.9.0+cu111 -f https://mirrors.aliyun.com/pytorch-wheels/cu111

6.数据集整理

6.1 CAMUS

网络上下载的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

6.2 TN3K,TG3K和DDTI

下载链接:https://drive.google.com/file/d/1reHyY5eTZ5uePXMVMzFOq5j3eFOSp50F/view?usp=sharing

链接内包含该三种数据集

6.3 BUSI

下载链接:Dataset | Aly Fahmy

6.4 UDIAT

由于UDIAT数据集需要申请,所以这里只列出申请链接:MH Yap - Datasets/Software

6.5 HMC-QU

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 

由于是本人自行制作,不保证完全无错,谨慎使用。

下面是转变后图片

SAMUS代码尝试复现出现的问题_第1张图片

这个是掩码

SAMUS代码尝试复现出现的问题_第2张图片

6.6 数据集汇总和整理

由于没有申请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中关于数据集的路径别忘了更改。

6.7 解读class.json

{
    "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必不可缺!!!

7.SAMUS与SAM代码对比

论文链接: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两个模块,分别承担特征提取空间下采样功能。

你可能感兴趣的:(pytorch,人工智能,python)