File size: 8,208 Bytes
b27cd24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
import cv2
import tkinter as tk
from tkinter import ttk
import os
import json
# from ultralytics import YOLO
from PIL import Image
# import torch

# Load the image
image_path = "image_024\image_024.jpg"
image = cv2.imread(image_path)
clone = image.copy()
original_height, original_width = image.shape[:2]
# Resize the image to have a height of 1000 while maintaining the aspect ratio
# height = 600
# scale = height / image.shape[0]
# width = int(image.shape[1] * scale)
# image = cv2.resize(image, (width, height))
# clone = image.copy()


# model = YOLO("yolo11n.pt")
# results = model("image_024\image_024.jpg", classes=0)

# tensor_boxes=results[0].boxes.xywhn

# for box in tensor_boxes:
#     x_center = int(box[0] * original_width * scale)
#     y_center = int(box[1] * original_height * scale)
#     cv2.circle(image, (x_center, y_center), 5, (0, 255, 0), -1)

# clone = image.copy()


# Variables to store start and end points of the line
start_point = None
end_point = None
drawing = False

# Annotation properties
annotation = {
    "line_shape": {
        "turns": None,
        "description": None
    },
    "people": {
        "number_of_people": None,
        "direction_they_are_facing": None,
        "start_person_description": None,
        "end_person_description": None,
        "counter_person_description": None
    },
    "boundary": {
        "boundary_present": None,
        "boundary_types": None
    },
    "start_of_line": {
        "visible": None,
        "location_if_visible": None,
        "direction_to_turn_if_not_visible": None
    },
    "end_of_line": {
        "visible": None,
        "location_if_visible": None,
        "direction_to_turn_if_not_visible": None
    },
    "line_purpose": None
    "line_completeness": None,
    "line_coordinates": None  # Set in draw_line()
}

def submit_annotations(entries):
    annotation["line_shape"]["turns"] = int(entries["Number of turns"].get())
    annotation["line_shape"]["description"] = entries["Line shape"].get()

    annotation["people"]["number_of_people"] = int(entries["Number of people in line"].get())
    annotation["people"]["direction_they_are_facing"] = entries["What direction is the line facing"].get()
    annotation["people"]["start_person_description"] = entries["Description of the person at the start of the line"].get()
    annotation["people"]["end_person_description"] = entries["Description of the person at the end of the line"].get()
    annotation["people"]["counter_person_description"] = entries["Description of the person at the counter"].get()

    annotation["line_purpose"] = entries["Line purpose"].get()

    annotation["boundary"]["boundary_present"] = entries["Is there a boundary?"].get().lower() == "yes"
    annotation["boundary"]["boundary_types"] = entries["Boundary types"].get()

    annotation["end_of_line"]["visible"] = entries["Do we see the end of line?"].get()
    annotation["end_of_line"]["location_if_visible"] = entries["If yes, where is the end of the line in the image?"].get()
    annotation["end_of_line"]["direction_to_turn_if_not_visible"] = entries["If not, in what direction should you move camera to see the end of the line?"].get()

    annotation["start_of_line"]["visible"] = entries["Do we see the start of line?"].get()
    annotation["start_of_line"]["location_if_visible"] = entries["If yes, where is the start of the line in the image?"].get()
    annotation["start_of_line"]["direction_to_turn_if_not_visible"] = entries["If not, in what direction should you move camera to see the start of the line?"].get()

    annotation["line_completeness"] = entries["Does the image show a full line or partial line?"].get()

    print("Annotation Properties:", annotation)

    image_base = os.path.splitext(os.path.basename(image_path))[0]
    with open(f"{image_base}.json", "w") as f:
        json.dump(annotation, f, indent=4)
    print(f"Saved annotation to {image_base}.json")


