HuguesdeF commited on
Commit
8f269fd
·
1 Parent(s): c9601a7
Files changed (3) hide show
  1. Corriger.py +155 -132
  2. requirements.txt +1 -0
  3. users.yaml +0 -0
Corriger.py CHANGED
@@ -1,12 +1,13 @@
1
  import streamlit as st
 
2
  from code.functions import pipeline_svg
3
  from PIL import Image
4
  import cv2
5
  import numpy as np
6
  from io import BytesIO
7
  import copy
8
-
9
- inch_value = 2.54
10
 
11
  logo = Image.open("seguinmoreau.png")
12
  st.set_page_config(
@@ -16,137 +17,159 @@ st.set_page_config(
16
  initial_sidebar_state="expanded"
17
  )
18
 
19
- st.markdown(
20
- """
21
- # Boîte à Outils de correction de logos :wrench:
22
-
23
- Bienvenue dans la boîte à outils de correction de logos de Seguin Moreau.
24
-
25
- ### :hammer: Les outils
26
- Dans cette boîte à outils, vous trouverez:
27
- * Un outil de Correction automatique de logo (enlever les petits défauts, lissage, vectorisation, grossissement des traits trop fins.
28
- * Un outil de Vectorisation (image en pixels => image vectorisée => image en pixels).
29
-
30
- ### :bulb: Mode d'emploi
31
- * Cliquer sur 'Browse files'
32
- * Sélectionner un logo
33
- * 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.
34
- * 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.
35
-
36
- """
37
- )
38
-
39
- logo = Image.open('seguinmoreau.png')
40
- st.image(logo, width=100)
41
-
42
- uploaded_files = st.file_uploader("Choisir un logo", accept_multiple_files=True)
43
-
44
- image_width = 500
45
- size_value = st.slider("Largeur de trait minimum", min_value=1, max_value=21, value=7, step=2)
46
-
47
- size_value = (size_value - 1) // 2
48
-
49
- #kernel_type_str = st.selectbox("Kernel type", ["Ellipse", "Rectangle", "Cross"])
50
- kernel_type_str = "Ellipse"
51
- dict_kernel_type = {"Ellipse": cv2.MORPH_ELLIPSE, "Rectangle": cv2.MORPH_RECT, "Cross": cv2.MORPH_CROSS}
52
- kernel_type = dict_kernel_type[kernel_type_str]
53
-
54
- for uploaded_file in uploaded_files:
55
- col1, col2, col3 = st.columns([1, 1, 1])
56
- col3.markdown("---")
57
-
58
- image = Image.open(uploaded_file).convert('L')
59
- image_input = np.array(image)
60
- image = copy.deepcopy(image_input)
61
- col1.image(image_input/255.0, caption="Image d'entrée", use_column_width='auto')
62
-
63
- with col3:
64
- with st.expander(":gear: Paramétrage"):
65
- st.write("Si l'image contient du gris, faire varier le seuil ci-dessous:")
66
- threshold = st.slider("Seuil pour convertir l'image en noir&blanc.", min_value=0, max_value=255, value=0,
67
- step=1, key=f"{uploaded_file}_slider_threshold")
68
- st.write("Si l'image est pixelisée, ou contient trop de détails, "
69
- "augmenter la valeur ci-dessous:")
70
- blur_value = st.slider("Seuil pour lisser l'image", min_value=1, max_value=11, value=1, step=2,
71
- key=f"{uploaded_file}_slider_gaussian_sigma")
72
- st.write("Si l'image contient des traits très fin (de l'odre du pixel),"
73
- " augmenter le seuil ci-dessous, de 1 par 1:")
74
- 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")
75
-
76
- st.write("Taille d'exportation d'image:")
77
-
78
- dpi_value = st.number_input("Valeur dpi:", key=f"{uploaded_file}_number_dpi_value", value=200)
79
- side_width_value = st.number_input("Taille max de côté cible (cm):", key=f"{uploaded_file}_number_target_value", value=20)
80
- new_largest_side_value = int(side_width_value / inch_value * dpi_value)
81
-
82
- h, w, *_ = image.shape
83
-
84
- # Resize image
85
- ratio = w / h
86
- if ratio > 1:
87
- width = new_largest_side_value
88
- height = int(new_largest_side_value / ratio)
89
- else:
90
- height = new_largest_side_value
91
- width = int(ratio * new_largest_side_value)
92
-
93
- target_width_value = st.number_input("Largeur cible (cm):", key=f"{uploaded_file}_number_width_value", value=0)
94
- target_height_value = st.number_input("Hauteur cible (cm):", key=f"{uploaded_file}_number_height_value", value=0)
95
-
96
- if target_width_value > 0 and target_height_value == 0:
97
- width = int(target_width_value / inch_value * dpi_value)
98
- height = int(width / ratio)
99
- elif target_height_value > 0 and target_width_value == 0:
100
- height = int(target_height_value / inch_value * dpi_value)
101
- width = int(height * ratio)
102
- elif target_height_value > 0 and target_width_value > 0:
103
- st.warning("Vous ne pouvez pas modifier la largeur et la hauteur simultanément.")
104
-
105
- if threshold > 0:
106
- image = (image > threshold)*255
107
- image = image.astype('uint8')
108
-
109
- if blur_value > 0:
110
- image = cv2.GaussianBlur(image, (blur_value, blur_value), blur_value - 1)
111
-
112
- # Process image cv32f ==> cv32f
113
- img_final = pipeline_svg(image, size_value=size_value, level=1, threshold=threshold, kernel_type=kernel_type, dilate_lines_value=dilate_lines_value)
114
-
115
- col2.image(img_final, caption="Image corrigée", use_column_width='auto')
116
-
117
- # Check for grayscale
118
- tolerance = 10
119
- ratio_of_gray_pixels = int(np.sum((tolerance < image)* (image < 255 - tolerance))/np.size(image)*100)
120
- if ratio_of_gray_pixels > 1:
121
- col3.warning(f":warning: Le nombre de pixels gris est élevé: {ratio_of_gray_pixels} % > 1%")
122
-
123
- # Check reconstruction fidelity
124
- distance = np.mean((np.array(image) - img_final)**2)
125
- if distance > 10:
126
- col3.warning(f":warning: Le logo est peut-être trop dégradé (MSE={distance:.2f} > 10).\nVérifier visuellement.")
127
-
128
-
129
-
130
- dim = (width, height)
131
- # resize image
132
- resized_img_final = cv2.resize(img_final, dim, interpolation=cv2.INTER_AREA)
133
- resized_image_input = cv2.resize(image_input, dim, interpolation=cv2.INTER_AREA)
134
-
135
- buf = BytesIO()
136
- img_stacked = np.hstack((resized_image_input, resized_img_final))
137
- img_final = Image.fromarray(img_stacked).convert("L")
138
- img_final.save(buf, format="PNG")
139
- byte_im= buf.getvalue()
140
-
141
- btn = col3.download_button(
142
- label=":inbox_tray: Télécharger l'image",
143
- data=byte_im,
144
- file_name=f"corrected_{uploaded_file.name}",
145
- mime="image/png"
146
- )
147
-
148
-
149
 
 
 
150
 
 
 
 
 
 
 
 
151
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
+ import streamlit_authenticator as stauth
3
  from code.functions import pipeline_svg
4
  from PIL import Image
5
  import cv2
6
  import numpy as np
7
  from io import BytesIO
8
  import copy
9
+ import yaml
10
+ from yaml.loader import SafeLoader
11
 
12
  logo = Image.open("seguinmoreau.png")
13
  st.set_page_config(
 
17
  initial_sidebar_state="expanded"
18
  )
19
 
20
+ # Authentication
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
+ with open('users.yaml') as file:
23
+ config = yaml.load(file, Loader=SafeLoader)
24
 
25
+ authenticator = stauth.Authenticate(
26
+ config['credentials'],
27
+ config['cookie']['name'],
28
+ config['cookie']['key'],
29
+ config['cookie']['expiry_days'],
30
+ config['preauthorized']
31
+ )
32
 
33
+ name, authentication_status, username = authenticator.login('Login', 'main')
34
+
35
+ if not authentication_status:
36
+ st.error("Nom d'utilisateur ou mot de passe incorrect")
37
+ elif authentication_status is None:
38
+ st.warning("Rentrer nom d'utilisateur et mot de passe")
39
+ elif authentication_status:
40
+ authenticator.logout('Logout', 'main')
41
+ # ------------------------------
42
+
43
+ inch_value = 2.54
44
+
45
+ logo = Image.open('seguinmoreau.png')
46
+ st.image(logo, width=200)
47
+ st.markdown(
48
+ """
49
+ # Boîte à Outils de correction de logos :wrench:
50
+
51
+ Bienvenue dans la boîte à outils de correction de logos de Seguin Moreau.
52
+
53
+ ### :hammer: Les outils
54
+ Dans cette boîte à outils, vous trouverez:
55
+ * Un outil de Correction automatique de logo (enlever les petits défauts, lissage, vectorisation, grossissement des traits trop fins).
56
+
57
+ ### :bulb: Mode d'emploi
58
+ * Cliquer sur 'Browse files'
59
+ * Sélectionner un logo
60
+ * 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.
61
+ * 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.
62
+
63
+ """
64
+ )
65
 
66
+ uploaded_files = st.file_uploader("Choisir un logo", accept_multiple_files=True)
67
+
68
+ image_width = 500
69
+ size_value = st.slider("Largeur de trait minimum", min_value=1, max_value=21, value=7, step=2)
70
+
71
+ size_value = (size_value - 1) // 2
72
+
73
+ # kernel_type_str = st.selectbox("Kernel type", ["Ellipse", "Rectangle", "Cross"])
74
+ kernel_type_str = "Ellipse"
75
+ dict_kernel_type = {"Ellipse": cv2.MORPH_ELLIPSE, "Rectangle": cv2.MORPH_RECT, "Cross": cv2.MORPH_CROSS}
76
+ kernel_type = dict_kernel_type[kernel_type_str]
77
+
78
+ for uploaded_file in uploaded_files:
79
+ col1, col2, col3 = st.columns([1, 1, 1])
80
+ col3.markdown("---")
81
+
82
+ image = Image.open(uploaded_file).convert('L')
83
+ image_input = np.array(image)
84
+ image = copy.deepcopy(image_input)
85
+ col1.image(image_input / 255.0, caption="Image d'entrée", use_column_width='auto')
86
+
87
+ with col3:
88
+ with st.expander(":gear: Paramétrage"):
89
+ st.write("Si l'image contient du gris, faire varier le seuil ci-dessous:")
90
+ threshold = st.slider("Seuil pour convertir l'image en noir&blanc.", min_value=0, max_value=255,
91
+ value=0,
92
+ step=1, key=f"{uploaded_file}_slider_threshold")
93
+ st.write("Si l'image est pixelisée, ou contient trop de détails, "
94
+ "augmenter la valeur ci-dessous:")
95
+ blur_value = st.slider("Seuil pour lisser l'image", min_value=1, max_value=11, value=1, step=2,
96
+ key=f"{uploaded_file}_slider_gaussian_sigma")
97
+ st.write("Si l'image contient des traits très fin (de l'odre du pixel),"
98
+ " augmenter le seuil ci-dessous, de 1 par 1:")
99
+ dilate_lines_value = st.slider("Dilatation de l'image d'origine: (en pixels)", min_value=0, max_value=5,
100
+ value=0, step=1, key=f"{uploaded_file}_slider_dilation_image")
101
+
102
+ st.write("Taille d'exportation d'image:")
103
+
104
+ dpi_value = st.number_input("Valeur dpi:", key=f"{uploaded_file}_number_dpi_value", value=200)
105
+ side_width_value = st.number_input("Taille max de côté cible (cm):",
106
+ key=f"{uploaded_file}_number_target_value", value=20)
107
+ new_largest_side_value = int(side_width_value / inch_value * dpi_value)
108
+
109
+ h, w, *_ = image.shape
110
+
111
+ # Resize image
112
+ ratio = w / h
113
+ if ratio > 1:
114
+ width = new_largest_side_value
115
+ height = int(new_largest_side_value / ratio)
116
+ else:
117
+ height = new_largest_side_value
118
+ width = int(ratio * new_largest_side_value)
119
+
120
+ target_width_value = st.number_input("Largeur cible (cm):", key=f"{uploaded_file}_number_width_value",
121
+ value=0)
122
+ target_height_value = st.number_input("Hauteur cible (cm):", key=f"{uploaded_file}_number_height_value",
123
+ value=0)
124
+
125
+ if target_width_value > 0 and target_height_value == 0:
126
+ width = int(target_width_value / inch_value * dpi_value)
127
+ height = int(width / ratio)
128
+ elif target_height_value > 0 and target_width_value == 0:
129
+ height = int(target_height_value / inch_value * dpi_value)
130
+ width = int(height * ratio)
131
+ elif target_height_value > 0 and target_width_value > 0:
132
+ st.warning("Vous ne pouvez pas modifier la largeur et la hauteur simultanément.")
133
+
134
+ if threshold > 0:
135
+ image = (image > threshold) * 255
136
+ image = image.astype('uint8')
137
+
138
+ if blur_value > 0:
139
+ image = cv2.GaussianBlur(image, (blur_value, blur_value), blur_value - 1)
140
+
141
+ # Process image cv32f ==> cv32f
142
+ img_final = pipeline_svg(image, size_value=size_value, level=1, threshold=threshold, kernel_type=kernel_type,
143
+ dilate_lines_value=dilate_lines_value)
144
+
145
+ col2.image(img_final, caption="Image corrigée", use_column_width='auto')
146
+
147
+ # Check for grayscale
148
+ tolerance = 10
149
+ ratio_of_gray_pixels = int(np.sum((tolerance < image) * (image < 255 - tolerance)) / np.size(image) * 100)
150
+ if ratio_of_gray_pixels > 1:
151
+ col3.warning(f":warning: Le nombre de pixels gris est élevé: {ratio_of_gray_pixels} % > 1%")
152
+
153
+ # Check reconstruction fidelity
154
+ distance = np.mean((np.array(image) - img_final) ** 2)
155
+ if distance > 10:
156
+ col3.warning(
157
+ f":warning: Le logo est peut-être trop dégradé (MSE={distance:.2f} > 10).\nVérifier visuellement.")
158
+
159
+ dim = (width, height)
160
+ # resize image
161
+ resized_img_final = cv2.resize(img_final, dim, interpolation=cv2.INTER_AREA)
162
+ resized_image_input = cv2.resize(image_input, dim, interpolation=cv2.INTER_AREA)
163
+
164
+ buf = BytesIO()
165
+ # img_stacked = np.hstack((resized_image_input, resized_img_final))
166
+ img_final = Image.fromarray(resized_image_input).convert("L")
167
+ img_final.save(buf, format="PNG")
168
+ byte_im = buf.getvalue()
169
+
170
+ btn = col3.download_button(
171
+ label=":inbox_tray: Télécharger l'image",
172
+ data=byte_im,
173
+ file_name=f"corrected_{uploaded_file.name}",
174
+ mime="image/png"
175
+ )
requirements.txt CHANGED
@@ -6,3 +6,4 @@ scipy==1.6.2
6
  streamlit==1.20.0
7
  potracer==0.0.4
8
  cairosvg==2.7.0
 
 
6
  streamlit==1.20.0
7
  potracer==0.0.4
8
  cairosvg==2.7.0
9
+ streamlit-authenticator==0.2.1
users.yaml ADDED
File without changes