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