猫咪如厕检测与分类识别系统系列~进阶【三】网页端算法启动架构及数据库实现
前情提要
家里养了三只猫咪,其中一只布偶猫经常出入厕所。但因为平时忙于学业,没法时刻关注牠的行为。我知道猫咪的如厕频率和时长与健康状况密切相关,频繁如厕可能是泌尿问题,停留过久也可能是便秘或不适。为了更科学地了解牠的如厕习惯,我计划搭建一个基于视频监控和AI识别的系统,自动识别猫咪进出厕所的行为,记录如厕时间和停留时长,并区分不同猫咪。这样即使我不在家,也能掌握猫咪的健康状态,更安心地照顾它们。
🎓 各位的关注与点赞是我持续分享的最大动力,衷心感谢大家的支持!
📢 欢迎正在攻读硕博学位的同学,或是对人工智能充满热情的朋友们,关注我的个人公众号。在这里,我将持续更新博士期间阅读的前沿论文解读、项目实战经验分享,以及我对AI技术趋势的思考与探讨。
✨ 无论你是科研工作者、工程开发者,还是AI初学者,都能在这里找到干货与灵感。让我们一起交流、成长、探索人工智能的无限可能!
已完成工作:
✅猫咪如厕检测与分类识别系统系列【一】 功能需求分析及猫咪分类特征提取
✅猫咪如厕检测与分类识别系统系列【二】多图上传及猫咪分类特征提取更新
✅猫咪如厕检测与分类识别系统系列【三】 融合yolov11目标检测
✅猫咪如厕检测与分类识别系统系列【四】融合检测日志输出及前端展示界面制作
✅猫咪如厕检测与分类识别系统系列【五】信息存储数据库改进+添加猫咪页面制作+猫咪躯体匹配算法架构更新
✅猫咪如厕检测与分类识别系统系列【六】分类模型训练+混合检测分类+未知目标自动更新
✅猫咪如厕检测与分类识别系统系列【七】 当前阶段总结报告
✅猫咪如厕检测与分类识别系统系列【八】 检测推理事件整合+视频推流架构分析
✅猫咪如厕检测与分类识别系统系列【九】 视频检测区域在线绘制+支持摄像头+网络摄像头+整体构建【上】
✅猫咪如厕检测与分类识别系统系列【九】 视频检测区域在线绘制+支持摄像头+网络摄像头+整体构建【下】
✅猫咪如厕检测与分类识别系统系列【十】 视频检测区域动态监测及实时更新
✅猫咪如厕检测与分类识别系统系列【十一】区域进入事件相应逻辑鲁棒性更新
✅猫咪如厕检测与分类识别系统系列【十二】猫咪进出事件逻辑及日志优化【上】
✅猫咪如厕检测与分类识别系统系列【十三】猫咪进出事件逻辑及日志优化【下】
✅猫咪如厕检测与分类识别系统系列~进阶【一】视频流推流及网页实时展示
✅猫咪如厕检测与分类识别系统系列~进阶【二】推流视频嵌入主界面实时播放控制
本小节目标:构建网页端实时算法启动架构及数据库实现
进阶部分最终目标:把算法启动,摄像头管理都做在系统上。然后使得整个系统从“脚本运行”变为“系统级服务/平台管理”,适合长期运行与远程管理。
目标描述
功能 | 实现方式 |
---|---|
自动启动算法 | 开机后自动运行(如 systemd、Windows 服务) |
摄像头管理 | 网页界面添加/禁用摄像头、切换源 |
状态监控 | 是否运行、摄像头是否连接、最近日志等 |
重启控制 | Web 远程控制算法进程重启或更新 |
架构
[摄像头] ─► [算法模块:检测+分类+追踪]│├─► 记录系统(SQLite)├─► 推流模块(FFmpeg ➜ ZLMediaKit)└─► Web 控制界面(Flask + JS)【系统控制】
│
├─ 后台启动脚本(Linux: systemd / Windows: 注册服务)
├─ 配置文件读取摄像头/IP/模型路径等
└─ 日志 & 异常提醒模块
把算法启动关闭,摄像头管理,推流等操作都做在网站上进行操作。可以通过 Web 管理界面(基于 Flask + HTML/JS) 实现以下功能的可视化控制:
✅ 功能目标
功能模块 | 可操作内容 |
---|---|
📷 摄像头管理 | 添加 / 删除 / 启动 / 停止摄像头 |
🧠 算法启动 / 停止 | 控制目标检测分类等主流程运行状态 |
📡 推流管理 | 启用/关闭 HLS 或 FLV 推流 |
🔄 实时状态 | 显示运行中、异常、摄像头离线等状态 |
🧰 设置中心 | 修改参数、模型路径、区域配置等 |
✅ 实现思路
- Flask 提供控制接口
@app.route("/control/start", methods=["POST"])
def start_algorithm():# 启动算法主线程或子进程return jsonify(success=True)@app.route("/control/stop", methods=["POST"])
def stop_algorithm():# 停止线程 / 杀掉子进程return jsonify(success=True)
- 摄像头状态管理接口
@app.route("/camera/list")
def list_cameras():# 从配置或数据库读取摄像头列表return jsonify(cameras=[...])@app.route("/camera/toggle", methods=["POST"])
def toggle_camera():# 启用/禁用某个 RTSP 摄像头源...
- 前端界面控制示意(HTML)
<h3>🧠 算法状态</h3>
<button onclick="startAlgo()">启动</button>
<button onclick="stopAlgo()">停止</button><h3>📷 摄像头</h3>
<div id="cameraList"></div><script>
function startAlgo() {fetch("/control/start", {method: "POST"});
}
function stopAlgo() {fetch("/control/stop", {method: "POST"});
}
function loadCameras() {fetch("/camera/list").then(res => res.json()).then(data => {document.getElementById("cameraList").innerHTML =data.cameras.map(c => `<p>${c.name} - ${c.url}</p>`).join('');});
}
loadCameras();
</script>
接下来就构建一整套猫咪如厕检测系统的 Web 管理平台 ,具备以下完整功能模块 ✅
✅ 平台功能总览
🧠 算法控制模块
-
✅ 启动 / 停止算法检测主程序
-
✅ 查看当前运行状态 / 日志信息
📷 摄像头管理模块
-
✅ 添加 / 编辑 / 删除摄像头(RTSP/USB)
-
✅ 开启/关闭单个摄像头检测流程
-
✅ 实时状态展示(在线 / 离线 / 异常)
📡 推流控制模块
-
✅ 启用 / 停止推流到 ZLMediaKit(FLV/HLS)
-
✅ 显示当前推流地址 & 播放状态
🧰 设置中心
-
✅ 修改模型路径、识别阈值、如厕区域等参数
-
✅ 动态配置保存至数据库或 JSON
📊 仪表盘整合
-
✅ 图表数据整合
-
✅ 可跳转查看每个摄像头的实时预览 / 状态页
🧩 技术结构规划
层级 | 技术 |
---|---|
前端 | Flask + Bootstrap + JS (fetch) |
后端 | Flask + SQLite + 多线程控制 |
子模块 | 线程管理器(摄像头进程)、推流控制器、算法封装 |
配置 | 使用 JSON / 数据库存储摄像头列表与参数配置 |
🛠 项目目录建议
project/
├── main.py # 启动入口(Flask + 控制线程)
├── camera_manager.py # 摄像头管理逻辑
├── algorithm_runner.py # 单摄像头算法运行线程
├── stream_pusher.py # 推流器
├── templates/
│ ├── index.html # 如厕记录页
│ ├── dashboard.html # 图表仪表盘
│ └── platform.html # 📍 控制平台页 ✅
├── static/
│ └── js/ platform.js # 控制中心JS(启动、控制)
├── config/
│ └── cameras.json # 摄像头配置
└── data/└── toilet_logs.db # 数据库
✅ 接下来我可以做什么:
-
创建
/platform
页面并美化界面 -
后端实现算法线程启动/终止
-
摄像头配置管理
-
推流启用关闭控制
-
实时状态可视化
📌 非常棒,咱们接下来就构建一整套猫咪如厕检测系统的 Web 管理平台** ,具备以下完整功能模块 ✅
✅ 平台功能总览(你将拥有的)
🧠 算法控制模块
-
✅ 启动 / 停止算法检测主程序
-
✅ 查看当前运行状态 / 日志信息
📷 摄像头管理模块
-
✅ 添加 / 编辑 / 删除摄像头(RTSP/USB)
-
✅ 开启/关闭单个摄像头检测流程
-
✅ 实时状态展示(在线 / 离线 / 异常)
📡 推流控制模块
-
✅ 启用 / 停止推流到 ZLMediaKit(FLV/HLS)
-
✅ 显示当前推流地址 & 播放状态
🧰 设置中心
-
✅ 修改模型路径、识别阈值、如厕区域等参数
-
✅ 动态配置保存至数据库或 JSON
📊 仪表盘整合
-
✅ 图表数据整合
-
✅ 可跳转查看每个摄像头的实时预览 / 状态页
技术结构规划
层级 | 技术 |
---|---|
前端 | Flask + Bootstrap + JS (fetch) |
后端 | Flask + SQLite + 多线程控制 |
子模块 | 线程管理器(摄像头进程)、推流控制器、算法封装 |
配置 | 使用 JSON / 数据库存储摄像头列表与参数配置 |
项目目录
project/
├── main.py # 启动入口(Flask + 控制线程)
├── camera_manager.py # 摄像头管理逻辑
├── algorithm_runner.py # 单摄像头算法运行线程
├── stream_pusher.py # 推流器
├── templates/
│ ├── index.html # 如厕记录页
│ ├── dashboard.html # 图表仪表盘
│ └── platform.html # 控制平台页
├── static/
│ └── js/ platform.js # 控制中心JS(启动、控制)
├── config/
│ └── cameras.json # 摄像头配置
└── data/└── toilet_logs.db # 数据库
✅ 检测任务配置功能(你想要实现的)
参数项 | 描述 |
---|---|
📷 摄像头选择 | 从已有摄像头中选一个(RTSP/USB) |
🧠 模型选择 | 可选择不同 YOLO 模型(检测/分割/分类) |
⚙️ 功能配置 | 是否启用检测 / 分类 / 推流 / 识别等 |
🗺️ 区域配置 | 指定如厕区域坐标(或使用已有区域) |
📝 任务名称 / 备注 | 自定义识别任务的命名与说明 |
✅ 页面
<h3>➕ 添加检测任务</h3>
<form method="POST" action="/task/create">📷 摄像头:<select name="camera_id"><option value="1">厕所1号(RTSP)</option>...</select>🧠 模型类型:<select name="model"><option value="yolov11.pt">YOLOv11</option><option value="segment.pt">分割模型</option></select>✅ 功能启用:<label><input type="checkbox" name="enable_detection" checked> 检测</label><label><input type="checkbox" name="enable_classify" checked> 分类</label><label><input type="checkbox" name="enable_stream"> 推流</label>🗺️ 区域坐标:<input name="region_x1" placeholder="x1"><input name="region_y1" placeholder="y1"><input name="region_x2" placeholder="x2"><input name="region_y2" placeholder="y2">📝 任务名称:<input name="task_name" placeholder="任务说明"><button type="submit">添加任务</button>
</form>
后端处理逻辑
-
提交表单 →
/task/create
POST 请求 -
解析参数 → 启动一个新检测线程(摄像头+模型+配置)
-
保存任务信息到数据库 / 配置文件(支持持久化)
暂时使用一个摄像头,后续设计好摄像头管理后可以选择,我们先围绕单摄像头任务管理 设计“添加检测任务”功能
✅ 当前阶段:任务创建核心功能
功能模块 | 支持内容 |
---|---|
✅ 固定摄像头源 | 先用默认 RTSP 或 USB 摄像头 |
✅ 可选模型路径 | 手动选择使用的模型文件(如 YOLOv11.pt) |
✅ 启用功能模块 | 检测 / 分类 / 推流开关 |
✅ 自定义如厕区域 | 提供坐标 x1 y1 x2 y2 |
✅ 自定义任务名 | 用于后台标识、日志保存等 |
🧩 网页界面示意(/task/new
)
字段 | 示例输入 |
---|---|
模型路径 | models/yolov11.pt |
功能 | ✅ 检测 ✅ 分类 ✅ 推流 |
区域坐标 | x1=100 y1=200 x2=500 y2=600 |
任务名 | 厕所检测任务1 |
接下来:
- 创建
/task/new
页面(任务创建表单) - 后端
/task/create
路由:接收并保存配置 - 启动任务线程(封装算法推理逻辑+摄像头接入)
- (后续)任务管理界面
/platform/tasks
from flask import Flask, render_template, request, redirect, url_for, jsonify
import os
import json# 创建 Flask 应用
app = Flask(__name__)# 任务配置文件路径
TASK_CONFIG_PATH = "/mnt/data/detection_tasks.json"# 初始化任务配置文件(如果不存在)
if not os.path.exists(TASK_CONFIG_PATH):with open(TASK_CONFIG_PATH, "w") as f:json.dump([], f)@app.route("/task/new")
def new_task():return """<!DOCTYPE html><html lang="zh"><head><meta charset="UTF-8"><title>添加检测任务</title></head><body><h2>➕ 添加检测任务</h2><form method="POST" action="/task/create"><label>任务名称:<input type="text" name="task_name" required></label><br><br><label>模型路径:<input type="text" name="model_path" value="models/yolov11.pt"></label><br><br><label>启用功能:</label><input type="checkbox" name="enable_detection" checked>检测<input type="checkbox" name="enable_classify" checked>分类<input type="checkbox" name="enable_stream">推流<br><br><label>如厕区域坐标:</label><br>x1: <input name="region_x1" type="number"> y1: <input name="region_y1" type="number"> x2: <input name="region_x2" type="number"> y2: <input name="region_y2" type="number"><br><br><button type="submit">提交任务</button></form></body></html>"""@app.route("/task/create", methods=["POST"])
def create_task():task = {"name": request.form.get("task_name"),"model_path": request.form.get("model_path"),"enable_detection": "enable_detection" in request.form,"enable_classify": "enable_classify" in request.form,"enable_stream": "enable_stream" in request.form,"region": {"x1": int(request.form.get("region_x1", 0)),"y1": int(request.form.get("region_y1", 0)),"x2": int(request.form.get("region_x2", 0)),"y2": int(request.form.get("region_y2", 0)),}}with open(TASK_CONFIG_PATH, "r+") as f:data = json.load(f)data.append(task)f.seek(0)json.dump(data, f, indent=2)f.truncate()return redirect(url_for("new_task"))app.run(host="0.0.0.0", port=5001)
STDOUT/STDERR
* Serving Flask app '__main__'* Debug mode: off
[31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m* Running on all addresses (0.0.0.0)* Running on http://127.0.0.1:5001* Running on http://10.129.66.192:5001
[33mPress CTRL+C to quit[0m