File size: 6,957 Bytes
78c8c21
091b39e
8f269fd
78c8c21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c198cf5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8f269fd
78c8c21
c198cf5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11c4504
c198cf5
 
 
 
 
 
 
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
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"
    )