fisheye-experimental / annotation_editor.js
oskarastrom's picture
Upload old results
592e4db
raw
history blame
No virus
10.5 kB
() => {
window.canvas = document.getElementById('canvas');
window.ctx = canvas.getContext('2d');
window.rects = [];
window.mouseX;
window.mouseY;
window.dragX;
window.dragY;
window.closeEnough = 10;
window.keys = {};
window.hover = false;
window.TL = 0;
window.TR = 1;
window.BL = 2;
window.BR = 3;
window.init = () => {
window.frames = JSON.parse(document.getElementById("annotation_info").innerHTML);
window.frame_index = 0;
document.addEventListener('keydown', keydown);
document.addEventListener('keyup', keyup);
show_frame();
}
window.prev_frame = () => {
window.frame_index = Math.max(window.frame_index - 1, 0);
show_frame();
}
window.next_frame = () => {
window.frame_index = Math.min(window.frame_index + 1, window.frames.length - 1);
show_frame();
}
window.show_frame = () => {
const frame_info = window.frames[window.frame_index];
const annotations = frame_info['annotations'];
const frame = frame_info['frame'];
window.annotations = [];
for (const annotation of annotations) {
const bbox = annotation['bbox']
window.annotations.push({
rect: {
startX: bbox.left,
startY: bbox.top,
w: bbox.right - bbox.left,
h: bbox.bottom - bbox.top
},
id: annotation.id,
conf: annotation.conf
})
}
console.log(window.annotations)
window.dragging = false;
document.getElementById("annotation_img").src = "data:image/png;base64," + frame;
}
window.draw = () => {
ctx = window.ctx;
canvas = window.canvas;
canvas.width = document.getElementById("annotation_img").width;
canvas.height = document.getElementById("annotation_img").height;
canvas.style = ""
annotations = window.annotations;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(document.getElementById("annotation_img"), 0, 0);
for (const annotation of annotations) {
//ctx.globalAlpha = annotation.conf
const rect = annotation.rect;
ctx.strokeStyle = color_from_id(annotation.id);
ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
ctx.font = "15px Arial";
ctx.fillStyle = color_from_id(annotation.id);
ctx.textAlign = "right";
ctx.fillText(annotation.id, rect.startX + rect.w, rect.startY - 3);
}
if (hover && !dragging) {
annotation = hover.annotation;
rect = annotation.rect;
handles = [
[rect.startX, rect.startY],
[rect.startX + rect.w, rect.startY],
[rect.startX, rect.startY + rect.h],
[rect.startX + rect.w, rect.startY + rect.h]
];
handle = handles[hover.corner];
ctx.fillStyle = color_from_id(annotation.id);
ctx.beginPath();
s = 6;
ctx.rect(handle[0]-s/2, handle[1]-s/2, s, s);
ctx.fill();
}
prettify_annotation();
}
color_from_id = (id) => {
c = Math.ceil(Math.log2(id));
hue = (2*id - Math.pow(2,c) - 1) / Math.pow(2,c);
return 'hsl(' + Math.floor(hue*359) + ', 100%, 50%)'
}
window.prettify_annotation = () => {
label_style = "style='width: calc(16% - 6px); display: inline-block; text-align:center; font-weight: bold;'";
input_style_base = "style='width: calc(16% - 6px); display: inline-block; padding: 5px;'";
input_style_selected = "style='width: calc(16% - 6px); display: inline-block; padding: 5px; border-width: 3px; border-color: orange; border-radius: 5px;'";
html = ""
for (const annotation of window.annotations) {
input_style = (window.hover && annotation === window.hover.annotation) ? input_style_selected : input_style_base;
html += `
<div style='margin: 0 0 20px 10px'>
<div>
<label ${label_style}>${"id"}</label>
<label ${label_style}>${"x"}</label>
<label ${label_style}>${"y"}</label>
<label ${label_style}>${"w"}</label>
<label ${label_style}>${"h"}</label>
<label ${label_style}>${"conf"}</label>
</div>
<div style='height:40px'>
<input ${input_style} type='text' value='${annotation.id}'>
<input ${input_style} type='text' value='${Math.round(annotation.rect.startX)}'>
<input ${input_style} type='text' value='${Math.round(annotation.rect.startY)}'>
<input ${input_style} type='text' value='${Math.round(annotation.rect.w)}'>
<input ${input_style} type='text' value='${Math.round(annotation.rect.h)}'>
<input ${input_style} type='text' value='${annotation.conf}'>
</div>
</div>`;
}
document.getElementById("annotation_display").innerHTML = html;
}
window.keyup = (e) => {
delete keys[e.key.toLowerCase()];
}
window.keydown = (e) => {
console.log(e.key.toLowerCase())
keys[e.key.toLowerCase()] = true;
// if pressing x, delete hovered annotation
if (keys['x'] && window.hover) delete_annotation(window.hover.annotation);
if (keys['arrowright'] || keys['d']) next_frame();
if (keys['arrowleft'] || keys['a']) prev_frame();
}
window.mouse_down = (e) => {
update_mouse(e);
dragX = mouseX;
dragY = mouseY;
// If holding 'n', create new annotation
if (keys['n']) return create_annotation();
// else, start dragging hovered object
window.dragging = false;
if (window.hover) {
window.dragging = {
annotation: window.hover.annotation,
corner: window.hover.corner
}
}
console.log(dragging)
window.draw()
}
window.mouse_up = () => {
console.log("mouseUp")
window.dragging = false;
}
window.mouse_move = (e) => {
ctx = window.ctx;
canvas = window.canvas;
dragging = window.dragging;
update_mouse(e);
if (!dragging) return window.draw();
annotation = dragging.annotation;
rect = annotation.rect
corner = dragging.corner;
console.log("drag", dragX, dragY)
console.log("d", rect.startX - mouseX, rect.startY - mouseY)
if (corner == window.TL) {
rect.w += rect.startX - mouseX;
rect.h += rect.startY - mouseY;
rect.startX = mouseX;
rect.startY = mouseY;
} else if (corner == window.TR) {
rect.w = mouseX - rect.startX;
rect.h += rect.startY - mouseY;
rect.startY = mouseY;
} else if (corner == window.BL) {
rect.w += rect.startX - mouseX;
rect.h = mouseY - rect.startY;
rect.startX = mouseX;
} else if (corner == window.BR) {
rect.w = mouseX - rect.startX;
rect.h = mouseY - rect.startY
}
//rect.startX = Math.floor(rect.startX);
//rect.startY = Math.floor(rect.startY);
//rect.w = Math.floor(rect.w);
//rect.h = Math.floor(rect.h);
// If w < 0 we have swapped sides, switch to horizontally opposite corner
if (rect.w < 0) {
rect.w = -rect.w;
if (corner == window.TL) corner = window.TR;
else if (corner == window.TR) corner = window.TL;
else if (corner == window.BL) corner = window.BR;
else if (corner == window.BR) corner = window.BL;
}
//If h < 0 we have swapped sides, switch to vertically opposite corner
if (rect.h < 0) {
rect.h = -rect.h;
if (corner == window.TL) corner = window.BL;
else if (corner == window.BL) corner = window.TL;
else if (corner == window.TR) corner = window.BR;
else if (corner == window.BR) corner = window.TR;
}
if (dragging.corner !== corner) console.log(dragging.corner + " -> " + corner);
dragging.corner = corner;
window.draw()
}
update_mouse = (e) => {
bodyRect = document.body.getBoundingClientRect();
canvasRect = e.target.getBoundingClientRect();
offset_x = canvasRect.left - bodyRect.left;
offset_y = canvasRect.top - bodyRect.top;
mouseX = e.pageX - offset_x;
mouseY = e.pageY - offset_y;
function sqDistance(x, y) {
dx = mouseX - x;
dy = mouseY - y;
return dx*dx + dy*dy;
}
window.hover = false;
threshold = 100;
for (const annotation of annotations) {
rect = annotation.rect;
square_dists = [
sqDistance(rect.startX, rect.startY),
sqDistance(rect.startX + rect.w, rect.startY),
sqDistance(rect.startX, rect.startY + rect.h),
sqDistance(rect.startX + rect.w, rect.startY + rect.h),
]
min_dist = Math.min(...square_dists);
if (min_dist > threshold) continue;
threshold = min_dist;
corner = square_dists.indexOf(min_dist);
window.hover = { corner, annotation }
}
}
create_annotation = () => {
new_annotation = {
rect: {
startX: mouseX,
startY: mouseY,
w: 0,
h: 0
},
color: "rgb(255, 0, 0)",
id: 1,
conf: 1
};
annotations.push(new_annotation);
window.dragging = {
annotation: new_annotation,
corner: window.BL
}
window.draw()
}
delete_annotation = (annotation) => {
window.annotations = window.annotations.filter(function (a) {
return a !== annotation;
});
window.dragging = false;
window.hover = false;
window.draw();
}
window.init();
}