作者主页(​​文火冰糖的硅基工坊​​​):​​文火冰糖(王文兵)的博客_文火冰糖的硅基工坊


目录

​第1步 执行程序​

​第2步 检测前准备​

​第3步 准备数据集​

​第4步 准备网络模型​

​第5步 预测前的准备​

​第6步 开始预测/目标检测​

​第7步 预测后处理​


第1步 执行程序



python detect.py --save-crop  --save-txt --save-conf


[YOLO专题-25]:YOLO V5 - ultralytics代码解析-detect.py检测代码的详细执行流程_YOLO V5

-- weights:​指定预训练好的模型,默认采用当前目录下的yolov5s.pt模型,该模型时yolov5s自带模型。

 -- source:​指定需要预测的图片,可以是一个包含图片,视频的目录,也可以是单一的图片或视频,也可以是网络链接,需要在线下载,也可以是摄像头。默认在data/images,这里有yolov5工程自带的几张测试图片。

源图片的位置(YOLO工程自带的测试图片):data\images

[YOLO专题-25]:YOLO V5 - ultralytics代码解析-detect.py检测代码的详细执行流程_ultralytics_02

-- imgsz:​送入到网络中的图片的尺寸,默认是640 * 640

--view-img:​在执行的过程中会直接显示被检测的图像或视频中的结果,单张图片效果不明显,一散而过。

--nosave:​不需要存储目标检测的图片(原图片+目标检测方框),默认是要存储的。

保存的图片位置:.\run\detect\expxxx\bus.jpg

保存的图片内容:

[YOLO专题-25]:YOLO V5 - ultralytics代码解析-detect.py检测代码的详细执行流程_detect_03

--save-txt:​把检测到的所有目标的信息写到文本文件中,每个目标包括分类信息+定位信息,实际上就是标签信息。

保存的文件位置:.\run\detect\expxxx\lables\bus.txt

保存的文件内容:

0         0.05                 0.668519 0.1 0.296296 0.308542

5         0.502469         0.466204 0.995062 0.547222 0.811215

0         0.917284         0.59213 0.162963 0.450926 0.833667

0         0.17284           0.603241 0.222222 0.469444 0.851886

0         0.35                 0.588889 0.146914 0.424074 0.869995

--save-conf​:把检测的目标的置信度信息也添加到save-txt文本中。

保存的文件位置:.\run\detect\expxxx\lables\bus.txt

保存的文件内容:

0         0.05                 0.668519 0.1 0.296296 0.308542

5         0.502469         0.466204 0.995062 0.547222 0.811215

0         0.917284         0.59213 0.162963 0.450926 0.833667

0         0.17284           0.603241 0.222222 0.469444 0.851886

0         0.35                 0.588889 0.146914 0.424074 0.869995

--save-crop:​把检测到的目标方框中的图片,裁剪出来,并存储起来。

保存的文件位置 (每个分类有一个独立的子目录)

        .\run\detect\expxxx\crops\person\

        \run\detect\expxxx\crops\bus\

保存的文件内容:

[YOLO专题-25]:YOLO V5 - ultralytics代码解析-detect.py检测代码的详细执行流程_ultralytics_04

从打印信息来看,文件的名称是显示的图片的名称,而不是目标的名称,这可能是一个bug. 

--visualize:​打开该开关后,会神经网络每一层的预测的图像都存储起来,用于可视化神经网络每一层的执行结果,如下图所示:

[YOLO专题-25]:YOLO V5 - ultralytics代码解析-detect.py检测代码的详细执行流程_程序流程_05

第2步 检测前准备

(1)主函数:main()

第3步 准备数据集

(1)根据 --source参数,检查数据是单张图片?视频?还是目录?还是摄像头?是否需要远程下载。

        is_file = Path(source).suffix[1:] in (IMG_FORMATS + VID_FORMATS)

        is_url = source.lower().startswith(('rtsp://', 'rtmp://', 'http://', 'https://'))

        webcam = source.isnumeric() or source.endswith('.txt') or (is_url and not is_file)

        source = check_file(source) # download

(2)创建预测结果输出目录: ./run/detect/expxxx(动态增加序号xxx)

第4步 准备网络模型

(1)设置GPU设备

(2)创建detect模型:​model = ​DetectMultiBackend​(weights, device=device, dnn=dnn)

yolov5支持传入多个权重网络,这时候,多个网络之间是​并行关系​,输入的图片分别送入到两个网络中进行预测,并把两个网络的预测结果组合在一起,然后进行非最大似然抑制。

(3)获取模型的信息:​特征压缩比stride,目标的名称列表,模型的类型等

(4)​把模型设置在half模式(float16模式),还是full模式(float32模式)

第5步 预测前的准备

(1)根据--source选项,创建相应的dataloader,加载数据到数据集dataset

        -- 网络:dataset = ​LoadStreams​(source, img_size=imgsz, stride=stride, auto=pt)

        -- 本地:dataset = ​LoadImages​(source, img_size=imgsz, stride=stride, auto=pt)

        -- 设置batch size = 1

在加载图片的过程中个,dataloader会对图片进行resize,resize之后,某个维度的维度的方向是imgsz,另一个维度方向进行等比例放缩。注意:resize时候的尺寸并​不是​imgsz * imgsz,如640 * 640,而是把图片的两个方向的尺寸限制在imgsz范围之内。

(2) 模型的warm up:用一个随机数据进行预测一次,但不保存结果

        - model.​warmup​(imgsz=(1, 3, *imgsz), half=half) # warmup

