File size: 2,739 Bytes
6dfcb0f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import cv2
import gradio as gr
import numpy as np

# Global variable to store the list of arrows (start and end points)
arrows = []
start_point = None


# Function to draw all arrows (including zero-length arrows) on the image
def draw_arrow(image, click_coords):
    global start_point, arrows

    # Convert the image to a numpy array if it's not already
    img_array = np.array(image, dtype=np.uint8)

    # Get the current point from the user (click coordinates as (x, y))
    current_point = (int(click_coords[0]), int(click_coords[1]))  # Convert float coords to int

    # If start point is not set, set it as the current click position
    if start_point is None:
        start_point = current_point
        return img_array  # No arrow yet, just return the original image

    # If start point is already set, add an arrow (including zero-length ones)
    end_point = current_point
    arrows.append((start_point, end_point))  # Save the arrow

    # Reset start_point for the next arrow
    start_point = None

    # Draw all arrows from the saved list
    for arrow in arrows:
        start, end = arrow
        color = (0, 255, 0)  # Green arrow
        thickness = 3

        # Draw the arrow (even if it's zero-length, i.e., start == end)
        cv2.arrowedLine(img_array, start, end, color, thickness)

    return img_array


# Function to reset the canvas (clearing all arrows)
def reset_canvas():
    global arrows, start_point
    arrows = []
    start_point = None
    return load_image()  # Return a fresh image


# Load an image for the user to interact with
def load_image():
    img = np.ones((400, 400, 3), dtype=np.uint8) * 255  # White background image
    return img


# Define Gradio interface using Blocks
def interactive_arrow_interface():
    with gr.Blocks() as demo:
        image_input = gr.Image(value=load_image(), interactive=True,
                               label="Click to specify the arrow's start and end points")
        output_image = gr.Image(label="Image with Arrows")
        reset_button = gr.Button("Reset")

        # Set up interaction: Handle click events with 'handle_click'
        def handle_click(image, evt: gr.SelectData):
            print(f"Click coordinates: {evt.index}")
            # Pass click coordinates to draw_arrow function and update the image
            updated_image = draw_arrow(image, (evt.index[0], evt.index[1]))
            return updated_image

        image_input.select(handle_click, [image_input], output_image)

        # Set up the reset button to clear all arrows
        reset_button.click(fn=reset_canvas, inputs=None, outputs=image_input)

        return demo


# Launch the interactive demo
interactive_arrow_interface().launch(inbrowser=True)