训练yolov8+SAM的过程记录

1-首先将拿到的数据集进行重新命名(dataset1:是经过校色之后裁剪的图片;dataset2:原图)
图片文件从1.jpg开始命名的代码:

folder_path = r'C:\Users\23608\Desktop\Luli_work\data\fanStudent\tongueseg\Fan\Fan\.jpg'
new_folder = r'C:\Users\23608\Desktop\Luli_work\data\fanStudent\tongueseg\imgOrig'

jpg_files = [f for f in os.listdir(folder_path) if f.endswith('.jpg')]
n = 1
for i, jpg_file in enumerate(jpg_files):
    new_filename = f'{n}.jpg'
    n =n+1
    
    # 构造原始文件和新文件的完整路径
    original_path = os.path.join(folder_path, jpg_file)
    new_path = os.path.join(new_folder, new_filename)
    
    # 复制文件到新文件夹并重命名
    shutil.copy(original_path, new_path)
    
print("重命名完成!")

2-将数据预处理之后的数据上传到服务器,接着使用yolov8SAM代码将代码中的舌体掩码跑出来:
数据存放位置
Imgorig:/share1/luli/tongueseg/data/dataset2/imgOrig/
IMgcrop:/share1/luli/tongueseg/data/dataset1/imgCrop/

微调SAM的查找

How to Fine-Tune Segment Anything

1. How to Fine-Tune Segment Anything

We gave an overview of the SAM architecture in the introduction section. The image encoder has a complex architecture with many parameters. To fine-tune the model, it makes sense for us to focus on the mask decoder which is lightweight and therefore easier, faster and more memory efficient to fine-tune.

In order to fine tune SAM, we need to extract the underlying pieces of its architecture (image and prompt encoders, mask decoder). We cannot use SamPredictor.predict (link) for two reasons:

· We want to fine tune only the mask decoder
· This function calls SamPredictor.predict_torch which has the @torch.no_grad() decorator (link), which prevents us from computing gradients

Thus, we need to examine the SamPredictor.predict function and call the appropriate functions with gradient calculation enabled on the part we want to fine tune (the mask decoder). Doing this is also a good way to learn more about how SAM works.

2. Creating a Custom Dataset

We need three things to fine tune our model:(这里其实并没有说GT、datase的具体类型)

· Images on which to draw segmentations
· Segmentation ground truth masks
· Prompts to feed into the model

后续在代码里面可以看到图片代码里面是png格式,mask掩码是黑白二值图。

我现在使用的是labelme标记的舌头,json文件,需要把json文件转化成二值图。

这里涉及到3个数据类型的转化:

· png图片转json文件(也就是使用yolov8+SAM对数据集进行简单的分割之后再人工进行微调,此时的微调使用的是labelme格式是json,这里使用到TongueSAM里马赛克json里面的代码)
· json文件转成png图片,这里使用到labelme里面的自己的代码(参考链接)[labelme] json格式批量转换为mask.png,步骤入下:
1.使用labelme制作语义分割数据集,生成.json格式文件,将所有放置于一个文件夹下。
2.找到labelme安装位置的json_to_dataset.py文件,(可以使用Everything软件)
用下面的代码替换里面的代码:

