ecoverify-ai / image_module.py
lmcuong199's picture
Update image_module.py
ea71843 verified
from ultralytics import YOLO
from huggingface_hub import hf_hub_download
from PIL import Image
import numpy as np
_model_general = None
_model_litter = None
WASTE_KEYWORDS = [
"bottle", "cup", "bag", "wrapper", "can", "trash", "bin",
"cardboard", "paper", "plastic", "litter", "garbage", "waste",
"box", "container", "food", "fruit", "banana", "orange",
"fork", "knife", "spoon", "bowl", "sandwich", "hotdog",
"pizza", "donut", "cake", "suitcase", "backpack", "handbag"
]
def get_general_model():
global _model_general
if _model_general is None:
_model_general = YOLO("yolov8n.pt")
return _model_general
def get_litter_model():
global _model_litter
if _model_litter is None:
try:
path = hf_hub_download(
repo_id="BowerApp/bowie-yolov8-multihead-trash-detection",
filename="best.pt"
)
_model_litter = YOLO(path)
except Exception:
_model_litter = None
return _model_litter
def analyze_image(image) -> tuple[str, float]:
if image is None:
return "Please upload an image.", 0.5
detected_all = []
methods_used = []
# ── Model 1: YOLOv8n COCO ─────────────────────────────────────────
try:
model_g = get_general_model()
results = model_g.predict(image, conf=0.05, verbose=False)
for box in results[0].boxes:
cls_name = model_g.names[int(box.cls[0])]
conf = float(box.conf[0])
detected_all.append({
"object": cls_name,
"confidence": f"{conf:.1%}",
"source": "YOLOv8-COCO"
})
methods_used.append("YOLOv8n-COCO")
except Exception as e:
methods_used.append(f"YOLOv8n failed: {e}")
# ── Model 2: Litter-specific ──────────────────────────────────────
try:
model_l = get_litter_model()
if model_l:
results2 = model_l.predict(image, conf=0.05, verbose=False)
for box in results2[0].boxes:
cls_name = model_l.names[int(box.cls[0])]
conf = float(box.conf[0])
detected_all.append({
"object": cls_name,
"confidence": f"{conf:.1%}",
"source": "Litter-Model"
})
methods_used.append("Litter-Detection")
except Exception as e:
methods_used.append(f"Litter model failed: {e}")
# ── Pixel heuristic ───────────────────────────────────────────────
try:
arr = np.array(Image.fromarray(np.array(image)).convert("RGB"))
r, g, b = arr[:,:,0], arr[:,:,1], arr[:,:,2]
dirty_brown = float(np.mean((r>120)&(g>80)&(g<140)&(b<80)))
dirty_grey = float(np.mean((r>100)&(g>100)&(b>100)&
(np.abs(r.astype(int)-g.astype(int))<20)))
pixel_risk = round(min((dirty_brown*0.6 + dirty_grey*0.4)*4, 1.0), 3)
except Exception:
pixel_risk = 0.0
# ── TΓ­nh risk ─────────────────────────────────────────────────────
waste_items = [
d for d in detected_all
if any(kw in d["object"].lower() for kw in WASTE_KEYWORDS)
]
seen = set()
unique_waste = []
for item in waste_items:
if item["object"] not in seen:
seen.add(item["object"])
unique_waste.append(item)
waste_count = len(unique_waste)
yolo_risk = round(min(waste_count / 5, 1.0), 3)
img_risk = round(min(yolo_risk * 0.7 + pixel_risk * 0.3, 1.0), 3)
# ── Verdict ───────────────────────────────────────────────────────
if img_risk > 0.5:
verdict = "🚨 Visible waste detected"
elif img_risk > 0.2:
verdict = "⚠️ Some waste indicators found"
else:
verdict = "βœ… Image appears clean"
output = f"""## {verdict}
| Metric | Value |
|--------|-------|
| Models used | {', '.join(methods_used)} |
| Waste objects found | {waste_count} |
| **Image Risk Score** | **{img_risk:.3f} / 1.0** |
"""
return output, img_risk