论文:Learning deep structured active contours end-to-end,CVPR 2018
代码:https://github.com/dmarcosg/DSAC
实验环境
Python 3.7
Tensorflow-gpu 1.14
创建虚拟环境:
conda create -n tensorflow37 python=3.7
依赖安装:
conda install tensorflow-gpu
conda install Pillow
conda install matplotlib
conda install scikit-image
实验数据
数据集1: Bing Huts(图像和标签均为 png 格式)
原图: 共 606 张(编号 0 ~ 605)
Single_mask: 共 606 张(编号 0 ~ 605),只包括中央建筑物的 mask,不考虑其周围的建筑物
All_mask: 共 606 张(编号 0 ~ 605),还包括了周围建筑物的 mask,从编号 4 的图片上可以看出来两种 mask 的不同
附加文件:building_coords.csv
记录了建筑物坐标,这个文件就和上面那一堆图片放在一个文件夹 single_buildings
下,搜索一下就出来了。
数据集2: Vaihingen buildings
原图: 共 168 张(编号 001 ~ 168)
ground truth: 共 168 张(编号 001 ~ 168)
Single_maske: 共 168 张(编号 001 ~ 168)
All_mask: 共 168 张(编号 001 ~ 168)
附加文件:
- dpsimplify.m
- extract_polygons.m
- polygons.csv
代码说明
extract_polygons.m
用于提取每张训练图像的二值mask(如果有 mask 这一块可以省略)并提取一个 csv 文件,里面存了所有训练图像简化后的顶点信息(这一点很重要)
ground truth(gt) 和 image(im) 图像大小均为 512 × 512 × 3 512 \times 512 \times 3 512×512×3
gt(:,:,1) 和 gt 对比图:
gt(:,:,2) 和 gt 对比图:
gt(:,:,3) 和 gt 对比图:
false()
函数:逻辑 0(假)
imreconstruct()
函数:https://ww2.mathworks.cn/help/images/ref/imreconstruct.html
bwboundaries()
函数:标记目标物体边缘
涉及到算法 dpsimplify.m
,简单说其实就是从一条曲线中挑选出一些点,用这些点也能大致拟合出原曲线的样子,这就是 dpsimplify 干的事情。
% Simplify line 简化曲线的例子
tol = 1;
% 创建绘图数据
x = 1:0.1:8*pi;
y = sin(x) + randn(size(x))*0.1;
% 转置x和y矩阵并合并,p为所有点的坐标矩阵
p = [x' y'];
% 简化曲线(减少坐标点)
ps = dpsimplify(p,tol);
% 可视化原曲线(黑色)和简化后的曲线(红色)
plot(p(:,1),p(:,2),'k')
hold on
plot(ps(:,1),ps(:,2),'r','LineWidth',2);
legend('original polyline','simplified')
在房屋标签的 boundary 简化中,一个小测试:
B = bwboundaries(the_building); % coords of boundary
[ps,ix] = dpsimplify(B{1},3); % simpify boundary line(extract 9 points)
plot(B{1}(:,1),B{1}(:,2),'k','LineWidth',4);
hold on;
plot(ps(:,1),ps(:,2),'g','LineWidth',1);
legend('original', 'simplified');
注意:B 是 cell 类型,其将矩阵存在了 {1,1} 这个 cell 上,所以读取矩阵时要索引到 B{1},这里 B 中存储的坐标原本有 1092
bwboundaries() 函数得到的轮廓和原二值图不太一样,此时图像逆时针旋转了90度(为什么?)
原因:绘图方式不一样,MATLAB 提取的坐标点其原点在左上角,而绘图时坐标原点在左下角。
mod() 函数:取余运算
imagesc() 函数:显示使用经过标度映射的颜色的图像
xticks() 函数:设置或查询 x 轴刻度值
numel() 函数:数组元素的数目
问题1:同样画轮廓线,为什么加上原图的就是正过来的?发现 y 轴是由大变小的
subplot(1,2,1);
imagesc(im); % draw org image
hold on
plot(ps(:,2),ps(:,1),'-o','LineWidth',3,'MarkerEdgeColor',[1,1,0]);
subplot(1,2,2);
plot(ps(:,2),ps(:,1),'-o','LineWidth',3,'MarkerEdgeColor',[1,1,0]);
以前 9 张图片为例,生成的 data 是这样的:
每一行代表一张图片中的坐标点集合,第一列表示该图片有几个顶点坐标,从第二列开始,每两个值为一个坐标对儿,由于每幅图的坐标点个数不同,所以矩阵的列数以顶点最多的一行为最大列数,其余行没有坐标值的补 0。
最后生成 mask 的图像,并保存
训练
训练报错:
Traceback (most recent call last):
File "/data/zyy/code/DSAC-master/tiff2png.py", line 3, in <module>
from osgeo import gdal
ModuleNotFoundError: No module named 'osgeo'
解决:将 tif 转换为 png
安装
conda install GDAL==2.3.0
测试
修改代码:
do_plot = True
do_train = False
报错:
AttributeError: module 'scipy.misc' has no attribute 'imresize'
解决: 安装的 scipy 版本过高,是 1.3.0 的,降级为 1.2.1
直接安装,就可以覆盖高版本的
conda install scipy=1.2.1