Skip to content

Commit d49a882

Browse files
committed
Initial commit: Organized Edge Deployment Model
0 parents  commit d49a882

42 files changed

Lines changed: 12936 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
build/
12+
develop-eggs/
13+
dist/
14+
downloads/
15+
eggs/
16+
.eggs/
17+
lib/
18+
lib64/
19+
parts/
20+
sdist/
21+
var/
22+
wheels/
23+
share/python-wheels/
24+
*.egg-info/
25+
.installed.cfg
26+
*.egg
27+
MANIFEST
28+
29+
# Virtual environments
30+
venv/
31+
env/
32+
.env
33+
.venv
34+
ENV/
35+
env.bak/
36+
venv.bak/
37+
38+
# Environment variables
39+
.env
40+
41+
# Jupyter Notebook
42+
.ipynb_checkpoints
43+
44+
# IDEs
45+
.vscode/
46+
.idea/
47+
*.swp
48+
*.swo
49+
50+
# Output and runtime directories
51+
output/
52+
trt_cache/
53+
54+
# Large files to ignore (though some models are tracked explicitly)
55+
# *.pt
56+
# *.onnx
57+
# *.whl

README.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Edge Deployable Deep Learning Model For Image Analysis
2+
3+
This repository contains the complete pipeline for an edge-deployable computer vision model designed to analyze images and detect insulator defects. The model is trained to be lightweight and optimized, ensuring it runs efficiently on edge devices like the **Nvidia Jetson Nano**.
4+
5+
## Dataset
6+
7+
The model was trained and evaluated on the **Insulator Defect Detection Dataset (IDID)**. The dataset consists of images categorized into three main classes:
8+
- `0: good`
9+
- `1: broken`
10+
- `2: flashover`
11+
12+
## Repository Structure
13+
14+
```text
15+
├── data/
16+
│ └── sample_images/ # Sample images for testing the model
17+
├── deployment/ # Edge deployment scripts (Jetson Nano/Local PC)
18+
│ ├── app.py # Streamlit web UI for defect diagnosis
19+
│ ├── best.onnx # Final optimized ONNX model
20+
│ ├── test2.py # Batch image inference script
21+
│ └── webcam_inference.py # Real-time webcam inference script
22+
├── docs/ # Project reports and presentations
23+
├── models/ # PyTorch model weights (.pt)
24+
│ ├── pruned_model.pt # Pruned YOLOv8 model
25+
│ ├── student_model.pt # Distilled YOLOv8 student model
26+
│ └── teacher_model.pt # Heavy baseline YOLOv8 teacher model
27+
├── training/ # Jupyter Notebooks for the training pipeline
28+
│ ├── preprocessing_teacher.ipynb
29+
│ ├── student_training.ipynb
30+
│ ├── pruning.ipynb
31+
│ └── onnx_conversion.ipynb
32+
├── requirements.txt # Project dependencies
33+
└── README.md # Project documentation
34+
```
35+
36+
---
37+
38+
## 🚀 Execution Workflow & Environments
39+
40+
The development of this project was split across cloud GPUs (for training) and Edge Devices (for inference).
41+
42+
### Phase 1: Training & Optimization (Environment: Kaggle / Google Colab)
43+
All `.ipynb` files in the `training/` folder were executed on cloud platforms (Kaggle/Google Colab) to leverage powerful GPUs. The workflow is strictly sequential:
44+
45+
1. **`preprocessing_teacher.ipynb`**: Preprocesses the IDID dataset and trains the heavy baseline teacher model (`teacher_model.pt`).
46+
2. **`student_training.ipynb`**: Applies Knowledge Distillation to transfer knowledge from the heavy teacher to a lightweight student model (`student_model.pt`).
47+
3. **`pruning.ipynb`**: Structurally prunes the student model to reduce its parameter count and physical size while maintaining accuracy (`pruned_model.pt`).
48+
4. **`onnx_conversion.ipynb`**: Converts the final optimized PyTorch model to the ONNX format (`best.onnx`) for high-speed inference on edge devices.
49+
50+
### Phase 2: Edge Deployment (Environment: Nvidia Jetson Nano / Local PC)
51+
Once the `best.onnx` model was generated, it was transferred to the **Nvidia Jetson Nano** for real-time edge deployment.
52+
53+
#### Jetson Nano Setup Requirements
54+
Before running the deployment scripts on the Jetson Nano, ensure your device is flashed with the appropriate NVIDIA JetPack SDK.
55+
- [Official Nvidia Jetson Nano Developer Kit Setup Guide](https://developer.nvidia.com/embedded/learn/get-started-jetson-nano-devkit)
56+
57+
> **Note:** The `deployment/` folder includes an `onnxruntime_gpu-1.11.0-cp38-cp38-linux_aarch64.whl` file, which is specifically required for enabling hardware-accelerated ONNX inference on the Jetson's ARM64 architecture.
58+
59+
---
60+
61+
## 🛠️ How to Run Inference
62+
63+
You can run the deployment scripts on a Jetson Nano or your Local PC (using CPU/GPU).
64+
65+
### 1. Install Dependencies
66+
```bash
67+
pip install -r requirements.txt
68+
```
69+
*(If on Jetson Nano, install the provided ONNX Runtime `.whl` wheel manually: `pip install deployment/onnxruntime_gpu-1.11.0-cp38-cp38-linux_aarch64.whl`)*
70+
71+
### 2. Navigate and Activate Environment
72+
```bash
73+
cd deployment
74+
source venv/bin/activate # Or your appropriate virtual environment activation command
75+
```
76+
77+
### 3. Choose your Inference Method:
78+
79+
- **Batch Image Processing** (Processes images from `data/sample_images/`):
80+
```bash
81+
python test2.py
82+
```
83+
84+
- **Real-Time Webcam Processing**:
85+
```bash
86+
python webcam_inference.py
87+
```
88+
89+
- **Interactive Web UI (Streamlit)**:
90+
```bash
91+
streamlit run app.py
92+
```
93+
94+
> **Note:** When you are done, you can exit the virtual environment by running `deactivate`.
95+
96+
Processed output images and logs will automatically be saved to the `deployment/output/` directory.
97+
98+
---
99+
100+
## 👥 Contributors
101+
102+
- **Gaurav Chhajed** - [GauravChhajed](https://github.com/GauravChhajed)
103+
- **Jay Sah** - [Jaysah02](https://github.com/Jaysah02)
104+
105+
---
106+
107+
**GitHub Repository:** [Edge_deployable_DeepLearning_Model_for_Image_Analysis](https://github.com/GauravChhajed/Edge_deployable_DeepLearning_Model_for_Image_Analysis)

data/sample_images/Input4.png

12.2 MB
Loading

data/sample_images/input1.png

885 KB
Loading

data/sample_images/input2.png

169 KB
Loading

data/sample_images/input3.jpeg

244 KB
Loading

data/sample_images/input5.jpeg

194 KB
Loading

data/sample_images/input6.jpeg

249 KB
Loading

deployment/app.py

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
import streamlit as st
2+
import cv2
3+
import numpy as np
4+
import onnxruntime as ort
5+
from PIL import Image
6+
import time
7+
import os
8+
from datetime import datetime
9+
10+
# =========================
11+
# GLOBALS & SETTINGS
12+
# =========================
13+
ort.set_default_logger_severity(3)
14+
15+
CLASS_NAMES = {
16+
0: "good",
17+
1: "broken",
18+
2: "flashover"
19+
}
20+
21+
BBOX_COLOR = (0, 255, 0) # Bright Green
22+
BBOX_THICKNESS = 3
23+
24+
# Ensure output directory exists locally
25+
OUTPUT_DIR = "output"
26+
os.makedirs(OUTPUT_DIR, exist_ok=True)
27+
28+
# =========================
29+
# CACHED MODEL LOADING
30+
# =========================
31+
@st.cache_resource
32+
def load_model():
33+
model_path = 'best.onnx'
34+
35+
providers = [
36+
(
37+
"TensorrtExecutionProvider",
38+
{
39+
"trt_fp16_enable": True,
40+
"trt_engine_cache_enable": True,
41+
"trt_engine_cache_path": "./trt_cache",
42+
"trt_max_workspace_size": 1073741824
43+
}
44+
),
45+
"CUDAExecutionProvider"
46+
]
47+
48+
sess_options = ort.SessionOptions()
49+
sess_options.log_severity_level = 3
50+
51+
session = ort.InferenceSession(
52+
model_path,
53+
sess_options=sess_options,
54+
providers=providers
55+
)
56+
57+
input_name = session.get_inputs()[0].name
58+
return session, input_name
59+
60+
# =========================
61+
# INFERENCE FUNCTION
62+
# =========================
63+
def run_inference(img, session, input_name, conf_thresh):
64+
img_h, img_w = img.shape[:2]
65+
66+
# Preprocess
67+
input_img = cv2.resize(img, (640, 640))
68+
input_img = input_img.transpose(2, 0, 1)
69+
input_img = np.expand_dims(input_img, axis=0).astype(np.float32) / 255.0
70+
71+
# Inference
72+
start_time = time.time()
73+
outputs = session.run(None, {input_name: input_img})
74+
infer_time = (time.time() - start_time) * 1000
75+
76+
# Postprocess
77+
predictions = np.squeeze(outputs[0]).T
78+
boxes, scores, class_ids = [], [], []
79+
80+
x_factor = img_w / 640
81+
y_factor = img_h / 640
82+
83+
for row in predictions:
84+
class_scores = row[4:]
85+
max_score = np.max(class_scores)
86+
87+
if max_score > conf_thresh:
88+
class_id = np.argmax(class_scores)
89+
xc, yc, w, h = row[0], row[1], row[2], row[3]
90+
91+
x_min = int((xc - w / 2) * x_factor)
92+
y_min = int((yc - h / 2) * y_factor)
93+
width = int(w * x_factor)
94+
height = int(h * y_factor)
95+
96+
boxes.append([x_min, y_min, width, height])
97+
scores.append(float(max_score))
98+
class_ids.append(class_id)
99+
100+
indices = cv2.dnn.NMSBoxes(boxes, scores, score_threshold=conf_thresh, nms_threshold=0.4)
101+
102+
defects_found = len(indices) if len(indices) > 0 else 0
103+
104+
# Draw Boxes
105+
if defects_found > 0:
106+
for i in indices.flatten():
107+
x, y, w, h = boxes[i]
108+
current_class_id = class_ids[i]
109+
class_name = CLASS_NAMES.get(current_class_id, f"Class {current_class_id}")
110+
111+
cv2.rectangle(img, (x, y), (x + w, y + h), BBOX_COLOR, BBOX_THICKNESS)
112+
label = f"{class_name}: {scores[i]:.2f}"
113+
(tw, th), _ = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.6, 2)
114+
cv2.rectangle(img, (x, y - th - 10), (x + tw, y), BBOX_COLOR, -1)
115+
cv2.putText(img, label, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 0), 2)
116+
117+
return img, defects_found, infer_time
118+
119+
# =========================
120+
# STREAMLIT UI LAYOUT
121+
# =========================
122+
st.set_page_config(page_title="Defect Diagnosis UI", layout="wide")
123+
124+
st.title("🔍 Edge AI Defect Diagnosis")
125+
st.markdown("Run TensorRT-optimized YOLOv8 inference directly from your browser.")
126+
127+
# Load Model
128+
with st.spinner('Loading TensorRT Engine...'):
129+
session, input_name = load_model()
130+
131+
# Sidebar controls
132+
st.sidebar.header("Settings")
133+
confidence_threshold = st.sidebar.slider(
134+
"Confidence Threshold",
135+
min_value=0.1, max_value=1.0, value=0.3, step=0.05
136+
)
137+
138+
st.sidebar.divider()
139+
140+
# Input Method Selector
141+
input_method = st.sidebar.radio(
142+
"Choose Input Method:",
143+
("📁 Upload Image(s)", "📷 Webcam Capture")
144+
)
145+
146+
st.sidebar.info(f"Processed images are automatically saved to `./{OUTPUT_DIR}/`")
147+
148+
# ----------------------------------------
149+
# MODE 1: FILE UPLOAD (Single or Multiple)
150+
# ----------------------------------------
151+
if input_method == "📁 Upload Image(s)":
152+
uploaded_files = st.file_uploader(
153+
"Upload images (Select multiple files to process a batch)",
154+
type=["jpg", "jpeg", "png"],
155+
accept_multiple_files=True
156+
)
157+
158+
if uploaded_files:
159+
cols = st.columns(2) # Create a 2-column grid
160+
161+
for idx, uploaded_file in enumerate(uploaded_files):
162+
# Read image
163+
image = Image.open(uploaded_file)
164+
img_array = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
165+
166+
# Run Inference
167+
result_img, defect_count, inf_time = run_inference(
168+
img_array, session, input_name, confidence_threshold
169+
)
170+
171+
# Save to output folder
172+
output_filepath = os.path.join(OUTPUT_DIR, uploaded_file.name)
173+
cv2.imwrite(output_filepath, result_img)
174+
175+
# Display in UI
176+
result_img_rgb = cv2.cvtColor(result_img, cv2.COLOR_BGR2RGB)
177+
with cols[idx % 2]:
178+
st.image(result_img_rgb, caption=f"{uploaded_file.name}")
179+
st.write(f"**Defects Found:** {defect_count} | **Time:** {inf_time:.2f} ms")
180+
st.divider()
181+
182+
# ----------------------------------------
183+
# MODE 2: WEBCAM CAPTURE
184+
# ----------------------------------------
185+
elif input_method == "📷 Webcam Capture":
186+
# Streamlit native webcam widget
187+
camera_image = st.camera_input("Take a picture to analyze")
188+
189+
if camera_image is not None:
190+
# Read image from camera buffer
191+
image = Image.open(camera_image)
192+
img_array = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
193+
194+
# Run Inference
195+
result_img, defect_count, inf_time = run_inference(
196+
img_array, session, input_name, confidence_threshold
197+
)
198+
199+
# Generate a unique filename using timestamp
200+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
201+
filename = f"webcam_{timestamp}.jpg"
202+
output_filepath = os.path.join(OUTPUT_DIR, filename)
203+
204+
# Save to output folder
205+
cv2.imwrite(output_filepath, result_img)
206+
207+
# Display in UI
208+
result_img_rgb = cv2.cvtColor(result_img, cv2.COLOR_BGR2RGB)
209+
210+
st.success(f"Image processed and saved locally as `{filename}`")
211+
st.image(result_img_rgb, caption="Webcam Analysis Result")
212+
st.write(f"**Defects Found:** {defect_count}")
213+
st.write(f"**Inference Time:** {inf_time:.2f} ms")

deployment/best.onnx

9.43 MB
Binary file not shown.

0 commit comments

Comments
 (0)