import argparse
import json
import os
import os.path as osp
import warnings
import copy
import numpy as np
import PIL.Image
from skimage import io
import yaml
from labelme import utils

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('json_file')   # 标注文件json所在的文件夹
    parser.add_argument('-o', '--out', default=None)
    args = parser.parse_args()

    json_file = args.json_file

    list = os.listdir(json_file)   # 获取json文件列表
    for i in range(0, len(list)):
        path = os.path.join(json_file, list[i])  # 获取每个json文件的绝对路径
        filename = list[i][:-5]       # 提取出.json前的字符作为文件名,以便后续保存Label图片的时候使用
        extension = list[i][-4:]
        if extension == 'json':
            if os.path.isfile(path):
                data = json.load(open(path))
                img = utils.image.img_b64_to_arr(data['imageData'])  # 根据'imageData'字段的字符可以得到原图像
                # lbl为label图片(标注的地方用类别名对应的数字来标,其他为0)lbl_names为label名和数字的对应关系字典
                lbl, lbl_names = utils.shape.labelme_shapes_to_label(img.shape, data['shapes'])   # data['shapes']是json文件中记录着标注的位置及label等信息的字段

                #captions = ['%d: %s' % (l, name) for l, name in enumerate(lbl_names)]
                #lbl_viz = utils.draw.draw_label(lbl, img, captions)
                out_dir = osp.basename(list[i])[:-5]+'_json'
                out_dir = osp.join(osp.dirname(list[i]), out_dir)
                if not osp.exists(out_dir):
                    os.mkdir(out_dir)

                PIL.Image.fromarray(img).save(osp.join(out_dir, '{}_source.png'.format(filename)))
                PIL.Image.fromarray(lbl).save(osp.join(out_dir, '{}_mask.png'.format(filename)))
                #PIL.Image.fromarray(lbl_viz).save(osp.join(out_dir, '{}_viz.jpg'.format(filename)))

                with open(osp.join(out_dir, 'label_names.txt'), 'w') as f:
                    for lbl_name in lbl_names:
                        f.write(lbl_name + '\n')

                warnings.warn('info.yaml is being replaced by label_names.txt')
                info = dict(label_names=lbl_names)
                with open(osp.join(out_dir, 'info.yaml'), 'w') as f:
                    yaml.safe_dump(info, f, default_flow_style=False)

                print('Saved to: %s' % out_dir)


if __name__ == '__main__':
    main()

在这里插入图片描述

找到 labelme_json_to_dataset的文件夹,在文件夹路径里面输入cmd
执行命令: labelme_json_to_dataset path/to/json
这样就可以生成以下四个文件(可以使用Everything软件找一下在哪)
在这里插入图片描述
上面的1_mask.png就是转化成功的了,看起来都是黑色的,但是没错。因为我的是单个目标检测,所以我又使用了下面的代码将目标区域变成白色,也就是重新将这图片转化成一个二值图。

# 这是转haul一张图片的代码==从全黑变成了黑白二值图==
import cv2
import numpy as np
from PIL import Image

# 图像文件路径
image_path = r"C:\Users\23608\Desktop\Luli_work\data\fanStudent\dataset1\GTpng\GTpng\0000_mask.png"
filename = '0.png'
image = Image.open(image_path)
img_arr = np.array(image)
# print(type(img_arr))
# print(img_arr.shape) # (777, 1286)
height, width = img_arr.shape
print(height, width)

mask = np.zeros((height, width))
h, w = mask.shape
print(h, w)
# 遍历图像的每个像素,并输出像素值
for y in range(height):
    for x in range(width):
        pixel_value = img_arr[y, x]
        if pixel_value:
            mask[y, x] = 255
            
cv2.imwrite(filename, mask)
# 这是一个文件夹的情况
import os
import cv2
import numpy as np
from PIL import Image

def mask2binary(input_folder, output_folder):
    # 获取输入文件夹中的所有PNG图片
    input_files = [f for f in os.listdir(input_folder) if f.endswith('.png')]

    for input_file in input_files:
        input_path = os.path.join(input_folder, input_file)
        image = Image.open(input_path)

        img_name = os.path.splitext(os.path.basename(input_file))[0]
        print(img_name)
        filename = img_name[:4]

        img_arr = np.array(image)
        height, width = img_arr.shape

        # 创建空的掩码
        mask = np.zeros((height, width))

        # 遍历图像的每个像素,并将非零值置为255
        for y in range(height):
            for x in range(width):
                pixel_value = img_arr[y, x]
                if pixel_value:
                    mask[y, x] = 255

        # 保存二进制掩码
        output_path = os.path.join(output_folder, f"{filename}.png")
        cv2.imwrite(output_path, mask)

