爱分享的 OpenVINO 中文社区
内 容 来 源 | 李国栋 赛博联物
排 版 | 卢书晴
OpenCV数据增强与LabelImg标注
一、概念
在深度学习过程中,往往假定训练样本每个类别的数量是基本相同的,但在实际生产过程中,对产品表面或内部质量的检测是否有瑕疵,想对每种类别的瑕疵得到这种等数量的样本是非常困难的,就算能收集到,也要花费大量的人力物力。因而才有迁移学习的方法,而且训练样本数量不平衡,会导致训练出来的模型在测试集上的泛化能力受到很大影响。
为了实现训练样本数量平衡,通常使用数据增强技术来增加样本数量。为了能够生成OpenVINO 能够识别和转化的 IR 文件,进行边缘推理,本文采用 Tensorflow Object Detection API 进行迁移学习,直接利用其在COCO 训练集上训练好的模型ssd_inception_v2_coco和faster_cnn_inception_v2_coco,对工业上的待检零件进行训练和学习。
本文中实际得到的零件图片约有500张,有瑕疵和合格的比例不等,而且每张图片约11MB大小。因此为了增加训练效果,减小数据存储空间,一般会对数据进行增强,增加样本数量,解决样本不平衡的问题。
因此,本文对拿到的图片进行缩放、旋转和镜像处理,然后各自选取等量的图片进行标注。其中数据增强采用的是 python 和 opencv 编码实现,在处理的过程中遇到两个坑,本文旨在阐述填平这两个坑的过程,其次,描述一下用 LabelImg 进行图片标注时,遇到的问题,与大家共享。
二、主要内容
文中用到的零件名称为 V8,目标是检测其内部缺陷,采用X射线探伤数字成像技术生成的图片。每张图片大小约11MB,尺寸为2560×1536的 .bmp文件。所以首先对图片进行压缩和缩放,生成448×448尺寸的 .jpg 图片,压缩后大小约为30kB,然后对选取的图片分别进行水平镜像、垂直镜像、旋转90度、180度和270度处理。V8 的零件图和检测生成的图像分别如下图所示:
因为 lattepanda 板上资源有限,数据增强和标注过程均是在PC机上完成。windows10 操作系统,python3.7.1,opencv4.2,通过在VSCode 环境下编写图像处理程序并进行调试,得到相应的处理图片。
1. 图片压缩和缩放
图片处理的机制是,先读入图片,然后进行压缩,再转存到所需要的大小和格式。采用 opencv 的 cv2 库进行处理,读取单张图片,一般是使用cv2.imread 函数,所用代码如下:
导入需要的库,定义缩放压缩处理函数
其次编写调用函数
当用 cv.imread 读取单张图片时,一切正常。而实际中要处理的图片很多,按不同的分类放在不同的文件夹下,我们希望的是批量处理,当采用下述代码时,程序不报错,但结果不对,比较隐晦。
通过断点跟踪,发现 cv.imread 循环读取文件夹内文件时,返回的是空对象,无法进行后续处理。在查阅一些资料之后,发现批量读取处理图片cv.imread 无法胜任,于是改用 cv.imdecode ,更改后代码如下,成功实现了大图的缩放。
2、图片的旋转和镜像
图片压缩到指定大小后,才到了数据增强的处理,本文为了保证图片处理后不变大或偏斜,只进行了水平镜像、垂直镜像,旋转90度、180度和270度五种方式。
依然采用的是批量处理,循环读取,本以为会顺利实现,然而结果却出人意料,还是用的cv.imdecode ,却没有出现想要的效果,于是再次断点跟踪,发现返回的还是空对象,why?
事实证明,只是单纯的模仿和使用,是解决不好根本问题的。原来 cv.imdecode 调用的第二个参数 flag 很有讲究,整理如下:
代码还是沿用前面的,flag取的是-1,结果却不正确,这是因为图像在压缩前后造成的差异,压缩前是bmp格式的彩色图,压缩后是jpg格式的灰度图,深度和通道都发生了改变。当取0和除1外的正数时,都可以正常的读入图像,进行镜像和旋转处理。代码如下:
3. LabelImg 图片标注
此部分内容主要参考《深度学习图像识别技术》的第三章3.4节, LabelImg 是一个 Python 写的开源免费的图像标注工具,其标注结果会以 PASCAL VOC 格式存成 XML 文件,也支持YOLO 格式。
上图是打开 LabelImg 后,在左侧工具栏中选择打开图片目录和保存目录,当图片正常显示在中部后,就可以选择创建选框,进行画矩形标注的过程了。当然前期需要制作预定义的分类标签文件,然后就可以框选图片上的合格或不合格的零件部分,并在右侧label中选择分类的 label ,图中是 v8_bad ,也就是框选的是不合格的部分,然后点击保存,就会在保存目录中看到生成了同名的 XML 文件。
这个操作过程简单,但数量多时,工作量大,考验耐心,并没有高的技术含量。本文中用到的图片有约4000张,一张张画框、选类别还是很费功夫的,也容易疲劳出错。所以想提醒读者,在用不同的开发框架进行模型训练时,需要将所有 XML 文件转成 csv 格式,然后再转成所用框架支持的数据输入格式文件,本例中用的 tensorflow ,所以要转换成 .tfrecord 格式。
我在标注的过程中遇到的问题是,由于图片是按合格、不合格,检验日期分类的不同的文件夹中存放的,所以也是分别标注的。这样造成的问题是,训练时需要将所有的图片都放到 images\train 的文件夹内,然后再转换数据格式,这样XML文件中的路径和文件名称就需要重新定位,虽然只是按一下空格键(快捷键)就可以完成,但如果是成千上万张图片,还是很累人的。所以建议,先将图片在名称上带有合格、日期等信息(这个可以通过程序来实现,我是已经在数据增强时完成了此工作),然后所有图片放到一个文件夹中再进行标注,然后再转换成数据格式文件。这样就会避免重复性的劳动,推理验证时也可直接看出预测结果是否正确,一目了然,所以即使是标注工作,也要提前进行设计和规划,才能不返工。
三、结论
Opencv 处理函数 imread 或 imdecoded 在批量读入图片时,第二参数 flag 至关重要,对不同格式和位数、通道的图片要选取合适的参数才能得到正确的结果。而且网上说的关于是中文目录的影响不完全,即使是英文或数字的目录或文件名,参数配置的不合理,也还是得不到正确的结果。
LabelImg 标注工具,框选只能是矩形框,如果是任意形状比较理想,但这主要是受深度学习算法的影响,矩形框以坐标和直线的形式进行点的搜索和直线的回归要容易一些,曲线处理的难度就大大增加。所以在矩形框选的前提下,要合理规划不同分类图片的目录和名称,并把相关文件放到同一目录下进行处理,则可以避免重复性的劳动。
关注我们,让开发变得更有趣
微信号:openvinodev
B站:OpenVINO 中文社区
*OpenVINO and the OpenVINO logo are trademarks of Intel Corporation or its subsidiaries.