当前位置:   article > 正文

基于YOLOv4的口罩检测的系统研究和实现_口罩目标检测系统设计与实现

口罩目标检测系统设计与实现

目录

一、实现效果

1.1、用户提交图片,检测是否带口罩

 1.2、实时检测

1.3、数据集介绍

二、算法原理

2.1数据增强:Mosaic

2.2网路模型

2.2.1SPP

2.2.2Modified PAN

2.2.3完整结构

三、实验过程

3.1推理阶段

3.1.1读取并加载权重文件

3.1.2读取图片并将输入的图片按照要求的大小进行调整

3.1.4代码

3.2训练阶段

3.2.1 网络结构

四、结果分析

4.1:推理阶段效果

五、结语

六、参考文献


一、实现效果

1.1、用户提交图片,检测是否带口罩

 1.2、实时检测

1.3、数据集介绍

训练集(下载地址(提取码:067d))

测试集

二、算法原理

以YOLOv4为例的深度学习的目标检测算法,是通过卷积神经网络学习预选框与真实框之间的坐标、长宽的回归模型和类别的分类模型,以此完成定位和分类任务。

2.1数据增强:Mosaic

YOLOv4中提出了新的数据增强方式。通过将四张随机选取的图片进行拼接得到一张新的图片。设要生成新图片大小为(W,H),随机得到左上图片的尺寸为(cutX,cutY),则在选取的四种图片中的第一张图片随机切割长宽为(cutX,cutY)的图片填充到左上角,其他三次同理,切割大小分别为(cutX,H-cutY),(W-cutX,cutY),(W-cutX,H-cutY)。

2.2网路模型

YOLOv4在先前的网络基础上进行了修改,加入SPP结构,将FPN结构改为采用Modified PAN结构。

2.2.1SPP

SPP全称为Spatial Pyramid Pooling ,即空间金字塔池化。如图二所示

YOLOv4中的实现是对进行 5 × 5 、 9 × 9  、 13 × 13  的最大池化,完成池化后,将三者进行concatenete,连接成一个特征图。SPP网络用在YOLOv4中的目的是增加网络的感受野。

图二:SPP

2.2.2Modified PAN

PAN是在FPN的基础上新添加了一条由下至上的路径。FPN即特征金字塔网络,如图三(a)所示,PAN如图三(a)(b)所示

FPN认为网络路径中靠前的网络层,即采样倍数较小的层,图片更为清晰,但语义能力差,相反网络路径中靠后的网络层,即采样倍数较大的层,图片较模糊,但语义能力强。使用短接将二者连接起来形成一个特征金字塔。

而PAN的研究发现,靠前网络层的传播路径仍然很漫长,如红线所示。注意不能以图片看见的层数作为实际的层数。绿色框代表了网络中的很多层。于是又新添加了一条有下至上的路径,使得信息更快的传播。

图三:FPN与PAN

YOLOv4对于原本的PAN又进行了修改,改变了原本的最终多层的特征融合方式,由数值的相加改为了维度的链接。使得多层的信息更好的融合保存下来。其如图 4所示

图四:PAN与Modifed PAN

2.2.3完整结构

图五:YOLOvv4输入图片大小为608*608时的网络结构。

如图所示,YOLOv4的网络大致可以分为CSPDarknet53,SPP,PANet,和最终输出结果的YoLo Head四个部分组成。可以看到YOLOv4的最终输出是由三个YoLo Head的输出组成,它们分别在网络结构的不同地方采样,采样倍数分别为,8倍,16倍,32倍。靠前的采样感受野较小,更加倾向于检测小目标,靠后的采样感受野大,能更好的检测大目标。三者的联合便使得此算法对各种大小的目标都能很好的进行检测。

三、实验过程

3.1推理阶段

需要指定运行时参数,设定要检测的类数量、权重文件位置、图片位置、检测结果图片的大小。如:

