前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python3.6+opencv+face_recognition+knn分类器实现人脸识别

python3.6+opencv+face_recognition+knn分类器实现人脸识别

作者头像
andrew_a
发布2019-07-30 15:02:45
2.1K0
发布2019-07-30 15:02:45
举报
文章被收录于专栏:Python爬虫与数据分析

搭环境啥的就不说了, 里面的各种库的安装可以参考我的博客:

https://blog.csdn.net/weixin_39121325/article/details/85247546

注意:在安装face_recognition之前,需要先将dlib安装了,ps(在安装dlib时版本19.7的最好安,可能是兼容性比较好~~O(∩_∩)O哈哈~~)

其他的自行百度~~~

看一下代码结构

faceRecognition_knn

  1. knn_example下分了三个图片集合:

2.model

  • test : 测试图片
  • train :训练集图片(图片集合是在网上下载的)
  • train1 :也是训练集图片(将train训练集图片拆分了的,集合比较小
  • trained_knn_model.clf (保存的是knn分类器训练之后的模型,主要的是图片集合中图片的编码特征)

直接上代码

代码语言:javascript
复制
# -*- coding: utf-8 -*-
# !/usr/bin/env python
# @Time    : 2019/1/10 15:50
# @Author  : xhh
# @Desc    : 利用knn分类器来进行人脸识别
# @File    : face_recognition_knn1.py
# @Software: PyCharm

import math
from sklearn import neighbors
import os
import os.path
import pickle
from PIL import Image, ImageDraw
import face_recognition
from face_recognition.face_recognition_cli import image_files_in_folder

ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg'}


def train(train_dir, model_save_path=None, n_neighbors=None, knn_algo='ball_tree', verbose=False):
    """
    Structure:
        <train_dir>/
        ├── <person1>/
        │   ├── <somename1>.jpeg
        │   ├── <somename2>.jpeg
        │   ├── ...
        ├── <person2>/
        │   ├── <somename1>.jpeg
        │   └── <somename2>.jpeg
        └── ...
    :param train_dir: 训练集地址
    :param model_save_path: 模型所保存的地址
    :param n_neighbors: 在训练时如果没有指定权重,则自动选择权重
    :param knn_algo:
    :param verbose:
    :return: knn_clf返回训练后的模型
    """
    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 = face_recognition.load_image_file(img_path)
            face_bounding_boxes = face_recognition.face_locations(image)
            if len(face_bounding_boxes) != 1:
                # 如果该训练集中没有人或者有很多人,则跳过该图像
                if verbose:
                    print("Image {} not suitable for training: {}".format(img_path,
                                                                          "Didn't find a face" if len(
                                                                              face_bounding_boxes) < 1 else "Found more than one face"))
            else:
                # 将图片中的人脸的编码加入到训练集中
                X.append(face_recognition.face_encodings(image, known_face_locations=face_bounding_boxes)[0])
                y.append(class_dir)
    # 确定KNN分类器中的权重
    if n_neighbors is None:
        n_neighbors = int(round(math.sqrt(len(X))))
        if verbose:
            print("Chose n_neighbors automatically:", n_neighbors)
    # 建立并训练KNN训练集
    knn_clf = neighbors.KNeighborsClassifier(n_neighbors=n_neighbors, algorithm=knn_algo, weights='distance')
    knn_clf.fit(X, y)
    # 保存KNN分类器
    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.6):
    """
    :param X_img_path: 测试集的图片地址
    :param knn_clf: 训练好的模型
    :param model_path: 模型地址
    :param distance_threshold: 给出当前测试图片中的人脸向量与模型中的距离
    :return:
    """
    if not os.path.isfile(X_img_path) or os.path.splitext(X_img_path)[1][1:] not in ALLOWED_EXTENSIONS:
        raise Exception("Invalid image path: {}".format(X_img_path))
    if knn_clf is None and model_path is None:
        raise Exception("Must supply knn classifier either thourgh knn_clf or model_path")

    # 加载KNN模型
    if knn_clf is None:
        with open(model_path, 'rb') as f:
            knn_clf = pickle.load(f)

    # 加载图片文件夹以及人脸
    X_img = face_recognition.load_image_file(X_img_path)
    X_face_locations = face_recognition.face_locations(X_img)

    # 如过图片中没有人脸,则返回空的结果集
    if len(X_face_locations) == 0:
        return []
    # 找出测试集中的人脸编码
    faces_encodings = face_recognition.face_encodings(X_img, known_face_locations=X_face_locations)
    # 利用KNN模型找出测试集中最匹配的人脸
    closest_distances = knn_clf.kneighbors(faces_encodings, n_neighbors=1)
    are_matches = []
    for i in range(len(X_face_locations)):
        are_matches.append(closest_distances[0][i][0] <= distance_threshold)
    # 预测类并删除不在阈值范围内的分类
    return [(pred, loc) if rec else ("unknown", loc) for pred, loc, rec in
            zip(knn_clf.predict(faces_encodings), X_face_locations, are_matches)]


