1 # 通过图片识别人脸 2 3 #1.概述: 人脸识别,是基于人的脸部特征信息进行身份识别的一种生物识别技术。用摄像机或摄像头采集含有人脸的图像或视频流,并自动在图像中检测和跟踪人脸,进而对检测到的人脸进行脸部的一系列相关技术,通常也叫做人像识别、面部识别。 4 5 # 2、人脸识别步骤 6 # 1 人脸图像采集及检测 7 # 2 人脸图像预处理 8 # 3 人脸图像特征提取以及匹配与识别 9 10 # 3、 人脸识别的方法 11 # 在OpenCV中主要使用了两种特征(即两种方法)进行人脸检测,Haar特征和LBP特征。使用已经训练好的XML格式的分类器进行人脸检测。在OpenCV的安装目录下的data文件夹里可以看到下图所示的内容(D:\PROFESSION_\PYTHON_\Lib\site-packages\cv2\data): 12 13 import os 14 import cv2 15 from PIL import Image, ImageDraw 16 from datetime import datetime 17 import time 18 19 20 # detectFaces()返回图像中所有人脸的矩形坐标(矩形左上、右下顶点) 21 # 使用haar特征的级联分类器haarcascade_frontalface_default.xml,在haarcascades目录下还有其他的训练好的xml文件可供选择。 22 # 注:haarcascades目录下训练好的分类器必须以灰度图作为输入。 23 def detectFaces(image_name): 24 img = cv2.imread(image_name) 25 face_cascade = cv2.CascadeClassifier("D:\PROFESSION_\PYTHON_\Lib\site-packages\cv2\data/haarcascade_frontalface_default.xml") 26 if img.ndim == 3: 27 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 28 print('转换灰度图成功','gray.ndim',gray.ndim) 29 else: 30 gray = img # if语句:如果img维度为3,说明不是灰度图,先转化为灰度图gray,如果不为3,也就是2,原图就是灰度图 31 print('我本来就是灰度图') 32 faces = face_cascade.detectMultiScale(gray, 1.3, 5) # 1.3和5是特征的最小、最大检测窗口,它改变检测结果也会改变 33 result = [] 34 for (x, y, width, height) in faces: 35 result.append((x, y, x + width, y + height)) 36 # print(result) [(148, 33, 210, 95), (51, 46, 110, 105), (306, 49, 369, 112)] 37 return result 38 39 40 # 保存人脸图 41 def saveFaces(image_name): 42 faces = detectFaces(image_name) 43 print('faces',faces) 44 if faces: 45 # 将人脸保存在save_dir目录下。 46 # Image模块:Image.open获取图像句柄,crop剪切图像(剪切的区域就是detectFaces返回的坐标),save保存。 47 save_dir = image_name.split('.')[0] + "_faces" 48 print('save_dir',save_dir) 49 os.mkdir(save_dir) 50 count = 0 51 for (x1, y1, x2, y2) in faces: 52 file_name = os.path.join(save_dir, str(count) + ".jpg") 53 Image.open(image_name).crop((x1, y1, x2, y2)).save(file_name) 54 count += 1 55 56 57 # 在原图像上画矩形,框出所有人脸。 58 # 调用Image模块的draw方法,Image.open获取图像句柄,ImageDraw.Draw获取该图像的draw实例,然后调用该draw实例的rectangle方法画矩形(矩形的坐标即 detectFaces返回的坐标),outline是矩形线条颜色(B,G,R)。 59 # 注:原始图像如果是灰度图,则去掉outline,因为灰度图没有RGB可言。drawEyes、detectSmiles也一样。 60 61 def drawFaces(image_name): 62 faces = detectFaces(image_name) 63 if faces: 64 img = Image.open(image_name) 65 draw_instance = ImageDraw.Draw(img) 66 for (x1, y1, x2, y2) in faces: 67 draw_instance.rectangle((x1, y1, x2, y2), outline=(255, 0, 0)) 68 img.save('drawfaces_' + image_name) 69 70 71 # 检测眼睛,返回坐标 72 # 由于眼睛在人脸上,我们往往是先检测出人脸,再细入地检测眼睛。故detectEyes可在detectFaces基础上来进行,代码中需要注意“相对坐标”。# 当然也可以在整张图片上直接使用分类器,这种方法代码跟detectFaces一样,这里不多说。 73 def detectEyes(image_name): 74 eye_cascade = cv2.CascadeClassifier('D:\PROFESSION_\PYTHON_\Lib\site-packages\cv2\data/haarcascade_eye.xml') 75 faces = detectFaces(image_name) 76 77 img = cv2.imread(image_name) 78 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 79 result = [] 80 for (x1, y1, x2, y2) in faces: 81 roi_gray = gray[y1:y2, x1:x2] 82 eyes = eye_cascade.detectMultiScale(roi_gray, 1.3, 2) 83 for (ex, ey, ew, eh) in eyes: 84 result.append((x1 + ex, y1 + ey, x1 + ex + ew, y1 + ey + eh)) 85 return result 86 87 88 # 在原图像上框出眼睛. 89 def drawEyes(image_name): 90 eyes = detectEyes(image_name) 91 if eyes: 92 img = Image.open(image_name) 93 draw_instance = ImageDraw.Draw(img) 94 for (x1, y1, x2, y2) in eyes: 95 draw_instance.rectangle((x1, y1, x2, y2), outline=(0, 0, 255)) 96 img.save('draweyes_' + image_name) 97 98 99 # 检测笑脸 100 def detectSmiles(image_name): 101 img = cv2.imread(image_name) 102 smiles_cascade = cv2.CascadeClassifier("D:\PROFESSION_\PYTHON_\Lib\site-packages\cv2\data/haarcascade_smile.xml") 103 if img.ndim == 3: 104 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 105 else: 106 gray = img # if语句:如果img维度为3,说明不是灰度图,先转化为灰度图gray,如果不为3,也就是2,原图就是灰度图 107 108 smiles = smiles_cascade.detectMultiScale(gray, 4, 5) 109 result = [] 110 for (x, y, width, height) in smiles: 111 result.append((x, y, x + width, y + height)) 112 return result 113 114 115 # 在原图像上框出笑脸 116 def drawSmiles(image_name): 117 smiles = detectSmiles(image_name) 118 if smiles: 119 img = Image.open(image_name) 120 draw_instance = ImageDraw.Draw(img) 121 for (x1, y1, x2, y2) in smiles: 122 draw_instance.rectangle((x1, y1, x2, y2), outline=(100, 100, 0)) 123 img.save('drawsmiles_' + image_name) 124 125 126 127 128 129 130 131 if __name__ == '__main__': 132 time1 = datetime.now() 133 result = detectFaces('d.jpg') 134 time2 = datetime.now() 135 print("耗时:" + str(time2 - time1)) 136 if len(result) > 0: 137 print("有人存在!!---》人数为:" + str(len(result))) 138 else: 139 print('视频图像中无人!!') 140 141 # drawFaces('d.jpg')#框出脸 142 # drawSmiles('d.jpg')#框出笑脸 143 # drawEyes('d.jpg') #框出眼睛 144 145 146 """ 147 上面的代码将眼睛、人脸、笑脸在不同的图像上框出,如果需要在同一张图像上框出,改一下代码就可以了。 148 总之,利用opencv里训练好的haar特征的xml文件,在图片上检测出人脸的坐标,利用这个坐标,我们可以将人脸区域剪切保存,也可以在原图上将人脸框出。剪切保存人脸以及用矩形工具框出人脸,本程序使用的是PIL里的Image、ImageDraw模块。 149 此外,opencv里面也有画矩形的模块,同样可以用来框出人脸。 150 """ 151 # --------------------- 152 # 作者:wsywb111 153 # 来源:CSDN 154 # 原文:https://blog.csdn.net/wsywb111/article/details/79152425 155 # 版权声明:本文为博主原创文章,转载请附上博文链接!