当前位置:   article > 正文

昇思25天打卡营-mindspore-ML- Day9-FCN图像语义分割

昇思25天打卡营-mindspore-ML- Day9-FCN图像语义分割

结束了入门教程。开始一些实例应用教程。

今天在mindspore平台上学习FCN图像语义分割。

先记录一下一些基本概念:(方便别人看,以及以后自己看)

什么是图像语义分割?

图像语义分割是 将图像中的每个像素点分配到一个语义类别。 与传统的图像分类任务不同,语义分割需要对图像中的每个像素进行精细的分类,而不是只识别图像中包含的物体类别。

语义分割的特点

  • 像素级预测: 语义分割任务需要输出与输入图像大小相同的分割图,其中每个像素都对应一个类别标签。
  • 类别层次结构: 语义分割通常涉及多个类别,例如天空、树木、道路、汽车、行人等,这些类别可能具有层次结构。
  • 局部和全局信息: 语义分割需要同时利用图像的局部特征和全局信息,例如物体的形状、纹理和上下文关系。

语义分割的应用

  • 自动驾驶: 用于识别道路、车辆、行人等,实现安全驾驶。
  • 机器人导航: 帮助机器人理解周围环境,进行路径规划。
  • 医学影像分析: 用于识别器官、病变等,辅助医生进行诊断。
  • 卫星图像分析: 用于识别土地类型、建筑物、道路等,进行资源管理和城市规划。

常用的语义分割模型

  • FCN (Fully Convolutional Network)
  • U-Net
  • DeepLab
  • Mask R-CNN

FCN (Fully Convolutional Network)用于语义分割的基本原理

FCN 模型就像一位超级精细的画家,它的目标是将一张彩色照片“上色”,让每个像素点都对应一个颜色,每种颜色代表一个类别(比如人、车、树)。就是说,FCN 模型就像一位超级精细的画家,它通过提取特征、缩小图像、恢复图像和跳跃连接等步骤,将一张彩色照片“上色”,让每个像素点都对应一个类别,从而实现图像的语义分割。

FCN 的工作流程:

  • 提取特征: FCN 首先通过一系列卷积和池化操作,提取图像中的特征,就像画家观察照片,找出不同的形状和纹理。
  • 缩小图像: 在提取特征的过程中,图像尺寸会逐渐缩小,就像画家将照片缩小,以便更好地观察细节。
  • 恢复图像: 为了得到与原图大小相同的分割图,FCN 需要进行上采样操作,将图像尺寸恢复到原始大小,就像画家将缩小的照片放大,并根据观察到的特征进行上色。
  • 跳跃连接: 为了保留图像的细节信息,FCN 会将浅层特征(细节丰富)与深层特征(全局信息)结合起来,就像画家在放大照片后,既参考整体轮廓,又参考细节纹理,才能画得更加精细。
  • 像素级预测: FCN 能够对图像中的每个像素进行精细的分类,得到更精确的分割结果。
  • 端到端学习: FCN 是一个端到端的学习模型,可以直接从原始图像学习到分割任务,无需手动设计特征。
  • 可扩展性: FCN 可以轻松扩展到不同的分割任务,例如人体姿态估计、视频分割等。

