小菊的语义分割3——数据预处理及像素级分类实现原理

本文详细介绍了语义分割任务中数据预处理的步骤,包括图像尺寸调整、归一化、数据增强等,并阐述了标签映射和像素级分类原理。通过Keras和TensorFlow实现模型训练,利用数据生成器加载数据,定义损失函数并进行模型编译与训练。同时,展示了如何优化标签处理以提高效率。

小菊的语义分割3🌼——数据预处理及像素级分类实现原理

1. 数据预处理

思路: 读取train.txt文件,获取训练图像及对应标签的文件路径,读取图像,将图像转化为tensor之后,resize调整图像尺寸大小并进行归一化处理,之后也可通过旋转,色偏,增加噪声等方式进行数据增强。注意要保证图像和标签的处理一致。

padding可以使图像在resize时不失真

2. label map 标签映射

如图就是我们的语义分割标签图像,相同颜色(像素值)的像素点代表的是同一类物体。假设像我们这个标签图像所展示的那样,我们需要分割出来图片中的猫和狗,那对我们的语义分割任务来说就是总共要分3类:0 背景;1 猫;2 狗;因此,我们需要创建一个[Height, Width, N_classes]数组来表示每一个像素点的类别;如下图所示:

label[0, 0] = [1, 0, 0] 说明[0, 0]位置是背景,label[1, 1] = [0, 1, 0]说明[1, 1]这个像素点属于猫。我们Reshape之后好像更方便大家理解:

seg_labels = np.reshape(seg_labels, (-1,NCLASSES))

 [[1, 0, 0],
  [1, 0, 0],
  [1, 0, 0],
  [1, 0, 0],
  [1, 0, 0],
  [0, 1, 0],
  [0, 0, 1],
  [0, 0, 1],
     ...
           ]

这就是我们最后用来和预测结果计算损失的数据啦🌼相信大家对为什么这样做还有点云里雾里的感觉,那么接下来就让我们揭开语义分割的神秘面纱吧🌼

3. 像素级分类原理

了解完lable的具体格式之后,我们来看一下网络的最后几层设计:

x = Conv2D(n_classes,(1,1), padding='vaild' )(x)
x = Reshape((-1,n_classes))(x)
output = Softmax()(x)

这个和我们label的处理是一致的,输出的是每一个像素点属于哪一类的概率,如下图:

tensor表示:


 [[0.4, 0.3, 0.3],
  [0.7, 0.2, 0.1],
  [0.8, 0.2, 0.0],
  [0.8, 0.1, 0.1],
        ...
                 ]

将我们处理之后的label和预测得到的结果传给我们的损失函数就能计算出loss了,这样我们就实现了像素级的分类————也就是语义分割了🌼

下面是包含了数据预处理,损失定义等整个模型训练过程的train.py文件,大家稍作修改就可以训练自己的语义分割模型了🌼

Keras实现

import numpy as np
from PIL import Image

import keras
from keras import backend as K
from keras.optimizers import Adam
from keras.layers import Lambda
from keras.callbacks import TensorBoard, ModelCheckpoint, ReduceLROnPlateau, EarlyStopping

# 标签像素值对应的物体类别, 0为背景
CLASSES = {
   
   
    '[0 0 0]' : 0, # 背景
    '[7 7 7]' : 1,
    '[26 26 26]' : 2,
}

NCLASSES = 2
HEIGHT = 576
WIDTH = 576

BATCH_SIZE = 2

# train.txt和val.txt的文件路径
path_train_txt = ''
path_val_txt = ''

# train的图像和标签路径
path_Xtrain = ''
path_Xlabel = ''
# val的图像和标签路径
path_Yval = ''
path_Ylabel = ''


# labels映射
def label_map(labels):
    labelmap = np.zeros((int(HEIGHT),int(WIDTH),NCLASSES))
    for h in range(int(HEIGHT)):
        for w in range(int(WIDTH)):
            if str(labels[h, w]) in CLASSES.keys():
                c = CLASSES[str(labels[h, w])]
            else:
                c = 0
            labelmap[h, w, c] = 1
    return labelmap


def data_generator(mode):
    assert mode in ['train', 'val'], \
        'mode must be ethier \'train\' or \'val\''

    if mode == 'train':
        with open(path_train_txt, 'r') as f:
            lines = f.readlines()
        np.random.shuffle(lines)

        n = len
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值