import streamlit as st import tensorflow as tf import numpy as np import time # ========================================================== # PROJECT: Machine Fault Detection using CNN # ========================================================== PROJECT_INFO = { "name" : "Machine Fault Diagnosis Using Deep Learning Approach", "version" : "1.0.0", "description" : "Vibration signal image classification", "classes" : ["Bearing Fault","Bent Shaft","Foundation Looseness","Healthy","Misalignment"], "channels" : ["CH1", "CH2", "CH3"], "img_size" : (224, 224), "num_classes" : 5, "framework" : "TensorFlow / Keras", } # ══════════════════════════════════════════════════════════════ # CONFIG # ══════════════════════════════════════════════════════════════ MODEL_PATH = r"C:\Users\HP\Python\saved_models\best_model.keras" IMG_H, IMG_W = 128, 256 CLASS_NAMES = [ "Bearing Fault", "Bent Shaft", "Foundation Looseness", "Healthy", "Misalignment", ] CLASS_INFO = { "Bearing Fault": "A bearing fault refers to damage or defects in the rolling elements, " "inner race, or outer race of a bearing. This causes periodic impulses " "in the vibration signal at characteristic defect frequencies (BPFO, BPFI, BSF, FTF).", "Bent Shaft": "A bent shaft causes excessive vibration at 1× and 2× the running speed. " "It leads to unbalanced rotational forces, increased bearing load, and " "accelerated wear of connected components.", "Foundation Looseness": "Foundation looseness occurs when the machine base or structural mounts " "are not properly secured. This creates non-linear vibration patterns " "and can cause secondary damage if left unaddressed.", "Healthy": "The machine is operating under normal healthy conditions. No faults " "detected in the vibration signal. Routine monitoring and scheduled " "maintenance is recommended to maintain this condition.", "Misalignment": "Shaft misalignment occurs when two coupled shafts are not collinear. " "Angular or parallel misalignment generates high vibration at 1× and 2× " "frequencies and causes premature bearing and coupling failure.", } CLASS_ACTION = { "Bearing Fault": "🔧 Schedule immediate bearing inspection. Check lubrication levels and " "bearing clearances. Replace damaged bearing within the next maintenance window. " "Monitor temperature and vibration amplitude until replacement.", "Bent Shaft": "🔧 Shut down the machine for shaft inspection. Perform dial-indicator runout " "measurement. Replace or straighten the shaft before resuming operation. " "Inspect associated couplings and bearings for secondary damage.", "Foundation Looseness": "🔧 Inspect all anchor bolts and mounting hardware. Re-torque foundation bolts " "to specification. Check for cracks in the machine base or mounting surface. " "Perform resonance test after re-tightening.", "Healthy": "✅ No immediate action required. Continue routine vibration monitoring as per " "maintenance schedule. Log this reading for trend analysis and baseline comparison.", "Misalignment": "🔧 Perform precision shaft alignment using laser alignment tools. Check coupling " "condition and re-align to manufacturer tolerance before next operation. " "Record alignment readings before and after correction.", } CLASS_SEVERITY = { "Bearing Fault": ("HIGH", "#E53E3E"), "Bent Shaft": ("HIGH", "#E53E3E"), "Foundation Looseness": ("MEDIUM", "#DD6B20"), "Healthy": ("NONE", "#38A169"), "Misalignment": ("MEDIUM", "#DD6B20"), } CLASS_ICONS = { "Bearing Fault": "⊙", "Bent Shaft": "↬", "Foundation Looseness": "⚠", "Healthy": "✔", "Misalignment": "⇹", } # ══════════════════════════════════════════════════════════════ # PAGE CONFIG # ══════════════════════════════════════════════════════════════ st.set_page_config( page_title="Machine Fault Diagnosis | CNN", page_icon="⚙️", layout="wide", initial_sidebar_state="expanded" ) # ══════════════════════════════════════════════════════════════ # CSS # ══════════════════════════════════════════════════════════════ st.markdown(""" """, unsafe_allow_html=True) # ══════════════════════════════════════════════════════════════ # LOAD MODEL # ══════════════════════════════════════════════════════════════ @st.cache_resource def load_model(): return tf.keras.models.load_model(MODEL_PATH) # ══════════════════════════════════════════════════════════════ # PREPROCESS # ══════════════════════════════════════════════════════════════ def preprocess(uploaded_file) -> np.ndarray: raw_bytes = uploaded_file.getvalue() img = tf.image.decode_png(raw_bytes, channels=1) img = tf.image.resize(img, [IMG_H, IMG_W]) img = tf.cast(img, tf.float32) / 255.0 img = tf.expand_dims(img, axis=0) return img.numpy() # ══════════════════════════════════════════════════════════════ # SESSION STATE # ══════════════════════════════════════════════════════════════ if "page" not in st.session_state: st.session_state.page = "diagnosis" # ══════════════════════════════════════════════════════════════ # SIDEBAR # ══════════════════════════════════════════════════════════════ with st.sidebar: st.markdown(""" """, unsafe_allow_html=True) st.markdown("
Navigation
", unsafe_allow_html=True) if st.button("🔍 Fault Diagnosis", key="sb_diag", use_container_width=True, type="primary" if st.session_state.page == "diagnosis" else "secondary"): st.session_state.page = "diagnosis" st.rerun() if st.button("📘 Project Info", key="sb_about", use_container_width=True, type="primary" if st.session_state.page == "about" else "secondary"): st.session_state.page = "about" st.rerun() st.markdown("
Fault Reference
", unsafe_allow_html=True) for cls in CLASS_NAMES: severity, sev_color = CLASS_SEVERITY[cls] icon = CLASS_ICONS[cls] st.markdown( "
" f"{icon}" "
" f"
{cls}
" f"
{severity} SEVERITY
" "
" "
", unsafe_allow_html=True ) st.markdown("
Dataset
", unsafe_allow_html=True) st.markdown("""
2,400
Train
300
Val
300
Test
5
Classes
""", unsafe_allow_html=True) st.markdown(""" """, unsafe_allow_html=True) # ══════════════════════════════════════════════════════════════ # PAGE: ABOUT PROJECT # ══════════════════════════════════════════════════════════════ if st.session_state.page == "about": # Nav row: spacer (left) | Back button (right) _spacer, _btn_col = st.columns([12, 2]) with _btn_col: if st.button("← Back to Diagnosis", key="back_to_diag"): st.session_state.page = "diagnosis" st.rerun() st.markdown("""

