HotshotGoku commited on
Commit
9b6bf86
·
1 Parent(s): b0315a6

initial_test

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
app.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, random, json
2
+ from datetime import datetime
3
+ from PIL import Image, ImageOps
4
+ import numpy as np
5
+ import gradio as gr
6
+
7
+ # -------- Configuration --------
8
+ folder_ai = "/images/ai"
9
+ folder_real = "/images/real"
10
+ now = datetime.now()
11
+ history_file = now.strftime("history_state_%Y-%m-%d_%H-%M-%S.json")
12
+ # --------------------------------
13
+
14
+ def load_history():
15
+ if os.path.exists(history_file):
16
+ with open(history_file, "r") as f:
17
+ return json.load(f)
18
+ return {"corrects": [], "wrongs": [], "attempts": [], "times": []}
19
+
20
+ def save_history(hist):
21
+ with open(history_file, "w") as f:
22
+ json.dump(hist, f)
23
+
24
+ def get_new_grid(state=None):
25
+ """
26
+ - Called on first load and on Refresh Grid.
27
+ - If state is None or doesn't have 'session_start', set session_start = now.
28
+ - Otherwise, preserve session_start.
29
+ - Always shuffle 16 images (4–12 AI + rest real) and return thumbs, resets, updated state.
30
+ """
31
+ ai_files = [
32
+ os.path.join(folder_ai, f)
33
+ for f in os.listdir(folder_ai)
34
+ if f.lower().endswith((".png", ".tif", ".tiff"))
35
+ ]
36
+ real_files = [
37
+ os.path.join(folder_real, f)
38
+ for f in os.listdir(folder_real)
39
+ if f.lower().endswith((".png", ".tif", ".tiff"))
40
+ ]
41
+ t = random.randint(4, 12) # between 4 and 12 AI images
42
+ sel_ai = random.sample(ai_files, t)
43
+ sel_real = random.sample(real_files, 16 - t)
44
+ combined = [(p, False) for p in sel_ai] + [(p, True) for p in sel_real]
45
+ random.shuffle(combined)
46
+ paths = [p for p, _ in combined]
47
+ truth = [lbl for _, lbl in combined]
48
+ thumbs = [np.array(Image.open(p).convert("RGB")) for p in paths]
49
+
50
+ # Set or preserve session_start
51
+ if (state is None) or ("session_start" not in state):
52
+ session_start = datetime.now().isoformat()
53
+ else:
54
+ session_start = state["session_start"]
55
+
56
+ new_state = {"paths": paths, "truth": truth, "session_start": session_start}
57
+ resets = [False] * 16
58
+ return (*thumbs, *resets, new_state)
59
+
60
+ def evaluate(
61
+ sel0, sel1, sel2, sel3,
62
+ sel4, sel5, sel6, sel7,
63
+ sel8, sel9, sel10, sel11,
64
+ sel12, sel13, sel14, sel15,
65
+ state
66
+ ):
67
+ """
68
+ Compare each of the 16 checkbox selections to truth.
69
+ Update history JSON with correct count, wrong filenames, and attempt number.
70
+ Return 16 bordered images + unchanged state.
71
+ """
72
+ sels = [
73
+ sel0, sel1, sel2, sel3,
74
+ sel4, sel5, sel6, sel7,
75
+ sel8, sel9, sel10, sel11,
76
+ sel12, sel13, sel14, sel15
77
+ ]
78
+ paths = state["paths"]
79
+ truth = state["truth"]
80
+ bordered, wrong_list, correct_count = [], [], 0
81
+
82
+ for i, chosen in enumerate(sels):
83
+ img = Image.open(paths[i]).convert("RGB")
84
+ is_real = truth[i]
85
+ if chosen == is_real:
86
+ color, correct_count = "green", correct_count + 1
87
+ else:
88
+ wrong_list.append(os.path.basename(paths[i]))
89
+ color = "red"
90
+ bordered.append(np.array(ImageOps.expand(img, border=5, fill=color)))
91
+
92
+ hist = load_history()
93
+ attempt_no = len(hist["attempts"]) + 1
94
+ hist["corrects"].append(correct_count)
95
+ hist["wrongs"].append(wrong_list)
96
+ hist["attempts"].append(attempt_no)
97
+ save_history(hist)
98
+
99
+ return (*bordered, state)
100
+
101
+ def done_now(state):
102
+ """
103
+ Compute total time from the very first grid load (session_start) until now.
104
+ Append that elapsed to history JSON and return a friendly message.
105
+ """
106
+ start = datetime.fromisoformat(state["session_start"])
107
+ elapsed = (datetime.now() - start).total_seconds()
108
+ minutes = int(elapsed // 60)
109
+ seconds = int(elapsed % 60)
110
+
111
+ hist = load_history()
112
+ hist["times"].append(elapsed)
113
+ save_history(hist)
114
+
115
+ return f"Total time spent on the task: {minutes} minutes {seconds} seconds"
116
+
117
+ with gr.Blocks() as demo:
118
+ gr.Markdown(
119
+ "## Real vs AI (4×4 Grid)\n"
120
+ "Click **Refresh Grid** whenever you want a new mix (4–12 AI images). "
121
+ "Your timer starts as soon as you first see the grid, and stops when you click “I am done now.”\n"
122
+ "Tick “Real?” under each thumbnail and click **Submit** to get feedback."
123
+ )
124
+
125
+ state = gr.State(None)
126
+ image_components = []
127
+ checkbox_components = []
128
+ for row in range(4):
129
+ with gr.Row():
130
+ for col in range(4):
131
+ idx = row * 4 + col
132
+ with gr.Column():
133
+ img = gr.Image(type="numpy", interactive=False, show_label=False)
134
+ cb = gr.Checkbox(label="Real?", elem_id=f"cb_{idx}")
135
+ image_components.append(img)
136
+ checkbox_components.append(cb)
137
+
138
+ submit_btn = gr.Button("Submit")
139
+ refresh_btn = gr.Button("Refresh Grid")
140
+ done_btn = gr.Button("I am done now")
141
+ done_out = gr.Textbox(interactive=False)
142
+
143
+ # On first load or when Refresh is clicked: generate new grid + reset checkboxes
144
+ demo.load(
145
+ fn=get_new_grid,
146
+ outputs=[*image_components, *checkbox_components, state]
147
+ )
148
+ refresh_btn.click(
149
+ fn=get_new_grid,
150
+ outputs=[*image_components, *checkbox_components, state]
151
+ )
152
+
153
+ # On Submit: evaluate selections (session_start remains intact)
154
+ submit_btn.click(
155
+ fn=evaluate,
156
+ inputs=[*checkbox_components, state],
157
+ outputs=[*image_components, state]
158
+ )
159
+
160
+ # On “I am done now”: calculate and display total elapsed time
161
+ done_btn.click(
162
+ fn=done_now,
163
+ inputs=[state],
164
+ outputs=[done_out]
165
+ )
166
+
167
+ demo.launch()
images/AI/196_1.png ADDED
images/AI/196_2.png ADDED
images/AI/197_1.png ADDED
images/AI/197_2.png ADDED
images/AI/198_1.png ADDED
images/AI/198_2.png ADDED
images/AI/199_1.png ADDED
images/AI/199_2.png ADDED
images/AI/200_1.png ADDED
images/AI/200_2.png ADDED
images/AI/201_1.png ADDED
images/AI/201_2.png ADDED
images/AI/202_1.png ADDED
images/AI/202_2.png ADDED
images/AI/203_1.png ADDED
images/AI/203_2.png ADDED
images/AI/204_1.png ADDED
images/AI/204_2.png ADDED
images/AI/205_1.png ADDED
images/AI/205_2.png ADDED
images/AI/207_1.png ADDED
images/AI/207_2.png ADDED
images/AI/208_1.png ADDED
images/AI/208_2.png ADDED
images/AI/210_1.png ADDED
images/AI/210_2.png ADDED
images/AI/211_1.png ADDED
images/AI/211_2.png ADDED
images/AI/212_1.png ADDED
images/AI/212_2.png ADDED
images/AI/214_1.png ADDED
images/AI/214_2.png ADDED
images/AI/215_1.png ADDED
images/AI/215_2.png ADDED
images/AI/217_1.png ADDED
images/AI/217_2.png ADDED
images/AI/218_1.png ADDED
images/AI/218_2.png ADDED
images/AI/221_1.png ADDED
images/AI/221_2.png ADDED
images/AI/222_1.png ADDED
images/AI/222_2.png ADDED
images/AI/223_1.png ADDED
images/AI/223_2.png ADDED
images/AI/224_1.png ADDED
images/AI/224_2.png ADDED
images/AI/226_1.png ADDED
images/AI/226_2.png ADDED
images/AI/227_1.png ADDED