人脸识别,使用 deepface + api + flask, 改写 + 调试

1. 起因, 目的, 感受:

  • github deepface 这个项目写的很好, 继续研究
  • 使用这个项目,改写 api。
  • 增加一个前端 flask app

2. 先看效果

请添加图片描述
请添加图片描述
请添加图片描述

3. 过程:

大力改写原始项目中 api 这部分的代码,
原始项目的文件结构太繁杂了:

在这里插入图片描述
我把这部分的内容,合为一个文件,即 api.py, 能删尽删。

代码 1, api
from flask import Flask
from flask_cors import CORS
import argparse
from typing import Union
from flask import Blueprint, request
import numpy as np
import os
import tempfile
import logging
from deepface import DeepFace
from deepface.api.src.modules.core import service
from deepface.commons import image_utils
from deepface.commons.logger import Logger# 配置日志
logging.basicConfig(level=logging.INFO)
logger = Logger()
blueprint = Blueprint("routes", __name__)# 辅助函数:将 NumPy 类型转换为 JSON 可序列化格式
def convert_numpy(obj):if isinstance(obj, np.floating):return float(obj)elif isinstance(obj, np.integer):return int(obj)elif isinstance(obj, np.ndarray):return obj.tolist()elif isinstance(obj, dict):return {k: convert_numpy(v) for k, v in obj.items()}elif isinstance(obj, list):return [convert_numpy(i) for i in obj]return objdef extract_image_from_request(img_key: str) -> Union[str, np.ndarray]:"""Extracts an image from the request either from json or a multipart/form-data file.Args:img_key (str): The key used to retrieve the image datafrom the request (e.g., 'img').Returns:img (str or np.ndarray): Given image detail (base64 encoded string, image path or url)or the decoded image as a numpy array."""if request.files:logging.info(f"request: {request}")logging.info(f"request.files: {request.files}")file = request.files.get(img_key)logging.info(f"img_key: {img_key}")logging.info(f"file: {file}")if file is None:raise ValueError(f"Request form data doesn't have {img_key}")if file.filename == "":raise ValueError(f"No file uploaded for '{img_key}'")# 获取文件扩展名_, ext = os.path.splitext(file.filename)if not ext:ext = '.jpg'# 保存到临时文件with tempfile.NamedTemporaryFile(delete=False, suffix=ext) as temp_file:file.save(temp_file.name)temp_file_path = temp_file.namelogging.info(f"Saved temp file: {temp_file_path}, size: {os.path.getsize(temp_file_path)} bytes")try:if not os.path.exists(temp_file_path):raise ValueError(f"Temporary file not found: {temp_file_path}")img, _ = image_utils.load_image(temp_file_path)if img is None:raise ValueError(f"Failed to load image from {temp_file_path}")logging.info(f"Loaded image shape: {img.shape if isinstance(img, np.ndarray) else 'not a numpy array'}")return imgfinally:if os.path.exists(temp_file_path):os.unlink(temp_file_path)elif request.is_json or request.form:logging.info(f"request.json: {request.json}")logging.info(f"request.form: {request.form}")input_args = request.get_json() or request.form.to_dict()if input_args is None:raise ValueError("empty input set passed")img = input_args.get(img_key)if not img:raise ValueError(f"'{img_key}' not found in either json or form data request")return imgraise ValueError(f"'{img_key}' not found in request in either json or form data")@blueprint.route("/")
def home():return f"<h1>Welcome to DeepFace API v{DeepFace.__version__}!</h1>"@blueprint.route("/represent", methods=["POST"])
def represent():input_args = (request.is_json and request.get_json()) or (request.form and request.form.to_dict())try:img = extract_image_from_request("img")except Exception as err:return {"exception": str(err)}, 400obj = service.represent(img_path=img,model_name=input_args.get("model_name", "VGG-Face"),detector_backend=input_args.get("detector_backend", "opencv"),enforce_detection=input_args.get("enforce_detection", True),align=input_args.get("align", True),anti_spoofing=input_args.get("anti_spoofing", False),max_faces=input_args.get("max_faces"),)logger.debug(obj)return convert_numpy(obj)  # 转换 NumPy 类型@blueprint.route("/verify", methods=["POST"])
def verify():input_args = (request.is_json and request.get_json()) or (request.form and request.form.to_dict())try:img1 = extract_image_from_request("img1")except Exception as err:return {"exception": str(err)}, 400try:img2 = extract_image_from_request("img2")except Exception as err:return {"exception": str(err)}, 400verification = service.verify(img1_path=img1,img2_path=img2,model_name=input_args.get("model_name", "VGG-Face"),detector_backend=input_args.get("detector_backend", "opencv"),distance_metric=input_args.get("distance_metric", "cosine"),align=input_args.get("align", True),enforce_detection=input_args.get("enforce_detection", True),anti_spoofing=input_args.get("anti_spoofing", False),)logger.debug(verification)return convert_numpy(verification)  # 转换 NumPy 类型@blueprint.route("/analyze", methods=["POST"])
def analyze():input_args = (request.is_json and request.get_json()) or (request.form and request.form.to_dict())try:img = extract_image_from_request("img")logging.info(f"api 里面收到的 img 是: {type(img)}")except Exception as err:return {"exception": str(err)}, 400actions = input_args.get("actions", ["age", "gender", "emotion", "race"])if isinstance(actions, str):actions = (actions.replace("[", "").replace("]", "").replace("(", "").replace(")", "").replace('"', "").replace("'", "").replace(" ", "").split(","))try:demographies = service.analyze(img_path=img,actions=actions,detector_backend=input_args.get("detector_backend", "opencv"),enforce_detection=input_args.get("enforce_detection", True),align=input_args.get("align", True),anti_spoofing=input_args.get("anti_spoofing", False),)except Exception as e:return {"error": f"Exception while analyzing: {str(e)}"}, 400logger.debug(demographies)return convert_numpy(demographies)  # 转换 NumPy 类型def create_app():app = Flask(__name__)CORS(app)app.register_blueprint(blueprint)logger.info(f"Welcome to DeepFace API v{DeepFace.__version__}!")return appif __name__ == "__main__":deepface_app = create_app()parser = argparse.ArgumentParser()parser.add_argument("-p", "--port", type=int, default=5005, help="Port of serving api")args = parser.parse_args()deepface_app.run(host="0.0.0.0", port=args.port, debug=True)
代码 2, flask app.py
  • 此项目,后端 api 是用 flask 写的, 前端我也用 flask 来写。
