基于卷积神经网络的口罩佩戴识别与检测

摘要

MobileNetV2模型概述与识别结果分析

1.基础理论--深度可分离卷积(DepthWise操作)

2.MobileNetV1遗留的问题

3.MobileNet V2的创新点

4.本文网络结构及代码实现

5. 实验结果分析

应用:口罩检测识别

结束

参考文献

摘要

在当前情况下,没有高效的口罩检测应用程序和相关高质量标注数据集,因此想对运输、人口稠密地区,居民区,大型商场实现自动口罩佩戴检测是一个亟需解决且非常有意义的问题,而且,由于缺少“ 带口罩”图像的大型数据集,因此该任务更加具有挑战性。目标检测是复杂的一个过程,首先需要有训练数据集,但是如何在没有采用labelimg软件进行标注数据集的数据上进行训练模型从而达到口罩佩戴识别的效果呢?本文将转换思路,在前人已经做好人脸检测的基础上完成对口罩佩戴识别与检测。为何是识别与检测:一是在佩戴和没有佩戴口罩数据集上进行训练MobileNetV2模型,以达到对图标是否佩戴口罩进行识别。二是基于已经训练好的模型参数(既是能够进行人脸检测的模型参数,如:res10_300x300_ssd_iter_140000.caffemodel和deploy.prototxt)能够选择出人脸边框图像,然后再进行二分类任务,识别出人脸是否佩带了口罩。因此,本文将完成以下任务:

MobileNetV2模型概述与识别结果分析

MobileNet V2 是对 MobileNet V1 的改进,同样是一个轻量级卷积神经网络。

1.基础理论--深度可分离卷积(DepthWise操作)

标准的卷积过程可以看上图,一个2×2的卷积核在卷积时,对应图像区域中的所有通道均被同时考虑,问题在于,为什么一定要同时考虑图像区域和通道?我们为什么不能把通道和空间区域分开考虑?

Xception网络就是基于以上的问题发明而来。我们首先对每一个通道进行各自的卷积操作,有多少个通道就有多少个过滤器。得到新的通道feature maps之后,这时再对这批新的通道feature maps 进行标准的1×1跨通道卷积操作。这种操作被称为“DepthWise convolution”,缩写“DW”。

这种操作是相当有效的,在 ImageNet 1000 类分类任务中已经超过了InceptionV3 的表现,而且也同时减少了大量的参数,我们来算一算,假设输入通道数为3,要求输出通道数为256,两种做法:

1. 直接接一个3×3×256的卷积核,参数量为:3×3×3×256 = 6,912

2. DW 操作,分两步完成,参数量为:3×3×3 + 3×1×1×256 = 795,又把参数量降低到九分之一!

因此,一个 Depthwise 操作比标准的卷积操作降低不少的参数量,同时论文中指出这个模型得到了更好的分类效果。

2.MobileNetV1遗留的问题

1、结构问题:

MobileNet V1 的结构其实非常简单,论文里是一个非常复古的直筒结构,类似于VGG一样。这种结构的性价比其实不高,后续一系列的 ResNet, DenseNet 等结构已经证明通过复用图像特征,使用 Concat/Eltwise+ 等操作进行融合,能极大提升网络的性价比。

2、Depthwise Convolution的潜在问题:

Depthwise Conv确实是大大降低了计算量,而且N×N Depthwise +1×1PointWise的结构在性能上也能接近N×N Conv。在实际使用的时候,我们发现Depthwise部分的kernel比较容易训废掉:训练完之后发现Depthwise训出来的kernel有不少是空的。当时我们认为,Depthwise每个kernel dim相对于普通Conv要小得多,过小的kernel_dim, 加上ReLU的激活影响下,使得神经元输出很容易变为0,所以就学废了。ReLU对于0的输出的梯度为0,所以一旦陷入0输出,就没法恢复了。我们还发现,这个问题在定点化低精度训练的时候会进一步放大。

3.MobileNet V2的创新点

1、Inverted Residual Block

MobileNet V1没有很好的利用Residual Connection,而Residual Connection通常情况下总是好的,所以MobileNet V2加上。

先用1x1降通道过ReLU,再3x3空间卷积过ReLU,再用1x1卷积过ReLU恢复通道,并和输入相加。之所以要1x1卷积降通道,是为了减少计算量,不然中间的3x3空间卷积计算量太大。所以Residual block是沙漏形,两边宽中间窄。

但是,现在我们中间的3x3卷积变为了Depthwise的了,计算量很少了,所以通道可以多一点,效果更好,所以通过1x1卷积先提升通道数,再Depthwise的3x3空间卷积,再用1x1卷积降低维度。两端的通道数都很小,所以1x1卷积升通道或降通道计算量都并不大,而中间通道数虽然多,但是Depthwise 的卷积计算量也不大。作者称之为Inverted Residual Block,两边窄中间宽,像柳叶,较小的计算量得到较好的性能。

2、ReLU6

首先说明一下 ReLU6,卷积之后通常会接一个 ReLU 非线性激活,在 MobileNet V1 里面使用 ReLU6,ReLU6 就是普通的ReLU但是限制最大输出值为 6,这是为了在移动端设备 float16/int8 的低精度的时候,也能有很好的数值分辨率,如果对 ReLU 的激活范围不加限制,输出范围为0到正无穷,如果激活值非常大,分布在一个很大的范围内,则低精度的float16/int8无法很好地精确描述如此大范围的数值,带来精度损失。

