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"
        )