据悉面部识别的日志系统的筹划及贯彻

依据面部识别的日志系统的统筹和实现

@(GUI程序开发)[PyQt, 信号, 面部识别, 多线程, 媒体播放, opencv]


[TOC]

那么时候自己还十分有些,现在自家还百般年轻。

要求及统筹

行使面部识别技术,识别进出重要通道的口,并针对人员出入动作进行记录。在人员进出时,在摄像机前征集画面,使用搜集到之画面和历史记录对比,如果人口既存在出入记录,追加一长长的记下即可;如果无存在则新建记录。

  无聊当中认识WOW,然后无聊之玩WOW,然后开了咱们的故事。

术和贯彻

  “来,给你张盘!”

核心技术

用Python来好总体程序的编排,面部识别应用python开源库face_recognition,
基于dlib(C++实现)。
动opencv来捕获视频流,支持地方摄像头和网摄像头。
采取QThread创建线程更新每一样帧图片及PyQt界面。

  “啊?有码还是无码?”

数存储

采用Sqlite3作为单机版数据库,同时支持MySQL数据库。
运用sqlite3进行数量存储。

  “无码网游”

前端界面

运PyQt4看作前端界面,使用绝对化布局。

  “啊?我喜欢”

展示监控画面

  “装好了,怎么玩?”

opencv捕获摄像机视频流

Opencv捕获视频流,主要利用opencv的videoCapture方法,
传入摄像头物理地址(0-99)或者网络视频流地址。

  • 安装(Ubuntu): sudo apt install
  • 应用(Python2.7 代码示例):

import cv2
#以下的代码片段应当被放在单独的线程中
#使用videoCapture捕获视频
#address可以是usb摄像头的地址(0-99)
#address也可以是视频流的网络地址 如海康摄像机rtsp地址
address = "rtsp://admin:12345@192.0.0.64:554/h264/ch1/main/av_stream"
cap = cv2.videoCapture(address)
#当视频流捕获到以后,开始获取捕获的每一帧
#拿到的frame实际上是以矩阵的形式存储的,具体的数据结构是numpy的ndarray
#并转换为PyQt可以显示的QPixmap(图片)
while cap.isOpened():
    ret, frame = cap.read()
        #拿到frame的信息,并从cv2默认的BGR模式转成RGB模式
        height, width, fps = frame.shape
        bytesPerLine = 3 * width
        cv2.cvtColor(frame, cv2.COLOR_BGR2RGB, frame)
        image = QtGui.QImage(frame.data, width, height,bytesPerLine, QtGui.QImage.Format_RGB888)
        #然后在主线程中更新image,Pyqt4发送信号并传送image到主线程即可

  “没号你打个锤子”

PyQt4子线程控制UI线程更新

  “不是单机?”

动用状况同样:子线程获取视频流的frame,主线程更新frame

  “。。。这是网游,自己去挂号个号,给你张卡,自己动手。”

动QT提供的线程类:QThread

下opencv获取视频流之后,应于UI线程中更新得的诸一样轴。
足起定义一个控件,集成自QLabel,然后从定义信号,这个信号将见面在自线程里被点,在主线程里执行。
切实落实方式:

class VideoPlayer(QtGui.QLabel):
    def __init__(self, parent, address):
        QtGui.QLabel.__init__(self, parent, address)
        #这里创建子线程,传递流媒体地址
        self.video_provider = videoThread(address)
        self.video_provider.start()
        #这里自定义一个信号,以便于在子线程里面触发更新帧的方法
        self.connect(self.video_provider, QtCore.SIGNAL('newImage(PyQt_PyObject)'), self.setFrame)
        #这里创建一个当前帧,初始化为None,方便以后截图
        self.current_frame = None

    #这个方法将在newImage信号触发之后执行
    def setFrame(self):
        pixmap = QtGui.QPixmap.fromImage(frame)
        self.current_frame = pixmap
        self.setPixmap(pixmap)

这样主线程(UI线程已经办好了有的预备干活,接下便于子线程内获得视频的各个一样幅,然后发送信号过来)
创造一个线程类,继承QtCore.QThread

#其实就是上面opencv的方法放在一个线程内
class videoThread(QtCore.QThread):
    '''线程类,负责更新视频的每一帧'''
    def __init__(self, address):
        '''初始化的时候传入视频流的地址'''
        super(videoThread, self).__init__()
        self.address = address

    def run(self):
        '''重写run函数,读取到视频流之后不断更新frame到主线程'''
        self.cap = cv2.VideoCapture(self.address)
        while self.cap.isOpened():
            _, frame = self.cap.read()
            if frame is not None:
                #这里进行frame的转换
                height, width, fps = frame.shape
                bytesPerLine = 3 * width
                cv2.cvtColor(frame, cv2.COLOR_BGR2RGB, frame)
                image = QtGui.QImage(frame.data, width, \
                height,bytesPerLine, QtGui.QImage.Format_RGB888)
            else:
                #如果没有拿到frame,则给一个摄像头连接失败的图片,递归,直到摄像头重新连接
                image = QtGui.QImage("./icons/no_video.png")
                self.run()
            #在这里发送信号的主线程,主线程会自动执行之前定义的setFrame方法,更新图片
            self.emit(QtCore.SIGNAL('newImage(PyQt_PyObject)'), image)
        #如果摄像头没有获取到,给链接失败的图片,然后递归
        image = QtGui.QImage("./icons/no_video.png")
        self.emit(QtCore.SIGNAL('newImage(PyQt_PyObject)'), image)
        self.run()

这般就可以于前者播放画面了。

  不久从此才理解,那无码网游原来就是是魔兽,当自家掌握常就是一样名为1级的略牛战士(超人牛牛)了。

动用状况二:视频的截屏,在子线程里截屏并保存到地头

  玩兵的由,是阡陌(给我盘的人头)说自家少责任心,要锤炼自己之责任心。

使用Python原声的threading.thread创建线程,只想略工作

截屏的当儿理应以界面显示:准备,3, 2, 1
的唤起,这样的唤起每一样蹩脚间隔1秒钟,以便让为用户3秒的调整时。
这样的办事务必于子线程内执行,否则在主线程内执行会阻断UI线程更新来看频流的事情,造成视频卡顿。
落实方式:
首先创建一个用以展示提示信息之Label,然后在子线程里更新Label的text即可。

from PtQt4 import QtGui, QtCore
from thread import threading

class MainWindow(QtGui.QWidget):
    def __init__(self):
        #...
        #...
        self.notify_label = QtGui.QLabel(self)
        self.take_photo_button = QtGui.QPushButton(self)
        self.take_photo_button.setText(u"拍照")
        self.connect(self.take_photo_button, QtCore.SIGNAL("clicked()"),\
            self, QtCore.SOLT("takePhoto()"))

    #自定义的槽,在class内应加上 装饰器
    @QtCore.pyqtSlot()
    def takePhoto(self):
        thread = threading(target=self.updateNotifyAndTakePhoto)
        thread.start()

    #这里是真正进行提示和截图的方法
    def updateNotifyAndTakePhoto(self):
        #先进性一轮循环,显示四个提示,每一次间隔一秒,持续四秒
        for text in [u"准备", '3', '2', '1']:
            self.notify_label.setText(text)
            time.sleep(1)
        #然后设置提示消息为空
        self.notify_label.setText("")
        #开始截图
        img = self.video_player.current_frame
        img.save("./tmp/face.jpg")

  同时期,寝室诞生了1叫作伟大的猎人(体内),1叫高大之胡子(阡陌),1名伟大的圣骑(大胸)!

PyQt4信号的其它一样种定义方法

  燃烧的远征以201如泣如诉寝室开始,当时风和日丽!

在子线程内打开新的窗口

  “哇哈!有人M我!第一个人M我什么!一个受“”的,啊哈!我之第一不成啊!”

概念信号,初始化的时节绑定,在子线程内调用

class MainWindow(QtGui.QMainWindow):
    '''程序主窗口'''
    #自定义的信号一定要作为类的成员变量
    record_window_signal = QtCore.pyqtSignal()
    def __init__(self):
        #... other code
        self.record_window_signal.connect(self.showRecordWindow)
        self.history_window_signal.connect(self.showHistoryWindow)
        #这里直接调用启动一个线程
        thread = threading(tearget=self.backgroundWork)
        thread.start()

    #一个函数,做后台工作
    def backgroundWork(self):
        #...做一些后台工作,比如人脸识别
        #需要打开新的窗口的时候,触发这个信号即可
        self.record_window_signal.emit()

    #自定义的信号被触发时打开一个自定义的Dialog
    def showRecordWindow(self):
        #CSInfoWindow是一个自定义的Didlog
        self.add_dialog = CSInfoWindow()
        self.add_dialog.exec_()

  “他问你啊?”

口脸检测与比较对

  “你忙么?你没时间吗?你用经验飞一般的晋级速度吗?本工作室发标准的人选呢汝提供正规的服务,有意者M!”

使用face_recognition检测图片内发无有人脸

以展开人脸识别的当儿,首先要由图纸内找到人脸,有时候图片内根本未曾脸,有时候是因为众多张脸,都亟待展开判定

  “干,代练,举报或屏蔽的!”

安装face_recognition模块

  • 设置依赖
    cmake 负责编译dlib sudo apt install cmake
    libboost dlib的依赖 sudo apt install libboost1.61-dev
    dlib 机器学习类库 sudo apt install libdlib-dev
  • 装模块
    pil python的图像处理模块 pip install pillow
    numpy 机器学习为主模块,无需多言
    pip install numpy face_recognition

  “别,别!好歹也是我之率先糟,我找他拉。”

使用face_recognition检测照片内的食指脸

重中之重是一些API的施用,后台的方法还于dlib中贯彻,python只是调用而现已
及同一张效果图:

检测出两单人口脸

立马张图直接检测出,两独人脸!!! 但是,其实我们只是需要平等张人脸。

#face_locations 就是对一张照片中人脸的定义,本质上是一个数组
face_locations = face_recognition.face_locations(image)
#如果有多张人脸,则不作处理,因为不符合我们的使用场景
if len(face_locations) > 1:
    print u"检测出了多张人脸,请确保镜头中只有一个人"
#如果没有任何人脸,也不做处理
if len(face_locations) == 0:
    print u"没有检测出来人脸,请重新识别"
#有且只有一张人脸的时候才开始进行人脸的定位
else:
    #face_locations[0]就是惟一的一张人脸
    top, right, bottom, left = face_locations[0]
    #按照人脸的尺寸,裁剪出来人脸
    face_image = image[top:bottom, left:right]
    pil_image = Image.fromarray(face_image)
    #显示截取出来的人脸
    pil_image.show()
    print u"人脸检测成功"
    filename = FACE_DIR + str(datetime.now()) + ".jpg"
    image = Image.fromarray(image)
    image.save(filename)

  “我忙碌,我从未工夫,我思感受飞一般的升级速度!”我反过来了同句子。

使用face_recognition进行面部的比对

在人员数据库被储存了多之人数脸,当用户刷脸之后,要指向人口脸进行比对,确定用户位置。
丁脸比对的API:
face_recognition.api.compare_faces(known_face_encodings, face_encoding_to_check, tolerance=0.6)

Compare a list of face encodings against a candidate encoding to see
if they match.
Parameters:
known_face_encodings – A list of known face encodings
face_encoding_to_check – A single face encoding to compare against
the list
tolerance– How much distance between faces to consider it a match.
Lower is more strict. 0.6 is typical best performance.
Returns:
A list of True/False values indicating which known_face_encodings
match the face encoding to check

  • 参数1: 需要数据库内之有着人脸数据做的数组(know_face_encodings
  • 参数2: 需要未知人脸的数量(矩阵): (face_encoding_to_check)
  • 严格程度: tolerance 严格程度起0.1 到1
    更是宽松,数值设置更加盖产生或识别错误,数据极其小是因为难以辨认及。

实际实现的代码:

def recognite(unknow_img):
    #传入一张未知图片的编码,转换成矩阵
    unknow_face_encoding = face_recognition.face_encodings(unknow_img)[0]
    know_faces = []
    know_labels = []
    # 从本地的文件夹内加载所有已经存在的人脸并转为矩阵,放在一个数组内
    for filename in os.listdir(FACE_DIR):
        path = os.path.join(FACE_DIR,filename)
        image = face_recognition.load_image_file(path)
        know_face_encoding = face_recognition.face_encodings(image)[0]
        know_faces.append(know_face_encoding)
        know_labels.append(filename)
    # 进行人脸的比对,这里精准度设置为0.4 具体需要根据摄像头的分辨率 拍摄距离等进行调试
    result = face_recognition.compare_faces(know_faces, unknow_face_encoding, tolerance=0.4)
    # 返回检测的结果级和对应的标签(姓名或者其他唯一性标识)
    return result, know_labels

  “代练1-70,包小鸟,送全身蓝装,送少征集专业,战士号,收费500”不交2秒就算死灰复燃了,我很崇拜他,比自己亲手写都争先。”

总结

  “人民币要美金?”

吸纳任务之首先反映

以刚起收取这个职责的当儿,其实是杀受惊之,因为作为机器学期或者人工智能的娴熟人来讲,我非常懂人脸识别意味着什么。(….代表算法,预测模型,训练模型,计算机图形学),总的及时就是一个藏的课题,要起实现无一个丁一致年两年就会闹成果的。但是好当前任有广大经历!

  “暂时只得了人民币。”

首的计划

额头!最初的想法是投机实现人口脸比对的算法,
因为之前运用knn算法随手写数字进行过识别,是一个榜首的督察法分类案例,具体的法就是是以图片转换为矩阵,再针对矩阵展开归一化,使用欧式距离公式来计算出来n维空间中这些点之相距,然后根据距离她最近之几只点进展概率判断,从而进行归类。但是人脸识别这样做根本不可行,人脸识别中既出回归分析又闹分类,还是特别伤脑筋的。

  “可以不费么?”

第三方SDK

通过查看资料发现,使用第三着SDK还是比较靠谱的,目前主流的由opencv和dlib,这里选择了dlib,因为dlib的面识别的密度比较深,所以精准度会高一点,但是项目蒙还是用了Opencv来开展观看频流的收获。

  “已经用你挡,我的首先糟下,迎来的是一个遮,悔恨不已!”

最终结出

理所当然打算当windows环境下使用c#心想事成,但是考虑到支付效率,
决定或者用python开发比较靠谱。但在此之前并没有python
GUI程序的出经历,所以开始学习了python的QT开发,
开发条件选择在linux下,但是QT跨平台,今后啊可是于windows平台下安排,不过同想到windows下复杂的软件以及类库安装过程,我就算呵呵了,决定运行环境依然以Linux下,避免电脑中毒导致系统崩溃(这个以前来月经之教训,所以强烈建议使用Linux来运行主要系统)。
通过三上半夜的支出, 从零开始实现了人脸识别的次序,
测试后还比较稳定,关于精准度的题材,这个还是待依据实际条件来调节,并且也要在摄影的时做好用户引导。因为,天喻后来微人口会被抄在数据库内,而且精准度又休能够最好没有,所以必须做好以人口之塑造,确保无会见认错人,或者认不出来人。
如果单位的丁于少,大得逐步采集原始数据,正脸,侧脸,各种角度表情都得存在数据库进行比对,但是这顺序一旦检测的靶子是不管三七二十一的,不是原则性的那几个人,但从脚下测试的结果来拘禁,正常下,距离摄像头2到4米的偏离拍照,基本上不会见重复误报,不遮蔽眼睛,不吐舌头,微笑,大笑还足以是识别。

  一个经久的历程,超人牛牛终于挣扎到40。

  “同志等,你们全寝室唯一的战士早已胜利升及40,你们是不是该送他匹马?”

  “我正采购60之马,无余额”阡陌的说话

  “我借为一个位刚认识的MM了,无余额”体内的语句

  “我哪怕没钱,不迷信自己扣!”大胸的语

  “你们就群畜,你们忍心一个40级的牛光着下在地上跑?”

  “我不在乎!”

  “TBC之前是隔三差五,你该感受下,多锻炼下脚力”

  “我较同情你,心有余而力不足啊,同志。你得去主城要嘛!建私房妖小号,去个来诱惑力的名字,一下午肯定能够凑合一起了。”

  “为什么要盖新号?”

  “因为乞讨毕竟非是异常好看,你吗不思量到了70之后还于人说:‘超人牛当初以AG乞讨了吧!’”

  经过一番郑重的深思熟虑后,我毅然决定,超人牛牛亲自上,因为自己总认为,干任何工作都设诚实,毕竟自己是一个于老实的总人口(当然多人数认为自己老丢脸,但自身郑重申明自己绝对不是极致无耻的,因为极度不要脸的人选于背后会并发)。

  我学会了第一个宏:“我给超人牛牛,第一软打魔兽,我生3个哥哥,大哥深受阡陌,二兄被体内,三单给大胸,他们都非给自家钱请马,故出来乞讨,希望热心人支持!给1G,我谢谢您;给2G,我挺谢谢;给5G,我表示我们寝室的谢谢你;给10G,我哭了;给50G?放心,我会还的”

  他们给我错过AG乞讨,因为那边人大多,我失去了森,因为自身看幽暗光线较暗,别人看不显现自己的脸,也不至于丢脸。

 魔兽乞讨手册规定首先看人配备,紫色装备的数据和乞讨成功的数量是成为正比的。终于,我找到了一个满身紫的弓弩手,巨魔猎人-斯蒂芬糖糖。宏发了于他,然后空格了少数生。

  5秒后(乞讨手册规定之5秒定律,5秒不被抢闪人),猎人交易我了,100G。

  “有人被了自家100G”我死去活来叫到

  “等有人为你1000G了更喊”阡陌

  “我日,比你们及时许多猪好些”

  “谢了,以后发生钱了本人还你!

  “不用,哥今天心情好!”

  “你是个老实人”

  “干”

  “要无自服你当哥吧,这样我就是不忧60底马了”

  “。。。。。”

  “考虑下否?”

  猎人又交易我了,1000G

  “哇哈哈,这丁还要为我1000G”

  “估计他是盗号的”阡陌的定论。

  “我对象说你是盗号的”

  “你叫他说,别给我遇到他,我做死他”

  “来咱们会无?”

  “我才40”

  “没事,来我们见面,哥罩你!”

  “好”

(未完待续)

图片 1

发表评论

电子邮件地址不会被公开。 必填项已用*标注