ericjedha commited on
Commit
6fe2de4
·
verified ·
1 Parent(s): 7c78074

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +65 -18
app.py CHANGED
@@ -62,47 +62,94 @@ def predict_single(image_pil, weights=(0.45, 0.25, 0.30)):
62
  }
63
 
64
  # ---- Grad-CAM ----
 
65
  def make_gradcam(image_pil, model, last_conv_layer_name, class_index):
66
  input_size = model.input_shape[1:3]
67
  img_np = np.array(image_pil)
68
  img_resized = cv2.resize(img_np, input_size)
69
 
70
- if 'xception' in model.name: preprocessor = preprocess_xception
71
- elif 'resnet50' in model.name: preprocessor = preprocess_resnet
72
- else: preprocessor = preprocess_densenet
 
 
 
73
 
74
  img_array_preprocessed = preprocessor(np.expand_dims(img_resized, axis=0))
75
 
76
- grad_model = Model(model.inputs, [model.get_layer(last_conv_layer_name).output, model.output])
 
 
 
 
 
 
 
77
  input_name = get_primary_input_name(model)
78
  input_for_model = {input_name: img_array_preprocessed}
79
 
80
  with tf.GradientTape() as tape:
81
  last_conv_layer_output, preds = grad_model(input_for_model, training=False)
82
- if isinstance(preds, list): preds = preds[0]
 
83
  class_channel = preds[:, class_index]
84
 
85
  grads = tape.gradient(class_channel, last_conv_layer_output)
86
- if grads is None: return img_resized
 
 
 
 
 
 
 
 
 
87
 
88
- pooled_grads = tf.reduce_mean(grads, axis=(0, 1))
89
  last_conv_layer_output = last_conv_layer_output[0]
90
 
 
91
  heatmap = last_conv_layer_output @ pooled_grads[..., tf.newaxis]
92
  heatmap = tf.squeeze(heatmap)
93
- heatmap = tf.maximum(heatmap, 0) / (tf.math.reduce_max(heatmap) + 1e-8)
94
- heatmap = heatmap.numpy()
95
-
96
- # ===== CORRECTION FINALE ET CRUCIALE =====
97
- # On redimensionne la heatmap (ex: 7x7) à la taille de l'image (ex: 224x224)
98
- heatmap = cv2.resize(heatmap, (img_resized.shape[1], img_resized.shape[0]))
99
- # =======================================
100
-
101
- heatmap = np.uint8(255 * heatmap)
102
- heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
103
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  img_bgr = cv2.cvtColor(img_resized, cv2.COLOR_RGB2BGR)
105
- superimposed_img = cv2.addWeighted(img_bgr, 0.6, heatmap, 0.4, 0)
106
 
107
  return cv2.cvtColor(superimposed_img, cv2.COLOR_BGR2RGB)
108
 
 
62
  }
63
 
64
  # ---- Grad-CAM ----
65
+ # ---- Grad-CAM CORRIGÉ ----
66
  def make_gradcam(image_pil, model, last_conv_layer_name, class_index):
67
  input_size = model.input_shape[1:3]
68
  img_np = np.array(image_pil)
69
  img_resized = cv2.resize(img_np, input_size)
70
 
71
+ if 'xception' in model.name:
72
+ preprocessor = preprocess_xception
73
+ elif 'resnet50' in model.name:
74
+ preprocessor = preprocess_resnet
75
+ else:
76
+ preprocessor = preprocess_densenet
77
 
78
  img_array_preprocessed = preprocessor(np.expand_dims(img_resized, axis=0))
79
 
80
+ # Vérification que la couche existe
81
+ try:
82
+ conv_layer = model.get_layer(last_conv_layer_name)
83
+ except ValueError:
84
+ print(f"Couche '{last_conv_layer_name}' non trouvée dans le modèle")
85
+ return img_resized
86
+
87
+ grad_model = Model(model.inputs, [conv_layer.output, model.output])
88
  input_name = get_primary_input_name(model)
89
  input_for_model = {input_name: img_array_preprocessed}
90
 
91
  with tf.GradientTape() as tape:
92
  last_conv_layer_output, preds = grad_model(input_for_model, training=False)
93
+ if isinstance(preds, list):
94
+ preds = preds[0]
95
  class_channel = preds[:, class_index]
96
 
97
  grads = tape.gradient(class_channel, last_conv_layer_output)
98
+
99
+ # Vérifications de sécurité
100
+ if grads is None:
101
+ print("Gradients sont None - retour de l'image originale")
102
+ return img_resized
103
+
104
+ # Vérifier les valeurs NaN ou inf
105
+ if tf.reduce_any(tf.math.is_nan(grads)) or tf.reduce_any(tf.math.is_inf(grads)):
106
+ print("Gradients contiennent des NaN/inf - retour de l'image originale")
107
+ return img_resized
108
 
109
+ pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2))
110
  last_conv_layer_output = last_conv_layer_output[0]
111
 
112
+ # Calcul de la heatmap
113
  heatmap = last_conv_layer_output @ pooled_grads[..., tf.newaxis]
114
  heatmap = tf.squeeze(heatmap)
 
 
 
 
 
 
 
 
 
 
115
 
116
+ # Normalisation sécurisée
117
+ heatmap = tf.maximum(heatmap, 0)
118
+ max_val = tf.math.reduce_max(heatmap)
119
+
120
+ if max_val == 0:
121
+ print("Heatmap max est 0 - création d'une heatmap neutre")
122
+ heatmap = tf.ones_like(heatmap) * 0.5
123
+ else:
124
+ heatmap = heatmap / max_val
125
+
126
+ heatmap_np = heatmap.numpy()
127
+
128
+ # Vérifications finales avant resize
129
+ if heatmap_np.size == 0:
130
+ print("Heatmap vide - retour de l'image originale")
131
+ return img_resized
132
+
133
+ if np.any(np.isnan(heatmap_np)) or np.any(np.isinf(heatmap_np)):
134
+ print("Heatmap contient des NaN/inf après conversion - retour de l'image originale")
135
+ return img_resized
136
+
137
+ # Redimensionnement sécurisé
138
+ try:
139
+ # S'assurer que heatmap_np est en float32 et dans [0,1]
140
+ heatmap_np = np.clip(heatmap_np.astype(np.float32), 0, 1)
141
+ heatmap_resized = cv2.resize(heatmap_np, (img_resized.shape[1], img_resized.shape[0]))
142
+ except cv2.error as e:
143
+ print(f"Erreur OpenCV resize: {e}")
144
+ return img_resized
145
+
146
+ # Conversion finale
147
+ heatmap_uint8 = np.uint8(255 * heatmap_resized)
148
+ heatmap_colored = cv2.applyColorMap(heatmap_uint8, cv2.COLORMAP_JET)
149
+
150
+ # Superposition
151
  img_bgr = cv2.cvtColor(img_resized, cv2.COLOR_RGB2BGR)
152
+ superimposed_img = cv2.addWeighted(img_bgr, 0.6, heatmap_colored, 0.4, 0)
153
 
154
  return cv2.cvtColor(superimposed_img, cv2.COLOR_BGR2RGB)
155