环境
- Python3安装
- OpenCV库安装在cmd中输入
pip install opencv-contrib-python
,如果显示pip不是内部或外部命令,那就是未配置环境变量,自行百度。 - Numpy库安装在cmd中输入
pip install numpy
- OpenCV人脸识别器下载(文件夹中已经有了,lbpcascade_frontalface.xml)这里我选择的是LBPH人脸识别器,他能很好的避免光线明暗的影响
准备训练数据
这里我们在网上搜集了20多张有关小孩情绪的照片(精力有限,只作简单的学习),将其手动标记为happy
和sad
两种标签,照片命名规则为标签.jpg。
将照片分为训练数据和测试数据,分别放在img_train
和img_predict
文件夹下。
所以我们的目录结构是这样的
-- img_train
-- happy1.jpg
-- happy2.jpg
-- ... -- sad1.jpg
-- sad2.jpg
-- ...-- img_predict
-- happy1.jpg
-- sad1.jpg
准备工作已经做好了,接下来我们可以开始编写代码了,这里我将代码分成了6个源文件源文件detect_face.py
import cv2 def detect_face(img): #将图像转变成灰度图像,因为OpenCV人脸检测器需要灰度图像 gray = cv2.cvtColor(img, cv2.COLOR_BAYER_BG2GRAY) #加载OpenCV人脸识别器,注意这里的路径是前面下载识别器时,你保存的位置 face_cascade = cv2.CascadeClassifier(r'D:\matlab\matlab\toolbox\vision\visionutilities\classifierdata\cascade\lbp\lbpcascade_frontalface.xml') #scaleFactor表示每次图像尺寸减小的比例,minNeighbors表示构成检测目标的相邻矩形的最小个数 #这里选择图像尺寸减小1.2倍。minNeighbors越大,识别出来的人脸越准确,但也极易漏判 faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=1) # 如果图中没有人脸,该图片不参与训练,返回None if len(faces) == 0: return None, None # 提取面部区域 (x, y, w, h) = faces[0] #返回人脸及其所在区域 return gray[y:y + w, x:x + h], faces[0]
detect_face.py文件中定义了函数detect_face
,它能提取输入图像的人脸及其位置。
源文件prepare_training_data.py
import os #引入刚刚编写好的源文件 from detect_face import detect_face import cv2 def prepare_training_data(): #读取训练文件夹中的图片名称 dirs = os.listdir(r'./img_train') faces = [] labels = [] for image_path in dirs: #如果图片的名称以happy开头,则标签为1l;sad开头,标签为2 if image_path[0] == 'h': label = 1 else: label = 2 #得到图片路径 image_path = './img_train/' + image_path #返回灰度图,返回Mat对象 image = cv2.imread(image_path,0) #以窗口形式显示图像,显示100毫秒 cv2.imshow("Training on image...", image) cv2.waitKey(100) #调用我们先前写的函数 face, rect = detect_face(image) if face is not None: faces.append(face) labels.append(label) cv2.destroyAllWindows() cv2.waitKey(1) cv2.destroyAllWindows() return faces, labels
目前为止,我们对图片的预处理已经做好了!
识别器的训练
函数cv2.face.LBPHFaceRecognizer_create()
将返回一个局部二值模式直方图(LBPH)人脸识别器我们可以开始写源文件main.py
了
from prepare_training_data import prepare_training_data import cv2 import numpy as np #该文件我们稍后编写 from predict import predict if __name__ == '__main__': print("Preparing data...") #调用之前写的函数,得到包含多个人脸矩阵的序列和它们对于的标签 faces, labels = prepare_training_data() print("Data prepared") print("Total faces: ", len(faces)) print("Total labels: ", len(labels)) #得到(LBPH)人脸识别器 face_recognizer = cv2.face.LBPHFaceRecognizer_create() #应用数据,进行训练 face_recognizer.train(faces, np.array(labels)) print("Predicting images...") # 加载预测图像,这里我图简单,就直接把路径写上去了 test_img1 = cv2.imread(r"./img_predict/happy1.jpg",0) test_img2 = cv2.imread(r"./img_predict/sad1.jpg",0) # 进行预测 # 注意,该函数我们还未编写!!! predicted_img1 = predict(test_img1, face_recognizer) predicted_img2 = predict(test_img2, face_recognizer) print("Prediction complete") # 显示预测结果 cv2.imshow('Happy', predicted_img1) cv2.imshow('Sad', predicted_img2) cv2.waitKey(0) cv2.destroyAllWindows()
相信到目前为止你已经对opencv的识别过程有了个清晰的认识,接下来我们将编写predict
函数。
预测
源文件predict.py
from detect_face import detect_face # 这两个文件我们还未编写 from draw_rectangle import draw_rectangle from draw_text import draw_text def predict(test_img, face_recognizer): # 将标签1,2转换成文字 subjects = ['', 'Happy', 'Sad'] # 得到图像副本 img = test_img.copy() # 从图像中检测脸部 face, rect = detect_face(img) # 使用我们的脸部识别器预测图像 label = face_recognizer.predict(face) # 获取由人脸识别器返回的相应标签的名称 label_text = subjects[label[0]] # 注意,下面两个函数我们还未编写!!! # 在检测到的脸部周围画一个矩形 draw_rectangle(img, rect) # 在矩形周围标出人脸情绪 draw_text(img, label_text, rect[0], rect[1] - 5) return img
程序的主要部分我们已经完成,还差draw_rectangle
,和draw_text
两个函数,我们将其完成:
源文件draw_rectangle.py
import cv2 def draw_rectangle(img, rect): (x, y, w, h) = rect cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
源文件draw_text.py
import cv2 def draw_text(img, text, x, y): cv2.putText(img, text, (x, y), cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 255, 0), 2)
大功告成!接下来我们运行main.py
,得到识别结果:
可以看到识别结果还不错,如果增加训练集应该能训练出一个不错的情绪识别器。