from flask import Flask, render_template, request, redirect, url_for, flash
from werkzeug.utils import secure_filename
import os
import uuid
import requests
import json
import numpy as npapp = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'static/uploads'
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024  # 限制上传文件大小为16MB
app.secret_key = 'your_secret_key'  # 用于 flash 消息# DeepFace API 的地址
DEEPFACE_API_URL = 'http://127.0.0.1:5005/analyze'# 允许的图片扩展名
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg'}# 检查文件扩展名是否允许
def allowed_file(filename):return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS# 确保上传文件夹存在
if not os.path.exists(app.config['UPLOAD_FOLDER']):os.makedirs(app.config['UPLOAD_FOLDER'])# 辅助函数:将 NumPy 数据转换为 JSON 可序列化格式
def convert_numpy(obj):if isinstance(obj, np.floating):return float(obj)elif isinstance(obj, np.integer):return int(obj)elif isinstance(obj, np.ndarray):return obj.tolist()elif isinstance(obj, dict):return {k: convert_numpy(v) for k, v in obj.items()}elif isinstance(obj, list):return [convert_numpy(i) for i in obj]return obj@app.route('/')
def index():# return render_template('index.html')return render_template('home.html')@app.route('/analyze', methods=['POST'])
def analyze():# 处理文件上传if 'file' in request.files and request.files['file'].filename:file = request.files['file']if not allowed_file(file.filename):flash('不支持的文件类型,仅支持 PNG、JPG、JPEG')return redirect(url_for('index'))# 保存文件(用于前端显示)filename = str(uuid.uuid4()) + '.' + file.filename.rsplit('.', 1)[1].lower()file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)file.save(file_path)# 重置文件流指针file.stream.seek(0)# 发送到 DeepFace APIfiles = {'img': (filename, file.stream, file.content_type)}data = {'actions': json.dumps(['age', 'gender', 'emotion', 'race']),'detector_backend': 'opencv','enforce_detection': 'true','align': 'true','anti_spoofing': 'false'}response = requests.post(DEEPFACE_API_URL, files=files, data=data)# 处理 Base64 输入(保留以兼容现有前端)elif request.form.get('base64'):base64_string = request.form['base64']if 'base64,' in base64_string:base64_string = base64_string.split('base64,')[1]payload = {'img': f'data:image/jpeg;base64,{base64_string}','actions': ['age', 'gender', 'emotion', 'race'],'detector_backend': 'opencv','enforce_detection': True,'align': True,'anti_spoofing': False}headers = {'Content-Type': 'application/json'}response = requests.post(DEEPFACE_API_URL, json=payload, headers=headers)else:flash('请上传图片文件或提供 Base64 字符串')return render_template('home.html')# 检查响应if response.status_code == 200:results = response.json()results = convert_numpy(results)flash('分析成功!')print(f"results: {results}")return render_template('home.html',   results=results, image_url=file_path if 'file' in request.files else None)else:print("API 响应:", response.text)error_msg = response.json()flash(f'API 调用失败:{error_msg}')return  render_template('home.html')if __name__ == '__main__':app.run(debug=True, host='0.0.0.0', port=8989)

4. 结论 ,todo, 感受

  • 有些地方我觉得能自己写,但是却不行。 步子太大了。 即便是有AI, 很多地方我还是不理解。
  • 这个项目只能说是,不尽完善。 所以我做起来,麻烦重重。
  • 一个球投不进,也不能全怪我,有可能是队友球传的不好,传的太偏了,太低了。

希望对大家有帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/81889.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

三维表面轮廓仪的维护保养是确保其长期稳定运行的关键

三维表面轮廓仪是一种高精度测量设备&#xff0c;用于非接触式或接触式测量物体表面的三维形貌、粗糙度、台阶高度、纹理特征等参数。其主要基于光学原理进行测量。它利用激光或其他光源投射到被测物体表面&#xff0c;通过接收反射光或散射光&#xff0c;结合计算机图像处理技…

Lambda表达式的高级用法

今天来分享下Java的Lambda表达式&#xff0c;以及它的高级用法。 使用它可以提高代码的简洁度&#xff0c;使代码更优雅。 一、什么是lambda表达式 Lambda 表达式是 Java 8 引入的特性&#xff0c;用于简化匿名内部类的语法&#xff0c;使代码更简洁&#xff0c;尤其在处理函…

31-35【动手学深度学习】深度学习硬件

1. CPU和GPU 1.1 CPU CPU每秒钟计算的浮点运算数为0.15&#xff0c;GPU为12。GPU的显存很低&#xff0c;16GB&#xff08;可能32G封顶&#xff09;&#xff0c;CPU可以一直插内存。 左边是GPU&#xff08;只能做些很简单的游戏&#xff0c;视频处理&#xff09;&#xff0c;中…

【MySQL成神之路】MySQL常见命令汇总

目录 MySQL常用命令总结 1. 数据库操作 2. 表操作 3. 数据操作&#xff08;DML&#xff09; 4. 索引与优化 5. 用户与权限管理 6. 备份与恢复 7. 事务控制 8. 常用函数 9. 系统状态与日志 总结 MySQL常用命令总结 MySQL作为最流行的关系型数据库之一&#xff0c;提供…

Dify的大语言模型(LLM) AI 应用开发平台-本地部署

前言 今天闲着&#xff0c;捣鼓一下 Dify 这个开源平台&#xff0c;在 mac 系统上&#xff0c;本地部署并运行 Dify 平台&#xff0c;下面记录个人在本地部署Dify 的过程。 Dify是什么&#xff1f; Dify是一个开源的大语言模型&#xff08;LLM&#xff09;应用开发平台&#…

【论文阅读】针对BEV感知的攻击

Understanding the Robustness of 3D Object Detection with Bird’s-Eye-View Representations in Autonomous Driving 这篇文章是发表在CVPR上的一篇文章&#xff0c;针对基于BEV的目标检测算法进行了两类可靠性分析&#xff0c;即恶劣自然条件以及敌对攻击。同时也提出了一…

SonarQube的核心作用与用途

SonarQube作为一个开源的代码质量管理平台&#xff0c;致力于持续分析代码的健康状态&#xff0c;帮助开发团队提升代码质量。以下是其核心作用与用途的详细说明&#xff1a; 1、静态代码分析 SonarQube通过静态代码分析技术&#xff0c;自动识别代码中的潜在问题。它能够检测…

AI工程师系列——面向copilot编程

前言 ​ 笔者已经使用copilot协助开发有一段时间了,但一直没有总结一个协助代码开发的案例,特别是怎么问copilot,按照什么顺序问,哪些方面可以高效的生成需要的代码,这一次,笔者以IP解析需求为例,沉淀一个实践案例,供大家参考 当然,其实也不局限于copilot本身,类似…

【软件设计师】知识点简单整理

文章目录 数据结构与算法排序算法图关键路径 软件工程决策表耦合类型 编程思想设计模式 计算机网络域名请求过程 数据结构与算法 排序算法 哪些排序算法是稳定的算法?哪些不是稳定的算法,请举出例子。 稳定排序算法&#xff1a;冒泡排序、插入排序、归并排序、基数排序、计数…

