PedestrianVision 行人车辆智能检测系统 基于深度学习的行人车辆智能检测与监控系统,采用最新的YOLOv26目标检测算法,结合Web端可视化界面、实时摄像头监控、历史记录管理和智能报告生

目标检测实战:仪表盘指针识别

保姆级 YOLOv8/9/10 教程,附完整数据集与源码

PedestrianVision 行人车辆智能检测系统
在这里插入图片描述

系统概述

这是一套基于深度学习的行人车辆智能检测与监控系统,采用最新的YOLOv26目标检测算法,结合Web端可视化界面、实时摄像头监控、历史记录管理和智能报告生成等先进功能。
在这里插入图片描述

技术亮点:
YOLOv26目标检测 - 采用最新YOLO算法,支持行人和车辆实时检测
Web端可视化界面 - 现代化HTML界面,支持图片/视频/摄像头多种检测模式
实时摄像头监控 - WebSocket实时通信,约20FPS流畅检测
历史记录管理 - 本地JSON存储,支持分页查看和记录管理
HTML报告导出 - 自动生成精美检测报告,支持下载保存
用户登录系统 - 完整的注册登录功能,数据安全隔离
检测结果放大 - 支持点击图片放大查看,细节清晰可见
拖拽上传支持 - 支持拖拽上传图片和视频,操作便捷
在这里插入图片描述

交付内容:在这里插入图片描述

完整的源代码在这里插入图片描述

训练好的YOLOv26模型文件
在这里插入图片描述

PedestrianVision 行人车辆智能检测系统 完整构建方案

一、系统核心功能

模块功能描述
用户模块注册、登录、权限隔离,数据安全存储
检测模块图片检测、视频检测、实时摄像头监控(支持拖拽上传)
结果管理历史记录分页查看、单条记录删除、检测结果放大查看
报告导出自动生成HTML格式检测报告,可下载保存
数据统计实时统计检测次数、目标总数、各类目标数量

二、环境依赖安装

# 后端依赖
pip install fastapi uvicorn ultralytics opencv-python python-multipart pydantic

# 前端依赖(Node.js环境)
npm install vue@3 element-plus axios

三、后端核心代码实现(FastAPI)

1. 项目结构

PedestrianVision/
├── app.py               # 主程序入口
├── models/
│   └── user.py          # 用户模型
├── routes/
│   ├── auth.py          # 登录注册路由
│   └── detection.py     # 检测与历史记录路由
├── static/              # 前端静态文件
├── uploads/             # 上传文件存储目录
├── output/              # 检测结果输出目录
└── logs/                # 日志与历史记录存储目录

2. 主程序入口 app.py

import os
import cv2
import json
import uuid
import shutil
from datetime import datetime
from pathlib import Path
from fastapi import FastAPI, File, UploadFile, WebSocket, WebSocketDisconnect, HTTPException
from fastapi.staticfiles import StaticFiles
from fastapi.responses import HTMLResponse, FileResponse
from fastapi.middleware.cors import CORSMiddleware
from ultralytics import YOLO

# 初始化FastAPI应用
app = FastAPI(title="行人车辆检测系统", description="基于YOLOv26的智能检测平台")

# 允许跨域
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 配置路径
BASE_DIR = Path(__file__).resolve().parent
STATIC_DIR = BASE_DIR / "static"
UPLOAD_DIR = BASE_DIR / "uploads"
OUTPUT_DIR = BASE_DIR / "output"
LOGS_DIR = BASE_DIR / "logs"
HISTORY_FILE = LOGS_DIR / "detection_history.json"
USERS_FILE = LOGS_DIR / "users.json"

# 确保目录存在
for dir_path in [STATIC_DIR, UPLOAD_DIR, OUTPUT_DIR, LOGS_DIR]:
    dir_path.mkdir(parents=True, exist_ok=True)

# 初始化模型
model = YOLO("yolov26.pt")

# 挂载静态文件
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")

3. 检测功能核心代码(图片/视频/实时监控)

# 全局变量
detection_history = []
users = {}

# 加载历史记录
if HISTORY_FILE.exists():
    with open(HISTORY_FILE, "r") as f:
        detection_history = json.load(f)
if USERS_FILE.exists():
    with open(USERS_FILE, "r") as f:
        users = json.load(f)

@app.post("/api/detect/image")
async def detect_image(file: UploadFile = File(...)):
    # 保存上传图片
    file_id = str(uuid.uuid4())
    filename = f"{file_id}_{file.filename}"
    file_path = UPLOAD_DIR / filename
    with open(file_path, "wb") as buffer:
        shutil.copyfileobj(file.file, buffer)

    # 目标检测
    img = cv2.imread(str(file_path))
    results = model(img)
    annotated_img = results[0].plot()

    # 统计目标数量
    counts = {}
    for box in results[0].boxes:
        cls_name = results[0].names[int(box.cls)]
        counts[cls_name] = counts.get(cls_name, 0) + 1

    # 保存检测结果图片
    output_path = OUTPUT_DIR / f"result_{filename}"
    cv2.imwrite(str(output_path), annotated_img)

    # 记录检测历史
    record = {
        "id": file_id,
        "type": "图片",
        "time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        "filename": file.filename,
        "counts": counts,
        "result_path": str(output_path.relative_to(BASE_DIR))
    }
    detection_history.append(record)
    with open(HISTORY_FILE, "w") as f:
        json.dump(detection_history, f)

    return {
        "code": 200,
        "data": {
            "result_url": f"/static/output/result_{filename}",
            "counts": counts,
            "total": sum(counts.values())
        }
    }

@app.websocket("/api/detect/ws")
async def detect_realtime(websocket: WebSocket):
    await websocket.accept()
    try:
        while True:
            # 接收摄像头帧数据(base64格式)
            data = await websocket.receive_text()
            # 解码并检测
            # 简化实现:实际需处理base64图像解码
            # 发送检测结果(标注后的帧+统计数据)
            await websocket.send_text(json.dumps({
                "counts": {"person": 0, "car": 0, "bus": 0},
                "frame": ""
            }))
    except WebSocketDisconnect:
        pass

4. 用户登录注册与历史记录路由

@app.post("/api/auth/register")
async def register(username: str, password: str):
    if username in users:
        raise HTTPException(status_code=400, detail="用户名已存在")
    users[username] = password
    with open(USERS_FILE, "w") as f:
        json.dump(users, f)
    return {"code": 200, "msg": "注册成功"}

@app.post("/api/auth/login")
async def login(username: str, password: str):
    if users.get(username) != password:
        raise HTTPException(status_code=400, detail="用户名或密码错误")
    return {"code": 200, "token": username}

@app.get("/api/history")
async def get_history():
    return {"code": 200, "data": detection_history}

@app.delete("/api/history/{record_id}")
async def delete_history(record_id: str):
    global detection_history
    detection_history = [r for r in detection_history if r["id"] != record_id]
    with open(HISTORY_FILE, "w") as f:
        json.dump(detection_history, f)
    return {"code": 200, "msg": "删除成功"}

@app.get("/api/report/{record_id}")
async def generate_report(record_id: str):
    # 生成HTML报告(简化实现)
    record = next((r for r in detection_history if r["id"] == record_id), None)
    if not record:
        raise HTTPException(status_code=404, detail="记录不存在")
    report_html = f"""
    <html>
    <head><title>检测报告</title></head>
    <body>
        <h1>行人车辆检测报告</h1>
        <p>检测类型:{record['type']}</p>
        <p>检测时间:{record['time']}</p>
        <p>目标统计:{record['counts']}</p>
        <img src="/{record['result_path']}" width="800">
    </body>
    </html>
    """
    report_path = OUTPUT_DIR / f"report_{record_id}.html"
    with open(report_path, "w") as f:
        f.write(report_html)
    return FileResponse(report_path, filename=f"report_{record_id}.html")

四、前端核心代码实现(Vue3+Element Plus)

1. 登录页面 src/views/Login.vue

<template>
  <div class="login-container">
    <div class="login-card">
      <div class="icon">🚗</div>
      <h2>智能检测系统</h2>
      <el-tabs v-model="activeTab">
        <el-tab-pane label="登录" name="login">
          <el-form :model="loginForm">
            <el-form-item label="用户名">
              <el-input v-model="loginForm.username"></el-input>
            </el-form-item>
            <el-form-item label="密码">
              <el-input v-model="loginForm.password" type="password"></el-input>
            </el-form-item>
            <el-button type="primary" @click="handleLogin">登录</el-button>
          </el-form>
        </el-tab-pane>
        <el-tab-pane label="注册" name="register">
          <el-form :model="registerForm">
            <el-form-item label="用户名">
              <el-input v-model="registerForm.username"></el-input>
            </el-form-item>
            <el-form-item label="密码">
              <el-input v-model="registerForm.password" type="password"></el-input>
            </el-form-item>
            <el-button type="primary" @click="handleRegister">注册</el-button>
          </el-form>
        </el-tab-pane>
      </el-tabs>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import axios from 'axios'

const router = useRouter()
const activeTab = ref('login')
const loginForm = ref({ username: 'admin', password: 'admin' })
const registerForm = ref({ username: '', password: '' })

const handleLogin = async () => {
  const res = await axios.post('/api/auth/login', loginForm.value)
  if (res.data.code === 200) {
    localStorage.setItem('token', res.data.token)
    router.push('/home')
  }
}

const handleRegister = async () => {
  await axios.post('/api/auth/register', registerForm.value)
  activeTab.value = 'login'
}
</script>

2. 图片检测页面 src/views/ImageDetect.vue

<template>
  <div class="detect-container">
    <el-card title="上传图片">
      <el-upload
        action="/api/detect/image"
        :headers="headers"
        :on-success="handleSuccess"
        list-type="picture-card"
        :auto-upload="false"
        :before-upload="beforeUpload"
      >
        <el-button>点击或拖拽上传</el-button>
      </el-upload>
    </el-card>

    <el-card title="检测结果" style="margin-top:20px">
      <img v-if="resultUrl" :src="resultUrl" alt="检测结果" style="max-width:100%">
      <div v-if="counts">
        <p v-for="(num, name) in counts" :key="name">{{ name }}: {{ num }}</p>
        <p>总计: {{ total }}</p>
      </div>
      <el-button type="primary" @click="downloadReport">导出报告</el-button>
    </el-card>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import axios from 'axios'

const headers = { Authorization: `Bearer ${localStorage.getItem('token')}` }
const resultUrl = ref('')
const counts = ref({})
const total = ref(0)
const recordId = ref('')

const beforeUpload = (file) => {
  const formData = new FormData()
  formData.append('file', file)
  axios.post('/api/detect/image', formData, { headers }).then(res => {
    if (res.data.code === 200) {
      resultUrl.value = res.data.data.result_url
      counts.value = res.data.data.counts
      total.value = res.data.data.total
    }
  })
  return false
}

const handleSuccess = (res) => {
  if (res.code === 200) {
    resultUrl.value = res.data.result_url
    counts.value = res.data.counts
    total.value = res.data.total
    recordId.value = res.data.id
  }
}

const downloadReport = () => {
  window.open(`/api/report/${recordId.value}`)
}
</script>

3. 实时监控页面 src/views/RealtimeMonitor.vue

<template>
  <div class="monitor-container">
    <el-card title="实时监控画面">
      <video ref="videoRef" autoplay playsinline style="width:100%"></video>
      <el-button type="primary" @click="startMonitor">开始监控</el-button>
      <el-button type="danger" @click="stopMonitor">停止监控</el-button>
    </el-card>

    <el-card title="实时统计" style="margin-top:20px">
      <p>行人: {{ stats.person }}</p>
      <p>车辆: {{ stats.car }}</p>
      <p>公交车: {{ stats.bus }}</p>
    </el-card>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

const videoRef = ref(null)
const stats = ref({ person: 0, car: 0, bus: 0 })
let stream, socket

const startMonitor = () => {
  navigator.mediaDevices.getUserMedia({ video: true }).then(s => {
    stream = s
    videoRef.value.srcObject = stream
    // 连接WebSocket,发送帧并接收检测结果
    socket = new WebSocket(`ws://${window.location.host}/api/detect/ws`)
    socket.onmessage = (event) => {
      const data = JSON.parse(event.data)
      stats.value = data.counts
    }
  })
}

const stopMonitor = () => {
  if (stream) stream.getTracks().forEach(track => track.stop())
  if (socket) socket.close()
}

onUnmounted(() => stopMonitor())
</script>

五、系统部署与运行

  1. 后端启动
    uvicorn app:app --host 0.0.0.0 --port 8000
    
  2. 前端启动
    npm run serve
    
  3. 使用流程
    • 注册账号并登录系统;
    • 选择图片/视频/实时监控模式进行检测;
    • 查看检测结果、统计数据,导出HTML报告;
    • 在历史记录中查看、删除过往检测记录。

六、扩展功能建议

  • 可接入MQTT协议,对接监控摄像头进行远程实时检测;
  • 可增加目标追踪功能,实现行人/车辆轨迹绘制;
  • 可增加异常行为告警功能,如行人闯入禁区、车辆违规停放等;
  • 可升级报告生成功能,支持PDF格式导出与数据可视化图表。

目标检测实战:仪表盘指针识别

保姆级 YOLOv8/9/10 教程,附完整数据集与源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值