mirror of
https://gitee.com/nanjing-yimao-information/ieemoo-ai-gift.git
synced 2025-08-23 23:50:25 +00:00
update
This commit is contained in:
76
pipline_test/choose_negtive.py
Normal file
76
pipline_test/choose_negtive.py
Normal file
@ -0,0 +1,76 @@
|
||||
import os
|
||||
import random
|
||||
import shutil # 新增:导入 shutil 模块用于目录复制
|
||||
|
||||
def extract_process_data_from_subfolders(root_path, shuffle=False):
|
||||
"""
|
||||
从指定路径下的每个子文件夹中提取 process.data 文件的内容,并与子文件夹名称建立对应关系。
|
||||
如果 shuffle 为 True,则随机从 root_path 中选择 65 个子文件夹。
|
||||
"""
|
||||
# 存储子文件夹名称与 process.data 文件内容的对应关系
|
||||
result = {}
|
||||
negtive = []
|
||||
# 获取所有子文件夹路径
|
||||
subfolders = [folder for folder in os.listdir(root_path) if os.path.isdir(os.path.join(root_path, folder))]
|
||||
|
||||
num = 0
|
||||
# 遍历指定路径下的所有子文件夹
|
||||
for folder_name in subfolders:
|
||||
folder_path = os.path.join(root_path, folder_name)
|
||||
if "process.data" in os.listdir(folder_path):
|
||||
file_path = os.path.join(folder_path, "process.data")
|
||||
|
||||
try:
|
||||
# 读取 process.data 文件内容
|
||||
with open(file_path, 'r', encoding='utf-8') as file:
|
||||
full_content = file.read()
|
||||
|
||||
# 提取 "gift identify result:" 后的内容
|
||||
if "gift identify result:" in full_content:
|
||||
content = full_content.split("gift identify result:", 1)[1].strip()
|
||||
# 去掉 content 中的换行符
|
||||
content = content.replace('\n', '')
|
||||
|
||||
# 新增:去掉逗号后面的空格
|
||||
content = content.replace(', ', ',')
|
||||
|
||||
# 新增:将 content 以逗号为分隔符分成若干组
|
||||
groups = content.split(',')
|
||||
|
||||
# 修改:以空格为分隔符取每组的前一个字符,并转成列表,同时去掉空字符串并转换为整数
|
||||
result_list = [float(group.split(' ')[0]) for group in groups if group.split(' ')[0]]
|
||||
result_list = sorted(result_list, reverse=True)
|
||||
if result_list and result_list[0] > 0.5:
|
||||
num += 1
|
||||
negtive.append(folder_path)
|
||||
continue
|
||||
|
||||
# 将结果列表存入字典
|
||||
result[os.path.basename(folder_path)] = result_list
|
||||
else:
|
||||
print(f"文件中未找到 'gift identify result:' 标记: {file_path}")
|
||||
continue
|
||||
except Exception as e:
|
||||
print(f"读取文件失败: {file_path}, 错误信息: {e}")
|
||||
print(num)
|
||||
print(negtive)
|
||||
|
||||
# 新增:将 negtive 列表中的目录复制到目标路径
|
||||
target_path = "../data/negtive"
|
||||
for folder in negtive:
|
||||
try:
|
||||
# 使用 shutil.copytree 复制目录
|
||||
shutil.copytree(folder, os.path.join(target_path, os.path.basename(folder)))
|
||||
print(f"成功复制目录: {folder}")
|
||||
except Exception as e:
|
||||
print(f"复制目录失败: {folder}, 错误信息: {e}")
|
||||
|
||||
return result
|
||||
|
||||
|
||||
# 调用函数并打印结果
|
||||
if __name__ == "__main__":
|
||||
# 指定根路径
|
||||
comm_path = "/testDataAndLogs/测试视频数据以及日志/全实时_YoloV10s/20250512"
|
||||
|
||||
comm_data_dict = extract_process_data_from_subfolders(comm_path, shuffle=False) # 修改:新增 shuffle 参数
|
40
pipline_test/create_text.py
Normal file
40
pipline_test/create_text.py
Normal file
@ -0,0 +1,40 @@
|
||||
import os
|
||||
import shutil
|
||||
|
||||
def delete_trajectory_files_and_dirs(root_dir):
|
||||
"""
|
||||
删除指定目录下的所有 trajectory 子目录、trajectory.png 文件以及 MP4 文件。
|
||||
|
||||
:param root_dir: 目标根目录
|
||||
"""
|
||||
for dirpath, dirnames, filenames in os.walk(root_dir, topdown=False):
|
||||
# 删除 trajectory 子目录
|
||||
for dirname in dirnames:
|
||||
if dirname == "trajectory":
|
||||
dir_to_delete = os.path.join(dirpath, dirname)
|
||||
try:
|
||||
shutil.rmtree(dir_to_delete)
|
||||
print(f"Deleted directory: {dir_to_delete}")
|
||||
except Exception as e:
|
||||
print(f"Failed to delete directory {dir_to_delete}: {e}")
|
||||
|
||||
# 删除 trajectory.png 文件和 MP4 文件
|
||||
for filename in filenames:
|
||||
if filename.endswith(".png") and "trajectory" in filename:
|
||||
file_to_delete = os.path.join(dirpath, filename)
|
||||
try:
|
||||
os.remove(file_to_delete)
|
||||
print(f"Deleted file: {file_to_delete}")
|
||||
except Exception as e:
|
||||
print(f"Failed to delete file {file_to_delete}: {e}")
|
||||
elif filename.endswith(".mp4"):
|
||||
file_to_delete = os.path.join(dirpath, filename)
|
||||
try:
|
||||
os.remove(file_to_delete)
|
||||
print(f"Deleted file: {file_to_delete}")
|
||||
except Exception as e:
|
||||
print(f"Failed to delete file {file_to_delete}: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
target_dir = "/home/lc/data_center/gift/trace_subimgs/actual_test/commodity"
|
||||
delete_trajectory_files_and_dirs(target_dir)
|
144
pipline_test/display_result.py
Normal file
144
pipline_test/display_result.py
Normal file
@ -0,0 +1,144 @@
|
||||
from sklearn.preprocessing import label_binarize
|
||||
from sklearn.metrics import precision_recall_curve, average_precision_score
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
# from utils.config import conf
|
||||
import os
|
||||
|
||||
|
||||
# def show_multiclass_pr(y_true, y_scores): # 多分类
|
||||
# # 将真实标签二值化
|
||||
# y_true_binarized = label_binarize(y_true, classes=np.arange(conf.n_classes))
|
||||
#
|
||||
# # 计算每个类别的PR曲线和平均精度
|
||||
# precision = dict()
|
||||
# recall = dict()
|
||||
# average_precision = dict()
|
||||
#
|
||||
# for i in range(conf.n_classes):
|
||||
# precision[i], recall[i], _ = precision_recall_curve(y_true_binarized[:, i], y_scores[:, i])
|
||||
# average_precision[i] = average_precision_score(y_true_binarized[:, i], y_scores[:, i])
|
||||
#
|
||||
# # 计算微平均PR曲线和平均精度
|
||||
# precision["micro"], recall["micro"], _ = precision_recall_curve(y_true_binarized.ravel(), y_scores.ravel())
|
||||
# average_precision["micro"] = average_precision_score(y_true_binarized, y_scores, average="micro")
|
||||
#
|
||||
# # 计算宏平均PR曲线和平均精度
|
||||
# precision["macro"] = np.mean([precision[i] for i in range(conf.n_classes)], axis=0)
|
||||
# recall["macro"] = np.mean([recall[i] for i in range(conf.n_classes)], axis=0)
|
||||
# average_precision["macro"] = np.mean([average_precision[i] for i in range(conf.n_classes)])
|
||||
#
|
||||
# # 绘制微平均PR曲线
|
||||
# plt.figure(figsize=(10, 7))
|
||||
# plt.plot(recall["micro"], precision["micro"], color='gold', lw=2,
|
||||
# label='micro-average Precision-recall curve (area = {0:0.2f})'
|
||||
# ''.format(average_precision["micro"]))
|
||||
#
|
||||
# # 绘制宏平均PR曲线
|
||||
# plt.plot(recall["macro"], precision["macro"], color='navy', lw=2,
|
||||
# label='macro-average Precision-recall curve (area = {0:0.2f})'
|
||||
# ''.format(average_precision["macro"]))
|
||||
#
|
||||
# # 绘制每个类别的PR曲线
|
||||
# colors = plt.cm.tab20(np.linspace(0, 1, conf.n_classes))
|
||||
# for i, color in zip(range(conf.n_classes), colors):
|
||||
# plt.plot(recall[i], precision[i], color=color, lw=2,
|
||||
# label='Precision-recall curve of class {0} (area = {1:0.2f})'
|
||||
# ''.format(i, average_precision[i]))
|
||||
#
|
||||
# plt.xlabel('Recall')
|
||||
# plt.ylabel('Precision')
|
||||
# plt.title('Extension of Precision-Recall curve to multi-class')
|
||||
# plt.legend(loc="best")
|
||||
# plt.show()
|
||||
# pass
|
||||
|
||||
|
||||
def calculate_similarity(outputs, targets, threshold):
|
||||
FN, FP, TN, TP = 0, 0, 0, 0
|
||||
for output, target in zip(outputs, targets):
|
||||
# print("output >> {} , target >> {}".format(output, target))
|
||||
if output != target:
|
||||
if target == 0:
|
||||
FP += 1
|
||||
elif target == 1:
|
||||
FN += 1
|
||||
else:
|
||||
if target == 0:
|
||||
TN += 1
|
||||
elif target == 1:
|
||||
TP += 1
|
||||
if TP == 0:
|
||||
prec, recall = 0, 0
|
||||
else:
|
||||
prec = TP / (TP + FP)
|
||||
recall = TP / (TP + FN)
|
||||
if TN == 0:
|
||||
tn_prec, tn_recall = 0, 0
|
||||
else:
|
||||
tn_prec = TN / (TN + FN)
|
||||
tn_recall = TN / (TN + FP)
|
||||
# print("TP>>{}, FP>>{}, TN>>{}, FN>>{}".format(TP, FP, TN, FN))
|
||||
if threshold == 0.1:
|
||||
print("TP>>{}, FP>>{}, TN>>{}, FN>>{}".format(TP, FP, TN, FN))
|
||||
return prec, recall, tn_prec, tn_recall
|
||||
|
||||
|
||||
def show_pr(prec, recall, tn_prec, tn_recall, thres, title_name):
|
||||
x = thres
|
||||
plt.figure(figsize=(10, 6))
|
||||
plt.plot(x, recall, color='red', label='recall:TP/TPFN')
|
||||
plt.plot(x, tn_recall, color='black', label='recall_TN:TN/TNFP')
|
||||
plt.plot(x, prec, color='blue', label='PrecisePos:TP/TPFN')
|
||||
plt.plot(x, tn_prec, color='green', label='PreciseNeg:TN/TNFP')
|
||||
plt.legend()
|
||||
plt.xlabel('threshold')
|
||||
# if self.title_name is not None:
|
||||
plt.title(title_name)
|
||||
plt.grid(True, linestyle='--', alpha=0.5)
|
||||
plt.savefig(os.sep.join(['../pr_test', 'yolo_pr.png']))
|
||||
plt.show()
|
||||
plt.close()
|
||||
|
||||
|
||||
def write_results_to_file(title_name, thres, recall, recall_TN, PrecisePos, PreciseNeg):
|
||||
file_path = os.sep.join(['../pr_test', title_name + '.txt'])
|
||||
with open(file_path, 'w') as file:
|
||||
file.write("threshold, recall, recall_TN, PrecisePos, PreciseNeg\n")
|
||||
for thre, rec, rec_tn, prec_pos, prec_neg in zip(thres, recall, recall_TN, PrecisePos, PreciseNeg):
|
||||
file.write(
|
||||
f"thre>>{thre:.2f}, recall>>{rec:.4f}, precise_pos>>{prec_pos:.4f}, recall_tn>>{rec_tn:.4f}, precise_neg>>{prec_neg:4f}\n")
|
||||
|
||||
|
||||
def show_to_pr(y_true, y_prob, type): # 二分类
|
||||
thres = [i * 0.01 for i in range(101)]
|
||||
title_name = 'yolo_pr'
|
||||
recall, recall_TN, PrecisePos, PreciseNeg = [], [], [], []
|
||||
for threshold in thres:
|
||||
y_scores_adjusted = []
|
||||
if type == 0:
|
||||
y_scores_adjusted = np.where(y_prob < threshold, 0, 1)
|
||||
elif type == 1:
|
||||
for yp in y_prob:
|
||||
if yp != 0:
|
||||
yp = np.array(yp)
|
||||
yp_num = np.sum(np.array(yp) > threshold)
|
||||
if yp_num / len(yp) > 0.1:
|
||||
y_scores_adjusted.append(1)
|
||||
else:
|
||||
y_scores_adjusted.append(0)
|
||||
else:
|
||||
y_scores_adjusted.append(0)
|
||||
prec, pos_recall, tn_prec, tn_recall = calculate_similarity(y_scores_adjusted, y_true, threshold)
|
||||
recall.append(pos_recall)
|
||||
recall_TN.append(tn_recall)
|
||||
PrecisePos.append(prec)
|
||||
PreciseNeg.append(tn_prec)
|
||||
# print(" prec>>{} recall>>{} tn_prec>>{} tn_recall>>{} threshold>>{}\n".format(prec, pos_recall, tn_prec,
|
||||
# tn_recall, threshold))
|
||||
show_pr(PrecisePos, recall, PreciseNeg, recall_TN, thres, title_name)
|
||||
write_results_to_file(title_name, thres, recall, recall_TN, PrecisePos, PreciseNeg)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pass
|
414
pipline_test/read_trackdata_filter.py
Normal file
414
pipline_test/read_trackdata_filter.py
Normal file
@ -0,0 +1,414 @@
|
||||
import os
|
||||
import numpy as np
|
||||
import cv2
|
||||
import shutil
|
||||
from scipy.spatial.distance import euclidean as d_euclidean
|
||||
def read_tracking_output(filepath):
|
||||
'''
|
||||
0/1_tracking_output.data 数据读取
|
||||
'''
|
||||
boxes = []
|
||||
feats = []
|
||||
gift_data = []
|
||||
|
||||
if not os.path.isfile(filepath):
|
||||
return boxes, feats, gift_data
|
||||
|
||||
with open(filepath, 'r', encoding='utf-8') as file:
|
||||
lines = file.readlines()
|
||||
|
||||
# 处理常规的boxes和feats数据
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
if line.find("gift identify result:") >= 0:
|
||||
break
|
||||
|
||||
if line.endswith(','):
|
||||
line = line[:-1]
|
||||
|
||||
try:
|
||||
data = np.array([float(x) for x in line.split(",")])
|
||||
if data.size == 9:
|
||||
boxes.append(data)
|
||||
if data.size == 256:
|
||||
feats.append(data)
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
# 提取gift identify result和select back tracking feats index之间的数据
|
||||
try:
|
||||
start_idx = -1
|
||||
end_idx = -1
|
||||
for i, line in enumerate(lines):
|
||||
if "gift identify result:" in line:
|
||||
start_idx = i + 1
|
||||
elif "select back tracking feats index:" in line:
|
||||
end_idx = i
|
||||
break
|
||||
|
||||
if start_idx != -1 and end_idx != -1:
|
||||
for i in range(start_idx, end_idx):
|
||||
line = lines[i].strip()
|
||||
if line:
|
||||
gift_data.append(line)
|
||||
except Exception as e:
|
||||
print(f"Error extracting gift data: {e}")
|
||||
|
||||
if len(feats) != len(boxes) or len(boxes) == 0:
|
||||
return [], [], gift_data
|
||||
|
||||
return [np.array(boxes)], [np.array(feats)], gift_data
|
||||
|
||||
|
||||
def extract_data_realtime(datapath):
|
||||
boxes, feats = [], []
|
||||
tracker_feats = {}
|
||||
with open(datapath, 'r', encoding='utf-8') as lines:
|
||||
for line in lines:
|
||||
line = line.strip() # 去除行尾的换行符和可能的空白字符
|
||||
if not line: # 跳过空行
|
||||
continue
|
||||
|
||||
if line.endswith(','):
|
||||
line = line[:-1]
|
||||
ftlist = [float(x) for x in line.split()]
|
||||
|
||||
if len(ftlist) != 265:
|
||||
continue
|
||||
boxes.append(ftlist[:9])
|
||||
feats.append(ftlist[9:])
|
||||
|
||||
trackerboxes = np.array(boxes)
|
||||
trackerfeats = np.array(feats)
|
||||
|
||||
if len(trackerboxes) == 0 or len(trackerboxes) != len(trackerfeats):
|
||||
return np.array([]), {}
|
||||
|
||||
frmIDs = np.sort(np.unique(trackerboxes[:, 7].astype(int)))
|
||||
for fid in frmIDs:
|
||||
idx = np.where(trackerboxes[:, 7] == fid)[0]
|
||||
box = trackerboxes[idx, :]
|
||||
feat = trackerfeats[idx, :]
|
||||
|
||||
for i in range(len(box)):
|
||||
f, b = int(box[i, 7]), int(box[i, 8])
|
||||
tracker_feats.update({f"{f}_{b}": feat[i, :]})
|
||||
return trackerboxes, tracker_feats
|
||||
|
||||
def crop_box(imgpath, xyxy):
|
||||
img = cv2.imread(imgpath)
|
||||
box = img[int(xyxy[1]):int(xyxy[3]), int(xyxy[0]):int(xyxy[2]), :]
|
||||
return box
|
||||
|
||||
def copy_subimgs(video_path, file_name):
|
||||
|
||||
for event in os.listdir(video_path):
|
||||
try:
|
||||
event_path = os.path.join(video_path, event)
|
||||
if len(os.listdir(event_path)) > 0:
|
||||
ori_path = os.path.join(event_path, file_name)
|
||||
sub_path = os.path.join(video_path+'_'+file_name, event, file_name)
|
||||
|
||||
shutil.copytree(ori_path, sub_path)
|
||||
# shutil.rmtree(ori_path)
|
||||
print(f'copy {ori_path} to {sub_path}')
|
||||
except Exception as e:
|
||||
with open('error_copy_subimgs.txt', 'a') as f:
|
||||
f.write(f"{event} {e}\n")
|
||||
|
||||
|
||||
|
||||
def get_img_file(event_path):
|
||||
imgfile_list = []
|
||||
for img_file in os.listdir(event_path):
|
||||
img_path = os.path.join(event_path, img_file)
|
||||
if os.path.isdir(img_path):
|
||||
imgfile_list.append(img_file)
|
||||
return imgfile_list
|
||||
|
||||
def compute_box_dist(boxes, dist=50):
|
||||
# print('boxes', boxes)
|
||||
previous_centers = ()
|
||||
new_boxes = []
|
||||
for i, box in enumerate(boxes):
|
||||
if box[0] == box[1] == box[2] == box[3]:
|
||||
continue
|
||||
x1, y1, x2, y2 = box[:4]
|
||||
center = ((x1 + x2) / 2, (y1 + y2) / 2)
|
||||
|
||||
if i == 0:
|
||||
# 如果前一帧没有中心点信息,则直接添加
|
||||
new_boxes.append(box)
|
||||
previous_centers = center
|
||||
else:
|
||||
distances = np.linalg.norm(np.array(center) - np.array(previous_centers))
|
||||
|
||||
if distances > dist:
|
||||
# 如果所有距离都大于等于100,则添加当前box
|
||||
new_boxes.append(box)
|
||||
previous_centers = center
|
||||
|
||||
return new_boxes
|
||||
|
||||
|
||||
class Trajectory():
|
||||
# def __init__(self, boxes_list):
|
||||
# self.boxes = boxes_list
|
||||
def minimum_desription_length(self, start_idx, curr_idx, trajectory, w_angular=1, w_perpendicular=1, par=True,
|
||||
directional=True):
|
||||
"""
|
||||
Calculate the minimum description length.
|
||||
"""
|
||||
LH = LDH = 0
|
||||
for i in range(start_idx, curr_idx - 1):
|
||||
ed = d_euclidean(trajectory[i], trajectory[i + 1])
|
||||
# print("ed:", ed)
|
||||
LH += max(0, np.log2(ed, where=ed > 0))
|
||||
if par:
|
||||
for j in range(start_idx, i - 1):
|
||||
# print()
|
||||
# print(np.array([trajectory[start_idx], trajectory[i]]))
|
||||
# print(np.array([trajectory[j], trajectory[j+1]]))
|
||||
LDH += w_perpendicular * self.d_perpendicular(np.array([trajectory[start_idx], trajectory[i]]),
|
||||
np.array([trajectory[j], trajectory[j + 1]]))
|
||||
LDH += w_angular * self.d_angular(np.array([trajectory[start_idx], trajectory[i]]),
|
||||
np.array([trajectory[j], trajectory[j + 1]]), directional=directional)
|
||||
# print("LDH:", LDH)
|
||||
if par:
|
||||
return LDH + LH
|
||||
return LH
|
||||
def partition(self, trajectory, directional=True, progress_bar=False, edis=30, w_perpendicular=1, w_angular=1):
|
||||
"""
|
||||
Partition a trajectory into segments.
|
||||
"""
|
||||
# Ensure that the trajectory is a numpy array of shape (n, 2)
|
||||
if not isinstance(trajectory, np.ndarray):
|
||||
raise TypeError("Trajectory must be a numpy array")
|
||||
elif trajectory.shape[1] != 2:
|
||||
raise ValueError("Trajectory must be a numpy array of shape (n, 2)")
|
||||
|
||||
# Initialize the characteristic points, add the first point as a characteristic point
|
||||
cp_indices = []
|
||||
cp_indices.append(0)
|
||||
|
||||
traj_len = trajectory.shape[0]
|
||||
start_idx = 0
|
||||
|
||||
length = 1
|
||||
while start_idx + length < traj_len:
|
||||
if progress_bar:
|
||||
print(f'\r{round(((start_idx + length) / traj_len) * 100, 2)}%', end='')
|
||||
# print(f'Current Index: {start_idx + length}, Trajectory Length: {traj_len}')
|
||||
curr_idx = start_idx + length
|
||||
# print(start_idx, curr_idx)
|
||||
# print(f"Current Index: {curr_idx}, Current point: {trajectory[curr_idx]}")
|
||||
cost_par = self.minimum_desription_length(start_idx, curr_idx, trajectory, w_angular=w_angular,
|
||||
w_perpendicular=w_perpendicular, directional=directional)
|
||||
cost_nopar = self.minimum_desription_length(start_idx, curr_idx, trajectory, par=False, directional=directional)
|
||||
# cost_par += 0 if 1 - cos == 0 else w_feats / (1 - cos)
|
||||
# print(f'Cost with partition: {cost_par}, Cost without partition: {cost_nopar}')
|
||||
if cost_par > cost_nopar and d_euclidean(trajectory[start_idx], trajectory[curr_idx]) > edis:
|
||||
# print('edp:', d_euclidean(trajectory[start_idx], trajectory[curr_idx]))
|
||||
# print(f"Added characteristic point: {trajectory[curr_idx-1]} with index {curr_idx-1}")
|
||||
cp_indices.append(curr_idx - 1)
|
||||
start_idx = curr_idx - 1
|
||||
length = 1
|
||||
else:
|
||||
length += 1
|
||||
|
||||
# Add last point to characteristic points
|
||||
cp_indices.append(len(trajectory) - 1)
|
||||
# print(cp_indices)
|
||||
|
||||
return np.array([trajectory[i] for i in cp_indices]), cp_indices
|
||||
|
||||
def d_angular(self, l1, l2, directional=True):
|
||||
"""
|
||||
Calculate the angular distance between two lines.
|
||||
"""
|
||||
|
||||
# Find the shorter line and assign that as l_shorter
|
||||
l_shorter = l_longer = None
|
||||
l1_len, l2_len = d_euclidean(l1[0], l1[-1]), d_euclidean(l2[0], l2[-1])
|
||||
if l1_len < l2_len:
|
||||
l_shorter = l1
|
||||
l_longer = l2
|
||||
else:
|
||||
l_shorter = l2
|
||||
l_longer = l1
|
||||
|
||||
# Get the minimum intersecting angle between both lines
|
||||
shorter_slope = (l_shorter[-1, 1] - l_shorter[0, 1]) / (l_shorter[-1, 0] - l_shorter[0, 0]) if l_shorter[
|
||||
-1, 0] - \
|
||||
l_shorter[
|
||||
0, 0] != 0 else np.inf
|
||||
longer_slope = (l_longer[-1, 1] - l_longer[0, 1]) / (l_longer[-1, 0] - l_longer[0, 0]) if l_longer[-1, 0] - \
|
||||
l_longer[
|
||||
0, 0] != 0 else np.inf
|
||||
|
||||
# The case of a vertical line
|
||||
theta = None
|
||||
if np.isinf(shorter_slope):
|
||||
# Get the angle of the longer line with the x-axis and subtract it from 90 degrees
|
||||
tan_theta0 = longer_slope
|
||||
tan_theta1 = tan_theta0 * -1
|
||||
theta0 = np.abs(np.arctan(tan_theta0))
|
||||
theta1 = np.abs(np.arctan(tan_theta1))
|
||||
theta = min(theta0, theta1)
|
||||
elif np.isinf(longer_slope):
|
||||
# Get the angle of the shorter line with the x-axis and subtract it from 90 degrees
|
||||
tan_theta0 = shorter_slope
|
||||
tan_theta1 = tan_theta0 * -1
|
||||
theta0 = np.abs(np.arctan(tan_theta0))
|
||||
theta1 = np.abs(np.arctan(tan_theta1))
|
||||
theta = min(theta0, theta1)
|
||||
else:
|
||||
tan_theta0 = (shorter_slope - longer_slope) / (1 + shorter_slope * longer_slope)
|
||||
tan_theta1 = tan_theta0 * -1
|
||||
|
||||
theta0 = np.abs(np.arctan(tan_theta0))
|
||||
theta1 = np.abs(np.arctan(tan_theta1))
|
||||
|
||||
theta = min(theta0, theta1)
|
||||
|
||||
if directional:
|
||||
return np.sin(theta) * d_euclidean(l_longer[0], l_longer[-1])
|
||||
|
||||
if 0 <= theta < (90 * np.pi / 180):
|
||||
return np.sin(theta) * d_euclidean(l_longer[0], l_longer[-1])
|
||||
elif (90 * np.pi / 180) <= theta <= np.pi:
|
||||
return np.sin(theta)
|
||||
else:
|
||||
raise ValueError("Theta is not in the range of 0 to 180 degrees.")
|
||||
|
||||
def get_distance_optimized_bboxes(self, boxes):
|
||||
points = []
|
||||
for box in boxes:
|
||||
points.append([int(box[2]), int(box[3])]) # points 取x2,y2的坐标
|
||||
points = np.array(points)
|
||||
print("&&&&&&&&&&&&&&&&&&", points.shape)
|
||||
partitions, indices = self.partition(points, progress_bar=False, w_perpendicular=100, w_angular=10)
|
||||
bboxes_opt = []
|
||||
for indice in indices:
|
||||
bboxes_opt.append(boxes[indice])
|
||||
return bboxes_opt
|
||||
|
||||
def d_perpendicular(self, l1, l2):
|
||||
"""
|
||||
Calculate the perpendicular distance between two lines.
|
||||
"""
|
||||
# Find the shorter line and assign that as l_shorter
|
||||
l_shorter = l_longer = None
|
||||
l1_len, l2_len = d_euclidean(l1[0], l1[-1]), d_euclidean(l2[0], l2[-1])
|
||||
if l1_len < l2_len:
|
||||
l_shorter = l1
|
||||
l_longer = l2
|
||||
else:
|
||||
l_shorter = l2
|
||||
l_longer = l1
|
||||
|
||||
ps = self.get_point_projection_on_line(l_shorter[0], l_longer)
|
||||
pe = self.get_point_projection_on_line(l_shorter[-1], l_longer)
|
||||
|
||||
lehmer_1 = d_euclidean(l_shorter[0], ps)
|
||||
lehmer_2 = d_euclidean(l_shorter[-1], pe)
|
||||
|
||||
if lehmer_1 == 0 and lehmer_2 == 0:
|
||||
return 0
|
||||
return (lehmer_1 ** 2 + lehmer_2 ** 2) / (lehmer_1 + lehmer_2) # , ps, pe, l_shorter[0], l_shorter[-1]
|
||||
|
||||
def get_point_projection_on_line(self, point, line):
|
||||
"""
|
||||
Get the projection of a point on a line.
|
||||
"""
|
||||
|
||||
# Get the slope of the line using the start and end points
|
||||
line_slope = (line[-1, 1] - line[0, 1]) / (line[-1, 0] - line[0, 0]) if line[-1, 0] != line[0, 0] else np.inf
|
||||
|
||||
# In case the slope is infinite, we can directly get the projection
|
||||
if np.isinf(line_slope):
|
||||
return np.array([line[0, 0], point[1]])
|
||||
|
||||
# Convert the slope to a rotation matrix
|
||||
R = self.slope_to_rotation_matrix(line_slope)
|
||||
|
||||
# Rotate the line and point
|
||||
rot_line = np.matmul(line, R.T)
|
||||
rot_point = np.matmul(point, R.T)
|
||||
|
||||
# Get the projection
|
||||
proj = np.array([rot_point[0], rot_line[0, 1]])
|
||||
|
||||
# Undo the rotation for the projection
|
||||
R_inverse = np.linalg.inv(R)
|
||||
proj = np.matmul(proj, R_inverse.T)
|
||||
|
||||
return proj
|
||||
|
||||
def slope_to_rotation_matrix(self, slope):
|
||||
"""
|
||||
Convert slope to rotation matrix.
|
||||
"""
|
||||
return np.array([[1, slope], [-slope, 1]])
|
||||
|
||||
# video_path = "20250402_gift_test"
|
||||
# video_path = "gift_test"
|
||||
video_path = "/testDataAndLogs/测试视频数据以及日志/各模块测试记录/赠品测试/20250512赠品测试数据"
|
||||
track_list = ['0_tracking_output.data', '1_tracking_output.data']
|
||||
del_staticBox = True #计算当前帧box与前一帧box中心点距离,距离小于50删除当前帧
|
||||
filter_track = False #使用轨迹过滤算法筛选box
|
||||
save_sub = '../data/negtive_dm50'
|
||||
|
||||
traclus = Trajectory()
|
||||
|
||||
|
||||
for event in os.listdir(video_path):
|
||||
# try:
|
||||
event_path = os.path.join(video_path, event)
|
||||
print('event_path', event_path)
|
||||
if len(os.listdir(event_path)) > 0:
|
||||
imgfile_list = get_img_file(event_path)
|
||||
# print('imgfile_list', imgfile_list)
|
||||
for track_data in track_list:
|
||||
track_path = os.path.join(event_path, track_data)
|
||||
boxes, feat = extract_data_realtime(track_path)
|
||||
camera_id = track_data.split('_')[0]
|
||||
imgfile = [x for x in imgfile_list if x.split('_')[0] == camera_id][0]
|
||||
if len(boxes) > 0:
|
||||
if del_staticBox: ##根据距离删除box
|
||||
boxes_ = compute_box_dist(boxes)
|
||||
elif filter_track:
|
||||
boxes_ = traclus.get_distance_optimized_bboxes(boxes)
|
||||
else:
|
||||
boxes_ = boxes
|
||||
# print('************box', boxes_)
|
||||
for i, box in enumerate(boxes_):
|
||||
|
||||
if box[0] == box[1] == box[2] == box[3]:
|
||||
break
|
||||
xyxy = box[:4]
|
||||
# print('0xyxy', xyxy)
|
||||
frame_id = int(box[7])
|
||||
imgpath = os.path.join(event_path, imgfile, f"{imgfile}_{frame_id}.jpg")
|
||||
# print('imgpath', imgpath)
|
||||
subimg = crop_box(imgpath, xyxy)
|
||||
if len(subimg) > 0:
|
||||
save_path = os.path.join(event_path, save_sub)
|
||||
if not os.path.exists(save_path):
|
||||
os.makedirs(save_path)
|
||||
save_subimg = os.path.join(save_path, f"{imgfile}_{frame_id}.jpg")
|
||||
cv2.imwrite(save_subimg, subimg)
|
||||
print(f'save imgs:{save_subimg}')
|
||||
break
|
||||
break
|
||||
# except Exception as e:
|
||||
# with open('error_tracluster_event.txt', 'a') as f:
|
||||
# f.write(f"{event} {e}\n")
|
||||
|
||||
|
||||
|
||||
# # '''将subimgs文件夹单独复制出来'''
|
||||
# file_name = 'sub_imgs_tracluster'
|
||||
# copy_subimgs(video_path, file_name)
|
107
pipline_test/trace_test.py
Normal file
107
pipline_test/trace_test.py
Normal file
@ -0,0 +1,107 @@
|
||||
import os
|
||||
import random # 新增:导入 random 模块用于随机采样
|
||||
from display_result import show_to_pr as sp
|
||||
import numpy as np
|
||||
|
||||
|
||||
def extract_process_data_from_subfolders(root_path, shuffle=False):
|
||||
"""
|
||||
从指定路径下的每个子文件夹中提取 process.data 文件的内容,并与子文件夹名称建立对应关系。
|
||||
如果 shuffle 为 True,则随机从 root_path 中选择 65 个子文件夹。
|
||||
"""
|
||||
# 存储子文件夹名称与 process.data 文件内容的对应关系
|
||||
result = {}
|
||||
|
||||
# 获取所有子文件夹路径
|
||||
subfolders = [folder for folder in os.listdir(root_path) if os.path.isdir(os.path.join(root_path, folder))]
|
||||
|
||||
# 如果 shuffle 为 True,则随机选择 65 个子文件夹
|
||||
if shuffle and len(subfolders) > 114:
|
||||
subfolders = random.sample(subfolders, 114)
|
||||
|
||||
# 遍历指定路径下的所有子文件夹
|
||||
for folder_name in subfolders:
|
||||
folder_path = os.path.join(root_path, folder_name)
|
||||
if "process.data" in os.listdir(folder_path):
|
||||
file_path = os.path.join(folder_path, "process.data")
|
||||
|
||||
try:
|
||||
# 读取 process.data 文件内容
|
||||
with open(file_path, 'r', encoding='utf-8') as file:
|
||||
full_content = file.read()
|
||||
|
||||
# 提取 "gift identify result:" 后的内容
|
||||
if "gift identify result:" in full_content:
|
||||
# content = full_content.split("gift identify result:", 1)[1].strip()
|
||||
# content = content.replace('\n', '')
|
||||
# content = content.split("select back tracking feats index:", 1)[0].strip()
|
||||
# # 去掉 content 中的换行符
|
||||
# content = content.replace('\n', '')
|
||||
|
||||
content = \
|
||||
full_content.split('gift identify result:', 1)[1].split('select back tracking feats index:')[
|
||||
0].replace('\n', '')
|
||||
|
||||
# 新增:去掉逗号后面的空格
|
||||
content = content.replace(', ', ',')
|
||||
|
||||
# 新增:将 content 以逗号为分隔符分成若干组
|
||||
groups = content.split(',')
|
||||
|
||||
# 修改:以空格为分隔符取每组的前一个字符,并转成列表,同时去掉空字符串并转换为整数
|
||||
result_list = [float(group.split(' ')[0]) for group in groups if group.split(' ')[0]]
|
||||
result_list = sorted(result_list, reverse=True)
|
||||
|
||||
# if shuffle and result_list and result_list[0] > 0.68:
|
||||
# continue
|
||||
|
||||
# 将结果列表存入字典
|
||||
result[os.path.basename(folder_path)] = result_list
|
||||
else:
|
||||
print(f"文件中未找到 'gift identify result:' 标记: {file_path}")
|
||||
continue
|
||||
except Exception as e:
|
||||
print(f"读取文件失败: {file_path}, 错误信息: {e}")
|
||||
if len(result) >= 113:
|
||||
break
|
||||
print(result)
|
||||
return result
|
||||
|
||||
|
||||
def estimate(data_list, type=None):
|
||||
number = round(len(data_list) * 0.2)
|
||||
if number > 0:
|
||||
if type == 0:
|
||||
result = round(sum(data_list[:number]) / number, 2) # 修改:使用 round() 函数保留小数点后两位
|
||||
elif type == 1:
|
||||
result = data_list
|
||||
return result
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
def deal_with_process_data(gift_data_dict, comm_data_dict):
|
||||
targets = []
|
||||
outputs = []
|
||||
type = 1 # type 0:qu
|
||||
for gift, comm, gift_evnt_name, comm_evnt_name in zip(gift_data_dict.values(), comm_data_dict.values(),
|
||||
gift_data_dict.keys(), comm_data_dict.keys()):
|
||||
outputs += [estimate(gift, type), estimate(comm, type)]
|
||||
targets += [1, 0]
|
||||
# print(outputs, targets)
|
||||
if type == 0:
|
||||
sp(np.array(targets), np.array(outputs), type)
|
||||
elif type == 1:
|
||||
sp(np.array(targets), outputs, type)
|
||||
|
||||
|
||||
# 调用函数并打印结果
|
||||
if __name__ == "__main__":
|
||||
# 指定根路径
|
||||
gift_path = "/testDataAndLogs/测试视频数据以及日志/全实时_YoloV10s/赠品测试/正样本"
|
||||
comm_path = "/testDataAndLogs/测试视频数据以及日志/全实时_YoloV10s/赠品测试/负样本"
|
||||
|
||||
# 提取 process.data 文件内容
|
||||
gift_data_dict = extract_process_data_from_subfolders(gift_path, shuffle=False) # 修改:新增 shuffle 参数
|
||||
comm_data_dict = extract_process_data_from_subfolders(comm_path, shuffle=True) # 修改:新增 shuffle 参数
|
||||
deal_with_process_data(gift_data_dict, comm_data_dict)
|
Reference in New Issue
Block a user