Machine Fault Diagnosis using Deep Learning

An AI-powered predictive maintenance system that classifies rotating machine faults from vibration signal images using a custom 4-block Convolutional Neural Network trained on multi-channel accelerometer data.

🎓 Final Year Project 🤖 Deep Learning 📡 Vibration Analysis 🏭 Predictive Maintenance 🔬 Signal Processing
""", unsafe_allow_html=True) col1, col2 = st.columns([1.05, 1], gap="large") with col1: # Project Info table st.markdown("""
🏫 Project Information
📌Project Title
Machine Fault Diagnosis using Deep Learning Approach
🏛️College
St. Vincent Pallotti College of Engineering and Technology, Nagpur
⚙️Department
Mechanical Engineering
📅Academic Year
2026 – 2027  Final Year · Sem VIII
🧠Framework
TensorFlow 2.x Keras
🚀Deployment
Streamlit  Web Application
""", unsafe_allow_html=True) # Problem Statement st.markdown("""
Problem Statement
Faults in rotating machinery pose significant risks to operational reliability, safety, and maintenance efficiency. Conventional fault diagnosis techniques rely heavily on manual feature extraction and expert knowledge, limiting their accuracy under complex operating conditions. This project addresses the need for an automated and reliable machine fault diagnosis system by employing deep learning techniques for accurate detection and classification of machine faults.
""", unsafe_allow_html=True) # Objectives st.markdown("""
🎯 Project Objectives
""", unsafe_allow_html=True) objectives = [ ("Collect & Organise Data", "Build a balanced vibration signal image dataset across 5 fault classes and 3 sensor channels (CH1, CH2, CH3)."), ("Preprocess Signals", "Convert raw time-domain vibration signals to 2D image representations; normalise and augment for robust training."), ("Design CNN Architecture", "Develop a custom 4-block CNN with BatchNorm, Dropout, and Global Average Pooling for efficient feature extraction."), ("Train & Optimise", "Train using Adam optimizer with EarlyStopping, ReduceLROnPlateau, and ModelCheckpoint callbacks."), ("Evaluate Rigorously", "Assess model using accuracy, precision, recall, F1-score, and confusion matrix on a held-out test set."), ("Deploy as Web Application", "Build a real-time Streamlit diagnostic application for live vibration signal image classification."), ] for i, (title, desc) in enumerate(objectives, 1): st.markdown( "
" f"
{i}
" f"
{title}: {desc}
" "
", unsafe_allow_html=True ) st.markdown("
", unsafe_allow_html=True) with col2: # Team st.markdown("""
👥 Project Team
🎓
Project Guide
Dr. Amit R Bhende
Department of Mechanical Engineering
Student Members
👨‍💻
Vedant Giri
Member 1
👨‍💻
Tushar Kamble
Member 2
👨‍💻
Sanskar Patil
Member 3
👨‍💻
Ansheel Salodkar
Member 4
""", unsafe_allow_html=True) # Technologies st.markdown("""
🛠️ Technologies Used
""", unsafe_allow_html=True) tech_groups = { "Deep Learning" : ["TensorFlow 2.x", "Keras", "NumPy"], "Data & Viz" : ["Matplotlib", "Seaborn", "Scikit-learn"], "Deployment" : ["Streamlit", "Python 3.x"], "Environment" : ["Anaconda", "Jupyter Notebook"], } for group, techs in tech_groups.items(): st.markdown( f"
{group}
", unsafe_allow_html=True ) pills = "".join([f"{t}" for t in techs]) st.markdown(f"
{pills}
", unsafe_allow_html=True) st.markdown("
", unsafe_allow_html=True) # Methodology timeline method_steps = [ ("Data Collection", "Vibration signals recorded via accelerometers at CH1, CH2, CH3 across 5 fault conditions."), ("Signal to Image", "Raw time-domain signals converted to 2D grayscale image representations."), ("Preprocessing", "Images resized to 224x224, normalised to [0,1]; augmentation applied on training set only."), ("CNN Training", "4-block custom CNN with BatchNorm, Dropout, GAP; Adam optimizer with smart callbacks."), ("Evaluation", "Confusion matrix, per-class F1-score, precision, recall on 300-image held-out test set."), ("Deployment", "Interactive Streamlit web application for real-time image upload and diagnosis."), ] parts = [ "
", "
🔄 Methodology
", "
", ] for idx, (title, desc) in enumerate(method_steps): connector = "" if idx == len(method_steps) - 1 else "
" parts.append( "
" "
" "
" + connector + "
" "
" "
" + title + "
" "
" + desc + "
" "
" "
" ) parts.append("
") st.markdown("".join(parts), unsafe_allow_html=True) # CNN Architecture st.markdown("""
🧠 CNN Architecture Overview
""", unsafe_allow_html=True) arch_cols = st.columns(2, gap="medium") arch_left = [ ("Input Layer", "224 × 224 × 3 — normalised to [0, 1]"), ("Conv Block 1", "Conv2D(32) → BN → Conv2D(32) → BN → MaxPool → Dropout(0.25)"), ("Conv Block 2", "Conv2D(64) → BN → Conv2D(64) → BN → MaxPool → Dropout(0.25)"), ("Conv Block 3", "Conv2D(128) → BN → Conv2D(128) → BN → MaxPool → Dropout(0.30)"), ] arch_right = [ ("Conv Block 4", "Conv2D(256) → BN → Conv2D(256) → BN → MaxPool → Dropout(0.30)"), ("Global Avg Pool", "Replaces Flatten — reduces parameters, controls overfitting"), ("Dense Head", "Dense(256, L2) → BN → Dropout(0.50) → Dense(128) → Dropout(0.40)"), ("Output Layer", "Dense(5) → Softmax — probability over 5 fault classes"), ] with arch_cols[0]: for name, detail in arch_left: st.markdown( "
" f"{name}" f"{detail}" "
", unsafe_allow_html=True ) with arch_cols[1]: for name, detail in arch_right: st.markdown( "
" f"{name}" f"{detail}" "
", unsafe_allow_html=True ) st.markdown("
", unsafe_allow_html=True) # Project Description st.markdown("""
📄 Project Description
This project presents an end-to-end deep learning pipeline for automated machine fault detection and classification. Vibration signals from rotating machinery are acquired using accelerometers placed at three different positions on the machine (Channel 1, 2, and 3), and the time-domain signals are converted into 2D image representations suitable for CNN-based feature extraction.

