一、概述

在这里插入图片描述
在当今的AI浪潮中,人脸识别技术已渗透到我们生活的方方面面。构建一个高效、可扩展的人脸识别服务是许多开发者和企业的需求。传统的Django框架虽然功能强大,但对于追求极致性能和现代API开发的场景,FastAPI 无疑是更优的选择。

为什么选择 FastAPI?

  • 极致性能:基于 Starlette 和 Pydantic,FastAPI 的性能与 NodeJS 和 Go 不相上下,是最高性能的 Python Web 框架之一。
  • 开发高效:得益于 Python 的类型提示,代码自动补全、类型检查和错误排查能力大大增强,开发效率提升约 200%-300%。
  • 现代易用:自动生成交互式 API 文档 (Swagger UI / ReDoc),支持异步 async/await,并采用依赖注入系统,代码结构清晰,易于维护。

本文将带领读者,利用 FastAPI 作为后端服务框架,SQLModel 作为现代化的数据库ORM,并结合强大的 DlibArcFace (FastDeploy) 深度学习模型,从零开始构建一个结构简洁、功能完整、具备商业级潜力的人脸识别系统。


二、项目搭建

2.1 环境安装

首先,确保系统中已安装 Python 3.8 或更高版本(推荐选择3.10)。然后,安装所有必要的库:

# Web框架和服务器
pip install fastapi "uvicorn[standard]" "python-multipart" jinja2 -i https://pypi.tuna.tsinghua.edu.cn/simple

# 数据库ORM
pip install sqlmodel -i https://pypi.tuna.tsinghua.edu.cn/simple

# 深度学习与图像处理
pip install numpy==1.23 opencv-python dlib fastdeploy-python -i https://pypi.tuna.tsinghua.edu.cn/simple

注意:dlib 库的安装需要编译,可能会花费几分钟时间,请耐心等待。另外,python3.11及以上版本需要自行参考FastDeploy官网编译FastDeploy库(本文推荐使用Python3.10,无需手动编译)。

2.2 核心模型下载

为了能够使用深度学习进行人脸识别,需要下载人脸检测和特征提取的深度学习模型。

  1. Dlib 人脸关键点检测模型
    下载地址:http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2
  2. ArcFace 人脸特征提取模型
    wget https://bj.bcebos.com/paddlehub/fastdeploy/ms1mv3_arcface_r100.onnx
    

下载并解压后,将 shape_predictor_68_face_landmarks.datms1mv3_arcface_r100.onnx 这两个文件放在项目根目录下。

2.3 项目结构

一个清晰的项目结构是高效开发的基石。本文采用如下简洁明了的结构:

/FaceRecAPI
├── app/
│   ├── __init__.py
│   ├── main.py          # FastAPI应用主文件,包含API路由
│   ├── database.py      # 数据库连接与会话管理
│   ├── models.py        # SQLModel数据模型定义
│   ├── crud.py          # 数据库增删改查(CRUD)操作
│   └── face_utils.py    # 封装人脸检测与特征提取的核心函数
├── static/              # 存放CSS, JS等静态文件
│   └── ...
├── templates/           # 存放HTML模板文件
│   └── ...
├── media/               # 存放上传的人物照片
│   └── person_photos/
├── shape_predictor_68_face_landmarks.dat  # Dlib模型
└── ms1mv3_arcface_r100.onnx               # ArcFace模型

三、后端核心功能开发

3.1 数据库与模型定义 (app/models.py)

SQLModel 结合了 Pydantic 和 SQLAlchemy 的优点,能用一个类同时定义数据模型、API数据结构和数据库表结构。

from typing import Optional
from sqlmodel import Field, SQLModel

class PersonBase(SQLModel):
    """ 人物基础模型,用于API输入输出 """
    chinese_name: str = Field(index=True)
    description: Optional[str] = None

class Person(PersonBase, table=True):
    """ 人物数据库表模型 """
    id: Optional[int] = Field(default=None, primary_key=True)
    photo_path: Optional[str] = None
    # 使用bytes存储numpy array转换后的二进制数据
    embedding: Optional[bytes] = None

class PersonRead(PersonBase):
    """ 用于读取人物的输出模型,包含ID和照片路径 """
    id: int
    photo_path: Optional[str]

3.2 数据库配置 (app/database.py)

下面使用轻量级的 SQLite 数据库进行实现,并配置数据库引擎和会话。

