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

#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;
}