The custom CNN model consists of four progressively deeper convolutional blocks, each employing dual convolution layers with Batch Normalisation for training stability, followed by Max Pooling for spatial downsampling and Dropout for regularisation. Global Average Pooling replaces the traditional Flatten layer, significantly reducing parameter count and mitigating overfitting.

The training strategy employs the Adam optimiser with a starting learning rate of 0.001, complemented by three callbacks: EarlyStopping (patience=10) to prevent overfitting, ReduceLROnPlateau (factor=0.5, patience=5) to escape training plateaus, and ModelCheckpoint to automatically preserve the best-performing weights based on validation accuracy.

Each sensor channel is treated as an independent sample, tripling the effective training dataset from 800 to 2,400 images. The model is evaluated on a completely held-out test set of 300 images using accuracy, per-class F1-score, precision, recall, and confusion matrix analysis to ensure robust, generalisable performance across all five fault categories.
""", unsafe_allow_html=True) st.markdown(""" """, unsafe_allow_html=True) # ══════════════════════════════════════════════════════════════ # PAGE: FAULT DIAGNOSIS # ══════════════════════════════════════════════════════════════ else: # Nav row: spacer (left) | Project Info button (right) _spacer, _btn_col = st.columns([15, 2]) with _btn_col: if st.button("📘 Project Info", key="topbar_about"): st.session_state.page = "about" st.rerun() st.markdown("""