第6步 开始预测/目标检测

(1)一次读取读取一个batch的图片,挨个进行预测:for path, im, im0s, vid_cap, s in dataset:

           -- path:图片的路径

           -- im: resize之后的图片,该图片是用来进行网络预测用的。

           -- im0s:没有resize之前的原始图片,用于最终的图片输出和目标框的绘制。

          -- vid_cap:视频捕捉器对象

          --s:图片的全路径名称

        (1)获取当前的时间

        (2)对需要预测的输入图片im进行​预处理

                (1)对图片进行归一化处理:im /= 255。

                        之所以没有在dataset内部做归一化,是因为输出图片是,需要原始图片作为蓝本。

                (2)把输入图片的维度扩展到YOLO所需要的维度:im = im[None]

                (3)获取当前的时间,计算用于​图片预处理​的时间

        (3)​关键点之一:​对图片进行​预测 (所有的目标框输出)

                (1)确定是否需要可视化,并创建相关的目录

                (2)模型预测:​pred ​= model(im, augment=augment, visualize=visualize)

                        预测结果为:torch.Size([1, 16380, 85])

                               --1:batch size

                                --16380:表示有16380个预测框,分为大中小三种类型,

                                                三种类型各自框的数量并不是等比例的,大框少,小框多。

                                -- 85 = 80 + 5, 其中80值每个分类的概率值

                                                          其中5 = 1 + 4, 1表示是物体的置信度,4表示物体坐标值。

                        需要说明的是:YOLO V5支持多个模型并行预测,

                                                其预测值是多个并行模型的联合输出。

                (3)获取当前的时间,计算用于图片预测的时间。

        (4)​关键点之二:非最大比抑制NMS处理(过滤掉没有目标的目标框后的输出)

                (1) ​pred ​= ​non_max_suppression ​(pred, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)

                        pred是一个列表,最外层的维度是batch size,代表多张图片同时预测。

                        当然,在预测时,通常情况下是单张单张图片进行预测,所以len(pred)==1

                        每一张图片是一个tensor,包含的是,每张图中的所有box的检测结果。

                        torch.Size([n, 6]),  n表示检测到的目标的数量,

                                                     6表示每个目标的参数,包括类别号,类别可能性,4个坐标值。

                        如果说,模型前向运算的输出,是所有预测框的预测值,

                        那么,最大抑制比输出,就是检测到的所有物体的信息:类别+可能性+坐标

                        经过最大抑制比之后,才选出了要检测的目标。

                (2)获取当前的时间,计算用于NMS处理的时间

第7步 预测后处理

(1)对每一张图片进行后期处理:​for i, det in enumerate(pred): # per image

         每个det对象,代表一张图,是每一张图片中所有发现物体的信息,而不是一个物体的信息。

          -- 

        (1)目标总数累计:seen += 1

        (2)为原图创建一个画图对象:annotator = ​Annotator​(im0,...)

        (3)把预测图片还原成原始图片的尺寸:det[:, :4] = ​scale_coords​(im)

        (4)在控制台中,打印该图片中发现的所有目标的汇总信息。

        (5)对每个发现的目标逐一处理:​for *xyxy, conf, cls in reversed(det):

                (1)把检测到的该目标的坐标信息,分类信息,放到txt文件中 (​--save-txt)

                (2)把检测到的该目标的置信度信息,放到txt文件中 ​(--save-conf)

                        ​ line = (cls, *xywh, conf) if save_conf else (cls, *xywh)

                         ​f.write(('%g ' * len(line)).rstrip() % line + '\n')

                        16 0.561875 0.512948 0.26375 0.938247 0.679971
                        15 0.814375 0.679283 0.26125 0.609562 0.821541
                        15 0.361875 0.656375 0.24125 0.675299 0.840133

                (3)在原图中标注发现的目标:位置框+分类lable名称+置信度/可能性(​--save-img​)

                        annotator.box_label(xyxy, label, color=colors(c, True))

                (4)把检测到的目标裁剪并保存 ​(--save-crop)

                        save_one_box​(xyxy, imc, file=save_dir / 'crops' / names[c] / f'{p.stem}.jpg')

        (6)打印预测时间:LOGGER.info(f'{s}Done. ({t3 - t2:.3f}s)')

        (7)显示标注过的图片:​(--view-img)

                im0 = annotator.result()

                cv2.imshow(str(p), im0)

        (8)存储带目标的标准框的图片或视频​(--nosave)

                (1)图片存储:cv2.imwrite(save_path, im0)

                (2)视频存储:cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc(*'mp4v'))

        (9)打印检测结果:

                image 1/3 yolov5\data\images\Dogs.jpg: 416x640 2 cats, 2 dogs, Done. (355.423s)

                image 2/3 yolov5\data\images\bus.jpg: 640x480 4 persons, 1 bus, Done. (1.363s)

                image 3/3 yolov5\data\images\zidane.jpg: 384x640 ​2 persons, 1 tie​, Done. (0.008s)

(2)打印整个预测汇总结果

Speed: 45234.7ms            =》总共花的时间

pre-process, 118931.5ms  =》预处理花的时间

inference, 90719.8ms        =》预测花的时间

NMS per image at shape (1, 3, 640, 640)

Results saved to runs\detect\exp67

(3)输出文件

\run\detect\expxxx\


作者主页(​​文火冰糖的硅基工坊​​​):​​文火冰糖(王文兵)的博客_文火冰糖的硅基工坊