You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
3.6 KiB
123 lines
3.6 KiB
|
|
#include <opencv2/opencv.hpp> |
|
#include <opencv2/video.hpp> |
|
|
|
#include "parking_method.h" |
|
#include "utility.h" |
|
#include <sys/time.h> |
|
#include <iostream> |
|
#include <random> |
|
|
|
using namespace cv; |
|
using namespace std; |
|
|
|
// 車輛信息結構體 |
|
struct VehicleInfo { |
|
Rect bbox; |
|
time_t firstSeen; // 首次偵測時間 |
|
time_t lastSeen; // 最後一次更新的時間 |
|
int isParked; // 是否已停車 |
|
}; |
|
|
|
vector<vector<VehicleInfo>> 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; |
|
} |
|
|
|
|
|
|