一.实验内容
使用opencv来进行特征提取过程,分别采用opencv的高级API和opencv的底层API进行人脸识别,由于我们要学习整个人脸识别的处理流程,所以这里以底层实现方法作为重点。
在特征提取出来后,分别采用欧氏距离和SVM的方法进行人脸识别。
二.实验步骤
本实验的项目的主要文件包括Recognize_e.py(底层API实现),Recognize_h.py(高级API实现)
- 底层API
本实验最终的结果是要对于在识别范围内的人,如果出现在摄像头中,则可以识别出每个人的名字,并进行标注,所以本质是一个多分类问题,不同的人分别是不同的类,通过前面一节的特征提取方法(PCA,Fisher,LBP)对特征进行提取后,然后用欧氏距离或SVM对结果进行预测。
- 高级API
最终结果相同,但是对人脸的处理过程略有不同,这里是首先对所有要识别的人脸进行训练,得到一个识别器,随后再用该识别器进行预测,隐藏了很多具体的实现细节
实验主要分为三步:
第一是人脸数据的采集,使用上上节讲的人脸检测程序的衍生程序DataCollect.py来采集和保存;
第二是人脸特征的处理,使用上节讲的人脸特征处理程序Feature.py来进行采集和保存
第三是新人脸的预测,也是本节的主要内容。
其中本节的主要文件Recognize_e.py,里面调用了第一二步,实现了第三步
第一步:训练数据的获取
这一步是通过获取由DataCollect文件夹中的图片,并进行处理,构造特征标签数据集,其中特征就是一张张图片,标签就是每一张图片对应的人的编号。这里我们同一个人的图片存储在同一个文件夹中,所以每个文件夹都对应一个标签。
数据集主要构造是在下面的函数中,通过对每个文件夹中数据进行读取,灰度化,矩阵化,并加上标签,构建出数据集
def read_images(pathes):
'''
构建数据集,从文件夹中读取图片
:param pathes: 读取数据的路径
:return: 读取后得到的X和y
'''
label_num=1
face_samples = []
ids = []
for path in pathes:
#用path可以自动加/,可以跨平台,错误率低
image_paths = [os.path.join(path, f) for f in os.listdir(path)]
#对图片进行一定的处理
for image_path in image_paths:
#运用PIL库转化为灰度图像,这里也可以用opencv库
image = Image.open(image_path).convert('L')
#将图像变成ndarray的形式便于进行处理
image_np = np.array(image, 'uint8')
#将当前图片矩阵加入到图片集合中
face_samples.append(image_np)
#将标签加入标签集合中
ids.append(label_num)
label_num+=1
return [face_samples,ids]
下面时在本项目对应的函数中的调用
# 计算特征提取模型
# 构造数据集
global label
[X, label] = read_images(dirs)
第二步:人脸特征的处理,具体的提取方法我们在上一个实验已经讲述过,这里不再赘述。本实验主要看时如何调用的,这里以LBP为例。
projection_l = lbpface(X, label)
print("模型加载成功!")
其中这里projection_l是训练数据经过LBP处理后得到的特征处理好的新训练数据。如果后面使用欧氏距离的方法则可以直接进行比对,如果后面使用SVM的方法则可以直接用这些数据和对应的标签进行训练
所以数据就可以看成类似与下面的形式
第三步:新人脸的预测
(1)欧氏距离方法:
对于欧式距离的方法,则可以直接用与对训练数据相同的特征提取方法对新图片的特征进行提取之后,与上面的人脸数据一一进行比对,然后得出来对应的数据标签即可。
这里同样用lbp为例
下面的recognizerpredict3就是具体实现调用
while True:
# 读取一帧
ret, im = cam.read()
# 灰度化
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
# 对图像(灰度图像)进行目标检测
faces = face_cascade.detectMultiScale(gray, 1.2, 5)
for (x, y, w, h) in faces:
cv2.rectangle(im, (x - 50, y - 50), (x + w + 50, y + h + 50), (225, 0, 0), 2)
# 找到灰度图像进行预测,这里一个是为了与原来相匹配,一个是为了减少计算量
image = gray[y - 10: y + h + 10, x - 10: x + w + 10]
image = cv2.resize(image, (185, 185))
'''
预测部分
'''
img_id = recognizerpredict3(image,projection_l)
img_id=dirs[img_id-1][9:]
# cv2.cv.PutText(cv2.cv.fromarray(im), str(Id), (x, y + h), font, 255)
cv2.putText(im, str(img_id), (x, y), font, 1, (0, 255, 0), 1)
cv2.imshow('im', im)
下面是recognizerpredict3,包括处理和比较两个过程
def recognizerpredict3(image,projection):
'''
这里是专门给lbp方法准备的
:param image:输入的图片
:param projection:数据在新的特征空间中的表示
:return:预测出的类
'''
#将image变成可以处理的形状
mindist=9999999
minclass=-1
#处理image,将image换一种表示方式
#image (185,185)
image=LBP(image)
#image (185,185)
image=calLbpHistogram(image).ravel()
#image (1,5*37*59)
for i in range(len(projection)):
#进行比较
dist=distance(projection[i],image)
if dist<mindist:
mindist=dist
minClass=label[i]
return minClass
(2)SVM方法
对于SVM方法,我们先用上一步得到的数据集进行训练,然后再进行预测
这里以lbp为例,首先就是调用sklearn中的SVM中的SVC方法,得到一个SVM分类模型
# 2.SVC 机器学习方法
svc = LinearSVC()
projection_l = lbpface(X, label)
print(list(zip(projection_l, label)))
print("模型加载成功!")
svc.fit(projection_l, label)
print("模型拟合成功!")
然后就进行对新的人脸进行预测
def recognizerpredict4(image,model):
'''
采取SVM的方式来预测
:param image:输入的数据
:param model:预测使用的模型
:return:预测出来的类别
'''
#处理image,将image换一种表示方式
#image (185,185)
image=LBP(image)
#image (185,185)
image=calLbpHistogram(image).ravel()
#image (1,5*37*59)
image=image.reshape(1,-1)
mclass=model.predict(image)
return mclass
最终的效果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M7FjUeBd-1591925757848)(/home/tina/.config/Typora/typora-user-images/image-20200102164407876.png)]