Enhance car detection logic with bbox area validation and update .gitignore
This commit is contained in:
		
							parent
							
								
									356da144fc
								
							
						
					
					
						commit
						34ecff244c
					
				
					 3 changed files with 94 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -733,12 +733,17 @@ def run_detection_with_tracking(frame, node, context=None):
 | 
			
		|||
            
 | 
			
		||||
            # Tracking zone validation removed - process all detections
 | 
			
		||||
            
 | 
			
		||||
            # Calculate bbox area
 | 
			
		||||
            x1, y1, x2, y2 = bbox
 | 
			
		||||
            bbox_area = (x2 - x1) * (y2 - y1)
 | 
			
		||||
            
 | 
			
		||||
            # Create detection object
 | 
			
		||||
            detection = {
 | 
			
		||||
                "class": class_name,
 | 
			
		||||
                "confidence": conf,
 | 
			
		||||
                "id": track_id,
 | 
			
		||||
                "bbox": bbox,
 | 
			
		||||
                "bbox_area": bbox_area,
 | 
			
		||||
                "class_id": cls_id
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
| 
						 | 
				
			
			@ -927,6 +932,31 @@ def update_single_track_stability(node, detection, camera_id, frame_shape=None,
 | 
			
		|||
    
 | 
			
		||||
    current_track_id = detection.get("id") if detection else None
 | 
			
		||||
    
 | 
			
		||||
    # ─── Bbox Area Validation for Stability ───
 | 
			
		||||
    # Only count detections where bbox area is >=20% of frame (close cars only)
 | 
			
		||||
    if detection and frame_shape is not None:
 | 
			
		||||
        bbox = detection.get("bbox", [0, 0, 0, 0])
 | 
			
		||||
        if bbox and len(bbox) >= 4:
 | 
			
		||||
            x1, y1, x2, y2 = bbox
 | 
			
		||||
            bbox_area = (x2 - x1) * (y2 - y1)
 | 
			
		||||
            frame_height, frame_width = frame_shape[:2]
 | 
			
		||||
            frame_area = frame_height * frame_width
 | 
			
		||||
            bbox_area_ratio = bbox_area / frame_area if frame_area > 0 else 0
 | 
			
		||||
            
 | 
			
		||||
            # Require bbox to be at least 20% of frame area
 | 
			
		||||
            min_area_ratio = 0.2
 | 
			
		||||
            
 | 
			
		||||
            if bbox_area_ratio < min_area_ratio:
 | 
			
		||||
                logger.info(f"🚫 Camera {camera_id}: Track {current_track_id} REJECTED for stability - bbox area {bbox_area_ratio:.1%} < {min_area_ratio:.0%} (too small/distant)")
 | 
			
		||||
                # Completely reset - remove track entirely (same as trackId change)
 | 
			
		||||
                if current_track_id and current_track_id in track_counters:
 | 
			
		||||
                    old_count = track_counters.pop(current_track_id, 0)  # Remove completely
 | 
			
		||||
                    stable_tracks.discard(current_track_id)  # Remove from stable
 | 
			
		||||
                    logger.info(f"🔄 Camera {camera_id}: COMPLETELY RESET track {current_track_id} counter from {old_count} to 0 (reason: bbox too small)")
 | 
			
		||||
                return {"validation_complete": False, "stable_tracks": list(stable_tracks), "current_tracks": [], "bbox_too_small": True}
 | 
			
		||||
            else:
 | 
			
		||||
                logger.debug(f"✅ Camera {camera_id}: Track {current_track_id} bbox area {bbox_area_ratio:.1%} >= {min_area_ratio:.0%} - acceptable for stability")
 | 
			
		||||
    
 | 
			
		||||
    # ═══ MODE-AWARE TRACK VALIDATION ═══
 | 
			
		||||
    logger.debug(f"📋 Camera {camera_id}: === TRACK VALIDATION ANALYSIS ===")
 | 
			
		||||
    logger.debug(f"📋 Camera {camera_id}: Current mode: {current_mode} (validation_mode={is_validation_mode})")
 | 
			
		||||
| 
						 | 
				
			
			@ -1432,6 +1462,35 @@ def run_pipeline(frame, node: dict, return_bbox: bool=False, context=None, valid
 | 
			
		|||
        else:
 | 
			
		||||
            # Normal detection stage - Using structured detection function
 | 
			
		||||
            all_detections, regions_dict, track_validation_result = run_detection_with_tracking(frame, node, context)
 | 
			
		||||
            
 | 
			
		||||
            # ─── Apply largest bbox area selection for full pipeline mode ───
 | 
			
		||||
            # When we have stable tracks and multiple detections, select the largest bbox area one
 | 
			
		||||
            stable_tracks = track_validation_result.get("stable_tracks", [])
 | 
			
		||||
            if stable_tracks and len(all_detections) > 1:
 | 
			
		||||
                logger.info(f"🔍 PIPELINE: Full pipeline mode - selecting largest bbox area from {len(all_detections)} detections")
 | 
			
		||||
                
 | 
			
		||||
                # Select detection with largest bbox area
 | 
			
		||||
                largest_detection = max(all_detections, key=lambda x: x.get("bbox_area", 0))
 | 
			
		||||
                logger.info(f"🎯 PIPELINE: Selected largest bbox area detection: conf={largest_detection.get('confidence', 0):.3f}, area={largest_detection.get('bbox_area', 0):.0f}")
 | 
			
		||||
                
 | 
			
		||||
                # Update all_detections to only contain the largest bbox area detection
 | 
			
		||||
                all_detections = [largest_detection]
 | 
			
		||||
                
 | 
			
		||||
                # Update regions_dict to reflect the selected detection
 | 
			
		||||
                class_name = largest_detection.get("class", "car")
 | 
			
		||||
                regions_dict = {
 | 
			
		||||
                    class_name: {
 | 
			
		||||
                        "confidence": largest_detection.get("confidence"),
 | 
			
		||||
                        "bbox": largest_detection.get("bbox", [0, 0, 0, 0]),
 | 
			
		||||
                        "detection": largest_detection
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                logger.debug(f"🔄 PIPELINE: Updated regions_dict for largest bbox area selection: {list(regions_dict.keys())}")
 | 
			
		||||
            elif stable_tracks:
 | 
			
		||||
                logger.debug(f"🔄 PIPELINE: Full pipeline mode - single detection, no area selection needed")
 | 
			
		||||
            else:
 | 
			
		||||
                logger.debug(f"🔄 PIPELINE: No stable tracks yet, proceeding with confidence-based detection")
 | 
			
		||||
        
 | 
			
		||||
        # Debug: Save crops for debugging (disabled for production)
 | 
			
		||||
        # if regions_dict:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue