基于yolo进行目标检测的实验和研究
作者:互联网
根据我接触到的项目经验来看,需要我们进行检测的不是自然场景下的任意物体,而是特定场景下一类物体。典型的就是钢管识别,这些照片一般都是在厂区里面拍的、是对着钢管拍的,拍摄的目的是识别出钢管的数量。这里就为YOLO一类目标检测技术提供了空间,通过基于自定义数据集的迁移学习,能够实现一些效果,这里将相关东西整理出来。
基础环境:
标注工具分为本机标注和网络智能标注。LabelImg能够提供不错的操作体验,在windows上我只找到一个老版本的,能够生成voc的数据格式;在linux上的最新版本可以直接生成yolo的格式。
easydate能够提供只能标注,简单来说就是你只需要标注几张图片(不同数据数量不同),它可以先训练一个小模型,辅助你继续进行标注。
这个的价值肯定是不言而喻的。在标注这块,我还编码实现了基于传统算法的标签生成工具。具体来说,就是基于传统算法,生成初略的数据集,将这里的结果作为标签导入模型训练中去。
多措并举,能够有效提高数据标注速度。当然,标注仍然是一个痛苦的过程。
在训练这块,我使用了基于Kaggle的yolo官方notebook(https://www.kaggle.com/code/jsxyhelu2019/yolov5),进行一些删改后使用。这样能够有效使用免费的GPU,而且相对来说也比较方便。
实验一:筷子识别
第一个例子使用了网络上找到的数据集“筷子识别”,他最大的优势就是提供了完整的数据集。
1、图片的采集,可以看到这里的数据是比较集中的、质量是比较高的。数量大概210左右。
2、labelimg标注。原作者提供了标注好的voc结果,可以直接使用,也可以拿过来自己体会一下。
3、智能标注扩充。生成3张图像,使用easydl进行智能进行扩充。注意这里如果无标注数据太少,智能标注会开启失败。
4、修正结果
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)
我还特地验证一下效果。
6、kaggle训练
数据上传注意需要都是zip格式的。
编写的一些内容:
path: datasets/kuaizi # dataset root dir train: train val: val test: # Classes nc: 1 names: ['label']
使用现有资源,进行训练.
注意这里的iamges和labels是放在一起的。
相关结果查看。
model下载,可以作为infer来使用。最好是能够测试,直接使用infer测试也是不错.
模型训练完成后,将runs/exp/weights下的模型(best.pt)复制在yolov5文件夹下。如下图所示:
实验二:钢管识别
有了前面的经验,可以更加放手做一些工作。
钢管数据的特点就是需要自己标注,所以这里我使用了很多trick来完成这个目标。
1、首先,单模型使用小标签(P)方便显示
2、使用现有工具,能够完成一些东西。那么数据需要重新来做,并且把里面重复的东西确实的去掉。
我现在给出的是这个代码可以生产coco json 的结果
3、使用easyDL进行标注管理。也需要做好多轮标注的准备
数据标注量很大,无法保证数据集的高可用,必须寻找到有效的迭代方法。比如这样图像的标注,实在是太费事了
开启easydl智能标注,需要60张左右;
4、最终easyDL给出了不错的错误观测界面,这个对于我数据分析来说是有用的
这个训练花了4个小时,这个也是需要注意一下的时间。最后就是部署这块
5、easydl提供了一些模式,但是需要和设备进行绑定。对于现在的我来说了,绑定不符合SMD的预期模式,所以先不看。我需要的还是YOLO原生,然后尽可能达到同样的MAP等
这里的mAP到底是否可用?我查了一些资料证明还是可行的
那这么看来目前这个值还是很高的。
6、方面验证是可行的,但是效果不尽如人意,其根本原因是我数据标注的不够。相关的技术需要研究出来去购买数据,这是另一个维度的问题。此外在软件使用过程中,如果能够将数据标注的过程反馈出来,那就是更上一个层次。
实验三:毛发识别
实际上,毛发识别存在尺度、方向等多个问题,并且需要解决的是3对象,难度是更大的。首先还是以现有的方法来进行处理,然后再思考其他。
说实话,我对使用深度学习解决毛发识别问题不是有完全的信息,因为这不是一个典型的问题,比如对象不是一个矩形框,而应该是自定义四边形。
如果使用举行进行标注,可以发现重叠非常多:
平行思考,如果基于AI去做语义分割的话,意义也不是很大,传统算法已经能够做很好的分割。
毛发识别算法的关键在于去除粘连,特别在根据现有的硬件进行精度测量,这样才能够获得高效的东西。
实验小结:
讨论一下传统方法和AI方法之间的关系:
1、AI能够解决很多传统方法无法解决、解决不好的问题,但AI不是万能的、仍然有很多问题目前无法解决;
2、使用传统方法为AI生产数据集、全流程地参与到AI生产中,可能是未来出路;
3、AI只不过是增加了一种解决问题的、不同维度的方法,它出来了很多模型和工具,但是解决问题的思路仍然关键决定因素。
感谢阅读至此,希望有所帮助。
标签:box,基于,检测,yolo,file,text,path,find,标注 来源: https://www.cnblogs.com/jsxyhelu/p/16485907.html