D:/cv/yolo4/pytorch-YOLOv4/models.py 80 weight/yolov4.pth data/dog.jpg 608 608

需要指定表示检测dog.jpg这张图片中包含coco数据集中的80个类别中的目标。

3.1.1读取并加载权重文件

  1. model = Yolov4(yolov4weight=None,n_classes=n_classes, inference=True)
  2. #加载模型参数
  3. pretrained_dict = torch.load(weightfile, map_location=torch.device('cuda' if use_cuda else 'cpu'))
  4. model.load_state_dict(pretrained_dict)
  5. if use_cuda:
  6.                model.cuda()

3.1.2读取图片并将输入的图片按照要求的大小进行调整

  1. img = cv2.imread(imgfile)
  2. sizedimg = cv2.resize(img, (width, height))
  3. sizedimg = cv2.cvtColor(sizedimg, cv2.COLOR_BGR2RGB)

3.1.3根据模型输出的预测框信息进行NMS后绘制

      NMS即非极大值抑制,抑制不是极大值的元素。通过NMS去除重复的预测框。
非极大值抑制的方法是:先假设有6个矩形框,根据分类器的类别分类概率做排序,假设从小到大属于某一类的概率分别为A、B、C、D、E、F。
(1)从最大概率矩形框F开始,分别判断A~E与F的重叠度IOU是否大于某个设定的阈值;
(2)假设B、D与F的重叠度超过阈值,那么就扔掉B、D;并标记第一个矩形框F,是我们保留下来的。
(3)从剩下的矩形框A、C、E中,选择概率最大的E,然后判断E与A、C的重叠度,重叠度大于一定的阈值,那么就扔掉;并标记E是我们保留下来的第二个矩形框。
就这样一直重复,找到所有被保留下来的矩形框。
NMS的代码如下:

  1. def nms_cpu(boxes, confs, nms_thresh=0.5, min_mode=False):
  2.     # print(boxes.shape)
  3.     x1 = boxes[:, 0]
  4.     y1 = boxes[:, 1]
  5.     x2 = boxes[:, 2]
  6.     y2 = boxes[:, 3]
  7.     areas = (x2 - x1) * (y2 - y1)
  8.     order = confs.argsort()[::-1]
  9.     keep = []
  10.     while order.size > 0:
  11.         idx_self = order[0]
  12.         idx_other = order[1:]
  13.         keep.append(idx_self)
  14.         xx1 = np.maximum(x1[idx_self], x1[idx_other])
  15.         yy1 = np.maximum(y1[idx_self], y1[idx_other])
  16.         xx2 = np.minimum(x2[idx_self], x2[idx_other])
  17.         yy2 = np.minimum(y2[idx_self], y2[idx_other])
  18.         w = np.maximum(0.0, xx2 - xx1)
  19.         h = np.maximum(0.0, yy2 - yy1)
  20.         inter = w * h
  21.         if min_mode:
  22.             over = inter / np.minimum(areas[order[0]], areas[order[1:]])
  23.         else:
  24.             over = inter / (areas[order[0]] + areas[order[1:]] - inter)
  25.         inds = np.where(over <= nms_thresh)[0]
  26.         order = order[inds + 1]
  27.     return np.array(keep)

3.1.4代码

  1. """
  2. Run a rest API exposing the yolov5s object detection model
  3. """
  4. import argparse
  5. import io
  6. import torch
  7. from PIL import Image
  8. from flask import Flask, request
  9. app = Flask(__name__)
  10. DETECTION_URL = "/v1/object-detection/yolov5s"
  11. @app.route(DETECTION_URL, methods=["POST"])
  12. def predict():
  13. if not request.method == "POST":
  14. return
  15. if request.files.get("image"):
  16. image_file = request.files["image"]
  17. image_bytes = image_file.read()
  18. img = Image.open(io.BytesIO(image_bytes))
  19. results = model(img, size=640) # reduce size=320 for faster inference
  20. return results.pandas().xyxy[0].to_json(orient="records")
  21. if __name__ == "__main__":
  22. parser = argparse.ArgumentParser(description="Flask API exposing YOLOv5 model")
  23. parser.add_argument("--port", default=5000, type=int, help="port number")
  24. args = parser.parse_args()
  25. # model = torch.hub.load("ultralytics/yolov5", "yolov5s", force_reload=True) # force_reload to recache
  26. model=torch.hub.load('../../', 'custom', path='./best.pt', source='local')
  27. app.run(host="0.0.0.0", port=args.port) # debug=True causes Restarting with stat

