update webcam output
This commit is contained in:
		
							parent
							
								
									7911245ff9
								
							
						
					
					
						commit
						192b96d658
					
				
					 3 changed files with 115 additions and 30 deletions
				
			
		
							
								
								
									
										2
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -5,3 +5,5 @@ app.log
 | 
			
		|||
# All pycache directories
 | 
			
		||||
__pycache__/
 | 
			
		||||
.mptacache
 | 
			
		||||
 | 
			
		||||
mptas
 | 
			
		||||
| 
						 | 
				
			
			@ -5,10 +5,17 @@ import time
 | 
			
		|||
import logging
 | 
			
		||||
import shutil
 | 
			
		||||
import threading  # added threading
 | 
			
		||||
import yaml  # for silencing YOLO
 | 
			
		||||
 | 
			
		||||
from siwatsystem.pympta import load_pipeline_from_zip, run_pipeline
 | 
			
		||||
 | 
			
		||||
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s [%(levelname)s] %(message)s")
 | 
			
		||||
# Configure logging
 | 
			
		||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
 | 
			
		||||
 | 
			
		||||
# Silence YOLO logging
 | 
			
		||||
os.environ["YOLO_VERBOSE"] = "False"
 | 
			
		||||
for logger_name in ["ultralytics", "ultralytics.hub", "ultralytics.yolo.utils"]:
 | 
			
		||||
    logging.getLogger(logger_name).setLevel(logging.WARNING)
 | 
			
		||||
 | 
			
		||||
# Global variables for frame sharing
 | 
			
		||||
global_frame = None
 | 
			
		||||
| 
						 | 
				
			
			@ -25,6 +32,51 @@ def clear_cache(cache_dir: str):
 | 
			
		|||
    if os.path.exists(cache_dir):
 | 
			
		||||
        shutil.rmtree(cache_dir)
 | 
			
		||||
 | 
			
		||||
def log_pipeline_flow(frame, model_tree, level=0):
 | 
			
		||||
    """
 | 
			
		||||
    Wrapper around run_pipeline that logs the model flow and detection results.
 | 
			
		||||
    Returns the same output as the original run_pipeline function.
 | 
			
		||||
    """
 | 
			
		||||
    indent = "  " * level
 | 
			
		||||
    model_id = model_tree.get("modelId", "unknown")
 | 
			
		||||
    logging.info(f"{indent}→ Running model: {model_id}")
 | 
			
		||||
    
 | 
			
		||||
    detection, bbox = run_pipeline(frame, model_tree, return_bbox=True)
 | 
			
		||||
    
 | 
			
		||||
    if detection:
 | 
			
		||||
        confidence = detection.get("confidence", 0) * 100
 | 
			
		||||
        class_name = detection.get("class", "unknown")
 | 
			
		||||
        object_id = detection.get("id", "N/A")
 | 
			
		||||
        
 | 
			
		||||
        logging.info(f"{indent}✓ Detected: {class_name} (ID: {object_id}, confidence: {confidence:.1f}%)")
 | 
			
		||||
        
 | 
			
		||||
        # Check if any branches were triggered
 | 
			
		||||
        triggered = False
 | 
			
		||||
        for branch in model_tree.get("branches", []):
 | 
			
		||||
            trigger_classes = branch.get("triggerClasses", [])
 | 
			
		||||
            min_conf = branch.get("minConfidence", 0)
 | 
			
		||||
            
 | 
			
		||||
            if class_name in trigger_classes and detection.get("confidence", 0) >= min_conf:
 | 
			
		||||
                triggered = True
 | 
			
		||||
                if branch.get("crop", False) and bbox:
 | 
			
		||||
                    x1, y1, x2, y2 = bbox
 | 
			
		||||
                    cropped_frame = frame[y1:y2, x1:x2]
 | 
			
		||||
                    logging.info(f"{indent}  ⌊ Triggering branch with cropped region {x1},{y1} to {x2},{y2}")
 | 
			
		||||
                    branch_result = log_pipeline_flow(cropped_frame, branch, level + 1)
 | 
			
		||||
                else:
 | 
			
		||||
                    logging.info(f"{indent}  ⌊ Triggering branch with full frame")
 | 
			
		||||
                    branch_result = log_pipeline_flow(frame, branch, level + 1)
 | 
			
		||||
                
 | 
			
		||||
                if branch_result[0]:  # If branch detection successful, return it
 | 
			
		||||
                    return branch_result
 | 
			
		||||
        
 | 
			
		||||
        if not triggered and model_tree.get("branches"):
 | 
			
		||||
            logging.info(f"{indent}  ⌊ No branches triggered")
 | 
			
		||||
    else:
 | 
			
		||||
        logging.info(f"{indent}✗ No detection for {model_id}")
 | 
			
		||||
    
 | 
			
		||||
    return detection, bbox
 | 
			
		||||
 | 
			
		||||
