Spaces:
Sleeping
Sleeping
File size: 7,684 Bytes
78c8c21 8f269fd 78c8c21 8f269fd 78c8c21 8f269fd 78c8c21 8f269fd 78c8c21 8f269fd 78c8c21 8f269fd 78c8c21 8f269fd 1c84be5 8f269fd |
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 |
import streamlit as st
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
import yaml
from yaml.loader import SafeLoader
logo = Image.open("seguinmoreau.png")
st.set_page_config(
page_title="Moulinette Logos",
page_icon=logo,
layout="wide",
initial_sidebar_state="expanded"
)
# Authentication
with open('users.yaml') as file:
config = yaml.load(file, Loader=SafeLoader)
authenticator = stauth.Authenticate(
config['credentials'],
config['cookie']['name'],
config['cookie']['key'],
config['cookie']['expiry_days'],
config['preauthorized']
)
name, authentication_status, username = authenticator.login('Login', 'main')
if not authentication_status:
st.error("Nom d'utilisateur ou mot de passe incorrect")
elif authentication_status is None:
st.warning("Rentrer nom d'utilisateur et mot de passe")
elif authentication_status:
authenticator.logout('Logout', 'main')
# ------------------------------
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)
side_width_value = st.number_input("Taille max de côté cible (cm):",
key=f"{uploaded_file}_number_target_value", value=20)
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(new_largest_side_value / ratio)
else:
height = new_largest_side_value
width = int(ratio * new_largest_side_value)
target_width_value = st.number_input("Largeur cible (cm):", key=f"{uploaded_file}_number_width_value",
value=0)
target_height_value = st.number_input("Hauteur cible (cm):", key=f"{uploaded_file}_number_height_value",
value=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.")
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")
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"
)
|