----------欢迎加入学习交流QQ群:657341423
要实现人面识别,首先安装opencv的opencv_contrib组件。首先在https://www.lfd.uci.edu/~gohlke/pythonlibs/#opencv下载相关组件。
在CMD窗口下先卸载原有的opencv,然后安装opencv_contrib的安装包。
pip uninstall opencv_python-3.4.1-cp35-cp35m-win_amd64.whl
pip install opencv_python-3.4.1+contrib-cp35-cp35m-win_amd64.whl
完成上述安装后,接着实现人面识别,首先装备人面资料,如图所示:
文件夹alin和xyjw是分别存放人物头像图片,分别代表人物alin和xyjw,图片格式为pgm格式。
由于一开始是没有人物头像图片,于是,我们先用人面检测获取人物头像图片,代码如下:
import cv2
def get_face_data():
# 加载Haar级联数据文件,用于检测人面
face_cascade = cv2.CascadeClassifier('cascades/haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('./cascades/haarcascade_eye.xml')
camera = cv2.VideoCapture(0)
count = 1
while True:
ret, frame = camera.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 人面识别。detectMultiScale参数说明:
# gray: 进行检测的图像, 这里是转换后的。
# scaleFactor: 官网文档说是每次图片缩小的比例, 其实可以这么理解, 距离相机不同的距离, 物体大小是不一样的, 在物体大小不一致的情况下识别一个东西是不方便的, 这就需要进行多次的缩放, 这就是这个参数的作用。
# minNeighbors: 可以理解为每次检测时, 对检测点(Scale)周边多少有效点同时检测, 因为可能选取的检测点大小不足而导致遗漏。
# minSize: 检测点的最小值, 或者说就是检测点的最终值。
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5, minSize=(5,5))
# 画出面部位置
for (x, y, w, h) in faces:
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('auto/alin/%s.pgm' %(str(count)),f)
count += 1
cv2.imshow('pic', frame)
# 停止程序
if cv2.waitKey(120) & 0xff == ord('q'):
break
camera.release()
cv2.destroyAllWindows()
if __name__=='__main__':
get_face_data()
人面图片的数据获取后,我们利用这些数据实现人面识别,其功能代码如下:
import sys,os,cv2
import numpy as np
# 加载面部资料
def read_images(path, sz=None):
"""Reads the images in a given folder, resizes images on the fly if size is given.
Args:
path: 人面数据所在的文件路径
sz: 图片尺寸设置
Returns:
A list [X,y]
X: 图片信息
y: 图片的读取顺序
"""
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):
filepath = os.path.join(subject_path, filename)
im = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE)
if (sz is not None):
im = cv2.resize(im, sz)
X.append(np.asarray(im, dtype=np.uint8))
y.append(c)
c = c+1
return [X,y]
# 面部识别
def face_rec():
names = ['Alin', 'XyJw', 'Jack']
[X, y] = read_images('E:\\auto\\')
# 创建识别模型,使用EigenFace算法识别,Confidence评分低于4000是可靠
# model = cv2.face.EigenFaceRecognizer_create()
# 创建识别模型,使用LBPHFace算法识别,Confidence评分低于50是可靠
# model = cv2.face.LBPHFaceRecognizer_create()
# 创建识别模型,使用FisherFace算法识别,Confidence评分低于4000是可靠
model = cv2.face.FisherFaceRecognizer_create()
# 训练模型
# train函数参数:images, labels,两参数必须为np.array格式,而且labels的值必须为整型
model.train(np.array(X), np.array(y))
# 开启摄像头
camera = cv2.VideoCapture(0)
# 加载Haar级联数据文件,用于检测人面
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]
# 将检测的人面缩放200*200大小,用于识别
# cv2.INTER_LINEAR是图片变换方式,其余变换方式如下:
# INTER_NN - 最近邻插值。
# INTER_LINEAR - 双线性插值(缺省使用)
# INTER_AREA - 使用象素关系重采样。当图像缩小时候,该方法可以避免波纹出现。
# INTER_CUBIC - 立方插值。
roi = cv2.resize(roi, (200, 200), interpolation=cv2.INTER_LINEAR)
# 检测的人面与模型进行匹配识别
params = model.predict(roi)
print("Label: %s, Confidence: %.2f" % (params[0], params[1]))
# 将识别结果显示在摄像头上
# cv2.FONT_HERSHEY_SIMPLEX 定义字体
# cv2.putText参数含义:图像,文字内容, 坐标 ,字体,大小,颜色,字体厚度
# 如果要输出中文字,可参考https://blog.csdn.net/m0_37606112/article/details/78511381
cv2.putText(img, names[params[0]], (x, y - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)
cv2.imshow("camera", img)
if cv2.waitKey(120) & 0xff == ord("q"):
break
cv2.destroyAllWindows()
if __name__ == "__main__":
face_rec()
函数read_images是分别读取文件夹alin和xyjw的图片数据和文件夹读取顺序。文件夹读取顺序是先读取alin的图片数据,然后在读取xyjw的图片数据,最后将两者的图片数据写入列表,因此这里存在一个先后顺序问题。
函数face_rec是调用函数read_images,因此函数read_images的返回值与变量names的值要一一对应,比如函数read_images的返回值第一个人面数据是alin,变量names的第一个值为alin。否则对应不上就会将名字写错。
人面识别也是通过摄像头来获取人物头像,然后根据算法与文件夹alin和xyjw的头像进行匹配对比。匹配成功会返回Label和Confidence,其中Label代表资料加载顺序,即函数read_images读取文件夹alin和xyjw的读取顺序。Confidence是识别评分,每种算法有一定的范围值,符合范围值才算匹配成功。
参考资料:OpenCV 3计算机视觉 Python语言实现第二版