def setup_annotation_gui():
    root = tk.Tk()
    root.title("Annotation Input")
    root.resizable(True, True)
    fields = {
        "Number of turns": tk.Entry,
        "Line shape": ttk.Combobox,
        "What direction is the line facing": ttk.Combobox,
        "Number of people in line": tk.Entry,
        "Line purpose": tk.Entry,
        "Description of the person at the start of the line": tk.Entry,
        "Description of the person at the end of the line": tk.Entry,
        "Description of the person at the counter": tk.Entry,
        "Is there a boundary?": ttk.Combobox,
        "Boundary types": ttk.Combobox,
        "Do we see the end of line?": ttk.Combobox,
        "If yes, where is the end of the line in the image?": ttk.Combobox,
        "If not, in what direction should you move camera to see the end of the line?": ttk.Combobox,
        "Do we see the start of line?": ttk.Combobox,
        "If yes, where is the start of the line in the image?": ttk.Combobox,
        "If not, in what direction should you move camera to see the start of the line?": ttk.Combobox,
        "Does the image show a full line or partial line?": ttk.Combobox
    }
    options = {
        "Line shape": ["Straight", "Curved", "S-shaped", "Angled","other"],
        "What direction is the line facing": ["Facing towards","Facing away","Facing sideways","other"],
        "Is there a boundary?": ["yes", "no"],
        "Boundary types": ["none", "cones", "rope dividers", "stanchions","other"],
        "Do we see the end of line?": ["yes", "no"],
        "If yes, where is the end of the line in the image?": ["far left", "center left", "center", "center right", "far right","N/A"],
        "If not, in what direction should you move camera to see the end of the line?": ["left", "right","back","N/A"],
        "Do we see the start of line?": ["yes", "no"],
        "If yes, where is the start of the line in the image?": ["far left", "center left", "center", "center right", "far right","N/A"],
        "If not, in what direction should you move camera to see the start of the line?": ["left", "right","back","N/A"],
        "Does the image show a full line or partial line?": ["full", "partial"]
    }
    entries = {}
    for field, widget_type in fields.items():
        row = tk.Frame(root)
        label = tk.Label(row, width=70, text=field, anchor='w')
        if field in options:
            entry = widget_type(row, values=options[field], state="readonly")
            entry.set(options[field][0])
        else:
            entry = widget_type(row)
        row.pack(side=tk.TOP, fill=tk.X, padx=5, pady=5)
        label.pack(side=tk.LEFT)
        entry.pack(side=tk.RIGHT, expand=tk.YES, fill=tk.X)
        entries[field] = entry
    submit_button = tk.Button(root, text="Submit", command=lambda: submit_annotations(entries))
    submit_button.pack(side=tk.BOTTOM, pady=10)
    root.update()
    return root

def draw_line(event, x, y, flags, param):
    global start_point, end_point, drawing, image
    if event == cv2.EVENT_LBUTTONDOWN:
        if start_point is None:
            start_point = (x, y)
            cv2.circle(image, start_point, 5, (255, 0, 0), -1)  # Blue dot
            cv2.imshow("Annotation Tool", image)
        else:
            end_point = (x, y)
            cv2.arrowedLine(image, start_point, end_point, color=(0, 0, 255), thickness=2, line_type=cv2.LINE_AA, tipLength=0.05)
            cv2.imshow("Annotation Tool", image)

            # Directly use the points as they are in original resolution
            annotation["line_coordinates"] = {
                "start": {"x": start_point[0], "y": start_point[1]},
                "end": {"x": end_point[0], "y": end_point[1]}
            }

            print(f"Line coordinates saved: Start - {start_point}, End - {end_point}")

cv2.namedWindow("Annotation Tool", cv2.WINDOW_NORMAL)
cv2.resizeWindow("Annotation Tool", 600, 800)
cv2.setMouseCallback("Annotation Tool", draw_line)
gui = setup_annotation_gui()
cv2.imshow("Annotation Tool", image)
gui.mainloop()
cv2.destroyAllWindows()