|
|
|
|
@ -270,7 +270,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
|
|
|
|
|
|
// ========== dashboard.html 스크립트 추가 시작 ==========
|
|
|
|
|
const uri = "ws://10.10.11.246:8765"; // 필요하면 여기만 수정
|
|
|
|
|
const imgEl = document.getElementById("frame");
|
|
|
|
|
|
|
|
|
|
// [수정] imgEl -> canvasEl로 변경
|
|
|
|
|
const canvasEl = document.getElementById("frame");
|
|
|
|
|
|
|
|
|
|
const statusEl = document.getElementById("status");
|
|
|
|
|
const frameInfoEl = document.getElementById("frame-info");
|
|
|
|
|
const detListEl = document.getElementById("det-list");
|
|
|
|
|
@ -281,6 +284,12 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
|
const modelDisplayEl = document.getElementById("current-model-display");
|
|
|
|
|
const fpsDisplayEl = document.getElementById("fps-display");
|
|
|
|
|
|
|
|
|
|
// [추가] 캔버스 2D 컨텍스트
|
|
|
|
|
let ctx = null;
|
|
|
|
|
if (canvasEl) {
|
|
|
|
|
ctx = canvasEl.getContext('2d');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// [추가] 클래스별 색상 팔레트 (원하는 색상으로 수정 가능)
|
|
|
|
|
const CLASS_COLORS = [
|
|
|
|
|
'#FF3838', // 0: Red
|
|
|
|
|
@ -299,7 +308,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
|
|
|
|
|
|
let lastFrameMeta = null;
|
|
|
|
|
|
|
|
|
|
if (imgEl && statusEl && frameInfoEl && detListEl && bboxContainerEl && modelContainerEl) {
|
|
|
|
|
// [수정] canvasEl 및 ctx 존재 여부 확인
|
|
|
|
|
if (canvasEl && ctx && statusEl && frameInfoEl && detListEl && bboxContainerEl && modelContainerEl) {
|
|
|
|
|
|
|
|
|
|
// 모델 변경 이벤트 리스너
|
|
|
|
|
modelContainerEl.addEventListener('change', (event) => {
|
|
|
|
|
@ -335,11 +345,12 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
|
|
|
|
|
|
// 박스 컨테이너 위치/크기 조절 함수
|
|
|
|
|
function updateBboxContainerPosition() {
|
|
|
|
|
if (!imgEl || !bboxContainerEl) return;
|
|
|
|
|
const top = imgEl.offsetTop;
|
|
|
|
|
const left = imgEl.offsetLeft;
|
|
|
|
|
const width = imgEl.offsetWidth;
|
|
|
|
|
const height = imgEl.offsetHeight;
|
|
|
|
|
// [수정] imgEl -> canvasEl
|
|
|
|
|
if (!canvasEl || !bboxContainerEl) return;
|
|
|
|
|
const top = canvasEl.offsetTop;
|
|
|
|
|
const left = canvasEl.offsetLeft;
|
|
|
|
|
const width = canvasEl.offsetWidth;
|
|
|
|
|
const height = canvasEl.offsetHeight;
|
|
|
|
|
bboxContainerEl.style.top = `${top}px`;
|
|
|
|
|
bboxContainerEl.style.left = `${left}px`;
|
|
|
|
|
bboxContainerEl.style.width = `${width}px`;
|
|
|
|
|
@ -382,7 +393,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
|
lines.push(`DET ch=${meta.ch} seq=${meta.seq} ts=${meta.ts_us} cnt=${items.length}`);
|
|
|
|
|
bboxContainerEl.innerHTML = "";
|
|
|
|
|
|
|
|
|
|
if (!imgEl || !lastFrameMeta) {
|
|
|
|
|
// [수정] imgEl -> canvasEl
|
|
|
|
|
if (!canvasEl || !lastFrameMeta) {
|
|
|
|
|
// [수정됨] x1,y1,x2,y2 형식에 맞게 텍스트 로그 수정
|
|
|
|
|
items.forEach((it, i) => {
|
|
|
|
|
// x1, y1, x2, y2 -> x, y, w, h
|
|
|
|
|
@ -402,8 +414,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updateBboxContainerPosition();
|
|
|
|
|
const imgWidth = imgEl.clientWidth;
|
|
|
|
|
const imgHeight = imgEl.clientHeight;
|
|
|
|
|
// [수정] imgEl -> canvasEl
|
|
|
|
|
const imgWidth = canvasEl.clientWidth;
|
|
|
|
|
const imgHeight = canvasEl.clientHeight;
|
|
|
|
|
const frameWidth = lastFrameMeta.w;
|
|
|
|
|
const frameHeight = lastFrameMeta.h;
|
|
|
|
|
|
|
|
|
|
@ -511,14 +524,12 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// [수정] ArrayBuffer 처리: img.src 대신 createImageBitmap 및 canvas.drawImage 사용
|
|
|
|
|
if (data instanceof ArrayBuffer && lastFrameMeta) {
|
|
|
|
|
const blob = new Blob([data], {type: "image/jpeg"});
|
|
|
|
|
const url = URL.createObjectURL(blob);
|
|
|
|
|
imgEl.onload = () => {
|
|
|
|
|
URL.revokeObjectURL(url);
|
|
|
|
|
updateBboxContainerPosition();
|
|
|
|
|
|
|
|
|
|
// [추가] FPS 계산
|
|
|
|
|
// ========== [수정됨] FPS 계산 로직 (이곳으로 이동) ==========
|
|
|
|
|
// WebSocket에서 ArrayBuffer(프레임)를 수신한 시점을 기준으로 FPS 계산
|
|
|
|
|
frameCount++;
|
|
|
|
|
const now = performance.now();
|
|
|
|
|
const delta = now - lastFpsCheckTime;
|
|
|
|
|
@ -529,8 +540,52 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
|
frameCount = 0;
|
|
|
|
|
lastFpsCheckTime = now;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
imgEl.src = url;
|
|
|
|
|
// ========== FPS 계산 로직 끝 ==========
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const blob = new Blob([data], {type: "image/jpeg"});
|
|
|
|
|
|
|
|
|
|
// createImageBitmap으로 비동기 디코딩 및 렌더링
|
|
|
|
|
createImageBitmap(blob)
|
|
|
|
|
.then(imageBitmap => {
|
|
|
|
|
// 캔버스 크기를 CSS에 정의된 표시 크기로 맞춥니다.
|
|
|
|
|
// (object-fit: contain을 시뮬레이션하기 위해 매번 필요)
|
|
|
|
|
canvasEl.width = canvasEl.clientWidth;
|
|
|
|
|
canvasEl.height = canvasEl.clientHeight;
|
|
|
|
|
|
|
|
|
|
const canvasWidth = canvasEl.width;
|
|
|
|
|
const canvasHeight = canvasEl.height;
|
|
|
|
|
const frameWidth = imageBitmap.width; // 실제 이미지 비트맵의 너비
|
|
|
|
|
const frameHeight = imageBitmap.height; // 실제 이미지 비트맵의 높이
|
|
|
|
|
|
|
|
|
|
// 'object-fit: contain' 로직
|
|
|
|
|
const widthRatio = canvasWidth / frameWidth;
|
|
|
|
|
const heightRatio = canvasHeight / frameHeight;
|
|
|
|
|
const ratio = Math.min(widthRatio, heightRatio);
|
|
|
|
|
|
|
|
|
|
const videoDisplayWidth = frameWidth * ratio;
|
|
|
|
|
const videoDisplayHeight = frameHeight * ratio;
|
|
|
|
|
const offsetX = (canvasWidth - videoDisplayWidth) / 2;
|
|
|
|
|
const offsetY = (canvasHeight - videoDisplayHeight) / 2;
|
|
|
|
|
|
|
|
|
|
// 캔버스를 지웁니다 (CSS의 background-color가 비친다)
|
|
|
|
|
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
|
|
|
|
|
|
|
|
|
|
// 계산된 위치에 이미지를 그립니다.
|
|
|
|
|
ctx.drawImage(imageBitmap, offsetX, offsetY, videoDisplayWidth, videoDisplayHeight);
|
|
|
|
|
|
|
|
|
|
// 비트맵 메모리 해제
|
|
|
|
|
imageBitmap.close();
|
|
|
|
|
|
|
|
|
|
// 프레임이 그려진 *이후*에 바운딩 박스 컨테이너 위치 업데이트
|
|
|
|
|
updateBboxContainerPosition();
|
|
|
|
|
|
|
|
|
|
// [수정됨] FPS 계산 로직이 위로 이동했으므로 여기서는 제거됩니다.
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
.catch(e => {
|
|
|
|
|
console.error("createImageBitmap error:", e);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
@ -550,5 +605,4 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
|
|
|
|
|
|
// ========== 페이지 로드 시 모델 목록 즉시 로드 ==========
|
|
|
|
|
loadModelList();
|
|
|
|
|
|
|
|
|
|
});
|