Forráskód Böngészése

系统配置增加目标识别和姿态识别开关

dev 1 hete
szülő
commit
9c9facf08e
3 módosított fájl, 50 hozzáadás és 25 törlés
  1. 6 4
      config/config.json
  2. 32 12
      src/main.cpp
  3. 12 9
      web/config.html

+ 6 - 4
config/config.json

@@ -51,7 +51,7 @@
     ],
     "fall_thresh": 0.5,
     "fence_file": "config/fences.json",
-    "grid_output": true,
+    "grid_output": false,
     "hdmi_fullscreen": true,
     "hdmi_grid_cols": 0,
     "idle_timeout": 5,
@@ -173,10 +173,12 @@
     ],
     "rtsp_timeout": 10,
     "skip_frames": 3,
-    "steel_output": true,
+    "steel_output": false,
     "web_auth": {
         "password": "admin",
         "username": "admin"
     },
-    "web_port": 8080
-}
+    "web_port": 8080,
+    "enable_bucket": false,
+    "target_enabled": true
+}

+ 32 - 12
src/main.cpp

@@ -300,6 +300,8 @@ int main(int argc, char* argv[]) {
 
     // ========== 本机画面输出(HDMI显示器) ==========
     string app_name = cfg.value("app_name", "钢包工位视频监测系统");
+    // 工位功能总开关(临时关闭可禁用钢包位/工位切换/空闲检测)
+    bool enable_bucket = cfg.value("enable_bucket", true);
     // 两个独立显示器输出: 网格(普通通道) + 钢包位(工位左右摄像头)
     bool grid_output = cfg.value("grid_output", true);
     bool steel_output = cfg.value("steel_output", true);
@@ -307,6 +309,7 @@ int main(int argc, char* argv[]) {
     bool hdmi_fullscreen = cfg.value("hdmi_fullscreen", true);
     cout << "[Display] 网格输出: " << (grid_output ? "启用" : "禁用")
          << " 钢包位输出: " << (steel_output ? "启用" : "禁用")
+         << " 工位功能: " << (enable_bucket ? "启用" : "禁用")
          << " 网格列=" << hdmi_grid_cols
          << " 全屏=" << (hdmi_fullscreen ? "是" : "否") << endl;
 
@@ -318,6 +321,7 @@ int main(int argc, char* argv[]) {
     float pose_nms_thresh = cfg.value("pose_nms_thresh", 0.45f);
     float fall_thresh = cfg.value("fall_thresh", 0.5f);
     int fall_frames = cfg.value("fall_frames", 3);
+    bool target_enabled = cfg.value("target_enabled", true);
     bool pose_enabled = cfg.value("pose_enabled", false);
     vector<string> pose_alarm_classes;
     if (cfg.contains("pose_alarm_classes") && cfg["pose_alarm_classes"].is_array())
@@ -331,6 +335,7 @@ int main(int argc, char* argv[]) {
         for (auto& c : cfg["fall_relays"])
             if (c.is_string()) fall_relays.push_back(c.get<string>());
     if (fall_relays.empty()) fall_relays = {"y01"};
+    cout << "[Target] 目标识别: " << (target_enabled ? "启用" : "禁用") << endl;
     cout << "[Pose] 姿态识别: " << (pose_enabled ? "启用" : "禁用")
          << " 模型=" << pose_model_path
          << " 跌倒阈值=" << fall_thresh
@@ -410,7 +415,7 @@ int main(int argc, char* argv[]) {
     cout << "========================================" << endl;
 
     YoloDetector detector;
-    if (!detector.load(model_path, input_size, conf_thresh, nms_thresh)) {
+    if (target_enabled && !detector.load(model_path, input_size, conf_thresh, nms_thresh)) {
         cerr << "RKNN模型加载失败!" << endl;
         return 1;
     }
@@ -466,7 +471,7 @@ int main(int argc, char* argv[]) {
         rfidClient->setConfig(rfidCfg);
         rfidClient->setTagCallback([&](const string& tag) {
             idleDetector.feed(tag);
-            if (!tag.empty()) {
+            if (!tag.empty() && enable_bucket) {
                 bucketManager.checkAutoSwitch(tag);
             }
         });
@@ -488,7 +493,7 @@ int main(int argc, char* argv[]) {
         modbusClient->setConfig(modbusCfg);
         modbusClient->setDataCallback([&](const vector<bool>& coils) {
             idleDetector.feed(coils);
-            bucketManager.checkAutoSwitch(coils);
+            if (enable_bucket) bucketManager.checkAutoSwitch(coils);
         });
         modbusClient->setStateCallback([&](bool online) {
             cout << "[Modbus] 状态: " << (online ? "在线" : "离线") << endl;
@@ -573,19 +578,23 @@ int main(int argc, char* argv[]) {
          << kMaxChannels << " 路" << endl;
 
     // 钢包位专用通道(占位创建, 工位激活时替换为工位左右摄像头)
-    {
+    if (enable_bucket) {
         auto chL = makeChannel(kBucketLeftId, "钢包位左", "");
         auto chR = makeChannel(kBucketRightId, "钢包位右", "");
         lock_guard<mutex> lk(bucket_channels_mtx);
         bucket_channels.push_back(chL);
         bucket_channels.push_back(chR);
+        cout << "[Main] 钢包位专用通道: 左CH" << kBucketLeftId
+             << " 右CH" << kBucketRightId << endl;
     }
-    cout << "[Main] 钢包位专用通道: 左CH" << kBucketLeftId
-         << " 右CH" << kBucketRightId << endl;
 
     // ========== 工位切换回调 ==========
     // 钢包位专用通道跟随工位切换(左右摄像头), 普通rtsp通道不受影响
     bucketManager.setActivateCallback([&](const BucketInfo* old, const BucketInfo* cur) {
+        if (!enable_bucket) {
+            idleDetector.reset();
+            return;
+        }
         cerr << "[Bucket] 回调触发: old=" << (old ? old->description : "null")
              << " cur=" << (cur ? cur->description : "null") << endl;
         // 停止旧工位钢包位摄像头
@@ -632,7 +641,9 @@ int main(int argc, char* argv[]) {
         s["conf_thresh"] = conf_thresh;
         s["alarm_retention_days"] = alarm_retention_days;
         s["alarm_classes"] = alarm_classes;
+        s["target_enabled"] = target_enabled;
         s["pose_enabled"] = pose_ok;
+        s["pose_cfg_enabled"] = pose_enabled;
         s["pose_model"] = pose_model_path;
         s["fall_thresh"] = fall_thresh;
         s["fall_frames"] = fall_frames;
@@ -1281,6 +1292,13 @@ int main(int argc, char* argv[]) {
             }
             if (j.contains("conf_thresh"))
                 full["conf_thresh"] = j["conf_thresh"];
+            if (j.contains("target_enabled")) {
+                bool en = j["target_enabled"].get<bool>();
+                full["target_enabled"] = en;
+                target_enabled = en;
+                cout << "[Target] 目标识别: " << (en ? "启用" : "禁用")
+                     << " (重启后生效)" << endl;
+            }
             if (j.contains("pose_enabled")) {
                 bool en = j["pose_enabled"].get<bool>();
                 full["pose_enabled"] = en;
@@ -1533,12 +1551,12 @@ int main(int argc, char* argv[]) {
     int grid_fixed = (int)channels.size();
     displayGrid.start(grid_output, hdmi_grid_cols, app_name + " - 通道网格",
                       hdmi_fullscreen, 100, grid_fixed);
-    displayBucket.start(steel_output, 2, app_name + " - 钢包位",
+    displayBucket.start(steel_output && enable_bucket, 2, app_name + " - 钢包位",
                         hdmi_fullscreen, 100, 2);
     cout << "[Main] Ctrl+C 退出" << endl;
 
     // 自动激活第一个工位(如果有配置)
-    {
+    if (enable_bucket) {
         auto bs = bucketManager.getBuckets();
         if (!bs.empty()) {
             cout << "[Main] 自动激活第一个工位: " << bs[0].description << endl;
@@ -1597,7 +1615,7 @@ int main(int argc, char* argv[]) {
 
         // RFID/Modbus空闲检测
         if (rfidClient) rfidClient->checkIdle();
-        if (idleDetector.isIdle() && bucketManager.getActiveBucketId() >= 0) {
+        if (enable_bucket && idleDetector.isIdle() && bucketManager.getActiveBucketId() >= 0) {
             cout << "[Bucket] 空闲超时,取消激活" << endl;
             bucketManager.activateBucket(-1);
         }
@@ -1711,9 +1729,11 @@ int main(int argc, char* argv[]) {
                 if (ch->frame_count <= 4)
                     cout << "[CH" << ch->id << "] infer frame=" << ch->frame_count
                          << " rgb=" << ch->rgb_buf.size() << endl;
-                auto dets = detector.detect(ch->rgb_buf.data(),
-                                             nv12.width, nv12.height,
-                                             scale, pad_x, pad_y);
+                vector<Detection> dets;
+                if (target_enabled)
+                    dets = detector.detect(ch->rgb_buf.data(),
+                                           nv12.width, nv12.height,
+                                           scale, pad_x, pad_y);
 
                 vector<cv::Point2f> centers;
                 vector<int> cids;

+ 12 - 9
web/config.html

@@ -134,11 +134,10 @@ body.rail .logo .t,body.rail .nav-label,body.rail .side-foot .nav-label{display:
       <div class="form-row">
         <div class="form-group"><label>RTSP超时(秒)</label><input type="number" id="rtspTimeout" min="1" max="60" value="10"></div>
         <div class="form-group">
-          <label>姿态识别(跌倒检测)</label>
-          <select id="poseEnabled">
-            <option value="true">启用</option>
-            <option value="false">禁用</option>
-          </select>
+          <label><input type="checkbox" id="targetEnabled"> 是否启用目标识别</label>
+        </div>
+        <div class="form-group">
+          <label><input type="checkbox" id="poseEnabled"> 是否启用姿态识别</label>
         </div>
       </div>
       <div class="form-row">
@@ -184,22 +183,25 @@ async function loadConfig() {
     ]);
     const modData = await modRes.json();
     const bucketData = await bucketRes.json();
-    let poseEnabled = true;
+    let targetEnabled = true, poseEnabled = true;
     try {
       const poseData = await poseRes.json();
+      if (poseData.target_enabled !== undefined) targetEnabled = poseData.target_enabled;
       if (poseData.pose_cfg_enabled !== undefined) poseEnabled = poseData.pose_cfg_enabled;
       else if (poseData.pose_enabled !== undefined) poseEnabled = poseData.pose_enabled;
     } catch (e) {}
     let gridOutput = true, steelOutput = true;
     try {
       const statusData = await statusRes.json();
+      if (statusData.target_enabled !== undefined) targetEnabled = statusData.target_enabled;
       if (statusData.grid_output !== undefined) gridOutput = statusData.grid_output;
       if (statusData.steel_output !== undefined) steelOutput = statusData.steel_output;
     } catch (e) {}
 
     document.getElementById('moduleType').value = modData.module_type || 'RFID';
     document.getElementById('idleTimeout').value = modData.idle_timeout || 5;
-    document.getElementById('poseEnabled').value = poseEnabled ? 'true' : 'false';
+    document.getElementById('targetEnabled').checked = targetEnabled;
+    document.getElementById('poseEnabled').checked = poseEnabled;
     document.getElementById('gridOutput').value = gridOutput ? 'true' : 'false';
     document.getElementById('steelOutput').value = steelOutput ? 'true' : 'false';
     onModuleTypeChange();
@@ -353,14 +355,15 @@ async function saveModuleConfig() {
 }
 
 async function saveSystemConfig() {
-  const poseEnabled = document.getElementById('poseEnabled').value === 'true';
+  const targetEnabled = document.getElementById('targetEnabled').checked;
+  const poseEnabled = document.getElementById('poseEnabled').checked;
   const gridOutput = document.getElementById('gridOutput').value === 'true';
   const steelOutput = document.getElementById('steelOutput').value === 'true';
   try {
     await fetch('/api/config', {
       method: 'POST',
       headers: {'Content-Type': 'application/json'},
-      body: JSON.stringify({ pose_enabled: poseEnabled, grid_output: gridOutput, steel_output: steelOutput })
+      body: JSON.stringify({ target_enabled: targetEnabled, pose_enabled: poseEnabled, grid_output: gridOutput, steel_output: steelOutput })
     });
     alert('系统配置已保存' + (poseEnabled ? '' : '(姿态识别需重启后生效)'));
   } catch (e) { alert('保存失败: ' + e.message); }