当前位置:   article > 正文

小生不财-语义分割2:训练自己的segnet模型(斑马线划分)_训练segnet

训练segnet

学习前言

  • 数据集以及标签详解
  • LOSS函数计算
  • 二、训练代码
    • 1.数据集的制作
    • 2.模型的训练
    • 3.模型的预测
  • 结果展示


前言

在第一部分完成了主干网络VGGnet还有segnet模型,这节主要简单讲一下模型的训练以及预测过程。如有遗忘参考小生不财-语义分割1:基于VGGNet模型的segnet讲解

数据集以及标签详解

语义分割模型训练的文件分为两部分。

第一部分是原图,像这样:

在这里插入图片描述

 第二部分标签,像这样:

在这里插入图片描述

 当你们看到这个标签的时候你们会说,我靠,你给我看的什么辣鸡,全黑的算什么标签,其实并不是这样的,这个标签看起来全黑,但是实际上在斑马线的部分其RGB三个通道的值都是1。

其实给你们换一个图你们就可以更明显的看到了。

在这里插入图片描述

这是它的标签。

在这里插入图片描述

为什么这里的标签看起来就清楚的多呢,因为在voc中,其一共需要分21类,所以火车的RGB的值可能都大于10了,当然看得见。所以,在训练集中,如果像本文一样分两类,那么背景的RGB就是000,斑马线的RGB就是111,如果分多类,那么还会存在222,333,444这样的。这说明其属于不同的类。

二、代码训练

1、数据集的制作

这里我自己制作了191例数据集,这里介绍如何把数据集制作成训练集和测试集,具体代码和注释如下:

  1. def train_data(NC):
  2. # 读取文件名,一部分是原图名字,另一部分是标签图片
  3. # txt是按行存的,读取时也是按照行读,中间使用的是';'分割的
  4. with open('dataset2/train.txt') as f:
  5. data = f.readlines()
  6. train = []
  7. label = []
  8. for ele in data:
  9. # 第一部分,读取训练集图片
  10. # 读取训练图片
  11. img = Image.open("dataset2/jpg/" + ele.split(';')[0])
  12. # 调整图片大小
  13. img = img.resize((WIDTH, HEIGHT))
  14. img = np.array(img)
  15. # 对图像进行归一化处理
  16. img = img / 255
  17. # 将图像存入train
  18. train.append(img)
  19. # 第二部分,读取label 这里必须和网络输出的格式一致,也就是说图片的长宽都要变为原来的1/2
  20. img = Image.open('dataset2/png/' + ele.split(';')[1].replace('\n', ''))
  21. # 调整图片大小
  22. img = img.resize((int(WIDTH / 2), int(HEIGHT / 2)))
  23. # 将图像转化为array ,然后进行归一化
  24. img = np.array(img)
  25. img = img / 255
  26. # 生成一个和segnet网络输出结构一致的图像
  27. seg_lable = np.zeros([int(WIDTH / 2), int(HEIGHT / 2), NC])
  28. # 因为斑马线三个通道都是1,背景为0
  29. for i in range(NC):
  30. # 因为标签图片,RGB第三个通道的值为1
  31. seg_lable[:, :, i] = (img[:, :, 0] == i).astype(int)
  32. # 进行一次reshape,将通道数进行调整,调整到和decoder格式一样
  33. seg_lable = np.reshape(seg_lable, (-1, NC))
  34. # 存放表情包
  35. label.append(seg_lable)
  36. return train, label

