roundabout,
created on Thursday, 29 August 2024, 13:10:30 (1724937030),
received on Friday, 30 August 2024, 03:07:47 (1724987267)
Author identity: vlad <vlad.muntoiu@gmail.com>
f21bc7fee4231363d0e629eb7d8b265e93b1657c
static/picture-annotation.py
@@ -70,11 +70,17 @@ async def select_shape(event):
object_list.appendChild(new_label) new_radio.addEventListener("change", change_object_type_proxy) selected_object = selected_shape.getAttribute("data-object-type") if not selected_object: new_radio.setAttribute("checked", "") for object, description in objects.items(): new_radio = document.createElement("input") new_radio.setAttribute("type", "radio") new_radio.setAttribute("name", "object-type") new_radio.setAttribute("value", object) if selected_object == object: new_radio.setAttribute("checked", "")new_label = document.createElement("label") new_label.appendChild(new_radio) new_label.append(object)
@@ -91,6 +97,8 @@ def unselect_shape(event):
selected_shape.classList.remove("selected") selected_shape = None object_list.innerHTML = "" select_shape_proxy = create_proxy(select_shape) unselect_shape_proxy = create_proxy(unselect_shape)
@@ -99,6 +107,7 @@ unselect_shape_proxy = create_proxy(unselect_shape)
# 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)) make_polygon_proxy = create_proxy(lambda event: make_polygon(event))follow_cursor_proxy = create_proxy(follow_cursor)
@@ -137,6 +146,10 @@ helper_message.innerText = "Select a shape type then click on the image to begin
def cancel_bbox(event): global bbox_pos, new_shape # Key must be ESCAPE if event is not None and event.key != "Escape": return if new_shape is not None and event is not None: # Require event so the shape is kept when it ends normally new_shape.remove()
@@ -197,17 +210,56 @@ def make_bbox(event):
cancel_bbox(None) polygon_points = [] def make_polygon(event): global new_shape, polygon_points print(new_shape.outerHTML) polygon = new_shape.children[0] zone_rect = zone.getBoundingClientRect() polygon_points.append(((event.clientX - zone_rect.left) / zone_rect.width, (event.clientY - zone_rect.top) / zone_rect.height)) # Update the polygon polygon.setAttribute("points", " ".join([f"{point[0] * image.naturalWidth},{point[1] * image.naturalHeight}" for point in polygon_points])) def close_polygon(event): # Polygon is already there, but we need to remove the events zone.removeEventListener("click", make_polygon_proxy) zone.removeEventListener("keydown", close_polygon_proxy) document.body.style.cursor = "auto" def cancel_polygon(event): # Delete the polygon new_shape.remove() zone.removeEventListener("click", make_polygon_proxy) zone.removeEventListener("keydown", close_polygon_proxy) document.body.style.cursor = "auto" close_polygon_proxy = create_proxy(close_polygon) def open_shape(event): global new_shape, bbox_pos if bbox_pos or shape_type == "select": return print("Creating a new shape of type:", shape_type) new_shape = document.createElementNS("http://www.w3.org/2000/svg", "svg")new_shape.setAttribute("width", "100%")new_shape.setAttribute("height", "100%")zone_rect = zone.getBoundingClientRect()new_shape.setAttribute("viewBox", f"0 0 {image.naturalWidth} {image.naturalHeight}")new_shape.classList.add("shape-container")if not polygon_points: new_shape = document.createElementNS("http://www.w3.org/2000/svg", "svg") new_shape.setAttribute("width", "100%") new_shape.setAttribute("height", "100%") zone_rect = zone.getBoundingClientRect() new_shape.setAttribute("viewBox", f"0 0 {image.naturalWidth} {image.naturalHeight}") new_shape.classList.add("shape-container")if shape_type == "shape-bbox": helper_message.innerText = ("Define the first point at the intersection of the lines "
@@ -221,6 +273,22 @@ def open_shape(event):
vertical_ruler.style.display = "block" horizontal_ruler.style.display = "block" document.body.style.cursor = "crosshair" elif shape_type == "shape-polygon": helper_message.innerText = ("Click on the image to define the points of the polygon, " "press escape to cancel, " "or press enter to close") if not polygon_points: zone.addEventListener("click", make_polygon_proxy) document.addEventListener("keydown", close_polygon_proxy) polygon = document.createElementNS("http://www.w3.org/2000/svg", "polygon") polygon.setAttribute("fill", "none") polygon.setAttribute("data-object-type", "") polygon.classList.add("shape-polygon") polygon.classList.add("shape") new_shape.appendChild(polygon) zone.appendChild(new_shape) document.body.style.cursor = "crosshair"for button in list(document.getElementById("shape-selector").children):
templates/picture-annotation.html
@@ -13,7 +13,7 @@
<h1>Annotating: {{ resource.title }}</h1> <p id="annotation-helper-message">Please wait for Python to load...</p> </x-frame> <x-frame is="main-area"><x-frame id="main-area"><x-buttonbox id="shape-selector"> <button class="button-flat" title="selection" id="select"> <iconify-icon icon="mdi:cursor-default"></iconify-icon>