先来普及一下概念, 计算机对人脸是如何识别的呢? 或者说图像是如何识别的。主要是获取单张图片的特征值记录了特征值以后,如果下一张图片来了以后两张图片特征值进行对比,如果相似度很高那么计算机就认定这两个是一类图(当然这是需要算法来实现的)
我写的这个是怎么实现的呢,一组训练集训练要识别的人的图像来进行特征提取保存到模型中,在通过摄像头返回的图像进行处理并最后展现出来
直接上代码: ---- 抱歉由于不知道插入代码后怎么写文字我就全写这了。代码不算完善,但是识别没问题 使用时修改 train_path 和 fd 的人脸描述.xml文件路径就ok了
训练文件结构描述 : train_path文件结构 train_path -> LL(老李) -> 所有人脸图片
face.xml 文件下载地址 : http://note.youdao.com/noteshare?id=a74c5cffa145ff5341560d6c269702cb&sub=6A602009232C468CBE83114E840D679E
# 抱歉由于本人不会用 github 所以大家用有道云下载吧(捂脸笑)
1 # -*- coding: utf-8 -*- 2 from __future__ import unicode_literals 3 # 操作文件 4 import os 5 # 科学计算 6 import numpy as np 7 # 图像识别 8 import cv2 as cv 9 # 数据预处理, 该项目中只使用了标签编码 10 import sklearn.preprocessing as sp 11 12 13 def load_imgs(directory): 14 '''加载 directory 该文件夹下所有以 .jpg 结尾的图片''' 15 # 识别 系统环境 自动分配当前系统的路径分隔符并替换 16 directory = os.path.normpath(directory) 17 # 判断当前路径是否为存在 18 if not os.path.isdir(directory): 19 # 手动抛出异常 biu biu biu 20 raise IOError("The directory '" + directory + "' doesn't exist!") 21 # 创建图片集合 用于存储文件夹名和该文件夹下所有的图片 22 faces = {} 23 # os.walk(directory) 获取当前文件夹下所有的文件夹以及文件 24 # curdir: 当前文件夹路径 25 # subdirs: 当前文件夹下所有文件夹 (列表) 26 # files: 当前文件夹下所有文件 (列表) 27 for curdir, subdirs, files in os.walk(directory): 28 # 首先便利所有的文件 筛选.jpg结尾文件并循环 29 for jpeg in (file for file in files if file.endswith('.jpg')): 30 # 拼接图片路径 31 path = os.path.join(curdir, jpeg) 32 # 获取该图片分类名称 33 label = path.split(os.path.sep)[-2] 34 # 判断当前key值是否存在图片集合中, 如果为空则创建该键并赋值空列表 35 # 否则给图片集合中的 key 添加图片路径 36 if label not in faces: 37 faces[label] = [] 38 faces[label].append(path) 39 # 返回图片集合 40 return faces 41 42 43 def LBPHModel(fd, codec, train_path): 44 ''' 45 ------------------- 46 参数说明: fd, codec, [model_path] 47 fd: Haar-like(人脸特征模型对象) 48 codec: LabelEncoder(标签编码器对象) 49 model_path: 服用模型路径(功能未实现, 没找到读取的函数...) 50 ------------------- 51 返回: 训练后的模型对象 52 ''' 53 # 加载当前文件加下所有.jpg结尾的图片 54 train_faces = load_imgs(train_path) # 'traom_imgs' 55 # 将所有标签放入编码器进行训练 56 codec.fit(list(train_faces.keys())) 57 # 创建空的训练集数组x y 58 train_x, train_y = [], [] 59 # 循环所有训练组 60 for label, filenames in train_faces.items(): 61 # 循环当前样本组中的图片 62 for filename in filenames: 63 # 读取图片 64 image = cv.imread(filename) 65 # 将图片转成灰度图 66 gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY) 67 # 获取人脸特征位置 68 faces = fd.detectMultiScale( 69 gray, 1.1, 2, minSize=(100, 100)) 70 # 循环脸部特征数组 71 for l, t, w, h in faces: 72 # 将图片中的脸部特征裁剪下来 73 train_x.append(gray[t:t + h, l:l + w]) 74 # 标签编码结果存储 75 train_y.append(codec.transform([label])[0]) 76 train_y = np.array(train_y) 77 # 创建LBPH人脸检测器 78 model = cv.face.LBPHFaceRecognizer_create() 79 # 对训练集进行训练 80 model.train(train_x, train_y) 81 return model 82 83 84 if __name__ == "__main__": 85 # 训练集图片存储路径 86 train_path = 'train_imgs' 87 # 读取人脸描述文件, 构建人脸检测器 88 fd = cv.CascadeClassifier('face.xml') 89 # 创建标签编码器 90 codec = sp.LabelEncoder() 91 # 获取model 92 model = LBPHModel(fd, codec, train_path) 93 # 打开视频捕捉设备 94 vc = cv.VideoCapture(0) 95 while True: 96 # 读取视频帧 97 frame = vc.read()[1] 98 # 反转图片 99 frame = cv.flip(frame, 1) 100 # print(frame) 101 # 人脸位置检测, 返回数组 102 faces = fd.detectMultiScale(frame, 1.3, 5) 103 # 循环人脸位置数组 104 for l, t, w, h in faces: 105 # 给人脸描边 106 cv.rectangle(frame, (l, t), (l + w, t + h), 107 (255, 0, 0), 4) 108 # 复制原图片文本 109 gray = frame.copy() 110 # 将图片变化成灰度图 111 gray = cv.cvtColor(gray, cv.COLOR_BGR2GRAY) 112 # 对面部特征进行识别 113 pred_test_y = model.predict(gray[t:t + h, l:l + w])[0] 114 # 将预测后的结果进行标签解码 115 face_name = codec.inverse_transform([pred_test_y])[0] 116 # 给图片添加文本 图片矩阵, 添加文本名称, 设置文本显示位置, 117 # 字体样式, 字体大小, 字体颜色, 字体粗细 118 cv.putText(frame, face_name, (l + 5, t - 15), 119 cv.FONT_HERSHEY_SIMPLEX, 1, 120 (255, 255, 255), 3) 121 # 打印名称 122 # print(face_name) 123 124 # 显示图片 125 cv.imshow('VideoCapture', frame) 126 # 等待按下ESC键退出, 每次等待33毫秒 127 if cv.waitKey(33) == 27: 128 break 129 # 关闭视频捕捉设备 130 vc.release() 131 # 关闭视频窗口 132 cv.destroyAllWindows()