语义分割动手实践-bisenetv2模型训练

语义分割动手实践 - bisenetv2、deeplabv3+语义分割模型训练

接上文https://blog.csdn.net/Hu_helloworld/article/details/118610897?spm=1001.2014.3001.5501

我们已经可以通过labelme工具标注语义分割数据,然后根据labelme提供的labelme_json_to_dataset脚本,将所有json文件批量生成如下的训练数据:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tXa5wUXr-1635840679764)(https://raw.githubusercontent.com/RoboCuper-hujinlei/markdown-images/main/20210709171227801.png)]

然后我们通过方法

1、moveSrcMasksImage()分别将原图(img.png)和掩膜图像(label.png)移动整理到JPEGImages和SegmentationClass文件夹。

2、通过couple_img_masks()方法制作、划分数据集。

deeplabv3+训练

这样划分出的数据集是一个原图img.png对应一个根据类别颜色分割的掩膜图像label.png。

采用VOC格式的数据集,img.png 和 label.png分别放入JPEGImages和SegmentationClass文件夹中,划分数据集将文件名写入train.txt和val.txt。训练时可选择resnet、mobilenet等多个backbone

用这样的数据集训练deeplab系列模型没问题。具体使用参见官方repo:https://github.com/jfzhang95/pytorch-deeplab-xception

bisenetv2训练

但这些数据在bisenetv2训练时出现“RuntimeError: copy_if failed to synchronize: cudaErrorIllegalAddress: an illegal memory access was encountered”的报错,原因是bisenetv2要求输入的标签是单通道的灰度图。而我们的mask图像仍然是RGB图

我们知道RGB图像可以用颜色区分类别,而灰度图每个像素只有0-255的灰度值,如何用单通道的灰度图表示多种类别呢?

解决思路巧妙的将每个类别的rgb颜色值用单通道的0,1…255灰度值置换。

其中我们用labelme脚本labelme_json_to_dataset生成的__json文件夹中:

  • img.png 对应的局部的jpg原图文件,训练时要用
  • label.png 局部语义类别标签
  • label_names.txt 在这张图像上目标的分类名称
  • label_viz.png 可视化标签图,便于我们确认是否标记正确

我们得到RGB的label.png(局部语义类别标签)后,还需要进行灰度类别转换成单通道的标签图像:
灰度类别转换后,属于背景区域的像素点的值全是0,属于标记目标的像素点按照所有类别名的顺序1,2…255排列。如属于cat的像素点值全是1。若再加一个dog像素点值就全是2

灰度类别转换 (局部类别标签RGB—>全局类别标签GRAY)
'''
TODO:
提取__json目录下的原图、并将label.png转换为最终的单通道标签。
param:
    __jsondir: labelme生成的__json文件夹目录
    class_txt:  所有像素的类别(包括背景0)
    image_path: 提取的原图路径
    label_path: 提取并转换的单通道全局标签路径
    
输出转换的标签数量、原图和标签的路径
Note:
	__json文件夹已全部生成,并将img.png,label.png提取整理到不同路径
'''


def label2singlechannel(__jsondir, class_txt='class_name.txt', image_path=None, label_path=None):
    class_txt = open(class_txt, "r", encoding='utf-8')
    class_names = class_txt.read().splitlines()     # 全局类别

    if image_path==None and label_path==None:
        image_path = os.path.join(__jsondir.rsplit('/', 2)[0], 'JPEGImages')
        label_path = os.path.join(__jsondir.rsplit('/', 2)[0], 'SegmentationClass')

    if not os.path.exists(image_path):
        os.mkdir(image_path)
    if not os.path.exists(label_path):
        os.mkdir(label_path)

    for json_dir in os.listdir(__jsondir):
        src_path = os.path.join(__jsondir, json_dir, 'img.png')
        file_path = os.path.join(__jsondir, json_dir, 'label.png')

        if not os.path.exists(src_path) or not os.path.exists(file_path):   # 文件夹为空 img不存在
            continue
        label_names = os.path.join(__jsondir, json_dir, 'label_names.txt')
        src = Image.open(src_path)
        src.save(os.path.join(image_path, json_dir+'.png'))

        img = Image.open(file_path)
        with open(label_names, "r") as f:
            names = f.read().splitlines()       # x_json文件里面存在的类 局部的类
        new = Image.new("RGB", [np.shape(img)[1], np.shape(img)[0]])
        # 找到局部的类在全局中的类的序号
        for name in names:
            index_json = names.index(name)      # 局部类
            index_all = class_names.index(name)      # 全局类别
            # 将局部类转换成为全局类
            # 将原图img中像素点的值为index_json的像素点乘以其在全局中的像素点的所对应的类的序号 得到 其实际在数据集中像素点的值

            # 比如dog,在局部类(output/x_json/label_names)中它的序号为1,dog在原图中的像素点的值也为1.
            # 但是在全局的类(before/classes.txt)中其对应的序号为2,所以在新的图片中要将局部类的像素点的值*全局类的序号,从而得到标签文件
            new = new + np.expand_dims(index_all * (np.array(img) == index_json), -1)
        
        new = Image.fromarray(np.uint8(new))    
        # 将转变后的得到的新的最终的标签图片保存到make_dataset/png文件夹下
        new.save(os.path.join(label_path, json_dir + '.png'))
        print(f"save: - {os.path.join(label_path, json_dir + '.png')}")
        # 找到新的标签文件中像素点值的最大值和最小值,最大值为像素点对应的类在class_name.txt中的序号,最小值为背景,即0
        print(np.max(new), np.min(new))
    print(f"\nJPEGImages: {image_path}\nSegmentationClass: {label_path}") 

由于像素点灰度值0 1 2亮度值很小,最终生成参与训练的全局标签文件是这种全黑的。

用原图 + 单通道的标签图像即可训练BiseNetv2模型。

具体BiseNetv2的训练方式可参考官方repo:https://github.com/CoinCheung/BiSeNet或其他教程

件是这种全黑的。

用原图 + 单通道的标签图像即可训练BiseNetv2模型。

具体BiseNetv2的训练方式可参考官方repo:https://github.com/CoinCheung/BiSeNet或其他教程

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
融合语义分割的ORB-SLAM2是一种在视觉SLAM(Simultaneous Localization and Mapping,即同时定位与建图)系统中引入语义分割信息的方法。ORB-SLAM2是一个经典的基于特征点的SLAM系统,它利用摄像头的视觉信息进行实时定位和建图。 语义分割是一种计算机视觉任务,目标是将图像中的每个像素分配到预定义的语义类别中。在融合语义分割的ORB-SLAM2中,通过将语义分割的结果与ORB-SLAM2的特征点匹配进行融合,可以提供更丰富的场景理解和语义感知。 具体来说,融合语义分割的ORB-SLAM2通常包括以下几个步骤: 1. 预处理:对输入图像进行语义分割处理,得到每个像素的语义类别。 2. 特征提取与匹配:使用ORB-SLAM2提取特征点,并对特征点进行描述子计算。同时,根据语义分割结果,筛选出具有特定语义类别的特征点。 3. 运动估计与优化:使用筛选后的特征点进行相机运动估计和地图优化,得到相机的姿态和三维地图。 4. 语义一致性检测:利用语义分割结果对地图进行语义一致性检测,即保证地图中的语义类别与实际场景一致。 通过融合语义分割信息,ORB-SLAM2可以提供更准确和丰富的场景理解。例如,在室内场景中,可以区分墙壁、地板、家具等不同的语义类别,从而提高定位和建图的精度,并为机器人或无人车等应用提供更多语义感知的能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值