当前位置: 首页 > article >正文

人脸识别,使用 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, 很多地方我还是不理解。
  • 这个项目只能说是,不尽完善。 所以我做起来,麻烦重重。
  • 一个球投不进,也不能全怪我,有可能是队友球传的不好,传的太偏了,太低了。

希望对大家有帮助。

相关文章:

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

1. 起因&#xff0c; 目的&#xff0c; 感受: github deepface 这个项目写的很好&#xff0c; 继续研究使用这个项目&#xff0c;改写 api。增加一个前端 flask app 2. 先看效果 3. 过程: 大力改写原始项目中 api 这部分的代码&#xff0c; 原始项目的文件结构太繁杂了: 我把…...

代码管理平台Gitlab如何通过快解析实现远程访问?

一、Gitlab功能介绍 Gitlab是被广泛使用的基于git的开源代码管理平台&#xff0c;用于管理、存储开发人员代码&#xff0c;同时可以协同开发 二、外网试用Gitlab遇到的问题 运维人员将Gitlab服务器部署在总部机房&#xff0c;而分公司开发人员和出差运维人员就无法访问Gitlab…...

基于SpringBoot+Vue的足球青训俱乐部管理后台系统的设计与开发

项目背景与概述 随着足球青训行业的快速发展&#xff0c;如何高效、规范地管理学员、教练以及课程等日常工作&#xff0c;成为了青训俱乐部运营的重要课题。为了提升俱乐部的管理效率与用户体验&#xff0c;基于 Spring Boot 和 Vue.js 开发了一个 足球青训俱乐部管理后台系统…...

Redis 是否适合像 MySQL 一样当数据库使用?

Redis 可以在特定场景下作为数据库使用&#xff0c;但与 MySQL 等关系型数据库还是有很大的差异。Redis 确实有持久化功能&#xff0c;开启 AOF 并把 appendfsync 设置为 always 后&#xff0c;它会把每一次数据操作都立刻记录到文件里&#xff0c;相当于每发生一件事就马上记下…...

AI是否会取代人类?浔川问答①

提问者&#xff1a;浔川社团官方联合会 回答者&#xff1a;deepseek 关于AI是否会取代人类的问题&#xff0c;目前科技界和社会学界的主流观点认为&#xff1a;AI会在许多领域显著改变人类的工作和生活方式&#xff0c;但“完全取代人类”的可能性极低。更可能的是人机协作的深…...

JDBC-java操作数据库

1.基本结构&#xff1a; package com.atguigu.servlets;import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement;public class JDBCemo {public static void main(String[] args) throws Exception{String url "jdbc:mysql:///mysql&qu…...

[原创](现代Delphi 12指南):[macOS 64bit App开发]: 如何获取目录大小?

[作者] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共24年] 职业生涯: 22年 开发语言: C/C++、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、 开发工具: Visual Studio、Delphi、XCode、…...

线程调度与单例模式:wait、notify与懒汉模式解析

一.wait 和 notify&#xff08;等待 和 通知&#xff09; 引入 wait notify 就是为了能够从应用层面&#xff0c;干预到多个不同线程代码的执行顺序&#xff0c;可以让后执行的线程主动放弃被调度的机会&#xff0c;等先执行的线程完成后通知放弃调度的线程重新执行。 自助取…...

MySQL中TCP和套接字SSL加密连接行为分析

目录 一、前言 二、背景 三、参数介绍 3.1、 have_openssl 3.2、have_ssl 3.3、require_secure_transport 四、--ssl-modemode 五、CREATE USER SSL/TLS选项 六、问题验证 6.1、使用套接字连接 6.2、使用TCP连接 七、分析与总结 一、前言 SSL&#xff08;Secure S…...

php本地 curl 请求证书问题解决

