CarolineM5 commited on
Commit
cef0cfd
·
verified ·
1 Parent(s): 4690a87

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +185 -133
app.py CHANGED
@@ -4,141 +4,193 @@ Created on Mon Apr 7 10:50:35 2025
4
 
5
  @author: camaac
6
  """
7
-
8
- # import streamlit as st
9
- # import os
10
- # from PIL import Image
11
- # import random
12
- # import json
13
-
14
- # st.set_page_config(page_title="Test perceptuel bois IA", layout="centered")
15
-
16
- # st.title("Test perceptuel : IA ou réel ?")
17
-
18
- # st.markdown("""
19
- # Vous allez voir **deux images de surface de bois**.
20
- # Votre mission :
21
- # - Choisissez **celle qui semble la plus réaliste** (meilleure qualité visuelle).
22
- # - Dites ensuite si vous pensez que l'image la plus réaliste est **générée par IA** ou **réelle**.
23
- # """)
24
-
25
- # image_folder = "images"
26
- # result_file = "results.json"
27
-
28
- # if not os.path.exists(image_folder):
29
- # st.error("Dossier d'images introuvable.")
30
- # st.stop()
31
-
32
- # # Trouver toutes les paires dispo
33
- # all_pairs = sorted(set(f.split("_")[1] for f in os.listdir(image_folder) if f.endswith(".png")))
34
- # random.shuffle(all_pairs)
35
-
36
- # # Afficher une seule paire par session utilisateur
37
- # if "current_index" not in st.session_state:
38
- # st.session_state.current_index = 0
39
- # if st.session_state.current_index >= len(all_pairs):
40
- # st.success("Merci ! Vous avez terminé toutes les paires d'images ")
41
- # st.stop()
42
-
43
- # pair_id = all_pairs[st.session_state.current_index]
44
- # img_a_path = os.path.join(image_folder, f"img_{pair_id}_a.png")
45
- # img_b_path = os.path.join(image_folder, f"img_{pair_id}_b.png")
46
-
47
- # # Mélanger l'ordre
48
- # order = ["a", "b"]
49
- # random.shuffle(order)
50
-
51
- # cols = st.columns(2)
52
- # for i, col in enumerate(cols):
53
- # img_path = os.path.join(image_folder, f"img_{pair_id}_{order[i]}.png")
54
- # with col:
55
- # st.image(Image.open(img_path), caption=f"Image {i+1}")
56
-
57
- # # Choix utilisateur
58
- # choice = st.radio("Quelle image est la plus réaliste ?", ["Image 1", "Image 2"])
59
- # is_real = st.radio("L'image choisie est-elle réelle ou générée par IA ?", ["Réelle", "IA"])
60
- # submit = st.button("Soumettre")
61
-
62
- # if submit:
63
- # # Enregistrer le résultat
64
- # data = {
65
- # "pair_id": pair_id,
66
- # "image1": f"img_{pair_id}_{order[0]}.png",
67
- # "image2": f"img_{pair_id}_{order[1]}.png",
68
- # "chosen": choice,
69
- # "user_thinks": is_real
70
- # }
71
- # if os.path.exists(result_file):
72
- # with open(result_file, "r") as f:
73
- # results = json.load(f)
74
- # else:
75
- # results = []
76
-
77
- # results.append(data)
78
- # with open(result_file, "w") as f:
79
- # json.dump(results, f, indent=2)
80
-
81
- # st.success("Merci ! Réponse enregistrée.")
82
- # st.session_state.current_index += 1
83
- # st.experimental_rerun()
84
-
85
-
86
-
87
  import streamlit as st
88
  import os
89
  import random
 
 
 
90
  from PIL import Image
91
 
