python人脸识别(四)

7 人脸识别和应用

7.1 训练模型

python人脸识别(四)_第1张图片

python人脸识别(四)_第2张图片

python人脸识别(四)_第3张图片

7.2最终代码

# -*- coding: utf-8 -*-
"""
Created on Tue Feb 26 14:24:07 2019

@author: fancheyu
"""

#导入模块
from sklearn import neighbors
import os
import os.path
import pickle
from PIL import Image,ImageDraw
import face_recognition as fr
from face_recognition.face_recognition_cli import image_files_in_folder

#函数定义
#训练
def train(train_dir,model_save_path='trained_knn_madel.clf',n_neighbors=3,knn_algo='ball_tree'):
    """
    训练一个KNN分类器
    :param train_dir
    :param model_save_path
    :param n_neighbors 
    :param knn_algo
    return:KNN分类器
    """
    
    #初始化训练集
    X = []
    y = []
    
    #遍历训练集中的每个人
    for class_dir in os.listdir(train_dir):
        if not os.path.isdir(os.path.join(train_dir,class_dir)):
            continue 
    #加载图片
        for img_path in image_files_in_folder(os.path.join(train_dir,class_dir)):
            image = fr.load_image_file(img_path)
            boxes = fr.face_locations(image)
            print("{}".format(img_path))
            #对每张照片编码
            X.append(fr.face_encodings(image,known_face_locations=boxes)[0])
            y.append(class_dir)
        
    #确定k
    if n_neighbors is None:
        n_neighbors = 3 
        
    #训练出分类器
    knn_clf = neighbors.KNeighborsClassifier(n_neighbors=n_neighbors)
    knn_clf.fit(X,y)
    
    #保存分类器
    if model_save_path is not None:
        with open(model_save_path,'wb') as f:
            pickle.dump(knn_clf,f)
    #返回分类器
    return  knn_clf
        
#预测
def predict(X_img_path,knn_clf=None,model_path=None,distance_threshold = 0.45):
    """
    利用KNN分离器识别
    :return :[人名,边界,...]
    """
    
    if knn_clf is None and model_path is None:
        raise Exception("请选择KNN分类器方式:knn_clf 或 model_path")
        
    #加载KNN模型
    #rb读入二进制数据
    if knn_clf is None:
        with open(model_path,'rb') as f:
            knn_clf = pickle.load(f)
            
    #加载图片,发现人脸位置
    X_img = fr.load_image_file(X_img_path)
    X_face_locations = fr.face_locations(X_img)
    
    #编码
    encodings = fr.face_encodings(X_img,known_face_locations=X_face_locations)
    
    #利用KNN找出匹配图片
    closest_distances = knn_clf.kneighbors(encodings,n_neighbors = 3)
    are_matches = [closest_distances[0][i][0] <= distance_threshold for i in range(len(X_face_locations))]
    
    #判断类别
    return[(pred,loc) if rec else ("unknown",loc) for pred,loc,rec in zip(knn_clf.predict(encodings),X_face_locations,are_matches)]
            
#识别结果可视化
def show_names_on_image(img_path,predictions)    :
    """
    :param img_path:待识别图片位置
    :Param prediction:预测结果
    """
    
    pil_image = Image.open(img_path).convert("RGB")
    draw = ImageDraw.Draw(pil_image)
    
    #画出人脸边界盒子
    for name,(top,right,bottom,left) in predictions:
        draw.rectangle(((left,top),(right,bottom)),outline = (225,0,255))

    #生成utf-8格式
    name = name.encode("UTF-8")
    name = name.decode("ascii")
    
    #写下名字作为标签
    text_width,text_height = draw.textsize(name)
    draw.rectangle(((left,bottom - text_height - 10),(right,bottom)),fill = (225,0,255),outline = (225,0,255))
    draw.text((left+6,bottom - text_height - 5),name,fill = (255,255,255))
    
    #名字列表
    li_names.append(name)
    
    #从内存删除
    del draw
    
    #显示结果图 
    pil_image.show()
    
#统计分析
    
li_names = []
    
#计算总人数
def count(train_dir):
    path = train_dir
    count = 0
    for fn in os.listdir(path):#fn代表文件夹
        count = count + 1
    return count
            
#获取所有名字的列表
def list_all(train_dir):
    path = train_dir
    result = []
    for fn in os.listdir(path):
        result.append(fn)
    return result
            
#输出结果
def stat_output():
    s_list = set(li_names)
    s_list_all = set(list_all("examples/train"))
    if "unknown" in s_list:
        s_list.remove("unknown")
        
    tot_num = count("examples/train")
    s_absent = set(s_list_all - s_list)
    print("\n")
    print("==================================================================")
    print("全体名单",s_list_all)
    print("已到名单",s_list)
    print("应到人数",tot_num)
    print("已到人数",len(s_list))
    print("出勤率:{:.2f}".format(float(len(s_list))/float(tot_num)))
    print("未到",s_absent)
    print("==================================================================")
            
#运行
if __name__ ==  "__main__":
    #1.训练分类器
    print("正在训练KNN分类器请稍后...")
    print("训练详情:")
    train("examples/train",model_save_path="trained_knn_model.clf",n_neighbors=3)
    print("训练完成!")
    #2.利用训练好的模型预测新照片
    for image_file in os.listdir("examples/test"):
        full_file_path = os.path.join("examples/test",image_file)
        
        #利用分类器找出人脸
        predictions = predict(full_file_path,model_path = "trained_knn_model.clf")
    #3.输出结果
        #打印
        print("识别结果如下:")
        for name,(top,right,bottom,left) in predictions:
            print("发现{},位置:{},{}.".format(name,top,right))
        #显示名字
        show_names_on_image(os.path.join("examples/test",image_file),predictions)
        
        #统计数据
        stat_output()
        

7.3结果

python人脸识别(四)_第4张图片

python人脸识别(四)_第5张图片

代码和测试文件已经上传github https://github.com/viafcccy/python-

也可以在CSDN下载来支持我 https://download.csdn.net/download/viafcccy/10979314

你可能感兴趣的:(py入门,图像处理,图像处理,python入门与实战)