from sqlmodel import create_engine, Session, SQLModel

# 使用SQLite数据库文件
DATABASE_URL = "sqlite:///database.db"
# connect_args 是SQLite特有的,确保单线程操作安全
engine = create_engine(DATABASE_URL, echo=True, connect_args={"check_same_thread": False})

def create_db_and_tables():
    """ 创建数据库和表 """
    SQLModel.metadata.create_all(engine)

def get_session():
    """ 依赖注入:获取数据库会话 """
    with Session(engine) as session:
        yield session

3.3 封装人脸处理工具 (app/face_utils.py)

将所有与深度学习模型相关的代码(人脸检测、特征提取)封装到一个单独的文件中,使主逻辑更清晰。

from typing import Optional
import dlib
import cv2
import numpy as np
import fastdeploy as fd
from pathlib import Path

# --- 模型初始化 ---
# 获取项目根目录
BASE_DIR = Path(__file__).resolve().parent.parent

# 1. Dlib 人脸检测器
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(str(BASE_DIR / 'shape_predictor_68_face_landmarks.dat'))

# 2. ArcFace 特征提取模型
option = fd.RuntimeOption()
option.use_cpu()
embedding_model = fd.vision.faceid.ArcFace(str(BASE_DIR / 'ms1mv3_arcface_r100.onnx'), runtime_option=option)

def detect_and_extract_face(image: np.ndarray) -> Optional[np.ndarray]:
    """
    从图像中检测并裁剪出最大的人脸。
    :param image: OpenCV格式的图像 (BGR)
    :return: 裁剪后的人脸图像,如果未检测到则返回None
    """
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    faces = detector(gray)
    if not faces:
        return None
    
    # 找到最大的人脸
    face = max(faces, key=lambda rect: rect.width() * rect.height())
    (x, y, w, h) = (face.left(), face.top(), face.width(), face.height())
    
    # 稍微扩大裁剪区域,以包含整个头部
    padding_h = int(0.4 * h)
    start_y = max(0, y - padding_h)
    
    face_image = image[start_y : y + h, x : x + w]
    return face_image

def get_embedding(face_image: np.ndarray) -> np.ndarray:
    """
    提取人脸图像的512维特征向量并进行归一化。
    :param face_image: 裁剪后的人脸图像
    :return: 归一化后的特征向量 (numpy array)
    """
    face_image = cv2.cvtColor(face_image, cv2.COLOR_BGR2GRAY) # 去除颜色
    face_image = cv2.cvtColor(face_image, cv2.COLOR_GRAY2BGR)
    result = embedding_model.predict(face_image)
    embedding = result.embedding
    embedding = np.array(embedding, dtype=np.float32)  # 使用float32以减小存储
    # L2 归一化
    embedding /= np.linalg.norm(embedding)
    return embedding

3.4 数据库操作 (app/crud.py)

创建专门的函数来处理与数据库的交互,实现关注点分离。

from sqlmodel import Session, select
from app import models

def get_person(db: Session, person_id: int):
    '''
    根据ID获取人物信息
    :param db: 数据库会话
    :param person_id: 人物ID
    :return: 人物信息
    '''
    return db.get(models.Person, person_id)

def get_persons(db: Session, skip: int = 0, limit: int = 100):
    '''
    获取所有人物信息
    :param db: 数据库会话
    :param skip: 跳过的记录数
    :param limit: 限制返回的记录数
    :return: 人物信息列表
    '''
    return db.exec(select(models.Person).offset(skip).limit(limit)).all()

def create_person(db: Session, person: models.Person):
    '''
    创建人物信息
    :param db: 数据库会话
    :param person: 人物信息
    :return: 创建后的人物信息
    '''
    db.add(person)
    db.commit()
    db.refresh(person)
    return person

def delete_person(db: Session, person_id: int):
    '''
    删除人物信息
    :param db: 数据库会话
    :param person_id: 人物ID
    :return: 删除的人物信息
    '''
    person = db.get(models.Person, person_id)
    if not person:
        return None
    db.delete(person)
    db.commit()
    return person

3.5 创建API端点 (app/main.py)

这是本项目的主应用文件,它将所有部分串联起来,并定义API路由。

import cv2
import numpy as np
import uuid
from pathlib import Path
from typing import List