def show_prediction_labels_on_image(img_path, predictions):
    """
    在图片给出标签并展示人脸
    :param img_path: path to image to be recognized
    :param predictions: results of the predict function
    :return:
    """
    pil_image = Image.open(img_path).convert("RGB")
    draw = ImageDraw.Draw(pil_image)
    for name, (top, right, bottom, left) in predictions:
        # 将人脸框出来利用pillow进行标注
        draw.rectangle(((left, top), (right, bottom)), outline=(0, 0, 255))
        name = name.encode("UTF-8")
        # 在人脸下面进行标配注
        text_width, text_height = draw.textsize(name)
        draw.rectangle(((left, bottom - text_height - 10), (right, bottom)), fill=(0, 0, 255), outline=(0, 0, 255))
        draw.text((left + 6, bottom - text_height - 5), name, fill=(255, 255, 255, 255))
    # 根据文档删除标注
    del draw
    # 显示图片结果
    pil_image.show()


if __name__ == "__main__":
    # 1:训练KNN分类器,并保存
    # Once the model is trained and saved, you can skip this step next time.
    # print("Training KNN classifier...")
    # classifier = train("knn_examples/train1", model_save_path="model/trained_knn_model.clf", n_neighbors=2)
    # print("Training complete!")

    # STEP 2: 利用分类器,来预测该图片是否为已知的
    for image_file in os.listdir("knn_examples/test"):
        full_file_path = os.path.join("knn_examples/test", image_file)
        print("Looking for faces in {}".format(image_file))
        # Find all people in the image using a trained classifier model
        # Note: You can pass in either a classifier file name or a classifier model instance
        predictions = predict(full_file_path, model_path="model/trained_knn_model.clf")
        # 在控制台打印结果
        for name, (top, right, bottom, left) in predictions:
            print("- Found {} at ({}, {})".format(name, left, top))
        # 在结果集中进行显示
        show_prediction_labels_on_image(os.path.join("knn_examples/test", image_file), predictions)

运行结果:

Training KNN classifier... Training complete! Looking for faces in Aaron_Eckhart_0001.jpg - Found Aaron_Eckhart at (67, 80) Looking for faces in Aaron_Peirsol_0003.jpg - Found Aaron_Peirsol at (76, 86) Looking for faces in Abba_Eban_0001.jpg - Found Abba_Eban at (67, 80)

看下截图:

部分图片的识别之后的标注:

训练集中没得,在这里回显示unknow的,比如下图的小女孩。。。

github地址:https://github.com/XHHz/faceRecognition_knn

大家可以关注我和我小伙伴的公众号~~~这里有我和我的小伙伴不定时的更新一些python技术资料哦!!大家也可以留言,讨论一下技术问题,希望大家多多支持,关注一下啦,谢谢大家啦~~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-04-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python爬虫scrapy 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
人脸识别
腾讯云神图·人脸识别(Face Recognition)基于腾讯优图强大的面部分析技术,提供包括人脸检测与分析、比对、搜索、验证、五官定位、活体检测等多种功能,为开发者和企业提供高性能高可用的人脸识别服务。 可应用于在线娱乐、在线身份认证等多种应用场景,充分满足各行业客户的人脸属性识别及用户身份确认等需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档