3.2训练阶段

需要指定学习率,预训练模型参数,类别数量,训练数据。其他通用设定都已在cfg文件中指定。如输入:

D:/cv/yolo4/pytorch-YOLOv4/train.py -l 0.001  -pretrained weight/yolov4.pth -classes 3 -dir D:/cv/yolo4/pytorch-YOLOv4/data1

表示训练一个二分类的网络模型,本次实验为检测有无。

3.2.1 网络结构

根据图 来进行网路的搭建。

因为每次卷积后都要进行Batch Normalization操作,所以将其抽象出来为一个模块。以及每个残差块的构建。每个残差块都为3层,将输入进行两次卷积,第三层为输入和两次卷积后结果的和。

卷积BN模块代码

  1. class Conv_Bn_Activation(nn.Module):
  2.     def __init__(self, in_channels, out_channels, kernel_size, stride, activation, bn=True, bias=False):
  3.         super().__init__()
  4.         # N = (W − F + 2P )/S+1步长为1时图片卷积后的尺寸不变
  5.         #步长为2时图片卷积后的尺寸减半
  6.         pad = (kernel_size - 1) // 2
  7.         self.conv = nn.ModuleList()
  8.         if bias:
  9.             self.conv.append(nn.Conv2d(in_channels, out_channels, kernel_size, stride, pad))
  10.         else:
  11.             self.conv.append(nn.Conv2d(in_channels, out_channels, kernel_size, stride, pad, bias=False))
  12.         if bn:
  13.             self.conv.append(nn.BatchNorm2d(out_channels))
  14.         if activation == "mish":
  15.             self.conv.append(Mish())
  16.         elif activation == "relu":
  17.             self.conv.append(nn.ReLU(inplace=True))
  18.         elif activation == "leaky":
  19.             self.conv.append(nn.LeakyReLU(0.1, inplace=True))
  20.         elif activation == "linear":
  21.             pass
  22.         else:
  23.             print("activate error !!! {} {} {}".format(sys._getframe().f_code.co_filename,
  24.                                                        sys._getframe().f_code.co_name, sys._getframe().f_lineno))
  25.     def forward(self, x):
  26.         for l in self.conv:
  27.             x = l(x)
  28.         return x

将真实框和预选框之间进行IoU计算,将真实框和预选框对应起来,每个真实框与和其Iou值最大的预选框所对应,得到target数据,与预测数据output之间进行loss计算。

  1. loss_xy += F.binary_cross_entropy(input=output[..., :2], target=target[..., :2],weight=tgt_scale * tgt_scale, reduction='sum')
  2. loss_wh += F.mse_loss(input=output[..., 2:4], target=target[..., 2:4], reduction='sum') / 2
  3. loss_obj += F.binary_cross_entropy(input=output[..., 4], target=target[..., 4], reduction='sum')
  4. loss_cls += F.binary_cross_entropy(input=output[..., 5:], target=target[..., 5:], reduction='sum')
  5. loss = loss_xy + loss_wh + loss_obj + loss_cls

3.2.2   迁移学习模型加载

由于目标检测coco数据集数量还是较少,与用于分类的ImageNet数量相比差距很多。于是先在ImageNet上训练模型的前一段,作为目标检测的初始参数,从而达到迁移学习。本次实验下载的是论文中作者已经预训练好的权重模型darknet.pth。