代码部分:


 

  1. import numpy as np
  2. import mindspore as ms
  3. import mindspore.nn as nn
  4. import mindspore.train as train
  5. class PixelAccuracy(train.Metric):
  6. def __init__(self, num_class=21):
  7. super(PixelAccuracy, self).__init__()
  8. self.num_class = num_class
  9. def _generate_matrix(self, gt_image, pre_image):
  10. mask = (gt_image >= 0) & (gt_image < self.num_class)
  11. label = self.num_class * gt_image[mask].astype('int') + pre_image[mask]
  12. count = np.bincount(label, minlength=self.num_class**2)
  13. confusion_matrix = count.reshape(self.num_class, self.num_class)
  14. return confusion_matrix
  15. def clear(self):
  16. self.confusion_matrix = np.zeros((self.num_class,) * 2)
  17. def update(self, *inputs):
  18. y_pred = inputs[0].asnumpy().argmax(axis=1)
  19. y = inputs[1].asnumpy().reshape(4, 512, 512)
  20. self.confusion_matrix += self._generate_matrix(y, y_pred)
  21. def eval(self):
  22. pixel_accuracy = np.diag(self.confusion_matrix).sum() / self.confusion_matrix.sum()
  23. return pixel_accuracy
  24. class PixelAccuracyClass(train.Metric):
  25. def __init__(self, num_class=21):
  26. super(PixelAccuracyClass, self).__init__()
  27. self.num_class = num_class
  28. def _generate_matrix(self, gt_image, pre_image):
  29. mask = (gt_image >= 0) & (gt_image < self.num_class)
  30. label = self.num_class * gt_image[mask].astype('int') + pre_image[mask]
  31. count = np.bincount(label, minlength=self.num_class**2)
  32. confusion_matrix = count.reshape(self.num_class, self.num_class)
  33. return confusion_matrix
  34. def update(self, *inputs):
  35. y_pred = inputs[0].asnumpy().argmax(axis=1)
  36. y = inputs[1].asnumpy().reshape(4, 512, 512)
  37. self.confusion_matrix += self._generate_matrix(y, y_pred)
  38. def clear(self):
  39. self.confusion_matrix = np.zeros((self.num_class,) * 2)
  40. def eval(self):
  41. mean_pixel_accuracy = np.diag(self.confusion_matrix) / self.confusion_matrix.sum(axis=1)
  42. mean_pixel_accuracy = np.nanmean(mean_pixel_accuracy)
  43. return mean_pixel_accuracy
  44. class MeanIntersectionOverUnion(train.Metric):
  45. def __init__(self, num_class=21):
  46. super(MeanIntersectionOverUnion, self).__init__()
  47. self.num_class = num_class
  48. def _generate_matrix(self, gt_image, pre_image):
  49. mask = (gt_image >= 0) & (gt_image < self.num_class)
  50. label = self.num_class * gt_image[mask].astype('int') + pre_image[mask]
  51. count = np.bincount(label, minlength=self.num_class**2)
  52. confusion_matrix = count.reshape(self.num_class, self.num_class)
  53. return confusion_matrix
  54. def update(self, *inputs):
  55. y_pred = inputs[0].asnumpy().argmax(axis=1)
  56. y = inputs[1].asnumpy().reshape(4, 512, 512)
  57. self.confusion_matrix += self._generate_matrix(y, y_pred)
  58. def clear(self):
  59. self.confusion_matrix = np.zeros((self.num_class,) * 2)
  60. def eval(self):
  61. mean_iou = np.diag(self.confusion_matrix) / (
  62. np.sum(self.confusion_matrix, axis=1) + np.sum(self.confusion_matrix, axis=0) -
  63. np.diag(self.confusion_matrix))
  64. mean_iou = np.nanmean(mean_iou)
  65. return mean_iou
  66. class FrequencyWeightedIntersectionOverUnion(train.Metric):
  67. def __init__(self, num_class=21):
  68. super(FrequencyWeightedIntersectionOverUnion, self).__init__()
  69. self.num_class = num_class
  70. def _generate_matrix(self, gt_image, pre_image):
  71. mask = (gt_image >= 0) & (gt_image < self.num_class)
  72. label = self.num_class * gt_image[mask].astype('int') + pre_image[mask]
  73. count = np.bincount(label, minlength=self.num_class**2)
  74. confusion_matrix = count.reshape(self.num_class, self.num_class)
  75. return confusion_matrix
  76. def update(self, *inputs):
  77. y_pred = inputs[0].asnumpy().argmax(axis=1)
  78. y = inputs[1].asnumpy().reshape(4, 512, 512)
  79. self.confusion_matrix += self._generate_matrix(y, y_pred)
  80. def clear(self):
  81. self.confusion_matrix = np.zeros((self.num_class,) * 2)
  82. def eval(self):
  83. freq = np.sum(self.confusion_matrix, axis=1) / np.sum(self.confusion_matrix)
  84. iu = np.diag(self.confusion_matrix) / (
  85. np.sum(self.confusion_matrix, axis=1) + np.sum(self.confusion_matrix, axis=0) -
  86. np.diag(self.confusion_matrix))
  87. frequency_weighted_iou = (freq[freq > 0] * iu[freq > 0]).sum()
  88. return frequency_weighted_iou

  1. import mindspore
  2. from mindspore import Tensor
  3. import mindspore.nn as nn
  4. from mindspore.train import ModelCheckpoint, CheckpointConfig, LossMonitor, TimeMonitor, Model
  5. device_target = "Ascend"
  6. mindspore.set_context(mode=mindspore.PYNATIVE_MODE, device_target=device_target)
  7. train_batch_size = 4
  8. num_classes = 21
  9. # 初始化模型结构
  10. net = FCN8s(n_class=21)
  11. # 导入vgg16预训练参数
  12. load_vgg16()
  13. # 计算学习率
  14. min_lr = 0.0005
  15. base_lr = 0.05
  16. train_epochs = 1
  17. iters_per_epoch = dataset.get_dataset_size()
  18. total_step = iters_per_epoch * train_epochs
  19. lr_scheduler = mindspore.nn.cosine_decay_lr(min_lr,
  20. base_lr,
  21. total_step,
  22. iters_per_epoch,
  23. decay_epoch=2)
  24. lr = Tensor(lr_scheduler[-1])
  25. # 定义损失函数
  26. loss = nn.CrossEntropyLoss(ignore_index=255)
  27. # 定义优化器
  28. optimizer = nn.Momentum(params=net.trainable_params(), learning_rate=lr, momentum=0.9, weight_decay=0.0001)
  29. # 定义loss_scale
  30. scale_factor = 4
  31. scale_window = 3000
  32. loss_scale_manager = ms.amp.DynamicLossScaleManager(scale_factor, scale_window)
  33. # 初始化模型
  34. if device_target == "Ascend":
  35. model = Model(net, loss_fn=loss, optimizer=optimizer, loss_scale_manager=loss_scale_manager, metrics={"pixel accuracy": PixelAccuracy(), "mean pixel accuracy": PixelAccuracyClass(), "mean IoU": MeanIntersectionOverUnion(), "frequency weighted IoU": FrequencyWeightedIntersectionOverUnion()})
  36. else:
  37. model = Model(net, loss_fn=loss, optimizer=optimizer, metrics={"pixel accuracy": PixelAccuracy(), "mean pixel accuracy": PixelAccuracyClass(), "mean IoU": MeanIntersectionOverUnion(), "frequency weighted IoU": FrequencyWeightedIntersectionOverUnion()})
  38. # 设置ckpt文件保存的参数
  39. time_callback = TimeMonitor(data_size=iters_per_epoch)
  40. loss_callback = LossMonitor()
  41. callbacks = [time_callback, loss_callback]
  42. save_steps = 330
  43. keep_checkpoint_max = 5
  44. config_ckpt = CheckpointConfig(save_checkpoint_steps=10,
  45. keep_checkpoint_max=keep_checkpoint_max)
  46. ckpt_callback = ModelCheckpoint(prefix="FCN8s",
  47. directory="./ckpt",
  48. config=config_ckpt)
  49. callbacks.append(ckpt_callback)
  50. model.train(train_epochs, dataset, callbacks=callbacks)

