作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客
本文网址:https://blog.csdn.net/HiWangWenBing/article/details/122377470
目录
第1步 执行程序
第2步 检测前准备
第3步 准备数据集
第4步 准备网络模型
第5步 预测前的准备
第6步 开始预测/目标检测
第7步 预测后处理
python detect.py --save-crop --save-txt --save-conf
-- weights:指定预训练好的模型,默认采用当前目录下的yolov5s.pt模型,该模型时yolov5s自带模型。
-- source:指定需要预测的图片,可以是一个包含图片,视频的目录,也可以是单一的图片或视频,也可以是网络链接,需要在线下载,也可以是摄像头。默认在data/images,这里有yolov5工程自带的几张测试图片。
源图片的位置(YOLO工程自带的测试图片):data\images
-- imgsz:送入到网络中的图片的尺寸,默认是640 * 640
--view-img:在执行的过程中会直接显示被检测的图像或视频中的结果,单张图片效果不明显,一散而过。
--nosave:不需要存储目标检测的图片(原图片+目标检测方框),默认是要存储的。
保存的图片位置:.\run\detect\expxxx\bus.jpg
保存的图片内容:
--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\
保存的文件内容:
从打印信息来看,文件的名称是显示的图片的名称,而不是目标的名称,这可能是一个bug.
--visualize:打开该开关后,会神经网络每一层的预测的图像都存储起来,用于可视化神经网络每一层的执行结果,如下图所示:
(1)主函数:main()
(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)
(1)设置GPU设备
(2)创建detect模型:model = DetectMultiBackend(weights, device=device, dnn=dnn)
yolov5支持传入多个权重网络,这时候,多个网络之间是并行关系,输入的图片分别送入到两个网络中进行预测,并把两个网络的预测结果组合在一起,然后进行非最大似然抑制。
(3)获取模型的信息:特征压缩比stride,目标的名称列表,模型的类型等
(4)把模型设置在half模式(float16模式),还是full模式(float32模式)
(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
(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处理的时间
(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\
作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客
本文网址:https://blog.csdn.net/HiWangWenBing/article/details/122377470