diff --git a/public/app.js b/public/app.js index 88e1075..76f90cc 100644 --- a/public/app.js +++ b/public/app.js @@ -151,12 +151,24 @@ document.addEventListener('DOMContentLoaded', () => { // [신규] Mission UI 로직 // ================================================= const MODEL_DEFINITIONS = { - 'OBJDET': {name: "객체 탐지", classes: ["person", "car", "motor", "bus", "truck"], defaults: ["person", "car", "motor", "bus", "truck"]}, + 'OBJDET': { + name: "객체 탐지", + classes: ["person", "car", "motor", "bus", "truck"], + defaults: ["person", "car", "motor", "bus", "truck"] + }, 'FIRE': {name: "화재 감지", classes: ["flame", "smoke"], defaults: ["flame", "smoke"]}, 'CROWD': {name: "군중 위험", classes: ["person", "car", "motor", "bus", "truck"], defaults: ["person"]}, - 'FACEATTR': {name: "얼굴 인식", classes: ["face", "person", "car", "motor", "bus", "truck"], defaults: ["face", "person"]}, + 'FACEATTR': { + name: "얼굴 인식", + classes: ["face", "person", "car", "motor", "bus", "truck"], + defaults: ["face", "person"] + }, 'ABNORM': {name: "이상 행동", classes: ["fallen", "person", "car", "motor", "bus", "truck"], defaults: ["fallen"]}, - 'LPR': {name: "차량 인식", classes: ["plate", "person", "car", "motor", "bus", "truck"], defaults: ["plate", "car", "motor", "bus", "truck"]}, + 'LPR': { + name: "차량 인식", + classes: ["plate", "person", "car", "motor", "bus", "truck"], + defaults: ["plate", "car", "motor", "bus", "truck"] + }, 'VIPTRACK': {name: "관심 인물", classes: ["person"], defaults: ["person"]} }; @@ -201,7 +213,7 @@ document.addEventListener('DOMContentLoaded', () => { changeModel(modelCode); updateFilterBar(modelCode); // 모델 변경 시 Summary 패널 초기화 - if (modelCode === 'FACEATTR' || modelCode === 'ABNORM') { + if (modelCode === 'FACEATTR' || modelCode === 'ABNORM' || modelCode === 'LPR') { summaryListEl.className = 'summary-content card-list'; summaryListEl.innerHTML = '
Waiting for card data...
'; } else { @@ -305,7 +317,7 @@ document.addEventListener('DOMContentLoaded', () => { // 2. 비디오 & 웹소켓 & Summary 패널 // ================================================= const LABEL_MAP = { - 1: {tagName: "객체 탐지", classes: {0: "person", 1: "car", 2: "van", 3: "truck", 4: "bus", 5: "motor"}}, + 1: {tagName: "객체 탐지", classes: {0: "person", 1: "-", 2: "car", 3: "motor", 4: "bus", 5: "truck"}}, 2: {tagName: "화재 인식", classes: {0: "flame", 1: "smoke"}}, 3: {tagName: "얼굴 인식", classes: {0: "face"}}, 4: {tagName: "차량번호", classes: {0: "plate"}}, @@ -356,10 +368,14 @@ document.addEventListener('DOMContentLoaded', () => { if (meta.type === "frame") { lastFrameMeta = meta; showDetections(meta); - } else if (meta.type === "card" && (currentModelCode === 'FACEATTR' || currentModelCode === 'ABNORM')) { + } else if (meta.type === "card" && (currentModelCode === 'FACEATTR' || currentModelCode === 'ABNORM' || currentModelCode === 'LPR')) { lastFrameMeta = meta; // 카드 데이터도 BBox를 포함할 수 있으므로 저장 showDetections(meta); // BBox 그리기 updateCardPanel(meta.items); // 카드 패널 업데이트 + + if (meta.type === "card" && currentModelCode === 'LPR') { + console.log("-----" + JSON.stringify(meta)); + } } } catch (e) { console.error(e); @@ -421,7 +437,11 @@ document.addEventListener('DOMContentLoaded', () => { const y1 = it.y1 || 0; const x2 = it.x2 || 0; const y2 = it.y2 || 0; - const boxColor = getBoxColor(displayClassName); + + let boxColor = getBoxColor(displayClassName); + if (currentModelCode === 'ABNORM') { + boxColor = '#FF0000'; + } const {r, dx, dy} = viewConfig; const screenX = dx + (x1 * r); @@ -454,7 +474,7 @@ document.addEventListener('DOMContentLoaded', () => { bboxContainerEl.appendChild(boxDiv); }); - if (currentModelCode !== 'FACEATTR' && currentModelCode !== 'ABNORM') { + if (currentModelCode !== 'FACEATTR' && currentModelCode !== 'ABNORM' && currentModelCode !== 'LPR') { updateSummaryPanel(currentCounts); } } @@ -511,6 +531,17 @@ document.addEventListener('DOMContentLoaded', () => {
쓰러짐 발생
`; + } else if (currentModelCode === 'LPR') { + const carImgSrc = item.car ? `data:image/jpeg;base64,${item.car}` : ''; + const lpImgSrc = item.lp ? `data:image/jpeg;base64,${item.lp}` : ''; + + card.innerHTML = ` + +
+ +
${item.ocr || ''}
+
+ `; } summaryListEl.appendChild(card); }); diff --git a/public/style.css b/public/style.css index ec164d3..95a4c0d 100644 --- a/public/style.css +++ b/public/style.css @@ -376,6 +376,38 @@ main { white-space: pre-wrap; /* 줄바꿈 적용 */ } +.card-car-img { + width: 120px; + height: auto; + max-height: 150px; + object-fit: contain; + border-radius: 4px; + background-color: #2a2a2a; +} + +.card-lp-img { + height: 40px; + width: auto; + max-width: 100%; + object-fit: contain; + background-color: #2a2a2a; + border: 1px solid #555; +} + +.card-ocr-info { + background-color: #2a2a2a; + padding: 8px; + border-radius: 4px; + font-size: 1.5rem; /* OCR 텍스트 크게 */ + font-weight: bold; + color: #ffd700; /* 강조색 */ + text-align: center; + flex-grow: 1; + display: flex; + align-items: center; + justify-content: center; +} + /* ========================================================== */ /* 7. 설정 탭 - AI 모델 & 관심 인물 관리 (Settings) */