模型评估:

  1. IMAGE_MEAN = [103.53, 116.28, 123.675]
  2. IMAGE_STD = [57.375, 57.120, 58.395]
  3. DATA_FILE = "dataset/dataset_fcn8s/mindname.mindrecord"
  4. # 下载已训练好的权重文件
  5. url = "https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/FCN8s.ckpt"
  6. download(url, "FCN8s.ckpt", replace=True)
  7. net = FCN8s(n_class=num_classes)
  8. ckpt_file = "FCN8s.ckpt"
  9. param_dict = load_checkpoint(ckpt_file)
  10. load_param_into_net(net, param_dict)
  11. if device_target == "Ascend":
  12. model = Model(net, loss_fn=loss, optimizer=optimizer, loss_scale_manager=loss_scale_manager, metrics={"pixel accuracy": PixelAccuracy(), "mean pixel accuracy": PixelAccuracyClass(), "mean IoU": MeanIntersectionOverUnion(), "frequency weighted IoU": FrequencyWeightedIntersectionOverUnion()})
  13. else:
  14. model = Model(net, loss_fn=loss, optimizer=optimizer, metrics={"pixel accuracy": PixelAccuracy(), "mean pixel accuracy": PixelAccuracyClass(), "mean IoU": MeanIntersectionOverUnion(), "frequency weighted IoU": FrequencyWeightedIntersectionOverUnion()})
  15. # 实例化Dataset
  16. dataset = SegDataset(image_mean=IMAGE_MEAN,
  17. image_std=IMAGE_STD,
  18. data_file=DATA_FILE,
  19. batch_size=train_batch_size,
  20. crop_size=crop_size,
  21. max_scale=max_scale,
  22. min_scale=min_scale,
  23. ignore_label=ignore_label,
  24. num_classes=num_classes,
  25. num_readers=2,
  26. num_parallel_calls=4)
  27. dataset_eval = dataset.get_dataset()
  28. model.eval(dataset_eval)