if __name__ == "__main__":
    input_folder = r"C:\Users\23608\Desktop\Luli_work\data\fanStudent\dataset1\GTpng\GTpng"
    output_folder = r"C:\Users\23608\Desktop\Luli_work\data\fanStudent\dataset1\GTpng\mask"
    os.makedirs(output_folder, exist_ok=True)
    mask2binary(input_folder, output_folder)

将二值图掩码转化成json文件, 代码(需要这个pycococreator-master, 应该是在github上直接下载的)

# mask2json.py
import os
import io
import json
import numpy as np
from pycococreatortools import pycococreatortools
from PIL import Image
import base64

'''
该函数用于将图像转化为base64字符类型
:param img_pil: Image类型
:return base64_string: 字符串
'''
def img_tobyte(img_pil):
    ENCODING = 'utf-8'
    img_byte = io.BytesIO()
    img_pil.save(img_byte, format = 'PNG')
    binary_str2 = img_byte.getvalue()
    imageData = base64.b64encode(binary_str2)
    base64_string = imageData.decode(ENCODING)
    return base64_string

# ROOT_DIR = '/home/luli/TongueSAM/mask2json/' # 请输入你文件的根目录
ROOT_DIR = '/home/luli/TongueSAM/fanStudent/jsonOutput/dataset2'
# Image_DIR = os.path.join(ROOT_DIR, 'Images') # 目录底下包含图片
Image_DIR = '/home/luli/TongueSAM/fanStudent/imgInput/dataset2'
Label_DIR = '/home/luli/TongueSAM/fanStudent/imgOutput/dataset2Output/output1'

# Image_DIR = '/home/luli/TongueSAM/mask2json/Images'
# Label_DIR = '/home/luli/TongueSAM/mask2json/GT'

# Label_DIR = os.path.join(ROOT_DIR, "GT")     # 目录底下包含label文件
Label_files = os.listdir(Label_DIR)          # 读取路径下的掩码
class_names = ['_background_', 'tongue']     # 指定png中index中对应的label

for Label_filename in Label_files:
    Json_output = {
        "version": "3.16.7",
        "flags": {},
        "fillColor": [255, 0, 0, 128],
        "lineColor": [0, 255, 0, 128],
        "imagePath": {},
        "shapes": [],
        "imageData": {}}
    print(Label_filename)
    
    name = Label_filename.split('.', 3)[0]
    name1 = name+'.jpg'
    Json_output['imagePath'] = name1
    image = Image.open(Image_DIR + '/' +name1)
    imageData = img_tobyte(image)
    Json_output['imageData'] = imageData

    # 获得注释的掩码
    binary_mask = np.array(np.array(Image.open(Label_DIR + '/' + Label_filename))).astype(np.uint8)

    # 分别对掩码中的label结果绘制边界点
    for i in np.unique(binary_mask):
        if i !=0:
            temp_mask = np.where(binary_mask == i, 1, 0)
            # 将二进制掩码转换为多边形表示:
            segmentation = pycococreatortools.binary_mask_to_polygon(temp_mask[:,:,0], tolerance = 7)
            for item in segmentation:
                if (len(item) > 10):
                    list1 = []
                    for j in range(0, len(item), 2):
                        list1.append([item[j], item[j+1]])
                    label = class_names[1]
                    seg_info = {'points': list1, "fill_color": None, "line_color": None, "label": label,
                                "shape_type": "polygon", "flags": {}}
                    Json_output['shapes'].append(seg_info)
    Json_output['imageHeight'] = binary_mask.shape[0]
    Json_output['imageWidth'] = binary_mask.shape[1]

    # 保存在根目录下的json文件中
    full_path = '{}/'+name+'.json'
    with open(full_path.format(ROOT_DIR), 'w') as output_json_file:
        json.dump(Json_output, output_json_file)

现在有了mask.png, img.jpg

在运行finetunne_and_inference_tutorial_D_data.ipynb这个代码代码之前,需要执行pre_gre_rgb2d.py制作数据集
创建mytrain.sh执行文件,制作数据集

python -m  pre_grey_rgb2D.py \
    --img_path /share1/luli/MedSAM/data/samfune/train/images \
    --gt_path /share1/luli/MedSAM/data/samfune/train/labels \
    --npz_path /share1/luli/MedSAM/data/my_npz_path \
    --data_name mytrain \
    --img_name_suffix .jpg

制作完成数据集会出现一个npz的数据,这个npz会在finetunne_and_inference_tutorial_D_data.ipynb的训练部分用到,在测试部分就不需要用数据转化了,直接是jpg+mask.png进行测试。

1-525张图片是公司人收集的数据集;
526- 708 来自dataset1; 183张
709-888来自dataset2;180张
889-925来自dataset;37张

使用SamMed微调的顺序

数据集结构

先把上述的数据集按照7:2划分为train,test

-images
-1.jpg
-2.jpg

-labels
-1.png
-2.png

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C语言】长篇详解,字符系列篇2-----strcat,strcmp,strncpy,strncat,strncmp函数的使用和模拟实现【图文详解】

欢迎来CILMY23的博客喔,本期系列为【C语言】长篇详解,字符系列篇2-----“混杂”的字符串函数,字符串函数的使用和模拟实现【图文详解】,图文讲解各种字符串函数,带大家更深刻理解C语言中各种字符串函数的应用&#xff…

springmvc+ssm+springboot房屋中介服务平台的设计与实现 i174z

本论文拟采用计算机技术设计并开发的房屋中介服务平台,主要是为用户提供服务。使得用户可以在系统上查看房屋出租、房屋出售、房屋求购、房屋求租,管理员对信息进行统一管理,与此同时可以筛选出符合的信息,给笔者提供更符合实际的…

《Linux C编程实战》笔记:消息队列

消息队列是一个存放在内核中的消息链表,每个消息队列由消息队列标识符标识。与管道不同的是消息队列存放在内核中,只有在内核重启(即操作系统重启)或显示地删除一个消息队列时,该消息队列才会被真正的删除。 操作消息…

英伟达推出免训练,可生成连贯图片的文生图模型

目前,多数文生图模型皆使用的是随机采样模式,使得每次生成的图像效果皆不同,在生成连贯的图像方面非常差。 例如,想通过AI生成一套图像连环画,即便使用同类的提示词也很难实现。虽然DALLE 3和Midjourney可以对图像实现…

如何修改unity的背景颜色

