从 0 到 1 手搓 AI 视觉识别平台前端:1,286 路视频、6 大模块、纯 HTML/CSS/JS 实现(附完整思路与代码)

摘要 :算法能跑通,只完成了 AI 视觉项目的 30%;剩下 70% 是「让人看得懂、用得上」。本文用一个可运行的单文件原型,拆解 AI 视觉识别平台的 6 大核心模块------态势总览、实时预览、事件中心、事件详情与处置、证据档案、检索分析,覆盖 KPI 体系、九宫格预览与检测框叠加、事件处置漏斗、合规化证据归档,以及以文搜图的多模态检索。全文零框架依赖,一个 index.html 双击即开,所有图表用 CSS/SVG 手绘,代码可直接抄进你的项目。

关键词:AI 视觉 · 视频结构化 · 前端可视化 · 边缘计算 · 以文搜图 · 智慧园区 · 数据大屏


一、先看效果:10 张图速览

整套控制台共 6 个业务页面 + 1 个占位页,全部在同一个 index.html 里切换:

模块 一句话作用
态势总览 5 个 KPI + 趋势/分布/TOP5/健康度,30 秒判断"今天安不安全"
实时预览 1/4/9 分屏 + PTZ 云台 + 检测框/轨迹/ROI 叠加
事件中心 多维筛选 + 事件列表 + 处置漏斗 + 处置效能
事件详情与处置 取证视频三联 + 结构化事件信息 + 闭环流程时间线
证据档案 证据包管理 + 存储策略 + 合规审计 + 导出日志
检索分析 以图搜图 / 以文搜图 / 条件检索,多模态向量检索

下面这张是整体分层架构,先看清楚数据从哪来到哪去:


二、为什么"算法跑通了",界面还是没法用?

做过视觉项目的同学都踩过这个坑:模型 mAP 做到 0.9+,交付给客户却换来一句"我看不懂这个界面"。问题通常不在算法,而在信息组织的三层断裂:

  1. 原始告警太多,没有收敛:1,286 路视频一天产生 342 条事件,不做分级合并,值班人员 10 分钟就麻木了;
  2. 只有告警,没有证据:安全事件要追责、要保险理赔,缺了原始帧/标注帧/短视频三联,事件就是"死"的;
  3. 只有查询,没有检索:事后复盘时只知道"大概上午有个穿红马甲的人从北门进去",传统按时间翻录像要翻几个小时。

所以前端要解决的是三件事:降噪(把 342 条压成 27 条待处置)、留证(一次事件一个证据包)、回溯(用一句话把视频捞出来)。下面按模块拆。


三、设计系统:一套 CSS 变量撑起整站

不做设计系统的大屏,改一个颜色要动 200 处。这里把颜色、圆角、阴影、侧边栏宽度全部收敛到 :root,并且语义化命名--red 而不是 #DC2626),业务里只写 var(--red),主题切换只要换一层变量:

复制代码
:root{
  --bg:#F5F7FB; --card:#FFFFFF; --border:#EEF1F7;
  --primary:#4C6FFF; --primary-soft:#EEF2FF; --primary-line:#DDE5FF;
  --purple:#7A5AF8; --purple-soft:#F1ECFF;
  --red:#DC2626; --red-soft:#FEECEC;
  --orange:#EA580C; --orange-soft:#FFF1E8;
  --amber:#D97706; --amber-soft:#FEF3E2;
  --green:#16A34A; --green-soft:#E7F6EC;
  --text:#1E293B; --text2:#334155; --muted:#64748B; --light:#94A3B8;
  --radius:12px; --radius-sm:8px; --radius-pill:999px;
  --shadow:0 1px 2px rgba(16,24,40,.04),0 1px 3px rgba(16,24,40,.06);
  --nav-w:220px; --topbar-h:64px;
  --font:"Noto Sans SC","Microsoft YaHei",-apple-system,sans-serif;
  /* 数字单独用等宽字体,KPI 跳动时不会左右抖 */
  --num:"Sarasa Gothic SC",ui-monospace,SFMono-Regular,Menlo,monospace;
}

三个值得抄的细节:

  • -soft 配套色 :每个主色都配一个浅色底(--red-soft),标签/图标底色直接用,不用手写 rgba()
  • 数字用等宽字体变量 --num:KPI 每秒刷新时,非等宽字体数字宽度变化会导致整行"呼吸抖动";
  • 语义色 = 业务等级--red 紧急 / --orange 高 / --amber 中 / --blue 低,代码里不出现"颜色",只出现"等级"。