def main(mpta_file: str, video_source: str):
 | 
			
		||||
    global capture_running
 | 
			
		||||
    CACHE_DIR = os.path.join(".", ".mptacache")
 | 
			
		||||
| 
						 | 
				
			
			@ -52,9 +104,11 @@ def main(mpta_file: str, video_source: str):
 | 
			
		|||
            if not global_ret or global_frame is None:
 | 
			
		||||
                continue  # wait until a frame is available
 | 
			
		||||
            
 | 
			
		||||
            frame = global_frame  # local copy to work with
 | 
			
		||||
            frame = global_frame.copy()  # local copy to work with
 | 
			
		||||
 | 
			
		||||
            # Replace run_pipeline with our logging version
 | 
			
		||||
            detection, bbox = log_pipeline_flow(frame, model_tree)
 | 
			
		||||
            
 | 
			
		||||
            detection, bbox = run_pipeline(frame, model_tree, return_bbox=True)
 | 
			
		||||
            if bbox:
 | 
			
		||||
                x1, y1, x2, y2 = bbox
 | 
			
		||||
                cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -87,6 +87,35 @@ def run_pipeline(frame, node: dict, return_bbox: bool = False):
 | 
			
		|||
    for drawing. Otherwise, returns only the detection.
 | 
			
		||||
    """
 | 
			
		||||
    try:
 | 
			
		||||
        # Check model type and use appropriate method
 | 
			
		||||
        model_task = getattr(node["model"], "task", None)
 | 
			
		||||
        
 | 
			
		||||
        if model_task == "classify":
 | 
			
		||||
            # Classification models need to use predict() instead of track()
 | 
			
		||||
            logging.debug(f"Running classification model: {node.get('modelId')}")
 | 
			
		||||
            results = node["model"].predict(frame, stream=False)
 | 
			
		||||
            detection = None
 | 
			
		||||
            best_box = None
 | 
			
		||||
            
 | 
			
		||||
            # Process classification results
 | 
			
		||||
            for r in results:
 | 
			
		||||
                probs = r.probs
 | 
			
		||||
                if probs is not None and len(probs) > 0:
 | 
			
		||||
                    # Get the most confident class
 | 
			
		||||
                    class_id = int(probs.top1)
 | 
			
		||||
                    conf = float(probs.top1conf)
 | 
			
		||||
                    detection = {
 | 
			
		||||
                        "class": node["model"].names[class_id],
 | 
			
		||||
                        "confidence": conf,
 | 
			
		||||
                        "id": None  # Classification doesn't have tracking IDs
 | 
			
		||||
                    }
 | 
			
		||||
            
 | 
			
		||||
            # Classification doesn't produce bounding boxes
 | 
			
		||||
            bbox = None
 | 
			
		||||
            
 | 
			
		||||
        else:
 | 
			
		||||
            # Detection/segmentation models use tracking
 | 
			
		||||
            logging.debug(f"Running detection/tracking model: {node.get('modelId')}")
 | 
			
		||||
            results = node["model"].track(frame, stream=False, persist=True)
 | 
			
		||||
            detection = None
 | 
			
		||||
            best_box = None
 | 
			
		||||
| 
						 | 
				
			
			@ -106,7 +135,7 @@ def run_pipeline(frame, node: dict, return_bbox: bool = False):
 | 
			
		|||
                        best_box = box_cpu
 | 
			
		||||
 | 
			
		||||
            bbox = None
 | 
			
		||||
        # Modified bounding box calculation: always compute bbox if best_box exists
 | 
			
		||||
            # Calculate bbox if best_box exists
 | 
			
		||||
            if detection and best_box is not None:
 | 
			
		||||
                coords = best_box.xyxy[0]
 | 
			
		||||
                x1, y1, x2, y2 = map(int, coords)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue