本文将介绍如何开发一个交互式应用程序,利用Adam Geitgey的人脸识别框架,从摄像头或网络摄像头设备识别人脸。

为了创建一个交互式应用程序,我们将使用Tkinter,Docker将用于确保一个包含所有必要依赖项的隔离环境。本文可以作为你自己项目的起点,因为使用哪些框架和库并不重要。

了解如何通过Docker创建一个利用摄像头设备、GPU加速和深度学习框架的交互式应用程序有很多可能性。

如果只希望通过Docker运行GUI,我创建了本文,你可以按照以下内容进行操作:

https://towardsdatascience.com/empowering-docker-using-tkinter-gui-bf076d9e4974


如果你想立即运行应用程序,可以下载我的Github存储库,并按照本文末尾的“运行应用程序”部分进行操作。

阅读教程

在本文中,将介绍应用程序中的脚本,之后将介绍运行应用程序的教程。文章将按照以下顺序进行。

目录

  1. 环境

  2. 应用程序概述

  3. Docker

  4. 编程

  5. 摄像设备

  6. 计算机视觉

  7. Shell脚本

  8. 运行应用程序

  9. 结论


环境

此应用程序仅使用Linux进行了测试,但是,它的工作原理应该与其他操作系统类似,其中一些参数可能不同,例如在运行Docker时。

对于先决条件,你应该安装摄像头或网络摄像头、Docker、CUDA和CuDNN。我已使用以下方法测试了应用程序:

  • Docker 20.10.8

  • CUDA 11.4

  • CuDNN 8.2.2

  • OS:Manjaro 21.1.2 Phavo

  • GPU:NVIDIA GeForce GTX 1080 Ti

  • 摄像头设备:罗技网络摄像头C930e

目录结构

本项目的目录结构如下所示。你可以事先创建这些文件,或者直接从我的Github存储库下载所有文件。

此外,你需要在dataset目录中创建自己的目录,并插入所需的图像。在我的例子中,如下所示,我在Kasper目录中添加了四个图像。你在不同场景中为同一个人添加的图像越多,你的预测就越可靠。关于脚本,本文将介绍它们的内容。

注意:encodings.pkl将在以后自动生成。

应用程序的目录结构:


应用程序概述

该应用程序包含一个GUI,其中有一个用于显示相机设备输出的面板。此外,还有一个用于激活/禁用人脸识别的按钮。

当前打开人脸识别的应用程序。


Docker

为了创建一个安装人脸识别、OpenCV、Dlib、Python等的隔离环境,使用了以下Docker代码。

Dockerfile创建隔离环境:

FROM nvidia/cuda:11.4.1-cudnn8-devel-ubuntu20.04ARG DEBIAN_FRONTEND=noninteractive# Install dependencies
RUN apt-get update -y
RUN apt-get install -y \git \cmake \libsm6 \libxext6 \libxrender-dev \python3 \python3-pip \gcc \python3-tk \ffmpeg \libopenblas-dev \ liblapack-dev# Install dlib
RUN git clone https://github.com/davisking/dlib.git && \cd dlib && \mkdir build && \cd build && \cmake .. -DDLIB_USE_CUDA=1 -DUSE_AVX_INSTRUCTIONS=1 && \cmake --build . && \cd .. && \python3 setup.py install # Install Face Recognition and OpenCV
RUN pip3 install face_recognition opencv-pythonWORKDIR /face_recognition/app

Tkinter

为了创建一个可由用户控制的交互式GUI以启用和禁用人脸识别,使用Tkinter库。下面的代码创建了先前显示的GUI。

主脚本,用于创建GUI并允许人脸识别。

import tkinter as tk
from src.facevision import FaceVision
from src.videostream import VideoStreamif __name__ == '__main__':# Tkinter窗口root_window = tk.Tk()# Window设置root_window.title('Face Recognition')root_window.geometry('500x540')  # widthxheight+x+yroot_window.configure(background='#353535')# 摄像头可视化面板panel = tk.Label(root_window)panel.pack(side='top', fill='none')# FaceVision初始化face_vision = FaceVision()# Webcam初始化vs = VideoStream(panel=panel, face_vision=face_vision)vs.stream()# 人脸识别按钮button_face_recognition = tk.Button(root_window, text='Activate Face Recognition', command=lambda: face_vision.change_facerec_state(button_face_recognition))button_face_recognition.pack()# 主循环root_window.mainloop()

摄像设备

