Spaces:
Running
Running
File size: 8,777 Bytes
9b6bf86 ce66387 5d30462 9b6bf86 5d30462 f99c6e0 1f78597 aa4569e 26884f2 aa4569e ce66387 9b6bf86 ce66387 9b6bf86 ce66387 d87f99a ce66387 d87f99a ce66387 d87f99a ce66387 9b6bf86 d87f99a 9b6bf86 ce66387 9b6bf86 ce66387 d87f99a e5bb8a3 ce66387 e5bb8a3 9b6bf86 ce66387 d87f99a 9b6bf86 d87f99a 9b6bf86 d87f99a ce66387 9b6bf86 d87f99a ce66387 9b6bf86 d87f99a 9b6bf86 d87f99a ce66387 d87f99a ce66387 d87f99a 9b6bf86 d87f99a ce66387 d87f99a ce66387 d87f99a 9b6bf86 c52f73f ce66387 9b6bf86 ce66387 d87f99a ce66387 e5bb8a3 ce66387 f99c6e0 aa4569e f99c6e0 e5bb8a3 ce66387 e5bb8a3 ce66387 f99c6e0 d87f99a 9b6bf86 ce66387 9b6bf86 |
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 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
import os, random, json
from datetime import datetime
from PIL import Image, ImageOps
import numpy as np
import gradio as gr
from gspread import service_account_from_dict
from huggingface_hub import HfApi, hf_hub_download
# -------- Configuration --------
HF_TOKEN = os.environ["HF_TOKEN"]
api = HfApi(token=HF_TOKEN)
REPO_ID = "HotshotGoku/Images_Test_AI_or_Real"
# List files in the dataset
all_files = api.list_repo_files(
repo_id=REPO_ID,
repo_type="dataset"
)
# Get the AI vs Real folders
ai_remote = [f for f in all_files if f.startswith("AI/")]
real_remote = [f for f in all_files if f.startswith("Real/")]
ai_files = [hf_hub_download(repo_id=REPO_ID, repo_type="dataset",filename=path, token=HF_TOKEN) for path in ai_remote]
real_files = [hf_hub_download(repo_id=REPO_ID, repo_type="dataset",filename=path, token=HF_TOKEN) for path in real_remote]
# Load a sample real image for the demo
real_demo_path= hf_hub_download(repo_id=REPO_ID, repo_type="dataset",filename="Experiment_grid_3x3.png", token=HF_TOKEN)
real_demo = Image.open(real_demo_path).convert("RGB")
real_demo.thumbnail((500, 500), resample=Image.LANCZOS) # now ≤500×500
# 2) Turn it into a numpy array
real_demo_small = np.array(real_demo)
history_file = "history_state.json"
# --------------------------------
# ——— Google Sheets setup ———
# load service‐account JSON from HF secret
info = json.loads(os.environ["JSON_ACCESS"])
# info = json.loads('service_account.json') # for local testing only
gc = service_account_from_dict(info)
# open by key for stability
ws = gc.open_by_key("1lfhomrFnhmRIxQvdJZr-7gASA3sONBT_mblHNreMKvc").sheet1
def record_run(name, session_start, attempt_num, elapsed_sec, familiarity, correct_count, wrong_list):
"""
Append one row with exactly:
Name | StartTime | #Attempt | ElapsedSec | Familiarity | AttemptsList | WrongsList
"""
ws.append_row([
name,
session_start, # when that grid/timer started
attempt_num, # 1, 2, 3, …
elapsed_sec, # seconds for this attempt
familiarity, # slider value
json.dumps([correct_count]), # e.g. [9]
json.dumps(wrong_list) # e.g. ["217_1.png","243_2.png"]
])
def get_new_grid(state=None):
"""
Generate a fresh 4×4 grid:
- Preserve attempt_count
- **Reset** timer_start to "now" whenever the user hits Retry (i.e. state is not None)
- Leave timer_start unset on initial load (so they must click Start or first Fake?)
"""
attempt_count = (state or {}).get("attempt_count", 0)
t = random.randint(4, 12)
sel_ai = random.sample(ai_files, t)
sel_real = random.sample(real_files, 16 - t)
combo = [(p, False) for p in sel_ai] + [(p, True) for p in sel_real]
random.shuffle(combo)
paths, truth = zip(*combo)
# 3) Build thumbnails + reset flags
thumbs = [np.array(Image.open(p).convert("RGB")) for p in paths]
resets = [False] * 16
new_state = {
"paths": paths,
"truth": truth,
"attempt_count": attempt_count , # increment attempt count,
"timer_start": datetime.now().isoformat()
}
return (*thumbs, *resets, new_state)
def evaluate(
sel0, sel1, sel2, sel3,
sel4, sel5, sel6, sel7,
sel8, sel9, sel10, sel11,
sel12, sel13, sel14, sel15,
state,
user_name,
familiarity
):
# 1) Increment the simple count
attempt_count = state.get("attempt_count", 0) + 1
state["attempt_count"] = attempt_count
# 2) Border logic as before...
sels = [sel0, sel1, sel2, sel3, sel4, sel5, sel6, sel7,
sel8, sel9, sel10, sel11, sel12, sel13, sel14, sel15]
bordered, wrong_list = [], []
correct_count = 0
for i, chosen in enumerate(sels):
img = Image.open(state["paths"][i]).convert("RGB")
is_real = state["truth"][i]
correct = chosen == (not is_real)
color = "green" if correct else "red"
if correct:
correct_count += 1
else:
wrong_list.append(os.path.basename(state["paths"][i]))
bordered.append(np.array(ImageOps.expand(img, border=5, fill=color)))
# 3) Timer logic
timer_iso = state.get("timer_start")
elapsed = (datetime.now() - datetime.fromisoformat(timer_iso)).total_seconds() if timer_iso else 0.0
# incremented earlier in evaluate:
attempt_num = state["attempt_count"]
record_run(
user_name, # your textbox input
state["timer_start"], # ISO start time for this grid
attempt_num, # 1, 2, 3, ...
elapsed, # per‐attempt elapsed
familiarity, # slider input
correct_count, # how many correct this try
wrong_list # which files were wrong
)
# 5) Summary text
pct = correct_count / 16 * 100
summary = f"Attempt {attempt_count}: {correct_count}/16 correct ({pct:.1f}%), time {elapsed:.1f}s. \n Retry to improve your score! (The grid of images will refresh )"
return (*bordered, state, summary)
with gr.Blocks(fill_width=True) as demo:
# Terms & Conditions gate
terms_cb = gr.Checkbox(
label="I agree that my game data can be used for downstream analysis purposes.",
value=False
)
# Main UI hidden until terms are accepted
with gr.Column(visible=False) as main_ui:
gr.Markdown("# Identify the Fake \nEnter your name, then play:")
user_name = gr.Textbox(label="Your name", placeholder="e.g. Can be anonymous ex: 'Trisolaris123'")
gr.Markdown("# Instructions: Click the images you think are AI-generated. \nWhen you are done, click 'Submit' to record your results.\nClick 'Retry' to get a new set of images and improve your score (infinite retries). ")
# Familiarity slider (1=first time, 10=expert)
familiarity = gr.Slider(
minimum=1, maximum=10, step=1, value=1,
label="How familiar are you with P. aeruginosa patterns? 1: First time seeing these 10: Have worked with these patterns before",
interactive=True
)
state = gr.State(None)
example_ui = gr.Column(visible=True)
with example_ui:
gr.Markdown("### Before you begin: This are what *Real* Images look like. Click start to begin the game. ")
gr.Image(value=real_demo_small, show_label=False) #.style(
# width=300, # px
# height=300 # px
# ) # set desired display height)
gr.Markdown("---")
# Add a Start button that WILL load images and start the timer
start_btn = gr.Button("Start")
# Now wrap the grid + controls in a hidden Column
with gr.Column(visible=False) as grid_ui:
image_components = []
checkbox_components = []
for row in range(4):
with gr.Row():
for col in range(4):
idx = row * 4 + col
with gr.Column(min_width=200, scale=1):
img = gr.Image(type="numpy", interactive=False, show_label=False)
cb = gr.Checkbox(label="Fake?", elem_id=f"cb_{idx}")
image_components.append(img)
checkbox_components.append(cb)
submit_btn = gr.Button("Submit")
retry_btn = gr.Button("Retry")
score_out = gr.Textbox(label="Score & Time", interactive=False)
retry_btn.click(
fn=get_new_grid,
inputs=[state],
outputs=[*image_components, *checkbox_components, state]
)
submit_btn.click(
fn=evaluate,
inputs=[*checkbox_components, state,user_name, familiarity],
outputs=[*image_components, state,score_out]
)
# Wire start_btn to both load the grid _and_ reveal it
start_btn.click(
fn=get_new_grid,
inputs=[state],
outputs=[*image_components, *checkbox_components, state]
)
start_btn.click(
fn=lambda _: gr.update(visible=True),
inputs=[],
outputs=[grid_ui]
)
start_btn.click(
fn=lambda _: gr.update(visible=False),
inputs=[],
outputs=[example_ui]
)
# Reveal main UI only after agreeing to terms
terms_cb.change(
fn=lambda agreed: gr.update(visible=agreed),
inputs=[terms_cb],
outputs=[main_ui]
)
demo.launch()
|