错误: cURL error 60: SSL certificate problem: unable to get local issuer certificate (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for 解决方案 在php目录下创建证书文件夹, 执行下面生成命令, 然后在php.ini 文件中配置证书路径; 重启环境 curl --eta…...

Callable

一、Callable 接口定义 FunctionalInterface public interface Callable<V> {V call() throws Exception; // 返回类型为泛型V&#xff0c;可抛出异常 }二、基本使用步骤 1. 定义 Callable 任务 // 示例1&#xff1a;计算两个数的和 Callable<Integer> sumTask …...

Honeywell 05701-A-0302 单通道控制卡

Honeywell 05701-A-0302 是System 57系列中的单通道控制卡&#xff0c;专为工业气体检测和火灾报警系统设计。该控制卡为系统提供单个检测通道的完整控制解决方案&#xff0c;包括传感器驱动、信号采集和报警管理功能。 主要特性 单通道控制&#xff1a;支持单个气体传感器或火…...

爱普生晶振赋能UWB汽车数字钥匙,解锁未来出行新方式

随着科技的发展&#xff0c;尤其是国产新能源汽车的崛起&#xff0c;相信大家对数字钥匙的概念已经不陌生了&#xff0c;通过手机、智能穿戴实现对汽车的多功能控制已经是很多汽车的标配。但是目前数字钥匙也有一定的局限性&#xff0c;比如定位不准、安全性不强等等&#xff0…...

电子电路:深入理解电磁耦合的定义与应用

电场和磁场是独立存在的吗&#xff1f;&#xff0c;但实际上根据麦克斯韦理论&#xff0c;它们是同一现象的两个方面&#xff0c;通过变化相互产生。这时候需要强调时变场的重要性&#xff0c;以及静态场和动态场的区别。 通过电磁波的概念&#xff0c;说明电磁耦合如何导致电…...

宝塔安装的 MySQL 无法连接的情况及解决方案

宝塔安装的 MySQL 无法连接的情况及解决方案 宝塔面板是一款流行的服务器管理工具&#xff0c;其中集成的 MySQL 数据库有时会出现连接问题。本文详细介绍两种最常见的 MySQL 连接错误&#xff1a;“1130 - Host is not allowed to connect” 和 “1045 - Access denied”&…...

今日行情明日机会——20250523

上证指数缩量下跌&#xff0c;个股下跌超过4000个&#xff0c;总体跌多涨少&#xff0c;日线总体处于高位&#xff0c;注意风险。 深证60分钟级别下跌趋势线压制&#xff0c;总体日线转下跌的概率大&#xff0c;注意风险。 2025年5月23日涨停股主要行业方向分析 一、核心主…...

微服务项目->在线oj系统(Java版 - 4)

相信自己,终会成功 目录 B端用户管理 C端用户代码 发送验证码: 验证验证码 退出登录 登录用户信息功能 用户详情与用户编辑 用户竞赛接口 用户报名竞赛 用户竞赛报名接口查询 用户信息列表 ThreadLocalUtil Hutool工具库 常用功能介绍 B端用户管理 进行列表显示与…...

ReAct 与 CoAct:AI 代理的推理与行动之旅

引言 能推理又能行动的 AI 代理&#xff0c;是朝着构建更自主系统迈出的重要一步。传统上&#xff0c;语言模型在“思维链”提示方面表现得很出色&#xff0c;也就是通过文本逐步思考问题来解决像算术、常识问题或符号推理这类任务。但用思维链时&#xff0c;模型只依赖自身的…...

电子电路:什么是滤波器,什么优势高通滤波器?

滤波器在信号处理中的基本类型有哪些?通常可能包括低通、高通、带通、带阻等。每种滤波器根据频率的不同来允许或阻止信号通过。高通滤波器就是其中一种,允许高频通过,衰减低频。 滤波器的实现方式,分为模拟和数字两种。模拟滤波器使用电阻、电容、电感等元件,而数字滤波…...

uni-app使用大集

1、手动修改页面标题 uni.setNavigationBarTitle({title: 修改标题 }); 2、单选 不止有 radio-group&#xff0c;还有 uni-data-checkbox 数据选择器 <!-- html部分 --> <uni-data-checkbox v-model"sex" :localdata"checkboxList"></u…...

[Spring Boot]整合Java Mail实现Outlook发送邮件

日常开发过程中,我们经常需要使用到邮件发送任务,比方说验证码的发送、日常信息的通知等。日常比较常用的邮件发送方包括:163、QQ等,本文主要讲解Outlook SMTP的开启方式、OutLook STARTTTL的配置、如何通过JavaMail来实现电子邮件的发送等。 Outlook作为微软提供的企业电子…...

零件剖切配置教学 | 玩转EasyTwin 工业产线第三期(上)课程回顾

-在工业数字孪生领域&#xff0c;工程施工模拟、车间产线运转、机械装置和零件配置等交互效果的呈现至关重要。通过EasyTwin&#xff0c;我们能够以更低成本、更高效率来构建数字孪生场景&#xff0c;但在搭建的过程中&#xff0c;也会因为复杂的场景交互配置产生一些疑问。该案…...

onnx模型转入rknn3399平台上工作记录

1.rknn虚拟环境使用时报错问题 使用rknn17环境的报错&#xff1a; ImportError: libdc1394.so.22: cannot open shared object file: No such file or directory 参考链接&#xff1a;https://blog.csdn.net/2301_80032564/article/details/142316410 创作软连接&#xff1a; …...

进考场!软考考试现场答题的注意事项

明天就要考试啦&#xff0c;简单说几条比较重要的考场答题注意事项&#xff1a; 选择题方面&#xff0c;一定要注意的是不要恋战&#xff0c;注意把握答题时间&#xff0c;对自己比较熟悉和有把握的题目按照顺序进行作答即可&#xff0c;但是对于不确定的题目或者需要大量时间计…...

第三个小程序动工:一款结合ai的菜谱小程序

1.环境搭建&#xff0c;与初步运行 安装及使用 | Taro 文档 找到一个合适的文件夹&#xff0c;cmd D:\gitee>pnpm install -g tarojs/cli╭──────────────────────────────────────────╮│ …...

OpenCV CUDA 模块图像过滤------创建一个线性滤波器(Linear Filter)函数createLinearFilter()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 该函数用于创建一个线性滤波器&#xff08;Linear Filter&#xff09;&#xff0c;可以对图像执行任意用户定义的卷积核&#xff08;kernel&…...

广告反作弊都有哪些方法

1. 基础检测手段 通过分析用户行为数据&#xff0c;识别异常点击模式&#xff1a; 频率检测&#xff1a;同一IP、设备ID、用户ID在短时间内多次点击广告&#xff08;如1秒内多次点击&#xff09;。可设定阈值&#xff08;如每小时最多5次点击&#xff09;&#xff0c;超过即标…...

Excel 密码忘记了?巧用PassFab for Excel 解密帮您找回数据!

在工作中&#xff0c;你是否遇到过这样的尴尬时刻&#xff1f;打开重要的 Excel 文件&#xff0c;却发现忘记密码&#xff0c;里面的财务报表、客户数据、项目计划瞬间变成 “加密天书”。重新制作耗时耗力&#xff0c;找专业人员解密又担心数据泄露&#xff0c;这个时候&#…...

Vue.js教学第十二章:Vue Router实战指南(二)

Vue Router(二):深入剖析 Vue Router 高级特性 在前端开发领域,Vue.js 框架凭借其简洁、灵活和高效的特点,得到了广泛应用。而 Vue Router 作为 Vue.js 的官方路由管理器,为构建单页面应用(SPA)提供了强大的支持。本文将深入探究 Vue Router 的高级特性,包括路由的动…...

【前端开发】Uniapp日期时间选择器:实现分钟动态步长设置

技术栈 Uniapp Vue3 uView年份显示前后一年&#xff0c;分钟动态设置间隔 效果图 主体显示 <view class"uni-row-between selector"><view class"uni-flex-1 left" click"!props.disabled && openPicker()"><uni-icons…...