基本原理及实例
计算机视觉技术:图像语义分割,根据「图像内容」对「指定区域」进行标记」的「计算机视觉」任务。简言之就是「这张图片里有什么,其在图片中的位置是什么?」
下面是语义分割后的图片(摇滚专辑封面)
英国披头士乐队的著名专辑封面 Abbey Road
!
Pink Floyd 乐队的名作《 Wish You Were Here》
英式摇滚绿洲乐队的《Morning Glory》
原理:
- 预测每一张图片中每一个像素的所属分类的概率。
可视化:
- 相同的类别,同一种颜色显示。
语义分割数据集 CamVid 的一个样本图片示例
数据集 Camvid
指标结果
fastiai创始人 Jeremy 的示例:Accuracy:93.3% (State-of-the-Art )
笔者复现:Accuracy:90.9% (更换预训练模型为 ResNets18,示例是 ResNets34)
笔记
- 算力需求->大
You may have to restart your kernel and come back to this stage if you run out of memory, and may also need to decrease bs.
笔记提示:
如果你的GPU内存耗尽,请重启 kernel,或者减小批量(batch_size)的大小。由此可见,相比于更简单的图片分类任务,语义分割非常消耗算力。(多买英伟达的股票吧,同志们。)
具体代码也有体现:
size = src_size
free = gpu_mem_get_free_no_cache()
# the max size of bs depends on the available GPU RAM
if free > 8200: bs=3
else: bs=1
print(f"using bs={bs}, have {free}MB of GPU RAM free")
如果RAM 内存容量大于 8200,batch_size设置为 3。
如果 RAM 内容容量小于或等于 8200,batch_size设置为 1。
- 数据存储结构
camvid = untar_data(URLs.CAMVID_TINY)
path_lbl = camvid/'labels'
path_img = camvid/'images'
[PosixPath('/home/ubuntu/course-v3/nbs/dl1/data/camvid/images'),
PosixPath('/home/ubuntu/course-v3/nbs/dl1/data/camvid/codes.txt'),
PosixPath('/home/ubuntu/course-v3/nbs/dl1/data/camvid/valid.txt'),
PosixPath('/home/ubuntu/course-v3/nbs/dl1/data/camvid/labels')]
图片数据集分为「图片文件夹」&「标签文件夹」
codes = np.loadtxt(camvid/'codes.txt', dtype=str); codes
array(['Animal', 'Archway', 'Bicyclist', 'Bridge', 'Building', 'Car', 'CartLuggagePram', 'Child', 'Column_Pole',
'Fence', 'LaneMkgsDriv', 'LaneMkgsNonDriv', 'Misc_Text', 'MotorcycleScooter', 'OtherMoving', 'ParkingBlock',
'Pedestrian', 'Road', 'RoadShoulder', 'Sidewalk', 'SignSymbol', 'Sky', 'SUVPickupTruck', 'TrafficCone',
'TrafficLight', 'Train', 'Tree', 'Truck_Bus', 'Tunnel', 'VegetationMisc', 'Void', 'Wall'], dtype='
一个文本文件,存储了所有的预测分类(classes),这些分类对应的是不同的分类的遮罩,比如动物、桥梁、汽车、道路、行人、树木等等。
get_y_fn = lambda x: path_lbl/f'{x.stem}_P{x.suffix}'
这个 python 匿名函数,主要是作用是不同的像素对应的分类,也就是标签对应像素点。
Mask遮罩
src_size = np.array(mask.shape[1:])
src_size,mask.data
Out[ ]:
(array([720, 960]), tensor([[[ 4, 4, 4, ..., 26, 26, 26],
[ 4, 4, 4, ..., 26, 26, 26],
[ 4, 4, 4, ..., 26, 26, 26],
...,
[19, 19, 19, ..., 17, 17, 17],
[19, 19, 19, ..., 17, 17, 17],
[19, 19, 19, ..., 17, 17, 17]]]))
4/26/17,这些数字,就是预测的像素类别。
- 数据预处理
data = (ImageFileList.from_folder(path_img) #Where are the input files? -> in path_img
.label_from_func(get_y_fn) #How to label? -> use get_y_fn
.random_split_by_pct() #How to split between train and valid? -> randomly
.datasets(SegmentationDataset, classes=codes) #How to create a dataset? -> use SegmentationDataset
.transform(get_transforms(), size=96, tfm_y=True) #Data aug -> Use standard tfms with tfm_y=True
.databunch(bs=64)) #Lastly convert in a databunch with batch size of 64.
定义一个 DataBunch 对象,设置图片地址、标签如何匹配(通过上面的函数get_y_fn
)、数据集类型(语义分割数据集 SegmentationDateset)、数据增强参数(大小 96,默认垂直翻转为 True 真值)、批大小 64
- 微调->图片放大(Go Big)
先训练小尺寸的样本图片,得到模型后,再将图片尺寸调大,再次微调。模型精度更高。
- 语义分割模型->预测新图片的代码
img = open_image('/home/jupyter/tutorials/fastai/course-v3/nbs/dl1/images/wish_you_here.png')
prediction = learn.predict(img)
prediction[0].show(figsize=(5,5))
参考来源:https://forums.fast.ai/t/image-segmentation-on-new-images-lesson-3-beginner/41209/4
其他
- 碎碎念
「付费,稳定、高速的服务 --> 完爆 --> 「免费,随机、不稳定的普通服务」
比如谷歌系自己的 GCP VS Colab。笔者曾在 colab 上用 fastai 训练一个亚马逊评论的数据集,多次运行中虚拟机器崩溃报错,训练过程支离破碎。相比之下,GCP 的机器,就跟在本地运行几乎一样的体验。
人也如此,在职场中,若一个人能够一个高速稳定简洁的接口一样。人人都爱啊。
changeLog
2019.07.12 init
2019.07.16 public