【人脸识别】一个简单的Python人脸识别应用 - 包含UI 支持训练自己的数据集

一个简单的人脸识别应用 - 包含UI 支持训练自己的数据集

简单易用;无需使用Pytorch或Tensorflow等机器学习框架,基于Face-Recognition库提取特征向量,使用scikit-learn的SVC作为分类方法

特性

  1. 基于Tkinter的GUI库,提供了一个简单美观的界面
  2. 原文件使用的是 Georgia Tech 面部识别数据集 ,也支持训练你自己的数据集
  3. 较高的精度:在该数据集上可以达到98.66%的准确率

Face Recognition库

本项目受Github项目ageitgey/face_recognition启发,它使用到的卷积神经网络结构如下:网络结构
经过作者训练得到的深度卷积神经网络能够在人脸识别挑战Labeled Faces in the Wild Home中获得99.38%的准确率,该模型以C++库的形式封装在了Python库face-recognition中,保证了调用的高效性和效果的可复现性,使用者无需在大型训练集上重新训练,只需以Python API的形式直接在程序内调用。

经过该深度卷积神经网络的特征提取,将会产生一组128维的向量,由于类别数小于特征数,以及推理时间等因素,本项目使用到的方法就没有采用全连接层与Softmax的端对端结构,而是采用了一个类似于R-CNN(Girshick et al., 2014)的结构:特征提取与分类网络分离,其特征提取网络使用深度卷积神经网络、分类网络采用支持向量机(Support Vector Machine, SVM)。具体的,其约束目标可以写作:
SVM
其中,C取正数,其值越大表示对误差的关注程度越高。

为了验证识别方法的性能,本项目在实现的方法上使用了K折交叉验证,本项目设置的K值为5。经验证,本项目使用的方法兼顾了识别效率和识别准确率,5折交叉验证的准确率为98.66%,原始分辨率下的推理时间为120ms。总体识别网络的结构为:
在这里插入图片描述

程序设计

本项目将数据集中的文件读入,使用face-recognition库中的深度卷积神经网络进行面部特征提取和编码,每张图片生成一个128维的向量。由于度卷积神经网络的推理速度较慢,读取一张图片返回结果的平均时间在1s以上,因此在读取数据集后将会对内存中的两个数组进行持久化处理,保存为data_list.p(pickle数据类型),方便分类模型下次直接读取训练。

如果使用自己的数据集或GT数据集,请将它放置在 /gt_db 目录下,该目录结构应当像这样:

gt_db
├─ s01 # 人名
│    ├─ 01.jpg 
│    ├─ ...
│    └─ 15.jpg # 该人名下的照片
├─ ...
└─ s50

其人脸分类流程与训练过程一次正向传播类似:使用深度卷积神经网络进行面部特征提取→使用支持向量机对该128维特征向量进行分类,如果含有多张人脸,则按顺序依次进行分类→返回结果并传递给UI,显示在输出框中。

以下是程序运行效果图:
在这里插入图片描述

代码

工具类

生成和加载编码文件

使用face-recognition库进行面部特征提取生成面部编码,遍历数据集得到对应姓名标签,并将编码-标签文件以pickle文件的形式存储在根目录下。

def generate_file(train_directory):
    _encodings = []
    _names = []
    for person in tqdm.tqdm(train_directory):
        if ".DS_Store" not in person: # .DS_Store文件是文件系统下的一类隐藏文件,遍历时需要排除
            pix = os.listdir('gt_db/' + person)  # 人名类似 s01, s02 etc.

            # 遍历该层级下所有照片
            for person_img in pix:
                if ".DS_Store" not in person_img:
                    # 获取所有面部编码
                    face = face_recognition.load_image_file('gt_db/' + person + "/" + person_img)
                    face_bounding_boxes = face_recognition.face_locations(face, model="cnn")
                    # 可能会出现无法识别/超过一个人的情况,无法用作训练集
                    if len(face_bounding_boxes) == 1:
                        face_enc = face_recognition.face_encodings(face)[0]
                        # 加入编码
                        _encodings.append(face_enc)
                        _names.append(person)
                    else:
                        print('')
                        print('Warning: ' + person + "/" + person_img + " was skipped and can't be used for training")
    data_file = open('data_list.p', 'wb')
    pickle.dump([_encodings, _names], data_file)
    data_file.close()
    print('data_list.p has been generated in the root')
    return _encodings, _names
 
def load_params(re_generate):
    if not re_generate:
        file = open('data_list.p', 'rb')
        _lists = pickle.load(file)
        _encodings = _lists[0]
        _names = _lists[1]
    else:
        _encodings, _names = generate_file(train_dir)
    return _encodings, _names

