Spaces:
Runtime error
Runtime error
| import streamlit as st | |
| import os | |
| import streamlit_authenticator as stauth | |
| from code.functions import pipeline_svg | |
| from PIL import Image | |
| import cv2 | |
| import numpy as np | |
| from io import BytesIO | |
| import copy | |
| logo = Image.open("seguinmoreau.png") | |
| st.set_page_config( | |
| page_title="Moulinette Logos", | |
| page_icon=logo, | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| inch_value = 2.54 | |
| logo = Image.open('seguinmoreau.png') | |
| st.image(logo, width=200) | |
| st.markdown( | |
| """ | |
| # Boîte à Outils de correction de logos :wrench: | |
| Bienvenue dans la boîte à outils de correction de logos de Seguin Moreau. | |
| ### :hammer: Les outils | |
| Dans cette boîte à outils, vous trouverez: | |
| * Un outil de Correction automatique de logo (enlever les petits défauts, lissage, vectorisation, grossissement des traits trop fins). | |
| ### :bulb: Mode d'emploi | |
| * Cliquer sur 'Browse files' | |
| * Sélectionner un logo | |
| * La correction est automatique. Si la correction ne vous convient pas, il est possible de régler les paramètres en cliquant sur 'Paramétrage' à droite de l'image. | |
| * Les deux paramètres permettent de corriger les défauts liés à la présence de gris sur le logo ou la 'pixélisation' du logo trop importante. | |
| """ | |
| ) | |
| uploaded_files = st.file_uploader("Choisir un logo", accept_multiple_files=True) | |
| image_width = 500 | |
| size_value = st.slider("Largeur de trait minimum", min_value=1, max_value=21, value=7, step=2) | |
| size_value = (size_value - 1) // 2 | |
| # kernel_type_str = st.selectbox("Kernel type", ["Ellipse", "Rectangle", "Cross"]) | |
| kernel_type_str = "Ellipse" | |
| dict_kernel_type = {"Ellipse": cv2.MORPH_ELLIPSE, "Rectangle": cv2.MORPH_RECT, "Cross": cv2.MORPH_CROSS} | |
| kernel_type = dict_kernel_type[kernel_type_str] | |
| for uploaded_file in uploaded_files: | |
| col1, col2, col3 = st.columns([1, 1, 1]) | |
| col3.markdown("---") | |
| image = Image.open(uploaded_file).convert('L') | |
| image_input = np.array(image) | |
| image = copy.deepcopy(image_input) | |
| col1.image(image_input / 255.0, caption="Image d'entrée", use_column_width='auto') | |
| with col3: | |
| with st.expander(":gear: Paramétrage"): | |
| st.write("Si l'image contient du gris, faire varier le seuil ci-dessous:") | |
| threshold = st.slider("Seuil pour convertir l'image en noir&blanc.", min_value=0, max_value=255, | |
| value=0, | |
| step=1, key=f"{uploaded_file}_slider_threshold") | |
| st.write("Si l'image est pixelisée, ou contient trop de détails, " | |
| "augmenter la valeur ci-dessous:") | |
| blur_value = st.slider("Seuil pour lisser l'image", min_value=1, max_value=11, value=1, step=2, | |
| key=f"{uploaded_file}_slider_gaussian_sigma") | |
| st.write("Si l'image contient des traits très fin (de l'odre du pixel)," | |
| " augmenter le seuil ci-dessous, de 1 par 1:") | |
| dilate_lines_value = st.slider("Dilatation de l'image d'origine: (en pixels)", min_value=0, max_value=5, | |
| value=0, step=1, key=f"{uploaded_file}_slider_dilation_image") | |
| st.write("Taille d'exportation d'image:") | |
| dpi_value = st.number_input("Valeur dpi:", key=f"{uploaded_file}_number_dpi_value", value=200) | |
| st.write("---") | |
| st.write("Spécifier la taille maximum d'un côté, en cm:") | |
| side_width_value = st.number_input("Taille max de côté cible (cm):", | |
| key=f"{uploaded_file}_number_target_value", value=20.0) | |
| new_largest_side_value = int(side_width_value / inch_value * dpi_value) | |
| h, w, *_ = image.shape | |
| # Resize image | |
| ratio = w / h | |
| if ratio > 1: | |
| width = new_largest_side_value | |
| height = int(width / ratio) | |
| else: | |
| height = new_largest_side_value | |
| width = int(ratio * height) | |
| st.write("---") | |
| st.write("Ou, spécifier la largeur OU la hauteur cible, en cm:") | |
| target_width_value = st.number_input("Largeur cible (cm):", key=f"{uploaded_file}_number_width_value", | |
| value=0.0) | |
| target_height_value = st.number_input("Hauteur cible (cm):", key=f"{uploaded_file}_number_height_value", | |
| value=0.0) | |
| if target_width_value > 0 and target_height_value == 0: | |
| width = int(target_width_value / inch_value * dpi_value) | |
| height = int(width / ratio) | |
| elif target_height_value > 0 and target_width_value == 0: | |
| height = int(target_height_value / inch_value * dpi_value) | |
| width = int(height * ratio) | |
| elif target_height_value > 0 and target_width_value > 0: | |
| st.warning("Vous ne pouvez pas modifier la largeur et la hauteur simultanément.") | |
| st.info(f"Le logo sera redimensionné de :") | |
| st.info(f"hauteur={h} pixels et largeur={w} pixels vers " | |
| f"hauteur={height} pixels et largeur={width} pixels.") | |
| if threshold > 0: | |
| image = (image > threshold) * 255 | |
| image = image.astype('uint8') | |
| if blur_value > 0: | |
| image = cv2.GaussianBlur(image, (blur_value, blur_value), blur_value - 1) | |
| # Process image cv32f ==> cv32f | |
| img_final = pipeline_svg(image, size_value=size_value, level=1, threshold=threshold, kernel_type=kernel_type, | |
| dilate_lines_value=dilate_lines_value) | |
| col2.image(img_final, caption="Image corrigée", use_column_width='auto') | |
| # Check for grayscale | |
| tolerance = 10 | |
| ratio_of_gray_pixels = int(np.sum((tolerance < image) * (image < 255 - tolerance)) / np.size(image) * 100) | |
| if ratio_of_gray_pixels > 1: | |
| col3.warning(f":warning: Le nombre de pixels gris est élevé: {ratio_of_gray_pixels} % > 1%") | |
| # Check reconstruction fidelity | |
| distance = np.mean((np.array(image) - img_final) ** 2) | |
| if distance > 10: | |
| col3.warning( | |
| f":warning: Le logo est peut-être trop dégradé (MSE={distance:.2f} > 10).\nVérifier visuellement.") | |
| dim = (width, height) | |
| # resize image | |
| resized_img_final = cv2.resize(img_final, dim, interpolation=cv2.INTER_AREA) | |
| resized_image_input = cv2.resize(image_input, dim, interpolation=cv2.INTER_AREA) | |
| buf = BytesIO() | |
| # img_stacked = np.hstack((resized_image_input, resized_img_final)) | |
| img_final = Image.fromarray(resized_img_final).convert("L") | |
| img_final.save(buf, format="PNG", dpi=(dpi_value, dpi_value)) | |
| byte_im = buf.getvalue() | |
| btn = col3.download_button( | |
| label=":inbox_tray: Télécharger l'image", | |
| data=byte_im, | |
| file_name=f"corrected_{uploaded_file.name}", | |
| mime="image/png" | |
| ) | |