1. 读入数据
使用了att_faces数据集, 存储格式为/att_faces/s1/1.pgm, 因此需要写个读入函数读取主文件夹下所有文件夹下的所有文件:
os.walk(path) 遍历path路径返回信息:
- root: path根路径
- dirs: path下的所有文件夹, 不递归
- files: path下的所有文件, 不递归
#%%
from cv2 import cv2
import matplotlib.pyplot as plt
import os
import numpy as np
import re
def readimgs(path):#读取所有文件
imgs=[]
labels=[]
for root,dirnames,f, in os.walk(path):#取得所有文件夹
for dir in dirnames:#遍历子文件夹
path2=os.path.join(path,dir)
for r,d,files, in os.walk(path2):#对文件夹取所有文件
for onefile in files:#对每个文件添加到列表中
path3=os.path.join(path2,onefile)
img=cv2.imread(path3)
img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转灰度
imgs.append(img)#添加到图片集
labels.append(int(re.sub("\\D","",dir)))#文件夹名作为标签
return imgs,labels
2. cv2.Eigenfaces训练
也可以换成Fisherface, 用法一样, 不过Eigen原理是PCA, Fisher原理是LDA
分割好训练集和测试集, att_faces数据中每个人有10张图片, 因此我每个人留了第一张作为测试集.
EigenFaceRecognizer_create(num_components = 0, threshold = DBL_MAX ):
- num_components, 保留的主成分数
- threshold, 预测时的阈值设置
- 返回一个识别模型
model.train(src, labels):
- src: 数据组, 具体到图像就是图像顺序容器, 例如vector<Mat>, [img1,img2,....]
- labels: 给定标签, 标签顺序不重要, 只要保证图像和标签对应即可. 顺序容器如Vector, 或者Mat (虽然我的list一定要转换为array才行...)
#%%主函数训练
if __name__ == "__main__":
#读取全部文件
imgs,labels=readimgs("./att_faces")
#划分训练集 测试集
testimgs=[]
testlabels=[]
trainimgs=[]
trainlabels=[]
for i in range(len(labels)):
if(i%10==0):#每10张, 即每一组留一张作为测试集
testimgs.append(imgs[i])
testlabels.append(labels[i])
else:
trainimgs.append(imgs[i])
trainlabels.append(labels[i])
trainlabels=np.asarray(trainlabels)
model = cv2.face.EigenFaceRecognizer_create()
model.train(trainimgs,trainlabels)
3. Eigenfaces预测
预测就是对之前保留的测试集, 一一预测并且检验正确率.
model.predict(data): 模型对data进行预测, 返回output[2]
- output[0], label, 即预测的标签.
- output[1], confidence, 即置信度, 注意confidence是越高越不相似
#%% 验证
count=0
for i in range(0,len(testlabels)):
test_img=testimgs[i]
output=model.predict(test_img)#对测试集每个图片进行预测
if(output[0]==testlabels[i]):#结果和真实标签比较
count+=1
print(count/len(testlabels))#输出成功率
输出效果如下: 准确率达到0.975
存在一个错误样例: