Web platform for sharing free image data for ML and research

Homepage: https://datasets.roundabout-host.com

Allow making polygons

by roundabout, Thursday, 29 August 2024, 13:10:30 (1724937030), pushed by roundabout, 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>