原文地址:https://www.cnblogs.com/jsxyhelu/p/16995892.html
传统图像处理算法进行“天空分割”存在精度问题且调参复杂,无法很好地应对云雾、阴霾等情况;本篇文章分享的“基于Unet+opencv实现天空对象的分割、替换和美化”,较好地解决了该问题,包括以下内容:
1、基于Unet语义分割的基本原理、环境构建、参数调节等 2、一种有效的天空分割数据集准备方法,并且获得数据集 3、基于OpenCV的Pytorch模型部署方法 4、融合效果极好的 SeamlessClone 技术 5、饱和度调整、颜色域等基础图像处理知识和编码技术
本文适合具备 OpenCV 和Pytorch相关基础,对“天空替换”感兴趣的人士。学完本文,可以获得基于Pytorch和OpenCV进行语义分割、解决实际问题的具体方法,提高环境构建、数据集准备、参数调节和运行部署等方面综合能力。
一、传统方法和语义分割基础
1.1传统方法主要通过“颜色域”来进行分割
比如,我们要找的是蓝天,那么在HSV域,就可以通过查表的方法找出蓝色区域。
在这张表中,蓝色的HSV的上下门限已经标注出来,我们编码实现。
cvtColor(matSrc,temp,COLOR_BGR2HSV); split(temp,planes); equalizeHist(planes[2],planes[2]);//对v通道进行equalizeHist merge(planes,temp); inRange(temp,Scalar(100,43,46),Scalar(124,255,255),temp); erode(temp,temp,Mat());//形态学变换,填补内部空洞 dilate(temp,temp,Mat()); imshow("原始图",matSrc);
在这段代码中,有两个小技巧,一个是对模板(MASK)进行了形态学变化,这个不展开说;一个是我们首先对HSV图进行了3通道分解,并且直方图增强V通道,而后将3通道合并回去。通过这种方法能够增强原图对比度,让蓝天更蓝、青山更青……大家可以自己调试看一下。 显示处理后识别为天空的结果(在OpenCV中,白色代表1也就是由数据,黑色代表0也就是没数据)
对于天坛这幅图来说,效果不错。虽然在右上角错误,而塔中间的一个很小的空洞,这些后期都是可以规避掉的错误。
但是对于阴霾图片来说,由于天空中没有蓝色,识别起来就很错误很多。
1.2 语义分割基础
图像语义分割(semantic segmentation),从字面意思上理解就是让计算机根据图像的语义来进行分割,例如让计算机在输入下面左图的情况下,能够输出右图。语义在语音识别中指的是语音的意思,在图像领域,语义指的是图像的内容,对图片意思的理解,比如左图的语义就是三个人骑着三辆自行车;分割的意思是从像素的角度分割出图片中的不同对象,对原图中的每个像素都进行标注,比如右图中粉红色代表人,绿色代表自行车。
那么对于天空分割问题来说,主要目标就是找到像素级别的天空对象,使用语义分割模型就是有效的。
二、Unet基本情况和环境构建
Unet 发表于 2015 年,属于 FCN 的一种变体,Unet 的初衷是为了解决生物医学图像方面的问题,由于效果确实很好后来也被广泛的应用在语义分割的各个方向,比如卫星图像分割,工业瑕疵检测等。它也有很多变体,但是对于天空分割问题来看,Unet的能力已经够了。
Unet 跟 FCN 都是 Encoder-Decoder 结构,结构简单但很有效。Encoder 负责特征提取,你可以将自己熟悉的各种特征提取网络放在这个位置。由于在医学方面,样本收集较为困难,作者为了解决这个问题,应用了图像增强的方法,在数据集有限的情况下获得了不错的精度。
如上图,Unet 网络结构是对称的,形似英文字母 U 所以被称为 Unet。整张图都是由蓝/白色框与各种颜色的箭头组成,其中,蓝/白色框表示 feature map;蓝色箭头表示 3x3 卷积,用于特征提取;灰色箭头表示 skip-connection,用于特征融合;红色箭头表示池化 pooling,用于降低维度;绿色箭头表示上采样 upsample,用于恢复维度;青色箭头表示 1x1 卷积,用于输出结果。
在环境构建这块,我建议一定要结合自己的实际情况,构建专用的代码库,这样才能够通过不断迭代,在总体正确的前提下形成自己风格。
在我的库中,基于现有的Unet代码进行了修改