From 030682c4be20b9cdd92855caba47b47136132415 Mon Sep 17 00:00:00 2001
From: "maxamed.nuurmaxa" <maxamed.nuurmaxamed@master.hes-so.ch>
Date: Fri, 4 Apr 2025 20:08:03 +0200
Subject: [PATCH] =?UTF-8?q?Ajout=20du=20mod=C3=A8le=20de=20segmentation=20?=
 =?UTF-8?q?U-Net=20pour=20la=20segmentation=20d'images.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../Model_siamois_finale.py"                  | 131 +++++++++++-------
 1 file changed, 79 insertions(+), 52 deletions(-)

diff --git "a/R\303\251seau_siamois/Model_siamois_finale.py" "b/R\303\251seau_siamois/Model_siamois_finale.py"
index f95deeb..3d95556 100644
--- "a/R\303\251seau_siamois/Model_siamois_finale.py"
+++ "b/R\303\251seau_siamois/Model_siamois_finale.py"
@@ -517,62 +517,89 @@ plt.show()
 #%% Fonction qui créer le modèle et une fonction qui calcul la distance
 
 
-def build_siamese_model(inputShape, embeddingDim=48):
-    # spécifie les entrées pour le réseau extracteur de caractéristiques
-    # applique les couches partagées aux entrées de chaque branche
-    l0a = Input(inputShape, name="l0a")  # Entrée A
-    
-    l1a = Conv2D(64, (2, 2), padding="valid", activation="relu", name='l1a')(l0a)  # Couche de convolution partagée 1
-    l1a_mp = MaxPooling2D(pool_size=(2, 2), name='l1a_mp')(l1a)  # Couche de pooling partagée 1
-    l1a_dp = Dropout(0.3)(l1a_mp)  # Couche de dropout partagée
-    # l1a_bm = BatchNormalization()(l1a_dp)
-    
-    l2a = Conv2D(64, (2, 2), padding="valid", activation="relu", name='l2a')(l1a_dp)  # Couche de convolution partagée 2
-    l2a_mp = MaxPooling2D(pool_size=(2,2), name='l2a_mp')(l2a)  # Couche de pooling partagée 2
-    l2a_dp = Dropout(0.3)(l2a_mp)  # Couche de dropout partagée
-    # l2a_bm = BatchNormalization()(l2a_dp)
-
-    # l3a = Conv2D(8, (2, 2), padding="same", activation="relu", name='l3a')(l2a_dp)  # Couche de convolution partagée 3
-    # l3a_dp = Dropout(0.3)(l3a)  # Couche de dropout partagée
-    # l3a_mp = MaxPooling2D(pool_size=(2,2), name='l3a_mp')(l3a_dp)  # Couche de pooling partagée 2
-    
-    
-    # l4a = Conv2D(8, (2, 2), padding="same", activation="relu", name='l4a')(l3a_mp)  # Couche de convolution partagée 3
-    # l4a_dp = Dropout(0.3)(l4a)  # Couche de dropout partagée
-    # l4a_mp = MaxPooling2D(pool_size=2, name='l4a_mp')(l4a_dp)  # Couche de pooling partagée 2
-    
+from tensorflow.keras.layers import Conv2D, Conv2DTranspose, MaxPooling2D, UpSampling2D, BatchNormalization, Dropout
+from tensorflow.keras.models import Model
+from tensorflow.keras.layers import Input
 
-    pooledOutputX = GlobalAveragePooling2D()(l2a_dp)  # Pooling global pour la sortie X
-    outputsX = Dense(embeddingDim)(pooledOutputX)  # Couche dense pour la sortie X
+# Fonction pour créer un modèle de segmentation (comme U-Net)
+def build_segmentation_model(input_shape):
+    inputs = Input(input_shape)
+
+    # Encodeur (Contracting path)
+    c1 = Conv2D(64, (3, 3), activation='relu', padding='same')(inputs)
+    c1 = BatchNormalization()(c1)
+    c1 = Conv2D(64, (3, 3), activation='relu', padding='same')(c1)
+    c1 = BatchNormalization()(c1)
+    p1 = MaxPooling2D((2, 2))(c1)
+    p1 = Dropout(0.2)(p1)
+
+    c2 = Conv2D(128, (3, 3), activation='relu', padding='same')(p1)
+    c2 = BatchNormalization()(c2)
+    c2 = Conv2D(128, (3, 3), activation='relu', padding='same')(c2)
+    c2 = BatchNormalization()(c2)
+    p2 = MaxPooling2D((2, 2))(c2)
+    p2 = Dropout(0.3)(p2)
+
+    c3 = Conv2D(256, (3, 3), activation='relu', padding='same')(p2)
+    c3 = BatchNormalization()(c3)
+    c3 = Conv2D(256, (3, 3), activation='relu', padding='same')(c3)
+    c3 = BatchNormalization()(c3)
+    p3 = MaxPooling2D((2, 2))(c3)
+    p3 = Dropout(0.4)(p3)
+
+    c4 = Conv2D(512, (3, 3), activation='relu', padding='same')(p3)
+    c4 = BatchNormalization()(c4)
+    c4 = Conv2D(512, (3, 3), activation='relu', padding='same')(c4)
+    c4 = BatchNormalization()(c4)
+    p4 = MaxPooling2D((2, 2))(c4)
+    p4 = Dropout(0.5)(p4)
+
+    # Bouteille de goulot (bottleneck)
+    c5 = Conv2D(1024, (3, 3), activation='relu', padding='same')(p4)
+    c5 = BatchNormalization()(c5)
+    c5 = Conv2D(1024, (3, 3), activation='relu', padding='same')(c5)
+    c5 = BatchNormalization()(c5)
+
+    # Décodeur (Expanding path)
+    u6 = Conv2DTranspose(512, (2, 2), strides=(2, 2), padding='same')(c5)
+    u6 = Dropout(0.5)(u6)
+    u6 = Conv2D(512, (3, 3), activation='relu', padding='same')(u6)
+    u6 = BatchNormalization()(u6)
+    u6 = Conv2D(512, (3, 3), activation='relu', padding='same')(u6)
+    u6 = BatchNormalization()(u6)
+
+    u7 = Conv2DTranspose(256, (2, 2), strides=(2, 2), padding='same')(u6)
+    u7 = Dropout(0.4)(u7)
+    u7 = Conv2D(256, (3, 3), activation='relu', padding='same')(u7)
+    u7 = BatchNormalization()(u7)
+    u7 = Conv2D(256, (3, 3), activation='relu', padding='same')(u7)
+    u7 = BatchNormalization()(u7)
+
+    u8 = Conv2DTranspose(128, (2, 2), strides=(2, 2), padding='same')(u7)
+    u8 = Dropout(0.3)(u8)
+    u8 = Conv2D(128, (3, 3), activation='relu', padding='same')(u8)
+    u8 = BatchNormalization()(u8)
+    u8 = Conv2D(128, (3, 3), activation='relu', padding='same')(u8)
+    u8 = BatchNormalization()(u8)
+
+    u9 = Conv2DTranspose(64, (2, 2), strides=(2, 2), padding='same')(u8)
+    u9 = Dropout(0.2)(u9)
+    u9 = Conv2D(64, (3, 3), activation='relu', padding='same')(u9)
+    u9 = BatchNormalization()(u9)
+    u9 = Conv2D(64, (3, 3), activation='relu', padding='same')(u9)
+    u9 = BatchNormalization()(u9)
+
+    # Sortie
+    outputs = Conv2D(1, (1, 1), activation='sigmoid')(u9)  # Pour segmentation binaire (0 ou 1)
+
+    # Créer le modèle
+    model = Model(inputs=inputs, outputs=outputs)
 
-    # crée le modèle
-    model = Model(inputs=l0a, outputs=outputsX)
-    
     return model
 
-def euclidean_distance(vectors):
-    # décompose les vecteurs en listes distinctes
-    (featsA, featsB) = vectors  # Vecteurs A et B
-    # calcule la somme des distances au carré entre les vecteurs
-    sumSquared = K.sum(K.square(featsA - featsB), axis=1, keepdims=True)  # Somme des distances au carré
-    # retourne la distance euclidienne entre les vecteurs
-    return K.sqrt(K.maximum(sumSquared, K.epsilon()))  # Distance euclidienne
-
-#%% Creation du modele
-
-input_shape=(target_size[1], target_size[0], 1)
-
-img_empty = Input(shape=input_shape)
-img_full = Input(shape=input_shape)
-
-featureExtractor = build_siamese_model(input_shape)
-featsA = featureExtractor(img_empty)
-featsB = featureExtractor(img_full)
-
-distance = Layer(trainable=False)(euclidean_distance)([featsA, featsB])
-
-outputs = Dense(1, activation="sigmoid")(distance)
-model = Model(inputs=[img_empty, img_full], outputs=outputs)
+# Créer le modèle de segmentation
+input_shape = (150, 200, 1)  # La taille d'entrée que vous avez (150x200 avec un seul canal)
+model = build_segmentation_model(input_shape)
 
 model.summary()
 
-- 
GitLab