鉴于论文原作者开源的SegNet网络是基于caffe框架的,而我们所用的框架是tensorflow,所以在github上找了一些tensorflow代码。本次全天空云图分割实验就是用的https://github.com/aizawan/segnet,整个代码很清晰,稍作修改就可以在CamVid数据集上进行Segnet网络训练。
但是仅仅在CamVid数据集上跑通SegNet网络是实验开始的第一步,我们的目标是想利用segnet网络来分割我们收集到的全天空云图,因此该怎样制作数据集呢?
从全天空云图仪网址上,按照顺序收集原图像以及分割后的标注图,分别放在两个文件夹里,命名为原图及标注。
(1)观察收集到的原图以及标注图,都是jpg格式的RGB图,size为2000×1944。由于图片尺寸过大,难以训练,因此首先对两个文件下的图片resize成480×360,并保存为png格式。
(2)再对resize后的标注图进行批量灰度化,保存在“灰度标注图”的文件夹下。批量灰度化后时,一定将标注图的灰度固定为三个值0,1,2,代表三个类别,分别为云,天空,太阳。不能有多余的其他灰度值,否则会出错。
(3)制作训练文本,将原图与灰度化后的标注图对应联系起来
以下是具体代码:
利用下述代码,对原图文件夹的图像批量resize,并保存在原图修改大小这个文件夹下,作为segnet神经网络的输入,也就是训练集的原图。
#提取目录下所有图片,更改尺寸后保存到另一目录
from PIL import Image
import os.path
import glob
def convertjpg(jpgfile, outdir, width=480, height=480):
img = Image.open(jpgfile)
new_img = img.resize((width, height), Image.NEAREST)
#采用最近邻算法进行缩放,主要是保证灰度化后不同类之间的灰度值差异大
outdir1 = os.path.join(outdir, os.path.basename(jpgfile))
outdir2 = outdir1.split('.')
new_img.save(outdir2[0], 'png')#将图像保存为.png格式
for jpgfile in glob.glob("原图/*.jpg"):
convertjpg(jpgfile, "原图修改大小")
首先对收集到的标注文件夹中的图像做同样的resize操作,并保存在标注修改大小文件夹下,再对这个文件夹下的图像批量灰度化,并保存在灰度图文件夹下。
from PIL import Image
import numpy as np
import os.path
import glob
def convert_gray(pngfile):
img=Image.open(pngfile).convert('L')
img.save(os.path.join('灰度图', os.path.basename(pngfile)),'png')
for pngfile in glob.glob('标注修改大小/*'):
convert_gray(pngfile)
灰度化之后,可通过im.show()查看单张图像灰度值,突然发现,同一类的灰度值是变化的,显然并不符合标注的要求(标注要求同一类的物体其灰度值是不变的),因此需要对此进行固定灰度。
经过用ps查看灰度值,发现云、天空、太阳这三类的灰度值虽然是变化的,但存在明显的分段,因此在这里将灰度值在20-60之间的像素其灰度值重设为1(代表云类),60-80之间的像素灰度值重设为2(代表天空类),其余设为0(代表太阳)。
经上述处理的灰度图保存为灰度标注图文件下,即可获得训练集的标注图。
from PIL import Image
from pylab import *
import numpy
import glob
import os.path
def convert(pngfile):
im = array(Image.open(pngfile))
w = im.shape[0]
h = im.shape[1]
for x in range(w):
for y in range(h):
if im[x][y]>=20 and im[x][y]<60:#云
im[x][y]=1
elif im[x][y]>=60 and im[x][y]<100:#天空
im[x][y]=2
else:
im[x][y] = 0
img = Image.fromarray(im.astype('uint8'))
img.save(os.path.join('灰度标注图', os.path.basename(pngfile)), 'png')
for pngfile in glob.glob('灰度图/*'):
convert(pngfile)
取原图修改大小文件中的图片为segnet网络的输入,取灰度标注图中的图片为Segnet网络的标注。
对于原图与标注而言,是放入两个文件夹下的,总得有一个联系将输入图像与对应的标注串起来。下图就是训练的文本,ASC100-1006_001是图片的名称,前面的是输入图像中的路径与图像名,后者是标注的路径与图像名。segnet通过读取这个txt文本,即可获取路径,提取图片进行训练。
注意到:
1、上述文件都是相对路径,可以根据自己的情况,修改为绝对路径,也是能行的;
2、保存为png格式时有点诡异,我并没有在图像名后面加上.png后缀,有些Windows可能无法显示,只要加上.png后缀就可以显示图像,反正在ubuntu下是可以看见的,而且在读取图像时,按照名称读取,如果名称没有包含jpg、png等后缀,则不需要加上;
3、之前用python一直不报错但是没有出处理结果,对于这种批量文件处理,可以先对单一图像进行处理,有结果了,再写个循环,对文件批量处理。