开箱即用-人脸检测识别Ai

背景

上一篇文章,小白教程-人脸识别检测,简单实现了人脸的检测识别,但是那只能作为一个demo玩玩,我们的目标是要有向外提供服务的能力,有向外提供服务的能力,才能落地,赋能业务。那我们应该怎么实现呢?

需求分析

基于公司门禁系统,场景分析下,我们的服务应该提供什么样的能力,才能往外提供服务,分析如下:

  1. 对目标图片进行识别,图片中是否有人?这人是谁?是我公司的人吗?提供人脸识别接口
  2. 对图片识别,我们首先是不是应该建立人脸基础库,有了人脸库,才能对目标图片进行识别。那就需要一个员工人脸录入信息的接口,简称:人脸注册
  3. 如果这个员工离职了,那再次回到公司,通过门禁系统,刷脸识别进入公司,那不是存在安全问题。那怎么处理呢?当员工离职了,我就要对应的删除人脸库这个员工的数据。人脸删除接口

通过以上分析,我们至少,要提供三个接口:

image.png

技术调研

我们需要把系统做成web应用,通过http协议提供服务,进行调研发现基于python的web框架有下面几种,可以简单了解下

Django

项目地址: https://github.com/django/django

Python 中最流行的 Web 框架,功能非常全面,像安全认证,URL Routing,模板引擎,ORM,甚至 Admin 管理后台,全部包括。

Flask

项目地址: https://github.com/pallets/flask

也是非常流行的一个 Web 框架,它的特定是轻便,灵活,可定制性强。

用户可以根据自己的需求来添加相应的功能,在保持核心功能简单的同时,实现功能的丰富与扩展,其强大的插件库可以让用户实现个性化的网站定制,开发出功能强大的网站。

Bottle

项目地址: https://github.com/bottlepy/bottle

一个简单高效的遵循 WSGI 的微型 Web 框架。说微型,是因为它只有一个文件,除 Python 标准库外,它不依赖于任何第三方模块。

这个框架使用的比较少,不过源码也很少,如果想读源码的话,从它入手倒是一个不错的选择

Tornado

项目地址: https://github.com/tornadoweb/tornado

Tornado 是一个基于 Python 的 Web 服务框架和异步网络库,通过利用非阻塞网络 I/O, 可以承载成千上万的活动连接。在需要长连接的场景下使用,效果会更好。

Sanic

项目地址: https://github.com/sanic-org/sanic

2016 年 5 月发布的第一个版本,整体表现还是不错的,使用的人也越来越多。

Sanic 是 Python3.7+ Web 服务器和 Web 框架,旨在提高性能。它允许使用 Python3.5 中添加的 async/await 语法,可以使代码有效的避免阻塞从而达到提升响应速度的目的。

FastAPI

项目地址: https://github.com/tiangolo/fastapi

FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框架,使用 Python 3.6+ 并基于标准的 Python 类型提示。

该框架鼓励使用 Pydantic 和 OpenAPI (以前称为 Swagger) 进行文档编制,使用 Docker 进行快速开发和部署以及基于 Starlette 框架进行的简单测试。

以上框架都能实现web服务,看个人喜欢,我选择flask框架,原因就是比较轻量

环境安装

使用flask,需要安装flask库

# 安装人脸识别包
# 人脸识别库
pip install -U insightface
# 图片处理的库
pip install opencv-python 
# 
pip install numpy==1.23
# ONNX Runtime是一个用于高性能运行和推断深度学习模型的开源引擎
pip install onnxruntime
pip install flask

功能实现

http提供的接口,数据传输协议,统一使用application/json

参数说明

名称类型说明
userIdint用户ID
userNamestring用户姓名
imgDatastring图片数据,base64,使用图片转换

人脸注册

用户输入用户名、用户id、用户人脸图片数据,图片转换为base64传输,图片转base64可以自己写代码实现,也可以使用在线工具转换

代码实现

@app.route('/face/add', methods=['POST'])
def faceRegister():
    # 获取body里面的数据
    personData = request.get_json()
    img = base64_cv2(personData['imgData'])
    # 获取注册图片是否有人脸,返回的结果是个人脸集合,如果图片上有多张脸,就返回多个结果
    faces = model.get(img)
    if len(faces) == 0:
        # 如果图片未识别出人脸,说明图片没有人脸,或者图片质量有问题
        return jsonify({'code': 201, 'msg': '图片未发现人脸,请重新注册'})
    elif len(faces) > 1:
        # 如果图片中有多个人脸对象,那你无法判断应该用哪一个人脸对象,所以,注册的图片,只能有一张脸
        return jsonify({'code': 202, 'msg': '图片中多张人脸,无法判断用哪一张脸'})

    # 获取人脸数据,上面已经做了限制,所以要注册的人脸数据faces[0]就行
    embedding = faces[0].normed_embedding
    # 人脸数据添加到全局人脸列表中
    faces_embedding.append({"userName": personData['userName'], "userId": personData['userId'], "embedding": embedding})
    # 把注册的人脸数据,写入到本地文件
    faceData = open('facedata/face_ai_db', 'wb')
    pickle.dump(faces_embedding, faceData)
    faceData.close()
    return jsonify({'code': 200, 'msg': '注册成功'})

人脸搜索

输入人脸数据,返回对应的人员数据,图片相似度得分、姓名、用户id

代码实现

# 人脸识别
@app.route('/face/search', methods=['POST'])
def faceRecognition():
    # 获取body里面的数据
    personData = request.get_json()
    img = base64_cv2(personData['imgData'])
    # 获取注册图片是否有人脸,返回的结果是个人脸集合,如果图片上有多张脸,就返回多个结果
    faces = model.get(img)
    if len(faces) == 0:
        return jsonify({'code': 201, 'msg': '图片未发现人脸'})
    result = dict()
    for face in faces_embedding:
        score = compute_sim(face['embedding'], faces[0].normed_embedding)
        # 设置阈值是40,大于40分认为是准确识别到人,如果精度要高,修改阈值,比如:90,才算正确
        if score > 40:
            result['userName'] = face['userName']
            result['userId'] = face['userId']
            result['score'] = score
            break
    return jsonify({'code': 200, 'msg': 'success', 'data': result})

人脸删除

当员工离职,通过用户id,删除库里的数据

代码实现

 # 人脸删除
@app.route('/face/del', methods=['POST'])
def delFace():
    # 获取body里面的数据
    personData = request.get_json()
    userId = personData['userId']
    for face in faces_embedding:
        if face['userId'] == userId:
            # 删除加载到内存的人脸数据
            faces_embedding.remove(face)
            break
    faceData = open('./facedata/face_ai_db', 'wb')
    # 人脸数据有修改,重新加载到本地文件,保持最新
    pickle.dump(faces_embedding, faceData)
    faceData.close()
    return jsonify({'code': 200, 'msg': '员工删除成功'})

完成代码实现

import base64
import os
import cv2
import insightface.app
import numpy as np
from flask import Flask, jsonify, request
from pickle4 import pickle
from numpy.linalg import norm

app = Flask("faceai")

# 初始化人脸识别模型
model = insightface.app.FaceAnalysis()
model.prepare(ctx_id=0, det_size=(640, 640))
# 加载本地人脸库数据
faces_embedding = list()


# 人脸注册
@app.route('/face/add', methods=['POST'])
def faceRegister():
    # 获取body里面的数据
    personData = request.get_json()
    img = base64_cv2(personData['imgData'])
    # 获取注册图片是否有人脸,返回的结果是个人脸集合,如果图片上有多张脸,就返回多个结果
    faces = model.get(img)
    if len(faces) == 0:
        # 如果图片未识别出人脸,说明图片没有人脸,或者图片质量有问题
        return jsonify({'code': 201, 'msg': '图片未发现人脸,请重新注册'})
    elif len(faces) > 1:
        # 如果图片中有多个人脸对象,那你无法判断应该用哪一个人脸对象,所以,注册的图片,只能有一张脸
        return jsonify({'code': 202, 'msg': '图片中多张人脸,无法判断用哪一张脸'})

    # 获取人脸数据,上面已经做了限制,所以要注册的人脸数据faces[0]就行
    embedding = faces[0].normed_embedding
    # 人脸数据添加到全局人脸列表中
    faces_embedding.append({"userName": personData['userName'], "userId": personData['userId'], "embedding": embedding})
    # 把注册的人脸数据,写入到本地文件
    faceData = open('facedata/face_ai_db', 'wb')
    pickle.dump(faces_embedding, faceData)
    faceData.close()
    return jsonify({'code': 200, 'msg': '注册成功'})


# 人脸识别
@app.route('/face/search', methods=['POST'])
def faceRecognition():
    # 获取body里面的数据
    personData = request.get_json()
    img = base64_cv2(personData['imgData'])
    # 获取注册图片是否有人脸,返回的结果是个人脸集合,如果图片上有多张脸,就返回多个结果
    faces = model.get(img)
    if len(faces) == 0:
        return jsonify({'code': 201, 'msg': '图片未发现人脸'})
    result = dict()
    for face in faces_embedding:
        score = compute_sim(face['embedding'], faces[0].normed_embedding)
        if score > 40:
            result['userName'] = face['userName']
            result['userId'] = face['userId']
            result['score'] = score
            break
    return jsonify({'code': 200, 'msg': 'success', 'data': result})


