一、项目简介
图像超分辨率(Super Resolution)是计算机视觉中非常常见的应用场景:将低分辨率图片放大为更清晰的高分辨率图片,可用于老照片修复、监控画面增强、电商商品图优化、医学影像辅助分析等业务。
本文实现一个完整的 Python 全栈项目:基于深度学习的图像超分辨率系统。它不是只讲算法概念,而是把"用户登录、图片上传、任务管理、结果下载、前后端交互、数据库落库、接口鉴权"全部串起来,形成一个可运行的业务系统。
项目采用 FastAPI + SQLite + Vue 3(Vite)技术栈。后端超分推理流程改用 PyTorch 实现:上传图片先转换为 NCHW Tensor,再通过 torch.nn.functional.interpolate 完成 bicubic 上采样,并使用逐通道卷积锐化核增强细节;同时通过 model_name 字段预留 FSRCNN、EDSR、Real-ESRGAN 等真实模型接入位置。
二、技术栈
| 层级 | 技术 | 作用 |
|---|---|---|
| 后端框架 | FastAPI | 提供 RESTful API、文件上传、接口鉴权 |
| 数据库 | SQLite | 保存用户、Token、超分任务记录 |
| ORM | SQLAlchemy | 定义数据模型并操作数据库 |
| 数据校验 | Pydantic | 请求参数和响应结构校验 |
| 超分推理 | PyTorch + Pillow | PyTorch 执行 Tensor 上采样与卷积增强,Pillow 负责图片读取与保存 |
| 前端框架 | Vue 3 + Vite | 构建单页应用、组件状态管理、接口调用 |
| 鉴权方式 | Bearer Token | 登录后生成 Token,保护核心业务接口 |
三、系统架构
系统分为三层:
text
浏览器 Vue 3 前端
├── 注册/登录页面
├── 上传超分任务页面
└── 任务列表与结果下载页面
↓ HTTP/JSON/FormData
FastAPI 后端服务
├── 用户认证模块
├── 图片上传模块
├── 超分推理模块
├── 任务管理模块
└── 文件下载模块
↓ SQLAlchemy
SQLite 数据库 + 本地文件存储
├── users
├── access_tokens
├── image_jobs
├── uploads/
└── results/
前端通过 api.js 统一封装请求。登录成功后 Token 存储在 localStorage,后续请求自动携带 Authorization: Bearer <token>。后端对 /api/jobs 等核心接口进行鉴权,确保用户只能操作自己的任务。
四、功能模块
1. 用户认证模块
- 用户注册:用户名、邮箱、密码。
- 密码哈希:使用 PBKDF2-HMAC-SHA256 加盐存储。
- 用户登录:验证密码后生成随机 Token。
- 退出登录:撤销当前 Token。
- 登录状态:前端刷新页面时调用
/api/auth/me恢复用户状态。
2. 图像超分任务模块
- 上传低分辨率图片。
- 设置任务标题、放大倍数(2x、3x、4x)、模型名称、备注。
- 后端保存原图到
uploads/。 - 执行 PyTorch 教学版超分推理并保存到
results/。 - 数据库保存任务记录,包括文件名、输出路径、模型、状态等。
3. 历史任务模块
- 查询当前用户的所有任务。
- 查看任务标题、模型、倍数、指标、创建时间。
- 下载处理后的图片。
- 删除任务记录。
五、数据库/数据模型设计
项目中定义了三个核心表。
users 用户表
| 字段 | 类型 | 说明 |
|---|---|---|
| id | Integer | 主键 |
| username | String | 用户名,唯一 |
| String | 邮箱,唯一 | |
| password_hash | String | 加盐哈希后的密码 |
| created_at | DateTime | 创建时间 |
access_tokens 登录令牌表
| 字段 | 类型 | 说明 |
|---|---|---|
| id | Integer | 主键 |
| token | String | 随机 Token,唯一 |
| user_id | Integer | 所属用户 |
| created_at | DateTime | 创建时间 |
image_jobs 超分任务表
| 字段 | 类型 | 说明 |
|---|---|---|
| id | Integer | 主键 |
| owner_id | Integer | 任务所属用户 |
| title | String | 任务标题 |
| original_filename | String | 原始文件名 |
| scale | Integer | 放大倍数 |
| model_name | String | 模型名称 |
| status | String | 任务状态 |
| input_path | String | 原图路径 |
| output_path | String | 结果图路径 |
| notes | Text | 备注 |
| psnr | String | 演示指标 |
| created_at | DateTime | 创建时间 |
核心模型代码如下:
python
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
username = Column(String(64), unique=True, index=True, nullable=False)
email = Column(String(120), unique=True, index=True, nullable=False)
password_hash = Column(String(255), nullable=False)
created_at = Column(DateTime, default=datetime.utcnow)
class ImageJob(Base):
__tablename__ = "image_jobs"
id = Column(Integer, primary_key=True, index=True)
owner_id = Column(Integer, ForeignKey("users.id"), nullable=False)
title = Column(String(120), nullable=False)
original_filename = Column(String(255), nullable=False)
scale = Column(Integer, default=2)
model_name = Column(String(80), default="FSRCNN-lite")
status = Column(String(30), default="completed")
input_path = Column(String(255), nullable=False)
output_path = Column(String(255), nullable=False)
六、后端接口设计
| 方法 | 路径 | 功能 | 是否鉴权 |
|---|---|---|---|
| GET | /api/health |
服务健康检查 | 否 |
| POST | /api/auth/register |
注册用户 | 否 |
| POST | /api/auth/login |
用户登录 | 否 |
| GET | /api/auth/me |
获取当前用户 | 是 |
| POST | /api/auth/logout |
退出登录 | 是 |
| POST | /api/jobs |
上传图片并创建超分任务 | 是 |
| GET | /api/jobs |
获取当前用户任务列表 | 是 |
| GET | /api/jobs/{job_id} |
获取任务详情 | 是 |
| GET | /api/jobs/{job_id}/download |
下载结果图 | 是 |
| DELETE | /api/jobs/{job_id} |
删除任务 | 是 |
鉴权依赖示例:
python
def current_user(authorization: str = Header(default=""), db: Session = Depends(get_db)):
if not authorization.startswith("Bearer "):
raise HTTPException(status_code=401, detail="缺少 Bearer Token")
token = authorization.removeprefix("Bearer ").strip()
user = crud.get_user_by_token(db, token)
if not user:
raise HTTPException(status_code=401, detail="登录已失效")
return user
上传任务接口使用 multipart/form-data:
python
@app.post("/api/jobs", response_model=schemas.ImageJobRead)
def upload_job(
title: str = Form(...),
scale: int = Form(2),
model_name: str = Form("FSRCNN-lite"),
notes: str = Form(""),
file: UploadFile = File(...),
db: Session = Depends(get_db),
user: models.User = Depends(current_user),
):
data = schemas.ImageJobCreate(title=title, scale=scale, model_name=model_name, notes=notes)
return crud.create_image_job(db, user, data, file)
七、前端页面设计
前端使用 Vue 3 + Vite 构建单页应用,主要包含以下区域:
- 顶部介绍区:展示系统名称和项目定位。
- 注册表单:输入用户名、邮箱、密码。
- 登录表单:登录后保存 Token。
- 任务创建表单:填写标题、选择模型、选择放大倍数、上传图片。
- 任务列表:展示历史任务、下载结果、删除任务。
api.js 对请求进行统一封装:
javascript
async function request(path, options = {}) {
const headers = options.headers || {}
const token = getToken()
if (token) headers.Authorization = `Bearer ${token}`
const res = await fetch(`${API_BASE}${path}`, { ...options, headers })
const body = res.headers.get('content-type')?.includes('application/json')
? await res.json()
: await res.blob()
if (!res.ok) throw new Error(body.detail || '请求失败')
return body
}
任务上传时使用 FormData:
javascript
const fd = new FormData()
fd.append('title', jobForm.title)
fd.append('scale', jobForm.scale)
fd.append('model_name', jobForm.model_name)
fd.append('notes', jobForm.notes)
fd.append('file', selectedFile.value)
await api.createJob(fd)
八、核心代码讲解
1. 密码哈希
系统没有明文保存密码,而是用随机盐和 PBKDF2 生成哈希:
python
def hash_password(password: str, salt: Optional[str] = None) -> str:
salt = salt or secrets.token_hex(16)
digest = hashlib.pbkdf2_hmac(
"sha256", password.encode("utf-8"), salt.encode("utf-8"), 120_000
)
return f"{salt}${digest.hex()}"
校验密码时重新计算哈希,并使用 secrets.compare_digest 防止简单时序攻击。
2. Token 鉴权
登录成功后后端生成随机 Token:
python
def create_token(db: Session, user: models.User) -> models.AccessToken:
token = models.AccessToken(token=secrets.token_urlsafe(32), user_id=user.id)
db.add(token)
db.commit()
db.refresh(token)
return token
前端保存该 Token,后续请求统一带上请求头:
javascript
headers.Authorization = `Bearer ${token}`
3. 超分推理流程
超分模块用 PyTorch 实现。教学版不依赖外部模型权重,而是保留深度学习推理的基本结构:图片读取后转换成 NCHW Tensor,使用 PyTorch bicubic 上采样放大,再通过逐通道卷积锐化核增强边缘细节,最后保存到 results/。
python
class TorchSuperResolutionModel:
def __init__(self, scale: int):
self.scale = max(1, int(scale))
def __call__(self, image_tensor):
import torch
import torch.nn.functional as F
upscaled = F.interpolate(
image_tensor,
scale_factor=self.scale,
mode="bicubic",
align_corners=False,
)
channels = upscaled.shape[1]
kernel = torch.tensor(
[[0.0, -1.0, 0.0], [-1.0, 5.0, -1.0], [0.0, -1.0, 0.0]],
dtype=upscaled.dtype,
device=upscaled.device,
).view(1, 1, 3, 3).repeat(channels, 1, 1, 1)
return F.conv2d(upscaled, kernel, padding=1, groups=channels).clamp(0.0, 1.0)
业务入口保持 run_super_resolution(input_path, output_path, scale) 不变。未来如果要接入真实模型,只需将 TorchSuperResolutionModel.__call__ 替换为 FSRCNN、EDSR、Real-ESRGAN 等模型的前向推理。
九、部署与运行步骤
1. 运行后端
bash
cd project/backend
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
后端默认地址:http://127.0.0.1:8000。
2. 运行前端
bash
cd project/frontend
npm install
npm run dev
前端默认访问后端 http://127.0.0.1:8000,Vite 默认页面通常为 http://127.0.0.1:5173。
3. 使用流程
- 打开前端页面。
- 注册新用户。
- 登录系统。
- 上传一张低分辨率图片。
- 选择 2x、3x 或 4x 放大。
- 查看任务列表并下载结果图片。
十、项目总结
本文完成了一个完整的 Python 全栈项目:基于深度学习的图像超分辨率系统。它覆盖了从用户认证、数据库设计、图片上传、推理处理、任务管理到 Vue 前端交互的完整流程。
这个项目的亮点在于:
- 不是单纯算法 Demo,而是可运行的全栈业务系统。
- 后端接口有完整注册、登录、Token 鉴权。
- 核心业务接口按用户隔离,避免越权访问。
- 前端使用 Vue 3 + Vite,具备登录状态处理和鉴权请求。
- 推理模块已使用 PyTorch 张量与卷积算子实现,接口清晰,方便后续替换为真实深度学习模型。
后续可继续扩展任务队列、GPU 推理、模型管理、图片预览对比、SSIM/PSNR 自动评估、管理员后台等功能,使其进一步接近生产级图像增强平台。