Multi-Scale Context Aggregation by Dilated Convolution训练记录

读完文章后,觉得应该网络框架类似FCN,却可以达到更好的效果。该网络的准确度和花费时间都应该好于FCN-8S,打算funetune一个自己的模型。

首先从测试开始,对于predict.py,我认真研究了他的代码,我来具体说一下他的代码结构:首先读入图片后,得到deploy.prototxt中输入图片的大小,以“dilation10_cityscapes_deploy.prototxt”为例,他的网络结构输入大小是1398*1398,prop输出的大小是1024*1024,差了两倍的margin,这些margin会通过卷积操作卷积没了。cityscape图片的大小是2048*1024的,首先对图片进行打pad,就是边界扩张操作(copyMakeBorder),两边都加上margin大小的边界,得到2420*1396大小的,然后计算滑动窗所需要滑动的次数,滑动窗的大小是1396*1396的。每次截取1396*1396大小的图片,如果发现图片某一轴上小于输入大小1396,那么加pad到1396。然后把这个1396*1396作为输入到网络中,输出1024*1024。最后输出的两个概率结果合并得到最终的结果。

如果是其他的prototxt,比如camvid,那么他是没有加upsampling的,所以输出是(输入大小-2×margin)/8,因此zoom=8,需要通过util.py对图像进行双线性差值来放大8倍。

在训练过程中,我一直有两个疑问,一是在不加入upsampling的情况下,输入的label大小怎么和输出的label大小对应上的,因为输入是输出的8倍,我看了源码image_label_data_layer.cpp中应该有将输入的label放缩到原来的1/8,这样可以加快方向传播的速度。而是这个crop_size的大小是怎么定的,在文章给的caffe源码中,padimage函数中" if (image.rows >= min_size && image.cols >= min_size) {return image; }"其中crop_size主要是对原图进行打pad处理,所以一般crop_size要比输入图片的长或宽大,这样才能打pad。还有一点就是(crop_size-2*magin)一定要倍8整除。比如cityscape的1396-2*186=1024,1024是可以被8整除的,camvid中的1100和900同样如此。
还有文章给的模型一共有三个“front-end,context,joint”,其中主要是front-end模型,context主要是加了上下文的信息,joint是将front-end和context结合起来。
我自己使用的cityscape进行训练的,不过我没有用原图,我缩小到原来的1/2,所以我重新定义了crop_size,去掉了upsamping(原作者提到,之所以在cityscape上使用usampling主要是因为cityscape的分辨率太高原话为“I added an upconv in training cityscapes models because the high resolution of cityscapes data”)。
至于源码中有没有对输入的label进行放缩将后续更新。


更新一下,今天找到可能是源码中的对输入label进行缩放的代码:

SampleScale(&cv_img, &cv_label);


template<typename Dtype>
void ImageLabelDataLayer::SampleScale(cv::Mat *image, cv::Mat *label) {
ImageLabelDataParameter data_param =
this->layer_param_.image_label_data_param();
if (!data_param.rand_scale())return;
double scale = std::uniform_real_distribution<double>(
data_param.min_scale(), data_param.max_scale())(*rng_);
cv::Sizezero_size(0,0);
cv::resize(*label, *label,cv::Size(0,0),
scale, scale, cv::INTER_NEAREST);

if (scale >1) {
cv::resize(*image, *image, zero_size, scale, scale, cv::INTER_CUBIC);
}else {
cv::resize(*image, *image, zero_size, scale, scale, cv::INTER_AREA);
}
}

其中

cv::resize(*label, *label,cv::Size(0,0),
scale, scale, cv::INTER_NEAREST);应该就是对图片进行了放缩操作。

但是还是没有弄懂GetLabelSlice这个函数是什么意义,不知道有没有大神可以解释一下。


今天终于证实了我的猜测,我通过计算模型的准确率得到的label值是通过缩小了8倍大小的图片,也就是说,在data层作者加入了放缩程序,大小就是stride.

你可能感兴趣的:(语义分割)