ソースを参照

姿态识别配置页: 功能与参数一一对应成行

- 每个动作一行: 开关 + 对应参数(跌倒带阈值/帧数, 静止/离岗带秒数)
- 新增疑似离岗开关(取消勾选即禁用, absent_sec=0)
- 布局: 动作配置网格自适应, 开关与参数同行显示
dev 6 日 前
親
コミット
2f67e8acc6
3 ファイル変更、51 行追加、28 行削除
  1. 6 6
      config/config.json
  2. 2 2
      src/main.cpp
  3. 43 20
      web/index.html

+ 6 - 6
config/config.json

@@ -67,6 +67,7 @@
     "model_path": "models/yolov5s_rk3588_int8.rknn",
     "module_type": "RFID",
     "nms_thresh": 0.45,
+    "pose_absent_sec": 30,
     "pose_alarm_classes": [
         "person"
     ],
@@ -91,6 +92,9 @@
     "pose_model_path": "models/yolov8n-pose_rk3588_fp.rknn",
     "pose_nms_thresh": 0.45,
     "pose_recline": true,
+    "pose_sleepy": true,
+    "pose_still": true,
+    "pose_still_sec": 15,
     "relay": {
         "alarm_max_sec": 30,
         "aliases": {
@@ -197,9 +201,5 @@
         "password": "admin",
         "username": "admin"
     },
-    "web_port": 8080,
-    "pose_sleepy": true,
-    "pose_still": true,
-    "pose_still_sec": 15,
-    "pose_absent_sec": 30
-}
+    "web_port": 8080
+}

+ 2 - 2
src/main.cpp

@@ -1763,7 +1763,7 @@ int main(int argc, char* argv[]) {
             }
             if (j.contains("pose_absent_sec")) {
                 int v = j["pose_absent_sec"].get<int>();
-                if (v >= 5 && v <= 3600) {
+                if (v >= 0 && v <= 3600) {
                     pose_absent_sec = v;
                     full["pose_absent_sec"] = v;
                 }
@@ -2269,7 +2269,7 @@ int main(int argc, char* argv[]) {
                     }
 
                     // ===== 离岗检测: 人体消失持续 N 秒 =====
-                    {
+                    if (pose_absent_sec > 0) {
                         if (ch->poses.empty() && !ch->absent_latched) {
                             if (!ch->last_had_person) {
                                 auto anow = chrono::steady_clock::now();

+ 43 - 20
web/index.html

@@ -255,28 +255,49 @@ border-left:3px solid #e94560;padding:8px 10px;margin-bottom:8px;cursor:pointer}
 
     <section id="page-posecfg" class="page pad">
       <div class="sys-wrap">
-        <div class="card">
-          <h3>基础参数</h3>
-          <div style="display:grid;grid-template-columns:1fr 1fr;gap:10px">
-            <div class="form-group" style="margin:0"><label>跌倒阈值</label><input type="number" id="cfgFallThresh" min="0" max="1" step="0.05" value="0.5"></div>
-            <div class="form-group" style="margin:0"><label>连续确认帧数</label><input type="number" id="cfgFallFrames" min="1" max="30" value="3"></div>
-            <div class="form-group" style="margin:0"><label>人体最小面积(px²)</label><input type="number" id="cfgMinArea" min="500" max="500000" value="3000" title="低于此面积的人体视为太远, 不判断动作也不显示"></div>
-            <div class="form-group" style="margin:0"><label>静止报警秒数</label><input type="number" id="cfgStillSec" min="3" max="600" value="15"></div>
-            <div class="form-group" style="margin:0"><label>离岗报警秒数</label><input type="number" id="cfgAbsentSec" min="5" max="3600" value="30"></div>
-          </div>
-          <div class="form-group" style="margin-top:12px">
+        <div class="card" style="grid-column:1/-1">
+          <div style="display:flex;align-items:center;gap:10px;margin-bottom:12px">
             <label style="display:flex;align-items:center;gap:5px;cursor:pointer"><input type="checkbox" id="cfgPoseEnabled"> 启用姿态识别</label>
+            <div class="form-group" style="margin:0;flex:1"><label>人体最小面积(px²)</label><input type="number" id="cfgMinArea" min="500" max="500000" value="3000" title="低于此面积的人体视为太远, 不判断动作也不显示"></div>
           </div>
-          <div class="btn-row" style="margin-top:8px"><button class="btn btn-primary" onclick="savePoseConfig()">保存姿态配置</button></div>
         </div>
-        <div class="card">
-          <h3>可报警姿态</h3>
-          <div class="form-group">
-            <label>勾选启用对应姿态报警</label>
-            <div id="poseActionList" style="display:grid;grid-template-columns:1fr 1fr;gap:8px 16px;font-size:13px"></div>
+        <div class="card" style="grid-column:1/-1">
+          <h3>动作配置</h3>
+          <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:10px">
+            <div style="display:flex;align-items:center;gap:8px;padding:8px;background:#0e1426;border:1px solid #0f3460">
+              <label style="display:flex;align-items:center;gap:4px;cursor:pointer;width:130px;flex-shrink:0"><input type="checkbox" class="pose-act-ck" value="跌倒"> 跌倒/倒地</label>
+              <div style="flex:1;display:flex;gap:6px">
+                <div style="flex:1"><label style="font-size:11px;color:#888">阈值</label><input type="number" id="cfgFallThresh" min="0" max="1" step="0.05" value="0.5" style="width:100%;padding:4px"></div>
+                <div style="flex:1"><label style="font-size:11px;color:#888">连续帧</label><input type="number" id="cfgFallFrames" min="1" max="30" value="3" style="width:100%;padding:4px"></div>
+              </div>
+            </div>
+            <div style="display:flex;align-items:center;gap:8px;padding:8px;background:#0e1426;border:1px solid #0f3460">
+              <label style="display:flex;align-items:center;gap:4px;cursor:pointer;width:130px;flex-shrink:0"><input type="checkbox" class="pose-act-ck" value="举手呼救"> 举手呼救</label>
+            </div>
+            <div style="display:flex;align-items:center;gap:8px;padding:8px;background:#0e1426;border:1px solid #0f3460">
+              <label style="display:flex;align-items:center;gap:4px;cursor:pointer;width:130px;flex-shrink:0"><input type="checkbox" class="pose-act-ck" value="异常蹲坐"> 异常蹲坐</label>
+            </div>
+            <div style="display:flex;align-items:center;gap:8px;padding:8px;background:#0e1426;border:1px solid #0f3460">
+              <label style="display:flex;align-items:center;gap:4px;cursor:pointer;width:130px;flex-shrink:0"><input type="checkbox" class="pose-act-ck" value="半躺"> 半躺</label>
+            </div>
+            <div style="display:flex;align-items:center;gap:8px;padding:8px;background:#0e1426;border:1px solid #0f3460">
+              <label style="display:flex;align-items:center;gap:4px;cursor:pointer;width:130px;flex-shrink:0"><input type="checkbox" class="pose-act-ck" value="手近嘴部"> 手近嘴部</label>
+            </div>
+            <div style="display:flex;align-items:center;gap:8px;padding:8px;background:#0e1426;border:1px solid #0f3460">
+              <label style="display:flex;align-items:center;gap:4px;cursor:pointer;width:130px;flex-shrink:0"><input type="checkbox" class="pose-act-ck" value="疲劳瞌睡"> 疲劳瞌睡</label>
+            </div>
+            <div style="display:flex;align-items:center;gap:8px;padding:8px;background:#0e1426;border:1px solid #0f3460">
+              <label style="display:flex;align-items:center;gap:4px;cursor:pointer;width:130px;flex-shrink:0"><input type="checkbox" class="pose-act-ck" value="长时间静止"> 长时间静止</label>
+              <div style="flex:1"><label style="font-size:11px;color:#888">秒数</label><input type="number" id="cfgStillSec" min="3" max="600" value="15" style="width:100%;padding:4px"></div>
+            </div>
+            <div style="display:flex;align-items:center;gap:8px;padding:8px;background:#0e1426;border:1px solid #0f3460">
+              <label style="display:flex;align-items:center;gap:4px;cursor:pointer;width:130px;flex-shrink:0"><input type="checkbox" class="pose-act-ck" value="疑似离岗"> 疑似离岗</label>
+              <div style="flex:1"><label style="font-size:11px;color:#888">秒数</label><input type="number" id="cfgAbsentSec" min="5" max="3600" value="30" style="width:100%;padding:4px"></div>
+            </div>
           </div>
+          <div class="btn-row" style="margin-top:10px"><button class="btn btn-primary" onclick="savePoseConfig()">保存姿态配置</button></div>
         </div>
-        <div class="card">
+        <div class="card" style="grid-column:1/-1">
           <h3>屏蔽区域</h3>
           <div class="form-group">
             <label>每路排除误识别区域, 格式: x1,y1,x2,y2 (多个用;分隔, 不同路用行分隔)</label>
@@ -1124,7 +1145,8 @@ const POSE_ACTIONS = [
   ['半躺', '半躺'],
   ['手近嘴部', '手近嘴部'],
   ['疲劳瞌睡', '疲劳瞌睡'],
-  ['长时间静止', '长时间静止']
+  ['长时间静止', '长时间静止'],
+  ['疑似离岗', '疑似离岗']
 ];
 function renderPoseActions() {
   const el = document.getElementById('poseActionList');
@@ -1146,7 +1168,6 @@ async function loadPoseConfig() {
     if (document.getElementById('cfgFallFrames')) document.getElementById('cfgFallFrames').value = pd.fall_frames;
     if (document.getElementById('cfgMinArea')) document.getElementById('cfgMinArea').value = pd.pose_min_area || 3000;
     // 可报警姿态: 由后端开关决定勾选
-    renderPoseActions();
     const enabled = [];
     if (pd.pose_hand_raise !== false) enabled.push('举手呼救');
     if (pd.pose_crouch !== false) enabled.push('异常蹲坐');
@@ -1154,6 +1175,8 @@ async function loadPoseConfig() {
     if (pd.pose_hand_to_mouth !== false) enabled.push('手近嘴部');
     if (pd.pose_sleepy !== false) enabled.push('疲劳瞌睡');
     if (pd.pose_still !== false) enabled.push('长时间静止');
+    // 疑似离岗: 由 absent 秒数>0 控制(无独立开关, 秒数>0即启用)
+    if ((pd.pose_absent_sec || 30) > 0) enabled.push('疑似离岗');
     // 跌倒固定启用
     enabled.push('跌倒');
     document.querySelectorAll('.pose-act-ck').forEach(c =>
@@ -1210,7 +1233,7 @@ async function savePoseConfig() {
     pose_sleepy: !!checks['疲劳瞌睡'],
     pose_still: !!checks['长时间静止'],
     pose_still_sec: parseInt(document.getElementById('cfgStillSec').value) || 15,
-    pose_absent_sec: parseInt(document.getElementById('cfgAbsentSec').value) || 30,
+    pose_absent_sec: !!checks['疑似离岗'] ? (parseInt(document.getElementById('cfgAbsentSec').value) || 30) : 0,
     pose_min_area: parseInt(document.getElementById('cfgMinArea').value) || 3000,
     pose_exclude_zones: ez
   };