File size: 16,101 Bytes
7ff5bfc
 
 
2aa3837
7ff5bfc
d8fac82
 
 
 
 
 
 
 
 
 
7ff5bfc
d8fac82
6bad7c8
eeb9126
7ff5bfc
2aa3837
 
 
7ff5bfc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d8fac82
 
 
 
 
 
 
 
 
 
2aa3837
 
 
d8fac82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2aa3837
d452a3c
d8fac82
 
 
 
 
 
 
 
 
7ff5bfc
d8fac82
2aa3837
d8fac82
 
7ff5bfc
d8fac82
 
 
 
 
7ff5bfc
d8fac82
 
 
 
 
7ff5bfc
d8fac82
 
 
 
 
7ff5bfc
2aa3837
d8fac82
 
 
 
 
 
 
 
 
 
 
2aa3837
47f1175
40203fd
 
 
 
 
 
 
 
 
 
 
 
 
28e0bf1
40203fd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2aa3837
40203fd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7ff5bfc
 
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
import streamlit as st
import numpy as np
import cv2
#from PIL import Image

# Configuration de la page pour éviter le comportement de retour en arrière
st.set_page_config(layout="wide")

# Initialisation des variables d'état
if 'color_rgb' not in st.session_state:
    st.session_state['color_rgb'] = np.array([128, 128, 128], dtype=np.uint8)
if 'color_space' not in st.session_state:
    st.session_state['color_space'] = "RGB"
    
# Fonctions de conversion de couleurs
def create_opencv_color_square(color_array):
    img = np.full((400, 400, 3), color_array, dtype=np.uint8)
    bordered_img = cv2.copyMakeBorder(src=img, top=1, bottom=1, left=1, right=1, borderType=cv2.BORDER_CONSTANT,value=[64,64,64]) 
    return bordered_img

def rgb_to_gray(rgb):
    return cv2.cvtColor(np.uint8([[rgb]]), cv2.COLOR_RGB2GRAY)[0][0]

def bgr_to_rgb(bgr):
    return cv2.cvtColor(np.uint8([[bgr]]), cv2.COLOR_BGR2RGB)[0][0]

def rgb_to_bgr(rgb):
    return cv2.cvtColor(np.uint8([[rgb]]), cv2.COLOR_RGB2BGR)[0][0]

def rgb_to_hsv(rgb):
    return cv2.cvtColor(np.uint8([[rgb]]), cv2.COLOR_RGB2HSV)[0][0]

def hsv_to_rgb(hsv):
    return cv2.cvtColor(np.uint8([[hsv]]), cv2.COLOR_HSV2RGB)[0][0]

def rgb_to_lab(rgb):
    return cv2.cvtColor(np.uint8([[rgb]]), cv2.COLOR_RGB2LAB)[0][0]

def lab_to_rgb(lab):
    return cv2.cvtColor(np.uint8([[lab]]), cv2.COLOR_LAB2RGB)[0][0]

# Fonction pour initialiser les valeurs des sliders en fonction de l'espace de couleur
def init_slider_values():
    if 'slider_initialized' not in st.session_state:
        st.session_state['slider_initialized'] = {}
    
    color_space = st.session_state['color_space']
    
    # Initialiser les valeurs des sliders uniquement si elles n'existent pas déjà ou si l'espace couleur a changé
    if color_space not in st.session_state['slider_initialized'] or not st.session_state['slider_initialized'][color_space]:
        if color_space == "Niveau de gris":
            #st.session_state['gray_value'] = int(st.session_state['color_rgb'][0])
            st.session_state['gray_value'] = int(rgb_to_gray(st.session_state['color_rgb']))
            print(st.session_state['gray_value'])
        
        elif color_space == "RGB":
            st.session_state['r_value'] = int(st.session_state['color_rgb'][0])
            st.session_state['g_value'] = int(st.session_state['color_rgb'][1])
            st.session_state['b_value'] = int(st.session_state['color_rgb'][2])
        
        elif color_space == "BGR":
            bgr_val = rgb_to_bgr(st.session_state['color_rgb'])
            st.session_state['b_value_bgr'] = int(bgr_val[0])
            st.session_state['g_value_bgr'] = int(bgr_val[1])
            st.session_state['r_value_bgr'] = int(bgr_val[2])
        
        elif color_space == "HSV":
            hsv_val = rgb_to_hsv(st.session_state['color_rgb'])
            st.session_state['h_value'] = int(hsv_val[0])
            st.session_state['s_value'] = int(hsv_val[1])
            st.session_state['v_value'] = int(hsv_val[2])
        
        elif color_space == "Lab":
            lab_val = rgb_to_lab(st.session_state['color_rgb'])
            #print(lab_val)
            st.session_state['l_value'] = int(lab_val[0]/2.55)
            st.session_state['a_value'] = int(lab_val[1]) - 128
            st.session_state['b_value_lab'] = int(lab_val[2]) - 128
        
        st.session_state['slider_initialized'][color_space] = True