# 人脸删除
@app.route('/face/del', methods=['POST'])
def delFace():
    # 获取body里面的数据
    personData = request.get_json()
    userId = personData['userId']
    for face in faces_embedding:
        if face['userId'] == userId:
            faces_embedding.remove(face)
            break
    faceData = open('./facedata/face_ai_db', 'wb')
    pickle.dump(faces_embedding, faceData)
    faceData.close()
    return jsonify({'code': 200, 'msg': '员工删除成功'})


def loadFaceData():
    path = './facedata/face_ai_db'
    # 判断文件是否存在,如果存在直接读取,不存在,就创建一个空文件
    if os.path.exists(path):
        faceData = open(path, 'rb')
        faces_embedding = pickle.load(faceData)
        faceData.close()
        return faces_embedding
    else:
        faceData = open(path, 'wb')
        faces_embedding = list()
        pickle.dump(faces_embedding, faceData)
        faceData.close()
        return faces_embedding


# 余弦相似度算法
def compute_sim(feat1, feat2):
    feat1 = feat1.ravel()
    feat2 = feat2.ravel()
    sim = np.dot(feat1, feat2) / (norm(feat1) * norm(feat2))
    sim = sim * 100
    return int(sim)


# 图片base64转换为numpy数组对象
def base64_cv2(base64_str):
    imgString = base64.b64decode(base64_str)
    nparr = np.frombuffer(imgString, np.uint8)
    image = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
    return image

# 服务启动入口
if __name__ == '__main__':
    # 加载本地人脸数据
    faces_embedding = loadFaceData()
    app.run(port=8888)

测试结果

人脸注册

image.png

人脸搜索

image.png

人脸删除

image.png

到此,基于falsk人脸检测we版本的就开发完成了,写作不易,如果对你有帮助,动动小手点赞评论加关注,谢谢

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
人脸识别是指利用计算机视觉技术对图像或视频中的人脸进行自动识别和分析的过程。人脸识别技术主要包括特征检测和人脸匹配两个部分。 特征检测是指从图像中提取出与人脸有关的特征信息,包括人脸的轮廓、眼睛、鼻子、嘴巴等特征点。在特征检测过程中,通常会使用Haar特征分类器、HOG特征分类器或者深度学习的卷积神经网络等算法来实现。 人脸匹配是指将提取出来的人脸特征与数据库中已有的人脸特征进行比对,以判断该人脸是否已经被识别过或者是否为指定人员。常见的人脸匹配算法包括欧氏距离匹配算法、余弦相似度匹配算法、支持向量机(SVM)等。 关于利用C++实现人脸识别的代码,可以参考开源库OpenCV中的示例代码,该库提供了丰富的图像处理和计算机视觉功能,包括人脸检测识别等。以下是一个简单的基于OpenCV的人脸检测识别的代码示例: ```c++ #include <opencv2/opencv.hpp> #include <opencv2/face.hpp> using namespace cv; using namespace std; using namespace cv::face; int main(int argc, char** argv) { // 加载人脸检测器和识别器 CascadeClassifier face_cascade; face_cascade.load("haarcascade_frontalface_alt.xml"); Ptr<LBPHFaceRecognizer> recognizer = LBPHFaceRecognizer::create(); // 加载训练好的模型 recognizer->read("model.xml"); // 打开摄像头 VideoCapture cap(0); if (!cap.isOpened()) { cout << "无法打开摄像头!" << endl; return -1; } while (true) { Mat frame; cap >> frame; // 转换成灰度图像并进行直方图均衡化 Mat gray; cvtColor(frame, gray, COLOR_BGR2GRAY); equalizeHist(gray, gray); // 检测人脸 vector<Rect> faces; face_cascade.detectMultiScale(gray, faces, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30)); // 对每个检测到的人脸进行识别 for (size_t i = 0; i < faces.size(); i++) { Mat face = gray(faces[i]); resize(face, face, Size(92, 112)); // 将人脸图像缩放到指定大小 int label = -1; double confidence = 0.0; recognizer->predict(face, label, confidence); // 在图像中标注出人脸位置和识别结果 rectangle(frame, faces[i], Scalar(255, 0, 0), 2); putText(frame, format("Person %d", label), Point(faces[i].x, faces[i].y - 5), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 255, 0), 2); } imshow("Face Recognition", frame); if (waitKey(30) == 'q') break; } return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值