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 = """ """ st.markdown(css, unsafe_allow_html=True) def add_custom_js(): js = """ """ 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( """

ADS VISOR est une application innovante pour analyser, transformer et explorer vos images. 🖼️✨

Que vous soyez un professionnel ou un passionné, découvrez un large éventail de fonctionnalités interactives !

""", 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( """

Notre équipe

Nous sommes une équipe passionnée travaillant sur des solutions innovantes.

Ngoue David

Ngoue David

🎓 Master 2 IA & Big Data

📧 ngouedavidrogeryannick@gmail.com

🌐 Profil GitHub

Bidzanga Armel

Bidzanga Armel

🎓 Master 2 IA & Big Data

📧 armelmbia08@gmail.com

🌐 Profil GitHub

Nziou Serena

Nziou Serena

🎓 Master 2 Administration Systèmes

📧 serenakeliane@gmail.com

🌐 Profil GitHub

""", unsafe_allow_html=True ) if __name__ == "__main__": main()