本博文介绍如何手把手制作自己的数据集,并使用SegNet网络进行语义分割,如何训练,如何测试自己的分割模型。
----------------------------------------------------------------------------------------------------------------------------------------------------------
感谢:
1.源码参考cudnn5版本的caffe-segnet,https://github.com/TimoSaemann/caffe-segnet-cudnn5
2.作者的官方指导文档:http://mi.eng.cam.ac.uk/projects/segnet/tutorial.html
3.一份使用指导:https://github.com/TqDavid/SegNet-Tutorial/tree/master/CamVid
4.如果想测试SegNet的效果,这里有官方的在线测试demo: http://mi.eng.cam.ac.uk/projects/segnet/#demo
5.一份segnet的预训练model
https://github.com/alexgkendall/SegNet-Tutorial/blob/master/Example_Models/segnet_model_zoo.md,以及相对应的
segnet_basic_inference.prototxt |
segnet_basic_solver.prototxt |
segnet_basic_train.prototxt |
6.参考了该博主的文章https://blog.csdn.net/caicai2526/article/details/77170223
7.以及该博主的文章https://blog.csdn.net/hjxu2016/article/details/77994925
8.对于已有mask和image,需要resize,可参考https://blog.csdn.net/u013249853/article/details/79827469
--------------------------------------------------------------------------------------------------------------------------------------------------------------
言归正传,开始正题。
下载上述caffe-segnet-cudnn5版本的代码,其路径后文称之为caffe_root,以下的操作都在该caffe_root目录下进行。
整体目录包含如下文件(夹):
一、制作自己数据集
SegNet网络需要两个输入,一个是原始图像,三通道的;一个是mask label,也就是待分割目标的标签,mask要求是单通道8位灰度图,格式是uint8, 像素0表示背景,像素1表示目标的位置。 下面分别准备这两样东西。
1. 原始图像就是你自己的照片了,注意一下:如果你不更改SegNet中参数,可以先保持与原作者的图像尺寸一致,后面可以根据自己的情况在更改,一般上采样2x,这里采用与原作者相同的图像尺寸,(360, 480)彩色图片,如果不是这样,建议resize一下,博主自己的图片是灰度的,resize前有一个转成rgb的过程,python代码函数;
# testdir为自己数据集路径,楼主的图是灰度图,所以有一个转换成rgb的过程,然后保存。
def resize_image_batch():
file_list = os.listdir(testdir)
for item in file_list:
#print(traindir + item)
imname = testdir + item
im = cv2.imread(imname, 0)
im = cv2.resize(im, (480, 360))
im_RGB = cv2.cvtColor(im, cv2.COLOR_GRAY2RGB)
print(im.shape)
print(im_RGB.shape)
#print(im)
print("============================")
#print(im_RGB[:,:,0])
#print(im_RGB[:,:,1])
#print(im_RGB[:,:,2])
print(im.dtype)
print(im_RGB.dtype)
cv2.imwrite('zht_test_use/'+ item, im_RGB)
#print("success!")
2.准备mask。
首先,博主的mask来源是用labelme 得到的。labelme的使用方法,这里不再赘述。简言之,对于每一张图,我们可以得到其
json标注文件, 再通过,labelme_json_to_dataset命令,可以得到最终我们需要的label mask,我们所需的是文件夹下的label.png。
labelme_json_to_dataset批量生成数据集的shell脚本如下;
for item in $(find ./huaweishouji_20170720_train_360x480_try -iname "*.json");
do
echo $item;
labelme_json_to_dataset $item;
done
接下来将lable.png转换成uint8,背景像素是0,目标像素是1的mask..convert_to_mask 代码如下:
def convert_to_mask():
file_list = os.listdir(traindir)
for item in file_list:
item_list = os.listdir(traindir + item)
#print("len(item) : ", len(item_list))
for atom in item_list:
if atom == "label.png":
np.set_printoptions(threshold='nan')
imname = traindir + item + "/" + atom
#print(imname)
im = io.imread(imname, 1)
print(imname)
#print(im[:, :])
print(im.shape)
print(im.dtype)
print("-------------after-----------------")
img = (im * 255).astype(np.uint8)
_, im_th= cv2.threshold(img, 0.0000000000000001, 1, cv2.THRESH_BINARY)
#print(img.shape)
print(im_th.shape)
print(im_th.dtype)
#print(im_th[ :, :])
print(item[:-5] + ".png")
cv2.imwrite(train_write_dir + item[:-5] + '.png', im_th )
#print(im[:,:,0])
#print(im[:,:,1])
#print(im[:,:,2])
#im_RGB = cv2.cvtColor(im, cv2.COLOR_GRAY2RGB)
#print(traindir + item)
#imname = traindir + item
#im = cv2.imread(imname, 0)
#im = cv2.resize(im, (480, 360))
#im_RGB = cv2.cvtColor(im, cv2.COLOR_GRAY2RGB)
#print(im.shape)
#print(im_RGB.shape)
#print(im)
#print("============================")
#print(im_RGB[:,:,0])
#print(im_RGB[:,:,1])
#print(im_RGB[:,:,2])
#print(im.dtype)
#print(im_RGB.dtype)
#cv2.imwrite('huaweishouji_20170720_test_360x480/'+ item, im_RGB)
def check_ma