Machine Fault Diagnosis System

CNN-based vibration signal analysis for predictive maintenance and condition monitoring.

🟢 System Ready ⚙️ CNN Model
""", unsafe_allow_html=True) with st.spinner("Initialising model..."): model = load_model() st.markdown( "
" "
" "Model loaded successfully" "|" f"Input: {model.input_shape}" "|" f"Parameters: {model.count_params():,}" "|" f"Classes: {len(CLASS_NAMES)}" "|" "✅ Ready for inference" "
", unsafe_allow_html=True ) st.markdown("""
📤  Upload Vibration Signal Image
""", unsafe_allow_html=True) uploaded = st.file_uploader( "Upload a vibration signal graph image (PNG / JPG) from CH1, CH2, or CH3", type=["png", "jpg", "jpeg"], label_visibility="visible" ) # ── EMPTY STATE ─────────────────────────────────────────── if uploaded is None: st.markdown("
", unsafe_allow_html=True) st.markdown("""
1
Upload Image
Select a PNG/JPG vibration signal graph from sensor channels CH1, CH2, or CH3.
2
CNN Analysis
The deep learning model automatically extracts fault features from the signal image.
3
Get Diagnosis
View fault class, confidence score, engineering explanation, and recommended action.
""", unsafe_allow_html=True) st.markdown("
", unsafe_allow_html=True) st.markdown("""
📋  Detectable Fault Classes
""", unsafe_allow_html=True) fault_html = "
" for cls in CLASS_NAMES: severity, sev_color = CLASS_SEVERITY[cls] icon = CLASS_ICONS[cls] fault_html += ( "
" f"
{icon}
" f"
{cls}
" f"" f"{severity}" "" "
" ) fault_html += "
" st.markdown(fault_html, unsafe_allow_html=True) st.markdown("
", unsafe_allow_html=True) # ── PREDICTION STATE ────────────────────────────────────── else: with st.spinner("🔍 Analysing vibration signal..."): t0 = time.time() arr = preprocess(uploaded) preds = model.predict(arr, verbose=0)[0] elapsed = time.time() - t0 pred_idx = int(np.argmax(preds)) pred_class = CLASS_NAMES[pred_idx] confidence = float(preds[pred_idx]) * 100 severity, sev_color = CLASS_SEVERITY[pred_class] icon = CLASS_ICONS[pred_class] st.markdown( "
" f"📁{uploaded.name}" f"⏱️{elapsed*1000:.0f} ms inference" f"📐{IMG_W} × {IMG_H} px input" "🧠CNN · Softmax output" "
", unsafe_allow_html=True ) left, right = st.columns([1.1, 1], gap="large") with left: st.markdown("""
🖼️ Uploaded Vibration Signal
""", unsafe_allow_html=True) st.image( uploaded.getvalue(), caption=f"{uploaded.name} | Resized to {IMG_W}×{IMG_H} for inference", use_container_width=True ) st.markdown("
", unsafe_allow_html=True) with right: st.markdown( "
" "
🔍 Diagnosis Result
" f"
" f"{icon}" "
Detected Fault Condition
" f"
{pred_class}
" f"
{confidence:.1f}%
" "
Model Confidence Score
" f"
" f"{severity} SEVERITY" "
" "
" "
", unsafe_allow_html=True ) st.markdown( "
" "
📖 Fault Explanation & Recommended Action
" f"Diagnosis — {icon} {pred_class}" f"
{CLASS_INFO[pred_class]}
" "Recommended Action" f"
{CLASS_ACTION[pred_class]}
" "
", unsafe_allow_html=True ) with st.expander("🔬 Technical Details — Raw Prediction Data"): d1, d2 = st.columns(2) with d1: st.markdown("**Preprocessed Tensor Info**") st.code( f"Shape : {arr.shape}\n" f"Dtype : {arr.dtype}\n" f"Pixel min : {arr.min():.4f}\n" f"Pixel max : {arr.max():.4f}\n" f"Pixel mean : {arr.mean():.4f}\n" f"Inference : {elapsed*1000:.1f} ms" ) with d2: st.markdown("**Raw Softmax Probabilities**") for cls, p in zip(CLASS_NAMES, preds): bar = "█" * int(p * 28) st.code(f"{cls:<22}: {p*100:>6.3f}% {bar}") st.markdown(""" """, unsafe_allow_html=True)