scrypted-detection-trainer 0.1.11 β†’ 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/out/plugin.zip CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scrypted-detection-trainer",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "Collect and label detections to fine-tune the Scrypted NVR object detection model.",
5
5
  "keywords": [
6
6
  "scrypted-plugin"
package/src/main.ts CHANGED
@@ -854,75 +854,6 @@ async function initBrowse() {
854
854
  }
855
855
  }
856
856
 
857
- async function loadBrowse() {
858
- const cameraId = document.getElementById('browse-camera').value;
859
- const hours = document.getElementById('browse-hours').value;
860
- const status = document.getElementById('browse-status');
861
- const list = document.getElementById('browse-list');
862
-
863
- if (!cameraId) { status.textContent = 'Select a camera first'; return; }
864
-
865
- status.textContent = 'Loading…';
866
- list.innerHTML = '';
867
-
868
- try {
869
- const res = await fetch(BASE + '/api/browse?cameraId=' + cameraId + '&hours=' + hours);
870
- const events = await res.json();
871
-
872
- if (events.error) { status.textContent = 'Error: ' + events.error; return; }
873
- if (!events.length) { status.textContent = 'No detection events found.'; list.innerHTML = '<div class="empty"><div class="icon">πŸ”</div><div>No ObjectDetector events in this time range.</div></div>'; return; }
874
-
875
- status.textContent = events.length + ' events found';
876
-
877
- list.innerHTML = events.map((ev, i) => {
878
- const date = new Date(ev.timestamp).toLocaleString();
879
- const dets = ev.detections || [];
880
- const primary = dets[0] || {};
881
- const score = Math.round((primary.score || 0) * 100);
882
- const allClasses = dets.map(d => d.className + ' ' + Math.round((d.score||0)*100) + '%').join(', ');
883
- return \`
884
- <div class="detection" id="bev-\${i}" style="opacity:1;transition:opacity .3s">
885
- <div class="detection-imgs">
886
- <div class="img-panel">
887
- <div class="img-label">Full frame</div>
888
- <canvas id="bcanvas-\${i}" class="det-canvas" width="240" height="160"></canvas>
889
- </div>
890
- <div class="img-panel" id="bcrop-panel-\${i}">
891
- <div class="img-label">Crop</div>
892
- <canvas id="bcanvas-crop-\${i}" class="det-canvas" width="160" height="160"></canvas>
893
- </div>
894
- </div>
895
- <div class="detection-info">
896
- <div class="detection-meta">
897
- <div><strong>\${ev.cameraName}</strong></div>
898
- <div>\${date}</div>
899
- <div class="det-class-badge">\${allClasses}</div>
900
- </div>
901
- <div style="font-size:12px;color:#888;">Add to dataset as:</div>
902
- <div class="label-buttons" id="blabels-\${i}">
903
- <button class="label-btn person" onclick="addEvent(\${i})('person')">πŸ‘€ Person</button>
904
- <button class="label-btn animal" onclick="addEvent(\${i})('animal')">🐾 Animal</button>
905
- <button class="label-btn face" onclick="addEvent(\${i})('face')">πŸ˜€ Face</button>
906
- <button class="label-btn vehicle" onclick="addEvent(\${i})('vehicle')">πŸš— Vehicle</button>
907
- <button class="label-btn" onclick="addEvent(\${i})('plate')">πŸ”’ Plate</button>
908
- <button class="label-btn" onclick="addEvent(\${i})('package')">πŸ“¦ Package</button>
909
- <button class="label-btn discard" onclick="addEvent(\${i})('discard')">πŸ—‘ Skip</button>
910
- </div>
911
- </div>
912
- </div>\`;
913
- }).join('');
914
-
915
- // Load images for each event
916
- for (let i = 0; i < events.length; i++) {
917
- const ev = events[i];
918
- loadBrowseImage(i, ev);
919
- }
920
-
921
- } catch(e) {
922
- status.textContent = 'Error: ' + e.message;
923
- }
924
- }
925
-
926
857
  // Store browse events for addEvent closure
927
858
  let browseEvents = [];
928
859
 
@@ -1026,7 +957,7 @@ function loadBrowseImage(i, ev) {
1026
957
  fullCanvas.onclick = () => openLightboxImg(img, ev.cameraName, ev.timestamp);
1027
958
  }
1028
959
  // Hide crop panel β€” no bounding box available
1029
- const cropPanel = document.getElementById('bcanvas-crop-' + i)?.closest('.img-panel') as HTMLElement;
960
+ const cropPanel = document.getElementById('bcanvas-crop-' + i)?.closest('.img-panel');
1030
961
  if (cropPanel) cropPanel.style.display = 'none';
1031
962
  URL.revokeObjectURL(url);
1032
963
  };