2、完整训练代码

  1. from net.segnet import mobilenet_segnet
  2. from tensorflow.keras.optimizers import Adam
  3. from PIL import Image
  4. import numpy as np
  5. import tensorflow as tf
  6. from tensorflow.keras.losses import binary_crossentropy
  7. from tensorflow.keras import backend as k
  8. import os
  9. # 定义分类种类
  10. NCLASSES = 2
  11. HEIGHT = 416
  12. WIDTH = 416
  13. # 制作数据集
  14. def train_data(NC):
  15. # 读取文件名,一部分是原图名字,另一部分是标签图片
  16. # txt是按行存的,读取时也是按照行读,中间使用的是';'分割的
  17. with open('dataset2/train.txt') as f:
  18. data = f.readlines()
  19. train = []
  20. label = []
  21. for ele in data:
  22. # 第一部分,读取训练集图片
  23. # 读取训练图片
  24. img = Image.open("dataset2/jpg/" + ele.split(';')[0])
  25. # 调整图片大小
  26. img = img.resize((WIDTH, HEIGHT))
  27. img = np.array(img)
  28. # 对图像进行归一化处理
  29. img = img / 255
  30. # 将图像存入train
  31. train.append(img)
  32. # 第二部分,读取label 这里必须和网络输出的格式一致,也就是说图片的长宽都要变为原来的1/2
  33. img = Image.open('dataset2/png/' + ele.split(';')[1].replace('\n', ''))
  34. # 调整图片大小
  35. img = img.resize((int(WIDTH / 2), int(HEIGHT / 2)))
  36. # 将图像转化为array ,然后进行归一化
  37. img = np.array(img)
  38. img = img / 255
  39. # 生成一个和segnet网络输出结构一致的图像
  40. seg_lable = np.zeros([int(WIDTH / 2), int(HEIGHT / 2), NC])
  41. # 因为斑马线三个通道都是1,背景为0
  42. for i in range(NC):
  43. # 因为标签图片,RGB第三个通道的值为1
  44. seg_lable[:, :, i] = (img[:, :, 0] == i).astype(int)
  45. # 进行一次reshape,将通道数进行调整,调整到和decoder格式一样
  46. seg_lable = np.reshape(seg_lable, (-1, NC))
  47. # 存放表情包
  48. label.append(seg_lable)
  49. return train, label
  50. # 自定义损失函数
  51. def loss(y_true, ypred):
  52. crossloss = binary_crossentropy(y_true, ypred)
  53. # 计算损失平均值
  54. loss = 4 * k.sum(crossloss) / HEIGHT / WIDTH
  55. return loss
  56. if __name__ == "__main__":
  57. # 加载数据
  58. train, labels = train_data(NCLASSES)
  59. train = np.array(train)
  60. labels = np.array(labels)
  61. # 对数据集进行打乱处理
  62. np.random.seed(11)
  63. np.random.shuffle(train)
  64. np.random.seed(11)
  65. np.random.shuffle(labels)
  66. print(train.shape)
  67. print(labels.shape)
  68. # 划分数据集
  69. total_num = train.shape[0]
  70. train_num = int(total_num * 0.9)
  71. x_train = train[:train_num, :, :, :]
  72. y_train = labels[:train_num, :, :]
  73. x_test = train[train_num:, :, :, :]
  74. y_test = labels[train_num:, :, :]
  75. # 获取模型
  76. model = mobilenet_segnet(n_classes=NCLASSES, input_width=WIDTH, input_height=HEIGHT)
  77. # 设置超参数
  78. model.compile(optimizer=Adam(), loss=loss, metrics=['accuracy'])
  79. # 保持模型路径
  80. model_save_path = './checks/crosswalk.h5'
  81. # 如果模型存在,则加载模型,在之前的基础上继续训练
  82. if os.path.exists(model_save_path + '.index'):
  83. print('--------------加载模型--------------')
  84. model.load_weights(model_save_path)
  85. # 设置模型模型要求
  86. cp_callback = tf.keras.callbacks.ModelCheckpoint(
  87. # 模型保存陆军
  88. filepath=model_save_path,
  89. # 只保存最好的一次
  90. save_best_only=True,
  91. # 保存模型
  92. save_weights_only=True
  93. )
  94. model.fit(x_train, y_train, batch_size=4, epochs=50, validation_data=(x_test, y_test), validation_freq=1,
  95. callbacks=[cp_callback])
  96. model.summary()

 3、模型预测代码实现

  1. from net.segnet import mobilenet_segnet
  2. from PIL import Image
  3. import numpy as np
  4. import copy
  5. import os
  6. # 给不同类别的目标,渲染颜色
  7. class_colors = [[0, 0, 0],
  8. [0, 255, 0]]
  9. NCLASSES = 2
  10. HEIGHT = 416
  11. WIDTH = 416
  12. # 加载模型
  13. model = mobilenet_segnet(n_classes=NCLASSES, input_height=HEIGHT, input_width=WIDTH)
  14. # 读取权重
  15. model.load_weights("./check/classess.ckpt")
  16. # 读取要预测的图片
  17. imgs = os.listdir("./img/")
  18. for jpg in imgs:
  19. # 对图片格式进行处理
  20. img = Image.open("./img/" + jpg)
  21. old_img = copy.deepcopy(img)
  22. orininal_h = np.array(img).shape[0]
  23. orininal_w = np.array(img).shape[1]
  24. img = img.resize((WIDTH, HEIGHT))
  25. img = np.array(img)
  26. img = img / 255
  27. img = img.reshape(-1, HEIGHT, WIDTH, 3)
  28. # 进行预测
  29. pr = model.predict(img)[0]
  30. # 调整通道,并返回通道上,每个轴上面的最大值
  31. pr = pr.reshape((int(HEIGHT / 2), int(WIDTH / 2), NCLASSES)).argmax(axis=-1)
  32. # 生成三通道黑色图片
  33. seg_img = np.zeros((int(HEIGHT / 2), int(WIDTH / 2), 3))
  34. colors = class_colors
  35. for c in range(NCLASSES):
  36. seg_img[:, :, 0] += ((pr[:, :] == c) * (colors[c][0])).astype('uint8')
  37. seg_img[:, :, 1] += ((pr[:, :] == c) * (colors[c][1])).astype('uint8')
  38. seg_img[:, :, 2] += ((pr[:, :] == c) * (colors[c][2])).astype('uint8')
  39. seg_img = Image.fromarray(np.uint8(seg_img)).resize((orininal_w, orininal_h))
  40. # 合成一副图像
  41. image = Image.blend(old_img, seg_img, 0.3)
  42. image.save("./img_out/" + jpg)

三、效果展示

原始图片

检测后图片

 


总结

        本文,在进行训练时,由于样本数和迭代次数较少,检测效果不是太好,希望大家学习之后可以改进,利用其他一些经典的卷积神经网络进行测试,比如ResNet、LeNet等去实现。也可以解码部分利用另外解码器进行解码。后续将更新一些新的方法。

训练代码和数据集地址:基于VGGnet模型的segnet斑马线划分-数据集文档类资源-CSDN下载

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/122378
推荐阅读
相关标签
  

闽ICP备14008679号