diff --git a/public/app.js b/public/app.js index 683aa0a..8140253 100644 --- a/public/app.js +++ b/public/app.js @@ -81,6 +81,7 @@ document.addEventListener('DOMContentLoaded', () => { alert('모델 목록을 불러오는 데 실패했습니다.'); }); } + // ========== AI 모델 목록 로드 함수 끝 ========== @@ -93,22 +94,23 @@ document.addEventListener('DOMContentLoaded', () => { headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ filename: filename }) // { "filename": "CUUVA_..." } - }) - .then(response => response.json()) - .then(data => { - if (data.status === 'success') { - alert(`파일이 성공적으로 삭제되었습니다: ${filename}`); - loadModelList(); // 삭제 성공 시 목록 새로고침 - } else { - alert(`삭제 실패: ${data.message}`); - } + body: JSON.stringify({filename: filename}) // { "filename": "CUUVA_..." } }) - .catch(error => { - console.error('Delete error:', error); - alert('삭제 중 오류가 발생했습니다.'); - }); + .then(response => response.json()) + .then(data => { + if (data.status === 'success') { + alert(`파일이 성공적으로 삭제되었습니다: ${filename}`); + loadModelList(); // 삭제 성공 시 목록 새로고침 + } else { + alert(`삭제 실패: ${data.message}`); + } + }) + .catch(error => { + console.error('Delete error:', error); + alert('삭제 중 오류가 발생했습니다.'); + }); } + // ========== 모델 삭제 요청 함수 끝 ========== @@ -178,29 +180,29 @@ document.addEventListener('DOMContentLoaded', () => { method: 'POST', body: formData }) - .then(response => response.json()) - .then(data => { - if (data.status === 'success') { - alert(`업로드 성공!\n파일: ${file.name}`); - globalFileInput.value = ''; // 파일 선택 초기화 - fileNameDisplay.textContent = '선택된 파일 없음'; - - // 업로드 성공 시 모델 목록 새로고침 - loadModelList(); - - } else { - alert(`업로드 실패: ${data.message}`); - } - }) - .catch(error => { - console.error('Upload error:', error); - alert('업로드 중 오류가 발생했습니다.'); - }) - .finally(() => { - // 버튼 다시 활성화 - globalUploadButton.disabled = false; - globalUploadButton.textContent = '업로드'; - }); + .then(response => response.json()) + .then(data => { + if (data.status === 'success') { + alert(`업로드 성공!\n파일: ${file.name}`); + globalFileInput.value = ''; // 파일 선택 초기화 + fileNameDisplay.textContent = '선택된 파일 없음'; + + // 업로드 성공 시 모델 목록 새로고침 + loadModelList(); + + } else { + alert(`업로드 실패: ${data.message}`); + } + }) + .catch(error => { + console.error('Upload error:', error); + alert('업로드 중 오류가 발생했습니다.'); + }) + .finally(() => { + // 버튼 다시 활성화 + globalUploadButton.disabled = false; + globalUploadButton.textContent = '업로드'; + }); }); } @@ -254,14 +256,19 @@ document.addEventListener('DOMContentLoaded', () => { if (logoutButton) { // 로그아웃 버튼이 있는지 확인 logoutButton.addEventListener('click', () => { console.log('Logout clicked'); - // 로그인 페이지(루트 '/')로 이동 - window.location.href = '/'; + + // [수정됨] 사용자에게 확인을 받습니다. + if (confirm('정말로 로그아웃하시겠습니까?')) { + // 확인을 누르면 로그인 페이지(루트 '/')로 이동 + window.location.href = '/'; + } + // 취소를 누르면 아무 일도 일어나지 않습니다. }); } // ========== 로그아웃 버튼 처리 끝 ========== - // ========== video-test.html 스크립트 추가 시작 ========== + // ========== dashboard.html 스크립트 추가 시작 ========== const uri = "ws://10.10.11.246:8765"; // 필요하면 여기만 수정 const imgEl = document.getElementById("frame"); const statusEl = document.getElementById("status"); @@ -270,6 +277,18 @@ document.addEventListener('DOMContentLoaded', () => { const bboxContainerEl = document.getElementById("bbox-container"); const modelContainerEl = document.getElementById("current-model-container"); + // [추가] 클래스별 색상 팔레트 (원하는 색상으로 수정 가능) + const CLASS_COLORS = [ + '#FF3838', // 0: Red + '#38BFFF', // 1: Blue + '#38FF4E', // 2: Green + '#FFF238', // 3: Yellow + '#FF9D38', // 4: Orange + '#C538FF', // 5: Purple + '#FF38C5', // 6: Pink + '#FFFFFF' // 7: White + ]; + let lastFrameMeta = null; if (imgEl && statusEl && frameInfoEl && detListEl && bboxContainerEl && modelContainerEl) { @@ -285,21 +304,21 @@ document.addEventListener('DOMContentLoaded', () => { headers: { 'Content-Type': 'application/json', }, - body: JSON.stringify({ model: selectedModel }), + body: JSON.stringify({model: selectedModel}), }) - .then(response => response.json()) - .then(data => { - console.log('Server response:', data); - if (data.status === 'success') { - logStatus(`모델 변경 완료: ${selectedModel}`); - } else { - logStatus(`모델 변경 실패: ${data.message}`, true); - } - }) - .catch(error => { - console.error('Error setting model:', error); - logStatus('모델 변경 중 오류 발생', true); - }); + .then(response => response.json()) + .then(data => { + console.log('Server response:', data); + if (data.status === 'success') { + logStatus(`모델 변경 완료: ${selectedModel}`); + } else { + logStatus(`모델 변경 실패: ${data.message}`, true); + } + }) + .catch(error => { + console.error('Error setting model:', error); + logStatus('모델 변경 중 오류 발생', true); + }); } }); @@ -326,7 +345,6 @@ document.addEventListener('DOMContentLoaded', () => { ` | FRAME ch=${meta.ch} ts=${meta.ts_us} w=${meta.w} h=${meta.h}`; } - // Detections 표시 함수 // Detections 표시 함수 (수정됨) function showDetections(meta) { const items = meta.items || []; @@ -337,13 +355,13 @@ document.addEventListener('DOMContentLoaded', () => { if (!imgEl || !lastFrameMeta) { // [수정됨] x1,y1,x2,y2 형식에 맞게 텍스트 로그 수정 items.forEach((it, i) => { - // x1, y1, x2, y2 -> x, y, w, h - const x = it.x1; - const y = it.y1; - const w = it.x2 - it.x1; - const h = it.y2 - it.y1; + // x1, y1, x2, y2 -> x, y, w, h + const x = it.x1; + const y = it.y1; + const w = it.x2 - it.x1; + const h = it.y2 - it.y1; - lines.push( + lines.push( `#${i} cls=${it.cls} tid=${it.tid} tag=${it.tag}` // prob, resv 대신 tid, tag 사용 + ` x=${x.toFixed(3)} y=${y.toFixed(3)}` + ` w=${w.toFixed(3)} h=${h.toFixed(3)}` @@ -362,13 +380,13 @@ document.addEventListener('DOMContentLoaded', () => { if (frameWidth === 0 || frameHeight === 0 || imgWidth === 0 || imgHeight === 0) { // [수정됨] x1,y1,x2,y2 형식에 맞게 텍스트 로그 수정 items.forEach((it, i) => { - // x1, y1, x2, y2 -> x, y, w, h - const x = it.x1; - const y = it.y1; - const w = it.x2 - it.x1; - const h = it.y2 - it.y1; + // x1, y1, x2, y2 -> x, y, w, h + const x = it.x1; + const y = it.y1; + const w = it.x2 - it.x1; + const h = it.y2 - it.y1; - lines.push( + lines.push( `#${i} cls=${it.cls} tid=${it.tid} tag=${it.tag}` // prob, resv 대신 tid, tag 사용 + ` x=${x.toFixed(3)} y=${y.toFixed(3)}` + ` w=${w.toFixed(3)} h=${h.toFixed(3)}` @@ -394,8 +412,11 @@ document.addEventListener('DOMContentLoaded', () => { const w = it.x2 - it.x1; const h = it.y2 - it.y1; + // [추가] 현재 항목의 클래스(cls) 가져오기 + const cls = it.cls; + lines.push( - `#${i} cls=${it.cls} tid=${it.tid} tag=${it.tag}` // prob, resv 대신 tid, tag 사용 + `#${i} cls=${cls} tid=${it.tid} tag=${it.tag}` // prob, resv 대신 tid, tag 사용 + ` x=${x.toFixed(3)} y=${y.toFixed(3)}` + ` w=${w.toFixed(3)} h=${h.toFixed(3)}` ); @@ -406,12 +427,23 @@ document.addEventListener('DOMContentLoaded', () => { const boxWidth = w * ratio; const boxHeight = h * ratio; + // [추가] 클래스(cls) 값에 따라 색상 결정 + // cls를 정수로 변환 (혹시 문자열일 경우 대비) + const classIndex = parseInt(cls, 10) || 0; + // 모듈러(%) 연산을 사용해 색상 배열을 순환 + const color = CLASS_COLORS[classIndex % CLASS_COLORS.length]; + const bbox = document.createElement('div'); bbox.className = 'bbox'; bbox.style.left = `${boxLeft}px`; bbox.style.top = `${boxTop}px`; bbox.style.width = `${boxWidth}px`; bbox.style.height = `${boxHeight}px`; + + // [추가] CSS의 'border' 대신 'borderColor'를 동적으로 설정 + // 이렇게 하면 style.css의 'border-width', 'border-style'은 유지됩니다. + bbox.style.borderColor = color; + bboxContainerEl.appendChild(bbox); }); detListEl.textContent = lines.join("\n"); @@ -421,7 +453,9 @@ document.addEventListener('DOMContentLoaded', () => { function connect() { const ws = new WebSocket(uri); ws.binaryType = "arraybuffer"; - ws.onopen = () => { logStatus(`연결됨: ${uri}`); }; + ws.onopen = () => { + logStatus(`연결됨: ${uri}`); + }; ws.onclose = (ev) => { logStatus(`연결 종료 (code=${ev.code}) 재접속 대기중...`, true); setTimeout(connect, 2000); @@ -448,7 +482,7 @@ document.addEventListener('DOMContentLoaded', () => { return; } if (data instanceof ArrayBuffer && lastFrameMeta) { - const blob = new Blob([data], { type: "image/jpeg" }); + const blob = new Blob([data], {type: "image/jpeg"}); const url = URL.createObjectURL(blob); imgEl.onload = () => { URL.revokeObjectURL(url); diff --git a/public/cuuva_logo.png b/public/cuuva_logo.png new file mode 100644 index 0000000..edf63ed Binary files /dev/null and b/public/cuuva_logo.png differ diff --git a/public/dashboard.html b/public/dashboard.html index e9a139a..e9c0778 100644 --- a/public/dashboard.html +++ b/public/dashboard.html @@ -11,7 +11,7 @@