之前我们学习了机器学习和数字图像处理的相关知识,了解了基本的概念理论和OpenCV和TensorFlow框架的使用,现在我们可以结合这些知识与工具写出属于我们自己的计算机视觉项目,本文主要介绍了如何使用OpenCV提供的函数来构建一个人脸识别和检测的应用
我们知道提取出图像数据的细节特征对产生稳定分类结果和跟踪结果很有用,两个图像的相似程度可以通过他们对应特征的欧氏距离来度量。
类Haar特征是一种用于实现实时人脸跟踪的特征。文献《Robust Real-time Face Detection》首次采用这种特征来进行人脸检测
OpenCV的源代码中data文件夹中包含了这种特征的XML文件,可以用来检测静止的图像、视频和摄像头中的人脸
我们可以利用这些特征创造自己的级联,并训练这些级联来检测各种对象
人脸检测首先是加载图像并检测人脸,这也是最基本的一步,我们在图片的人脸处绘制矩形框
首先在项目中创建cascades文件夹,把特征XML文件放入cascades文件夹中。使用Python实现:
import cv2
filename = 'images/6.jpg'
def detect(filename):
"""
函数:face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml')
该函数声明了face_cascade变量,该变量为CascadeClassifier对象,它负责人脸检测
函数:faces = face_cascade.detectMultiScale(gray,1.3,5)
传递的参数是scaleFactor和minNeighbors,它们分别表示人脸检测过程中每次迭代时图像的
压缩率以及每个人脸矩形保留邻近数目的最小值
返回值为人脸矩形数组
函数:img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
通过坐标来绘制矩形(x,y表示左上角的坐标,w,h表示人脸矩形的宽度和高度)
"""
face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml')
img = cv2.imread(filename)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray,1.3,5)
for (x,y,w,h) in faces:
img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
cv2.namedWindow('Vikings Detected!!')
cv2.imshow('Vikings Detected!!', img)
cv2.waitKey(0)
detect(filename)
下面识别索尔维会议中的人脸(有两个人没有检测出来,可见光用使用face_cascade一个特征来识别人脸还是不太行啊)
在视频的帧上重复这个过程就能完成视频中的人脸检测
import cv2
import sys
def detect():
"""
定义两个特征:面部特征和眼部特征
"""
face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('./cascades/haarcascade_eye.xml')
camera = cv2.VideoCapture(0) #0表示使用第一个摄像头
"""
接下来捕获帧,read()函数会返回两个值:第一个值为布尔值,用来表明是否成功读取帧,第二个值为帧本身。捕捉到帧后,将其
转换成灰度图像
"""
while (True):
ret, frame = camera.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces: # 返回的x,y代表roi区域的左上角坐标,w,h代表宽度和高度
img = cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)
roi_gray = gray[y:y + h, x:x + w]
eyes = eye_cascade.detectMultiScale(roi_gray, 1.03, 5, 0, (40, 40))
for (ex, ey, ew, eh) in eyes:
cv2.rectangle(img, (x + ex, y + ey), (x + ex + ew, y + ey + eh), (0, 255, 0), 2)
cv2.imshow("camera", frame)
key = cv2.waitKey(30) & 0xff #按ESC退出
if key == 27:
sys.exit()
if __name__ == "__main__":
detect()
我们在实现人脸检测,它是人脸识别的基础,识别和检测的区别在于一个程序能否识别出给定图像或视频中的人脸。实现这一目标的方法之一是用一系列分好类的图像(人脸数据库)来“训练”程序,并基于这些图像来进行识别
在这里,我们可以利用视频操作来生成属于自己的面部数据
样本图像满足
import cv2
import sys
def detect():
"""
定义两个特征:面部特征和眼部特征
"""
face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('./cascades/haarcascade_eye.xml')
camera = cv2.VideoCapture(0) #0表示使用第一个摄像头
count = 0
"""
接下来捕获帧,read()函数会返回两个值:第一个值为布尔值,用来表明是否成功读取帧,第二个值为帧本身。捕捉到帧后,将其
转换成灰度图像
"""
while (True):
ret, frame = camera.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces: # 返回的x,y代表roi区域的左上角坐标,w,h代表宽度和高度
img = cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)
f = cv2.resize(gray[y:y+h, x:x+w],(200,200))
cv2.imwrite('./data/at/jm/%s.pgm' % str(count),f)
count += 1
cv2.imshow("camera", frame)
key = cv2.waitKey(30) & 0xff #按ESC退出
if key == 27:
sys.exit()
if __name__ == "__main__":
detect()
Opencv提供的三种算法:
这些方法都有类似的过程,即都使用了分好类的训练数据集来训练,并从两方面来确认:是否识别到目标;目标真正被识别到的置信度的度量,这也称为置信度评分
import cv2,os,sys
import numpy as np
def read_images(path, sz = None):
c = 0
X, y = [], []
for dirname, dirnames, filenames in os.walk(path):
for subdirname in dirnames:
subject_path = os.path.join(dirname, subdirname)
for filename in os.listdir(subject_path):
try:
if not filename.endswith('.pgm'):
continue
filepath = os.path.join(subject_path, filename)
im = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE)
if sz is not None:
im = cv2.resize(im,(200,200))
X.append(np.asarray(im, dtype=np.uint8))
y.append(c)
except:
print("Unexpected error:",sys.exc_info()[0])
c = c + 1
return [X, y]
def face_rec(img_path):
names = ['Leon']
[X,y] = read_images(img_path)
y = np.asarray(y, dtype=np.int32)
model = cv2.face.EigenFaceRecognizer_create()
model.train(np.asarray(X), np.asarray(y))
camera = cv2.VideoCapture(0)
face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml')
while (True):
read, img = camera.read()
faces = face_cascade.detectMultiScale(img, 1.3, 5)
for (x, y, w, h) in faces:
img = cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
roi = gray[x: x+w, y: y+h]
try:
roi = cv2.resize(roi, (200, 200), interpolation=cv2.INTER_LINEAR)
params = model.predict(roi)
print("Label: %s, Confidence: %.2f" % (params[0], params[1]))
cv2.putText(img, names[params[0]], (x, y - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, 255, 2)
except:
continue
cv2.imshow("camera", img)
if cv2.waitKey(1000 // 12) & 0xff == ord('q'):
break
cv2.destroyAllWindows()
if __name__ == "__main__":
face_rec('./data/at/') #人脸数据路径img_path
置信度评价: