本人刚接触这方面不久,在网上搜索了很多文章,发现很多文章都存在一些弊端,自己做了一些总结,方法比较基础,但亲测有效。
首先,我们得有一些原始图片,然后通过labelme标注后得到json文件(labelme使用大家可以去搜一下),接下来我们需要做的是将json文件转换为可用于训练的标签集。
网上很多说python中自带了一个脚本json_to_dataset.py可以转换(路径在python安装路径下,比如我的是在D:\python3.6.7\Lib\site-packages\labelme\cli中),调用方法是在cmd下输入: labelme_json_to_dataset <文件路径>.json,就可以得到标签图片(保存路径就是json文件目录下),但有一个问题就是,一次性只能转换一张标签,这多麻烦啊。于是,很多人写了脚本,可以批量化转换,但就我目前看到批量转换脚本,大多存在着一个致命的问题,就是对于不同图片,他的类别标注是对应不上的(这些脚本只是负责把图送到json_to_dataset.py,并没有对标签进行其他处理),看下图:
从上面两张图片可以看出,两种完全不是同一类别的东西都被赋予相同的颜色(也即相同标签),这肯定不是我们想要的。
然后就想尝试了一个比较官方的方法:
先将json文件转换为voc格式的文件
(为什么要这样做呢,因为voc格式算是比较官方的格式,针对其的转换程序也是正规的,解决了批量转换和不同类别时被赋予不同的像素的问题),然后就在github上找打了一个voc的转换脚本,链接在这里:
https://github.com/wkentaro/labelme/tree/master/examples/semantic_segmentation
,里面有教程教你怎么调用,这里就直接写下吧,cmd下输入:
python ./labelme2voc.py(尽量写绝对路径) 图片和json文件存放的路径(放在一起) 保存路径 --labels labels.txt路径(中间都是空格隔开)
这里需要注意的是,你需要将你自己的标签类别制作成一个txt文本(也就是上面调用命令中的labels.txt),你可以仿照上面那个链接中的labels.txt做,这个程序会根据你的类别去转换,然后你就会得到四个文件夹,其中有用的只有两个JPEGImages(原图像),SegmentationClassPNG(voc格式的标签图像),转换后的标签如下图所示:
可以看到,两种不同的东西被赋予了不同的标签,但是这种图片是索引图(索引图是为了增强灰度图的差异性,其实他也是单通道的,只不过每一个灰度都对应着一种颜色),如果你的模型是要求索引图作为标签,那么到这里就已经完成了;如果你的模型是要求灰度图作为标签,那么还得进行第二步转换(错把索引图当做灰度图作为标签,可能出现label out of boundary的错误提示),即
将voc格式的索引图转换为可用于训练的灰度图
(看上去是全黑的)。这里有两种方法:
1.先读取索引图中各种类别的像素值,然后一一改过来,比如上面球像素值是125,然后遍历就把所有图片中的125的像素值都改为1(表示第一个类别),而红色的是225,就把所有图片中的225都改为2,然后再保存为灰度图格式就可以了。这种方法对于类别较多的就比较麻烦,而且遍历每一个像素值耗时很大。
2.第二种是我在网上找到的转换脚本,很快很好用
""
"Removes the color map from segmentation annotations
.
Removes the color map from the ground truth segmentation annotations
and
save
the results to output_dir
.
#源程序链接:https
:
/
/
github
.
com
/
tensorflow
/
models
/
tree
/
master
/
research
/
deeplab
/
datasets
#该程序用于将voc格式的索引图片转换为可用于语义分割的灰度图片,因为TensorFlow版本的缘故,在原程序上做了少许改动
#tf.__version__==1.12
import glob
import os
.
path
import numpy as np
from PIL import Image
import tensorflow as tf
#FLAGS = tf.compat.v1.flags.FLAGS
FLAGS
=
tf
.
flags
.
FLAGS
tf
.
flags
.
DEFINE_string
(
'original_gt_folder'
,
#读取voc格式的png图片路径
'F:\Dataset_segmentaion\data_dataset_voc\SegmentationClassPNG'
,
#
default
'Original ground truth annotations.'
)
#help
tf
.
flags
.
DEFINE_string
(
'segmentation_format'
,
'png'
,
'Segmentation format.'
)
tf
.
flags
.
DEFINE_string
(
'output_dir'
,
#保存路径
'F:\Dataset_segmentaion\data_dataset_voc\labels'
,
'folder to save modified ground truth annotations.'
)
def
_remove_colormap
(
filename
)
:
""
"Removes the color map from the annotation
.
Args
:
filename
:
Ground truth annotation filename
.
Returns
:
Annotation without color map
.
return
np
.
array
(
Image
.
open
(
filename
)
)
def
_save_annotation
(
annotation
,
filename
)
:
""
"Saves the annotation as png file
.
Args
:
annotation
:
Segmentation annotation
.
filename
:
Output filename
.
pil_image
=
Image
.
fromarray
(
annotation
.
astype
(
dtype
=
np
.
uint8
)
)
with tf
.
io
.
gfile
.
GFile
(
filename
,
mode
=
'w'
)
as f
:
#with open(filename, mode='w') as f:
print
(
f
)
pil_image
.
save
(
f
,
'PNG'
)
pil_image
.
save
(
filename
)
def
main
(
unused_argv
)
:
# Create the output directory if not exists.
if
not
os
.
path
.
exists
(
FLAGS
.
output_dir
)
:
os
.
makedirs
(
FLAGS
.
output_dir
)
#
if
not tf.io.gfile.isdir(FLAGS.output_dir):
#tf.io.gfile.makedirs(FLAGS.output_dir)
annotations
=
glob
.
glob
(
os
.
path
.
join
(
FLAGS
.
original_gt_folder
,
'*.'
+
FLAGS
.
segmentation_format
)
)
for
annotation in annotations
:
raw_annotation
=
_remove_colormap
(
annotation
)
filename
=
os
.
path
.
basename
(
annotation
)
[
:
-
4
]
_save_annotation
(
raw_annotation
,
os
.
path
.
join
(
FLAGS
.
output_dir
,
filename
+
'.'
+
FLAGS
.
segmentation_format
)
)
if
__name__
==
'__main__'
:
#tf.compat.v1.app.run()
tf
.
app
.
run
(
)
只需要将上面存放voc格式的png图像路径以及保存路径改成你自己的路径即可,转换后的图片是这样的:
你没有看错,就是全黑的,但只是看上去,除了背景像素值为零,其他的像素值不是零(可以调用np.unique(image)看看),比如你有21个类别,那么,对应的像素就是0-21,但看上去就是一团黑,不好分辨,因此才有了上面的索引图。到这里,标签图片就只做完成了,希望对大家有帮助。
本人刚接触这方面不久,课题是关于语义分割的内容,在网上搜索了很多文章,发现很多文章都存在一些弊端,自己做了一些总结,方法比较基础,但亲测有效。首先,我们得有一些原始图片,然后通过labelme标注后得到json文件(labelme使用大家可以去搜一下),接下来我们需要做的是将json文件转换为可用于训练的标签集。网上很多说python中自带了一个脚本json_to_dataset.py可以转换...
模型在FloodNet数据集上进行了训练,mIOU在0.83左右,可训练自己的数据集
建议在训练网络的时候将输入的训练集其切分为384x384的小图片后,再来进行训练
模型采用标准的UNet,可以采用如下方式训练你自己的模型
数据集地址可以在train.py中修改为你自己的文件夹
python
train.py -- --epochs 20 --batch-size 16 --learning-rate 2e-4 --scale 1 --validation 0.1 --classes 10 --amp
其中--amp为半精度训练
--scale是训练的时候对图片进行缩放,已经裁剪为384x384后就不需要再裁剪了
语义分割
动手实践 - labelme标注和
标签
生成
最近接触到
语义分割
任务,借助deeplabv3+和BiSeNet v2对分割任务有了初步的了解,为自己记录下整个流程
1、
语义分割
数据标注
标注工具:由于语义/实例分割任务多是多边形(polygons)轮廓标注,在此选用labelme标注工具。
labelme安装,有需要可以创建虚拟环境,有
python
和pyqt5即可:
创建labelme虚拟环境
conda create -n labelme
python
=3.8
激活虚拟环境
conda activa
如果没有安装anaconda3,可以跟着 anaconda安装配置教程 安装一下,
深度学习
必备工具。
进入anaconda中的
python
环境,然后输入pip install labelme,回车进行安装。
1、在
python
环境中输入labelme,回车就会打开下图所示的标注窗口。
2、点击左侧create polygons,开始框区域,鼠标点击就会放置一个点,然后拉线再放下一个点,这样环绕框....