FastAPI 支持文件下载和上传

文章目录 1. 文件下载处理1.1. 服务端处理1.1.1. 下载小文件1.1.2. 下载大文件&#xff08;yield 支持预览的&#xff09;1.1.3. 下载大文件&#xff08;bytes&#xff09;1.1.4. 提供静态文件服务1.1.5. 中文文件名错误 1.2. 客户端处理1.2.1. 普通下载1.2.2. 分块下载1.2.3. …

naive-ui切换主题

1、在App.vue文件中使用 <script setup lang"ts"> import Dashboard from ./views/dashboard/index.vue import { NConfigProvider, NGlobalStyle, darkTheme } from naive-ui import { useThemeStore } from "./store/theme"; // 获取存储的主题类…

Kotlin 协程 (三)

协程通信是协程之间进行数据交换和同步的关键机制。Kotlin 协程提供了多种通信方式&#xff0c;使得协程能够高效、安全地进行交互。以下是对协程通信的详细讲解&#xff0c;包括常见的通信原语、使用场景和示例代码。 1.1 Channel 定义&#xff1a;Channel 是一个消息队列&a…

使用SQLite Studio导出/导入SQL修复损坏的数据库

使用SQLite Studio导出/导入SQL修复损坏的数据库 使用Zotero时遇到了数据库损坏&#xff0c;在软件中寸步难行&#xff0c;遂尝试修复数据库。 一、SQLite Studio简介 SQLite Studio是一款专为SQLite数据库设计的免费开源工具&#xff0c;支持Windows/macOS/Linux。相较于其…

【git config --global alias | Git分支操作效率提升实践指南】

git config --global alias | Git分支操作效率提升实践指南 背景与痛点分析 在现代软件开发团队中&#xff0c;Git分支管理是日常工作的重要组成部分。特别是在规范的开发流程中&#xff0c;我们经常会遇到类似 feature/user-management、bugfix/login-issue 或 per/cny/dev …

(八)深度学习---计算机视觉基础

分类问题回归问题聚类问题各种复杂问题决策树√线性回归√K-means√神经网络√逻辑回归√岭回归密度聚类深度学习√集成学习√Lasso回归谱聚类条件随机场贝叶斯层次聚类隐马尔可夫模型支持向量机高斯混合聚类LDA主题模型 一.图像数字化表示及建模基础 二.卷积神经网络CNN基本原…

在tensorflow源码环境里,编译出独立的jni.so,避免依赖libtensorflowlite.so,从而实现apk体积最小化

需要在APP里使用tensorflow lite来运行PC端训练的model.tlite&#xff0c;又想apk的体积最小&#xff0c;尝试了如下方法&#xff1a; 1. 在gradle里配置 implementation("org.tensorflow:tensorflow-lite:2.16.1") 这样会引入tensorflow.jar&#xff0c;最终apk的…

neo4j框架:java安装教程

安装使用neo4j需要事先安装好java&#xff0c;java版本的选择是一个犯难的问题。本文总结了在安装java和使用Java过程中遇到的问题以及相应的解决方法。 Java的安装包可以在java官方网站Java Downloads | Oracle 中国进行下载 以java 8为例&#xff0c;选择最后一行的x64 compr…

[服务器备份教程] Rclone实战:自动备份数据到阿里云OSS/腾讯云COS等对象存储

更多服务器知识&#xff0c;尽在hostol.com 各位服务器的守护者们&#xff0c;咱们都知道&#xff0c;数据是数字时代的“黄金”&#xff0c;而服务器上的数据更是我们业务的命脉。可天有不测风云&#xff0c;硬盘可能会突然“寿终正寝”&#xff0c;手滑执行了“毁灭性”命令…

Nextjs App Router 开发指南

Next.js是一个用于构建全栈web应用的React框架。App Router 是 nextjs 的基于文件系统的路由器&#xff0c;它使用了React的最新特性&#xff0c;比如 Server Components, Suspense, 和 Server Functions。 术语 树(Tree): 一种用于可视化的层次结构。例如&#xff0c;包含父…

山东大学计算机图形学期末复习15——CG15

CG15 OpenGL缓冲区、读写操作以及混合&#xff08;Blending&#xff09; 一、OpenGL缓冲区概述 OpenGL中的缓冲区是用于存储像素数据的内存区域&#xff0c;主要包括以下类型&#xff1a; 颜色缓冲区&#xff08;Color Buffer&#xff09;&#xff1a;存储每个像素的颜色值…