deeplab语义分割训练自定数据集

链接:https://pan.baidu.com/s/1KkkM1rLfyiMPtYLycpnxmg?pwd=j2rd

提取码:j2rd

--来自百度网盘超级会员V2的分享

采用数据集: https://aistudio.baidu.com/datasetdetail/130647

采用代码:

https://github.com/jfzhang95/pytorch-deeplab-xception

本文会讲解两种方法:一种是使用开源数据集(不是deeplab支持的数据集)完成在deeplab上训练,另一种是通过标注自定义数据集来完成训练

第一种用开源数据集训练

将carvana image masking challenge数据集转化为Pascal VOC 格式

以下讲述你需要更改的一些地方以及怎么更改

首先要看你的模型支持什么样的数据集,一般通过train.py文件或者通过github文档查看

或者通过train.py

可见deeplab支持这4种VOC, SBD, Cityscapes and COCO datasets

要自定义数据集就需要把你的数据集转化以上4种即可,本文是将数据集转化为VOC 格式

下载数据集https://aistudio.baidu.com/datasetdetail/130647后,结构如下

也就是这个数据集只有train_mask和train_hq,test一般都是没有模板的,在语义分割中test是不需要模板的,其他的数据集也是这样,test只用来看最后的效果。

VOC 格式如下:

也就是需要提供JPEGImages、SegmentationClass、ImageSets

或者你可以查看代码中

通过这个代码也大概知道需要提供什么文件夹

整理好需求,然后直接跟deepseek进行沟通:

将需求拆解开来一步一步来,

1、首先将carvana image masking challenge的train_mask中的git后缀改成png

2、因为VOC 格式的标签和图像的名称是对应的,所以需要将carvana image masking challenge的_mask.gif改为.png

然后他会生成一个代码,你可以跑一下,看是否解决问题了,如果这个问题解决了就解决下一个需求

也就是目前解决了SegmentationClass,接下来需要解决JPEGImages

 

因为carvana image masking challenge的train_hq的图片格式也是jpg,所以你只需要将train_hq文件夹的名称改成JPEGImages即可

也就是解决了SegmentationClass、JPEGImages,接下来解决ImageSets

然后生成新的代码,就完成了数据集的格式转化。

也就是这个过程你主要做的是怎么将需求转化成多个步骤,一步一步完成需求就可以,以后不管是要转化成coco格式还是Cityscapes 都可以用这种方法。

比如Cityscapes 我可能先将train_hq拆分成train文件夹、val文件夹、test文件夹,train_masks也是拆分成3个文件夹,并且图片和标签的路径需要一致,名称需要根据Cityscapes 定义。然后我们知道Cityscapes 的train、val下还会有城市名称,我们随便起一个城市名称北京,路径格式对应就可以

最后我的carvana image masking challenge就转化成这种Cityscapes 风格

说话carvana image masking challenge转化为VOC 格式,我们已经完成了所有步骤,我把这个程序命名为了拆分.py,运行我们的程序“拆分.py”

第二种方法通过标注训练自定数据集

一、准备数据集

1. 数据集文件夹目录

  • ImageSets 文件夹内还有一个文件夹Segmentation,里面存放的是训练集、测试集txt文件

  • JPEGImages 存放原图image

  • SegmentationClass 存放原图对应的mask,要和JPEGImages里的图片一一对应

2. yolo格式转json格式

我使用的标注方式是: Sign in to Roboflow ,大大减少了标注时间,推荐!!!

导出yolo格式之后进行转json格式,代码如下

import json
import os

# 输入TXT标注文件夹路径
txt_folder_path = "E:/VScode project/pytorch-deeplab-xception-master111/Seg552/txt/"
# 输出JSON文件夹路径
json_folder_path = "E:/VScode project/pytorch-deeplab-xception-master111/Seg552/json/"

# 确保输出文件夹存在
os.makedirs(json_folder_path, exist_ok=True)

# 类别ID映射(如有需要可以修改)
label_mapping = {1: "ripe fruits", 0: "branch"}

# 遍历TXT文件夹
for txt_file in os.listdir(txt_folder_path):
    if txt_file.endswith('.txt'):
        txt_file_path = os.path.join(txt_folder_path, txt_file)
        json_file_path = os.path.join(json_folder_path, txt_file.replace('.txt', '.json'))

        # JSON模板
        json_data = {
            "version": "5.2.1",
            "flags": {},
            "shapes": [],
            "imagePath": txt_file.replace('.txt', '.jpg'),  # 假设图像名与TXT文件名相同
            "imageHeight": 1080,
            "imageWidth": 1920
        }

        # 解析TXT文件并构造JSON结构
        with open(txt_file_path, 'r') as file:
            for line in file:
                # 分割类别ID和坐标数据
                parts = line.strip().split()
                class_id = int(parts[0])  # 类别ID
                label = label_mapping.get(class_id, "unknown")  # 类别名称
                coordinates = list(map(float, parts[1:]))  # 坐标数据

                # 将坐标数据转换为(x, y)点对,并按比例转换为实际像素位置
                points = []
                for i in range(0, len(coordinates), 2):
                    x = coordinates[i] * json_data["imageWidth"]
                    y = coordinates[i + 1] * json_data["imageHeight"]
                    points.append([x, y])

                # 添加标注信息到JSON
                shape_data = {
                    "label": label,
                    "points": points,
                    "group_id": None,
                    "description": "",
                    "shape_type": "polygon",
                    "flags": {}
                }
                json_data["shapes"].append(shape_data)

        # 保存为JSON文件
        with open(json_file_path, 'w') as json_file:
            json.dump(json_data, json_file, indent=2)

        print(f"已成功将 {txt_file} 转换为 JSON 文件:{json_file_path}")

3. 文件夹重命名

虽然用网页标注导出来的image和TXT文件的名称是一致的,但为了避免在后续格式转换中出现冲突,现在需要将image图片和txt文件重新命名。相应代码:

import os

# 文件夹路径
folder1 = 'E:/VScode project/pytorch-deeplab-xception-master111/Seg552/txt/'  # 替换为您的文件夹路径
folder2 = 'E:/VScode project/pytorch-deeplab-xception-master111/Seg552/img/'  # 替换为您的文件夹路径

# 获取文件名列表
files1 = os.listdir(folder1)
files2 = os.listdir(folder2)

# 对文件进行排序,确保顺序一致
files1.sort()
files2.sort()

# 确保两个文件夹的文件数相同
if len(files1) != len(files2):
    print("警告:两个文件夹的文件数量不同!")

# 重命名第一个文件夹的文件
for idx, filename in enumerate(files1):
    new_name = f"{idx:03d}{os.path.splitext(filename)[1]}"  # 保留后缀
    os.rename(os.path.join(folder1, filename), os.path.join(folder1, new_name))

# 重命名第二个文件夹的文件
for idx, filename in enumerate(files2):
    new_name = f"{idx:03d}{os.path.splitext(filename)[1]}"
    os.rename(os.path.join(folder2, filename), os.path.join(folder2, new_name))

print("重命名完成。")

4. json格式转mask图片

import argparse
import base64
import json
import os
import os.path as osp
import imgviz
import PIL.Image
from labelme.logger import logger
from labelme import utils
import glob
import yaml

