基于质心欧氏距离优化鸟瞰图彩色车辆检测的技术咨询
Hey Khaled, let's work through this problem to fix those persistent false positives from static objects like your T-shirt. The core issue here is that static interference will eventually have centroid distances under your threshold once the vehicle is gone—so we need to add checks that distinguish stable, long-term static objects from either moving vehicles or temporarily stationary ones. Here are practical, actionable tweaks you can implement:
1. Add Centroid "Activity" Validation (Not Just Single Frame Distance)
Static interference will have a perfectly consistent centroid across frames (or near-perfect, thanks to minimal detection noise), while even stationary vehicles will have tiny fluctuations in their detected centroid. Instead of comparing just two frames, calculate the variance of centroid coordinates across recent frames to measure "activity":
import numpy as np from collections import deque import scipy.spatial.distance centroids = deque(maxlen=10) # Extend to store more frames for better variance calculation # After detecting a center and adding it to centroids if len(centroids) >= 5: # Convert recent centroids to a numpy array for easy stats recent_centroids = np.array(list(centroids)[:5]) # Calculate variance of x and y coordinates x_variance = np.var(recent_centroids[:, 0]) y_variance = np.var(recent_centroids[:, 1]) # Set a small threshold (adjust based on your detection noise) activity_threshold = 2.0 if x_variance < activity_threshold and y_variance < activity_threshold: # This blob is too stable—likely a static interference, skip it continue
2. Track Continuous Blob Presence Over Frames
Real vehicles (even stationary ones) will appear consistently across multiple frames, while random static interference might pop up after the vehicle leaves, or only appear sporadically. Use a tracking dictionary to count how many consecutive frames a blob has been detected:
from collections import defaultdict # Dictionary to track consecutive appearance counts for each blob (using centroid as key) blob_tracker = defaultdict(int) match_threshold = 10 # Max distance to consider two centroids the same blob # After detecting current center matched_centroid = None for existing_centroid in list(blob_tracker.keys()): dist = scipy.spatial.distance.euclidean(center, existing_centroid) if dist < match_threshold: matched_centroid = existing_centroid break if matched_centroid: blob_tracker[matched_centroid] += 1 # Remove old entries to avoid clutter if blob_tracker[matched_centroid] > 20: del blob_tracker[matched_centroid] blob_tracker[tuple(center)] = blob_tracker[matched_centroid] else: blob_tracker[tuple(center)] = 1 # Only keep blobs that have appeared in at least 3 consecutive frames if blob_tracker[tuple(center)] < 3: continue
3. Layer in Color Histogram Similarity Checks
Your histogram backprojection already matches color ranges, but you can refine this by comparing the full color distribution of the candidate blob to a pre-sampled vehicle histogram. Static objects like T-shirts might have similar hue but different color variance or intensity distributions:
import cv2 # Precompute a histogram from a known red vehicle sample (do this once at startup) sample_vehicle_img = cv2.imread("red_vehicle_sample.jpg") sample_hist = cv2.calcHist([sample_vehicle_img], [0, 1, 2], None, [8, 8, 8], [0, 256, 0, 256, 0, 256]) cv2.normalize(sample_hist, sample_hist, 0, 255, cv2.NORM_MINMAX) # For each candidate blob (x,y,w,h are the blob's bounding box) blob_roi = frame[y:y+h, x:x+w] blob_hist = cv2.calcHist([blob_roi], [0, 1, 2], None, [8, 8, 8], [0, 256, 0, 256, 0, 256]) cv2.normalize(blob_hist, blob_hist, 0, 255, cv2.NORM_MINMAX) # Use Bhattacharyya distance (lower = more similar) to compare histograms similarity_score = cv2.compareHist(sample_hist, blob_hist, cv2.HISTCMP_BHATTACHARYYA) if similarity_score > 0.3: # Adjust threshold based on your samples continue
4. Static Background Filtering
Since you're working with a bird's-eye view, the background (like pavement, tables) is likely stable. Use a background subtractor to filter out objects that are part of the static background:
bg_subtractor = cv2.createBackgroundSubtractorMOG2(history=500, detectShadows=False) # Apply to each frame fg_mask = bg_subtractor.apply(frame) # Check if the blob's region is mostly foreground roi_mask = fg_mask[y:y+h, x:x+w] foreground_ratio = np.sum(roi_mask == 255) / (w * h) if foreground_ratio < 0.5: # Less than 50% foreground = static background object continue
How to Combine These
Start with the fastest checks first to minimize computation:
- Background filtering → quickly eliminate static background objects
- Rectangularity/area checks → remove obvious non-vehicle shapes
- Centroid activity validation → filter out overly static blobs
- Continuous presence tracking → ensure the blob is a consistent object
- Color histogram similarity → final fine-tune for color distribution matches
This layered approach should eliminate those T-shirt false positives while keeping valid vehicle detections intact.
内容的提问来源于stack exchange,提问作者Khaled