使用训练的网络对模型推理结果进行展示。

  1. import cv2
  2. import matplotlib.pyplot as plt
  3. net = FCN8s(n_class=num_classes)
  4. # 设置超参
  5. ckpt_file = "FCN8s.ckpt"
  6. param_dict = load_checkpoint(ckpt_file)
  7. load_param_into_net(net, param_dict)
  8. eval_batch_size = 4
  9. img_lst = []
  10. mask_lst = []
  11. res_lst = []
  12. # 推理效果展示(上方为输入图片,下方为推理效果图片)
  13. plt.figure(figsize=(8, 5))
  14. show_data = next(dataset_eval.create_dict_iterator())
  15. show_images = show_data["data"].asnumpy()
  16. mask_images = show_data["label"].reshape([4, 512, 512])
  17. show_images = np.clip(show_images, 0, 1)
  18. for i in range(eval_batch_size):
  19. img_lst.append(show_images[i])
  20. mask_lst.append(mask_images[i])
  21. res = net(show_data["data"]).asnumpy().argmax(axis=1)
  22. for i in range(eval_batch_size):
  23. plt.subplot(2, 4, i + 1)
  24. plt.imshow(img_lst[i].transpose(1, 2, 0))
  25. plt.axis("off")
  26. plt.subplots_adjust(wspace=0.05, hspace=0.02)
  27. plt.subplot(2, 4, i + 5)
  28. plt.imshow(res[i])
  29. plt.axis("off")
  30. plt.subplots_adjust(wspace=0.05, hspace=0.02)
  31. plt.show()

这部分内容的学习总结如下:

  • 介绍了全卷积网络(FCN),它是一种用于图像语义分割的框架,是深度学习应用在图像语义分割的开山之作。
  • 解释了语义分割的概念,即对图像中每个像素点进行分类,并展示了一些语义分割的实例。
  • 描述了FCN的网络结构,包括卷积化、上采样和跳跃结构等技术。2
  • 提供了数据处理、网络构建、损失函数和评价指标、模型训练和推理等方面的代码实现。

原理上:

  • FCN通过将全连接层替换为全卷积层,使网络能够接受任意大小的输入图像,并输出与输入图像大小相同的分割结果。
  • 网络中的卷积层用于提取图像的特征,池化层用于降低特征图的分辨率,上采样层用于恢复特征图的分辨率,跳跃结构用于将深层的全局信息与浅层的局部信息相结合。
  • 在训练过程中,使用交叉熵损失函数来计算网络输出与真实标签之间的差异,并通过反向传播算法来更新网络的参数。
  • 在推理过程中,将输入图像输入到训练好的FCN网络中,得到输出的分割结果。

代码包括: 

1. 数据预处理:对输入图像进行标准化处理,使其具有相同的尺寸和数值范围。 - 数据加载:将PASCAL VOC2012数据集与SDB数据集进行混合,并使用MindSpore的Dataset类进行加载。 - 训练集可视化:运行代码观察载入的数据集图片。

2. 网络构建: 描述了FCN网络的流程,包括卷积、池化、反卷积等操作。 - 网络结构:使用MindSpore的nn模块构建FCN-8s网络,包括卷积层、池化层、反卷积层等。 - 导入预训练权重:导入VGG-16部分预训练权重,以提高模型的性能。

3. 损失函数和评价指标: - 损失函数:选择交叉熵损失函数来计算FCN网络输出与mask之间的交叉熵损失。 - 评价指标:自定义了PixelAccuracy、PixelAccuracyClass、MeanIntersectionOverUnion和FrequencyWeightedIntersectionOverUnion等评价指标,用于评估模型的性能。

4. 模型训练: - 导入预训练参数:实例化损失函数、优化器,使用Model接口编译网络,训练FCN-8s网络。 - 模型评估:使用训练好的模型对测试集进行评估,计算模型的准确率、召回率等指标。

5. 模型推理: - 模型推理:使用训练的网络对模型推理结果进行展示。 总结笔记: - FCN是一种用于图像分割的全卷积网络,通过将全连接层替换为全卷积层,实现了对任意大小输入图像的像素级预测。 - FCN的主要贡献包括提出使用全卷积层、可以接受任意大小的输入图像、更加高效等。 - FCN的网络结构包括卷积层、池化层、反卷积层等,通过跳跃结构将深层的全局信息与浅层的局部信息相结合。 - FCN的训练过程包括数据预处理、网络构建、损失函数和评价指标的选择、模型训练和模型评估等步骤。 - FCN的推理结果可以通过可视化展示,展示了模型对输入图像的分割效果。

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

闽ICP备14008679号