注意:在 /utils.py 的第25行,可以设置face-recognition库的识别方式,在本项目中,默认识别方式为CNN,即代码中表现为
face_locations = face_recognition.face_locations(_test_image, model="cnn"),如果想要更快的识别效率,可以将 model="cnn"删去,此时使用的是HOG进行识别。更改之后pickle文件的生成速度也会快两倍以上。

输入并产生结果

对验证或测试图像使用face-recognition库进行面部特征提取生成面部编码,通过分类器得到最终识别结果 。

def test_image(_clf, image_loc='test.jpg'):
    # 载入数据
    _test_image = face_recognition.load_image_file(image_loc)

    face_locations = face_recognition.face_locations(_test_image, model="cnn")
    no = len(face_locations)
    print("Number of faces detected: ", no)

    print("Found:")
    names = []
    for i in range(no):
        test_image_enc = face_recognition.face_encodings(_test_image)[i]
        name = _clf.predict([test_image_enc])
        names.append(name[0])
        print(*name)
    return names
K折交叉验证
def evaluate(encodings, names):
    clf_all = svm.SVC(kernel='linear')  # 创建线性核SVM
    scores_cv = cross_val_score(clf_all, encodings, names, cv=5)  # 5折交叉验证
    clf_all.fit(encodings, names)  # 拟合数据集
    print("Cross validation scores: {}".format(scores_cv))
    return scores_cv, clf_all

图形界面

MainWindow类

继承自Tkinter,用于完成主界面的显示

class MainWindows(tk.Tk):
    def __init__(self):
        super().__init__()  # 初始化基类
        self.title("Face Recognition Master")
        self.resizable(width=False, height=False)
        self.minsize(640, 320)
        self.tabControl = ttk.Notebook(self)  # 创建标签栏整体
        self.tab1 = ttk.Frame(self.tabControl)  # 创建标签栏1
        self.tab2 = ttk.Frame(self.tabControl)  # 创建标签栏2
        self.tab3 = ttk.Frame(self.tabControl)  # 创建标签栏3
        self.menu_bar = Menu(self)  # 创建菜单栏
        self.init_ui()
        self.selected_files = []  # 被选中的文件,获取识别结果被使用
        self.photo_libs = []  # 本地图片库
        self.feature_libs = []  # 本地特征向量库
        self.lib_path = 'gt_db/'  # 本地库文件路径
        self.update_treeview()

    def init_ui(self):  # 初始化 UI界面
        self.tabControl.add(self.tab1, text='model') 
        self.tabControl.add(self.tab2, text='face recognition')
        self.tabControl.add(self.tab3, text='database') 
        self.tabControl.pack(expand=1, fill="both") 

        self.init_tab1()
        self.init_tab2()
        self.init_tab3()

        self.config(menu=self.menu_bar)
        self.init_menu()
文件读取和编码操作
def select_file(self):  # 选择文件进行测试
    self.selected_files = []
    ftypes = [('Image Files', '*.tif *.jpg *.png')]
    dlg = filedialog.Open(filetypes=ftypes, multiple=True)
    filename = dlg.show()
    self.selected_files = filename
    return filename

def select_btn_tab2(self):  # 交互操作反馈(返回图片)
    self.show_img([self.label_rec], self.select_file())

def get_result2(self):  # 返回结果(预测值),如果没有已训练模型将会提示
    global clf
    if clf is None:
        self.name2.set('⚠️ Please train a model first! (go to <model> page)')
    if len(self.selected_files) >= 1 and clf is not None:
        file = self.selected_files[0]
        names = test_image(clf, image_loc=file)
        list_ = ' '.join(str(name) for name in names)
        self.name2.set(list_)

参考文献

Girshick, Ross, et al. “Rich feature hierarchies for accurate object detection and semantic segmentation.” Proceedings of the IEEE conference on computer vision and pattern recognition. 2014.
H.-W. Ng, S. Winkler. A data-driven approach to cleaning large face datasets. Proc. IEEE International Conference on Image Processing (ICIP), Paris, France, Oct. 27-30, 2014
O. M. Parkhi, A. Vedaldi, A. Zisserman Deep Face Recognition British Machine Vision Conference, 2015.

代码

全部代码已上传至Github仓库
https://github.com/HaoyuCui/Simple-Face-Recognition
[ 此Repo遵守Apache-2.0协议 ]
如果我的工作对你有帮助,欢迎点赞及Star!

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值