def main():
    logger.warning(
        "This script is aimed to demonstrate how to convert the "
        "JSON file to a single image dataset."
    )
    logger.warning(
        "It will handle multiple JSON files to generate a "
        "real-use dataset."
    )

    parser = argparse.ArgumentParser()
    parser.add_argument("--json_dir", required=True)
    parser.add_argument("-o", "--out", required=True)
    args = parser.parse_args()

    json_dir = args.json_dir
    output_dir = args.out

    if osp.isfile(json_dir):
        json_list = [json_dir] if json_dir.endswith('.json') else []
    else:
        json_list = glob.glob(os.path.join(json_dir, '*.json'))

    for json_file in json_list:
        logger.info(f"Processing file: {json_file}")
        json_name = osp.basename(json_file).split('.')[0]
        out_dir = osp.join(output_dir, json_name)

        if not osp.exists(out_dir):
            os.makedirs(out_dir)

        try:
            data = json.load(open(json_file))
        except Exception as e:
            logger.error(f"Error loading JSON file {json_file}: {e}")
            continue  # Skip to the next file

        imageData = data.get("imageData")

        if not imageData:
            image_filename = osp.basename(data["imagePath"])
            imagePath = osp.join("E:/VScode project/pytorch-deeplab-xception-master111/Seg552/JPEGImages", image_filename)
            try:
                with open(imagePath, "rb") as f:
                    imageData = f.read()
                    imageData = base64.b64encode(imageData).decode("utf-8")
            except FileNotFoundError:
                logger.error(f"File not found: {imagePath}")
                continue  # Skip to the next JSON file
            except Exception as e:
                logger.error(f"Error reading image file {imagePath}: {e}")
                continue

        try:
            img = utils.img_b64_to_arr(imageData)

            label_name_to_value = {"_background_": 0}
            for shape in sorted(data["shapes"], key=lambda x: x["label"]):
                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_value
            
            lbl, _ = utils.shapes_to_label(img.shape, data["shapes"], label_name_to_value)

            label_names = [None] * (max(label_name_to_value.values()) + 1)
            for name, value in label_name_to_value.items():
                label_names[value] = name

            lbl_viz = imgviz.label2rgb(lbl, imgviz.asgray(img), label_names=label_names, loc="rb")

            # Save files to corresponding subdirectory
            PIL.Image.fromarray(img).save(osp.join(out_dir, "img.png"))
            utils.lblsave(osp.join(out_dir, "label.png"), lbl)
            PIL.Image.fromarray(lbl_viz).save(osp.join(out_dir, "label_viz.png"))

            with open(osp.join(out_dir, "label_names.txt"), "w") as f:
                for lbl_name in label_names:
                    f.write(str(lbl_name if lbl_name is not None else "unknown") + "\n")

            yaml_data = {
                "label_name_to_value": label_name_to_value,
                "label_names": label_names
            }
            with open(osp.join(out_dir, "labels.yaml"), "w") as yaml_file:
                yaml.dump(yaml_data, yaml_file)

            logger.info(f"Saved to: {out_dir}")

        except Exception as e:
            logger.error(f"Error processing file {json_file}: {e}")

if __name__ == "__main__":
    main()

运行指令为:

python My_json_to_dataset.py --json_dir "E:/VScode project/pytorch-deeplab-xception-master111/Seg552/json" -o "E:/VScode project/pytorch-deeplab-xception-master111/Seg552/labelme_json"

生成的文件为

需要将labelme_json文件下的每个文件中的label.png文件重新命名,相应代码:

import os

# 替换为你的json文件夹所在的目录
json_dir = "E:/VScode project/pytorch-deeplab-xception-master111/Seg552/labelme_json"

for root, dirs, files in os.walk(json_dir):
    for dr in dirs:
        file_dir = os.path.join(root, dr)

        # 确认label.png文件存在
        label_file = os.path.join(file_dir, 'label.png')
        if os.path.exists(label_file):
            # 将文件夹名分割,得到原图名
            original_name = dr.split('_')[0] + '.png'
            new_file_name = os.path.join(file_dir, original_name)

            # 执行重命名操作
            os.rename(label_file, new_file_name)
            print(f"Renamed '{label_file}' to '{new_file_name}'")

最后将提取出所有文件夹中的000.png 并放在指定目录中,相应代码:

import os
from shutil import copyfile

for root, dirs, names in os.walk(
        "E:/VScode project/pytorch-deeplab-xception-master111/Seg552/labelme_json"):  # 改成你自己的json文件夹所在的目录
    for dr in dirs:
        file_dir = os.path.join(root, dr)
        print(dr)
        file = os.path.join(file_dir, dr + '.png')
        print(file)
        new_name = dr.split('_')[0] + '.png'
        new_file_name = os.path.join(file_dir, new_name)
        print(new_file_name)

        tar_root = 'E:/VScode project/pytorch-deeplab-xception-master111/Seg552/Segmentationclass'  # 目标路径
        tar_file = os.path.join(tar_root, new_name)
        copyfile(new_file_name, tar_file)

该代码运行得到的文件,就是我们所需要的SegmentationClass

5. 生成txt文件

生成的训练集txt和验证集txt,里面的图片名称( 去掉后缀 )的分配是随机的。相应代码:

import os
import random

# 设置图像目录和输出目录
image_dir = 'E:/VScode project/pytorch-deeplab-xception-master111/Seg552/JPEGImages'  # 替换为你的图像目录
output_dir = 'E:/VScode project/pytorch-deeplab-xception-master111/Seg552/ImageSets/Segmentation'  # 替换为输出目录

# 获取所有图像文件名(去掉后缀)
image_files = [f.split('.')[0] for f in os.listdir(image_dir) if f.endswith(('.jpg', '.png'))]

# 随机打乱图像文件名
random.shuffle(image_files)

# 分割训练集和验证集
train_files = image_files[:int(len(image_files) * 0.8)]  # 80% 为训练集
val_files = image_files[int(len(image_files) * 0.8):]  # 20% 为验证集

# 写入 train.txt
with open(os.path.join(output_dir, 'train.txt'), 'w') as f:
    for file in train_files:
        f.write(f"{file}\n")

# 写入 val.txt
with open(os.path.join(output_dir, 'val.txt'), 'w') as f:
    for file in val_files:
        f.write(f"{file}\n")

print("train.txt 和 val.txt 已生成。")

 

修改deeplab代码

然后就是改代码,train.py中的dataset改成我们自定义的llmCver数据集,名称随便起

修改训练层数和学习率,当然这个可能不需要修改,因为在上面parser.add_argument也有个层数和学习率,但是我看到了以防万一也改动了。

修改mypath.py,加入你的路径

修改dataloaders\utils.py,因为我自定义的数据集只有两个类别

 

def decode_segmap(label_mask, dataset, plot=False):我们加入了label_colours = get_llmCver_labels(),

也就是我们调用了get_llmCver_labels()函数,我们需要在下面把get_llmCver_labels()的定义写清楚。

怎么定义你可以get_cityscapes_labels和get_pascal_labels函数怎么写的,你模仿着写。

我看到carvana image masking challenge只有两个类别,车和背景,也就是模板里面只有[0, 0, 0]和[255, 255, 255]两个颜色,所以我的get_llmCver_labels函数里就定义了这两个颜色,[0, 0, 0]存储第一位,所以他是对应类别0,[255, 255, 255]存储第二位对应类别1。这样代码就区分出了两种类别。

carvana image masking challenge数据集有多少个类别可以直接问ai,这种信息类的ai一般通过网络信息整理会找的比人快。或者根据经验判断。

dataloaders\datasets\llmCver.py在这个路径下加入llmCver.py,用于代码解析自定义数据集路径信息。这个代码怎么写?可以参考pascal.py(因为我们模仿的是pascal voc,所以voc有什么代码我们跟着做就可以)

复制pascal.py后将改一下文件名称,我改成了llmCver.py

下面的if name == '__main__':里的函数也需要改一下,但是不改也可以。

顺便讲一下if name == '__main__',假如我们在做一个机器人项目,那么我们会将这个项目手.py、脚.py、头.py等等还有一个整体调用.py。我做到最后肯定是调用整体调用.py就能完成整个机器人的运动,这时候只会用到整体调用.py里的if name == '__main__',而手.py、脚.py、头.py里面的if name == '__main__'是不会执行,因为此时整体调用.py是主函数。

当我们的手部出现异常了,为了调试手部的一些功能我们就只会调用手.py,这个时候我们的手.py是主函数,所以手.py里面的if name == '__main__'会生效,也就是我们每次运行程序最多只有一个程序能调用if name == '__main__'。你运行哪个程序,哪个程序里的if name == '__main__'就会生效。

dataloaders\__init__.py中加入

修改完基本就差不多了

然后修改train.py里面的参数,根据自己想要用什么主干网,多少学习率这些都不是固定,可以根据自己想法来,配置完直接按下右上角的运行键就可以跑起来了。

我的程序有个bug,不知道是本来就有的还是,就是训练的时候看不到进度,但是不影响训练。

File "d:\YOLO\pytorch-deeplab-xception-master\train.py", line 305, in <module> main() File "d:\YOLO\pytorch-deeplab-xception-master\train.py", line 298, in main trainer.training(epoch) File "d:\YOLO\pytorch-deeplab-xception-master\train.py", line 115, in training self.summary.visualize_image(self.writer, self.args.dataset, image, target, output, global_step) File "d:\YOLO\pytorch-deeplab-xception-master\utils\summaries.py", line 18, in visualize_image grid_image = make_grid(decode_seg_map_sequence(torch.max(output[:3], 1)[1].detach().cpu().numpy(), File "D:\APP\conda\envs\yolov5prune\lib\site-packages\torch\utils\_contextlib.py", line 115, in decorate_context return func(*args, **kwargs) TypeError: make_grid() got an unexpected keyword argument 'range'

如果报了这个错误是因为你的torch版本太高,修改一下程序就可以了

修改pytorch-deeplab-xception-master\utils\summaries.py

把range去掉就可以了

        # 处理输出图像
        grid_image = make_grid(
            decode_seg_map_sequence(torch.max(output[:3], 1)[1].detach().cpu().numpy(), dataset=dataset),
            nrow=3, normalize=False, scale_each=False
        )
        writer.add_image('Predicted label', grid_image, global_step)

        # 处理目标图像
        grid_image = make_grid(
            decode_seg_map_sequence(torch.squeeze(target[:3], 1).detach().cpu().numpy(), dataset=dataset),
            nrow=3, normalize=False, scale_each=False
        )

在Win10系统下,使用DeepLab V3进行语义分割训练自己的数据集可以通过以下步骤实现: 1. 准备数据集:首先,需要进行数据集的准备工作。收集大量的图像数据,并为每张图像标注像素级别的语义标签。确保训练图像和标签数据是一一对应的。 2. 安装依赖环境:在Win10系统下,首先需要安装Python和TensorFlow等深度学习框架,并配置好相应的环境变量。确保能够成功导入相关的库和模块。 3. 下载DeepLab V3:从GitHub上下载DeepLab V3的源代码,并解压到本地目录。在命令行中切换到DeepLab V3的根目录。 4. 数据预处理:使用脚本文件对数据集进行预处理,将图像和标签数据转换成模型可接受的格式。这可以通过运行预处理脚本来完成。 5. 配置参数:在配置文件中设置相关的训练参数,如训练图像的路径、标签的路径、模型的参数等。可以根据实际需要进行调整。 6. 运行训练:在命令行中运行训练脚本,该脚本会调用DeepLab V3模型进行训练。根据配置文件中的设置,模型将使用训练数据进行迭代训练,以优化模型的性能。 7. 评估模型:训练完成后,可以运行评估脚本对训练得到的模型进行评估。该脚本将使用测试数据进行预测,并计算出预测结果的准确性。 8. 使用模型:训练完成后,可以使用已训练好的模型对新的图像进行语义分割。通过在命令行中运行预测脚本,将输入图像作为参数进行预测,即可得到相应的语义分割结果。 以上是在Win10系统下使用DeepLab V3进行语义分割训练自己的数据集的基本步骤。根据具体情况和需求,可能还需要进行一些额外的调整和改进。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值