Yourgotoguy commited on
Commit
e35098c
·
verified ·
1 Parent(s): 4e81c52

updated the background

Browse files
Files changed (1) hide show
  1. streamlit_app.py +222 -222
streamlit_app.py CHANGED
@@ -1,223 +1,223 @@
1
- import streamlit as st
2
- from PIL import Image
3
- import numpy as np
4
- import cv2
5
- import tempfile
6
- from ultralytics import YOLO
7
- from collections import Counter
8
- from segment_anything import sam_model_registry, SamPredictor
9
- from sklearn.cluster import KMeans
10
- import torch
11
- import base64
12
- import os
13
- import gdown # Keep if needed for other models
14
- from huggingface_hub import hf_hub_download # NEW IMPORT for Hugging Face
15
-
16
- # --- Define File Paths ---
17
- BACKGROUND_IMAGE_PATH = "photo-1507525428034-b723cf961d3e.jpeg"
18
- GARBAGE_YOLO_MODEL_PATH = "garbage_detection.pt"
19
- WATER_YOLO_MODEL_PATH = "water_detection.pt"
20
-
21
- # --- SAM Model Download Configuration ---
22
- # IMPORTANT: Replace with YOUR Hugging Face repo_id and filename
23
- SAM_HF_REPO_ID = "Yourgotoguy/SAM_for_garbage" # e.g., "Yourgotoguy/LitterLens-SAM-Model"
24
- SAM_HF_FILENAME = "sam_vit_b_01ec64.pth"
25
- # The downloaded file will be cached by huggingface_hub in a local directory (e.g., ~/.cache/huggingface/hub)
26
- # We need to get the actual path where it's downloaded to pass to sam_model_registry
27
- SAM_CHECKPOINT_PATH_LOCAL = None # This will be set by hf_hub_download
28
-
29
-
30
- def set_background(image_path):
31
- if not os.path.exists(image_path):
32
- st.error(f"Background image not found at: {image_path}. Please ensure it's in the same directory as streamlit_app.py.")
33
- st.stop()
34
- with open(image_path, "rb") as img_file:
35
- encoded = base64.b64encode(img_file.read()).decode()
36
-
37
- css = f"""
38
- <style>
39
- .stApp {{
40
- background-image: url("data:image/jpeg;base64,{encoded}");
41
- background-size: cover;
42
- background-position: center;
43
- background-repeat: no-repeat;
44
- }}
45
- </style>
46
- """
47
- st.markdown(css, unsafe_allow_html=True)
48
-
49
-
50
- # --- Load Models ---
51
- @st.cache_resource
52
- def load_yolo_garbage_model():
53
- if not os.path.exists(GARBAGE_YOLO_MODEL_PATH):
54
- st.error(f"YOLO Garbage Detection Model not found at: {GARBAGE_YOLO_MODEL_PATH}.")
55
- st.stop()
56
- return YOLO(GARBAGE_YOLO_MODEL_PATH)
57
-
58
- @st.cache_resource
59
- def load_yolo_water_model():
60
- if not os.path.exists(WATER_YOLO_MODEL_PATH):
61
- st.error(f"YOLO Water Detection Model not found at: {WATER_YOLO_MODEL_PATH}.")
62
- st.stop()
63
- return YOLO(WATER_YOLO_MODEL_PATH)
64
-
65
- @st.cache_resource
66
- def load_sam_model():
67
- global SAM_CHECKPOINT_PATH_LOCAL # Declare global to set the path after download
68
-
69
- # Download SAM model from Hugging Face Hub
70
- st.info(f"Checking for SAM model '{SAM_HF_FILENAME}' from Hugging Face Hub '{SAM_HF_REPO_ID}'...")
71
- try:
72
- SAM_CHECKPOINT_PATH_LOCAL = hf_hub_download(
73
- repo_id=SAM_HF_REPO_ID,
74
- filename=SAM_HF_FILENAME,
75
- # local_dir=".", # Optional: specify local directory, default cache is fine
76
- # local_dir_use_symlinks=False, # Important if you specify local_dir
77
- # etag_timeout=10, # Add a timeout if downloads get stuck
78
- )
79
- st.success(f"SAM model ready at: {SAM_CHECKPOINT_PATH_LOCAL}")
80
- except Exception as e:
81
- st.error(f"Failed to download SAM model from Hugging Face Hub: {e}")
82
- st.error("Please ensure the Hugging Face repo_id and filename are correct and the model is public.")
83
- st.stop()
84
-
85
- # Verify that the file exists locally and is not a tiny LFS pointer (unlikely with hf_hub_download)
86
- if not os.path.exists(SAM_CHECKPOINT_PATH_LOCAL):
87
- st.error(f"SAM Checkpoint not found at: {SAM_CHECKPOINT_PATH_LOCAL} after attempted download.")
88
- st.stop()
89
- # Optional: Debugging - check actual size if you suspect a partial download
90
- # st.info(f"SAM model local file size: {os.path.getsize(SAM_CHECKPOINT_PATH_LOCAL)} bytes")
91
-
92
-
93
- # Load the model
94
- try:
95
- sam = sam_model_registry["vit_b"](checkpoint=SAM_CHECKPOINT_PATH_LOCAL)
96
- sam.to("cuda" if torch.cuda.is_available() else "cpu")
97
- return SamPredictor(sam)
98
- except Exception as e:
99
- st.error(f"Error loading SAM model from checkpoint: {e}")
100
- st.warning("This might indicate a corrupted download, an incorrect model file, or insufficient memory during loading.")
101
- st.stop()
102
-
103
-
104
- # --- Rest of your app code remains the same ---
105
- set_background(BACKGROUND_IMAGE_PATH)
106
-
107
- def classify_color(rgb):
108
- import colorsys
109
- r, g, b = [x / 255.0 for x in rgb]
110
- h, s, v = colorsys.rgb_to_hsv(r, g, b)
111
- h *= 360
112
- if 20 <= h <= 60 and v < 0.5:
113
- return "muddy brown"
114
- if h < 30 or h > 330:
115
- return "red"
116
- elif 30 <= h <= 65:
117
- return "yellow"
118
- elif 65 < h <= 170:
119
- return "green"
120
- elif s < 0.2 and v < 0.5:
121
- return "grayish / unclear"
122
- else:
123
- return "unknown"
124
-
125
- def show_color_advisory(rgb_color):
126
- color_category = classify_color(rgb_color)
127
- st.markdown(f"### 💧 Detected Water Color Category: **`{color_category.title()}`**")
128
- color_advisories = {
129
- "red": "🚨 **Unusual red color detected.** Could be from natural or industrial sources. **Extreme caution** is advised while handling this water.",
130
- "yellow": "⚠️ **Unusual yellow color detected.** Possible industrial or organic matter contamination. Handle with care.",
131
- "muddy brown": "💧 **High turbidity and suspended solids detected.** May indicate **microbial contamination** or runoff pollution.",
132
- "green": "🟢 **Green color detected.** Possible **eutrophication** due to high nitrogen or phosphorus levels.",
133
- }
134
- if color_category in color_advisories:
135
- st.warning(color_advisories[color_category])
136
- else:
137
- st.info("ℹ️ No specific advisory for this color.")
138
-
139
- st.set_page_config(page_title="🌿 Environmental Analyzer", layout="wide")
140
- st.markdown("<h1 style='text-align: center; color: teal;'> Environmental Analyzer</h1>", unsafe_allow_html=True)
141
- st.markdown("<h4 style='text-align: center; color: gray;'>Detect Garbage or Analyze Water Color with AI</h4>", unsafe_allow_html=True)
142
- mode = st.radio("Choose Task", ["Garbage Detection", "Water Color Detection"], horizontal=True)
143
- uploaded_file = st.file_uploader("Upload an image", type=["jpg", "jpeg", "png"])
144
- st.markdown("""
145
- <style>
146
- div[data-baseweb="slider"] > div {
147
- background: linear-gradient(to left, #79adb3 0%, #e2c3a8 100%) !important;
148
- }
149
- </style>
150
- """, unsafe_allow_html=True)
151
-
152
- if mode == "Garbage Detection":
153
- conf_threshold = st.slider("🎯 Confidence Threshold", min_value=0.1, max_value=0.9, value=0.3, step=0.05,)
154
- if uploaded_file:
155
- st.image(uploaded_file, caption="Uploaded Image", width=400)
156
- if st.button("🚀 Detect Garbage"):
157
- yolo_model = load_yolo_garbage_model()
158
- image = Image.open(uploaded_file).convert("RGB")
159
- with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as tmp:
160
- image.save(tmp.name)
161
- results = yolo_model(tmp.name, conf=conf_threshold)[0]
162
- img = np.array(image).copy()
163
- detected_classes = []
164
- for box in results.boxes:
165
- x1, y1, x2, y2 = map(int, box.xyxy[0])
166
- cls = int(box.cls[0])
167
- conf = float(box.conf[0])
168
- label = f"{yolo_model.names[cls]} {conf:.2f}"
169
- detected_classes.append(yolo_model.names[cls])
170
- cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
171
- cv2.putText(img, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 0), 2)
172
- st.image(img, caption="🧾 Detection Result", use_container_width=True)
173
- if detected_classes:
174
- st.markdown("### ♻️ Detected Garbage Types")
175
- count = Counter(detected_classes)
176
- for garbage_type, qty in count.items():
177
- st.write(f"• **{garbage_type.capitalize()}**: {qty}")
178
- else:
179
- st.info("No garbage types detected.")
180
- else: # Water Color Detection
181
- if uploaded_file:
182
- st.image(uploaded_file, caption="Uploaded Image", width=400)
183
- if st.button("Detect Water Color"):
184
- yolo_model = load_yolo_water_model()
185
- predictor = load_sam_model() # This is where SAM is loaded/downloaded
186
- image = Image.open(uploaded_file).convert("RGB")
187
- image_np = np.array(image)
188
- image_bgr = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)
189
- with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as tmp:
190
- image.save(tmp.name)
191
- results = yolo_model(tmp.name)[0]
192
- predictor.set_image(image_np)
193
- found = False
194
- for box in results.boxes.xyxy:
195
- x1, y1, x2, y2 = map(int, box)
196
- input_box = np.array([x1, y1, x2, y2])
197
- masks, scores, _ = predictor.predict(box=input_box[None, :], multimask_output=False)
198
- mask = masks[0]
199
- segmented_pixels = image_bgr[mask]
200
- if segmented_pixels.size == 0:
201
- continue
202
- k = 3
203
- pixels = segmented_pixels.astype(np.float32)
204
- brightness = np.mean(pixels, axis=1)
205
- filtered_pixels = pixels[brightness < 80]
206
- if len(filtered_pixels) < k:
207
- continue
208
- kmeans = KMeans(n_clusters=k, random_state=42, n_init='auto')
209
- kmeans.fit(filtered_pixels)
210
- cluster_centers = kmeans.cluster_centers_
211
- labels, counts = np.unique(kmeans.labels_, return_counts=True)
212
- dominant_color_bgr = cluster_centers[labels[np.argmax(counts)]].astype(int)
213
- dominant_color_rgb = tuple(int(c) for c in dominant_color_bgr[::-1])
214
- found = True
215
- st.markdown(f"### 🌊 Dominant Water Color (RGB): `{dominant_color_rgb}`")
216
- overlay = image_bgr.copy()
217
- overlay[mask] = dominant_color_bgr
218
- cv2.rectangle(overlay, (x1, y1), (x2, y2), (0, 255, 0), 2)
219
- st.image(cv2.cvtColor(overlay, cv2.COLOR_BGR2RGB), caption="Water Region with Dominant Color", use_container_width=True)
220
- show_color_advisory(dominant_color_rgb)
221
- break
222
- if not found:
223
  st.warning("No water region detected or not enough dark pixels.")
 