要在Unity中将背景颜色设为黑色,可以按照以下步骤进行: 1、在Unity编辑器中,选择你想要修改背景颜色的摄像机对象(一般是Main Camera)。 2、在Inspector面板中,找到"Clear Flags"(清…

掌握Redis核心:常用数据类型的高效运用秘籍!

在数据驱动的时代,高效地存储和处理数据成为了开发者们的重要任务。Redis,作为一个开源的高性能键值对(key-value)数据库,以其独特的数据结构和丰富的功能,成为了众多项目的首选。 今天,我们就…

高精度双向计量旋翼干式脉冲水表

在现代社会,水资源的合理利用与精确管理至关重要。随着科技的不断进步,水表技术也在迭代升级。今天,我们将探讨一种高科技水表——高精度双向计量旋翼干式脉冲水表,它如何改变我们的用水习惯,提升水资源管理的效率。 1…

Stable Diffusion 模型分享:FenrisXL(芬里斯XL)

本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十 下载地址 模型介绍 FenrisXL 是一个拟人化的 SDXL 模型,可以为动物们穿上人类的衣服&…

吴恩达机器学习全课程笔记第三篇

目录 前言 P42-P48 神经元和大脑 神经网络中的层 更复杂的神经网络 前向传播(做出预测) P49-P53 代码中的推理 构建一个神经网络 P54-P60 矩阵乘法 TensorFlow框架实现神经网络 前言 这是吴恩达机器学习笔记的第三篇,第二篇笔记…

苍穹外卖学习-----2024/02/21

1.新增员工 /*** 处理SQL异常* param sqlIntegrityConstraintViolationException* return*/ExceptionHandlerpublic Result exceptionHandler(SQLIntegrityConstraintViolationException sqlIntegrityConstraintViolationException){//String message sqlIntegrityConstraintV…

IDEA启动Springboot报错:无效的目标发行版:17 的解决办法

无效的目标发行版:17 的解决办法 一般有两个原因,一可能是本地没有安装JDK17,需要安装后然后在IDEA中选择对应版本;二可能是因为IDEA版本太低,不支持17,需要升级IDEA版本。然后在File->Project Struct…

Zabbix 6.2.1 安装

目录 1、监控介绍 监控的重要性 网站的可用性 监控范畴 如何监控 2、Zabbix 介绍 zabbix 简介 zabbix 主要功能 zabbix 监控范畴 Zabbix 监控组件 zabbix 常见进程 zabbix agentd 工作模式 zabbix 环境监控中概念 3、搭建LNMP 拓扑规划 安装MySQL 安装 Nginx …

libpng编译-android端(libpng官网下载是没有android编译脚本)

libpng编译-android端(libpng官网下载是没有android编译脚本) 环境配置(mac的原理一样可以自己配置,我在linux编译) 配置ubuntu的ndk环境 1、执行 sudo vim /etc/profile,对Path的路径文件进行更改&…

python(23)——while循环

前言 在Python中,while 循环用于重复执行一段代码块,只要指定的条件保持为真(True)。一旦条件变为假(False),循环就会终止。while 循环通常用于在不知道循环将执行多少次的情况下进行迭代。 w…

linux下开发,stm32和arduino,我该何去何从?

linux下开发,stm32和arduino,我该何去何从? 在开始前我有一些资料,是我根据网友给的问题精心整理了一份「stm3的资料从专业入门到高级教程」, 点个关注在评论区回复“888”之后私信回复“888”,全部无偿共…

React 模态框的设计(一)拖动组件的设计

春节终结束了,忙得我头疼。终于有时间弄自己的东西了。今天来写一个关于拖动的实例讲解。先看效果: 这是一个简单的组件设计,如果用原生的js设计就很简单,但在React中有些事件必须要多考虑一些。这是一个系列的文章,…

Megalinter 初体验

简介 MegaLinter 是一个多语言、多工具的集成代码检查工具,它能够通过一个统一的工作流来运行多个静态代码分析工具,从而提供全面的代码质量检查。 官网:https://megalinter.io/latest/ MegaLinter 的特点: 多语言支持&#x…

深入理解指针(c语言)

目录 一、使用指针访问数组二、数组名的理解1、数组首元素的地址2、整个数组 三、一维数组传参的本质四、冒泡排序五、二级指针六、指针数组 一、使用指针访问数组 可以使用指针来访问数组元素。例如,可以声明一个指针变量并将其指向数组的第一个元素,然…

QT-模拟电梯上下楼

QT-模拟电梯上下楼 一、演示效果二、核心程序三、下载链接 一、演示效果 二、核心程序 #include "ElevatorController.h" #include <QGridLayout> #include <QLabel> #include <QGroupBox> #include <QGridLayout> #include <QPushButto…

2024「诺奖风向标」斯隆奖出炉:杨笛一、杜少雷、清华校友姜楠、北大校友金驰等入选​

今天&#xff0c;斯隆基金会公布了 2024年度斯隆研究奖&#xff08;Sloan Research Fellowship&#xff09;获得者名单&#xff0c;本次斯隆研究奖共颁发给了126 人&#xff0c;其中计算机科学领域 共有 7名华人学者当选。 包括斯坦福大学杨笛一&#xff08;上海交大ACM班校友…