img --> canvas.

main
dongjin kim 7 months ago
parent ac157c2b6b
commit cd39c6d05a

@ -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();
});

@ -34,7 +34,7 @@
<span id="current-model-display" class="video-overlay top-right"></span>
<span id="fps-display" class="video-overlay bottom-right"></span>
<img id="frame" alt="video frame">
<canvas id="frame"></canvas>
<div id="bbox-container"></div>
</div>
<div id="det-wrap">

@ -276,7 +276,6 @@ main {
min-height: 0;
max-width: 100%;
background: #000;
object-fit: contain;
border: 1px solid #333;
position: relative;
z-index: 1;

Loading…
Cancel
Save