模式识别课程设计,OpenCV实现⼈脸识别以及识别率,Python(完整代码)项⽬背景
对“待分类”中的每⼀个图像,根据模式识别算法判断它与“已知类别”中哪⼀个图像最相似。
如果最相似的图像与它的⽂件名前四个字符相同,则说明识别正确,否则是识别错误。
计算出识别率:“待分类”中识别正确的图像个数 除以 “待分类”中的图像总数。
项⽬中的主要算法:
局部⼆值模式直⽅图(LBPH)⼈脸识别器 :
Eigenfaces和Fisherfaces⼈脸识别算法都受光线影响,在现实⽣活中,我们⽆法保证完美的光照条件。 LBPH⼈脸识别器是克服这个缺点的⼀种改进。
LBPH,Local Binary Patterns Histograms,即LBP特征的统计直⽅图,LBPH将LBP特征与图像的空间信息结合在⼀起。这种表⽰⽅法由Ahonen等⼈在论⽂中提出,他们将LBP特征图像分成m个局部块,并提取每个局部块的直⽅图,然后将这些直⽅图依次连接在⼀起形成LBP特征的统计直⽅图,即L
BPH。
该算法不看整个图像,⽽是查图像的局部特征。 LBPH算法试图出图像的局部结构,并通过⽐较每个像素与其相邻像素来实现。
LBP原理介绍以及算法实现:
LBP(Local Binary Pattern,局部⼆值模式)是⼀种⽤来描述图像局部纹理特征的算⼦;它具有旋转不变性和灰度不变性等显著的优点。它⽤于纹理特征提取。⽽且,提取的特征是图像的局部的纹理特征。
1、LBP特征的描述
原始的LBP算⼦定义为在33的窗⼝内,以窗⼝中⼼像素为阈值,将相邻的8个像素的灰度值与其进⾏⽐较,若周围像素值⼤于中⼼像素值,则该像素点的位置被标记为1,否则为0。这样,33邻域内的8个点经⽐较可产⽣8位⼆进制数(通常转换为⼗进制数即LBP码,共256种),即得到该窗⼝中⼼像素点的LBP值,并⽤这个值来反映该区域的纹理信息。如下图所⽰:
图2.1 LBP特征的描述图
2、LBP特征⽤于检测的原理
提取的LBP算⼦在每个像素点都可以得到⼀个LBP“编码”,那么,对⼀幅图像(记录的是每个像素点的灰度值)提取其原始的LBP算⼦之后,得到的原始LBP特征依然是“⼀幅图⽚”(记录的是每个像素点的LBP值)。
(a)原始图像 (b)LBP图谱
图2.2 不同光照程度下的LBP图像
从上图可以看出LBP对光照具有很强的鲁棒性。
LBP的应⽤中,如纹理分类、⼈脸分析等,⼀般都不将LBP图谱作为特征向量⽤于分类识别,⽽是采⽤LBP特征谱的统计直⽅图作为特征向量⽤于分类识别。
因为,从上⾯的分析我们可以看出,这个“特征”跟位置信息是紧密相关的。直接对两幅图⽚提取这种“特征”,并进⾏判别分析的话,会因为“位置没有对准”⽽产⽣很⼤的误差。后来,研究⼈员发现,可以将⼀幅图⽚划分为若⼲的⼦区域,对每个⼦区域内的每个像素点都提取LBP特征,然后,在每个⼦区域内建⽴LBP特征的统计直⽅图。如此⼀来,每个⼦区域,就可以⽤⼀个统计直⽅图来进⾏描述;整个图⽚就由若⼲个统计直⽅图组成;
例如:⼀幅100100像素⼤⼩的图⽚,划分为1010=100个⼦区域(可以通过多种⽅式来划分区域),每个⼦区域的⼤⼩为1010像素;在每个⼦区域内的每个像素点,提取其LBP特征,然后,建⽴统计直⽅图;这样,这幅图⽚就有1010个⼦区域,也就有了1010个统计直⽅图,利⽤这1010个统计直⽅图,就可以描述这幅图⽚了。之后,我们利⽤各种相似性度量函数,就可以判断两幅图像之间的相似性了。
3、对LBP特征向量进⾏提取的步骤
(1)⾸先将检测窗⼝划分为16×16的⼩区域(cell);
(2)对于每个cell中的⼀个像素,将相邻的8个像素的灰度值与其进⾏⽐较,若周围像素值⼤于中⼼像素值,则该像素点的位置被标记为1,否则为0。这样,3*3邻域内的8个点经⽐较可产⽣8位⼆进制数,即得到该窗⼝中⼼像素点的LBP值;
图2.3
(3)然后计算每个cell的直⽅图,即每个数字(假定是⼗进制数LBP值)出现的频率;然后对该直⽅图进⾏归⼀化处理。
图2.4:样本直⽅图
(4)最后将得到的每个cell的统计直⽅图进⾏连接成为⼀个特征向量,也就是整幅图的LBP纹理特征向量;然后便可利⽤SVM或者其他机器学习算法进⾏分类了。
(2)程序的实现步骤和思路:
1、准备训练数据:在这⼀步中,我们将遍历“已知分类”的⽂件夹,读取每个⼈/主体的训练图像及其标签,从每个图像中检测⼈脸并为每个检测到的⼈脸分配其所属⼈员的整数标签。
2、训练⼈脸识别器:在这⼀步中,我们将训练OpenCV的LBPH⼈脸识别器,为其提供我们在步骤1中准备的数据。
3、测试:在这⼀步中,我们会将遍历“待分类”的⽂件夹,将图像传递给⼈脸识别器,通过返回值在图⽚的⼈脸中绘制出来识别出来的名字,并判断它是否能够正确预测它们,最后通过识别正确的数量与图⽚数量之⽐获得识别率。
# 导⼊OpenCV模块
import cv2
# 导⼊os模块⽤于读取训练数据⽬录和路径
import os
# 导⼊numpy将python列表转换为numpy数组
#OpenCV⼈脸识别器需要它
import numpy as np
subjects =[""]
#使⽤OpenCV⽤来检测脸部的函数
def detect_face(img):
# 将测试图像转换为灰度图像,因为opencv⼈脸检测器需要灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 加载OpenCV⼈脸检测器
face_cascade = cv2.CascadeClassifier('opencv-files/l')
# 结果是⼀张脸的列表
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5);
# 如果未检测到⾯部,则返回原始图像
if(len(faces)==0):
return None,None
# 只有⼀张脸,
# 提取⾯部区域
(x, y, w, h)= faces[0]
# 只返回图像的正⾯部分
return gray[y:y+w, x:x+h], faces[0]
#该功能将读取所有⼈的训练图像,从每个图像检测⼈脸
#并将返回两个完全相同⼤⼩的列表,⼀个列表
# 每张脸的脸部和另⼀列标签
# 参数为⽬录的path
def prepare_training_data(data_folder_path):
# 列表来保存所有主题的⾯孔
faces =[]
# 列表以保存所有主题的标签
labels =[]
# 获取给定主题⽬录内的图像名称
subject_images_names = os.listdir(data_folder_path)
label =0
# 浏览每个图⽚的名称,阅读图⽚,
# 检测脸部并将脸部添加到脸部列表
for image_name in subject_images_names:
# 忽略.DS_Store之类的系统⽂件
if image_name.startswith("."):
continue;
# 建⽴图像路径
# sample image path = training-data/s1/1.pgm
image_path = data_folder_path +"/"+ image_name
# 阅读图像
image = cv2.imread(image_path)
# print("image_name"+image_name)
# 显⽰图像窗⼝以显⽰图像
cv2.imshow("Training 图⽚"+image_name, size(image,(400,500)))        veWindow("Training 图⽚"+image_name,200,200)
cv2.waitKey(100)
# 侦测脸部
face, rect = detect_face(image)
# 我们将忽略未检测到的脸部
if face is not None:
subjects.append(image_name)
label = label +1;
# 将脸添加到脸部列表
faces.append(face)
# 为这张脸添加标签
labels.append(label)
else:
print("已知分类中没有检测到⼈脸=="+image_name)
cv2.destroyAllWindows()
cv2.waitKey(1)
cv2.destroyAllWindows()
# print("labels" + str(len(labels)))
return faces, labels
#准备好我们的训练数据
#数据将在两个相同⼤⼩的列表中
#⼀个列表将包含所有的⾯孔
#数据将在两个相同⼤⼩的列表中
print("")
#faces, labels = prepare_training_data("./training-data2")
faces, labels = prepare_training_data("./yizhi-fen-lei")
print("Data prepared")
# 打印总⾯和标签
print("Total faces: ",len(faces))
print("Total labels: ",len(labels))
# 训练⼈脸识别器
#
#      OpenCV配备了三个⼈脸识别器。
#
#   1、EigenFaces⼈脸识别器识别器 - ateEigenFaceRecognizer()
#
#   2、FisherFaces⼈脸识别器识别器 - ateFisherFaceRecognizer()
#
rectangle函数opencv#   3、局部⼆值模式直⽅图(LBPH)⼈脸识别器 - ateLBPHFaceRecognizer() #
#  使⽤LBPH⼈脸识别器
#创建LBPH⼈脸识别器
face_recognizer = cv2.face.LBPHFaceRecognizer_create()
#或者使⽤EigenFaceRecognizer替换上⾯的⾏
#face_recognizer = ateEigenFaceRecognizer()
#或者使⽤FisherFaceRecognizer替换上⾯的⾏
#face_recognizer = ateFisherFaceRecognizer()
# 初始化了我们的⼈脸识别器,
# 准备了训练数据,现在是时候训练⼈脸识别器了。
# 通过调⽤⼈脸识别器的序列(⾯向量,标签向量)⽅法来实现这⼀点。
#训练⾯部识别器
ain(faces, np.array(labels))
#函数在图像上绘制矩形
#根据给定的(x,y)坐标和
#给定的宽度和⾼度
def draw_rectangle(img, rect):
(x, y, w, h)= rect
# 函数在从图像开始绘制⽂本
# 通过(x,y)坐标。
def draw_text(img, text, x, y):
cv2.putText(img, text,(x, y), cv2.FONT_HERSHEY_PLAIN,1.5,(0,255,0),2)
# 他的功能可以识别通过图像的⼈
#并在检测到的⾯周围绘制⼀个矩形,
def predict(test_img):
# 制作图像的副本,不更改原始图像
img = py()

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。