四、模块拆解

4.1 态势总览:5 个 KPI 定义"今天安不安全"

KPI 不是越多越好,这张卡片组只保留 5 个能直接驱动动作的指标:

KPI 环比 为什么是它
接入路数 1,286 路 ▲2.3% 规模底盘,扩容/计费依据
设备在线率 98.6% ▲0.4% 低于阈值说明"盲区"出现,算法再准也没用
今日事件 342 ▼5.1% 总量趋势,判断整改是否有效
待处置 27 ▲8 唯一需要立刻点进去的数字
事件闭环率 95.2% ▲1.2% 考核运营质量,不是考核算法

配图区用四象限解决"看趋势 / 看当下 / 看分布 / 看瓶颈":

  • 左上 事件趋势·近 7 日(折线 + 实时标记)
  • 右上 实时告警流(滚动列表,紧急/高/中/低四级色标)
  • 左下 事件类型分布(环形图):未戴安全帽 22%、区域入侵 20%、烟火检测 18%、人员倒地 15%、违章停车 14%、人车计数 11%
  • 右下 高发点位 TOP5:2 号车间北门 42 → 园区西路 35 → 周界东 28 → 仓库 A 区 21 → 办公楼前 15

设计要点:TOP5 点位其实是"整改优先级清单"。它和类型分布做交叉分析才有价值------比如"2 号车间北门 + 未戴安全帽"双高,答案不是加摄像头,而是在门口装个语音提示喇叭。

底部再加两块运维视角:算法健康度 (YOLOv8 96% / ByteTrack 92% / 烟火检测 94% / VLM 90% / Grounding DINO 88%)与边缘节点负载表 。节点表里"边缘节点-周界B"是离线状态(CPU/GPU 显示 ---),这种「空值要有专门的占位形态」是很容易被忽略的细节:

复制代码
<tr>
  <td class="id-cell">边缘节点-周界B</td>
  <td>10.30.1.11</td>
  <td>64</td>
  <td>---</td><td>---</td>
  <td><span class="tag tag-gray">离线</span></td>
</tr>

4.2 实时预览:九宫格 + 检测框叠加 + PTZ

这是全站技术含量最高的一屏,核心是视频层与算法层的解耦<img> 只负责画面,检测框是绝对定位的 <div>,坐标用百分比而不是像素------这样 1 分屏、4 分屏、9 分屏切换时,框不用重算。

复制代码
<div class="grid9" id="grid9">
  <div class="tile">
    <img src="assets/cam3.png"/>
    <div class="osd-tl">CH03 仓库A区</div>
    <div class="osd-time">11:42:10</div>
    <!-- 检测框:百分比坐标,跟着容器自适应 -->
    <div class="box" style="left:46%;top:30%;width:28%;height:40%;border-color:#EA580C">
      <span class="bl" style="background:#EA580C">烟雾 0.88</span>
    </div>
  </div>
  ...
</div>

.grid9{display:grid;grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(3,1fr);gap:12px;}
.tile{position:relative;border-radius:9px;overflow:hidden;background:#0B1220;}
.tile img{width:100%;height:100%;object-fit:cover;display:block;}
.tile .osd-tl{position:absolute;top:8px;left:8px;background:rgba(8,12,20,.55);color:#fff;
  font-size:11px;padding:3px 7px;border-radius:5px;backdrop-filter:blur(2px);}
.tile .box{position:absolute;border:2px solid;border-radius:3px;}
.tile .box .bl{position:absolute;top:-18px;left:-2px;font-size:10px;font-weight:600;
  padding:1px 5px;border-radius:3px;white-space:nowrap;}

几个工程经验:

  1. OSD 用半透明深色底 + backdrop-filter:blur,避免白色文字压在亮画面上看不清;
  2. 检测框颜色跟事件等级走,一眼就能在 9 路画面里定位异常(红=紧急、橙=高、琥珀=中、蓝=低);
  3. 信号丢失要有"空态",而不是破图或黑屏。用统一占位块 + 图标 + 文案,运维才知道是"设备掉线"而不是"页面崩了";
  4. 右上角叠加快切换开关(检测框 / 轨迹 / ROI / 标签),轨迹密集时一键关掉,性能与可读性都能救回来。

右侧 PTZ 用圆形方向盘(上下左右 + 中间 Home)+ 变倍滑杆,同时展示当前通道的分辨率 2560×1440 / 码率 4.0 Mbps / 帧率 25 fps / 编码 H.265------排查"卡顿是谁的锅"时,这四个数缺一不可。

4.3 事件中心:把 342 条压成 27 条

筛选区给了 5 个维度(关键词 / 时间范围 / 点位 / 类型 / 等级 / 状态),顶部再用 Tab 做频道的快速切换:全部 342 · 待处置 27 · 今日 342 · 误报 19。这里"待处置 27"就是值班人员的真实工作量,也是这一屏唯一需要被点开的入口。

右侧的事件处置漏斗是整个平台最有价值的一张图------它把"算法准不准"和"运营到不到位"分开了:

复制代码
触发 342 → AI识别 338 → 告警推送 320 → 人工确认 305 → 闭环 290
环节 损耗 暴露的问题
触发 → AI识别 -4 算法侧漏检/去重收敛
AI识别 → 告警推送 -18 推送链路问题(MQTT 掉线、Webhook 超时、免打扰时段)
告警推送 → 人工确认 -15 值班响应问题,人不够或告警太吵
人工确认 → 闭环 -15 现场处置能力问题

注意漏斗旁边那行小字:闭环率 = 已闭环事件 / 全部事件;平均处置时长仅统计已闭环事件 。口径不写清楚,95.2% 这个数就会被误读成"算法准确率 95.2%"。任何比率型指标,都要在界面上写清分母------这是大屏设计中最容易被审计挑出来的问题。

4.4 事件详情与处置:一屏完成"看证据 + 定责任 + 留痕"

点开一条紧急事件,页面要回答三个问题:

① 到底发生了什么? 用「标注帧 / 原始帧 / 短视频」三联视图。标注帧证明算法看到了什么,原始帧保留真实性,短视频呈现过程------三者缺一,证据链就不完整。

② 机器怎么判的? 结构化事件信息表格把"黑盒"摊开:

字段
事件类型 烟火检测
发生点位 仓库A区
触发时间 2026-09-11 11:42:08
算法模型 烟火检测 v3.2
置信度 0.88
关联设备 CH03 / 边缘节点-园区A
推送方式 MQTT + Webhook

③ 后来怎么样了? 用时间线展示闭环流程(事件触发 → AI 识别与分级 → 告警推送 → 人工确认 → 现场处置 → 闭环归档),未完成节点显式标注"待处理 / 未开始"。底部三个动作按钮:确认有效 / 标记误报 / 派单------"标记误报"必须存在,它是模型迭代的负样本来源(本例当天 19 条误报,误报率 5.6%,全部可回流训练)。

4.5 证据档案:留存策略写进界面

这一屏面向合规与审计。顶部 4 个指标:证据包总数 18,426(本周 +312)、存储总量 6.8 TB、证据完整率 100%、存储可用率 99.98%。

中间把留存与合规策略直接展示,而不是藏在配置里:

原始视频留存 90 天
证据包留存 永久
加密方式 AES-256
合规标准 GB/T 28181
审计日志 已开启

右侧两块是审计最关心的:证据构成 (视频 57% / 图片 22% / 结构化 21%,用于容量规划)与导出日志 (谁、什么时候、导了哪个包)。导出是高危操作,必须逐条留痕------EP-20260911-0342 张伟 · 11:50 导出 这种粒度才够。

4.6 检索分析:用一句话把视频捞出来

传统安防检索是"选摄像头 → 拖时间轴 → 人肉看"。多模态向量检索把它变成一句自然语言:

穿红色马甲的作业人员出现在 2 号车间北门

返回按相似度排序的命中片段(共 46 条):0.94 红色马甲 · CH02 2号车间北门 11:390.91 红色马甲 · CH02 10:120.87 疑似目标 · CH01 09:400.83 疑似目标 · CH05 08:55

右侧把检索参数显式化 :检索方式(以文搜图)、目标描述、范围点位、时间范围、向量模型 VLM-Embed v2相似度阈值 0.80。阈值一定要露给用户------它直接决定"宁可漏还是宁可多",是个业务决策而不是技术参数。三种模式(以图搜图 / 以文搜图 / 条件检索)用 Tab 切换,覆盖"我有照片 / 我只记得描述 / 我知道时间和点位"三类场景。


五、关键代码实现

5.1 单页多屏:不用路由库,30 行搞定

所有页面都是 <section class="screen">,用 data-screen 声明目标,切换就是增删一个 .active

复制代码
function showScreen(id, name, crumb){
  document.querySelectorAll('.screen').forEach(s=>s.classList.remove('active'));
  document.getElementById(id).classList.add('active');
  document.getElementById('pageTitle').textContent = name;
  document.getElementById('crumb').textContent = crumb;
  document.querySelectorAll('.nav-item').forEach(n=>n.classList.remove('active'));
  var activeNav = document.querySelector('.nav-item[data-screen="'+id+'"]');
  if(activeNav) activeNav.classList.add('active');
  document.querySelector('.content').scrollTop = 0;
}

document.querySelectorAll('.nav-item').forEach(function(item){
  item.addEventListener('click', function(){
    var sc = item.getAttribute('data-screen');
    if(sc === 'coming'){ /* 建设中模块:复用同一个占位页,只换标题 */ return; }
    var titles = {s1:['态势总览','首页 / 态势总览'], s2:['实时预览','首页 / 视频监控 / 实时预览'],
                  s3:['事件中心','首页 / 事件处置 / 事件中心'], s5:['证据档案','首页 / 事件处置 / 证据档案'],
                  s6:['检索分析','首页 / 事件处置 / 检索分析']};
    showScreen(sc, titles[sc][0], titles[sc][1]);
  });
});

好处是:DOM 一次性渲染完,切换零成本、零白屏,非常适合演示与内网部署;后续接真实数据,只要把每个 screen 的渲染函数注册进去即可。

5.2 不引图表库:环形图就是 6 个 <circle>

stroke-dasharray + stroke-dashoffset 做扇区,周长 2πr ≈ 289(r=46),每段长度 = 占比 × 289:

复制代码
<svg viewBox="0 0 120 120" width="120" height="120">
  <circle cx="60" cy="60" r="46" fill="none" stroke="#EEF1F7" stroke-width="16"/>
  <circle cx="60" cy="60" r="46" fill="none" stroke="#4C6FFF" stroke-width="16"
          stroke-dasharray="28 261" stroke-dashoffset="0"  transform="rotate(-90 60 60)"/>
  <circle cx="60" cy="60" r="46" fill="none" stroke="#EA580C" stroke-width="16"
          stroke-dasharray="24 265" stroke-dashoffset="-28" transform="rotate(-90 60 60)"/>
  <!-- 后续扇区:dashoffset 累计减去前一段长度 -->
</svg>

漏斗图更省,纯 div + 宽度百分比:

复制代码
<div class="funnel">
  <div class="fn-row"><span class="fn-label">触发</span>
    <div class="fn-bar" style="width:100%;background:#4C6FFF">342</div></div>
  <div class="fn-row"><span class="fn-label">AI识别</span>
    <div class="fn-bar" style="width:90%;background:#5B79F0">338</div></div>
  <div class="fn-row"><span class="fn-label">告警推送</span>
    <div class="fn-bar" style="width:82%;background:#7A5AF8">320</div></div>
  <div class="fn-row"><span class="fn-label">人工确认</span>
    <div class="fn-bar" style="width:74%;background:#D97706">305</div></div>
</div>

横向柱状(高发点位 TOP5)与健康度柱状同理,用 .r-track + .r-fill.h-bar 两层 div。整套控制台零第三方 JS、零 ECharts,首屏无请求、离线可用,内网交付时这一点非常加分。

5.3 状态标签:一套语义色走天下

复制代码
.tag{display:inline-flex;align-items:center;height:20px;padding:0 8px;border-radius:6px;font-size:11px;font-weight:600;}
.tag-red{background:var(--red-soft);color:var(--red);}       /* 紧急 */
.tag-orange{background:var(--orange-soft);color:var(--orange);} /* 高 */
.tag-amber{background:var(--amber-soft);color:var(--amber);}    /* 中 */
.tag-blue{background:var(--primary-soft);color:var(--primary);} /* 低 */
.tag-green{background:var(--green-soft);color:var(--green);}    /* 已闭环 */
.tag-gray{background:#EEF1F7;color:var(--muted);}                /* 离线/失效 */

六、接真实后端:这些口子要提前留好

原型跑的是静态数据,接生产时按下面对齐即可(建议 REST + WebSocket + MQTT 三通道分工):

能力 建议方案 说明
视频流预览 GB/T 28181 / RTSP → WebRTC 或 HLS 别直接播 RTSP,浏览器不支持;低延迟用 WebRTC
实时告警流 WebSocket 推送 告警流要求秒级,轮询会拖垮服务端
事件查询/派单 REST(GET /eventsPOST /events/{id}/dispatch 筛选条件全部走 query string
设备/节点状态 REST 轮询 + WebSocket 变更推送 心跳 30s,离线判定 3 次丢失
边缘节点上报 MQTT(结构化事件 JSON) 边缘侧弱网,MQTT 比 HTTP 稳
第三方系统联动 Webhook 派单到工单系统、钉钉/企微
以文搜图 POST /search/text → 向量库(VLM-Embed v2) 阈值由前端传入,默认 0.80
证据包下载 带签名的临时 URL 每次下载写审计日志

数据结构上,一条事件建议至少包含:eventId / cameraId / nodeId / type / level / confidence / model / ts / status / evidenceId,前端的所有筛选、漏斗、闭环率都从这几个字段算出来,别让前端做二次推断。


七、踩过的坑与优化建议

  1. 9 路视频同屏会卡:优先降码率走子码流(主码流 2560×1440 只在 1 分屏时用),非焦点画面降到 10 fps;
  2. 检测框坐标用百分比而不是像素,否则一分屏/九分屏切换要重算,还容易错位;
  3. 密集轨迹要能一键关闭:ByteTrack 在人流密集处会画出上百条轨迹,既挡画面又耗 CPU;
  4. 比率指标必须写清口径,闭环率、准确率、在线率旁边都要有注释行;
  5. 空态/离线态单独设计,破图和"0"比"------"更容易被误判成系统故障;
  6. 数字用等宽字体,实时刷新时不抖动;
  7. 告警分级要能配置:同一个"未戴安全帽"在车间是"中"、在危化品仓库就该是"紧急",等级规则不要写死在前端。

八、总结

这套控制台的核心不是"好看",而是把 AI 视觉项目里最容易被忽略的三件事做扎实:

  • 降噪:342 条原始事件 → 27 条待处置,让值班的人有精力处理;
  • 留证:标注帧 / 原始帧 / 短视频 + 结构化信息 + 闭环时间线,形成可审计的证据链;
  • 回溯:以文搜图把"翻录像几小时"压缩成"一句话几秒钟"。

技术上,纯 HTML/CSS/JS + CSS 变量 + SVG 手绘图表,零依赖、单文件、可离线,既适合快速做方案评审,也能作为生产项目的前端骨架直接长上去。

后续可扩展:① 接入真实 WebRTC 流与 PTZ 控制协议;② 事件地图(GIS 一张图)与点位的空间联动;③ 模型效果评测页(漏报/误报回流与版本对比);④ 任务布防的时段化策略(白天/夜间/节假日不同算法)。


如果这篇对你有帮助,欢迎点赞 + 收藏 + 关注。你在做视觉平台时遇到过哪些"算法很强但界面没人用"的场景?评论区聊聊,我把典型问题整理成续篇。

如果对您有所帮助,请点赞打赏支持!

技术合作交流q+++q:2401315930

最后分享一下地图下载器设计及下载地址:

链接:https://pan.baidu.com/s/1RZX7JpTpxES-G7GiaVUxOw

提取码:61cn

地图下载器代码结构设计及功能实现_地图下载管理器解析-CSDN博客

相关推荐
ishangy4 天前
海思 2T 算力|泵吸式四合一气体 AI 布控球技术方案解析
边缘计算·gb28181·ai视觉·气体检测·布控球·有限空间
土星云SaturnCloud1 个月前
充电站AI视觉算法全方案:安全监管+运营提效+服务升级,土星云边缘计算赋能场站智能化
服务器·人工智能·ai·边缘计算·ai视觉
XMAIPC_Robot2 个月前
RK3588+8路AHD+双CAN工控方案|多路模拟视频同步采集+工业总线联动AI边缘检测落地
人工智能·rk3588·ai视觉·图像采集·多路ahd视频
ishangy4 个月前
AI视觉赋能智慧矿山:新一代安全防控体系解决方案
人工智能·边缘计算·ai视觉·智慧矿山·ai视觉监测·智能防控
ishangy4 个月前
山西沁源矿难警示:AI视觉技术如何重塑智慧矿山安全防控体系
ai视觉解决方案·ai视觉·智慧矿山·矿山智能化·山西沁源矿难·智能预警
模拟器连接器曾工6 个月前
AI视觉检测设备参数有哪些?从硬件到算法的全面解析
人工智能·算法·视觉检测·ai视觉·ai视觉检测
朝饮坠露兮2 年前
庐山派K230学习日记5 UART
嵌入式硬件·k230·ai视觉
朝饮坠露兮2 年前
庐山派K230学习日记6 ADC
嵌入式硬件·k230·ai视觉
David_jiahuan2 年前
AI视觉相关的预训练模型、公开数据集
人工智能·预训练模型·公开数据集·ai视觉