import os import cv2 import numpy as np import requests from flask import Flask, render_template, request, jsonify from ultralytics import YOLO from datetime import datetime import threading app = Flask(__name__) # --- CONFIGURATION --- MICROMIND_API_URL = "https://training.aimicromind.com/api/v1/prediction/606f1092-e94c-42f8-ba6f-09671904a15e" # GLOBAL SETTINGS current_settings = { "target_class_id": 0, "target_label": "person", "confidence": 0.5, "status": "ARMED" } # Load AI Model print("--- Loading AI Model... ---") try: model = YOLO('yolov8n.pt') print("✅ Model Loaded.") except Exception as e: print(f"⚠️ Model download/load warning: {e}") # Alert sender function def send_alert(alert_msg): """Sends alert in background - fully non-blocking.""" try: requests.post(MICROMIND_API_URL, json={"question": alert_msg}, timeout=5) print(f"✅ Alert sent to MicroMind") except Exception as e: print(f"⚠️ Alert sending failed: {e}") @app.route('/') def index(): """Serves the webpage to the user.""" return render_template('index.html') @app.route('/process_frame', methods=['POST']) def process_frame(): """Receives an image frame from the browser, runs AI, and returns results.""" if current_settings['status'] == 'DISARMED': return jsonify({"status": "DISARMED", "detections": []}) try: # 1. Get Image from Request file = request.files['image'].read() npimg = np.frombuffer(file, np.uint8) img = cv2.imdecode(npimg, cv2.IMREAD_COLOR) # 2. Run YOLO AI with optimized settings results = model(img, verbose=False, conf=current_settings['confidence']) detected = False detections_list = [] # 3. Analyze Results for result in results: for box in result.boxes: cls_id = int(box.cls[0]) conf = float(box.conf[0]) # Check against current settings if cls_id == current_settings['target_class_id']: detected = True detections_list.append({ "label": current_settings['target_label'], "confidence": round(conf, 2), "bbox": box.xyxy[0].tolist() }) # 4. Alert MicroMind (Fully Non-blocking) if detected: print(f"🚨 THREAT: {current_settings['target_label']} detected!") alert_msg = (f"ALERT: {current_settings['target_label']} detected.\n" f"Source: Cloud Web Cam\n" f"Confidence: {detections_list[0]['confidence']}") # Send alert in separate thread - fully fire-and-forget threading.Thread( target=lambda: send_alert(alert_msg), daemon=True ).start() return jsonify({ "status": "ARMED", "target": current_settings['target_label'], "detections": detections_list }) except Exception as e: print(f"Error: {e}") return jsonify({"error": str(e)}), 500 @app.route('/update_settings', methods=['POST']) def update_settings(): """Endpoint for MicroMind Agent to change settings.""" data = request.json # Simple mapping for demo label_map = { 'person': 0, 'bicycle': 1, 'car': 2, 'motorcycle': 3, 'airplane': 4, 'bus': 5, 'train': 6, 'truck': 7, 'boat': 8, 'bird': 14, 'cat': 15, 'dog': 16, 'backpack': 24, 'umbrella': 25, 'handbag': 26, 'tie': 27, 'suitcase': 28, 'bottle': 39, 'cup': 41, 'fork': 42, 'knife': 43, 'spoon': 44, 'bowl': 45, 'banana': 46, 'apple': 47, 'sandwich': 48, 'chair': 56, 'couch': 57, 'bed': 59, 'dining table': 60, 'laptop': 63, 'mouse': 64, 'remote': 65, 'keyboard': 66, 'cell phone': 67, 'microwave': 68, 'oven': 69, 'toaster': 70, 'sink': 71, 'refrigerator': 72, 'book': 73, 'clock': 74, 'vase': 75, 'scissors': 76, 'teddy bear': 77, 'toothbrush': 79 } if 'label' in data: new_label = data['label'].lower() if new_label in label_map: current_settings['target_label'] = new_label current_settings['target_class_id'] = label_map[new_label] if 'confidence' in data: current_settings['confidence'] = float(data['confidence']) if 'status' in data: current_settings['status'] = data['status'].upper() return jsonify({"status": "success", "current_state": current_settings}) if __name__ == '__main__': port = int(os.environ.get("PORT", 7860)) app.run(host='0.0.0.0', port=port)