roundabout,
created on Thursday, 5 September 2024, 08:43:10 (1725525790),
received on Thursday, 5 September 2024, 10:39:47 (1725532787)
Author identity: vlad <vlad.muntoiu@gmail.com>
610489a27a2da9b629f66fcdb24c2c7242e24f83
app.py
@@ -36,6 +36,12 @@ def split(value, separator=None, maxsplit=-1):
return value.split(separator, maxsplit) @app.template_filter("median") def median(value): value = list(value) # prevent generators return sorted(value)[len(value) // 2] with app.app_context(): class User(db.Model):
static/picture-annotation.py
@@ -116,7 +116,7 @@ def put_shapes(json_shapes):
rectangle.setAttribute("width", str(shape["shape"]["w"] * image.naturalWidth)) rectangle.setAttribute("height", str(shape["shape"]["h"] * image.naturalHeight)) rectangle.setAttribute("fill", "none") rectangle.setAttribute("data-object-type", shape["object"])rectangle.setAttribute("data-object-type", shape["object"] or "")rectangle.classList.add("shape-bbox") rectangle.classList.add("shape") new_shape.appendChild(rectangle)
@@ -126,7 +126,7 @@ def put_shapes(json_shapes):
[f"{point['x'] * image.naturalWidth},{point['y'] * image.naturalHeight}" for point in shape["shape"]]) polygon.setAttribute("points", points) polygon.setAttribute("fill", "none") polygon.setAttribute("data-object-type", shape["object"])polygon.setAttribute("data-object-type", shape["object"] or "")polygon.classList.add(f"shape-{shape['type']}") polygon.classList.add("shape") new_shape.appendChild(polygon)
@@ -137,7 +137,7 @@ def put_shapes(json_shapes):
point.setAttribute("r", "0") point.classList.add("shape-point") point.classList.add("shape") point.setAttribute("data-object-type", shape["object"])point.setAttribute("data-object-type", shape["object"] or "")new_shape.appendChild(point) zone.appendChild(new_shape)
static/style.css
@@ -130,6 +130,9 @@ iconify-icon {
.shape-container-viewonly > .shape-point { stroke: var(--color-info); transition: r 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), stroke-width 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), filter 0.25s cubic-bezier(0.61, 1, 0.88, 1);} .shape-label {
@@ -162,6 +165,12 @@ iconify-icon {
transform: scale(1); } /* Hide points with a bubble */ #annotation-zone:has(+ x-buttonbox #show-objects:checked) > .shape-container-viewonly > .shape-point:has(+ foreignObject) { r: 0; border-width: 0; } #annotation-zone:has(+ x-buttonbox #show-shapes:checked) > .shape-container-viewonly > .shape { fill-opacity: 0.1; stroke-opacity: 1;
templates/picture.html
@@ -1,5 +1,14 @@
{% extends "default.html" %} {% block title %}Picture | gigadata{% endblock %} {% macro shape_label(x, y, text) %} {% if text %} <foreignObject height="100%" width="100%" x="{{ x * size[0] }}" y="{{ y * size[1] }}"> <div class="shape-label"> {{ text }} </div> </foreignObject> {% endif %} {% endmacro %}{% block content %} <x-frame style="--width: 768px"> <h1>{{ resource.title }}</h1>
@@ -12,10 +21,13 @@
<svg class="shape-container-viewonly" viewBox="0 0 {{ size[0] }} {{ size[1] }}"> <rect x="{{ region.json.shape.x * size[0] }}" y="{{ region.json.shape.y * size[1] }}" width="{{ region.json.shape.width * size[0] }}"height="{{ region.json.shape.height * size[1] }}"width="{{ region.json.shape.w * size[0] }}" height="{{ region.json.shape.h * size[1] }}"fill="none" class="shape-bbox shape" ></rect> {% set centre_x = region.json.shape.x + region.json.shape.w / 2 %} {% set centre_y = region.json.shape.y + region.json.shape.h / 2 %} {{ shape_label(centre_x, centre_y, region.object_id) }}</svg> {% elif region.json.type == "polygon" %} <svg class="shape-container-viewonly" viewBox="0 0 {{ size[0] }} {{ size[1] }}">
@@ -26,19 +38,20 @@
{% set right = region.json.shape | sort(attribute='x') | last %} {% set centre_x = (left.x + right.x) / 2 %} {% set centre_y = (top.y + bottom.y) / 2 %} <foreignObject height="100%" width="100%" x="{{ centre_x * size[0] }}" y="{{ centre_y * size[1] }}"><div class="shape-label">{{ region.object_id }}</div></foreignObject>{{ shape_label(centre_x, centre_y, region.object_id) }}</svg> {% elif region.json.type == "polyline" %} <svg class="shape-container-viewonly" viewBox="0 0 {{ size[0] }} {{ size[1] }}"> <polyline points="{% for point in region.json.shape %}{{ point.x * size[0] }},{{ point.y * size[1] }} {% endfor %}" fill="none" class="shape-polyline shape"></polyline><polyline points="{% for point in region.json.shape %}{{ point.x * size[0] }},{{ point.y * size[1] }} {% endfor %}" fill="none" class="shape-polyline shape"> {# Median point #} {% set centre_x = region.json.shape | map(attribute="x") | median %} {% set centre_y = region.json.shape | map(attribute="y") | median %} {{ shape_label(centre_x, centre_y, region.object_id) }}</svg> {% elif region.json.type == "point" %} <svg class="shape-container-viewonly" viewBox="0 0 {{ size[0] }} {{ size[1] }}"> <circle cx="{{ region.json.shape.x * size[0] }}" cy="{{ region.json.shape.y * size[1] }}" r="0" fill="none" class="shape-point shape"></circle> {{ shape_label(region.json.shape.x, region.json.shape.y, region.object_id) }}</svg> {% endif %} {% endfor %}