File size: 27,250 Bytes
d63a8cc
 
 
 
 
 
 
 
62ec819
d63a8cc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6280e83
d63a8cc
 
 
 
 
0d48712
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4ad82f1
0d48712
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d63a8cc
 
0d48712
 
 
 
 
2a2df0c
0d48712
 
 
 
 
d63a8cc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0d48712
 
8e9af33
0d48712
 
8e9af33
0d48712
 
 
 
6280e83
8e9af33
 
0d48712
 
d63a8cc
 
 
 
2a2df0c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4ad82f1
8e9af33
761fe44
d63a8cc
4ad82f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0d48712
 
 
 
4ad82f1
0d48712
6280e83
 
 
 
 
 
 
 
4ad82f1
 
0d48712
 
4ad82f1
0d48712
6280e83
 
 
 
 
 
4ad82f1
 
0d48712
 
4ad82f1
0d48712
6280e83
 
 
 
 
 
4ad82f1
 
0d48712
 
4ad82f1
0d48712
6280e83
 
 
 
 
 
d63a8cc
 
4ad82f1
d63a8cc
6280e83
 
 
 
4ad82f1
 
6280e83
 
 
 
4ad82f1
 
 
 
 
 
 
 
6280e83
 
d63a8cc
6280e83
 
 
 
 
 
 
 
 
 
 
 
 
4ad82f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6280e83
 
 
d63a8cc
4ad82f1
d63a8cc
 
 
4ad82f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d63a8cc
 
4ad82f1
0d48712
 
 
4ad82f1
 
0d48712
4ad82f1
 
6280e83
 
 
 
 
 
d63a8cc
4ad82f1
d63a8cc
 
 
4ad82f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d63a8cc
4ad82f1
 
0d48712
4ad82f1
 
0d48712
4ad82f1
 
6280e83
 
 
 
 
 
d63a8cc
4ad82f1
d63a8cc
 
 
4ad82f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0d48712
 
4ad82f1
 
0d48712
4ad82f1
 
6280e83
 
 
 
 
 
 
 
d63a8cc
 
6280e83
8e9af33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0d48712
43dda14
 
 
1f58921
 
 
 
43dda14
 
1f58921
 
 
 
 
43dda14
1f58921
 
 
43dda14
1f58921
62ec819
1f58921
 
 
 
 
 
 
62ec819
1f58921
 
 
62ec819
1f58921
43dda14
1f58921
 
 
62ec819
1f58921
 
 
 
 
62ec819
1f58921
 
62ec819
1f58921
 
 
43dda14
1f58921
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62ec819
43dda14
 
 
 
 
 
 
1f58921
43dda14
 
 
1f58921
43dda14
 
8e9af33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d61fa7f
761fe44
8e9af33
 
 
 
 
761fe44
 
8e9af33
 
 
 
 
 
43dda14
1f58921
d63a8cc
 
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
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
import streamlit as st
import cv2
import numpy as np
from PIL import Image
from io import BytesIO
import barcode
from barcode.writer import ImageWriter
import qrcode
import tempfile

def image_to_bytes(img):
    pil_image = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    buffer = BytesIO()
    pil_image.save(buffer, format="PNG")
    return buffer.getvalue()

def generate_barcode(link):
    code128 = barcode.get_barcode_class('code128')
    barcode_image = code128(link, writer=ImageWriter())
    buffer = BytesIO()
    barcode_image.write(buffer)
    return Image.open(buffer)

def generate_qrcode(link):
    qr = qrcode.QRCode(
        version=2,  
        error_correction=qrcode.constants.ERROR_CORRECT_L,  
        box_size=4,  
        border=2,    
    )
    qr.add_data(link)
    qr.make(fit=True)
    qr_image = qr.make_image(fill_color="black", back_color="white")

    small_qr_image = qr_image.resize((512, 512), Image.Resampling.LANCZOS)

    buffer = BytesIO()
    small_qr_image.save(buffer, format="PNG")
    return Image.open(buffer)

