roundabout,
created on Tuesday, 3 September 2024, 09:19:17 (1725355157),
received on Wednesday, 4 September 2024, 09:03:53 (1725440633)
Author identity: vlad <vlad.muntoiu@gmail.com>
5334ea6555889b7df7f58e3ceed7430a4305bd39
static/picture-annotation.py
@@ -9,11 +9,13 @@ image = document.getElementById("annotation-image")
zone = document.getElementById("annotation-zone")
confirm_button = document.getElementById("annotation-confirm")
cancel_button = document.getElementById("annotation-cancel")
backspace_button = document.getElementById("annotation-backspace")
object_list = document.getElementById("object-types")
confirm_button.style.display = "none"
cancel_button.style.display = "none"
backspace_button.style.display = "none"
shape_type = ""
bbox_pos = None
new_shape = None
@@ -147,7 +149,7 @@ def cancel_bbox(event):
global bbox_pos, new_shape
# Key must be ESCAPE
if event is not None and event.key != "Escape":
if event is not None and hasattr(event, "key") and event.key != "Escape":
return
if new_shape is not None and event is not None:
@@ -229,23 +231,52 @@ def make_polygon(event):
def close_polygon(event):
if event is not None and hasattr(event, "key") and event.key != "Enter":
return
# Polygon is already there, but we need to remove the events
zone.removeEventListener("click", make_polygon_proxy)
zone.removeEventListener("keydown", close_polygon_proxy)
document.removeEventListener("keydown", close_polygon_proxy)
document.removeEventListener("keydown", cancel_polygon_proxy)
confirm_button.style.display = "none"
cancel_button.style.display = "none"
confirm_button.removeEventListener("click", close_polygon_proxy)
cancel_button.removeEventListener("click", cancel_polygon_proxy)
polygon_points.clear()
document.body.style.cursor = "auto"
def cancel_polygon(event):
if event is not None and hasattr(event, "key") and event.key != "Escape":
return
# Delete the polygon
new_shape.remove()
zone.removeEventListener("click", make_polygon_proxy)
zone.removeEventListener("keydown", close_polygon_proxy)
document.removeEventListener("keydown", close_polygon_proxy)
document.removeEventListener("keydown", cancel_polygon_proxy)
confirm_button.style.display = "none"
cancel_button.style.display = "none"
confirm_button.removeEventListener("click", close_polygon_proxy)
cancel_button.removeEventListener("click", cancel_polygon_proxy)
polygon_points.clear()
document.body.style.cursor = "auto"
def backspace_polygon(event):
if event is not None and hasattr(event, "key") and event.key != "Backspace":
return
if not polygon_points:
return
polygon_points.pop()
polygon = new_shape.children[0]
polygon.setAttribute("points", " ".join([f"{point[0] * image.naturalWidth},{point[1] * image.naturalHeight}" for point in polygon_points]))
close_polygon_proxy = create_proxy(close_polygon)
cancel_polygon_proxy = create_proxy(cancel_polygon)
backspace_polygon_proxy = create_proxy(backspace_polygon)
def open_shape(event):
@@ -275,12 +306,20 @@ def open_shape(event):
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")
"press escape to cancel, enter to close, or backspace to "
"remove the last point")
if not polygon_points:
zone.addEventListener("click", make_polygon_proxy)
document.addEventListener("keydown", close_polygon_proxy)
document.addEventListener("keydown", cancel_polygon_proxy)
document.addEventListener("keydown", backspace_polygon_proxy)
cancel_button.addEventListener("click", cancel_polygon_proxy)
cancel_button.style.display = "block"
confirm_button.addEventListener("click", close_polygon_proxy)
confirm_button.style.display = "block"
backspace_button.addEventListener("click", backspace_polygon_proxy)
backspace_button.style.display = "block"
polygon = document.createElementNS("http://www.w3.org/2000/svg", "polygon")
polygon.setAttribute("fill", "none")
polygon.setAttribute("data-object-type", "")
templates/picture-annotation.html
@@ -21,21 +21,12 @@
<button class="button-flat" title="rectangle" id="shape-bbox">
<iconify-icon icon="mdi:square"></iconify-icon>
</button>
<button class="button-flat" title="ellipse" id="shape-ellipse">
<iconify-icon icon="mdi:circle"></iconify-icon>
</button>
<button class="button-flat" title="polygon" id="shape-polygon">
<iconify-icon icon="mdi:pentagon"></iconify-icon>
</button>
<button class="button-flat" title="freehand closed" id="shape-freehand-polygon">
<iconify-icon icon="mdi:lasso"></iconify-icon>
</button>
<button class="button-flat" title="line" id="shape-line">
<iconify-icon icon="mdi:graph-line-variant"></iconify-icon>
</button>
<button class="button-flat" title="freehand open" id="shape-freehand-line">
<iconify-icon icon="mdi:gesture"></iconify-icon>
</button>
<button class="button-flat" title="point" id="shape-point">
<iconify-icon icon="mdi:crosshairs-gps"></iconify-icon>
</button>
@@ -57,6 +48,9 @@
<button class="button-flat" title="apply" id="annotation-confirm">
<iconify-icon icon="mdi:check"></iconify-icon>
</button>
<button class="button-flat" title="remove last point" id="annotation-backspace">
<iconify-icon icon="mdi:backspace"></iconify-icon>
</button>
</x-buttonbox>
<x-vbox id="object-types" style="--gap-box: 0.25rem; --padding-box: 1rem;">
</x-vbox>
templates/picture.html
@@ -9,7 +9,8 @@
<p>
<a href="{{ resource.origin_url }}">Original source</a> |
<a href="/raw/picture/{{ resource.id }}">View</a> |
<a href="/raw/picture/{{ resource.id }}" download="GigadataPicture_{{ resource.id }}{{ file_extension }}">Download</a>
<a href="/raw/picture/{{ resource.id }}" download="GigadataPicture_{{ resource.id }}{{ file_extension }}">Download</a> |
<a href="/picture/{{ resource.id }}/annotate">Annotate</a>
</p>
</x-frame>
{% endblock %}