# -*- coding: utf-8 -*- """ Created on Wed Sep 11 11:57:30 2024 永辉现场试验输出数据的 1:1 性能评估 适用于202410前数据保存版本的,需调用 OneToOneCompare.txt @author: ym """ import os import numpy as np from pathlib import Path import matplotlib.pyplot as plt import sys sys.path.append(r"D:\DetectTracking") from tracking.utils.read_data import read_similar def read_one2one_data(filepath): simiList = [] with open(filepath, 'r', encoding='utf-8') as f: lines = f.readlines() split_flag = False simi_dict = {} for i, line in enumerate(lines): line = line.strip() if not line: if len(simi_dict): simiList.append(simi_dict) simi_dict = {} continue label = line.split(':')[0].strip() value = line.split(':')[1].strip() if label.find("SeqDir") >= 0: simi_dict["SeqDir"] = value if label.isdigit() and len(label) >= 8: simi_max, simi_min = value.strip(',').split('.') simi_dict["barcode"] = label simi_dict["simi_max"] = float(simi_max) / 1000 simi_dict["simi_min"] = float(simi_min) / 1000 if len(simi_dict): simiList.append(simi_dict) return simiList def plot_pr_curve(matrix): simimax, simimean = [], [] need_analysis = [] for simidict in matrix: simimax.append(simidict["simi_max"]) simimean.append(simidict["simi_min"]) if simidict["simi_max"]>0.6: need_analysis.append(simidict) simimax = np.array(simimax) simimean = np.array(simimean) TPFN_max = len(simimax) TPFN_mean = len(simimean) fig, axs = plt.subplots(2, 1) axs[0].hist(simimax, bins=60, edgecolor='black') axs[0].set_xlim([-0.2, 1]) axs[0].set_title(f'Same Barcode, Num: {TPFN_max}') axs[1].hist(simimean, bins=60, edgecolor='black') axs[1].set_xlim([-0.2, 1]) axs[1].set_title(f'Cross Barcode, Num: {TPFN_mean}') # plt.savefig(f'./result/{file}_hist.png') # svg, png, pdf Recall_Neg = [] Thresh = np.linspace(-0.2, 1, 100) for th in Thresh: TN = np.sum(simimax < th) Recall_Neg.append(TN/TPFN_max) fig, ax = plt.subplots() ax.plot(Thresh, Recall_Neg, 'b', label='Recall_Pos: TP/TPFN') ax.set_xlim([0, 1]) ax.set_ylim([0, 1]) ax.grid(True) ax.set_title('Positive recall') ax.set_xlabel(f"Num: {TPFN_max}") ax.legend() plt.show() # plt.savefig(f'./result/{file}_pr.png') # svg, png, pdf print("Have done!") pass def test_compare(): filepaths = [r"\\192.168.1.28\share\测试_202406\0913_扫A放B\0913_1\OneToOneCompare.txt", r"\\192.168.1.28\share\测试_202406\0913_扫A放B\0913_2\OneToOneCompare.txt", r"\\192.168.1.28\share\测试_202406\0914_扫A放B\0914_1\OneToOneCompare.txt", r"\\192.168.1.28\share\测试_202406\0914_扫A放B\0914_2\OneToOneCompare.txt" ] simiList = [] for fp in filepaths: slist = read_one2one_data(fp) simiList.extend(slist) plot_pr_curve(simiList) def one2one_pr(paths): paths = Path(paths) evtpaths = [p for p in paths.iterdir() if p.is_dir() and len(p.name.split('_'))>=2] events, similars = [], [] ##===================================== 扫A放A, 扫A放B场景 one2oneAA, one2oneAB = [], [] ##===================================== 应用于展厅 1:N tp_events, fn_events, fp_events, tn_events = [], [], [], [] tp_simi, fn_simi, tn_simi, fp_simi = [], [], [], [] ##===================================== 应用于1:n tpevents, fnevents, fpevents, tnevents = [], [], [], [] tpsimi, fnsimi, tnsimi, fpsimi = [], [], [], [] for path in evtpaths: barcode = path.stem.split('_')[-1] datapath = path.joinpath('process.data') if not barcode.isdigit() or len(barcode)<10: continue if not datapath.is_file(): continue try: SimiDict = read_similar(datapath) except Exception as e: print(f"{path.stem}, Error: {e}") one2one = SimiDict['one2one'] one2n = SimiDict['one2n'] barcodes, similars = [], [] for dt in one2one: barcodes.append(dt['barcode']) similars.append(dt['similar']) if len(barcodes)!=len(similars) or len(barcodes)==0: continue ##===================================== 扫A放A, 扫A放B场景 simAA = [similars[i] for i in range(len(barcodes)) if barcodes[i]==barcode] simAB = [similars[i] for i in range(len(barcodes)) if barcodes[i]!=barcode] one2oneAA.extend(simAA) one2oneAB.extend(simAB) ##===================================== 以下应用适用于展厅 1:N max_idx = similars.index(max(similars)) max_sim = similars[max_idx] # max_bcd = barcodes[max_idx] for i in range(len(one2one)): bcd, simi = barcodes[i], similars[i] if bcd==barcode and simi==max_sim: tp_simi.append(simi) tp_events.append(path.stem) elif bcd==barcode and simi!=max_sim: fn_simi.append(simi) fn_events.append(path.stem) elif bcd!=barcode and simi!=max_sim: tn_simi.append(simi) tn_events.append(path.stem) else: fp_simi.append(simi) fp_events.append(path.stem) ##===================================== 以下应用适用1:n events, evt_barcodes, evt_similars, evt_types = [], [], [], [] for dt in one2n: events.append(dt["event"]) evt_barcodes.append(dt["barcode"]) evt_similars.append(dt["similar"]) evt_types.append(dt["type"]) if len(events)!=len(evt_barcodes) or len(evt_barcodes)!=len(evt_similars) \ or len(evt_barcodes)!=len(evt_similars) or len(events)==0: continue maxsim = evt_similars[evt_similars.index(max(evt_similars))] for i in range(len(one2n)): bcd, simi = evt_barcodes[i], evt_similars[i] if bcd==barcode and simi==maxsim: tpsimi.append(simi) tpevents.append(path.stem) elif bcd==barcode and simi!=maxsim: fnsimi.append(simi) fnevents.append(path.stem) elif bcd!=barcode and simi!=maxsim: tnsimi.append(simi) tnevents.append(path.stem) else: fpsimi.append(simi) fpevents.append(path.stem) '''命名规则: 1:1 1:n 1:N TP_ TP TPX PPrecise_ PPrecise PPreciseX tpsimi tp_simi ''' ''' 1:1 数据存储''' PPrecise_, PRecall_ = [], [] NPrecise_, NRecall_ = [], [] ''' 1:n 数据存储''' PPrecise, PRecall = [], [] NPrecise, NRecall = [], [] ''' 展厅 1:N 数据存储''' PPreciseX, PRecallX = [], [] NPreciseX, NRecallX = [], [] Thresh = np.linspace(-0.2, 1, 100) for th in Thresh: '''============================= 1:1''' TP_ = sum(np.array(one2oneAA) >= th) FP_ = sum(np.array(one2oneAB) >= th) FN_ = sum(np.array(one2oneAA) < th) TN_ = sum(np.array(one2oneAB) < th) PPrecise_.append(TP_/(TP_+FP_+1e-6)) PRecall_.append(TP_/(TP_+FN_+1e-6)) NPrecise_.append(TN_/(TN_+FN_+1e-6)) NRecall_.append(TN_/(TN_+FP_+1e-6)) '''============================= 1:n''' TP = sum(np.array(tpsimi) >= th) FP = sum(np.array(fpsimi) >= th) FN = sum(np.array(fnsimi) < th) TN = sum(np.array(tnsimi) < th) PPrecise.append(TP/(TP+FP+1e-6)) PRecall.append(TP/(TP+FN+1e-6)) NPrecise.append(TN/(TN+FN+1e-6)) NRecall.append(TN/(TN+FP+1e-6)) '''============================= 1:N 展厅''' TPX = sum(np.array(tp_simi) >= th) FPX = sum(np.array(fp_simi) >= th) FNX = sum(np.array(fn_simi) < th) TNX = sum(np.array(tn_simi) < th) PPreciseX.append(TPX/(TPX+FPX+1e-6)) PRecallX.append(TPX/(TPX+FNX+1e-6)) NPreciseX.append(TNX/(TNX+FNX+1e-6)) NRecallX.append(TNX/(TNX+FPX+1e-6)) '''============================= 1:1 曲线''' fig, ax = plt.subplots() ax.plot(Thresh, PPrecise_, 'r', label='Precise_Pos: TP/TPFP') ax.plot(Thresh, PRecall_, 'b', label='Recall_Pos: TP/TPFN') ax.plot(Thresh, NPrecise_, 'g', label='Precise_Neg: TN/TNFP') ax.plot(Thresh, NRecall_, 'c', label='Recall_Neg: TN/TNFN') ax.set_xlim([0, 1]) ax.set_ylim([0, 1]) ax.grid(True) ax.set_title('Precise & Recall') ax.set_xlabel(f"Num: {len(evtpaths)}") ax.legend() plt.show() '''============================= 1:1 直方图''' fig, axes = plt.subplots(2, 1) axes[0].hist(np.array(one2oneAA), bins=60, edgecolor='black') axes[0].set_xlim([-0.2, 1]) axes[0].set_title('AA') axes[1].hist(np.array(one2oneAB), bins=60, edgecolor='black') axes[1].set_xlim([-0.2, 1]) axes[1].set_title('BB') plt.show() '''============================= 1:n 曲线''' fig, ax = plt.subplots() ax.plot(Thresh, PPrecise, 'r', label='Precise_Pos: TP/TPFP') ax.plot(Thresh, PRecall, 'b', label='Recall_Pos: TP/TPFN') ax.plot(Thresh, NPrecise, 'g', label='Precise_Neg: TN/TNFP') ax.plot(Thresh, NRecall, 'c', label='Recall_Neg: TN/TNFN') ax.set_xlim([0, 1]) ax.set_ylim([0, 1]) ax.grid(True) ax.set_title('Precise & Recall') ax.set_xlabel(f"Num: {len(evtpaths)}") ax.legend() plt.show() '''============================= 1:n 直方图''' fig, axes = plt.subplots(2, 2) axes[0, 0].hist(tpsimi, bins=60, edgecolor='black') axes[0, 0].set_xlim([-0.2, 1]) axes[0, 0].set_title('TP') axes[0, 1].hist(fpsimi, bins=60, edgecolor='black') axes[0, 1].set_xlim([-0.2, 1]) axes[0, 1].set_title('FP') axes[1, 0].hist(tnsimi, bins=60, edgecolor='black') axes[1, 0].set_xlim([-0.2, 1]) axes[1, 0].set_title('TN') axes[1, 1].hist(fnsimi, bins=60, edgecolor='black') axes[1, 1].set_xlim([-0.2, 1]) axes[1, 1].set_title('FN') plt.show() '''============================= 1:N 展厅 曲线''' fig, ax = plt.subplots() ax.plot(Thresh, PPreciseX, 'r', label='Precise_Pos: TP/TPFP') ax.plot(Thresh, PRecallX, 'b', label='Recall_Pos: TP/TPFN') ax.plot(Thresh, NPreciseX, 'g', label='Precise_Neg: TN/TNFP') ax.plot(Thresh, NRecallX, 'c', label='Recall_Neg: TN/TNFN') ax.set_xlim([0, 1]) ax.set_ylim([0, 1]) ax.grid(True) ax.set_title('Precise & Recall') ax.set_xlabel(f"Num: {len(evtpaths)}") ax.legend() plt.show() '''============================= 1:N 展厅 直方图''' fig, axes = plt.subplots(2, 2) axes[0, 0].hist(tp_simi, bins=60, edgecolor='black') axes[0, 0].set_xlim([-0.2, 1]) axes[0, 0].set_title('TP') axes[0, 1].hist(fp_simi, bins=60, edgecolor='black') axes[0, 1].set_xlim([-0.2, 1]) axes[0, 1].set_title('FP') axes[1, 0].hist(tn_simi, bins=60, edgecolor='black') axes[1, 0].set_xlim([-0.2, 1]) axes[1, 0].set_title('TN') axes[1, 1].hist(fn_simi, bins=60, edgecolor='black') axes[1, 1].set_xlim([-0.2, 1]) axes[1, 1].set_title('FN') plt.show() print('Done!') if __name__ == "__main__": evtpaths = r"\\192.168.1.28\share\测试视频数据以及日志\各模块测试记录\展厅测试\1120_展厅模型v801测试\扫A放A" one2one_pr(evtpaths)