用Python写一个简单的脸部识别项目(4)|与语音api结合,实现多线程

[用Python写一个简单的脸部识别项目|汇总]这个系列的第四篇文章,这篇介绍如何将脸部识别和语音结合在一起。

实现多线程

为什么需要多线程

摄像头在不停的扫描和计算图像的相似度占据很大的计算量,同时要处理谷歌的speech2text API会造成卡顿的现象。

摄像头画面的更新,脸部识别,声音应该分开成不同的线程。

多线程的实现

  • 主线程:画面更新
  • 副线程1:识别出人脸的位置,并识别出人名
  • 副线程2:识别出人名后调出谷歌API
  • 如何将class的不同函数分成不同的线程

观察者模式实现 observer Pattern

  • Observer Pattern的概念[Observer Pattern 学习资料]
  • 语音不需要不停的播放,收到人名的时候播放就行了
  • Publisher:faceDetector class
  • Subscriber: speaker class

代码实现

生成多线程的wrapper

faceDetector.py
1
2
3
4
5
6
7
def threaded(fn):
def wrapper(*args, **kwargs):
thread = threading.Thread(target=fn, args=args, kwargs=kwargs)
thread.daemon=True
thread.start()
return thread
return wrapper

speaker class的代码

faceDetector.py
1
2
3
4
5
6
7
8
9
10
11
12
13
import cv2
import jatts #这是之前自己写的jatts class 文件,连接谷歌语音
import time
import threading
import numpy as np
class Speaker:
def __init__(self,name='Speaker'):
self.name=name
# 收到名字 生成实例,调用实例的speak函数
def update(self,message):
speaker = jatts(message)
speaker.speak()
)

faceDetector class的代码

faceDetector.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
class FaceDetector:
def __init__(self):
# observer pattern用的,保存subscriber object
self.subscribers=dict()
# 读取识别人脸位置的模型
self.detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

#摄像机的设定
self.cap = cv2.VideoCapture(0)
ret, self.img = self.cap.read()
self.cap.set(cv2.CAP_PROP_FPS, 25) # FPS
self.cap.set(cv2.CAP_PROP_BUFFERSIZE,3) # 缓存几张图片
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) # 摄像头解析度设定
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)

# 选好算法,读取之前训练好的模型
self.recognizer = cv2.face.LBPHFaceRecognizer_create()
self.recognizer.read("trainingData.yml")
self.faces=np.array([])#人脸所在位置的xy坐标和width,height
self.gray=[] # 保存灰化之后的图片数据,节省计算量

# 显示在画面上的情报 要用到的各种变量
self.id = -1 # user ID
self.conf=0.0 # 摄像机提取的图片于学习模型的距离,越小越像
self.font = cv2.FONT_HERSHEY_SIMPLEX
self.detect_threshold = 10#还未实现
self.username = ""


# 侦测出脸部所在位置,并更新各种参数
@threaded
def detectFaceArea(self):
while True:
time.sleep(0.05)
ret, self.img = self.cap.read()
self.gray = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY)

faces = self.detector.detectMultiScale(self.gray, 1.3, 5)
if(faces!= ()):
self.faces=faces
for (x,y,h,w) in faces:
self.id, self.conf = self.recognizer.predict(self.gray[y:y + h, x:x + w])

def update(self):
# 画面更新以及各种描写的处理
username=""
while True:
ret, self.img = self.cap.read()
for (x, y, w, h) in self.faces:
# draw rectangle around faces (x,y) start point w=width h=high ,color , thickness
cv2.rectangle(self.img, (x, y), (x + w, y + h), (255, 0, 0), 2)
if (self.conf > 90):
username = "Unknown"
else:
if (self.id == 1):
username = "chou"
elif (self.id == 2):
username = "bbbb"

elif (self.id == -1):
username = "Unknown"

# 显示出人名等信息
cv2.putText(self.img, "User:" + username+ (x, y - 10), self.font, 1, (0, 255, 0), 3)
cv2.putText(self.img, "Conf:" + str(self.conf), (x, y - 50), self.font, 1, (0, 255, 0), 3)
self.username=username

cv2.imshow('aaa', self.img)

# 按q键 结束程序
if cv2.waitKey(1) & 0xFF == ord('q'):
break

def end(self):
self.cap.release()
cv2.destroyAllWindows()
def register(self,who,callback=None):
if callback is None:
callback=getattr(who,'update')
self.subscribers[who]=callback
def unregister(self,who):
del self.subscribers[who]
def dispath(self,message):
# 这里的callable指向的是subscriber的update函数
for subscriber,callable in self.subscribers.items():
callable(message)

@threaded
def sendName(self):#
lastName = ""
while True:
time.sleep(1)
if(self.username!="" and self.username!=lastName):
self.dispath(self.username+"hello")
lastName = self.username

主程序

faceDetector.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if __name__=='__main__':

# 脸部识别器生成
face=FaceDetector()
# 语音实例生成
speaker=Speaker()
# 将语音的实例添加到face实例中,即speaker开始监听face的消息
face.register(speaker,speaker.update)

# 副线程thread-1 :1,识别出人脸的位置 2,识别对应人名
face.detectFaceArea()
# 副线程thread-2 :1,识别出新的人名时向speaker发消息 2,speaker接收后说话
face.sendName()
# 主线程 MainThread :画面更新
face.update()

face.end()

本文标题:用Python写一个简单的脸部识别项目(4)|与语音api结合,实现多线程

文章作者:caili-zhang

发布时间:2017年12月21日 - 02:12

最后更新:2017年12月24日 - 17:12

原始链接:https://caili-zhang.github.io/2017/12/21/python-face-04/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

据说喜欢打赏的人运气都不会太差