Fully Convolutional Networks for Semantic Segmentation---FCN论文复现(基于Pytorch)

在论文解读时并没有对FCN论文进行详细的解读,只是在介绍语义分割综述的时候介绍到这篇开天辟地的神作,试着去复现论文的精髓。从GitHub上down了几个源码下来,可能是能力有限不能完全的运行,主要面对的数据集不同,数据读取方式的不同导致了很多bug,最后经过调试这个源码,程序可以正常运行,能运行的原因主要是作者把VOC2012数据中的十几张图一起放在源码中,这样就避免了读取数据路径以及读取方式错误的问题,只需更改源码一些提示报错就可以正常运行。但最后的mIOU效果很差,因为数据集太小了,所以尝试使用全部的VOC2012数据集进行训练。

首先作者的将每张图片的路径放在txt文件中,如下所示

                        Fully Convolutional Networks for Semantic Segmentation---FCN论文复现(基于Pytorch)_第1张图片

为了保持与原数据读取方式一致,我写了一个函数将VOC2012中用于分割的数据图片全部读取出来,代码如下:

import os 
import time
import math
import torch
root = './data/VOCdevkit/VOC2012'  #VOC2012文件位置
txt_fname = 'data/VOCdevkit/VOC2012/ImageSets/Segmentation/trainval.txt' 
#用于分割的验证集的路径
with open(txt_fname, 'r') as f:
    images = f.read().split()
    imagepath_train = []
    for i in images:   
        labelpath_val = os.path.join(root, 'SegmentationClass', i+'.png')
        file=open('cratedata/abcd2.txt','a')  #保存TXT文件中
        file.write(str(labelpath_val))
        file.write('\n')
        file.close()

利用上面这段代码可以将所有的训练集,验证集,测试集的图片的路径放在各自的txt文件中,这样就可以直接进行训练了,但开始报错:cuda runtime error() : device-side assert triggered at ....

Fully Convolutional Networks for Semantic Segmentation---FCN论文复现(基于Pytorch)_第2张图片

出现这种错误的原因有多种可能,但基本上都是与label相关的,一般情况下有几种可能:

  • CrossEntropyLoss2d损失函数,类别的定义需要从0开始,如VOC2012中,0-20类,一共21类,需要到label.py中看label是否从0开始
  • label类别号溢出也会报错
  • label图片为单通道,但数据集中的为RGB图片,导致会在求loss的时候报错,需要将label中所有的图片转化为单通道图片

image为[n*m*3],jpg格式,label为[n*m*1],png格式。而VOC2012 SegmentationClass中的label数据格式为[n*m*3],需将label数据从RGB的3通道转为’L'的单通道即可,代码如下:

import numpy as np
from PIL import Image
from keras.preprocessing.image import load_img, img_to_array
import os
 
classes = ['background', 'aeroplane', 'bicycle', 'bird', 'boat',
           'bottle', 'bus', 'car', 'cat', 'chair', 'cow', 'dining table',
           'dog', 'horse', 'motorbike', 'person', 'potted plant',
           'sheep', 'sofa', 'train', 'tv/monitor']
 
colormap = [[0, 0, 0], [128, 0, 0], [0, 128, 0], [128, 128, 0], [0, 0, 128],
            [128, 0, 128], [0, 128, 128], [128, 128, 128], [64, 0, 0], [192, 0, 0],
            [64, 128, 0], [192, 128, 0], [64, 0, 128], [192, 0, 128],
            [64, 128, 128], [192, 128, 128], [0, 64, 0], [128, 64, 0],
            [0, 192, 0], [128, 192, 0], [0, 64, 128]]
 
# 利用下面的代码,将标注的图片转换为单通道的label图像
cm2lbl = np.zeros(256**3)
for i, cm in enumerate(colormap):
    cm2lbl[(cm[0]*256+cm[1])*256+cm[2]] = i
 
 
def image2label(im):
    # 输入为标记图像的矩阵,输出为单通道映射的label图像
    data = im.astype('int32')
    idx = (data[:, :, 0]*256+data[:, :, 1])*256+data[:, :, 2]
    return np.array(cm2lbl[idx])
 
 
def change_label(label_url, label_name):
 
    label_img = load_img(label_url)
    label_img = img_to_array(label_img)
    label_img = image2label(label_img)  # 将图片映射为单通道数据
    print(np.max(label_img))
 
    label_single = Image.fromarray(label_img)
    label_single = label_single.convert('L')
 
    #save_path = './datasets/VOC2012/Label'
    save_path = os.path.join(label_name)  # 确定保存路径及名称
    label_single.save(save_path)
 
 
val_file_path = './data/val/label.txt'  # 文件名存放路径
label_file_path = './data/VOCdevkit/VOC2012/SegmentationClass'  # 原label存放路径
 
with open(val_file_path, 'r') as f:
    file_names = f.readlines()
    count = 0
    for name in file_names:
        count += 1
        name = name.strip('\n')  # 去掉换行符
        label_name = name   # label文件名
        label_url = os.path.join(label_name)
        print('这是第 %s 张' % count)
        print(label_url)
        change_label(label_url, label_name)

注意文件的读取路径是跟之前读取数据集的路径保持一致的,直接利用前面TXT文件中路径进行检索的。

Fully Convolutional Networks for Semantic Segmentation---FCN论文复现(基于Pytorch)_第3张图片

后期将会尝试直接对RGB图片进行训练,未完待续。。。

 

 

 

你可能感兴趣的:(论文复现)