from fastapi import FastAPI, Depends, HTTPException, UploadFile, File, Form
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
from sqlmodel import Session

from app import crud, models, face_utils
from app.database import get_session, create_db_and_tables

# --- FastAPI 应用初始化 ---
app = FastAPI(title="人脸识别API系统")

# 挂载静态文件目录,用于存放上传的图片
BASE_DIR = Path(__file__).resolve().parent.parent
app.mount("/media", StaticFiles(directory=BASE_DIR / "media"), name="media")

# --- 应用启动时创建数据库表 ---
@app.on_event("startup")
def on_startup():
    create_db_and_tables()

# --- 人物管理API ---
@app.post("/persons/", response_model=models.PersonRead)
def create_person_api(
    chinese_name: str = Form(...),
    description: str = Form(None),
    photo: UploadFile = File(...),
    db: Session = Depends(get_session)
):
    # 1. 读取上传的图片
    contents = photo.file.read()
    nparr = np.frombuffer(contents, np.uint8)
    img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
    if img is None:
        raise HTTPException(status_code=400, detail="照片读取异常,请检查源文件。")

    # 2. 人脸检测
    face_image = face_utils.detect_and_extract_face(img)
    if face_image is None:
        raise HTTPException(status_code=400, detail="未检测到人脸,请上传有效照片。")
    
    # 3. 提取特征向量
    embedding = face_utils.get_embedding(face_image)

    # 4. 保存裁剪后的人脸图片
    media_dir = BASE_DIR / "media" / "person_photos"
    media_dir.mkdir(parents=True, exist_ok=True)
    
    filename = f"{uuid.uuid4().hex}.jpg"
    save_path = media_dir / filename
    cv2.imwrite(str(save_path), face_image)

    # 5. 创建数据库记录
    person_data = models.Person(
        chinese_name=chinese_name,
        description=description,
        photo_path=f"/media/person_photos/{filename}",
        embedding=embedding.tobytes() # 将numpy array转为bytes存储
    )
    
    return crud.create_person(db, person_data)

@app.get("/persons/", response_model=List[models.PersonRead])
def read_persons_api(skip: int = 0, limit: int = 100, db: Session = Depends(get_session)):
    persons = crud.get_persons(db, skip=skip, limit=limit)
    return persons

@app.delete("/persons/{person_id}")
def delete_person_api(person_id: int, db: Session = Depends(get_session)):
    deleted_person = crud.delete_person(db, person_id=person_id)
    if not deleted_person:
        raise HTTPException(status_code=404, detail="人物不存在")
    return {"message": f"人物 {deleted_person.chinese_name} 已删除"}


# --- 在线人脸识别API ---
@app.post("/recognize/")
def recognize_face_api(photo: UploadFile = File(...), db: Session = Depends(get_session)):
    # 1. 读取和处理上传的图片
    contents = photo.file.read()
    nparr = np.frombuffer(contents, np.uint8)
    img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)

    if img is None:
        raise HTTPException(status_code=400, detail="照片读取异常,请检查源文件。")

    face_image = face_utils.detect_and_extract_face(img)
    if face_image is None:
        return JSONResponse(status_code=400, content={"message": "未检测到人脸"})
    
    # 2. 提取待识别图片的特征
    query_embedding = face_utils.get_embedding(face_image)
    
    # 3. 从数据库获取所有人脸特征
    all_persons = crud.get_persons(db, limit=1000) # 假设人物库小于1000
    if not all_persons:
        return JSONResponse(status_code=404, content={"message": "人物库为空"})
    
    db_embeddings = [np.frombuffer(p.embedding, dtype=np.float32) for p in all_persons]
    
    # 4. 计算余弦相似度
    similarities = [np.dot(query_embedding, db_emb) for db_emb in db_embeddings]
    
    # 5. 找到最相似的人
    best_match_index = np.argmax(similarities)
    max_similarity = similarities[best_match_index]
    
    # 设定一个阈值,低于该阈值则认为不是同一个人
    if max_similarity < 0.5:
        return {"name": "未找到匹配人物", "similarity": f"{max_similarity*100:.2f}%"}
        
    most_similar_person = all_persons[best_match_index]
    
    result = {
        'name': most_similar_person.chinese_name,
        'similarity': f"{max_similarity * 100:.2f}%",
        'photo_url': most_similar_person.photo_path
    }
    return result

3.6 启动应用