代码:

  1. _model = nn.Sequential(self.down1, self.down2, self.down3, self.down4, self.down5, self.neek)
  2. pretrained_dict = torch.load(yolov4weight)
  3. model_dict = _model.state_dict()
  4. #  过滤掉不需要的参数
  5. pretrained_dict = {k1: v for (k, v), k1 in zip(pretrained_dict.items(), model_dict)}
  6.            
  7. model_dict.update(pretrained_dict)
  8. _model.load_state_dict(model_dict)

四、结果分析

4.1:推理阶段效果

输入图片进行测试

图七:推理左图为输入图片,右图为输出图片。

4.2  训练阶段效果

输入命令

tensorboard.py --logdir=log

可视化查看loss的下降效果

 图九:训练损失函数

将训练好的模型加载,输入图片进行推理测试

D:/cv/yolo4/pytorch-YOLOv4/models.py 3 checkpoints/Yolov4_epoch200.pth data/test.jpg 608 608

五、结语

通过本次复现实现,更加入深入的了解了一阶段目标检测,特别是YOLO系列的一步步改进。YOLOv4论文中也做了大量的实验,通过此论文了解了很多实验技巧,网路的残差连接以融合特征,学习率的动态改变,新的激活函数等通用的技巧,还学习到YOLOv4中的loss的一步步修改变形和为什么要如此变化。理解预选框的作用和loss的设计,对将此通用目标检测算法用到特定任务上有了一定的经验。了解使用了Netron、tensorboard等可视化图形工具,使得网路模型可视化,理解起来更加清晰(完整的网路模型图见附件)。训练过程可视化,可以清晰的看见loss的变化,便于更好的调整。

六、参考文献

1.Bochkovskiy, A., Wang, C.-Y., Liao, H.-Y.M., 2020. YOLOv4: Optimal Speed and Accuracy of Object Detection. CoRR abs/2004.10934.

2.Huang, Z., Wang, J., 2019. DC-SPP-YOLO: Dense Connection and Spatial Pyramid Pooling Based YOLO for Object Detection. CoRR abs/1903.08589.

3.Lin, T.-Y., Dollár, P., Girshick, R.B., He, K., Hariharan, B., Belongie, S.J., 2017. Feature Pyramid Networks for Object Detection., in: 2017 IEEE Conference on Computer Vision and Pattern Recognition, CVPR 2017, Honolulu, HI, USA, July 21-26, 2017. pp. 936–944. https://doi.org/10.1109/CVPR.2017.106

4.Lin, T.-Y., Goyal, P., Girshick, R., He, K., Dollar, P., 2020. Focal Loss for Dense Object Detection. IEEE Trans. Pattern Anal. Mach. Intell. 42, 318–327. Focal Loss for Dense Object Detection | IEEE Journals & Magazine | IEEE Xplore

5.Liu, S., Qi, L., Qin, H., Shi, J., Jia, J., 2018. Path Aggregation Network for Instance Segmentation., in: 2018 IEEE Conference on Computer Vision and Pattern Recognition, CVPR 2018, Salt Lake City, UT, USA, June 18-22, 2018. pp. 8759–8768.

6.Misra, D., 2020. Mish: A Self Regularized Non-Monotonic Activation Function., in: 31st British Machine Vision Conference 2020, BMVC 2020, Virtual Event, UK, September 7-10, 2020.

7.Zheng, Z., Wang, P., Liu, W., Li, J., Ye, R., Ren, D., 2020. Distance-IoU Loss: Faster and Better Learning for Bounding Box Regression., in: The Thirty-Fourth AAAI Conference on Artificial Intelligence, AAAI 2020, The Thirty-Second Innovative Applications of Artificial Intelligence Conference, IAAI 2020, The Tenth AAAI Symposium on Educational Advances in Artificial Intelligence, EAAI 2020, New York, NY, USA, February 7-12, 2020. pp. 12993–13000.

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/128659?site
推荐阅读
相关标签
  

闽ICP备14008679号