本文提出,最后输出的 ReLU6 去掉,直接线性输出,理由是:ReLU 变换后保留非0区域对应于一个线性变换,仅当输入低维时ReLU 能保留所有完整信息。

在看 MobileNet V1的时候,我就疑问为什么没有把后面的 ReLU去掉,因为Xception已经实验证明了 Depthwise 卷积后再加ReLU 效果会变差,作者猜想可能是 Depthwise 输出太浅了, 应用 ReLU会带来信息丢失,而 MobileNet V1还引用了 Xception 的论文,但是在 Depthwise 卷积后面还是加了ReLU。在 MobileNet V2 这个 ReLU终于去掉了,并用了大量的篇幅来说明为什么要去掉。

总之,去掉最后那个 ReLU,效果更好。

4.本文网络结构及代码实现

这样,我们就得到 MobileNet V2的基本结构了,左边是 V1 的没有 Residual Connection并且带最后的 ReLU,右边是 V2 的带Residual Connection 并且去掉了最后的 ReLU:

 

网络的整体配置结构如下:

baseModel = MobileNetV2(weights="imagenet", include_top=False,
	input_tensor=Input(shape=(224, 224, 3)))

# construct the head of the model that will be placed on top of the
# the base model
headModel = baseModel.output
headModel = AveragePooling2D(pool_size=(7, 7))(headModel)
headModel = Flatten(name="flatten")(headModel)
headModel = Dense(128, activation="relu")(headModel)
headModel = Dropout(0.5)(headModel)
headModel = Dense(2, activation="softmax")(headModel)

# place the head FC model on top of the base model (this will become
# the actual model we will train)
model = Model(inputs=baseModel.input, outputs=headModel)
model.summary()

大家可以自己通过model.summary()函数自行去看模型的参数个数及相关模型具体结构。

5. 实验结果分析

训练过程:

分割数据集:

  • with_mask:2165张图片
  • no_with_mask:1930张图片
(trainX, testX, trainY, testY) = train_test_split(data, labels,
	test_size=0.20, stratify=labels, random_state=42)

训练损失函数及准确率图像: 

输出准确率矩阵:

应用:口罩检测识别

接着,本文打算使用MobileNet V2保存的训练参数和res10_300x300_ssd_iter_140000.caffemodel及deploy.prototxt来检测识别视频中的人是否佩戴了口罩。为此,首先,我们需要实现人脸检测。在此使用res10_300x300_ssd_iter_140000.caffemodel及deploy.prototxt来检测面部特征。最后,使用OpenCV库运行无限循环以使用我们的电脑摄像头,当检测出面部特征后,将其转换为224x224图片,将其传递给训练MobileNet V2模型参数进行预测面部是否带有遮罩。其实现代码如下:

prototxtPath = r"face_detector\deploy.prototxt"
weightsPath = r"face_detector\res10_300x300_ssd_iter_140000.caffemodel"
faceNet = cv2.dnn.readNet(prototxtPath, weightsPath)
maskNet = load_model("mask_detector.model")
print("[INFO] starting video stream...")
vs = VideoStream(src=0).start()
while True:
	frame = vs.read()
	frame = imutils.resize(frame, width=400)
	(locs, preds) = detect_and_predict_mask(frame, faceNet, maskNet)
	for (box, pred) in zip(locs, preds):
		(startX, startY, endX, endY) = box
		(mask, withoutMask) = pred
		label = "Mask" if mask > withoutMask else "No Mask"
		color = (0, 255, 0) if label == "Mask" else (0, 0, 255)
		label = "{}: {:.2f}%".format(label, max(mask, withoutMask) * 100)
		cv2.putText(frame, label, (startX, startY - 10),
			cv2.FONT_HERSHEY_SIMPLEX, 0.45, color, 2)
		cv2.rectangle(frame, (startX, startY), (endX, endY), color, 2)
	cv2.imshow("Frame", frame)
	key = cv2.waitKey(1) & 0xFF
	if key == ord("q"):
		break
cv2.destroyAllWindows()
vs.stop()

放几张图片的输入输出:

 

 

结束

2019年底见证了冠状病毒疾病(COVID-19)的爆发,即使在2020年,该疾病仍就造成数百万人生活困难和不便。随着世界从大流行病中恢复正常状态,在这次疫情中有研究证明,戴上口罩可大大降低病毒传播的风险并提供保护。但是,手动跟踪此策略的实施是不可行的,因此有必要引入深度学习方法实现智能检测识别。我们基于目前没有标注好的口罩检测数据集,本文做了两个工作完成口罩佩戴检测识别:一是在佩戴和没有佩戴口罩数据集上进行训练MobileNetV2模型,以达到对图标是否佩戴口罩进行识别。二是基于已经训练好的模型参数(既是能够进行人脸检测的模型参数,如:res10_300x300_ssd_iter_140000.caffemodel和deploy.prototxt)能够选择出人脸边框图像,然后再进行二分类任务,识别出人脸是否佩带了口罩。该方法能够检测佩戴和未佩戴口罩的人,且该方法可以与安装的摄像机集成使用。

参考文献

1. https://arxiv.org/ftp/arxiv/papers/2009/2009.07627.pdf

2.Kumar M , Saluja K K , Sachdeva M , et al. Face Mask Detection Using YOLOv3 and Faster R-CNN Models: COVID-19 Environment[J]. Multimedia Tools and Applications, 2021.

3. 基于MobileNetV2的目标检测算法研究与应用[D]. 2020.

4. https://arxiv.org/abs/18

 

 

 

版权声明:本文为CSDN博主「就是求关注」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_40651515/article/details/114810423

就是求关注

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