# -*- coding: utf-8 -*- """ Created on Mon Dec 16 18:56:18 2024 @author: ym """ import os import cv2 import json import numpy as np import matplotlib.pyplot as plt from pathlib import Path from matplotlib import rcParams from matplotlib.font_manager import FontProperties from scipy.spatial.distance import cdist from utils.event import ShoppingEvent, save_data from utils.calsimi import calsimi_vs_stdfeat_new, get_topk_percent, cluster from utils.tools import get_evtList import pickle rcParams['font.sans-serif'] = ['SimHei'] # 用黑体显示中文 rcParams['axes.unicode_minus'] = False # 正确显示负号 '''*********** USearch ***********''' def read_usearch(): stdFeaturePath = r"D:\contrast\stdlib\v11_test.json" stdBarcode = [] stdlib = {} with open(stdFeaturePath, 'r', encoding='utf-8') as f: data = json.load(f) for dic in data['total']: barcode = dic['key'] feature = np.array(dic['value']) stdBarcode.append(barcode) stdlib[barcode] = feature return stdlib def get_eventlist_errortxt(evtpaths): ''' 读取一次测试中的错误事件 ''' text1 = "one_2_Small_n_Error.txt" text2 = "one_2_Big_N_Error.txt" events = [] text = (text1, text2) for txt in text: txtfile = os.path.join(evtpaths, txt) with open(txtfile, "r") as f: lines = f.readlines() for i, line in enumerate(lines): line = line.strip() if line: fpath=os.path.join(evtpaths, line) events.append(fpath) events = list(set(events)) return events def save_eventdata(): evtpaths = r"/home/wqg/dataset/test_dataset/performence_dataset/" events = get_eventlist_errortxt(evtpaths) '''定义当前事件存储地址及生成相应文件件''' resultPath = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\result\single_event" for evtpath in events: event = ShoppingEvent(evtpath) save_data(event, resultPath) print(event.evtname) # def get_topk_percent(data, k): # """ # 获取数据中最大的 k% 的元素 # """ # # 将数据转换为 NumPy 数组 # if isinstance(data, list): # data = np.array(data) # percentile = np.percentile(data, 100-k) # top_k_percent = data[data >= percentile] # return top_k_percent # def cluster(data, thresh=0.15): # # data = np.array([0.1, 0.13, 0.7, 0.2, 0.8, 0.52, 0.3, 0.7, 0.85, 0.58]) # # data = np.array([0.1, 0.13, 0.2, 0.3]) # # data = np.array([0.1]) # if isinstance(data, list): # data = np.array(data) # data1 = np.sort(data) # cluter, Cluters, = [data1[0]], [] # for i in range(1, len(data1)): # if data1[i] - data1[i-1]< thresh: # cluter.append(data1[i]) # else: # Cluters.append(cluter) # cluter = [data1[i]] # Cluters.append(cluter) # clt_center = [] # for clt in Cluters: # ## 是否应该在此处限制一个聚类中的最小轨迹样本数,应该将该因素放在轨迹分析中 # # if len(clt)>=3: # # clt_center.append(np.mean(clt)) # clt_center.append(np.mean(clt)) # # print(clt_center) # return clt_center # def calsimi_vs_stdfeat_new(event, stdfeat): # '''事件与标准库的对比策略 # 该比对策略是否可以拓展到事件与事件的比对? # ''' # def calsiml(feat1, feat2, topkp=75, cluth=0.15): # '''轨迹样本和标准特征集样本相似度的选择策略''' # matrix = 1 - cdist(feat1, feat2, 'cosine') # simi_max = [] # for i in range(len(matrix)): # sim = np.mean(get_topk_percent(matrix[i, :], topkp)) # simi_max.append(sim) # cltc_max = cluster(simi_max, cluth) # Simi = max(cltc_max) # ## cltc_max为空属于编程考虑不周,应予以排查解决 # # if len(cltc_max): # # Simi = max(cltc_max) # # else: # # Simi = 0 #不应该走到该处 # return Simi # front_boxes = np.empty((0, 9), dtype=np.float64) ##和类doTracks兼容 # front_feats = np.empty((0, 256), dtype=np.float64) ##和类doTracks兼容 # for i in range(len(event.front_boxes)): # front_boxes = np.concatenate((front_boxes, event.front_boxes[i]), axis=0) # front_feats = np.concatenate((front_feats, event.front_feats[i]), axis=0) # back_boxes = np.empty((0, 9), dtype=np.float64) ##和类doTracks兼容 # back_feats = np.empty((0, 256), dtype=np.float64) ##和类doTracks兼容 # for i in range(len(event.back_boxes)): # back_boxes = np.concatenate((back_boxes, event.back_boxes[i]), axis=0) # back_feats = np.concatenate((back_feats, event.back_feats[i]), axis=0) # if len(front_feats): # front_simi = calsiml(front_feats, stdfeat) # if len(back_feats): # back_simi = calsiml(back_feats, stdfeat) # '''前后摄相似度融合策略''' # if len(front_feats) and len(back_feats): # diff_simi = abs(front_simi - back_simi) # if diff_simi>0.15: # Similar = max([front_simi, back_simi]) # else: # Similar = (front_simi+back_simi)/2 # elif len(front_feats) and len(back_feats)==0: # Similar = front_simi # elif len(front_feats)==0 and len(back_feats): # Similar = back_simi # else: # Similar = None # 在event.front_feats和event.back_feats同时为空时 # return Similar def simi_matrix(): evtpaths = r"/home/wqg/dataset/pipeline/contrast/single_event_V10/evtobjs/" stdfeatPath = r"/home/wqg/dataset/test_dataset/total_barcode/features_json/v11_barcode_0304/" resultPath = r"/home/wqg/dataset/performence_dataset/result/" evt_paths, bcdSet = get_evtList(evtpaths) ## read std features stdDict={} evtDict = {} for barcode in bcdSet: stdpath = os.path.join(stdfeatPath, f"{barcode}.json") if not os.path.isfile(stdpath): continue with open(stdpath, 'r', encoding='utf-8') as f: stddata = json.load(f) feat = np.array(stddata["value"]) stdDict[barcode] = feat for evtpath in evt_paths: barcode = Path(evtpath).stem.split("_")[-1] if barcode not in stdDict.keys(): continue # try: # with open(evtpath, 'rb') as f: # evtdata = pickle.load(f) # except Exception as e: # print(evtname) with open(evtpath, 'rb') as f: event = pickle.load(f) stdfeat = stdDict[barcode] Similar = calsimi_vs_stdfeat_new(event, stdfeat) # 构造 boxes 子图存储路径 subimgpath = os.path.join(resultPath, f"{event.evtname}", "subimg") if not os.path.exists(subimgpath): os.makedirs(subimgpath) histpath = os.path.join(resultPath, "simi_hist") if not os.path.exists(histpath): os.makedirs(histpath) mean_values, max_values = [], [] cameras = ('front', 'back') fig, ax = plt.subplots(2, 3, figsize=(16, 9), dpi=100) kpercent = 25 for camera in cameras: boxes = np.empty((0, 9), dtype=np.float64) ##和类doTracks兼容 evtfeat = np.empty((0, 256), dtype=np.float64) ##和类doTracks兼容 if camera == 'front': for i in range(len(event.front_boxes)): boxes = np.concatenate((boxes, event.front_boxes[i]), axis=0) evtfeat = np.concatenate((evtfeat, event.front_feats[i]), axis=0) imgpaths = event.front_imgpaths else: for i in range(len(event.back_boxes)): boxes = np.concatenate((boxes, event.back_boxes[i]), axis=0) evtfeat = np.concatenate((evtfeat, event.back_feats[i]), axis=0) imgpaths = event.back_imgpaths assert len(boxes)==len(evtfeat), f"Please check the Event: {event.evtname}" if len(boxes)==0: continue print(event.evtname) matrix = 1 - cdist(evtfeat, stdfeat, 'cosine') simi_1d = matrix.flatten() simi_mean = np.mean(matrix, axis=1) # simi_max = np.max(matrix, axis=1) '''以相似度矩阵每一行最大的 k% 的相似度做均值计算''' simi_max = [] for i in range(len(matrix)): sim = np.mean(get_topk_percent(matrix[i, :], kpercent)) simi_max.append(sim) mean_values.append(np.mean(matrix)) max_values.append(np.mean(simi_max)) diff_max_mean = np.mean(simi_max) - np.mean(matrix) '''相似度统计特性图示''' k =0 if camera == 'front': k = 1 '''********************* 相似度全体数据 *********************''' ax[k, 0].hist(simi_1d, bins=60, range=(-0.2, 1), edgecolor='black') ax[k, 0].set_xlim([-0.2, 1]) ax[k, 0].set_title(camera) _, y_max = ax[k, 0].get_ylim() # 获取y轴范围 '''相似度变动范围''' ax[k, 0].text(-0.1, 0.15*y_max, f"rng:{max(simi_1d)-min(simi_1d):.3f}", fontsize=18, color='b') '''********************* 均值********************************''' ax[k, 1].hist(simi_mean, bins=24, range=(-0.2, 1), edgecolor='black') ax[k, 1].set_xlim([-0.2, 1]) ax[k, 1].set_title("mean") _, y_max = ax[k, 1].get_ylim() # 获取y轴范围 '''相似度变动范围''' ax[k, 1].text(-0.1, 0.15*y_max, f"rng:{max(simi_mean)-min(simi_mean):.3f}", fontsize=18, color='b') '''********************* 最大值 ******************************''' ax[k, 2].hist(simi_max, bins=24, range=(-0.2, 1), edgecolor='black') ax[k, 2].set_xlim([-0.2, 1]) ax[k, 2].set_title("max") _, y_max = ax[k, 2].get_ylim() # 获取y轴范围 '''相似度变动范围''' ax[k, 2].text(-0.1, 0.15*y_max, f"rng:{max(simi_max)-min(simi_max):.3f}", fontsize=18, color='b') '''绘制聚类中心''' cltc_mean = cluster(simi_mean) for value in cltc_mean: ax[k, 1].axvline(x=value, color='m', linestyle='--', linewidth=3) cltc_max = cluster(simi_max) for value in cltc_max: ax[k, 2].axvline(x=value, color='m', linestyle='--', linewidth=3) '''绘制相似度均值与最大值均值''' ax[k, 1].axvline(x=np.mean(matrix), color='r', linestyle='-', linewidth=3) ax[k, 2].axvline(x=np.mean(simi_max), color='g', linestyle='-', linewidth=3) '''绘制相似度最大值均值 - 均值''' _, y_max = ax[k, 2].get_ylim() # 获取y轴范围 ax[k, 2].text(-0.1, 0.05*y_max, f"g-r={diff_max_mean:.3f}", fontsize=18, color='m') plt.show() # for i, box in enumerate(boxes): # x1, y1, x2, y2, tid, score, cls, fid, bid = box # imgpath = imgpaths[int(fid-1)] # image = cv2.imread(imgpath) # subimg = image[int(y1/2):int(y2/2), int(x1/2):int(x2/2), :] # camerType, timeTamp, _, frameID = os.path.basename(imgpath).split('.')[0].split('_') # subimgName = f"cam{camerType}_{i}_tid{int(tid)}_fid({int(fid)}, {frameID})_{simi_mean[i]:.3f}.png" # imgpairs.append((subimgName, subimg)) # spath = os.path.join(subimgpath, subimgName) # cv2.imwrite(spath, subimg) # oldname = f"cam{camerType}_{i}_tid{int(tid)}_fid({int(fid)}, {frameID}).png" # oldpath = os.path.join(subimgpath, oldname) # if os.path.exists(oldpath): # os.remove(oldpath) if len(mean_values)==2: mean_diff = abs(mean_values[1]-mean_values[0]) ax[0, 1].set_title(f"mean diff: {mean_diff:.3f}") if len(max_values)==2: max_diff = abs(max_values[1]-max_values[0]) ax[0, 2].set_title(f"max diff: {max_diff:.3f}") try: fig.suptitle(f"Similar: {Similar:.3f}", fontsize=16) except Exception as e: print(e) print(f"Similar: {Similar}") pltpath = os.path.join(subimgpath, f"hist_max_{kpercent}%_.png") plt.savefig(pltpath) pltpath1 = os.path.join(histpath, f"{event.evtname}_.png") plt.savefig(pltpath1) plt.close() def main(): simi_matrix() if __name__ == "__main__": main() # cluster()