# Fonction pour mettre à jour la couleur RGB en fonction des valeurs des sliders
def update_color_from_sliders():
    color_space = st.session_state['color_space']
    
    if color_space == "Niveau de gris":
        gray = st.session_state['gray_value']
        #print(gray)
        st.session_state['color_rgb'] = np.array([gray, gray, gray], dtype=np.uint8)
    
    elif color_space == "RGB":
        r = st.session_state['r_value']
        g = st.session_state['g_value']
        b = st.session_state['b_value']
        st.session_state['color_rgb'] = np.array([r, g, b], dtype=np.uint8)
    
    elif color_space == "BGR":
        b_val = st.session_state['b_value_bgr']
        g_val = st.session_state['g_value_bgr']
        r_val = st.session_state['r_value_bgr']
        st.session_state['color_rgb'] = bgr_to_rgb(np.array([b_val, g_val, r_val], dtype=np.uint8))
    
    elif color_space == "HSV":
        h = st.session_state['h_value']
        s = st.session_state['s_value']
        v = st.session_state['v_value']
        st.session_state['color_rgb'] = hsv_to_rgb(np.array([h, s, v], dtype=np.uint8))
    
    elif color_space == "Lab":
        l = int(st.session_state['l_value']*2.55)
        a = st.session_state['a_value']
        b_val = st.session_state['b_value_lab']
        st.session_state['color_rgb'] = lab_to_rgb(np.array([l, a + 128, b_val + 128], dtype=np.uint8))

# Fonction pour changer l'espace de couleur
def change_color_space():
    st.session_state['slider_initialized'][st.session_state['color_space']] = False
    # Ne pas mettre à jour la couleur RGB ici, juste changer l'espace

# Interface utilisateur principale
def main():
    #st.title("Manipulation des espaces colorimétriques")
    st.markdown("""<style>.block-container {padding-top:1.2rem;}</style>""", unsafe_allow_html=True)
    st.markdown("<h1 style='text-align: left;padding-left:12.5%;margin-top: 0;'>Manipuler les espaces colorimétriques</h1>", unsafe_allow_html=True)
    #st.markdown("<br>", unsafe_allow_html=True)
    # Initialisation
    if 'slider_initialized' not in st.session_state:
        st.session_state['slider_initialized'] = {}
        for cs in ["Niveau de gris", "RGB", "BGR", "HSV", "Lab"]:
            st.session_state['slider_initialized'][cs] = False

    # Structure de l'application
    col_settings, col_visual, col_definitions,other = st.columns([1, 1, 1,1],gap="large",border=False,vertical_alignment="top")

    with col_settings:
        st.markdown("<h3 style='text-align: center;'>Réglages</h3>", unsafe_allow_html=True)
        #st.markdown("---")
        # Sélection de l'espace colorimétrique (avec callback pour initialiser les sliders)
        color_space = st.selectbox(
            "Choisissez un espace colorimétrique",
            ("Niveau de gris", "RGB", "BGR", "HSV", "Lab"),
            key="color_space",
            on_change=change_color_space
        )
        
        # Initialiser les valeurs des sliders
        init_slider_values()
        
        # Afficher les sliders en fonction de l'espace colorimétrique
        if color_space == "Niveau de gris":
            st.slider("Niveau de gris", 0, 255, key="gray_value", on_change=update_color_from_sliders)
        
        elif color_space == "RGB":
            st.slider("Rouge (R)", 0, 255, key="r_value", on_change=update_color_from_sliders)
            st.slider("Vert (G)", 0, 255, key="g_value", on_change=update_color_from_sliders)
            st.slider("Bleu (B)", 0, 255, key="b_value", on_change=update_color_from_sliders)
        
        elif color_space == "BGR":
            st.slider("Bleu (B)", 0, 255, key="b_value_bgr", on_change=update_color_from_sliders)
            st.slider("Vert (G)", 0, 255, key="g_value_bgr", on_change=update_color_from_sliders)
            st.slider("Rouge (R)", 0, 255, key="r_value_bgr", on_change=update_color_from_sliders)
        
        elif color_space == "HSV":
            st.slider("Teinte (H)", 0, 179, key="h_value", on_change=update_color_from_sliders)
            st.slider("Saturation (S)", 0, 255, key="s_value", on_change=update_color_from_sliders)
            st.slider("Valeur (V)", 0, 255, key="v_value", on_change=update_color_from_sliders)
        
        elif color_space == "Lab":
            st.slider("Luminosité (L)", 0, 100, key="l_value", on_change=update_color_from_sliders)
            st.slider("Composante a", -128, 127, key="a_value", on_change=update_color_from_sliders)
            st.slider("Composante b", -128, 127, key="b_value_lab", on_change=update_color_from_sliders)

    with col_visual:
        st.markdown("<h3 style='text-align: center;'>Visualisation</h3>", unsafe_allow_html=True)
        st.markdown("---")
        # Afficher l'échantillon de couleur et ses coordonnées
        if color_space == "Niveau de gris":
            nb = rgb_to_gray(st.session_state['color_rgb'])
            st.image(create_opencv_color_square(nb), 
                     caption=f"Niveau de gris : {int(st.session_state['color_rgb'][0])}")        
        elif color_space == "RGB":
            st.image(create_opencv_color_square(st.session_state['color_rgb']), 
                     caption=f"RGB : ({int(st.session_state['color_rgb'][0])}, {int(st.session_state['color_rgb'][1])}, {int(st.session_state['color_rgb'][2])})")
        
        elif color_space == "BGR":
            bgr_color = rgb_to_bgr(st.session_state['color_rgb'])
            st.image(create_opencv_color_square(st.session_state['color_rgb']), 
                     caption=f"BGR : ({int(bgr_color[0])}, {int(bgr_color[1])}, {int(bgr_color[2])})")
        
        elif color_space == "HSV":
            hsv_color = rgb_to_hsv(st.session_state['color_rgb'])
            st.image(create_opencv_color_square(st.session_state['color_rgb']), 
                     caption=f"HSV : ({int(hsv_color[0])}, {int(hsv_color[1])}, {int(hsv_color[2])})")
        
        elif color_space == "Lab":
            lab_color = rgb_to_lab(st.session_state['color_rgb'])
            #print(lab_color)
            st.image(create_opencv_color_square(st.session_state['color_rgb']), 
                     caption=f"Lab : ({int(lab_color[0]/2.55)}, {int(lab_color[1]) - 128:.0f}, {int(lab_color[2]) - 128:.0f})")

    with col_definitions:
        #st.markdown("<h3 style='text-align: center;'>Définitions des paramètres</h3>", unsafe_allow_html=True)
        st.markdown("<h3 style='text-align: center;'>Définitions</h3>", unsafe_allow_html=True)
        st.markdown("---")  # Ajout d'une ligne de séparation
        
        if 'color_space' in st.session_state and st.session_state.color_space == "Niveau de gris":
            st.markdown("**Niveau de gris :**")
            st.markdown("* La valeur de chaque pixel varie de `0` à `255`.")
            st.markdown("* `0` représente le noir et `255` représente le blanc.")
            st.markdown("* Les valeurs intermédiaires représentent différentes nuances de gris.")
        
        elif 'color_space' in st.session_state and st.session_state.color_space == "RGB":
            st.markdown("**RGB (Rouge, Vert, Bleu) :**")
            st.markdown("* Chaque pixel est représenté par une combinaison de trois canaux de couleur primaires : le **Rouge (R)**, le **Vert (G)** et le **Bleu (B)**.")
            st.markdown("* La valeur de chaque canal varie généralement de `0` à `255`.")
            st.markdown("* `0` signifie l'absence de cette couleur primaire, et `255` signifie sa pleine intensité.")
            st.markdown("* En combinant différentes intensités de ces trois couleurs, on peut obtenir un large spectre de couleurs.")
            st.markdown("* Par exemple :")
            st.markdown("    * `(255, 0, 0)` représente le rouge pur.")
            st.markdown("    * `(0, 255, 0)` représente le vert pur.")
            st.markdown("    * `(0, 0, 255)` représente le bleu pur.")
            st.markdown("    * `(255, 255, 255)` représente le blanc.")
            st.markdown("    * `(0, 0, 0)` représente le noir.")
            st.markdown("**Applications :**")
            st.markdown("* Apprentissage profond")
            st.markdown("* Génération d'images")
            st.markdown("* Là où la fidélité des couleurs est importante")
        elif 'color_space' in st.session_state and st.session_state.color_space == "BGR":
            st.markdown("**Format d'OpenCV.**")
            st.markdown("**BGR (Bleu, Vert, Rouge) :**")
            st.markdown("* Similaire à RGB, mais l'ordre des canaux de couleur est inversé : **Bleu (B)**, **Vert (G)** et **Rouge (R)**.")
            st.markdown("* La valeur de chaque canal varie généralement de `0` à `255`, avec la même signification qu'en RGB.")
            st.markdown("* Par exemple, la représentation BGR du rouge pur serait `(0, 0, 255)`. ")
            st.markdown("**Applications :**")
            st.markdown("* Uniquement pour l'interopérabilité si l'espace utilisé est BGR. **Sinon transformer en RGB.**")
            
        elif 'color_space' in st.session_state and st.session_state.color_space == "HSV":
            st.markdown("Représente les couleurs en fonction de trois composantes plus intuitives pour la perception humaine. Il sépare l'information de la couleur (teinte) de son intensité et de sa pureté")
            st.markdown("**HSV (Teinte, Saturation, Valeur) :**")
            st.markdown("    * **Teinte (Hue)** : Indique le type de couleur (rouge, jaune, vert, bleu, violet, magenta, rouge). Elle est généralement représentée par un angle sur un cercle de couleurs, allant de `0°` à `360°` (ou normalisée de `0` à `1`). **Pour OpenCV, l'angle va de 0 à 180°.**")
            st.markdown("    * **Saturation (Saturation)** : Décrit la pureté de la couleur. Une saturation élevée signifie une couleur vive et intense, tandis qu'une saturation faible tend vers le gris (`0` signifie un gris pur). Elle varie généralement de `0` à `1` ou de `0%` à `100%`.**Pour OpenCV, la saturation varie de 0 à 255.**")
            st.markdown("    * **Valeur (Value)** : Représente la luminosité de la couleur. Une valeur élevée signifie une couleur claire, tandis qu'une valeur faible tend vers le noir (`0` signifie le noir). Elle varie généralement de `0` à `1` ou de `0%` à `100%`.**Pour OpenCV, la value varie de 0 à 255.**")
            st.markdown("**Applications :**")
            st.markdown("* Segmentation d'objets ou de régions de couleur spécifique")
            st.markdown("* Détection d'objets plus robuste que RGB")
            st.markdown("* Analyse de couleurs dominantes et filtrage de couleurs")
            st.markdown("* Analyse de textures par rapport à la couleur")
            st.markdown("* Vision par ordinateur dans des conditions d'éclairage variable")
        elif 'color_space' in st.session_state and st.session_state.color_space == "Lab":
            st.markdown("Espace colorimétrique conçu pour être **perceptuellement uniforme**, ce qui signifie qu'une même différence numérique de couleur correspond à une différence visuellement similaire pour l'œil humain.")
            st.markdown("**Lab (Luminosité, a, b) :**")
            st.markdown("    * **Luminosité (L)** : Représente la clarté de la couleur, allant de `0` (noir absolu) à `100` (blanc diffus).")
            st.markdown("    * **a** : Représente la position sur l'axe vert-rouge. Les valeurs négatives indiquent le vert, et les valeurs positives indiquent le rouge. La plage typique est d'environ `-128` à `+127` (cela peut varier).")
            st.markdown("    * **b** : Représente la position sur l'axe bleu-jaune. Les valeurs négatives indiquent le bleu, et les valeurs positives indiquent le jaune. La plage typique est également d'environ `-128` à `+127` (cela peut varier).")
            st.markdown("* L'espace Lab est souvent utilisé dans le traitement d'image pour des tâches comme la mesure de la couleur et la correction des couleurs, car il est moins dépendant des dispositifs (écrans, imprimantes) que les espaces RGB ou CMYK.")
            st.markdown("**Applications :**")
            st.markdown("* Segmentation où la disctinction doit correspondre à la perception humaine")
            st.markdown("* Mesure et comparaison de la différence de couleur")
            st.markdown("* Ajout de couleurs réalistes à des images en noir et blanc")
            st.markdown("* Analyse d'images médicales ou scientifiques")
        else:
            st.info("Sélectionnez un espace colorimétrique pour afficher sa définition.")
if __name__ == "__main__":
    main()