def add_custom_css():
    css = """
    <style>
        body {
            background: linear-gradient(135deg, #a8dadc, #f1faee);
            color: #1d3557;
            font-family: 'Arial', sans-serif;
            animation: backgroundAnimation 10s infinite alternate;
        }

        @keyframes backgroundAnimation {
            0% {
                background: linear-gradient(135deg, #a8dadc, #f1faee);
            }
            100% {
                background: linear-gradient(135deg, #f1faee, #457b9d);
            }
        }

        .stButton>button {
            background-color: #457b9d;
            color: white;
            border-radius: 5px;
            transition: transform 0.3s, background-color 0.3s;
            box-shadow: 2px 2px 6px rgba(0,0,0,0.2);
        }

        .stButton>button:hover {
            transform: scale(1.1);
            background-color: #1d3557;
        }

        .stSidebar {
            background: linear-gradient(to bottom, #87CEEB, #FFFFFF);
            color: white;
            font-size: 16px;
        }

        .stImage {
            animation: fadeIn 2s ease-in-out;
        }

        @keyframes fadeIn {
            0% {
                opacity: 0;
            }
            100% {
                opacity: 1;
            }
        }

        header, footer {
            background: #457b9d;
            color: white;
        }

        .stMarkdown {
            animation: slideIn 1s ease-out;
        }

        @keyframes slideIn {
            0% {
                transform: translateY(-20px);
                opacity: 0;
            }
            100% {
                transform: translateY(0);
                opacity: 1;
            }
        }
    </style>
    """
    st.markdown(css, unsafe_allow_html=True)

def add_custom_js():
    js = """
    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const elements = document.querySelectorAll('.stButton>button');
            elements.forEach(button => {
                button.addEventListener('click', () => {
                    button.style.backgroundColor = '#a8dadc';
                    button.style.transform = 'rotate(360deg)';
                    setTimeout(() => button.style.transform = 'rotate(0deg)', 300);
                });
            });
        });
    </script>
    """
    st.markdown(js, unsafe_allow_html=True)

