picture-annotation.py
Python script, ASCII text executable
1
from pyscript import document
2
from pyodide.ffi import create_proxy
3
4
document.getElementById("shape-options").style.display = "flex"
5
6
image = document.getElementById("annotation-image")
7
zone = document.getElementById("annotation-zone")
8
9
10
shape_type = ""
11
12
13
def switch_shape(event):
14
global shape_type
15
shape = event.currentTarget.id
16
shape_type = shape
17
print("Shape is now of type:", shape)
18
19
20
vertical_ruler = document.getElementById("annotation-ruler-vertical")
21
horizontal_ruler = document.getElementById("annotation-ruler-horizontal")
22
vertical_ruler_2 = document.getElementById("annotation-ruler-vertical-secondary")
23
horizontal_ruler_2 = document.getElementById("annotation-ruler-horizontal-secondary")
24
helper_message = document.getElementById("annotation-helper-message")
25
26
helper_message.innerText = "Select a shape type then click on the image to begin defining it"
27
28
29
def follow_cursor(event):
30
rect = zone.getBoundingClientRect()
31
x = event.clientX - rect.left
32
y = event.clientY - rect.top
33
vertical_ruler.style.left = str(x) + "px"
34
horizontal_ruler.style.top = str(y) + "px"
35
36
37
bbox_pos = None
38
39
40
def make_bbox(event):
41
global new_shape, bbox_pos
42
zone_rect = zone.getBoundingClientRect()
43
44
if bbox_pos is None:
45
bbox_pos = [event.clientX - zone_rect.left, event.clientY - zone_rect.top]
46
vertical_ruler_2.style.left = str(bbox_pos[0]) + "px"
47
horizontal_ruler_2.style.top = str(bbox_pos[1]) + "px"
48
vertical_ruler_2.style.display = "block"
49
horizontal_ruler_2.style.display = "block"
50
51
else:
52
x0, y0 = bbox_pos
53
x1, y1 = event.clientX - zone_rect.left, event.clientY - zone_rect.top
54
55
rectangle = document.createElementNS("http://www.w3.org/2000/svg", "rect")
56
minx = min(x0, x1)
57
miny = min(y0, y1)
58
maxx = max(x0, x1)
59
maxy = max(y0, y1)
60
61
rectangle.setAttribute("x", str(minx))
62
rectangle.setAttribute("y", str(miny))
63
rectangle.setAttribute("width", str(maxx - minx))
64
rectangle.setAttribute("height", str(maxy - miny))
65
rectangle.setAttribute("fill", "none")
66
rectangle.classList.add("shape-bbox")
67
68
new_shape.appendChild(rectangle)
69
zone.appendChild(new_shape)
70
vertical_ruler.style.display = "none"
71
horizontal_ruler.style.display = "none"
72
vertical_ruler_2.style.display = "none"
73
horizontal_ruler_2.style.display = "none"
74
75
zone.removeEventListener("click", create_proxy(make_bbox))
76
77
return
78
79
80
zone.addEventListener(
81
"mousemove",
82
create_proxy(follow_cursor)
83
)
84
85
new_shape = None
86
87
def open_shape(event):
88
global last_click_position, new_shape
89
print("Creating a new shape of type:", shape_type)
90
new_shape = document.createElementNS("http://www.w3.org/2000/svg", "svg")
91
new_shape.setAttribute("width", image.width)
92
new_shape.setAttribute("height", image.height)
93
94
if shape_type == "shape-bbox":
95
bbox_pos = None
96
zone.addEventListener(
97
"click",
98
create_proxy(make_bbox)
99
)
100
vertical_ruler.style.display = "block"
101
horizontal_ruler.style.display = "block"
102
103
zone.appendChild(new_shape)
104
105
106
for button in list(document.getElementById("shape-selector").children):
107
button.addEventListener(
108
"click",
109
create_proxy(switch_shape)
110
)
111
print("Shape", button.id, "is available")
112
113
114
115
zone.addEventListener(
116
"click",
117
create_proxy(open_shape)
118
)
119