import streamlit as st import cv2 import numpy as np import tensorflow as tf from tensorflow.keras.preprocessing import image from tensorflow.keras.models import load_model import pandas as pd class GradCAM: def __init__(self, model, layer_name): self.model = model self.layer_name = layer_name self.grad_model = tf.keras.models.Model( [self.model.inputs], [self.model.get_layer(layer_name).output, self.model.output] ) def __call__(self, img_array, cls): with tf.GradientTape() as tape: conv_outputs, predictions = self.grad_model(img_array) loss = predictions[:, cls] output = conv_outputs[0] grads = tape.gradient(loss, conv_outputs)[0] gate_f = tf.cast(output > 0, 'float32') gate_r = tf.cast(grads > 0, 'float32') guided_grads = gate_f * gate_r * grads weights = tf.reduce_mean(guided_grads, axis=(0, 1)) cam = np.zeros(output.shape[0:2], dtype=np.float32) for index, w in enumerate(weights): cam += w * output[:, :, index] cam = cv2.resize(cam.numpy(), (224, 224)) cam = np.maximum(cam, 0) cam = cam / cam.max() return cam def apply_heatmap(img, heatmap, heatmap_ratio=0.6): heatmap = cv2.applyColorMap(np.uint8(255 * heatmap), cv2.COLORMAP_JET) heatmap = cv2.cvtColor(heatmap, cv2.COLOR_BGR2RGB) return np.uint8(heatmap * heatmap_ratio + img * (1 - heatmap_ratio)) def load_image(img_path, df, preprocess=True, H=320, W=320): mean, std = get_mean_std_per_batch(img_path, df, H=H, W=W) x = image.load_img(img_path, target_size=(H, W)) x = image.img_to_array(x) if preprocess: x -= mean x /= std x = np.expand_dims(x, axis=0) return x def get_mean_std_per_batch(image_path, df, H=320, W=320): sample_data = [] for idx, img in enumerate(df.sample(100)["Image Index"].values): sample_data.append( np.array(image.load_img(image_path, target_size=(H, W)))) mean = np.mean(sample_data[0]) std = np.std(sample_data[0]) return mean, std def compute_gradcam(img, model, df, labels, layer_name='bn'): preprocessed_input = load_image(img, df) predictions = model.predict(preprocessed_input) top_indices = np.argsort(predictions[0])[-3:][::-1] top_labels = [labels[i] for i in top_indices] top_predictions = [predictions[0][i] for i in top_indices] original_image = load_image(img, df, preprocess=False) grad_cam = GradCAM(model, layer_name) gradcam_images = [] for i in range(3): idx = top_indices[i] label = top_labels[i] prob = top_predictions[i] gradcam = grad_cam(preprocessed_input, idx) gradcam_image = apply_heatmap(original_image, gradcam) gradcam_images.append((gradcam_image, f"{label}: p={prob:.3f}")) return gradcam_images def calculate_mse(original_image, enhanced_image): mse = np.mean((original_image - enhanced_image) ** 2) return mse def calculate_psnr(original_image, enhanced_image): mse = calculate_mse(original_image, enhanced_image) if mse == 0: return float('inf') max_pixel_value = 255.0 psnr = 20 * np.log10(max_pixel_value / np.sqrt(mse)) return psnr def calculate_maxerr(original_image, enhanced_image): maxerr = np.max((original_image - enhanced_image) ** 2) return maxerr def calculate_l2rat(original_image, enhanced_image): l2norm_ratio = np.sum(original_image ** 2) / np.sum((original_image - enhanced_image) ** 2) return l2norm_ratio def process_image(original_image, enhancement_type, fix_monochrome=True): if fix_monochrome and original_image.shape[-1] == 3: original_image = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY) image = original_image - np.min(original_image) image = image / np.max(original_image) image = (image * 255).astype(np.uint8) enhanced_image = enhance_image(image, enhancement_type) mse = calculate_mse(original_image, enhanced_image) psnr = calculate_psnr(original_image, enhanced_image) maxerr = calculate_maxerr(original_image, enhanced_image) l2rat = calculate_l2rat(original_image, enhanced_image) return enhanced_image, mse, psnr, maxerr, l2rat def apply_clahe(image): clahe = cv2.createCLAHE(clipLimit=40.0, tileGridSize=(8, 8)) return clahe.apply(image) def invert(image): return cv2.bitwise_not(image) def hp_filter(image, kernel=None): if kernel is None: kernel = np.array([[-1, -1, -1], [-1, 9, -1], [-1, -1, -1]]) return cv2.filter2D(image, -1, kernel) def unsharp_mask(image, radius=5, amount=2): def usm(image, radius, amount): blurred = cv2.GaussianBlur(image, (0, 0), radius) sharpened = cv2.addWeighted(image, 1.0 + amount, blurred, -amount, 0) return sharpened return usm(image, radius, amount) def hist_eq(image): return cv2.equalizeHist(image) def enhance_image(image, enhancement_type): if enhancement_type == "Invert": return invert(image) elif enhancement_type == "High Pass Filter": return hp_filter(image) elif enhancement_type == "Unsharp Masking": return unsharp_mask(image) elif enhancement_type == "Histogram Equalization": return hist_eq(image) elif enhancement_type == "CLAHE": return apply_clahe(image) else: raise ValueError(f"Unknown enhancement type: {enhancement_type}") st.title("Image Enhancement and Quality Evaluation") uploaded_file = st.file_uploader("Upload Original Image", type=["png", "jpg", "jpeg"]) enhancement_type = st.radio("Enhancement Type", ["Invert", "High Pass Filter", "Unsharp Masking", "Histogram Equalization", "CLAHE"]) if uploaded_file is not None: original_image = np.array(image.load_img(uploaded_file, color_mode='rgb' if enhancement_type == "Invert" else 'grayscale')) enhanced_image, mse, psnr, maxerr, l2rat = process_image(original_image, enhancement_type) st.image(original_image, caption='Original Image', use_column_width=True) st.image(enhanced_image, caption='Enhanced Image', use_column_width=True) st.write("MSE:", mse) st.write("PSNR:", psnr) st.write("Maxerr:", maxerr) st.write("L2Rat:", l2rat) st.title("Grad-CAM Visualization") uploaded_gradcam_file = st.file_uploader("Upload Image for Grad-CAM", type=["png", "jpg", "jpeg"], key="gradcam") if uploaded_gradcam_file is not None: df_file = st.file_uploader("Upload DataFrame for Mean/Std Calculation", type=["csv"]) labels = st.text_area("Labels", placeholder="Enter labels separated by commas") model_path = st.text_input("Model Path", 'model/densenet.hdf5') pretrained_model_path = st.text_input("Pretrained Model Path", 'model/pretrained_model.h5') if df_file and labels and model_path and pretrained_model_path: df = pd.read_csv(df_file) labels = labels.split(',') model = load_model(model_path) pretrained_model = load_model(pretrained_model_path) gradcam_images = compute_gradcam(uploaded_gradcam_file, pretrained_model, df, labels) for idx, (gradcam_image, label) in enumerate(gradcam_images): st.image(gradcam_image, caption=f'Grad-CAM {idx+1}: {label}', use_column_width=True)