Shivamsinghtomar78 commited on
Commit
ebe77f6
Β·
verified Β·
1 Parent(s): d9eff00

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +189 -188
app.py CHANGED
@@ -1,188 +1,189 @@
1
- import streamlit as st
2
- import cv2
3
- import numpy as np
4
- from PIL import Image
5
- import pandas as pd
6
- import plotly.express as px
7
- import plotly.graph_objects as go
8
- from ultralytics import YOLO
9
- import time
10
-
11
-
12
- st.set_page_config(
13
- page_title="Blood Cell Detection App",
14
- page_icon="πŸ”¬",
15
- layout="wide",
16
- initial_sidebar_state="expanded"
17
- )
18
-
19
- st.markdown("""
20
- <style>
21
- @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600&display=swap');
22
- * { font-family: 'Poppins', sans-serif; }
23
- .main-header { font-size: 2.5rem; font-weight: 600; color: #4B0082; text-align: center; margin-bottom: 1rem; }
24
- .sub-header { font-size: 1.5rem; font-weight: 500; color: #6200EA; margin: 1rem 0; }
25
- .card { background: white; border-radius: 0.8rem; padding: 1rem; margin-bottom: 1rem; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
26
- .stButton>button { background: #6200EA; color: white; border: none; border-radius: 0.5rem; padding: 0.5rem 1rem; }
27
- .metric-card { text-align: center; padding: 1rem; }
28
- .metric-value { font-size: 2rem; font-weight: 600; color: #6200EA; }
29
- .metric-label { font-size: 0.9rem; color: #555; }
30
- .cell-badge { padding: 0.2rem 0.5rem; border-radius: 1rem; font-size: 0.8rem; }
31
- .rbc-badge { background: rgba(255,82,82,0.2); color: #FF5252; border: 1px solid #FF5252; }
32
- .wbc-badge { background: rgba(33,150,243,0.2); color: #2196F3; border: 1px solid #2196F3; }
33
- .plt-badge { background: rgba(76,175,80,0.2); color: #4CAF50; border: 1px solid #4CAF50; }
34
- .footer { text-align: center; padding: 1rem; color: #777; font-size: 0.8rem; border-top: 1px solid #eee; margin-top: 2rem; }
35
- </style>
36
- """, unsafe_allow_html=True)
37
-
38
-
39
- st.markdown("<h1 class='main-header'>Blood Cell Detection System</h1>", unsafe_allow_html=True)
40
-
41
-
42
- tab1, tab2, tab3 = st.tabs(["πŸ“Š Analysis", "ℹ️ About", "❓ Help"])
43
-
44
-
45
- with tab1:
46
-
47
- @st.cache_data
48
- def preprocess_image(uploaded_file):
49
- try:
50
- bytes_data = uploaded_file.getvalue()
51
- img = cv2.imdecode(np.frombuffer(bytes_data, np.uint8), cv2.IMREAD_COLOR)
52
- if img is None:
53
- raise ValueError("Invalid image file")
54
- return cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
55
- except Exception as e:
56
- st.error(f"Error preprocessing image: {str(e)}")
57
- return None
58
-
59
- @st.cache_resource
60
- def load_model():
61
- try:
62
- model = YOLO("bccd_yolov10_best.pt")
63
- return model
64
- except Exception as e:
65
- st.error(f"Error loading model: {str(e)}")
66
- return None
67
-
68
- def perform_inference(model, image):
69
- try:
70
- results = model.predict(image, conf=0.25)
71
- return results[0]
72
- except Exception as e:
73
- st.error(f"Error during inference: {str(e)}")
74
- return None
75
-
76
- def create_visualization(image, results):
77
- if not results.boxes:
78
- return None
79
- fig = go.Figure()
80
- fig.add_trace(go.Image(z=image))
81
- boxes = results.boxes.xyxy.cpu().numpy()
82
- classes = results.boxes.cls.cpu().numpy()
83
- confs = results.boxes.conf.cpu().numpy()
84
- class_names = ["RBC", "WBC", "Platelets"]
85
- colors = ["#FF5252", "#2196F3", "#4CAF50"]
86
- for box, cls, conf in zip(boxes, classes, confs):
87
- x0, y0, x1, y1 = box
88
- cls_name = class_names[int(cls)]
89
- color = colors[int(cls)]
90
- fig.add_shape(type="rect", x0=x0, y0=y0, x1=x1, y1=y1, line=dict(color=color, width=2))
91
- fig.add_annotation(x=x0, y=y0-5, text=f"{cls_name} ({conf:.2f})", showarrow=False,
92
- font=dict(color="white", size=10), bgcolor=color, bordercolor=color)
93
- fig.update_layout(width=700, height=500, margin=dict(l=0, r=0, b=0, t=0), showlegend=False)
94
- fig.update_xaxes(showticklabels=False, showgrid=False)
95
- fig.update_yaxes(showticklabels=False, showgrid=False)
96
- return fig
97
-
98
- def create_cell_counts_chart(results):
99
- if not results.boxes:
100
- return None
101
- classes = results.boxes.cls.cpu().numpy()
102
- class_names = ["RBC", "WBC", "Platelets"]
103
- counts = {name: sum(1 for cls in classes if class_names[int(cls)] == name) for name in class_names}
104
- df = pd.DataFrame({"Cell Type": list(counts.keys()), "Count": list(counts.values())})
105
- fig = px.bar(df, x="Cell Type", y="Count", color="Cell Type",
106
- color_discrete_sequence=["#FF5252", "#2196F3", "#4CAF50"],
107
- text=df["Count"], height=400)
108
- fig.update_layout(title="Cell Count Distribution", xaxis_title="", yaxis_title="Count")
109
- fig.update_traces(textposition="outside")
110
- return fig
111
-
112
- # Main Content
113
- st.markdown("<div class='card'>", unsafe_allow_html=True)
114
- model = load_model()
115
- if not model:
116
- st.stop()
117
-
118
- st.markdown("<h2 class='sub-header'>Upload Image</h2>", unsafe_allow_html=True)
119
- uploaded_file = st.file_uploader("Choose an image (JPG, JPEG, PNG)", type=["jpg", "jpeg", "png"])
120
- st.markdown("</div>", unsafe_allow_html=True)
121
-
122
- if uploaded_file:
123
- st.markdown("<div class='card'>", unsafe_allow_html=True)
124
- col1, col2 = st.columns(2)
125
- with col1:
126
- image = preprocess_image(uploaded_file)
127
- if image is None:
128
- st.stop()
129
- st.image(image, caption="Uploaded Image", use_container_width=True)
130
- with col2:
131
- if st.button("πŸ” Detect Blood Cells"):
132
- with st.spinner("Analyzing..."):
133
- time.sleep(1) # Simulate processing
134
- results = perform_inference(model, image)
135
- if results and results.boxes:
136
- vis_fig = create_visualization(image, results)
137
- st.plotly_chart(vis_fig, use_container_width=True)
138
-
139
- # Metrics
140
- classes = results.boxes.cls.cpu().numpy()
141
- class_names = ["RBC", "WBC", "Platelets"]
142
- counts = {name: sum(1 for cls in classes if class_names[int(cls)] == name) for name in class_names}
143
- cols = st.columns(4)
144
- cols[0].markdown(f"<div class='metric-card'><div class='metric-value'>{len(classes)}</div><div class='metric-label'>Total Cells</div></div>", unsafe_allow_html=True)
145
- cols[1].markdown(f"<div class='metric-card'><div class='metric-value' style='color:#FF5252'>{counts['RBC']}</div><div class='metric-label'>RBC</div></div>", unsafe_allow_html=True)
146
- cols[2].markdown(f"<div class='metric-card'><div class='metric-value' style='color:#2196F3'>{counts['WBC']}</div><div class='metric-label'>WBC</div></div>", unsafe_allow_html=True)
147
- cols[3].markdown(f"<div class='metric-card'><div class='metric-value' style='color:#4CAF50'>{counts['Platelets']}</div><div class='metric-label'>Platelets</div></div>", unsafe_allow_html=True)
148
-
149
-
150
- count_fig = create_cell_counts_chart(results)
151
- st.plotly_chart(count_fig, use_container_width=True)
152
-
153
-
154
- st.markdown("<h2 class='sub-header'>Detailed Results</h2>", unsafe_allow_html=True)
155
- data = [{"ID": i+1, "Cell Type": f"<span class='cell-badge {['rbc','wbc','plt'][int(cls)]}-badge'>{class_names[int(cls)]}</span>",
156
- "Confidence": f"{conf*100:.2f}%"}
157
- for i, (cls, conf) in enumerate(zip(classes, results.boxes.conf.cpu().numpy()))]
158
- st.write(pd.DataFrame(data).to_html(escape=False, index=False), unsafe_allow_html=True)
159
-
160
-
161
- st.download_button("πŸ“Š Export as CSV",
162
- pd.DataFrame({"Cell Type": [class_names[int(cls)] for cls in classes],
163
- "Confidence": [f"{conf*100:.2f}%" for conf in results.boxes.conf.cpu().numpy()]}).to_csv(index=False),
164
- "results.csv", "text/csv")
165
- else:
166
- st.warning("No cells detected or analysis failed.")
167
- st.markdown("</div>", unsafe_allow_html=True)
168
-
169
-
170
- with tab2:
171
- st.markdown("<div class='card'>", unsafe_allow_html=True)
172
- st.markdown("<h2 class='sub-header'>About</h2>", unsafe_allow_html=True)
173
- st.markdown("""
174
- This app uses YOLOv10 to detect Red Blood Cells (RBC), White Blood Cells (WBC), and Platelets in blood smear images.
175
- Upload an image in the Analysis tab to see counts, visualizations, and detailed results.
176
- """)
177
- st.markdown("</div>", unsafe_allow_html=True)
178
-
179
- with tab3:
180
- st.markdown("<div class='card'>", unsafe_allow_html=True)
181
- st.markdown("<h2 class='sub-header'>Help</h2>", unsafe_allow_html=True)
182
- st.markdown("""
183
- - **Upload**: Select a JPG, JPEG, or PNG image in the Analysis tab.
184
- - **Detect**: Click "Detect Blood Cells" to analyze.
185
- - **Results**: View counts and export data as CSV.
186
- - **Support**: Email [email protected] for issues.
187
- """)
188
- st.markdown("</div>", unsafe_allow_html=True)
 
 
1
+ !pip install -r requirements.txt
2
+ import streamlit as st
3
+ import cv2
4
+ import numpy as np
5
+ from PIL import Image
6
+ import pandas as pd
7
+ import plotly.express as px
8
+ import plotly.graph_objects as go
9
+ from ultralytics import YOLO
10
+ import time
11
+
12
+
13
+ st.set_page_config(
14
+ page_title="Blood Cell Detection App",
15
+ page_icon="πŸ”¬",
16
+ layout="wide",
17
+ initial_sidebar_state="expanded"
18
+ )
19
+
20
+ st.markdown("""
21
+ <style>
22
+ @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600&display=swap');
23
+ * { font-family: 'Poppins', sans-serif; }
24
+ .main-header { font-size: 2.5rem; font-weight: 600; color: #4B0082; text-align: center; margin-bottom: 1rem; }
25
+ .sub-header { font-size: 1.5rem; font-weight: 500; color: #6200EA; margin: 1rem 0; }
26
+ .card { background: white; border-radius: 0.8rem; padding: 1rem; margin-bottom: 1rem; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
27
+ .stButton>button { background: #6200EA; color: white; border: none; border-radius: 0.5rem; padding: 0.5rem 1rem; }
28
+ .metric-card { text-align: center; padding: 1rem; }
29
+ .metric-value { font-size: 2rem; font-weight: 600; color: #6200EA; }
30
+ .metric-label { font-size: 0.9rem; color: #555; }
31
+ .cell-badge { padding: 0.2rem 0.5rem; border-radius: 1rem; font-size: 0.8rem; }
32
+ .rbc-badge { background: rgba(255,82,82,0.2); color: #FF5252; border: 1px solid #FF5252; }
33
+ .wbc-badge { background: rgba(33,150,243,0.2); color: #2196F3; border: 1px solid #2196F3; }
34
+ .plt-badge { background: rgba(76,175,80,0.2); color: #4CAF50; border: 1px solid #4CAF50; }
35
+ .footer { text-align: center; padding: 1rem; color: #777; font-size: 0.8rem; border-top: 1px solid #eee; margin-top: 2rem; }
36
+ </style>
37
+ """, unsafe_allow_html=True)
38
+
39
+
40
+ st.markdown("<h1 class='main-header'>Blood Cell Detection System</h1>", unsafe_allow_html=True)
41
+
42
+
43
+ tab1, tab2, tab3 = st.tabs(["πŸ“Š Analysis", "ℹ️ About", "❓ Help"])
44
+
45
+
46
+ with tab1:
47
+
48
+ @st.cache_data
49
+ def preprocess_image(uploaded_file):
50
+ try:
51
+ bytes_data = uploaded_file.getvalue()
52
+ img = cv2.imdecode(np.frombuffer(bytes_data, np.uint8), cv2.IMREAD_COLOR)
53
+ if img is None:
54
+ raise ValueError("Invalid image file")
55
+ return cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
56
+ except Exception as e:
57
+ st.error(f"Error preprocessing image: {str(e)}")
58
+ return None
59
+
60
+ @st.cache_resource
61
+ def load_model():
62
+ try:
63
+ model = YOLO("bccd_yolov10_best.pt")
64
+ return model
65
+ except Exception as e:
66
+ st.error(f"Error loading model: {str(e)}")
67
+ return None
68
+
69
+ def perform_inference(model, image):
70
+ try:
71
+ results = model.predict(image, conf=0.25)
72
+ return results[0]
73
+ except Exception as e:
74
+ st.error(f"Error during inference: {str(e)}")
75
+ return None
76
+
77
+ def create_visualization(image, results):
78
+ if not results.boxes:
79
+ return None
80
+ fig = go.Figure()
81
+ fig.add_trace(go.Image(z=image))
82
+ boxes = results.boxes.xyxy.cpu().numpy()
83
+ classes = results.boxes.cls.cpu().numpy()
84
+ confs = results.boxes.conf.cpu().numpy()
85
+ class_names = ["RBC", "WBC", "Platelets"]
86
+ colors = ["#FF5252", "#2196F3", "#4CAF50"]
87
+ for box, cls, conf in zip(boxes, classes, confs):
88
+ x0, y0, x1, y1 = box
89
+ cls_name = class_names[int(cls)]
90
+ color = colors[int(cls)]
91
+ fig.add_shape(type="rect", x0=x0, y0=y0, x1=x1, y1=y1, line=dict(color=color, width=2))
92
+ fig.add_annotation(x=x0, y=y0-5, text=f"{cls_name} ({conf:.2f})", showarrow=False,
93
+ font=dict(color="white", size=10), bgcolor=color, bordercolor=color)
94
+ fig.update_layout(width=700, height=500, margin=dict(l=0, r=0, b=0, t=0), showlegend=False)
95
+ fig.update_xaxes(showticklabels=False, showgrid=False)
96
+ fig.update_yaxes(showticklabels=False, showgrid=False)
97
+ return fig
98
+
99
+ def create_cell_counts_chart(results):
100
+ if not results.boxes:
101
+ return None
102
+ classes = results.boxes.cls.cpu().numpy()
103
+ class_names = ["RBC", "WBC", "Platelets"]
104
+ counts = {name: sum(1 for cls in classes if class_names[int(cls)] == name) for name in class_names}
105
+ df = pd.DataFrame({"Cell Type": list(counts.keys()), "Count": list(counts.values())})
106
+ fig = px.bar(df, x="Cell Type", y="Count", color="Cell Type",
107
+ color_discrete_sequence=["#FF5252", "#2196F3", "#4CAF50"],
108
+ text=df["Count"], height=400)
109
+ fig.update_layout(title="Cell Count Distribution", xaxis_title="", yaxis_title="Count")
110
+ fig.update_traces(textposition="outside")
111
+ return fig
112
+
113
+ # Main Content
114
+ st.markdown("<div class='card'>", unsafe_allow_html=True)
115
+ model = load_model()
116
+ if not model:
117
+ st.stop()
118
+
119
+ st.markdown("<h2 class='sub-header'>Upload Image</h2>", unsafe_allow_html=True)
120
+ uploaded_file = st.file_uploader("Choose an image (JPG, JPEG, PNG)", type=["jpg", "jpeg", "png"])
121
+ st.markdown("</div>", unsafe_allow_html=True)
122
+
123
+ if uploaded_file:
124
+ st.markdown("<div class='card'>", unsafe_allow_html=True)
125
+ col1, col2 = st.columns(2)
126
+ with col1:
127
+ image = preprocess_image(uploaded_file)
128
+ if image is None:
129
+ st.stop()
130
+ st.image(image, caption="Uploaded Image", use_container_width=True)
131
+ with col2:
132
+ if st.button("πŸ” Detect Blood Cells"):
133
+ with st.spinner("Analyzing..."):
134
+ time.sleep(1) # Simulate processing
135
+ results = perform_inference(model, image)
136
+ if results and results.boxes:
137
+ vis_fig = create_visualization(image, results)
138
+ st.plotly_chart(vis_fig, use_container_width=True)
139
+
140
+ # Metrics
141
+ classes = results.boxes.cls.cpu().numpy()
142
+ class_names = ["RBC", "WBC", "Platelets"]
143
+ counts = {name: sum(1 for cls in classes if class_names[int(cls)] == name) for name in class_names}
144
+ cols = st.columns(4)
145
+ cols[0].markdown(f"<div class='metric-card'><div class='metric-value'>{len(classes)}</div><div class='metric-label'>Total Cells</div></div>", unsafe_allow_html=True)
146
+ cols[1].markdown(f"<div class='metric-card'><div class='metric-value' style='color:#FF5252'>{counts['RBC']}</div><div class='metric-label'>RBC</div></div>", unsafe_allow_html=True)
147
+ cols[2].markdown(f"<div class='metric-card'><div class='metric-value' style='color:#2196F3'>{counts['WBC']}</div><div class='metric-label'>WBC</div></div>", unsafe_allow_html=True)
148
+ cols[3].markdown(f"<div class='metric-card'><div class='metric-value' style='color:#4CAF50'>{counts['Platelets']}</div><div class='metric-label'>Platelets</div></div>", unsafe_allow_html=True)
149
+
150
+
151
+ count_fig = create_cell_counts_chart(results)
152
+ st.plotly_chart(count_fig, use_container_width=True)
153
+
154
+
155
+ st.markdown("<h2 class='sub-header'>Detailed Results</h2>", unsafe_allow_html=True)
156
+ data = [{"ID": i+1, "Cell Type": f"<span class='cell-badge {['rbc','wbc','plt'][int(cls)]}-badge'>{class_names[int(cls)]}</span>",
157
+ "Confidence": f"{conf*100:.2f}%"}
158
+ for i, (cls, conf) in enumerate(zip(classes, results.boxes.conf.cpu().numpy()))]
159
+ st.write(pd.DataFrame(data).to_html(escape=False, index=False), unsafe_allow_html=True)
160
+
161
+
162
+ st.download_button("πŸ“Š Export as CSV",
163
+ pd.DataFrame({"Cell Type": [class_names[int(cls)] for cls in classes],
164
+ "Confidence": [f"{conf*100:.2f}%" for conf in results.boxes.conf.cpu().numpy()]}).to_csv(index=False),
165
+ "results.csv", "text/csv")
166
+ else:
167
+ st.warning("No cells detected or analysis failed.")
168
+ st.markdown("</div>", unsafe_allow_html=True)
169
+
170
+
171
+ with tab2:
172
+ st.markdown("<div class='card'>", unsafe_allow_html=True)
173
+ st.markdown("<h2 class='sub-header'>About</h2>", unsafe_allow_html=True)
174
+ st.markdown("""
175
+ This app uses YOLOv10 to detect Red Blood Cells (RBC), White Blood Cells (WBC), and Platelets in blood smear images.
176
+ Upload an image in the Analysis tab to see counts, visualizations, and detailed results.
177
+ """)
178
+ st.markdown("</div>", unsafe_allow_html=True)
179
+
180
+ with tab3:
181
+ st.markdown("<div class='card'>", unsafe_allow_html=True)
182
+ st.markdown("<h2 class='sub-header'>Help</h2>", unsafe_allow_html=True)
183
+ st.markdown("""
184
+ - **Upload**: Select a JPG, JPEG, or PNG image in the Analysis tab.
185
+ - **Detect**: Click "Detect Blood Cells" to analyze.
186
+ - **Results**: View counts and export data as CSV.
187
+ - **Support**: Email [email protected] for issues.
188
+ """)
189
+ st.markdown("</div>", unsafe_allow_html=True)