|
import streamlit as st |
|
import uuid |
|
import re |
|
import numpy as np |
|
import cv2 |
|
import matplotlib.pyplot as plt |
|
import matplotlib.image as mpimg |
|
import plotly.graph_objects as go |
|
import plotly.figure_factory as ff |
|
import tensorflow as tf |
|
import keras |
|
|
|
from keras.layers import Conv2D |
|
from tensorflow.keras.preprocessing.image import img_to_array, array_to_img |
|
from keras.models import load_model |
|
|
|
|
|
def show_profile(name, linkedin_url, github_url): |
|
st.markdown(""" |
|
<style> |
|
.icon-img { |
|
height: 20px; # Taille des icônes |
|
width: 20px; |
|
margin-top: 0px; |
|
margin-left: 5px; |
|
margin-right:5px; |
|
} |
|
.name-with-icons { |
|
display: flex-shrink; |
|
align-items: center; |
|
margin-top: -5px; |
|
margin-bottom: 0px; |
|
} |
|
.name-with-icons:first-child { |
|
margin-top: -5px; /* Marge négative pour le premier élément */ |
|
} |
|
</style> |
|
""", unsafe_allow_html = True) |
|
|
|
st.markdown(f""" |
|
<div class='name-with-icons'> |
|
<a href='{github_url}' target='_blank'><img class='icon-img' src='https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg'></a> |
|
<a href='{linkedin_url}' target='_blank'><img class='icon-img' src='https://upload.wikimedia.org/wikipedia/commons/c/ca/LinkedIn_logo_initials.png'></a> |
|
{name} |
|
</div> |
|
""", unsafe_allow_html = True) |
|
|
|
|
|
def create_styled_box(text, text_color, background_color, alignment = 'left', display = 'block'): |
|
unique_id = uuid.uuid4().hex |
|
|
|
st.markdown(f""" |
|
<style> |
|
.styled-box-{unique_id} {{ |
|
background-color: {background_color}; /* couleur de fond */ |
|
color: {text_color}; /* couleur de texte */ |
|
padding: 10px 20px; /* espace intérieur vertical et horizontal */ |
|
border: 1px solid {text_color}; /* bordure de la même couleur que le texte */ |
|
border-radius: 8px; /* bord arrondi */ |
|
font-size: 16px; /* taille de la police */ |
|
font-weight: regular; /* format de la police */ |
|
box-shadow: 0 4px 8px rgba(0,0,0,0.2); /* ombre pour donner de la profondeur */ |
|
text-align: {alignment}; /* alignement du texte */ |
|
display: {display}; |
|
}} |
|
</style> |
|
""", unsafe_allow_html = True) |
|
|
|
|
|
st.markdown(f""" |
|
<div class="styled-box-{unique_id}">{text}</div> |
|
""", unsafe_allow_html = True) |
|
|
|
|
|
def calc_mean_intensity(image_path): |
|
img = mpimg.imread(image_path) |
|
|
|
if img.ndim == 3: |
|
img_gray = np.dot(img[...,:3], [0.2989, 0.5870, 0.1140]) |
|
else: |
|
img_gray = img |
|
return np.mean(img_gray) |
|
|
|
|
|
def source_extract(url): |
|
pattern = re.compile(r'https?://(?:www\.)?([^/]+)') |
|
match = pattern.search(url) |
|
if match: |
|
return match.group(1) |
|
else: |
|
return None |
|
|
|
|
|
def plot_loss_curve(history): |
|
fig = go.Figure() |
|
fig.add_trace(go.Scatter(x = list(range(len(history['loss']))), |
|
y = history['loss'], |
|
mode = 'lines+markers', |
|
name = 'Perte d\'entraînement', |
|
marker = dict(color = 'lightblue'))) |
|
|
|
fig.add_trace(go.Scatter(x = list(range(len(history['val_loss']))), |
|
y = history['val_loss'], |
|
mode = 'lines+markers', |
|
name = 'Perte de validation', |
|
marker = dict(color = 'salmon'))) |
|
|
|
fig.update_layout(title = dict(text = "Courbe de Perte", font = dict(color = 'white')), |
|
xaxis_title = dict(text = "Époque", font = dict(color = 'white')), |
|
yaxis_title = dict(text = "Perte", font = dict(color = 'white')), |
|
template = 'plotly_white', |
|
paper_bgcolor = 'rgba(0,0,0,0)', |
|
plot_bgcolor = 'rgba(0,0,0,0)', |
|
legend = dict(font = dict(color = 'white'))) |
|
st.plotly_chart(fig) |
|
|
|
def plot_precision_curve(history): |
|
fig = go.Figure() |
|
fig.add_trace(go.Scatter(x = list(range(len(history['precision']))), |
|
y = history['precision'], |
|
mode = 'lines+markers', |
|
name = "Précision d'entraînement", |
|
marker = dict(color = 'lightblue'))) |
|
|
|
fig.add_trace(go.Scatter(x = list(range(len(history['val_precision']))), |
|
y = history['val_precision'], |
|
mode = 'lines+markers', |
|
name = 'Précision de validation', |
|
marker = dict(color = 'salmon'))) |
|
|
|
fig.update_layout(title = dict(text = "Courbe de Précision", font = dict(color = 'white')), |
|
xaxis_title=dict(text = "Époque", font = dict(color = 'white')), |
|
yaxis_title=dict(text = "Précision", font = dict(color = 'white')), |
|
template = 'plotly_white', |
|
paper_bgcolor = 'rgba(0,0,0,0)', |
|
plot_bgcolor = 'rgba(0,0,0,0)', |
|
legend = dict(font = dict(color='white'))) |
|
st.plotly_chart(fig) |
|
|
|
def plot_auc(history): |
|
fig = go.Figure() |
|
fig.add_trace(go.Scatter(x = list(range(len(history['auc']))), |
|
y = history['auc'], |
|
mode = 'lines+markers', |
|
name = "AUC moyen d'entraînement", |
|
marker = dict(color='lightblue'))) |
|
|
|
fig.add_trace(go.Scatter(x = list(range(len(history['val_auc']))), |
|
y = history['val_auc'], |
|
mode = 'lines+markers', |
|
name = 'AUC moyen de validation', |
|
marker=dict(color = 'salmon'))) |
|
|
|
fig.update_layout(title = "Courbe de AUC-ROC", |
|
xaxis_title = "Époque", |
|
yaxis_title = "Area Under Curve", |
|
template = 'plotly_white', |
|
paper_bgcolor = 'rgba(0,0,0,0)', |
|
plot_bgcolor = 'rgba(0,0,0,0)', |
|
legend = dict(font = dict(color = 'white')), |
|
xaxis = dict(tickfont = dict(color = 'white')), |
|
yaxis = dict(tickfont = dict(color = 'white')), |
|
title_font = dict(color = 'white')) |
|
st.plotly_chart(fig) |
|
|
|
def plot_f1_score(history): |
|
fig = go.Figure() |
|
fig.add_trace(go.Scatter(x = list(range(len(history['f1_score']))), |
|
y=np.mean(history['f1_score'], axis = 1), |
|
mode = 'lines+markers', |
|
name = "F1 Score d'entraînement", |
|
marker = dict(color = 'lightblue'))) |
|
|
|
fig.add_trace(go.Scatter(x = list(range(len(history['val_f1_score']))), |
|
y = np.mean(history['val_f1_score'], axis = 1), |
|
mode = 'lines+markers', |
|
name = 'F1 Score moyen de validation', |
|
marker = dict(color = 'salmon'))) |
|
|
|
fig.update_layout(title = "Courbe de F1 Score", |
|
xaxis_title = "Époque", |
|
yaxis_title = "F1 Score", |
|
template = 'plotly_white', |
|
paper_bgcolor = 'rgba(0,0,0,0)', |
|
plot_bgcolor = 'rgba(0,0,0,0)', |
|
legend = dict(font = dict(color = 'white')), |
|
xaxis = dict(tickfont = dict(color = 'white')), |
|
yaxis = dict(tickfont = dict(color = 'white')), |
|
title_font = dict(color = 'white')) |
|
st.plotly_chart(fig) |
|
|
|
|
|
def plot_CM(matrix): |
|
confusion_matrix = np.array(matrix) |
|
class_names = ['Covid', 'Lung opacity', 'Normal', 'Viral Pneumonia'] |
|
st.title('Matrice de Confusion') |
|
fig = ff.create_annotated_heatmap(z = confusion_matrix, x = class_names, y = class_names, colorscale = 'RdBu') |
|
fig.update_layout( |
|
title = 'Matrice de Confusion', |
|
xaxis = dict(title = 'Classe Prédite'), |
|
yaxis = dict(title = 'Classe Réelle') |
|
) |
|
st.plotly_chart(fig) |
|
|
|
def plot_CM_ResNetV2(): |
|
confusion_lines = [ |
|
[192, 3, 7, 2], |
|
[9, 148, 24, 0], |
|
[5, 17, 139, 4], |
|
[1, 0, 4, 165] |
|
] |
|
|
|
confusion_matrix = np.array(confusion_lines) |
|
class_names = ['Covid', 'Lung opacity', 'Normal', 'Viral Pneumonia'] |
|
size = max(confusion_matrix.shape) |
|
fig = ff.create_annotated_heatmap(z=confusion_matrix, x=class_names, y=class_names, colorscale='Cividis') |
|
fig.update_layout( |
|
width=size*140, |
|
height=size*140, |
|
xaxis=dict(title='Classe Prédite'), |
|
yaxis=dict(title='Classe Réelle') |
|
) |
|
st.plotly_chart(fig) |
|
|
|
def plot_CM_ResNet121(): |
|
confusion_lines = [ |
|
[181, 11, 11, 1], |
|
[8, 148, 25, 0], |
|
[10, 17, 135, 3], |
|
[2, 0, 1, 167] |
|
] |
|
|
|
confusion_matrix = np.array(confusion_lines) |
|
class_names = ['Covid', 'Lung opacity', 'Normal', 'Viral Pneumonia'] |
|
size = max(confusion_matrix.shape) |
|
fig = ff.create_annotated_heatmap(z=confusion_matrix, x=class_names, y=class_names, colorscale='Cividis') |
|
fig.update_layout( |
|
width=size*140, |
|
height=size*140, |
|
xaxis=dict(title='Classe Prédite'), |
|
yaxis=dict(title='Classe Réelle') |
|
) |
|
st.plotly_chart(fig) |
|
|
|
def plot_CM_DenseNet201(): |
|
confusion_lines = [ |
|
[190, 5, 7, 2], |
|
[6, 156, 19, 0], |
|
[4, 21, 139, 1], |
|
[1, 0, 0, 169] |
|
] |
|
|
|
confusion_matrix = np.array(confusion_lines) |
|
class_names = ['Covid', 'Lung opacity', 'Normal', 'Viral Pneumonia'] |
|
size = max(confusion_matrix.shape) |
|
fig = ff.create_annotated_heatmap(z=confusion_matrix, x=class_names, y=class_names, colorscale='Cividis') |
|
fig.update_layout( |
|
width=size*140, |
|
height=size*140, |
|
xaxis=dict(title='Classe Prédite'), |
|
yaxis=dict(title='Classe Réelle') |
|
) |
|
st.plotly_chart(fig) |
|
|
|
def plot_CM_VGG16(): |
|
|
|
confusion_lines = [ |
|
[178, 5, 9, 2], |
|
[4, 152, 17, 0], |
|
[2, 11, 160, 3], |
|
[0, 0, 4, 175] |
|
] |
|
|
|
confusion_matrix = np.array(confusion_lines) |
|
class_names = ['Covid', 'Lung opacity', 'Normal', 'Viral Pneumonia'] |
|
size = max(confusion_matrix.shape) |
|
fig = ff.create_annotated_heatmap(z=confusion_matrix, x=class_names, y=class_names, colorscale='Cividis') |
|
fig.update_layout( |
|
width=size*140, |
|
height=size*140, |
|
xaxis=dict(title='Classe Prédite'), |
|
yaxis=dict(title='Classe Réelle') |
|
) |
|
st.plotly_chart(fig) |
|
|
|
def plot_CM_VGG19(): |
|
confusion_lines = [ |
|
[182, 7, 3, 0], |
|
[7, 158, 8, 0], |
|
[8, 21, 142, 5], |
|
[1, 1, 3, 174] |
|
] |
|
|
|
confusion_matrix = np.array(confusion_lines) |
|
class_names = ['Covid', 'Lung opacity', 'Normal', 'Viral Pneumonia'] |
|
size = max(confusion_matrix.shape) |
|
fig = ff.create_annotated_heatmap(z=confusion_matrix, x=class_names, y=class_names, colorscale='Cividis') |
|
fig.update_layout( |
|
width=size*140, |
|
height=size*140, |
|
xaxis=dict(title='Classe Prédite'), |
|
yaxis=dict(title='Classe Réelle') |
|
) |
|
st.plotly_chart(fig) |
|
|
|
def plot_CM_ConvnextTiny(): |
|
confusion_lines = [ |
|
[122, 11, 19, 0], |
|
[13, 142, 15, 0], |
|
[17, 14, 144, 1], |
|
[4, 1, 7, 168] |
|
] |
|
|
|
confusion_matrix = np.array(confusion_lines) |
|
class_names = ['Covid', 'Lung opacity', 'Normal', 'Viral Pneumonia'] |
|
size = max(confusion_matrix.shape) |
|
fig = ff.create_annotated_heatmap(z=confusion_matrix, x=class_names, y=class_names, colorscale='Cividis') |
|
fig.update_layout( |
|
width=size*140, |
|
height=size*140, |
|
xaxis=dict(title='Classe Prédite'), |
|
yaxis=dict(title='Classe Réelle') |
|
) |
|
st.plotly_chart(fig) |
|
|
|
def plot_CM_ConvnextBase(): |
|
confusion_lines = [ |
|
[168, 9, 15, 0], |
|
[9, 152, 12, 0], |
|
[12, 8, 153, 3], |
|
[2, 0, 8, 169] |
|
] |
|
|
|
confusion_matrix = np.array(confusion_lines) |
|
class_names = ['Covid', 'Lung opacity', 'Normal', 'Viral Pneumonia'] |
|
size = max(confusion_matrix.shape) |
|
fig = ff.create_annotated_heatmap(z=confusion_matrix, x=class_names, y=class_names, colorscale='Cividis') |
|
fig.update_layout( |
|
width=size*140, |
|
height=size*140, |
|
xaxis=dict(title='Classe Prédite'), |
|
yaxis=dict(title='Classe Réelle') |
|
) |
|
st.plotly_chart(fig) |
|
|
|
def plot_CM_EfficientNet_B4(): |
|
confusion_lines = [ |
|
[177, 17, 10, 0], |
|
[3, 148, 30, 0], |
|
[1, 13, 151, 0], |
|
[2, 1, 9, 158] |
|
] |
|
|
|
confusion_matrix = np.array(confusion_lines) |
|
class_names = ['Covid', 'Lung opacity', 'Normal', 'Viral Pneumonia'] |
|
size = max(confusion_matrix.shape) |
|
fig = ff.create_annotated_heatmap(z=confusion_matrix, x=class_names, y=class_names, colorscale='Cividis') |
|
fig.update_layout( |
|
width=size*140, |
|
height=size*140, |
|
xaxis=dict(title='Classe Prédite'), |
|
yaxis=dict(title='Classe Réelle') |
|
) |
|
st.plotly_chart(fig) |
|
|
|
def plot_CM_VGG16_FT(): |
|
confusion_lines = [ |
|
[229, 7, 6, 0], |
|
[1, 198, 16, 1], |
|
[7, 6, 199, 4], |
|
[0, 0, 1, 225] |
|
] |
|
|
|
confusion_matrix = np.array(confusion_lines) |
|
class_names = ['Covid', 'Lung opacity', 'Normal', 'Viral Pneumonia'] |
|
size = max(confusion_matrix.shape) |
|
fig = ff.create_annotated_heatmap(z=confusion_matrix, x=class_names, y=class_names, colorscale='Cividis') |
|
fig.update_layout( |
|
width=size*140, |
|
height=size*140, |
|
xaxis=dict(title='Classe Prédite'), |
|
yaxis=dict(title='Classe Réelle') |
|
) |
|
st.plotly_chart(fig) |
|
|
|
def plot_CM_ResNetFT(): |
|
|
|
confusion_lines = [ |
|
[278, 6, 3, 1], |
|
[3, 242, 16, 0], |
|
[7, 38, 197, 17], |
|
[2, 1, 0, 265] |
|
] |
|
|
|
confusion_matrix = np.array(confusion_lines) |
|
class_names = ['Covid', 'Lung opacity', 'Normal', 'Viral Pneumonia'] |
|
size = max(confusion_matrix.shape) |
|
fig = ff.create_annotated_heatmap(z=confusion_matrix, x=class_names, y=class_names, colorscale='Cividis') |
|
fig.update_layout( |
|
width=size*140, |
|
height=size*140, |
|
xaxis=dict(title='Classe Prédite'), |
|
yaxis=dict(title='Classe Réelle') |
|
) |
|
st.plotly_chart(fig) |
|
|
|
def plot_CM_DenseNetFT(): |
|
confusion_lines = [ |
|
[285, 1, 2, 0], |
|
[3,235 , 23, 0], |
|
[5, 17, 232, 5], |
|
[0, 0, 3, 265] |
|
] |
|
|
|
confusion_matrix = np.array(confusion_lines) |
|
class_names = ['Covid', 'Lung opacity', 'Normal', 'Viral Pneumonia'] |
|
size = max(confusion_matrix.shape) |
|
fig = ff.create_annotated_heatmap(z=confusion_matrix, x=class_names, y=class_names, colorscale='Cividis') |
|
fig.update_layout( |
|
width=size*140, |
|
height=size*140, |
|
xaxis=dict(title='Classe Prédite'), |
|
yaxis=dict(title='Classe Réelle') |
|
) |
|
st.plotly_chart(fig) |
|
|
|
def plot_CM_ENetB4(): |
|
confusion_lines = [ |
|
[282, 2, 3, 1], |
|
[4, 244, 13, 0], |
|
[2, 22, 220, 15], |
|
[1, 0, 0, 267] |
|
] |
|
|
|
confusion_matrix = np.array(confusion_lines) |
|
class_names = ['Covid', 'Lung opacity', 'Normal', 'Viral Pneumonia'] |
|
size = max(confusion_matrix.shape) |
|
fig = ff.create_annotated_heatmap(z=confusion_matrix, x=class_names, y=class_names, colorscale='Cividis') |
|
fig.update_layout( |
|
width=size*140, |
|
height=size*140, |
|
xaxis=dict(title='Classe Prédite'), |
|
yaxis=dict(title='Classe Réelle') |
|
) |
|
st.plotly_chart(fig) |
|
|
|
|
|
def make_gradcam_heatmap(img_array, model, last_conv_layer_name, pred_index=None): |
|
model_output = model.output if isinstance(model.output, list) else [model.output] |
|
grad_model = tf.keras.models.Model( |
|
inputs=model.inputs, |
|
outputs=[model.get_layer(last_conv_layer_name).output] + model_output |
|
) |
|
|
|
with tf.GradientTape() as tape: |
|
last_conv_layer_output, preds = grad_model(img_array) |
|
if pred_index is None: |
|
pred_index = tf.argmax(preds[0]) |
|
class_channel = preds[:, pred_index] |
|
|
|
grads = tape.gradient(class_channel, last_conv_layer_output) |
|
|
|
pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2)) |
|
|
|
last_conv_layer_output = last_conv_layer_output[0] |
|
heatmap = last_conv_layer_output @ pooled_grads[..., tf.newaxis] |
|
heatmap = tf.squeeze(heatmap) |
|
|
|
heatmap = tf.maximum(heatmap, 0) / tf.math.reduce_max(heatmap) |
|
return heatmap.numpy() |
|
|
|
def save_and_display_gradcam(img, heatmap, alpha=0.4): |
|
heatmap = np.uint8(255 * heatmap) |
|
|
|
jet = plt.cm.jet |
|
|
|
jet_colors = jet(np.arange(256))[:, :3] |
|
jet_heatmap = jet_colors[heatmap] |
|
|
|
jet_heatmap = array_to_img(jet_heatmap) |
|
jet_heatmap = jet_heatmap.resize((img.shape[1], img.shape[0])) |
|
jet_heatmap = img_to_array(jet_heatmap) |
|
|
|
superimposed_img = jet_heatmap * alpha + img |
|
superimposed_img = array_to_img(superimposed_img) |
|
|
|
return superimposed_img |
|
|