HSAS-H4o5F / APP

智慧社区 APP
GNU General Public License v3.0
1 stars 1 forks source link

身份ID:人脸识别 #32

Open xfqwdsj opened 1 year ago

xfqwdsj commented 1 year ago
### 人脸识别开发
- [x] 阅读材料
- [x] 确认方案
- [ ] https://github.com/HSAS-H4o5F/Backend/issues/2
- [ ] https://github.com/HSAS-H4o5F/APP/issues/35

计划方案

采用前端调用摄像头,通过 WebSocket 协议 (或 RTMP 等实时视频协议,具体待定) (确认使用 WebSocket)与后端建立连接。后端从实时视频流中提取帧,进行人脸检测、注册训练和识别操作,将结果返回前端。

方案(暂定)

前端使用 camera 包调用摄像头,提取帧后以二进制 Blob 格式通过 Socket.IO 发送到后端。

由于 camera 包限制,目前只能在移动平台上实现该功能。未来将考虑自行开发其他平台上的实现。

后端增加一个 Socket.IO 服务器接收前端发送的帧,通过 python-shell 发送到 Python 脚本。

图像处理采用 OpenCV,采用的模型与数据集如下:

未来可以迁移到其他的处理方法。

参考资料

参考仓库

所需依赖

camera 包暂无 Linux 和 macOS 支持,且只能在 Android 和 iOS 上传输视频流。

flutter/flutter#41710 | flutter/flutter#41708

xfqwdsj commented 1 year ago

Real-Time Face-Recognition using OpenCV & Face-Recognition | https://medium.com/analytics-vidhya/real-time-face-recognition-using-opencv-face-recog-507d355e0018 | 作者 https://medium.com/@pavankunchalapk