def main():
    st.set_page_config(page_title="ADS VISOR - Un autre regard", layout="wide")

    add_custom_css()
    add_custom_js()


    logo_path = "logo.jpg"  
    logo = Image.open(logo_path)
    st.image(logo, width=150, caption="ADS VISOR")

    st.title("ADS VISOR - Un autre regard")

    st.sidebar.header("Chargement de l'image")
    if "default_image" not in st.session_state:
        st.session_state["default_image"] = None

    uploaded_file = st.sidebar.file_uploader("Charge une image", type=["png", "jpg", "jpeg"])
    if uploaded_file is not None:
        image = Image.open(uploaded_file)
        st.session_state["default_image"] = np.array(image)
        st.sidebar.image(image, caption="Image par défaut", use_container_width=True)

    if st.session_state["default_image"] is None:
        st.sidebar.warning("Veuillez charger une image pour commencer.")
        return

    st.sidebar.header("Fonctionnalités")
    menu_option = st.sidebar.selectbox(
        "Choisissez une fonctionnalité",
        ["Accueil", "Niveaux de couleurs", "Cropping", "Rotation", "Floutage", "Contours", "Génération de Code-barres et QR Code", "Détection Faciale", "À propos de nous"],
        format_func=lambda x: {
            "Accueil": "🏠 Accueil",
            "Niveaux de couleurs": "🖼️ Niveaux de couleurs",
            "Cropping": "✂️ Cropping",
            "Rotation": "🔄 Rotation",
            "Floutage": "🌫️ Floutage",
            "Contours": "🔍 Contours",
            "Génération de Code-barres et QR Code": "📇 Codes numériques",
            "Détection Faciale": "🙂 Détection Faciale",
            "À propos de nous": "👨‍💻 À propos de nous"
        }.get(x, x)
    )

    image_np = st.session_state["default_image"]

    if menu_option == "Accueil":
        st.header("Bienvenue sur ADS VISOR")
        st.markdown(
            """
            <div class="stMarkdown">
                <h2>ADS VISOR est une application innovante pour analyser, transformer et explorer vos images. 🖼️✨</h2>
                <p>Que vous soyez un professionnel ou un passionné, découvrez un large éventail de fonctionnalités interactives !</p>
                <ul>
                    <li><b>Transformations d'image :</b> Couleurs, niveaux de gris, etc.</li>
                    <li><b>Découpage & Rotation :</b> Ajustez vos images à la perfection.</li>
                    <li><b>Détection Faciale :</b> Identifiez les visages automatiquement.</li>
                    <li><b>Codes-barres & QR Codes :</b> Génération rapide pour vos projets.</li>
                </ul>
            </div>
            """,
            unsafe_allow_html=True
        )

    # Niveaux de couleurs
    elif menu_option == "Niveaux de couleurs":
        st.subheader("Niveaux de couleurs")

        # Instructions générales sur les niveaux de couleurs
        st.markdown("""
        ### Légende : Fonctionnement des niveaux de couleurs
        - **Les niveaux de couleurs** permettent de manipuler les différentes composantes d'une image : **Rouge**, **Vert**, **Bleu**.
        - L'édition des canaux colorimétriques permet de visualiser une image en mettant en valeur une couleur spécifique.
        
        ### Options disponibles :
        - **Niveaux de Gris** : Convertit l'image en une seule nuance de gris, supprimant les informations de couleur.
        - **Rouge** : Filtre l'image pour ne conserver que la composante rouge.
        - **Vert** : Filtre l'image pour ne conserver que la composante verte.
        - **Jaune** : Combine les composantes rouge et verte pour donner une teinte jaune.

        ### Exemple :
        - Si vous choisissez l'option **Rouge**, vous obtiendrez une image où seules les nuances rouges sont visibles, les autres couleurs étant supprimées.
        """)

        # Création des onglets pour afficher les images dans différentes couleurs
        tab1, tab2, tab3, tab4 = st.tabs([
            "Gris 🖤", "Rouge ❤️", "Vert 💚", "Jaune 💛"
        ])

        # Onglet 1 : Gris
        with tab1:
            gray_image = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)
            st.image(gray_image, caption="Image en Niveaux de Gris", use_container_width=True)
            st.download_button(
                label="Télécharger l'image en gris",
                data=image_to_bytes(gray_image),
                file_name="image_gris.png",
                mime="image/png"
            )

        # Onglet 2 : Rouge
        with tab2:
            red = image_np.copy()
            red[:, :, 1:] = 0  # On met les canaux vert et bleu à zéro
            st.image(red, caption="Image Rouge", use_container_width=True)
            st.download_button(
                label="Télécharger l'image rouge",
                data=image_to_bytes(red),
                file_name="image_rouge.png",
                mime="image/png"
            )

        # Onglet 3 : Vert
        with tab3:
            green = image_np.copy()
            green[:, :, [0, 2]] = 0  # On met les canaux rouge et bleu à zéro
            st.image(green, caption="Image Verte", use_container_width=True)
            st.download_button(
                label="Télécharger l'image verte",
                data=image_to_bytes(green),
                file_name="image_verte.png",
                mime="image/png"
            )

        # Onglet 4 : Jaune
        with tab4:
            yellow = image_np.copy()
            yellow[:, :, 0] = 0  # On supprime la composante bleue
            st.image(yellow, caption="Image Jaune", use_container_width=True)
            st.download_button(
                label="Télécharger l'image jaune",
                data=image_to_bytes(yellow),
                file_name="image_jaune.png",
                mime="image/png"
            )

    elif menu_option == "Cropping":
        st.subheader("Cropping - Recadrage d'Image")

        # Explications pour les paramètres
        st.markdown(
            """
            ### Légende : Fonctionnement du recadrage
            Le recadrage d'une image consiste à extraire une portion rectangulaire de celle-ci. Pour cela, nous définissons les coordonnées des coins du rectangle :

            - **`x1` (Coordonnée x du coin supérieur gauche)** : Position horizontale du début du rectangle (0 ≤ `x1` < largeur-1).
            - **`y1` (Coordonnée y du coin supérieur gauche)** : Position verticale du début du rectangle (0 ≤ `y1` < hauteur-1).
            - **`x2` (Coordonnée x du coin inférieur droit)** : Position horizontale de la fin du rectangle (1 ≤ `x2` ≤ largeur).
            - **`y2` (Coordonnée y du coin inférieur droit)** : Position verticale de la fin du rectangle (1 ≤ `y2` ≤ hauteur).

            ### Exemple illustratif :
            Imaginons que vous avez une image de 300x300 pixels. Si vous entrez `x1=50`, `y1=50`, `x2=200`, et `y2=200`, l'image sera recadrée en un rectangle de taille 150x150 pixels, commençant à partir du pixel (50, 50) jusqu'à (200, 200).

            ### Étapes :
            1. Saisissez les coordonnées du rectangle que vous souhaitez extraire.
            2. Vous verrez une prévisualisation de la zone sélectionnée avant de la confirmer.
            3. Téléchargez l'image recadrée.
            """
        )

        # Entrée des coordonnées
        try:
            x1 = st.number_input("x1 (Coordonnée x du coin supérieur gauche)", 0, image_np.shape[1] - 1, step=1)
            y1 = st.number_input("y1 (Coordonnée y du coin supérieur gauche)", 0, image_np.shape[0] - 1, step=1)
            x2 = st.number_input("x2 (Coordonnée x du coin inférieur droit)", 1, image_np.shape[1], step=1)
            y2 = st.number_input("y2 (Coordonnée y du coin inférieur droit)", 1, image_np.shape[0], step=1)

            # Validation des coordonnées
            if x1 >= x2:
                st.error("`x2` doit être strictement supérieur à `x1`. Veuillez corriger vos entrées.")
            elif y1 >= y2:
                st.error("`y2` doit être strictement supérieur à `y1`. Veuillez corriger vos entrées.")
            else:
                # Calcul des dimensions du recadrage
                cropped_width = x2 - x1
                cropped_height = y2 - y1

                # Bouton pour générer l'image recadrée
                if st.button("Générer le Recadrage"):
                    # Recadrage de l'image
                    cropped = image_np[int(y1):int(y2), int(x1):int(x2)]

                    # Affichage de l'image recadrée
                    st.image(cropped, caption="Image Croppée", use_container_width=True)

                    # Affichage des informations sur la taille du rectangle
                    st.write(f"Le rectangle recadré mesure {cropped_width} pixels de large et {cropped_height} pixels de haut.")

                    # Bouton de téléchargement pour l'image recadrée
                    st.download_button(
                        label="⬇️ Télécharger l'image croppée",
                        data=image_to_bytes(cropped),
                        file_name="image_cropped.png",
                        mime="image/png"
                    )

        except Exception as e:
            st.error(f"Une erreur est survenue : {e}")

    # Rotation
    elif menu_option == "Rotation":
        st.subheader("Rotation")

        # Instructions sur la rotation
        st.markdown("""
        ### Légende : Fonctionnement de la rotation
        - La **rotation** d'une image consiste à tourner l'image autour de son centre selon un angle défini.
        - Vous pouvez choisir un angle prédéfini pour faire pivoter l'image à gauche ou à droite.
        
        ### Options disponibles :
        - Choisissez un angle parmi les options proposées : **45°, 90° ou 180°**.
        - L'image sera ensuite tournée dans le sens des aiguilles d'une montre.

        ### Exemple :
        - Si vous choisissez un angle de **90°**, l'image sera pivotée de 90 degrés dans le sens des aiguilles d'une montre par rapport à son centre.
        """)
        
        # Sélection de l'angle de rotation
        angle = st.selectbox("Angle de rotation", [45, 90, 180])

        # Calcul des dimensions et application de la rotation
        rows, cols, _ = image_np.shape
        rotation_matrix = cv2.getRotationMatrix2D((cols / 2, rows / 2), angle, 1)
        rotated = cv2.warpAffine(image_np, rotation_matrix, (cols, rows))

        # Affichage de l'image après rotation
        st.image(rotated, caption=f"Image Rotée de {angle} degrés", use_container_width=True)

        # Bouton de téléchargement pour l'image rotée
        st.download_button(
            label="Télécharger l'image rotée",
            data=image_to_bytes(rotated),
            file_name=f"image_rotated_{angle}.png",
            mime="image/png"
        )

    # Floutage
    elif menu_option == "Floutage":
        st.subheader("Floutage")

        # Instructions sur le floutage
        st.markdown("""
        ### Légende : Fonctionnement du floutage
        - Le **floutage** est utilisé pour adoucir une image en réduisant les détails fins, ce qui est utile pour l'anonymisation ou pour appliquer des effets esthétiques.
        - Vous pouvez ajuster l'intensité du flou en fonction du niveau choisi.

        ### Options disponibles :
        - Le **Niveau de flou (k)** détermine l'intensité du flou appliqué. Plus la valeur est élevée, plus l'image sera floutée.
        - Les valeurs sont comprises entre 1 (très léger flou) et 51 (flou maximal), et doivent être des nombres impairs.

        ### Exemple :
        - Si vous choisissez **k = 15**, l'image sera floutée de manière modérée, et vous pourrez voir l'effet de réduction de détails.
        """)
        
        # Sélection du niveau de flou
        blur_level = st.slider("Niveau de flou (k)", min_value=1, max_value=51, step=2, value=15)

        # Application du flou sur l'image
        blurred = cv2.GaussianBlur(image_np, (blur_level, blur_level), 0)

        # Affichage de l'image floutée
        st.image(blurred, caption=f"Image Floutée (k={blur_level})", use_container_width=True)

        # Bouton de téléchargement pour l'image floutée
        st.download_button(
            label="Télécharger l'image floutée",
            data=image_to_bytes(blurred),
            file_name=f"image_blurred_k{blur_level}.png",
            mime="image/png"
        )

    # Détection des contours
    elif menu_option == "Contours":
        st.subheader("Contours")

        # Instructions sur la détection des contours
        st.markdown("""
        ### Légende : Fonctionnement de la détection de contours
        - La **détection de contours** consiste à identifier les bords distincts de l'image, ce qui permet de mieux comprendre les structures présentes.
        - Elle est souvent utilisée dans des traitements d'image avancés comme la reconnaissance d'objets ou l'analyse d'images.

        ### Options disponibles :
        - L'image sera convertie en niveaux de gris, et ensuite un algorithme de détection de contours (Canny) sera appliqué pour extraire les bords de l'image.
        - Cela permet de visualiser les contours dans des images complexes.

        ### Exemple :
        - Après l'application de l'algorithme Canny, l'image ne contient que les contours des objets, ce qui peut être utilisé pour détecter des formes, des objets ou d'autres détails visuels importants.
        """)
        
        # Conversion de l'image en niveaux de gris pour la détection des contours
        gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)
        edges = cv2.Canny(gray, 100, 200)

        # Affichage de l'image avec les contours détectés
        st.image(edges, caption="Contours de l'Image", use_container_width=True)

        # Bouton de téléchargement pour l'image avec contours
        st.download_button(
            label="Télécharger l'image avec contours",
            data=image_to_bytes(edges),
            file_name=f"image_edges.png",
            mime="image/png"
        )
        
        
    elif menu_option == "Génération de Code-barres et QR Code":
        st.subheader("Génération de Code-barres et QR Code")

        # Légende pour guider l'utilisateur
        st.markdown(
            """
            🔄 **Instructions :**
            1. Saisis un lien ou un texte dans le champ ci-dessous.  
            2. Accède à l'onglet souhaité pour générer un **Code-barres** 📊 ou un **QR Code** 📱.  
            3. Clique sur le bouton **"Générer"** pour voir le résultat et utilise le bouton **⬇️ Télécharger** pour sauvegarder l'image.
            """
        )

        # Gestion de l'entrée utilisateur avec sauvegarde dans session_state
        if "link" not in st.session_state:
            st.session_state["link"] = ""

        # Entrée utilisateur
        link = st.text_input("🔗 Entre un lien ou un texte pour générer les codes", value=st.session_state["link"])
        if link:
            st.session_state["link"] = link

        # Création des onglets
        tab1, tab2 = st.tabs(["📊 Code-barres", "📱 QR Code"])

        # Onglet Code-barres
        with tab1:
            st.header("📊 Génération de Code-barres")
            if st.button("Générer le Code-barres"):
                if st.session_state["link"]:
                    try:
                        # Génération du code-barres
                        barcode_image = generate_barcode(st.session_state["link"])
                        st.image(barcode_image, caption="Code-barres généré", use_container_width=True)

                        # Bouton de téléchargement avec icône
                        barcode_buffer = BytesIO()
                        barcode_image.save(barcode_buffer, format="PNG")
                        barcode_buffer.seek(0)
                        st.download_button(
                            label="⬇️ Télécharger le Code-barres",
                            data=barcode_buffer,
                            file_name="barcode.png",
                            mime="image/png"
                        )
                    except Exception as e:
                        st.error(f"Une erreur est survenue lors de la génération : {e}")
                else:
                    st.warning("⚠️ Veuillez entrer un lien ou un texte valide.")

        # Onglet QR Code
        with tab2:
            st.header("📱 Génération de QR Code")
            if st.button("Générer le QR Code"):
                if st.session_state["link"]:
                    try:
                        # Génération du QR Code
                        qrcode_image = generate_qrcode(st.session_state["link"])
                        st.image(qrcode_image, caption="QR Code généré", use_container_width=True)

                        # Bouton de téléchargement avec icône
                        qrcode_buffer = BytesIO()
                        qrcode_image.save(qrcode_buffer, format="PNG")
                        qrcode_buffer.seek(0)
                        st.download_button(
                            label="⬇️ Télécharger le QR Code",
                            data=qrcode_buffer,
                            file_name="qrcode.png",
                            mime="image/png"
                        )
                    except Exception as e:
                        st.error(f"Une erreur est survenue lors de la génération : {e}")
                else:
                    st.warning("⚠️ Veuillez entrer un lien ou un texte valide.")


    elif menu_option == "Détection Faciale":
        st.subheader("Détection Faciale")

        # Sélectionner la source de l'image
        source_option = st.radio("Choisissez la source", ("Image Importée", "Autre Image", "Webcam", "Vidéo"))

        # Charger le classificateur de visages pré-entrainé de OpenCV
        face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")

        if source_option == "Image Importée":
            if st.session_state["default_image"] is not None:
                img = image_np
                gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
                faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))

                # Dessiner des rectangles autour des visages
                for (x, y, w, h) in faces:
                    cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)

                st.image(img, caption="Image avec Visages Détectés", use_container_width=True)

        elif source_option == "Autre Image":
            uploaded_file_2 = st.file_uploader("Charge une autre image", type=["png", "jpg", "jpeg"])
            if uploaded_file_2 is not None:
                image_2 = Image.open(uploaded_file_2)
                img = np.array(image_2)
                gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
                faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))

                # Dessiner des rectangles autour des visages
                for (x, y, w, h) in faces:
                    cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)

                st.image(img, caption="Autre Image avec Visages Détectés", use_container_width=True)

        elif source_option == "Webcam":
            stframe = st.empty()
            cap = cv2.VideoCapture(0)

            while True:
                ret, frame = cap.read()
                if not ret:
                    st.write("Erreur dans la lecture de la webcam.")
                    break

                gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
                faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))

                # Dessiner des rectangles autour des visages
                for (x, y, w, h) in faces:
                    cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)

                # Affichage dans le streamlit
                stframe.image(frame, channels="BGR", use_container_width=True)

                if cv2.waitKey(1) & 0xFF == ord("q"):  # Quitter avec la touche 'q'
                    break

            cap.release()

        elif source_option == "Vidéo":
            video_file = st.file_uploader("Charge une vidéo", type=["mp4", "avi", "mov"])
            if video_file is not None:
                video_bytes = video_file.read()
                with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
                    tmp_file.write(video_bytes)
                    video_path = tmp_file.name

                cap = cv2.VideoCapture(video_path)
                while cap.isOpened():
                    ret, frame = cap.read()
                    if not ret:
                        break

                    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
                    faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))

                    # Dessiner des rectangles autour des visages
                    for (x, y, w, h) in faces:
                        cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)

                    st.image(frame, caption="Vidéo avec Visages Détectés", use_container_width=True)

                cap.release()
        
    elif menu_option == "À propos de nous":
        st.header("À propos de nous")
        st.markdown(
            """
            <div style="text-align:center; font-family: Arial; margin: 20px 0;">
                <h2>Notre équipe</h2>
                <p>Nous sommes une équipe passionnée travaillant sur des solutions innovantes.</p>
            </div>
            <div style="display: flex; justify-content: center; gap: 30px; flex-wrap: wrap;">
                <div style="text-align: center;">
                    <img src="https://avatars.githubusercontent.com/u/1234567" alt="Ngoue David" style="width: 150px; height: 150px; border-radius: 50%;">
                    <h4>Ngoue David</h4>
                    <p>🎓 Master 2 IA & Big Data</p>
                    <p>📧 <a href="mailto:ngouedavidrogeryannick@gmail.com">ngouedavidrogeryannick@gmail.com</a></p>
                    <p>🌐 <a href="https://github.com/TheBeyonder237" target="_blank">Profil GitHub</a></p>
                </div>
                <div style="text-align: center;">
                    <img src="https://avatars.githubusercontent.com/u/7654321" alt="Bidzanga Armel" style="width: 150px; height: 150px; border-radius: 50%;">
                    <h4>Bidzanga Armel</h4>
                    <p>🎓 Master 2 IA & Big Data</p>
                    <p>📧 <a href="mailto:armelmbia08@gmail.com">armelmbia08@gmail.com</a></p>
                    <p>🌐 <a href="https://github.com/armelmbia10" target="_blank">Profil GitHub</a></p>
                </div>
                <div style="text-align: center;">
                    <img src="https://avatars.githubusercontent.com/u/9876543" alt="Nziou Serena" style="width: 150px; height: 150px; border-radius: 50%;">
                    <h4>Nziou Serena</h4>
                    <p>🎓 Master 2 Administration Systèmes</p>
                    <p>📧 <a href="mailto:serenakeliane@gmail.com">serenakeliane@gmail.com</a></p>
                    <p>🌐 <a href="https://github.com/serkeli0011" target="_blank">Profil GitHub</a></p>
                </div>
            </div>
            """,
            unsafe_allow_html=True
        )



if __name__ == "__main__":
    main()