Spaces:
Running
Running
Commit
·
9b6bf86
1
Parent(s):
b0315a6
initial_test
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- app.py +167 -0
- images/AI/196_1.png +0 -0
- images/AI/196_2.png +0 -0
- images/AI/197_1.png +0 -0
- images/AI/197_2.png +0 -0
- images/AI/198_1.png +0 -0
- images/AI/198_2.png +0 -0
- images/AI/199_1.png +0 -0
- images/AI/199_2.png +0 -0
- images/AI/200_1.png +0 -0
- images/AI/200_2.png +0 -0
- images/AI/201_1.png +0 -0
- images/AI/201_2.png +0 -0
- images/AI/202_1.png +0 -0
- images/AI/202_2.png +0 -0
- images/AI/203_1.png +0 -0
- images/AI/203_2.png +0 -0
- images/AI/204_1.png +0 -0
- images/AI/204_2.png +0 -0
- images/AI/205_1.png +0 -0
- images/AI/205_2.png +0 -0
- images/AI/207_1.png +0 -0
- images/AI/207_2.png +0 -0
- images/AI/208_1.png +0 -0
- images/AI/208_2.png +0 -0
- images/AI/210_1.png +0 -0
- images/AI/210_2.png +0 -0
- images/AI/211_1.png +0 -0
- images/AI/211_2.png +0 -0
- images/AI/212_1.png +0 -0
- images/AI/212_2.png +0 -0
- images/AI/214_1.png +0 -0
- images/AI/214_2.png +0 -0
- images/AI/215_1.png +0 -0
- images/AI/215_2.png +0 -0
- images/AI/217_1.png +0 -0
- images/AI/217_2.png +0 -0
- images/AI/218_1.png +0 -0
- images/AI/218_2.png +0 -0
- images/AI/221_1.png +0 -0
- images/AI/221_2.png +0 -0
- images/AI/222_1.png +0 -0
- images/AI/222_2.png +0 -0
- images/AI/223_1.png +0 -0
- images/AI/223_2.png +0 -0
- images/AI/224_1.png +0 -0
- images/AI/224_2.png +0 -0
- images/AI/226_1.png +0 -0
- images/AI/226_2.png +0 -0
- images/AI/227_1.png +0 -0
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
|