网站服务器 64位广州推广工具
✅ 前情提要
家里养了三只猫咪,其中一只布偶猫经常出入厕所。但因为平时忙于学业,没法时刻关注牠的行为。我知道猫咪的如厕频率和时长与健康状况密切相关,频繁如厕可能是泌尿问题,停留过久也可能是便秘或不适。为了更科学地了解牠的如厕习惯,我计划搭建一个基于视频监控和AI识别的系统,自动识别猫咪进出厕所的行为,记录如厕时间和停留时长,并区分不同猫咪。这样即使我不在家,也能掌握猫咪的健康状态,更安心地照顾它们。
已完成工作:
✅猫咪如厕检测与分类识别系统系列【一】 功能需求分析及猫咪分类特征提取
✅猫咪如厕检测与分类识别系统系列【二】多图上传及猫咪分类特征提取更新
✅猫咪如厕检测与分类识别系统系列【三】 融合yolov11目标检测
计划工作:
✅ 猫咪管理功能:已完成猫咪照片上传与名称登记模块。
✅ 多图上传与分类特征提取:已支持批量上传猫咪图像并自动更新个体特征库。
🔄 目标检测与事件识别集成(YOLOv11):功能开发中,已实现猫咪行为自动识别,正在集成至页面。
⏳ 检测区域绘制功能:待开发,计划支持用户自定义如厕检测区域。
⏳ 事件行为记录模块:待完善,将实现如厕进出时间、停留时长等事件记录功能。
⏳ 检测结果推流展示:待更新,计划支持算法结果实时推流。
⏳ 整体运行结果推流整合:待更新,计划集成检测图像与系统状态为统一视频流输出。
本次将继续制作 实时检测模块中的Flask 页面展示记录:🔜 现在我们要继续完成的:
✅ 1. 如厕事件记录系统:
-
记录猫进入、
-
显示:
-
猫咪名字
-
进入时间
-
离开时间
-
如厕时长
-
图片预览
-
-
可按时间筛选、导出记录
✅ 第一步:添加如厕记录系统(记录 + 存图)
🔧 toilet_logger.py
(事件记录模块)
import os
import csv
from datetime import datetimeclass ToiletLogger:def __init__(self, save_dir="records", csv_path="records/toilet_log.csv"):self.save_dir = save_dirself.csv_path = csv_pathos.makedirs(save_dir, exist_ok=True)# 创建CSV头if not os.path.exists(self.csv_path):with open(self.csv_path, 'w', newline='') as f:writer = csv.writer(f)writer.writerow(["Name", "Enter Time", "Exit Time", "Duration(s)", "Enter Image", "Exit Image"])def log(self, name, entry_time, exit_time, enter_img, exit_img):duration = round(exit_time - entry_time, 2)enter_time_str = datetime.fromtimestamp(entry_time).strftime("%Y-%m-%d %H:%M:%S")exit_time_str = datetime.fromtimestamp(exit_time).strftime("%Y-%m-%d %H:%M:%S")enter_path = os.path.join(self.save_dir, enter_img)exit_path = os.path.join(self.save_dir, exit_img)with open(self.csv_path, 'a', newline='') as f:writer = csv.writer(f)writer.writerow([name, enter_time_str, exit_time_str, duration, enter_path, exit_path])
✅ 第二步:在 main.py
检测逻辑中调用记录器
加入:
from toilet_logger import ToiletLogger
logger = ToiletLogger()
然后在状态变化处加上记录逻辑:
# 进入区域
if detected and not cat_present:entry_time = time.time()cat_enter_img = f"{cat_name}_enter_{int(entry_time)}.jpg"cv2.imwrite(f"records/{cat_enter_img}", frame)print(f"🐱 {cat_name} 进入区域")# 离开区域
if not detected and cat_present:exit_time = time.time()cat_exit_img = f"{cat_name}_exit_{int(exit_time)}.jpg"cv2.imwrite(f"records/{cat_exit_img}", frame)duration = round(exit_time - entry_time, 2)logger.log(cat_name, entry_time, exit_time, cat_enter_img, cat_exit_img)print(f"🚪 {cat_name} 离开区域,用时 {duration} 秒")
✅ 第三步:Flask 页面展示记录
页面功能:
-
展示如厕记录表格
-
显示进入/离开时间、图片、猫名
你可以先测试下这部分如厕记录逻辑是否正常工作:
🐾 猫进入 → 保存图片 → 离开 → 记录进 CSV → records/
下有图像和日志。
目录结构:
已分析
# 项目结构
dirs = ["cat_monitor/recognizer","cat_monitor/web/templates","cat_monitor/web/static/uploads","cat_monitor/data/embeddings","cat_monitor/records"
]
#main.py
import cv2
import time
import numpy as np
from recognizer.embedder import CatEmbedder
from recognizer.database import CatDatabase
from recognizer.matcher import CatMatcher
from toilet\_logger import ToiletLogger
from ultralytics import YOLO# 初始化模型与识别器model = YOLO("yolov11.pt") \# 替换为你的模型路径embedder = CatEmbedder()db = CatDatabase()matcher = CatMatcher(db)logger = ToiletLogger()# RTSP 摄像头地址rtsp_url = "rtsp://192.168.0.102:554/stream1"cap = cv2.VideoCapture(rtsp_url)cap.set(cv2.CA\_PROP_BUFFERSIZE, 1)# 区域设定(如厕区域)TOILET_REGION = (100, 100, 400, 400)# 状态追踪cat_present= Falseentry_time = Nonecat_name = "Unknown"cv2.namedWindow("Cat Monitor", cv2.WINDOW\_NORMAL)cv2.resizeWindow("Cat Monitor", 960, 720)
while True:ret, frame = cap.read()if not ret:
✅ 主程序 main.py
已写入,支持:
-
RTSP 视频流读取
-
YOLOv11 检测 + 区域判断
-
猫咪识别(调用分类模块)
-
如厕进入/离开状态跟踪
-
自动保存图像并写入记录日志
接下来我会继续添加:
-
toilet_logger.py
(如厕记录模块) -
分类模块:
embedder.py
,database.py
,matcher.py
-
Flask 前端页面(用于展示如厕记录)
如厕记录前端界面:
# app.py (Flask 前端展示记录)from flask import Flask, render\_templateimport csvapp = Flask(__name__)CSV_FILE = "records/toilet_log.csv"@app.route('/')def index():records = []try:with open(CSV_FILE, newline='') as f:reader = csv.DictReader(f)for row in reader:records.append(row)except FileNotFoundError:passreturn render_template('index.html', records=records)if __name__ == '__main__':app.run(debug=True)
✅ Flask 后端展示代码已完成(app.py
)。
Flask 后端页面代码:
html_code = """
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>猫咪如厕记录</title><style>body { font-family: Arial, sans-serif; margin: 20px; }table { width: 100%; border-collapse: collapse; margin-top: 20px; }th, td { border: 1px solid #ccc; padding: 8px; text-align: center; }th { background-color: #f2f2f2; }input[type="text"] { padding: 6px; width: 200px; margin-right: 10px; }.thumbnail { height: 80px; cursor: pointer; }.modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.7); align-items: center; justify-content: center; }.modal img { max-width: 80%; max-height: 80%; }</style>
</head>
<body><h2>🐱 猫咪如厕记录</h2><input type="text" id="filterInput" placeholder="输入猫咪名字筛选..." onkeyup="filterTable()"><table id="recordTable"><thead><tr><th>猫咪</th><th>进入时间</th><th>离开时间</th><th>如厕时长 (秒)</th><th>进入图</th><th>离开图</th></tr></thead><tbody>{% for r in records %}<tr><td>{{ r['Name'] }}</td><td>{{ r['Enter Time'] }}</td><td>{{ r['Exit Time'] }}</td><td>{{ r['Duration(s)'] }}</td><td><img src="{{ '/' + r['Enter Image'] }}" class="thumbnail" onclick="showModal(this.src)"></td><td><img src="{{ '/' + r['Exit Image'] }}" class="thumbnail" onclick="showModal(this.src)"></td></tr>{% endfor %}</tbody></table><div class="modal" id="imgModal" onclick="hideModal()"><img id="modalImg" src=""></div><script>function filterTable() {let input = document.getElementById("filterInput").value.toLowerCase();let rows = document.querySelectorAll("#recordTable tbody tr");rows.forEach(row => {let name = row.cells[0].textContent.toLowerCase();row.style.display = name.includes(input) ? "" : "none";});}function showModal(src) {document.getElementById("modalImg").src = src;document.getElementById("imgModal").style.display = "flex";}function hideModal() {document.getElementById("imgModal").style.display = "none";}</script>
</body>
</html>
"""with open("cat_monitor/web/templates/index.html", "w", encoding="utf-8") as f:f.write(html_code)"Flask 页面 HTML 已写入完成,支持筛选、图片预览。"
结果
✅ Flask 页面 index.html
已完成,具备以下功能:
-
猫咪名字筛选(实时搜索)
-
如厕记录表格展示(进入时间 / 离开时间 / 时长)
-
进入图 & 离开图缩略图展示
-
点击图片放大预览(弹窗模式)