# -*- coding: utf-8 -*- """ Created on Sat Jul ** 14:07:25 2024 现场测试精度、召回率分析程序,是 feat_select.py 的简化版, 但支持循环计算,并输出总的pr曲线 @author: ym """ import os.path import shutil import numpy as np import matplotlib.pyplot as plt import cv2 from pathlib import Path import sys sys.path.append(r"D:\DetectTracking") from tracking.utils.plotting import Annotator, colors from tracking.utils.read_data import extract_data, read_deletedBarcode_file, read_tracking_output, read_returnGoods_file from tracking.utils.plotting import draw_tracking_boxes, get_subimgs from contrast.utils.tools import showHist, show_recall_prec, compute_recall_precision # ============================================================================= # def read_tracking_output(filepath): # boxes = [] # feats = [] # with open(filepath, 'r', encoding='utf-8') as file: # for line in file: # line = line.strip() # 去除行尾的换行符和可能的空白字符 # # if not line: # continue # # if line.endswith(','): # line = line[:-1] # # data = np.array([float(x) for x in line.split(",")]) # if data.size == 9: # boxes.append(data) # if data.size == 256: # feats.append(data) # # return np.array(boxes), np.array(feats) # ============================================================================= def read_tracking_imgs(imgspath): ''' input: imgspath:该路径中的图像为Yolo算法的输入图像,640x512 output: imgs_0:后摄图像,根据 frameId 进行了排序 imgs_1:前摄图像,根据 frameId 进行了排序 ''' imgs_0, frmIDs_0, imgs_1, frmIDs_1 = [], [], [], [] for filename in os.listdir(imgspath): file, ext = os.path.splitext(filename) flist = file.split('_') if len(flist)==4 and ext==".jpg": camID, frmID = flist[0], int(flist[-1]) imgpath = os.path.join(imgspath, filename) img = cv2.imread(imgpath) if camID=='0': imgs_0.append(img) frmIDs_0.append(frmID) if camID=='1': imgs_1.append(img) frmIDs_1.append(frmID) if len(frmIDs_0): indice = np.argsort(np.array(frmIDs_0)) imgs_0 = [imgs_0[i] for i in indice ] if len(frmIDs_1): indice = np.argsort(np.array(frmIDs_1)) imgs_1 = [imgs_1[i] for i in indice ] return imgs_0, imgs_1 # ============================================================================= # def draw_tracking_boxes(imgs, tracks): # '''tracks: [x1, y1, x2, y2, track_id, score, cls, frame_index, box_index] # 0 1 2 3 4 5 6 7 8 # 关键:imgs中的次序和 track 中的 fid 对应 # ''' # subimgs = [] # for *xyxy, tid, conf, cls, fid, bid in tracks: # label = f'id:{int(tid)}_{int(cls)}_{conf:.2f}' # # annotator = Annotator(imgs[int(fid-1)].copy()) # if cls==0: # color = colors(int(cls), True) # elif tid>0 and cls!=0: # color = colors(int(tid), True) # else: # color = colors(19, True) # 19为调色板的最后一个元素 # # pt2 = [p/2 for p in xyxy] # annotator.box_label(pt2, label, color=color) # img0 = annotator.result() # # subimgs.append(img0) # # return subimgs # ============================================================================= def get_contrast_paths(pair, basepath): assert(len(pair)==2 or len(pair)==3), "pair: seqdir, delete, barcodes" getout_fold = pair[0] # 取出操作对应的文件夹 relvt_barcode = pair[1] # 取出操作对应放入操作的 Barcode if len(pair)==3: error_match = pair[2] # 取出操作错误匹配的 Barcode else: error_match = '' getoutpath, inputpath, errorpath = '', '', '' day, hms = getout_fold.strip('_').split('-') input_folds, times = [], [] errmatch_folds, errmatch_times = [], [] for pathname in os.listdir(basepath): if pathname.endswith('_'): continue if os.path.isfile(os.path.join(basepath, pathname)):continue infold = pathname.split('_') if len(infold)!=2: continue day1, hms1 = infold[0].split('-') if day1==day and infold[1]==relvt_barcode and int(hms1) simimax for k in idx: if similarity[k] > simimax: idxmax = k simimax = similarity[k] if idxmax>-1: input_event = events[idxmax] else: input_event = '' errpairs.append((seqdir, input_event, events[index])) err_similarity.append(max(similarity)) return corrpairs, errpairs, corr_similarity, err_similarity def test_rpath_deleted(): '''deletedBarcode.txt 格式的 1:n 数据结果文件, returnGoods.txt格式数据文件不需要调用该函数''' del_bfile = r'\\192.168.1.28\share\测试_202406\709\deletedBarcode.txt' basepath = r'\\192.168.1.28\share\测试_202406\709' savepath = r'D:\DetectTracking\contrast\result' saveimgs = True relative_paths = [] '''1. 读取 deletedBarcode 文件 ''' all_list = read_deletedBarcode_file(del_bfile) '''2. 算法性能评估,并输出 (取出,删除, 错误匹配) 对 ''' corrpairs, errpairs, _, _ = one2n_deleted(all_list) '''3. 构造事件组合(取出,放入并删除, 错误匹配) 对应路径 ''' for errpair in errpairs: GetoutPath, InputPath, ErrorPath = get_contrast_paths(errpair, basepath) pairs = (GetoutPath, InputPath, ErrorPath) relative_paths.append(pairs) print(InputPath) '''3. 获取 (取出,放入并删除, 错误匹配) 对应路径,保存相应轨迹图像''' if saveimgs: save_tracking_imgpairs(pairs, savepath) def test_rpath_return(): return_bfile = r'\\192.168.1.28\share\测试_202406\1101\images\returnGoods.txt' basepath = r'\\192.168.1.28\share\测试_202406\1101\images' savepath = r'D:\DetectTracking\contrast\result' all_list = read_returnGoods_file(return_bfile) corrpairs, errpairs, _, _ = one2n_return(all_list) for corrpair in corrpairs: GetoutPath = os.path.join(basepath, corrpair[0]) InputPath = os.path.join(basepath, corrpair[1]) pairs = (GetoutPath, InputPath) save_tracking_imgpairs(pairs, savepath) for errpair in errpairs: GetoutPath = os.path.join(basepath, errpair[0]) InputPath = os.path.join(basepath, errpair[1]) ErrorPath = os.path.join(basepath, errpair[2]) pairs = (GetoutPath, InputPath, ErrorPath) save_tracking_imgpairs(pairs, savepath) def test_one2n(): ''' 1:n 性能测试 兼容 2 种 txt 文件格式:returnGoods.txt, deletedBarcode.txt fpath: 文件路径、或文件夹,其中包含多个 txt 文件 savepath: pr曲线保存路径 ''' # fpath = r'\\192.168.1.28\share\测试_202406\deletedBarcode\other' # deletedBarcode.txt fpath = r'\\192.168.1.28\share\测试_202406\1108_展厅模型v800测试' # returnGoods.txt savepath = r'\\192.168.1.28\share\测试_202406\deletedBarcode\illustration' if os.path.isdir(fpath): filepaths = [os.path.join(fpath, f) for f in os.listdir(fpath) if f.find('.txt')>0 and (f.find('deletedBarcode')>=0 or f.find('returnGoods')>=0)] elif os.path.isfile(fpath): filepaths = [fpath] else: return if not os.path.exists(savepath): os.mkdir(savepath) BarLists, blists = {}, [] for pth in filepaths: file = str(Path(pth).stem) if file.find('deletedBarcode')>=0: blist = read_deletedBarcode_file(pth) if file.find('returnGoods')>=0: blist = read_returnGoods_file(pth) BarLists.update({file: blist}) blists.extend(blist) if len(blists): BarLists.update({"Total": blists}) for file, blist in BarLists.items(): if all(b['filetype']=="deletedBarcode" for b in blist): _, _, correct_similarity, err_similarity = one2n_deleted(blist) if all(b['filetype']=="returnGoods" for b in blists): _, _, correct_similarity, err_similarity = one2n_return(blist) recall, prec, ths = compute_recall_precision(err_similarity, correct_similarity) plt1 = show_recall_prec(recall, prec, ths) # plt1.show() plt1.xlabel(f'threshold, Num: {len(blist)}') plt1.savefig(os.path.join(savepath, file+'_pr.png')) # plt1.close() plt2 = showHist(err_similarity, correct_similarity) plt2.show() plt2.savefig(os.path.join(savepath, file+'_hist.png')) # plt.close() if __name__ == '__main__': # test_one2n() test_rpath_return() # returnGoods.txt # test_rpath_deleted() # deleteBarcode.txt # try: # test_rpath_return() # test_rpath_deleted() # except Exception as e: # print(e)