粉丝投稿 | OpenCV数据增强与LabelImg标注

粉丝投稿 | OpenCV数据增强与LabelImg标注

爱分享的 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.

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
要使用 OpenCV 处理 DICOM 图像,你需要先将 DICOM 文件读入内存中,然后将其转换为 OpenCV Mat 对象。可以使用 pydicom 库来读取 DICOM 文件,然后使用 OpenCV 的 cv2.imread() 函数将其转换为 Mat 对象。 以下是一个简单的示例代码,演示如何读取 DICOM 文件并将其转换为 OpenCV Mat 对象: ```python import cv2 import pydicom # 读取 DICOM 文件 ds = pydicom.dcmread('path/to/dicom/file.dcm') # 将 DICOM 数据转换为 OpenCV Mat 对象 img = ds.pixel_array.astype('uint16') img = cv2.normalize(img, None, 0, 65535, cv2.NORM_MINMAX) img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) ``` 对于将照片转换为素描风格,可以使用 OpenCV 中的 Pencil Sketch 算法。该算法包括两个步骤:首先将图像转换为灰度图像,然后应用高斯模糊和 Sobel 滤波器来生成素描效果。 以下是一个简单的示例代码,演示如何将照片转换为素描风格: ```python import cv2 # 读取图像 img = cv2.imread('path/to/image.jpg') # 将图像转换为灰度图像 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 应用高斯模糊 gray_blur = cv2.GaussianBlur(gray, (21, 21), 0) # 应用 Sobel 滤波器 sobelx = cv2.Sobel(gray_blur, cv2.CV_64F, 1, 0, ksize=5) sobely = cv2.Sobel(gray_blur, cv2.CV_64F, 0, 1, ksize=5) sobel = cv2.addWeighted(sobelx, 1, sobely, 1, 0) # 反转颜色并应用归一化阈值 sketch = 255 - cv2.threshold(sobel, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1] sketch = cv2.normalize(sketch, None, 0, 255, cv2.NORM_MINMAX) # 显示结果 cv2.imshow('Original', img) cv2.imshow('Sketch', sketch) cv2.waitKey(0) cv2.destroyAllWindows() ``` 这将显示原始图像和转换后的素描图像。你可以调整算法的参数来获得不同的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值