为了从相机设备获取图像并更新Tkinter GUI,可以使用以下脚本。

在第7行中,它使用函数VideoCapture by OpenCV,其中的参数应与你的设备相对应。默认相机id通常为0,但是,如果不起作用,可以尝试使用1或-1。

如果你希望使用视频,你应该能够用视频路径替换设备id,但可能需要进行一些其他调整。在第26行,它在一毫秒后再次调用函数本身。

import cv2
from PIL import Image, ImageTkclass VideoStream():def __init__(self, panel, face_vision):self.cap = cv2.VideoCapture(0) # 参数应该对应于你的设备self.panel = panelself.face_vision = face_visiondef stream(self):# 从相机获取图像_, frame = self.cap.read()img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)# 人脸识别img = self.face_vision.process_image(img=img)# Tkinterimg = Image.fromarray(img)tk_img = ImageTk.PhotoImage(img)self.panel.imgtk = tk_imgself.panel.configure(image=tk_img)# 再次运行self.panel.after(ms=1, func=self.stream)

计算机视觉

与大多数计算机视觉应用程序相反,在大多数计算机视觉应用程序中,你通过展示数百个类的示例来训练模型以对所需类进行分类,而在人脸识别中,你可以使用深度度量学习。

通过深度度量学习,你可以训练模型来描述所需对象,而不是预测它是哪个类。在我们的例子中,我们使用它来提供一个特征向量,一种128维编码,它使用实数来描述每个人脸。教授一个模型来描述人脸而不是预测一个特定的人是一个优势,因为如果想要识别一个新的人,就不需要对模型进行再训练。

相反,我们应该简单地保存模型可以访问的新人的编码。我们将在本文后面获得这些编码。使用框架人脸识别,我们不必从头开始训练模型,而是使用通过人脸识别提供的已经训练过的模型。如果想要进一步探索人脸识别领域,《人脸识别框架》详细阐述了这一主题:

https://medium.com/@ageitgey/machine-learning-is-fun-part-4-modern-face-recognition-with-deep-learning-c3cffc121d78

数据集与编码器

为了使模型能够识别人脸,需要一个包含人脸编码的pickle文件。要实现这一点,正如前面在“目录结构”一节中提到的,你必须在目录数据集中创建一个包含所需人员姓名的目录。之后,编码器应包含以下代码。

在这段代码中,我们递归地获取dataset目录中每个人的所有图像。通过使用人脸识别框架,我们定位人脸并为每幅图像提取编码。

构造包含数据集编码的pickle文件:

import face_recognition
import cv2
from pathlib import Path
import pickleif __name__ == '__main__':print('Starting Encoding..')data = {'names': [], 'encodings': []}# 数据集路径path = Path.cwd() / './data/dataset/'# 浏览每一张图片for file_name in path.rglob('*.jpg'):# 从数据集读取图像img = cv2.imread(str(file_name))img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)# 定位人脸face_location = face_recognition.face_locations(img, number_of_times_to_upsample=1, model='cnn')# 编码的人脸encoding = face_recognition.face_encodings(face_image=img, known_face_locations=face_location, model='small')# 保存信息data['names'].append(file_name.parent.name)data['encodings'].append(encoding)# 在pickle文件中保存编码with open('./data/encodings.pkl', 'wb') as f:pickle.dump(data, f)print('Completed Encoding!')

人脸识别

为了识别人脸,将使用以下代码。为了总结代码,它使用来自我们的相机设备的图像,检测人脸,为每个人脸提取128维编码,然后将新编码与我们的编码数据集进行比较。

为了进行比较,它会检查新编码的特征与我们编码的数据集之间的距离,如果特征的距离小于阈值参数,则该特征将获得投票。为了找到最佳匹配,我们只需选择得票最多的人。如果简单的解决方案不够,你可以实现更强大的分类器。

更具体地说,视频流为每一帧调用函数process_image,该函数完成了实现人脸识别所需的所有工作。在第43–45行中,可以调整比较的阈值参数。阈值越低,比较就越严格。此外,在第48-51行中,最高投票数也可以调整,以增加或减少严格程度。

计算机视觉部分,基于人脸识别框架:

import face_recognition
import pickle
import cv2
import numpy as npclass FaceVision():def __init__(self):# 加载编码data = pickle.loads(open('./data/encodings.pkl', 'rb').read())self.encoded_data = data['encodings']self.name_data = data['names']self.use_face_recognition = Falsedef process_image(self, img):# 检测和定位人脸face_locations = self.__locate_faces(img)# 如果没有找到人脸,返回原始图像if not face_locations:return img# 编码输入图像encodings = face_recognition.face_encodings(face_image=img, known_face_locations=face_locations, model='small')# 通过比较新的编码和之前编码的pickle文件来识别人脸self.__identify_faces(image=img, face_locations=face_locations, encodings=encodings)return imgdef __locate_faces(self, image):if self.use_face_recognition is True:# 检测人脸并接收他们的位置face_locations = face_recognition.face_locations(img=image, number_of_times_to_upsample=1, model='cnn')return face_locationsdef __identify_faces(self, image, face_locations, encodings):# 比较保存的编码和新的编码for face_bbox, encoding in zip(face_locations, encodings):# 找到匹配matches = face_recognition.compare_faces(known_face_encodings=self.encoded_data, face_encoding_to_check=encoding, tolerance=0.01)# 计算投票并找到最佳匹配votes = [np.count_nonzero(m==True) for m in matches]highest_vote = max(votes)highest_vote_idx = votes.index(highest_vote)person_match = self.name_data[highest_vote_idx]# 投票阈值,如果没有超过,投票的名字将是Unknownif highest_vote < 20:person_match = 'Unknown'# 添加可视化图像t, r, b, l = face_bboxcv2.rectangle(image, (l, t), (r, b), (0, 255, 0), 2)        cv2.putText(image, person_match, (l, t-10), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 1)def change_facerec_state(self, button):# 取反self.use_face_recognition = not self.use_face_recognition# 改变按钮的文本if self.use_face_recognition is True:button.configure(text='Disable Face Recognition')else:button.configure(text='Activate Face Recognition')

Shell脚本(警告)

为了简化操作,请创建一个shell脚本,该脚本使用以下参数运行xhost和Docker。

对于xhost,启用对所有人的访问,然后在卸载Docker容器后禁用它。在这个Docker命令中,我们共享GPU,显示GUI。

警告:如果在本地运行,则使用xhost和这些Docker参数不应成为问题。但是,如果在生产中使用,则应增强安全性,这在此处是推荐的。

自动启用/禁用xhost并运行Docker容器:

#!/bin/bash
xhost +
docker run --gpus all --device /dev/nvidia0 --device /dev/nvidia-uvm --device /dev/nvidia-uvm-tools \--device /dev/nvidiactl \-it \--rm \-e DISPLAY=$DISPLAY \-v /tmp/.X11-unix:/tmp/.X11-unix:rw \-v $(pwd):/face_recognition \--device=/dev/video0:/dev/video0 \face_recognition
xhost -

运行应用程序

  1. 构建Docker镜像:docker build -t facerecognition_gui

  2. 使shell脚本可执行:chmod +x ./run.sh

  3. 运行shell脚本:./run.sh

  4. 在Docker容器中,创建编码的数据集(确保图像位于数据集目录中的目录中):python3 encoder.py

  5. 运行应用程序:python3 gui.py

  6. 现在可以启用人脸识别。

注意:要分离/退出Docker容器,请按ctrl-D

结论

在本文中,你已经了解了如何将GUI、摄像头设备、GPU与Docker一起使用。了解如何结合这些,提供了许多可用于学术和商业目的的可能性。

此外,使用相同的策略,通过Docker共享etc设备,你应该能够利用其他库和框架,而不必经历环境问题。

☆ END ☆

如果看到这里,说明你喜欢这篇文章,请转发、点赞。微信搜索「uncle_pn」,欢迎添加小编微信「 woshicver」,每日朋友圈更新一篇高质量博文。

扫描二维码添加小编↓

基于Docker的交互式人脸识别应用相关推荐

  1. Python人脸识别教程 - 基于Python的开源人脸识别库:离线识别率高达99.38%

    Python人脸识别教程 - 基于Python的开源人脸识别库:离线识别率高达99.38% 仅用 Python 和命令行就可以实现人脸识别的库开源了.该库使用 dlib 顶尖的深度学习人脸识别技术构建 ...

  2. 《繁凡的论文精读》(一)CVPR 2019 基于决策的高效人脸识别黑盒对抗攻击(清华朱军)

    点我一文弄懂深度学习所有基础和各大主流研究方向! <繁凡的深度学习笔记>,包含深度学习基础和 TensorFlow2.0,PyTorch 详解,以及 CNN,RNN,GNN,AE,GAN, ...

  3. 第十九课.基于sklearn的SVM人脸识别

    目录 数据集 确定人脸的类别标记 划分训练集和测试集与训练 实验为基于sklearn的SVM人脸识别,使用 SVM 算法对戴眼镜的人脸和不戴眼镜的人脸进行分类,从而完成 识别戴眼镜的人脸 的任务:实验 ...

  4. 基于改进的RPCA人脸识别算法

    from:http://www.chinaaet.com/article/3000011311 基于改进的RPCA人脸识别算法 作者:首照宇,杨晓帆,莫建文 2015/11/15 18:04:00 摘 ...

  5. 基于稀疏表示的人脸识别 (SRC,LASRC,RASL,MRR)

    FROM:http://blog.csdn.net/loadstar_kun/article/details/39453839 1.  问题背景 信号的稀疏表示并不是新的东西.我们很早就一直在利用这一 ...

  6. 基于Python的开源人脸识别库:离线识别率高达99.38%

    基于Python的开源人脸识别库:离线识别率高达99.38% 2019年04月18日 18:13:18 AI终结者 阅读数 1233 项目地址:https://github.com/ageitgey/ ...

  7. 基于PYQT编写一个人脸识别软件(2)

    前言 以前在博客:基于PYQT编写一个人脸识别软件 中给出了我自己用PYQT编写的一个小软件.鉴于使用的是开源库--face_recogniton,尽管使用很简单,但是还有些问题,比如:识别黄种人时效 ...

  8. 基于PYQT编写一个人脸识别软件

    转载请注明出处:http://blog.csdn.net/hongbin_xu 或 http://hongbin96.com/ 文章链接:http://blog.csdn.net/hongbin_xu ...

  9. python dlib caffe人脸相似度_基于深度学习的人脸识别系统(Caffe+OpenCV+Dlib)【一】如何配置caffe属性表...

    前言 基于深度学习的人脸识别系统,一共用到了5个开源库:OpenCV(计算机视觉库).Caffe(深度学习库).Dlib(机器学习库).libfacedetection(人脸检测库).cudnn(gp ...

最新文章

  1. 网站增加外链的基本原则技巧有哪些?
  2. .Net - Lambda 表达式
  3. GCN pytorch实现 笔记
  4. 想进大厂,先自问 Dubbo 普普通通 9 问能答出来吗!
  5. pdf数据脱敏 如何恢复_如何恢复Word文档丢失的数据?
  6. java解析edi报文_EDI文件解析语法规则
  7. linux申请令牌错误,解决“请求中包含的安全令牌已过期”错误
  8. java导出繁体字word,word繁体字转换
  9. HTML5 音频文件
  10. easyUI datebox 日期只显示年月及年月日切换的实现 js样式重新渲染加载
  11. 先行试点,创新改造:中信期货关键业务系统自主可控的实践之路
  12. oracle ora 3136,oracle中ORA-3136,ORA-609
  13. 系统架构设计知识梳理--分布式架构
  14. 中国电信-天翼云-云监控
  15. FPGA中亚稳态、异步信号处理、建立和保持时间违例及题目合集
  16. 美拍解析去水印原理,sign签名算法,获得无水印播放地址
  17. zip格式压缩和解压缩(支持中文和文件嵌套解压缩)
  18. 【C语言】平均分的战争。有m个人的成绩存放在score数组中,请编写程序求出平均成绩并且罗列出低于平均分的分数。
  19. nginx 反向代理 proxy_pass DNS 缓存问题
  20. 基于python的知识融合_独家干货2,融合多个技巧的Python文件-综合实战应用

热门文章

  1. 2021年最新最全Flink系列教程_Flink快速入门(概述,安装部署)(一)(JianYi收藏)
  2. 程鑫峰:3.1余威未散鲍威尔再度归来,伦敦金、长江金业行情分析
  3. 【车间调度】FJSP的属性模型符号约定和约束条件
  4. mysql研究内容_基于MySQL数据库的数据管理的研究
  5. 系统进程启动流程分析(一)
  6. 正大市场监管总局、发改委、证监会联合提醒告诫部分铁矿石
  7. rpa机器人java开发,RPA机器人的“三大铁律”
  8. 为什么PCB上的单端阻抗控制50欧姆
  9. C# 小程序 getPhoneNumber(e),后台解析手机号码
  10. 如何用一个makefile编译多个目标