在项目根目录下,运行以下命令启动服务:

uvicorn app.main:app --reload

现在,打开浏览器访问 http://127.0.0.1:8000/docs,你将看到 FastAPI 自动生成的交互式 API 文档,可以在这里直接测试你的所有 API 接口!


四、前端界面与集成

FastAPI 的核心是构建高效的 API,但一个完整的项目离不开用户交互的界面。在这一部分,本项目将利用经典的前端技术栈(HTML, CSS, JavaScript)和 Bootstrap 5,打造一个简洁、直观的单页面应用(SPA),并将其与 FastAPI 后端无缝集成。

4.1 设计理念:简洁的单页面应用 (SPA)

相比于传统的多页面跳转,单页面应用将所有功能都承载在一个页面上,通过 JavaScript 动态更新内容,提供了更流畅的用户体验。本项目前端页面将包含两个核心功能区:

  1. 在线识别区:用户上传一张图片,系统立即返回识别结果。
  2. 人物库管理区:展示所有已录入的人物信息,并提供一个表单用于添加新的人物。

这种设计不仅结构清晰,也让前后端交互的逻辑更加集中和易于管理。

4.2 配置 FastAPI 服务静态文件与模板

首先,需要让 FastAPI 应用能够“托管”HTML 页面和静态资源(如 CSS, JS 文件)。

  1. 创建目录:在项目根目录下,确保已经创建了 templatesstatic/js 文件夹。

  2. 安装 Jinja2:如果之前没装,请安装模板引擎。

    pip install jinja2
    
  3. 修改 app/main.py:在 app/main.py 文件中,需要引入必要的模块,并配置模板和静态文件路径。

    # app/main.py
    
    # ... 其他 import ...
    from fastapi import Request
    from fastapi.templating import Jinja2Templates
    from fastapi.responses import HTMLResponse
    
    # --- FastAPI 应用初始化 ---
    app = FastAPI(title="人脸识别API系统")
    
    # 获取项目根目录
    BASE_DIR = Path(__file__).resolve().parent.parent
    
    # 1. 挂载 static 文件夹,前端可以通过 /static/... 访问
    app.mount("/static", StaticFiles(directory=BASE_DIR / "static"), name="static")
    # 2. 挂载 media 文件夹,用于访问上传的图片
    app.mount("/media", StaticFiles(directory=BASE_DIR / "media"), name="media")
    # 3. 配置 Jinja2 模板引擎
    templates = Jinja2Templates(directory=BASE_DIR / "templates")
    
    # --- 应用启动事件 ---
    @app.on_event("startup")
    def on_startup():
        create_db_and_tables()
    
    # --- 新增:服务前端页面的根路由 ---
    @app.get("/", response_class=HTMLResponse)
    async def read_root(request: Request):
        # 返回 index.html 模板
        return templates.TemplateResponse("index.html", {"request": request})
    
    # ... 其他 API 路由(/persons/, /recognize/ 等)保持不变 ...
    

4.3 创建主 HTML 页面 (templates/index.html)

