基于yolo进行目标检测的实验和研究

根据我接触到的项目经验来看,需要我们进行检测的不是自然场景下的任意物体,而是特定场景下一类物体。典型的就是钢管识别,这些照片一般都是在厂区里面拍的、是对着钢管拍的,拍摄的目的是识别出钢管的数量。这里就为YOLO一类目标检测技术提供了空间,通过基于自定义数据集的迁移学习,能够实现一些效果,这里将相关东西整理出来。

image

基础环境:

标注工具分为本机标注和网络智能标注。LabelImg能够提供不错的操作体验,在windows上我只找到一个老版本的,能够生成voc的数据格式;在linux上的最新版本可以直接生成yolo的格式。

image

easydate能够提供只能标注,简单来说就是你只需要标注几张图片(不同数据数量不同),它可以先训练一个小模型,辅助你继续进行标注。

image

这个的价值肯定是不言而喻的。在标注这块,我还编码实现了基于传统算法的标签生成工具。具体来说,就是基于传统算法,生成初略的数据集,将这里的结果作为标签导入模型训练中去。

image

多措并举,能够有效提高数据标注速度。当然,标注仍然是一个痛苦的过程。

在训练这块,我使用了基于Kaggle的yolo官方notebook(https://www.kaggle.com/code/jsxyhelu2019/yolov5),进行一些删改后使用。这样能够有效使用免费的GPU,而且相对来说也比较方便。

image

实验一:筷子识别

第一个例子使用了网络上找到的数据集“筷子识别”,他最大的优势就是提供了完整的数据集。

1、图片的采集,可以看到这里的数据是比较集中的、质量是比较高的。数量大概210左右。

image

2、labelimg标注。原作者提供了标注好的voc结果,可以直接使用,也可以拿过来自己体会一下。

image

3、智能标注扩充。生成3张图像,使用easydl进行智能进行扩充。注意这里如果无标注数据太少,智能标注会开启失败。

image

image

4、修正结果

image

5、数据格式转换。需要将voc格式转换成为yolo格式。注意这里的label和前面标注的label是一样的。

**import** **os** **import** **xml**.etree.ElementTree as ET classes = ["label"] # 将x1, y1, x2, y2转换成yolov5所需要的x, y, w, h格式 **def** xyxy2xywh(size, box):     dw = 1. / size[0]     dh = 1. / size[1]     x = (box[0] + box[2]) / 2 * dw     y = (box[1] + box[3]) / 2 * dh     w = (box[2] - box[0]) * dw     h = (box[3] - box[1]) * dh     **return** (x, y, w, h)         # 返回的都是标准化后的值 **def** voc2yolo(path):     # 可以打印看看该路径是否正确     **print**(**len**(**os**.listdir(path)))     # 遍历每一个xml文件     **for** file **in** **os**.listdir(path):         # xml文件的完整路径         label_file = path + file         # 最终要改成的txt格式文件,这里我是放在voc2007/labels/下面         out_file = **open**(path.replace('Annotations', 'labels') + file.replace('xml', 'txt'), 'w')         # print(label_file)         # 开始解析xml文件         tree = ET.parse(label_file)         root = tree.getroot()         size = root.**find**('size')            # 图片的shape值         w = **int**(size.**find**('width').text)         h = **int**(size.**find**('height').text)         **for** obj **in** root.iter('object'):             difficult = obj.**find**('difficult').text             cls = obj.**find**('name').text             **if** cls **not** **in** classes **or** **int**(difficult) == 1:                 **continue**             # 将名称转换为id下标                 cls_id = classes.index(cls)             # 获取整个bounding box框             bndbox = obj.**find**('bndbox')             # xml给出的是x1, y1, x2, y2             box = [**float**(bndbox.**find**('xmin').text), **float**(bndbox.**find**('ymin').text), **float**(bndbox.**find**('xmax').text),                 **float**(bndbox.**find**('ymax').text)]             # 将x1, y1, x2, y2转换成yolov5所需要的x, y, w, h格式             bbox = xyxy2xywh((w, h), box)             # 写入目标文件中,格式为 id x y w h             out_file.write(**str**(cls_id) + " " + " ".join(**str**(x) **for** x **in** bbox) + '\n') **if** **__name__** == '__main__':     # 这里要改成自己数据集路径的格式     path = 'E:/DatasetId_1624813_1657795900/Annotations/'     voc2yolo(path)

image

我还特地验证一下效果。

image

6、kaggle训练

数据上传注意需要都是zip格式的。

编写的一些内容:

image

image

path: datasets/kuaizi  # dataset root dir train: train   val: val    test:  # Classes nc: 1   names: ['label']

image

使用现有资源,进行训练.

image

注意这里的iamges和labels是放在一起的。

image

相关结果查看。

image

image

model下载,可以作为infer来使用。最好是能够测试,直接使用infer测试也是不错.

模型训练完成后,将runs/exp/weights下的模型(best.pt)复制在yolov5文件夹下。如下图所示:

image

实验二:钢管识别

有了前面的经验,可以更加放手做一些工作。

钢管数据的特点就是需要自己标注,所以这里我使用了很多trick来完成这个目标。

1、首先,单模型使用小标签(P)方便显示

image

2、使用现有工具,能够完成一些东西。那么数据需要重新来做,并且把里面重复的东西确实的去掉。

image

我现在给出的是这个代码可以生产coco json 的结果

3、使用easyDL进行标注管理。也需要做好多轮标注的准备

image

数据标注量很大,无法保证数据集的高可用,必须寻找到有效的迭代方法。比如这样图像的标注,实在是太费事了

image

开启easydl智能标注,需要60张左右;

4、最终easyDL给出了不错的错误观测界面,这个对于我数据分析来说是有用的

image

image

image

这个训练花了4个小时,这个也是需要注意一下的时间。最后就是部署这块

image

5、easydl提供了一些模式,但是需要和设备进行绑定。对于现在的我来说了,绑定不符合SMD的预期模式,所以先不看。我需要的还是YOLO原生,然后尽可能达到同样的MAP等

image

这里的mAP到底是否可用?我查了一些资料证明还是可行的

image

那这么看来目前这个值还是很高的。

6、方面验证是可行的,但是效果不尽如人意,其根本原因是我数据标注的不够。相关的技术需要研究出来去购买数据,这是另一个维度的问题。此外在软件使用过程中,如果能够将数据标注的过程反馈出来,那就是更上一个层次。

image

实验三:毛发识别

实际上,毛发识别存在尺度、方向等多个问题,并且需要解决的是3对象,难度是更大的。首先还是以现有的方法来进行处理,然后再思考其他。

image

说实话,我对使用深度学习解决毛发识别问题不是有完全的信息,因为这不是一个典型的问题,比如对象不是一个矩形框,而应该是自定义四边形。

image

如果使用举行进行标注,可以发现重叠非常多:

image

平行思考,如果基于AI去做语义分割的话,意义也不是很大,传统算法已经能够做很好的分割。

毛发识别算法的关键在于去除粘连,特别在根据现有的硬件进行精度测量,这样才能够获得高效的东西。

实验小结:

讨论一下传统方法和AI方法之间的关系:

1、AI能够解决很多传统方法无法解决、解决不好的问题,但AI不是万能的、仍然有很多问题目前无法解决;

2、使用传统方法为AI生产数据集、全流程地参与到AI生产中,可能是未来出路;

3、AI只不过是增加了一种解决问题的、不同维度的方法,它出来了很多模型和工具,但是解决问题的思路仍然关键决定因素。

感谢阅读至此,希望有所帮助。

posted on 2022-07-17 09:08  jsxyhelu  阅读(551)  评论(0编辑  收藏  举报

导航