#include #include #include "parking_method.h" #include "utility.h" #include #include #include using namespace cv; using namespace std; // 車輛信息結構體 struct VehicleInfo { Rect bbox; time_t firstSeen; // 首次偵測時間 time_t lastSeen; // 最後一次更新的時間 int isParked; // 是否已停車 }; vector> putting_vehicles(MAX_DETECTION_ZONE); // 超時清理的時間閾值 (10秒未更新就清理) const int timeoutThreshold = 10; // time_t now = time(0); void push_back_to_track_vehicle(detection_pos* pNext, int detection_zone_idx) { if (putting_vehicles[detection_zone_idx].size() < MAX_QUEUE_VEHICLEINFO_SIZE) { VehicleInfo newVehicle; newVehicle.bbox.x = pNext->left_x; newVehicle.bbox.y = pNext->top_y; newVehicle.bbox.width = pNext->width; newVehicle.bbox.height = pNext->height; time_t current_time = time(0); newVehicle.firstSeen = current_time; newVehicle.lastSeen = current_time; newVehicle.isParked = 0; putting_vehicles[detection_zone_idx].push_back(newVehicle); } } void pop_not_to_track_vehicles(int detection_zone_idx, time_t current_time) { // 用 for 迴圈檢查車輛是否需要清除 if (putting_vehicles[detection_zone_idx].size() >= 1) { for (int j = putting_vehicles[detection_zone_idx].size() - 1; j >= 0; --j) { // 從後往前遍歷,避免刪除時影響索引 double unseenDuration = difftime(current_time, putting_vehicles[detection_zone_idx][j].lastSeen); if (unseenDuration > timeoutThreshold) { putting_vehicles[detection_zone_idx].erase(putting_vehicles[detection_zone_idx].begin() + j); // 刪除符合條件的車輛 } } if (putting_vehicles[detection_zone_idx].empty()) { putting_vehicles[detection_zone_idx].clear(); // 清除所有元素 putting_vehicles[detection_zone_idx].shrink_to_fit(); // 釋放未使用的記憶體 } } } void clear_putting_vehicles() { for (int i = 0; i < MAX_DETECTION_ZONE; i++) { putting_vehicles[i].clear(); // 清除所有元素 putting_vehicles[i].shrink_to_fit(); // 釋放未使用的記憶體 } putting_vehicles.clear(); } int isVehicleStatic(const Rect& prev_bbox, const Rect& curr_bbox, int threshold = 8) { int deltaX = abs((prev_bbox.x + prev_bbox.width / 2) - (curr_bbox.x + curr_bbox.width / 2)); int deltaY = abs((prev_bbox.y + prev_bbox.height / 2) - (curr_bbox.y + curr_bbox.height / 2)); // 檢查長度和寬度是否在一定範圍內 int deltaWidth = abs(prev_bbox.width - curr_bbox.width); int deltaHeight = abs(prev_bbox.height - curr_bbox.height); if (deltaX <= threshold && deltaY <= threshold && deltaWidth <= threshold * 2 && deltaHeight <= threshold * 2) return 1; else return 0; } int check_vehicle_over_time(detection_pos* pNext,int detection_zone_idx,double parkingTimeThreshold) { int check_if_over_time = 0; if (pNext->center_stability == (float)DIRECTION_DEFAULT) { int foundMatch = 0; time_t current_time = time(0); Rect bbox(pNext->left_x, pNext->top_y, pNext->width, pNext->height); // 嘗試在已追蹤的車輛中找到相似位置的車輛 for (auto& vInfo : putting_vehicles[detection_zone_idx]) { // 如果車輛位置相似,則更新該車輛的信息 if (isVehicleStatic(vInfo.bbox, bbox)) { foundMatch = 1; double duration = difftime(current_time, vInfo.firstSeen); // 判斷是否停車 if (duration > parkingTimeThreshold) { vInfo.isParked = 1; check_if_over_time = 1; } // 更新物件框和最後一次看到的時間 vInfo.bbox = bbox; vInfo.lastSeen = current_time; break; } } // 如果沒有匹配,新增這個車輛到追蹤清單 if (!foundMatch) { push_back_to_track_vehicle(pNext, detection_zone_idx); } } return check_if_over_time; }