嘿,这是我在 Medium 上撰写的第一篇文章,正如您所看到的标题,这篇文章是关于人脸识别的,让我们开始吧。 您可以在[**这里**](https://github.com/Pavankunchala/Deep-Learning/blob/master/Face-Recognisation/face_recog_live.py)从我的 Github 仓库中查看代码。 # **导入所需库** 让我们开始导入需要的库,正如您猜到的,我们需要 [**OpenCV**](https://pypi.org/project/opencv-python/)(您可以从该链接安装它)和numpy,以及这个代码最重要的库 [**face_recognition**](https://pypi.org/project/face-recognition/)。 ```py # https://gist.github.com/Pavankunchala/a82345e8e1f6059c2681b4debc224ddf#file-import-py import face_recognition import cv2 import numpy as np ``` **访问摄像头并加载样本图像** 我们可以使用 `VideoCapture(0)` 来启动摄像头,然后开始加载您想要识别的图像或其他图像,并可以使用 face_recognition 库来获取它的编码。 ```py # https://gist.github.com/Pavankunchala/ebfdf04e26edf64a269106808964deb7#file-acces-py # Get a reference to webcam #0 (the default one) video_capture = cv2.VideoCapture(0) # Load a sample picture and learn how to recognize it. pavan_image = face_recognition.load_image_file("Pavan-1.jpg") pavan_face_encoding = face_recognition.face_encodings(pavan_image)[0] # Load a second sample picture and learn how to recognize it. obama_image = face_recognition.load_image_file("obama.jpg") obama_face_encoding = face_recognition.face_encodings(obama_image)[0] ``` **创建已知编码数组** 正如上面的标题所述,创建一个数组(有时候就是这么简单),并初始化一些变量。 ```py # https://gist.github.com/Pavankunchala/9b82aef31439f93d604b293edf18b42d#file-array-py # Create arrays of known face encodings and their names known_face_encodings = [ obama_face_encoding, pavan_face_encoding ] known_face_names = [ "Barack Obama", "Pavan Kunchala" ] # Initialize some variables face_locations = [] face_encodings = [] face_names = [] process_this_frame = True ``` ## 读取,调整大小和处理 现在,使用 `while True` 读取帧,调整其大小(使其能够实时运行),并进行处理,以便我们可以比较面部编码。我使用了最小距离公式,这样我们可以轻松比较人脸,当然还有比这更好的方法。可以自己尝试进行实验。 ```py # https://gist.github.com/Pavankunchala/9ee7bf00b1574abf71ebaf7614077cb3#file-process-py while True: # Grab a single frame of video ret, frame = video_capture.read() # Resize frame of video to 1/4 size for faster face recognition processing small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) # Convert the image from BGR color (which OpenCV uses) to RGB color (which face_recognition uses) rgb_small_frame = small_frame[:, :, ::-1] # Only process every other frame of video to save time if process_this_frame: # Find all the faces and face encodings in the current frame of video face_locations = face_recognition.face_locations(rgb_small_frame) face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations) face_names = [] for face_encoding in face_encodings: # See if the face is a match for the known face(s) matches = face_recognition.compare_faces(known_face_encodings, face_encoding) name = "Unknown" # # If a match was found in known_face_encodings, just use the first one. # if True in matches: # first_match_index = matches.index(True) # name = known_face_names[first_match_index] # Or instead, use the known face with the smallest distance to the new face face_distances = face_recognition.face_distance(known_face_encodings, face_encoding) best_match_index = np.argmin(face_distances) if matches[best_match_index]: name = known_face_names[best_match_index] face_names.append(name) process_this_frame = not process_this_frame # Display the results for (top, right, bottom, left), name in zip(face_locations, face_names): # Scale back up face locations since the frame we detected in was scaled to 1/4 size top *= 4 right *= 4 bottom *= 4 left *= 4 # Draw a box around the face cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2) # Draw a label with a name below the face cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED) font = cv2.FONT_HERSHEY_DUPLEX cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1) # Display the resulting image cv2.imshow('Video', frame) # Hit 'q' on the keyboard to quit! if cv2.waitKey(1) & 0xFF == ord('q'): break # Release handle to the webcam video_capture.release() cv2.destroyAllWindows() ``` 这就是结尾(至少目前是这样的)。 **附言:** 我知道有很多地方可以改进我的解释,尤其是代码部分,我会尽快更新它们。(有关更多信息,请参见英文原文) 祝您有美好的一天。

返回

xfqwdsj commented 1 year ago

Real-time Face detection | Face Mask Detection using OpenCV | https://www.mygreatlearning.com/blog/real-time-face-detection/ | 作者 Great Learning Team

在本文中,我们将了解如何使用OpenCV[实时检测人脸](https://www.mygreatlearning.com/academy/learn-for-free/courses/face-detection-with-opencv-in-python/?gl_blog_id=17581)。在从网络摄像头流中检测到人脸后,我们将保存包含人脸的帧。稍后,我们将把这些帧(图像)传递给我们的口罩检测分类器,以判断人是否戴口罩。 我们还可以学习到如何使用[Tensorflow和Keras](https://www.mygreatlearning.com/academy/learn-for-free/courses/introduction-to-tensorflow-and-keras/?gl_blog_id=17581)创建自定义口罩检测器,但您可以跳过这部分,因为我将在下面附上已训练好的模型文件,您可以下载并使用。 ## 什么是人脸检测? 人脸检测的目标是确定图像或视频中是否有任何人脸。如果存在多个人脸,则每个人脸都由一个边界框包围,因此我们知道人脸的位置。 人脸检测算法的主要目标是准确高效地确定图像或视频中人脸的存在和位置。这些算法分析数据的视觉内容,搜索与面部特征相对应的模式和特征。通过使用各种技术,如机器学习、图像处理和模式识别,人脸检测算法旨在区分视觉数据中的面部与其他对象或背景元素。 由于人脸有很多可以改变的变量,例如面部表情、方向、光照条件以及太阳镜、围巾、口罩等部分遮挡,因此对人脸进行建模较为困难。检测结果提供了人脸位置参数,可以以各种形式呈现,例如覆盖面部中央部分的矩形、眼睛中心或标志点,包括眼睛、鼻子和嘴巴的角点、眉毛、鼻孔等。 ## 人脸检测方法 人脸检测有两种主要方法: 1. 基于特征的方法 2. 基于图像的方法 #### 基于特征的方法 通常通过其独特的特征来识别对象。人脸有许多特征,可以在人脸和许多其他对象之间进行识别。它通过提取结构特征(如眼睛、鼻子、嘴巴等)来定位人脸,然后使用这些特征来检测人脸。通常会使用某种统计分类器来将面部和非面部区域分开。此外,人脸具有特定的纹理,可以用于区分面部和其他对象。此外,特征的边缘可以帮助检测面部上的对象。在接下来的部分中,我们将使用[OpenCV教程](https://www.mygreatlearning.com/academy/learn-for-free/courses/opencv-tutorial?gl_blog_id=17581)来实现基于特征的方法。 #### 基于图像的方法 一般来说,基于图像的方法依赖于统计分析和机器学习技术,以找到人脸和非人脸图像的相关特征。学习到的特征以分布模型或判别函数的形式存在,因此用于人脸检测。在这种方法中,我们使用不同的算法,如神经网络、隐马尔可夫模型(HMM)、[支持向量机](https://www.mygreatlearning.com/academy/learn-for-free/courses/support-vector-machines/?gl_blog_id=17581)(SVM)、[AdaBoost学习](https://www.mygreatlearning.com/blog/adaboost-algorithm/)。在接下来的部分,我们将看到如何使用MTCNN或多任务级联卷积[神经网络](https://www.mygreatlearning.com/blog/types-of-neural-networks/)(Multi-Task Cascaded Convolutional Neural Network)进行人脸检测,这是一种基于图像的人脸检测方法。 ## 人脸检测算法 使用特征为基础的方法之一是[Viola-Jones算法](https://www.mygreatlearning.com/blog/viola-jones-algorithm),我在这里会简要讨论它。如果您想详细了解,请查看这篇文章:使用Viola Jones算法进行人脸检测。 **Viola-Jones**算法是2001年提出的,由两位计算机视觉研究人员Paul **Viola**和Michael **Jones**在他们的论文“Rapid Object Detection using a Boosted Cascade of Simple Features”中命名。尽管这是一个过时的框架,但Viola-Jones相当强大,其应用在实时人脸检测中非常显著。该算法在训练时非常缓慢,但可以以令人印象深刻的速度实时检测人脸。 给定一张图像(该算法适用于灰度图像),该算法查看许多较小的子区域,并通过在每个子区域中寻找特定特征来寻找人脸。它需要检查许多不同的位置和比例,因为一张图像可能包含许多不同大小的人脸。Viola和Jones在此算法中使用Haar-like特征来检测人脸。 ## 人脸识别 人脸检测和人脸识别经常互相混用,但它们是不同的。实际上,人脸检测只是人脸识别的一部分。 人脸识别是一种使用人脸来识别或验证个体身份的方法。有各种算法可以进行人脸识别,但其准确性可能有所不同。在这里,我将描述如何使用深度学习进行人脸识别。 实际上,这里有一篇文章《Python人脸识别》(Face Recognition Python),展示了如何实现人脸识别。 **[使用Python进行人脸检测](https://www.mygreatlearning.com/academy/learn-for-free/courses/face-recognition-using-python/?gl_blog_id=17581)** 正如之前提到的,我们将看到如何使用基于图像的方法进行人脸检测。MTCNN或多任务级联卷积神经网络无疑是最受欢迎且最准确的人脸检测工具之一,它是基于[深度学习](https://www.mygreatlearning.com/deep-learning/free-courses/?gl_blog_id=17581)架构的,具体由三个神经网络(P-Net、R-Net和O-Net)级联连接而成。 因此,让我们看看如何在Python中使用这个算法来实时检测人脸。首先,您需要安装包含可以检测人脸的训练模型的MTCNN库。 ```sh pip install mtcnn ``` 现在让我们看看如何使用MTCNN: ```py from mtcnn import MTCNN import cv2 detector = MTCNN() # 加载视频 video_capture = cv2.VideoCapture(0) while (True): ret, frame = video_capture.read() frame = cv2.resize(frame, (600, 400)) boxes = detector.detect_faces(frame) if boxes: box = boxes[0]['box'] conf = boxes[0]['confidence'] x, y, w, h = box[0], box[1], box[2], box[3] if conf > 0.5: cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 255, 255), 1) cv2.imshow("帧", frame) if cv2.waitKey(25) & 0xFF == ord('q'): break video_capture.release() cv2.destroyAllWindows() ``` ## 使用OpenCV进行人脸检测 在本节中,我们将通过网络摄像头从实时视频流中[使用OpenCV进行人脸检测](https://www.mygreatlearning.com/academy/learn-for-free/courses/face-detection-with-opencv-in-python?gl_blog_id=17581)。 如您所知,视频基本上由帧组成,这些帧是静止图像。我们对视频中的每一帧进行人脸检测。因此,在静态图像中检测人脸和在实时视频流中检测人脸之间几乎没有太大区别。 我们将使用Haar级联算法,也称为Viola-Jones算法,来检测人脸。它基本上是一种用于在图像或视频中识别对象的机器学习目标检测算法。在OpenCV中,我们有几个经过训练的Haar级联模型,这些模型保存为XML文件。我们将使用“haarcascade_frontalface_alt2.xml”文件在本项目中。现在让我们开始编写代码。 第一步是找到“haarcascade_frontalface_alt2.xml”文件的路径。我们使用Python语言的os模块来完成这个任务。 ```py import os cascPath = os.path.dirname(cv2.__file__) + "/data/haarcascade_frontalface_alt2.xml" ``` 接下来的步骤是加载我们的分类器。将上述XML文件的路径作为参数传递给OpenCV的`CascadeClassifier()`方法。 ```py faceCascade = cv2.CascadeClassifier(cascPath) ``` 在加载分类器之后,让我们使用这个简单的OpenCV一行代码打开网络摄像头。 ```py video_capture = cv2.VideoCapture(0) ``` 接下来,我们需要从网络摄像头流中获取帧,我们使用`read()`函数来完成这个任务。我们在无限循环中使用它以获取所有帧,直到我们想要关闭流。 ```py while True: # 逐帧捕获 ret, frame = video_capture.read() ``` `read()`函数返回: 1. 实际读取的视频帧(每次循环一帧) 2. 返回码 返回码告诉我们是否已经读取完所有帧,如果我们正在从文件中读取,这会发生。这在从网络摄像头读取时并不重要,因为我们可以无限制地记录,所以我们会忽略它。 对于这个特定的分类器,我们需要将帧转换为灰度。 ```py gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) ``` `faceCascade`对象有一个`detectMultiScale()`方法,它接收一个帧(图像)作为参数,并在图像上运行分类器级联。MultiScale一词表示该算法在图像的多个尺度下查看子区域,以检测不同大小的人脸。 ```py faces = faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(60, 60), flags=cv2.CASCADE_SCALE_IMAGE) ``` 让我们仔细看看这个函数的参数: - `scaleFactor` – 指定在每个图像尺度上缩小图像尺寸的程度的参数。通过重新调整输入图像,您可以将较大的人脸调整为较小的人脸,使其可以被算法检测到。对于这个参数,1.05是一个很好的可能值,这意味着您使用较小的步长进行调整大小,即将大小减小5%,增加找到与模型匹配的检测大小的机会。 - `minNeighbors` – 指定每个候选矩形应该具有多少个相邻的矩形以保留它的参数。该参数将影响检测到的人脸的质量。较大的值会导致更少的检测,但质量更高。3~6是一个不错的值。 - `flags` – 操作模式。 - `minSize` – 最小可能对象大小。小于此大小的对象将被忽略。 变量`faces`现在包含目标图像的所有检测结果。检测结果保存为像素坐标。每个检测由其左上角坐标和包围检测到的人脸的矩形的宽度和高度定义。 为了显示检测到的人脸,我们将在其上绘制一个矩形。OpenCV的`rectangle()`在图像上绘制矩形,它需要知道左上角和右下角的像素坐标。坐标指示图像中的像素行和列。我们可以从变量`face`中轻松获取这些坐标。 ```py for (x,y,w,h) in faces: cv2.rectangle(frame, (x, y), (x + w, y + h),(0,255,0), 2) ``` `rectangle()`接受以下参数: - 原始图像。 - 检测的左上点的坐标。 - 检测的右下点的坐标。 - 矩形的颜色(一个元组,定义红色、绿色和蓝色的量(0-255)。在我们的情况下,我们将绿色设为255,其余设为零。 - 矩形线的厚度。 接下来,我们只需显示结果帧,并设置一种退出这个无限循环并关闭视频流的方法。通过按下q键,我们可以在这里退出脚本。 ```py cv2.imshow('Video', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break ``` 接下来的两行只是为了清理和释放图片。 ```py video_capture.release() cv2.destroyAllWindows() ``` 以下是完整的代码。 ```py import cv2 import os cascPath = os.path.dirname( cv2.__file__) + "/data/haarcascade_frontalface_alt2.xml" faceCascade = cv2.CascadeClassifier(cascPath) video_capture = cv2.VideoCapture(0) while True: # 逐帧捕获 ret, frame = video_capture.read() gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(60, 60), flags=cv2.CASCADE_SCALE_IMAGE) for (x,y,w,h) in faces: cv2.rectangle(frame, (x, y), (x + w, y + h),(0,255,0), 2) # 显示结果帧 cv2.imshow('视频', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break video_capture.release() cv2.destroyAllWindows() ``` ## 创建一个识别戴口罩的模型 在本节中,我们将创建一个分类器,可以区分戴口罩和不戴口罩的人脸。如果您想跳过这部分,这里是一个[链接](https://drive.google.com/file/d/16uMH4YwdkA8sdnMlJNE7nv_tBJkX5eNe/view?usp=sharing) ,可以下载预训练模型。保存它并继续下一节,了解如何使用它在OpenCV中检测口罩。查看我们的[OpenCV课程集合](https://www.mygreatlearning.com/opencv/free-courses?gl_blog_id=17581) ,帮助您提升技能,更好地理解。 因此,为了创建这个分类器,我们需要以图像的形式获取数据。幸运的是,我们有一个包含带口罩和不带口罩的人脸图像的数据集。由于这些图像数量很少,我们不能从头开始训练神经网络。相反,我们微调一个称为MobileNetV2的预训练网络,该网络在Imagenet数据集上进行了训练。 首先,让我们导入所有必要的库。 ```py from tensorflow.keras.preprocessing.image import ImageDataGenerator from tensorflow.keras.applications import MobileNetV2 from tensorflow.keras.layers import AveragePooling2D from tensorflow.keras.layers import Dropout from tensorflow.keras.layers import Flatten from tensorflow.keras.layers import Dense from tensorflow.keras.layers import Input from tensorflow.keras.models import Model from tensorflow.keras.optimizers import Adam from tensorflow.keras.applications.mobilenet_v2 import preprocess_input from tensorflow.keras.preprocessing.image import img_to_array from tensorflow.keras.preprocessing.image import load_img from tensorflow.keras.utils import to_categorical from sklearn.preprocessing import LabelBinarizer from sklearn.model_selection import train_test_split from imutils import paths import matplotlib.pyplot as plt import numpy as np import os ``` 接下来的步骤是读取所有图像,并将它们分配给某个列表。在这里,我们获取与这些图像相关联的所有路径,然后根据路径标记它们。请记住,我们的数据集包含两个文件夹,即“with_masks”和“without_masks”。因此,我们可以通过从路径中提取文件夹名称来轻松获取标签。此外,我们对图像进行预处理并将其调整为224x224尺寸。 ```py imagePaths = list(paths.list_images('/content/drive/My Drive/dataset')) data = [] labels = [] # 遍历图像路径 for imagePath in imagePaths: # 从文件名中提取类别标签 label = imagePath.split(os.path.sep)[-2] # 加载输入图像(224x224)并进行预处理 image = load_img(imagePath, target_size=(224, 224)) image = img_to_array(image) image = preprocess_input(image) # 更新数据和标签列表 data.append(image) labels.append(label) # 将数据和标签转换为NumPy数组 data = np.array(data, dtype="float32") labels = np.array(labels) ``` 接下来的步骤是加载预训练模型并根据我们的问题进行自定义。因此,我们只需移除此预训练模型的顶层,并添加自己的几层。正如您所看到的,最后一层有两个节点,因为我们只有两个输出。这称为迁移学习。 ```py baseModel = MobileNetV2(weights="imagenet", include_top=False, input_shape=(224, 224, 3)) # 构建放置在基本模型顶部的模型头部 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) # 将头部全连接模型放置在基本模型顶部(这将成为我们将要训练的实际模型) model = Model(inputs=baseModel.input, outputs=headModel) # 遍历基本模型中的所有层,并冻结它们,以便它们在第一次训练过程中不会更新 for layer in baseModel.layers: layer.trainable = False ``` 现在我们需要将标签转换为独热编码(one-hot encoding)。之后,我们将数据分为训练集和测试集进行评估。另外,下一步是数据增强,这显著增加了可用于训练模型的数据的多样性,而无需实际收集新数据。数据增强技术,如裁剪、旋转、错切和水平翻转,通常用于训练大型神经网络。 ```py lb = LabelBinarizer() labels = lb.fit_transform(labels) labels = to_categorical(labels) # 使用80%的数据进行训练,剩余20%进行测试,将数据划分为训练和测试集 (trainX, testX, trainY, testY) = train_test_split(data, labels, test_size=0.20, stratify=labels, random_state=42) # 为数据增强构建训练图像生成器 aug = ImageDataGenerator( rotation_range=20, zoom_range=0.15, width_shift_range=0.2, height_shift_range=0.2, shear_range=0.15, horizontal_flip=True, fill_mode="nearest") ``` 接下来的步骤是编译模型并在增强数据上进行训练。 ```py INIT_LR = 1e-4 EPOCHS = 20 BS = 32 print("[INFO] 编译模型...") opt = Adam(lr=INIT_LR, decay=INIT_LR / EPOCHS) model.compile(loss="binary_crossentropy", optimizer=opt, metrics=["accuracy"]) # 训练网络的头部 print("[INFO] 训练头部...") H = model.fit( aug.flow(trainX, trainY, batch_size=BS), steps_per_epoch=len(trainX) // BS, validation_data=(testX, testY), validation_steps=len(testX) // BS, epochs=EPOCHS) ``` 现在,我们的模型已经训练完毕,让我们绘制一个图表来查看其学习曲线。此外,我们将模型保存以备将来使用。这是指向保存的模型的[链接](https://drive.google.com/file/d/16uMH4YwdkA8sdnMlJNE7nv_tBJkX5eNe/view?usp=sharing)。 ```py N = EPOCHS plt.style.use("ggplot") plt.figure() plt.plot(np.arange(0, N), H.history["loss"], label="train_loss") plt.plot(np.arange(0, N), H.history["val_loss"], label="val_loss") plt.plot(np.arange(0, N), H.history["accuracy"], label="train_acc") plt.plot(np.arange(0, N), H.history["val_accuracy"], label="val_acc") plt.title("训练损失和准确率") plt.xlabel("Epoch #") plt.ylabel("Loss/Accuracy") plt.legend(loc="lower left") ``` **输出:** ![face detection](https://d1m75rqqgidzqn.cloudfront.net/wp-data/2020/07/17193710/download.png) ```py #保存训练好的模型 model.save('mask_recog_ver2.h5') ``` ## 如何进行实时口罩检测 在继续下一部分之前,请确保从此[链接](https://drive.google.com/file/d/16uMH4YwdkA8sdnMlJNE7nv_tBJkX5eNe/view?usp=sharing)下载上述模型,并将其放置在与您将要编写下面代码的Python脚本相同的文件夹中。 现在,我们的模型已经训练完毕,我们可以修改第一部分的代码,以便它可以检测人脸,并告诉我们人是否戴着口罩。 为了使我们的口罩检测模型工作,它需要人脸图像。为此,我们将使用第一部分中所示的方法检测带有人脸的帧,然后在对它们进行预处理后将其传递给我们的模型。因此,首先让我们导入所需的所有库。 ```py import cv2 import os from tensorflow.keras.preprocessing.image import img_to_array from tensorflow.keras.models import load_model from tensorflow.keras.applications.mobilenet_v2 import preprocess_input import numpy as np ``` 前几行与第一部分完全相同。唯一不同的是我们已经将预训练的口罩检测模型赋值给了变量`model`。 ```py ascPath = os.path.dirname( cv2.__file__) + "/data/haarcascade_frontalface_alt2.xml" faceCascade = cv2.CascadeClassifier(cascPath) model = load_model("mask_recog1.h5") video_capture = cv2.VideoCapture(0) while True: # 逐帧捕获 ret, frame = video_capture.read() gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(60, 60), flags=cv2.CASCADE_SCALE_IMAGE) ``` 接下来,我们定义一些列表。`faces_list`包含所有被faceCascade模型检测到的脸部,`preds`列表用于存储口罩检测模型的预测结果。 ```py faces_list=[] preds=[] ``` 另外,由于`faces`变量包含人脸所围成矩形的左上角坐标、高度和宽度,我们可以利用它来获取人脸的框架,然后对该框架进行预处理,以便将其馈送到模型进行预测。预处理步骤与第二节训练模型时遵循的步骤相同。例如,模型是在RGB图像上训练的,因此我们在这里将图像转换为RGB。 ```py for (x, y, w, h) in faces: face_frame = frame[y:y+h,x:x+w] face_frame = cv2.cvtColor(face_frame, cv2.COLOR_BGR2RGB) face_frame = cv2.resize(face_frame, (224, 224)) face_frame = img_to_array(face_frame) face_frame = np.expand_dims(face_frame, axis=0) face_frame = preprocess_input(face_frame) faces_list.append(face_frame) if len(faces_list)>0: preds = model.predict(faces_list) for pred in preds: #mask contain probabily of wearing a mask and vice versa (mask, withoutMask) = pred ``` 获取预测结果后,我们在人脸上绘制一个矩形,并根据预测结果放置一个标签。 ```py label = "戴口罩" if mask > withoutMask else "无口罩" color = (0, 255, 0) if label == "戴口罩" else (0, 0, 255) label = "{}: {:.2f}%".format(label, max(mask, withoutMask) * 100) cv2.putText(frame, label, (x, y- 10), cv2.FONT_HERSHEY_SIMPLEX, 0.45, color, 2) cv2.rectangle(frame, (x, y), (x + w, y + h),color, 2) ``` 其余步骤与第一节相同。 ```py cv2.imshow('视频', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break video_capture.release() cv2.destroyAllWindows() ``` 以下是完整的代码: ```py import cv2 import os from tensorflow.keras.preprocessing.image import img_to_array from tensorflow.keras.models import load_model from tensorflow.keras.applications.mobilenet_v2 import preprocess_input import numpy as np cascPath = os.path.dirname( cv2.__file__) + "/data/haarcascade_frontalface_alt2.xml" faceCascade = cv2.CascadeClassifier(cascPath) model = load_model("mask_recog1.h5") video_capture = cv2.VideoCapture(0) while True: # 逐帧捕获视频 ret, frame = video_capture.read() gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(60, 60), flags=cv2.CASCADE_SCALE_IMAGE) faces_list=[] preds=[] for (x, y, w, h) in faces: face_frame = frame[y:y+h,x:x+w] face_frame = cv2.cvtColor(face_frame, cv2.COLOR_BGR2RGB) face_frame = cv2.resize(face_frame, (224, 224)) face_frame = img_to_array(face_frame) face_frame = np.expand_dims(face_frame, axis=0) face_frame = preprocess_input(face_frame) faces_list.append(face_frame) if len(faces_list)>0: preds = model.predict(faces_list) for pred in preds: (mask, withoutMask) = pred label = "戴口罩" if mask > withoutMask else "无口罩" color = (0, 255, 0) if label == "戴口罩" else (0, 0, 255) label = "{}: {:.2f}%".format(label, max(mask, withoutMask) * 100) cv2.putText(frame, label, (x, y- 10), cv2.FONT_HERSHEY_SIMPLEX, 0.45, color, 2) cv2.rectangle(frame, (x, y), (x + w, y + h),color, 2) # 显示处理后的帧 cv2.imshow('视频', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break video_capture.release() cv2.destroyAllWindows() ``` 这就结束了本文,我们学习了如何实时检测人脸,并设计了一个可以检测戴口罩人脸的模型。使用这个模型,我们能够将人脸检测器修改为口罩检测器。 **更新**:我训练了另一个模型,可以将图像分类为佩戴口罩、不戴口罩和不正确佩戴口罩。这是该模型的[Kaggle笔记本链接](https://www.kaggle.com/mirzamujtaba/face-mask-detection)。您可以对其进行修改,并从那里下载模型,将其用于替代本文中训练的模型。虽然这个模型不像我们在本文中训练的模型那样高效,但它具有额外的功能,可以检测未正确佩戴口罩的情况。 如果您使用了这个模型,需要对代码进行一些微小的更改。将前面的代码替换为以下代码。 ```py #以下是在OpenCV代码中的一些小修改 for (box, pred) in zip(locs, preds): # 解包边界框和预测 (startX, startY, endX, endY) = box (mask, withoutMask, notproper) = pred # 确定要绘制边界框和文本的类别标签和颜色 if (mask > withoutMask and mask > notproper): label = "未戴口罩" elif ( withoutMask > notproper and withoutMask > mask): label = "戴口罩" else: label = "正确佩戴口罩" if label == "戴口罩": color = (0, 255, 0) elif label == "未戴口罩": color = (0, 0, 255) else: color = (255, 140, 0) # 在输出帧上显示标签和边界框矩形 label = "{}: {:.2f}%".format(label, max(mask, withoutMask, notproper) * 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) ``` 您还可以通过[Great Learning](https://www.mygreatlearning.com/)的[人工智能和机器学习课程](https://www.mygreatlearning.com/pg-program-artificial-intelligence-course?gl_blog_id=17581)进行提升。该课程提供行业领袖的指导,并且您还将有机会参与实时的行业相关项目。 如果您想提升技能或者在新领域进行探索,但又不想花费太多,我们的[免费在线课程](https://www.mygreatlearning.com/academy)是一个完美的选择。深入探索网络安全、管理、云计算、IT和软件、人工智能等激动人心的领域,获得可以使您脱颖而出的知识。无论您是技术爱好者、有志创业者还是对数字领域感兴趣,我们的课程提供了一种灵活、可访问的学习方式。

返回