92
- # Titre de l'app
93
- st.title("Test perceptuel : image réelle ou générée ?")
94
-
95
- # Récupération des fichiers
96
- image_dir = "images"
97
- gt_images = sorted([f for f in os.listdir(image_dir) if f.endswith(".png") and "_gen" not in f])
98
-
99
- # Index courant
100
- index = st.session_state.get("index", 0)
101
-
102
- if index >= len(gt_images):
103
- st.success("Merci ! Vous avez terminé l'évaluation.")
104
- else:
105
- # Fichiers pour l'image courante
106
- gt_file = gt_images[index]
107
- base_name = gt_file.replace(".png", "")
108
- gen_file = base_name + "_gen0.png"
109
-
110
- gt_path = os.path.join(image_dir, gt_file)
111
- gen_path = os.path.join(image_dir, gen_file)
112
-
113
- try:
114
- img_gt = Image.open(gt_path)
115
- img_gen = Image.open(gen_path)
116
-
117
- # Mélanger l'ordre des images
118
- images = [("Réelle", img_gt), ("Générée", img_gen)]
119
- random.shuffle(images)
120
-
121
- # Affichage
122
- st.write(f"Image {index + 1} sur {len(gt_images)}")
123
- cols = st.columns(2)
124
- for i, (label, img) in enumerate(images):
125
- with cols[i]:
126
- st.image(img, caption=f"Image {i + 1}", use_column_width=True)
127
-
128
- choice = st.radio(
129
- "Selon vous, laquelle est l'image réelle ?",
130
- options=["Image 1", "Image 2"],
131
- key=f"choice_{index}"
132
- )
133
-
134
- if st.button("Valider"):
135
- # Sauvegarde des résultats (à adapter si tu veux un fichier ou DB)
136
- correct = images[int(choice[-1]) - 1][0] == "Réelle"
137
- st.session_state[f"result_{index}"] = {"choice": choice, "correct": correct}
138
-
139
- # Passer à la suivante
140
- st.session_state["index"] = index + 1
141
- st.rerun()
142
-
143
- except Exception as e:
144
- st.error(f"Erreur lors du chargement des images : {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  @author: camaac
6
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  import streamlit as st
8
  import os
9
  import random
10
+ import pandas as pd
11
+ import base64
12
+ from io import BytesIO
13
  from PIL import Image
14
 
15
+ # --- Global parameters ---
16
+ IMAGE_DIR = "images" # Dossier contenant les images.
17
+ # Naming convention: ground truth image: "00001.png", generated image: "00001_gen0.png"
18
+ NUM_PAIRS = 50 # Nombre de paires à évaluer.
19
+ RESULTS_FILE = "results.csv" # Fichier où sauvegarder les résultats.
20
+
21
+ # --- Fonctions utilitaires ---
22
+
23
+ def load_image_pair(index):
24
+ """Retourne le chemin de la ground truth et du generated pour un index donné.
25
+ Les index sont des entiers convertis en chaînes à 5 chiffres.
26
+ """
27
+ idx_str = str(index).zfill(5)
28
+ gt_path = os.path.join(IMAGE_DIR, f"{idx_str}.png")
29
+ pred_path = os.path.join(IMAGE_DIR, f"{idx_str}_gen0.png")
30
+ return gt_path, pred_path
31
+
32
+ def load_and_open_image(path):
33
+ """Charge l'image depuis le chemin et retourne un objet PIL.Image."""
34
+ return Image.open(path)
35
+
36
+ def get_shuffled_pair(index):
37
+ """Charge la paire d'images, puis renvoie une liste contenant tuples (label, image)
38
+ dans un ordre aléatoire. Le label est "GT" pour ground truth et "Pred" pour generated.
39
+ """
40
+ gt_path, pred_path = load_image_pair(index)
41
+ img_gt = load_and_open_image(gt_path)
42
+ img_pred = load_and_open_image(pred_path)
43
+ pair = [("GT", img_gt), ("Pred", img_pred)]
44
+ random.shuffle(pair)
45
+ return pair
46
+
47
+ def image_to_base64(image, width=300):
48
+ """Convertit une image PIL en code base64, pour l'inclure dans du HTML."""
49
+ buffered = BytesIO()
50
+ image.save(buffered, format="PNG")
51
+ img_str = base64.b64encode(buffered.getvalue()).decode()
52
+ html_code = f'<a href="?selected={{}}"><img src="data:image/png;base64,{img_str}" width="{width}"></a>'
53
+ return html_code
54
+
55
+ # --- Gestion de la navigation entre pages via st.session_state ---
56
+
57
+ if "page" not in st.session_state:
58
+ st.session_state.page = "intro"
59
+ if "user_name" not in st.session_state:
60
+ st.session_state.user_name = ""
61
+ if "current_index" not in st.session_state:
62
+ st.session_state.current_index = 1
63
+ if "results" not in st.session_state:
64
+ st.session_state.results = []
65
+ if "pair_order" not in st.session_state:
66
+ st.session_state.pair_order = {}
67
+
68
+ # --- Page d'introduction ---
69
+ if st.session_state.page == "intro":
70
+ st.title("Wood Surface Evaluation Study")
71
+ st.markdown("""
72
+ **Welcome!**
73
+
74
+ In this study, you will be shown pairs of wood surface images.
75
+ One image is a real photograph (Ground Truth) and the other is generated by AI.
76
+ Your task is to select, by clicking on the image, the one you believe is **real**.
77
+
78
+ Please enter your name below and click "Start Evaluation" to begin.
79
+ """)
80
+ name = st.text_input("Enter your name:")
81
+ if st.button("Start Evaluation") and name:
82
+ st.session_state.user_name = name
83
+ st.session_state.page = "evaluation"
84
+ st.experimental_rerun()
85
+ st.stop()
86
+
87
+ # --- Page d'évaluation ---
88
+ if st.session_state.page == "evaluation":
89
+ st.title("Wood Surface Evaluation")
90
+ st.write(f"User: **{st.session_state.user_name}**")
91
+
92
+ if st.session_state.current_index > NUM_PAIRS:
93
+ st.success("Thank you for completing the evaluation!")
94
+ # Exporter les résultats sous forme de CSV
95
+ results_df = pd.DataFrame(st.session_state.results)
96
+ results_df.to_csv(RESULTS_FILE, index=False)
97
+ st.write("Results saved in:", RESULTS_FILE)
98
+ st.stop()
99
+
100
+ st.write(f"Image Pair {st.session_state.current_index} of {NUM_PAIRS}")
101
+
102
+ # Charger et mélanger la paire pour l'index courant
103
+ pair = get_shuffled_pair(st.session_state.current_index)
104
+ st.session_state.pair_order[st.session_state.current_index] = [label for label, _ in pair]
105
+
106
+ # Afficher les deux images dans deux colonnes, en les rendant cliquables via HTML
107
+ col1, col2 = st.columns(2)
108
+ with col1:
109
+ # On prépare le HTML avec un placeholder pour la clé "1"
110
+ img_html = image_to_base64(pair[0][1])
111
+ # On injecte le code HTML en remplaçant {} par "1"
112
+ st.markdown(img_html.format("1"), unsafe_allow_html=True)
113
+ st.caption("Image 1")
114
+ with col2:
115
+ img_html = image_to_base64(pair[1][1])
116
+ st.markdown(img_html.format("2"), unsafe_allow_html=True)
117
+ st.caption("Image 2")
118
+
119
+ st.markdown("**Click on the image you believe is real.**")
120
+
121
+ # Récupérer les paramètres de la requête
122
+ query_params = st.experimental_get_query_params()
123
+ if "selected" in query_params:
124
+ selected = query_params["selected"][0] # "1" ou "2"
125
+ selected_label = pair[int(selected) - 1][0] # "GT" ou "Pred"
126
+ st.write(f"You selected: **Image {selected}** (label: **{selected_label}**)")
127
+ # Enregistrer le résultat pour cette paire
128
+ st.session_state.results.append({
129
+ "pair_index": st.session_state.current_index,
130
+ "pair_order": st.session_state.pair_order[st.session_state.current_index],
131
+ "selected": selected_label,
132
+ })
133
+ # Nettoyer les query params pour éviter la sélection persistante
134
+ st.experimental_set_query_params()
135
+ # Passer à la paire suivante
136
+ st.session_state.current_index += 1
137
+ st.rerun()
138
+
139
+ # import streamlit as st
140
+ # import os
141
+ # import random
142
+ # from PIL import Image
143
+
144
+ # # Titre de l'app
145
+ # st.title("Test perceptuel : image réelle ou générée ?")
146
+
147
+ # # Récupération des fichiers
148
+ # image_dir = "images"
149
+ # gt_images = sorted([f for f in os.listdir(image_dir) if f.endswith(".png") and "_gen" not in f])
150
+
151
+ # # Index courant
152
+ # index = st.session_state.get("index", 0)
153
+
154
+ # if index >= len(gt_images):
155
+ # st.success("Merci ! Vous avez terminé l'évaluation.")
156
+ # else:
157
+ # # Fichiers pour l'image courante
158
+ # gt_file = gt_images[index]
159
+ # base_name = gt_file.replace(".png", "")
160
+ # gen_file = base_name + "_gen0.png"
161
+
162
+ # gt_path = os.path.join(image_dir, gt_file)
163
+ # gen_path = os.path.join(image_dir, gen_file)
164
+
165
+ # try:
166
+ # img_gt = Image.open(gt_path)
167
+ # img_gen = Image.open(gen_path)
168
+
169
+ # # Mélanger l'ordre des images
170
+ # images = [("Réelle", img_gt), ("Générée", img_gen)]
171
+ # random.shuffle(images)
172
+
173
+ # # Affichage
174
+ # st.write(f"Image {index + 1} sur {len(gt_images)}")
175
+ # cols = st.columns(2)
176
+ # for i, (label, img) in enumerate(images):
177
+ # with cols[i]:
178
+ # st.image(img, caption=f"Image {i + 1}", use_column_width=True)
179
+
180
+ # choice = st.radio(
181
+ # "Selon vous, laquelle est l'image réelle ?",
182
+ # options=["Image 1", "Image 2"],
183
+ # key=f"choice_{index}"
184
+ # )
185
+
186
+ # if st.button("Valider"):
187
+ # # Sauvegarde des résultats (à adapter si tu veux un fichier ou DB)
188
+ # correct = images[int(choice[-1]) - 1][0] == "Réelle"
189
+ # st.session_state[f"result_{index}"] = {"choice": choice, "correct": correct}
190
+
191
+ # # Passer à la suivante
192
+ # st.session_state["index"] = index + 1
193
+ # st.rerun()
194
+
195
+ # except Exception as e:
196
+ # st.error(f"Erreur lors du chargement des images : {e}")