templates 文件夹中创建 index.html。这个文件是整个应用的“骨架”,它将定义页面的所有可见元素。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>FastAPI 人脸识别系统</title>
    <!-- 引入 Bootstrap 5 CSS -->
    <link href="{{ url_for('static', path='css/bootstrap.min.css') }}" rel="stylesheet">
    <style>
        body { background-color: #f8f9fa; }
        .card-img-top { width: 100%; height: 18vw; object-fit: cover; }
        @media (max-width: 768px) { .card-img-top { height: 50vw; } }
        #recognition-result-card { display: none; }
    </style>
</head>
<body>
    <!-- 导航栏 -->
    <nav class="navbar navbar-dark bg-dark">
        <div class="container-fluid">
            <a class="navbar-brand" href="#">
                FastAPI + 深度学习:人脸识别系统
            </a>
        </div>
    </nav>

    <div class="container mt-4">
        <div class="row">
            <!-- 左侧:在线识别区域 -->
            <div class="col-md-5">
                <h3>1. 在线识别</h3>
                <div class="card">
                    <div class="card-body">
                        <form id="recognition-form">
                            <div class="mb-3">
                                <label for="recognition-image" class="form-label">上传待识别人脸图片</label>
                                <input class="form-control" type="file" id="recognition-image" name="photo" accept="image/*" required>
                            </div>
                            <img id="image-preview" src="" class="img-fluid rounded mb-3" alt="图片预览" style="max-height: 300px; display: none;">
                            <button type="submit" class="btn btn-primary w-100">开始识别</button>
                        </form>
                    </div>
                </div>
                <!-- 识别结果显示卡片 -->
                <div id="recognition-result-card" class="card mt-3">
                    <div class="card-header">识别结果</div>
                    <div class="card-body">
                        <h5 class="card-title">最相似人物: <span id="result-name"></span></h5>
                        <p class="card-text">相似度: <span id="result-similarity" class="fw-bold"></span></p>
                    </div>
                </div>
                 <div id="alert-container-rec" class="mt-3"></div>
            </div>

            <!-- 右侧:人物库管理区域 -->
            <div class="col-md-7">
                <h3>2. 人物库管理</h3>
                <!-- 添加人物表单 -->
                <div class="card mb-4">
                    <div class="card-body">
                        <h5 class="card-title">添加新人物</h5>
                        <form id="add-person-form">
                            <div class="row">
                                <div class="col-md-6 mb-3">
                                    <label for="person-name" class="form-label">姓名</label>
                                    <input type="text" class="form-control" id="person-name" name="chinese_name" required>
                                </div>
                                <div class="col-md-6 mb-3">
                                    <label for="person-photo" class="form-label">照片 (请确保包含清晰人脸)</label>
                                    <input type="file" class="form-control" id="person-photo" name="photo" accept="image/*" required>
                                </div>
                            </div>
                            <button type="submit" class="btn btn-success w-100">确认添加</button>
                        </form>
                         <div id="alert-container-add" class="mt-3"></div>
                    </div>
                </div>
                <!-- 人物列表 -->
                <h5>已录入人物</h5>
                <div id="person-list" class="row row-cols-2 row-cols-md-3 g-4">
                    <!-- 人物卡片将通过JS动态插入这里 -->
                </div>
            </div>
        </div>
    </div>

    <!-- 引入我们自己的JS文件 -->
    <script src="{{ url_for('static', path='js/app.js') }}"></script>
</body>
</html>

4.4 编写客户端 JavaScript 逻辑 (static/js/app.js)

这是前端的“大脑”。在 static/js/ 目录下创建 app.js 文件,用于处理所有与后端API的交互和页面DOM的操作。

// 页面加载完成后立即执行
document.addEventListener('DOMContentLoaded', () => {
    // 1. 加载已存在的人物列表
    loadPersons();

    // 2. 绑定“添加人物”表单的提交事件
    const addPersonForm = document.getElementById('add-person-form');
    addPersonForm.addEventListener('submit', handleAddPerson);

    // 3. 绑定“在线识别”表单的提交事件
    const recognitionForm = document.getElementById('recognition-form');
    recognitionForm.addEventListener('submit', handleRecognizeFace);
    
    // 4. 为识别图片输入框添加预览功能
    const recognitionImageInput = document.getElementById('recognition-image');
    recognitionImageInput.addEventListener('change', (event) => {
        const preview = document.getElementById('image-preview');
        const file = event.target.files[0];
        if (file) {
            preview.src = URL.createObjectURL(file);
            preview.style.display = 'block';
        }
    });
});

// 显示提示信息的辅助函数
function showAlert(message, type = 'danger', containerId) {
    const container = document.getElementById(containerId);
    const wrapper = document.createElement('div');
    wrapper.innerHTML = [
        `<div class="alert alert-${type} alert-dismissible" role="alert">`,
        `   <div>${message}</div>`,
        '   <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>',
        '</div>'
    ].join('');
    container.append(wrapper);
}


// 函数:加载人物列表
async function loadPersons() {
    try {
        const response = await fetch('/persons/');
        if (!response.ok) throw new Error('获取人物列表失败');
        
        const persons = await response.json();
        const personListDiv = document.getElementById('person-list');
        personListDiv.innerHTML = ''; // 清空现有列表

        persons.forEach(person => {
            const col = document.createElement('div');
            col.className = 'col';
            col.innerHTML = `
                <div class="card h-100">
                    <img src="${person.photo_path}" class="card-img-top" alt="${person.chinese_name}">
                    <div class="card-body">
                        <h6 class="card-title text-center">${person.chinese_name}</h6>
                    </div>
                </div>
            `;
            personListDiv.appendChild(col);
        });
    } catch (error) {
        console.error('Error loading persons:', error);
        showAlert(error.message, 'danger', 'alert-container-add');
    }
}

// 函数:处理添加人物的表单提交
async function handleAddPerson(event) {
    event.preventDefault(); // 阻止表单默认的刷新页面行为
    
    const form = event.target;
    const formData = new FormData(form);

    try {
        const response = await fetch('/persons/', {
            method: 'POST',
            body: formData,
            // 注意:使用FormData时,浏览器会自动设置正确的Content-Type,无需手动指定
        });

        const result = await response.json();

        if (!response.ok) {
            // 如果后端返回错误信息(如:未检测到人脸)
            throw new Error(result.detail || '添加失败,请检查输入。');
        }
        
        showAlert(`人物 "${result.chinese_name}" 添加成功!`, 'success', 'alert-container-add');
        form.reset(); // 清空表单
        loadPersons(); // 重新加载人物列表
    } catch (error) {
        console.error('Error adding person:', error);
        showAlert(error.message, 'danger', 'alert-container-add');
    }
}

// 函数:处理人脸识别的表单提交
async function handleRecognizeFace(event) {
    event.preventDefault();

    const form = event.target;
    const formData = new FormData(form);
    const resultCard = document.getElementById('recognition-result-card');
    
    try {
        const response = await fetch('/recognize/', {
            method: 'POST',
            body: formData,
        });

        const result = await response.json();

        if (!response.ok) {
             throw new Error(result.message || '识别失败');
        }

        // 更新结果显示区域
        document.getElementById('result-name').textContent = result.name;
        document.getElementById('result-similarity').textContent = result.similarity;
        resultCard.style.display = 'block'; // 显示结果卡片

    } catch (error) {
        console.error('Error recognizing face:', error);
        resultCard.style.display = 'none'; // 隐藏结果卡片
        showAlert(error.message, 'danger', 'alert-container-rec');
    }
}

4.5 最终效果

现在,重新运行 FastAPI 应用 (uvicorn app.main:app --reload),然后访问 http://127.0.0.1:8000,将会看到一个干净、功能齐全的单页面应用:

  • 右侧,可以上传新人物的照片和姓名,点击“确认添加”后,人物卡片会立即出现在下方的列表中。
  • 左侧,可以上传任意一张包含人脸的图片,点击“开始识别”,系统会与右侧的人物库进行比对,并在下方卡片中实时显示出最相似的人物及其相似度。

人物添加功能如下
在这里插入图片描述
人物识别功能如下
在这里插入图片描述
在这里插入图片描述
通过以上步骤,不仅构建了强大的后端API,还为其配备了一个现代、简洁且用户友好的前端界面,真正实现了一个从前端到后端的全栈人脸识别项目。


五、优化建议

本项目系统已经可以良好地工作,但对于真正的商业级应用,还有一些优化方向:

  1. 向量检索数据库:当人脸库达到数万甚至数百万级别时,线性遍历计算相似度会变得非常缓慢。可以引入 FAISSMilvus 等专业的向量检索引擎。在系统启动时,将所有数据库中的人脸特征加载到向量库中,实现毫秒级的海量数据检索。

  2. GPU 加速:如果服务器配备了 GPU,应配置 FastDeploy 使用 GPU 进行推理。只需在初始化 RuntimeOption 时修改为 option.use_gpu(0),即可将特征提取的速度提升数十倍。

  3. 异步任务处理:对于添加人物这种包含文件读写、模型推理和数据库写入的耗时操作,可以利用 FastAPI 的 BackgroundTasks 将其放入后台执行。API 可以立即返回一个“处理中”的响应,提升用户体验。


六、总结

本文成功地使用 FastAPI和深度学习模型构建了一个现代化、高性能的人脸识别系统,体验了 FastAPI 带来的开发效率和卓越性能,学习了如何通过 SQLModel 优雅地管理数据,并掌握了将深度学习模型集成到 Web 服务中的核心流程。

本项目不仅是一个功能完备的 Demo,更是一个可以轻松扩展和优化的起点。希望它能为读者在探索 AI 应用开发的道路上提供有力的帮助。

FastAPI和深度学习项目学习交流群(qq):820106877

本项目完整代码链接https://github.com/qianbin1989228/FaceRecAPI

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