1
+ import streamlit as st
2
+ from PIL import Image
3
+ import numpy as np
4
+ import cv2
5
+ import tempfile
6
+ from ultralytics import YOLO
7
+ from collections import Counter
8
+ from segment_anything import sam_model_registry, SamPredictor
9
+ from sklearn.cluster import KMeans
10
+ import torch
11
+ import base64
12
+ import os
13
+ import gdown # Keep if needed for other models
14
+ from huggingface_hub import hf_hub_download # NEW IMPORT for Hugging Face
15
+
16
+ # --- Define File Paths ---
17
+ BACKGROUND_IMAGE_PATH = "new_background.png"
18
+ GARBAGE_YOLO_MODEL_PATH = "garbage_detection.pt"
19
+ WATER_YOLO_MODEL_PATH = "water_detection.pt"
20
+
21
+ # --- SAM Model Download Configuration ---
22
+ # IMPORTANT: Replace with YOUR Hugging Face repo_id and filename
23
+ SAM_HF_REPO_ID = "Yourgotoguy/SAM_for_garbage" # e.g., "Yourgotoguy/LitterLens-SAM-Model"
24
+ SAM_HF_FILENAME = "sam_vit_b_01ec64.pth"
25
+ # The downloaded file will be cached by huggingface_hub in a local directory (e.g., ~/.cache/huggingface/hub)
26
+ # We need to get the actual path where it's downloaded to pass to sam_model_registry
27
+ SAM_CHECKPOINT_PATH_LOCAL = None # This will be set by hf_hub_download
28
+
29
+
30
+ def set_background(image_path):
31
+ if not os.path.exists(image_path):
32
+ st.error(f"Background image not found at: {image_path}. Please ensure it's in the same directory as streamlit_app.py.")
33
+ st.stop()
34
+ with open(image_path, "rb") as img_file:
35
+ encoded = base64.b64encode(img_file.read()).decode()
36
+
37
+ css = f"""
38
+ <style>
39
+ .stApp {{
40
+ background-image: url("data:image/jpeg;base64,{encoded}");
41
+ background-size: cover;
42
+ background-position: center;
43
+ background-repeat: no-repeat;
44
+ }}
45
+ </style>
46
+ """
47
+ st.markdown(css, unsafe_allow_html=True)
48
+
49
+
50
+ # --- Load Models ---
51
+ @st.cache_resource
52
+ def load_yolo_garbage_model():
53
+ if not os.path.exists(GARBAGE_YOLO_MODEL_PATH):
54
+ st.error(f"YOLO Garbage Detection Model not found at: {GARBAGE_YOLO_MODEL_PATH}.")
55
+ st.stop()
56
+ return YOLO(GARBAGE_YOLO_MODEL_PATH)
57
+
58
+ @st.cache_resource
59
+ def load_yolo_water_model():
60
+ if not os.path.exists(WATER_YOLO_MODEL_PATH):
61
+ st.error(f"YOLO Water Detection Model not found at: {WATER_YOLO_MODEL_PATH}.")
62
+ st.stop()
63
+ return YOLO(WATER_YOLO_MODEL_PATH)
64
+
65
+ @st.cache_resource
66
+ def load_sam_model():
67
+ global SAM_CHECKPOINT_PATH_LOCAL # Declare global to set the path after download
68
+
69
+ # Download SAM model from Hugging Face Hub
70
+ st.info(f"Checking for SAM model '{SAM_HF_FILENAME}' from Hugging Face Hub '{SAM_HF_REPO_ID}'...")
71
+ try:
72
+ SAM_CHECKPOINT_PATH_LOCAL = hf_hub_download(
73
+ repo_id=SAM_HF_REPO_ID,
74
+ filename=SAM_HF_FILENAME,
75
+ # local_dir=".", # Optional: specify local directory, default cache is fine
76
+ # local_dir_use_symlinks=False, # Important if you specify local_dir
77
+ # etag_timeout=10, # Add a timeout if downloads get stuck
78
+ )
79
+ st.success(f"SAM model ready at: {SAM_CHECKPOINT_PATH_LOCAL}")
80
+ except Exception as e:
81
+ st.error(f"Failed to download SAM model from Hugging Face Hub: {e}")
82
+ st.error("Please ensure the Hugging Face repo_id and filename are correct and the model is public.")
83
+ st.stop()
84
+
85
+ # Verify that the file exists locally and is not a tiny LFS pointer (unlikely with hf_hub_download)
86
+ if not os.path.exists(SAM_CHECKPOINT_PATH_LOCAL):
87
+ st.error(f"SAM Checkpoint not found at: {SAM_CHECKPOINT_PATH_LOCAL} after attempted download.")
88
+ st.stop()
89
+ # Optional: Debugging - check actual size if you suspect a partial download
90
+ # st.info(f"SAM model local file size: {os.path.getsize(SAM_CHECKPOINT_PATH_LOCAL)} bytes")
91
+
92
+
93
+ # Load the model
94
+ try:
95
+ sam = sam_model_registry["vit_b"](checkpoint=SAM_CHECKPOINT_PATH_LOCAL)
96
+ sam.to("cuda" if torch.cuda.is_available() else "cpu")
97
+ return SamPredictor(sam)
98
+ except Exception as e:
99
+ st.error(f"Error loading SAM model from checkpoint: {e}")
100
+ st.warning("This might indicate a corrupted download, an incorrect model file, or insufficient memory during loading.")
101
+ st.stop()
102
+
103
+
104
+ # --- Rest of your app code remains the same ---
105
+ set_background(BACKGROUND_IMAGE_PATH)
106
+
107
+ def classify_color(rgb):
108
+ import colorsys
109
+ r, g, b = [x / 255.0 for x in rgb]
110
+ h, s, v = colorsys.rgb_to_hsv(r, g, b)
111
+ h *= 360
112
+ if 20 <= h <= 60 and v < 0.5:
113
+ return "muddy brown"
114
+ if h < 30 or h > 330:
115
+ return "red"
116
+ elif 30 <= h <= 65:
117
+ return "yellow"
118
+ elif 65 < h <= 170:
119
+ return "green"
120
+ elif s < 0.2 and v < 0.5:
121
+ return "grayish / unclear"
122
+ else:
123
+ return "unknown"
124
+
125
+ def show_color_advisory(rgb_color):
126
+ color_category = classify_color(rgb_color)
127
+ st.markdown(f"### 💧 Detected Water Color Category: **`{color_category.title()}`**")
128
+ color_advisories = {
129
+ "red": "🚨 **Unusual red color detected.** Could be from natural or industrial sources. **Extreme caution** is advised while handling this water.",
130
+ "yellow": "⚠️ **Unusual yellow color detected.** Possible industrial or organic matter contamination. Handle with care.",
131
+ "muddy brown": "💧 **High turbidity and suspended solids detected.** May indicate **microbial contamination** or runoff pollution.",
132
+ "green": "🟢 **Green color detected.** Possible **eutrophication** due to high nitrogen or phosphorus levels.",
133
+ }
134
+ if color_category in color_advisories:
135
+ st.warning(color_advisories[color_category])
136
+ else:
137
+ st.info("ℹ️ No specific advisory for this color.")
138
+
139
+ st.set_page_config(page_title="🌿 Environmental Analyzer", layout="wide")
140
+ st.markdown("<h1 style='text-align: center; color: teal;'> Environmental Analyzer</h1>", unsafe_allow_html=True)
141
+ st.markdown("<h4 style='text-align: center; color: gray;'>Detect Garbage or Analyze Water Color with AI</h4>", unsafe_allow_html=True)
142
+ mode = st.radio("Choose Task", ["Garbage Detection", "Water Color Detection"], horizontal=True)
143
+ uploaded_file = st.file_uploader("Upload an image", type=["jpg", "jpeg", "png"])
144
+ st.markdown("""
145
+ <style>
146
+ div[data-baseweb="slider"] > div {
147
+ background: linear-gradient(to left, #79adb3 0%, #e2c3a8 100%) !important;
148
+ }
149
+ </style>
150
+ """, unsafe_allow_html=True)
151
+
152
+ if mode == "Garbage Detection":
153
+ conf_threshold = st.slider("🎯 Confidence Threshold", min_value=0.1, max_value=0.9, value=0.3, step=0.05,)
154
+ if uploaded_file:
155
+ st.image(uploaded_file, caption="Uploaded Image", width=400)
156
+ if st.button("🚀 Detect Garbage"):
157
+ yolo_model = load_yolo_garbage_model()
158
+ image = Image.open(uploaded_file).convert("RGB")
159
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as tmp:
160
+ image.save(tmp.name)
161
+ results = yolo_model(tmp.name, conf=conf_threshold)[0]
162
+ img = np.array(image).copy()
163
+ detected_classes = []
164
+ for box in results.boxes:
165
+ x1, y1, x2, y2 = map(int, box.xyxy[0])
166
+ cls = int(box.cls[0])
167
+ conf = float(box.conf[0])
168
+ label = f"{yolo_model.names[cls]} {conf:.2f}"
169
+ detected_classes.append(yolo_model.names[cls])
170
+ cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
171
+ cv2.putText(img, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 0), 2)
172
+ st.image(img, caption="🧾 Detection Result", use_container_width=True)
173
+ if detected_classes:
174
+ st.markdown("### ♻️ Detected Garbage Types")
175
+ count = Counter(detected_classes)
176
+ for garbage_type, qty in count.items():
177
+ st.write(f"• **{garbage_type.capitalize()}**: {qty}")
178
+ else:
179
+ st.info("No garbage types detected.")
180
+ else: # Water Color Detection
181
+ if uploaded_file:
182
+ st.image(uploaded_file, caption="Uploaded Image", width=400)
183
+ if st.button("Detect Water Color"):
184
+ yolo_model = load_yolo_water_model()
185
+ predictor = load_sam_model() # This is where SAM is loaded/downloaded
186
+ image = Image.open(uploaded_file).convert("RGB")
187
+ image_np = np.array(image)
188
+ image_bgr = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)
189
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as tmp:
190
+ image.save(tmp.name)
191
+ results = yolo_model(tmp.name)[0]
192
+ predictor.set_image(image_np)
193
+ found = False
194
+ for box in results.boxes.xyxy:
195
+ x1, y1, x2, y2 = map(int, box)
196
+ input_box = np.array([x1, y1, x2, y2])
197
+ masks, scores, _ = predictor.predict(box=input_box[None, :], multimask_output=False)
198
+ mask = masks[0]
199
+ segmented_pixels = image_bgr[mask]
200
+ if segmented_pixels.size == 0:
201
+ continue
202
+ k = 3
203
+ pixels = segmented_pixels.astype(np.float32)
204
+ brightness = np.mean(pixels, axis=1)
205
+ filtered_pixels = pixels[brightness < 80]
206
+ if len(filtered_pixels) < k:
207
+ continue
208
+ kmeans = KMeans(n_clusters=k, random_state=42, n_init='auto')
209
+ kmeans.fit(filtered_pixels)
210
+ cluster_centers = kmeans.cluster_centers_
211
+ labels, counts = np.unique(kmeans.labels_, return_counts=True)
212
+ dominant_color_bgr = cluster_centers[labels[np.argmax(counts)]].astype(int)
213
+ dominant_color_rgb = tuple(int(c) for c in dominant_color_bgr[::-1])
214
+ found = True
215
+ st.markdown(f"### 🌊 Dominant Water Color (RGB): `{dominant_color_rgb}`")
216
+ overlay = image_bgr.copy()
217
+ overlay[mask] = dominant_color_bgr
218
+ cv2.rectangle(overlay, (x1, y1), (x2, y2), (0, 255, 0), 2)
219
+ st.image(cv2.cvtColor(overlay, cv2.COLOR_BGR2RGB), caption="Water Region with Dominant Color", use_container_width=True)
220
+ show_color_advisory(dominant_color_rgb)
221
+ break
222
+ if not found:
223
  st.warning("No water region detected or not enough dark pixels.")