Niharmahesh/Decoding-CNN
0
1import streamlit as st2import numpy as np3from PIL import Image, ImageDraw, ImageFont4from tensorflow.keras.models import Sequential5from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dropout, Layer6from tensorflow.keras.layers import LeakyReLU, ELU7import imageio8import json9from streamlit_lottie import st_lottie10import tensorflow.keras.activations as activations11from tensorflow.keras.layers import Activation12 13# Function to load a Lottie animation from a local file14def load_lottiefile(filepath: str):15 with open(filepath, "r") as file:16 return json.load(file)17 18# Function to display a Lottie animation in the sidebar19def display_lottiefile_sidebar(lottie_json, unique_key):20 st_lottie(lottie_json, speed=1, width=250, height=250, key=unique_key)21 22# Function to parse and preprocess the uploaded image23def parse_image(uploaded_file):24 img = Image.open(uploaded_file)25 img = img.resize((64, 64)).convert('L') # Convert to grayscale26 img = np.array(img)27 img = np.expand_dims(img, axis=0) # Shape (1, 64, 64)28 img = np.expand_dims(img, axis=-1) # Shape (1, 64, 64, 1)29 img = img / 255.0 # Normalize30 return img31 32# Function to dynamically add an activation layer based on user selection33def add_activation_layer(model, activation_name):34 if activation_name == 'leakyrelu':35 model.add(LeakyReLU())36 elif activation_name == 'elu':37 model.add(ELU())38 else:39 # For 'relu', 'sigmoid', 'tanh', 'softmax', 'selu'40 if hasattr(activations, activation_name):41 activation_function = getattr(activations, activation_name)42 model.add(Activation(activation_function))43 else:44 raise ValueError(f"Unsupported activation function: {activation_name}")45 46# Function to create a model and return the feature map47def display_feature_map(img, num_filters, kernel_size, activation, dropout_rate):48 model = Sequential()49 model.add(Conv2D(num_filters, (kernel_size, kernel_size), input_shape=(64, 64, 1)))50 add_activation_layer(model, activation)51 model.add(MaxPooling2D(pool_size=(2, 2)))52 model.add(Dropout(dropout_rate))53 conv2d_output = model.predict(img)54 return conv2d_output55 56def main():57 st.title("Convolutional Neural Network Visualizer")58 with st.sidebar:59 lottie_animation = load_lottiefile("Animation - 1707640885996.json")60 display_lottiefile_sidebar(lottie_animation, "lottie_animation_key")61 st.sidebar.markdown("""62 # Interactive CNN Visualizer Explanation63 This interactive tool allows you to visualize how different parameters of a Convolutional Neural Network (CNN) affect the features detected in an input image. Here's a brief overview of the parameters you can adjust:64 65 ## Filters/Kernels66 - **What they are**: Small matrices of weights that slide over the input image to produce a feature map. Each filter is trained to detect a specific feature in the image, such as edges, corners, or textures.67 68 ## Kernel Size69 - **What it is**: Determines the size of the filter. For example, a kernel size of 3 means the filter is a 3x3 matrix. The kernel size affects the level of detail the filter can capture. Smaller kernels can capture fine-grained details, while larger kernels capture more abstract features.70 71 ## Number of Filters72 - **What it is**: Determines the number of feature maps that will be produced by a Conv2D layer. Each filter is trained to detect a different feature, so having more filters allows the model to recognize a wider variety of features.73 74 ## Activation Function75 - **What it is**: Applied to the feature maps after the convolution operation. It introduces non-linearity into the model, which allows the model to learn more complex patterns. Common choices include ReLU (Rectified Linear Unit), sigmoid, and tanh.76 77 ## MaxPooling78 - **What it is**: This operation reduces the spatial dimensions (i.e., width and height) of the input by taking the maximum value in each window of a certain size. This helps to make the model invariant to small translations and reduces the computational complexity of the model.79 80 In the interactive visualization you've created, you can adjust the number of filters, the kernel size, and the activation function to see how these parameters affect the features that the model detects in the input image.81""", unsafe_allow_html=True)82 83 84 # Architecture parameters input85 num_filters = st.slider('Number of Filters:', 16, 256, 32)86 kernel_size = st.slider('Kernel Size:', 2, 7, 3)87 activation = st.selectbox('Activation Function:', ['relu', 'sigmoid', 'tanh', 'leakyrelu', 'elu'])88 dropout_rate = st.slider('Dropout Rate:', 0.0, 0.5, 0.25)89 90 # Image upload section91 st.subheader("Upload Image")92 uploaded_file = st.file_uploader("", type=["png", "jpg", "jpeg"], help="Choose an image to upload")93 if uploaded_file is not None:94 img = parse_image(uploaded_file)95 st.session_state['uploaded_image'] = img96 st.success("Image uploaded successfully!")97 98 # Process button to visualize the model99 if st.button("Process"):100 if 'uploaded_image' in st.session_state:101 visualize_activation_overlays(st.session_state['uploaded_image'], num_filters, kernel_size, activation, dropout_rate)102 else:103 st.error("Please upload an image first.")104 105 # Reset button to clear session state and start over106 if st.button("Reset"):107 st.session_state.clear()108 st.rerun()109 110def visualize_activation_overlays(img, num_filters, kernel_size, activation, dropout_rate):111 conv2d_output = display_feature_map(img, num_filters, kernel_size, activation, dropout_rate)112 113 # Define the new size for the output images114 new_size = (800, 800) # Example new size, adjust as needed115 116 # Assuming img was normalized to [0, 1], convert back to [0, 255], RGB, and resize117 original_img = np.squeeze(img) * 255.0118 original_img = Image.fromarray(np.uint8(original_img)).convert('RGB').resize(new_size)119 120 frames = [] # To hold each frame for the GIF121 122 for i in range(conv2d_output.shape[-1]): # Iterate through each feature map123 feature_map = conv2d_output[0, :, :, i]124 125 # Normalize the feature map to enhance visualization126 normalized_feature_map = (feature_map - np.min(feature_map)) / (np.max(feature_map) - np.min(feature_map))127 128 # Resize to new output size129 resized_feature_map = Image.fromarray(np.uint8(normalized_feature_map * 255)).resize(new_size, Image.NEAREST)130 131 # Create a mask where high activations are marked132 mask = np.array(resized_feature_map) > 128 # Threshold to identify high activations133 134 # Create an overlay image with red color in the high activation areas135 overlay = np.array(original_img).copy()136 overlay[mask] = [255, 0, 0] # Red color for high activation areas137 138 # Convert numpy array back to PIL Image for display139 overlay_img = Image.fromarray(overlay)140 141 # Draw filter number or text on the image142 draw = ImageDraw.Draw(overlay_img)143 # Specify font size and type (default font here, you can specify a path to a .ttf file for custom fonts)144 font = ImageFont.load_default()145 # Position for the text (bottom left corner in this case)146 text_position = (100, new_size[1] - 30)147 # Drawing text148 draw.text(text_position, f"Filter {i+1}", fill=(255,255,255), font=font)149 150 frames.append(overlay_img)151 152 # Create a GIF from the frames153 gif_path = 'activation_overlay_large.gif'154 imageio.mimsave(gif_path, frames, fps=1) # Adjust fps as needed155 156 # Display the GIF in Streamlit157 st.image(gif_path)158if __name__ == "__main__":159 main()160 