roundabout,
created on Monday, 19 August 2024, 16:05:11 (1724083511),
received on Monday, 19 August 2024, 16:05:16 (1724083516)
Author identity: vlad <vlad.muntoiu@gmail.com>
ebc5eaa33368d9916ecdf3a5226f192e6fe8880f
static/picture-annotation.py
@@ -5,9 +5,29 @@ document.getElementById("shape-options").style.display = "flex"
image = document.getElementById("annotation-image") zone = document.getElementById("annotation-zone") confirm_button = document.getElementById("annotation-confirm") cancel_button = document.getElementById("annotation-cancel")confirm_button.style.display = "none" cancel_button.style.display = "none" shape_type = "" bbox_pos = None new_shape = None def follow_cursor(event): rect = zone.getBoundingClientRect() x = event.clientX - rect.left y = event.clientY - rect.top vertical_ruler.style.left = str(x) + "px" horizontal_ruler.style.top = str(y) + "px" # These are functions usable in JS cancel_bbox_proxy = create_proxy(lambda event: cancel_bbox(event)) make_bbox_proxy = create_proxy(lambda event: make_bbox(event)) follow_cursor_proxy = create_proxy(follow_cursor)def switch_shape(event):
@@ -16,7 +36,6 @@ def switch_shape(event):
shape_type = shape print("Shape is now of type:", shape) vertical_ruler = document.getElementById("annotation-ruler-vertical") horizontal_ruler = document.getElementById("annotation-ruler-horizontal") vertical_ruler_2 = document.getElementById("annotation-ruler-vertical-secondary")
@@ -26,22 +45,33 @@ helper_message = document.getElementById("annotation-helper-message")
helper_message.innerText = "Select a shape type then click on the image to begin defining it" def follow_cursor(event):rect = zone.getBoundingClientRect()x = event.clientX - rect.lefty = event.clientY - rect.topvertical_ruler.style.left = str(x) + "px"horizontal_ruler.style.top = str(y) + "px"def cancel_bbox(event): global bbox_pos, new_shapebbox_pos = Noneif new_shape is not None and event is not None: # Require event so the shape is kept when it ends normally new_shape.remove() new_shape = None zone.removeEventListener("click", make_bbox_proxy) document.removeEventListener("keydown", cancel_bbox_proxy) cancel_button.removeEventListener("click", cancel_bbox_proxy)bbox_pos = None vertical_ruler.style.display = "none" horizontal_ruler.style.display = "none" vertical_ruler_2.style.display = "none" horizontal_ruler_2.style.display = "none" document.body.style.cursor = "auto" cancel_button.style.display = "none" helper_message.innerText = "Select a shape type then click on the image to begin defining it" def make_bbox(event): global new_shape, bbox_pos zone_rect = zone.getBoundingClientRect() if bbox_pos is None: helper_message.innerText = "Now define the second point"bbox_pos = [(event.clientX - zone_rect.left) / zone_rect.width, (event.clientY - zone_rect.top) / zone_rect.height] vertical_ruler_2.style.left = str(bbox_pos[0] * 100) + "%"
@@ -50,11 +80,15 @@ def make_bbox(event):
horizontal_ruler_2.style.display = "block" else: x0, y0 = bbox_posx0, y0 = bbox_pos.copy()x1 = (event.clientX - zone_rect.left) / zone_rect.width y1 = (event.clientY - zone_rect.top) / zone_rect.height rectangle = document.createElementNS("http://www.w3.org/2000/svg", "rect") new_shape.appendChild(rectangle) zone.appendChild(new_shape)minx = min(x0, x1) miny = min(y0, y1) maxx = max(x0, x1)
@@ -67,27 +101,12 @@ def make_bbox(event):
rectangle.setAttribute("fill", "none") rectangle.classList.add("shape-bbox") new_shape.appendChild(rectangle)zone.appendChild(new_shape)vertical_ruler.style.display = "none"horizontal_ruler.style.display = "none"vertical_ruler_2.style.display = "none"horizontal_ruler_2.style.display = "none"document.body.style.cursor = "auto"zone.removeEventListener("click", create_proxy(make_bbox))returnzone.addEventListener("mousemove",create_proxy(follow_cursor))new_shape = Nonecancel_bbox(None)def open_shape(event): global last_click_position, new_shapeglobal new_shape, bbox_pos if bbox_pos: returnprint("Creating a new shape of type:", shape_type) new_shape = document.createElementNS("http://www.w3.org/2000/svg", "svg") new_shape.setAttribute("width", "100%")
@@ -96,26 +115,23 @@ def open_shape(event):
new_shape.setAttribute("viewBox", f"0 0 {image.naturalWidth} {image.naturalHeight}") if shape_type == "shape-bbox": helper_message.innerText = ("Define the first point at the intersection of the lines " "by clicking on the image, or click the cross to cancel") cancel_button.addEventListener("click", cancel_bbox_proxy) document.addEventListener("keydown", cancel_bbox_proxy) cancel_button.style.display = "block"bbox_pos = None zone.addEventListener("click",create_proxy(make_bbox))zone.addEventListener("click", make_bbox_proxy)vertical_ruler.style.display = "block" horizontal_ruler.style.display = "block" document.body.style.cursor = "crosshair" for button in list(document.getElementById("shape-selector").children): button.addEventListener("click",create_proxy(switch_shape))button.addEventListener("click", create_proxy(switch_shape))print("Shape", button.id, "is available") zone.addEventListener("click",create_proxy(open_shape))zone.addEventListener("mousemove", follow_cursor_proxy) zone.addEventListener("click", create_proxy(open_shape))
templates/picture-annotation.html
@@ -37,7 +37,7 @@
<iconify-icon icon="mdi:gesture"></iconify-icon> </button> <button class="button-flat" title="point" id="shape-point"> <iconify-icon icon="mdi:circle"></iconify-icon><iconify-icon icon="mdi:crosshairs-gps"></iconify-icon></button> <button class="button-flat" title="whole picture" id="shape-all"> <iconify-icon icon="mdi:image"></iconify-icon>
@@ -51,10 +51,10 @@
<div id="annotation-ruler-horizontal-secondary" class="annotation-ruler"></div> </div> <x-buttonbox style="display: none;" id="shape-options"> <button class="button-flat" title="cancel" disabled><button class="button-flat" title="cancel" id="annotation-cancel"><iconify-icon icon="mdi:close"></iconify-icon> </button> <button class="button-flat" title="apply" disabled><button class="button-flat" title="apply" id="annotation-confirm"><iconify-icon icon="mdi:check"></iconify-icon> </button> </x-buttonbox>