From c47894ddc003e91a897ddf0d4f3bf48331e66d93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BA=86=E5=88=9A?= Date: Fri, 8 Nov 2024 08:52:56 +0800 Subject: [PATCH] abc --- contrast/__pycache__/genfeats.cpython-39.pyc | Bin 0 -> 4373 bytes contrast/feat_select.py | 2 +- contrast/genfeats.py | 27 +- contrast/one2n_contrast.py | 319 ++++++----- contrast/one2one_contrast.py | 521 +++++------------- time_devide.py | 1 - .../utils/__pycache__/plotting.cpython-39.pyc | Bin 12899 -> 12924 bytes .../__pycache__/read_data.cpython-39.pyc | Bin 10023 -> 10496 bytes tracking/utils/plotting.py | 60 +- tracking/utils/read_data.py | 147 ++--- 说明文档.txt | 129 ++++- 11 files changed, 562 insertions(+), 644 deletions(-) create mode 100644 contrast/__pycache__/genfeats.cpython-39.pyc diff --git a/contrast/__pycache__/genfeats.cpython-39.pyc b/contrast/__pycache__/genfeats.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ca68b228770637386fbf48ea72be2c30d6a4d406 GIT binary patch literal 4373 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 simimax: idxmax = k simimax = similarity[k] - - errpairs.append((seqdir, events[idxmax], events[index])) + if idxmax>-1: + input_event = events[idxmax] + else: + input_event = '' + + errpairs.append((seqdir, input_event, events[index])) err_similarity.append(max(similarity)) - - return errpairs, corrpairs, err_similarity, correct_similarity + return corrpairs, errpairs, corr_similarity, err_similarity -# def contrast_analysis(del_barcode_file, basepath, savepath, saveimgs=False): -def get_relative_paths(del_barcode_file, basepath, savepath, saveimgs=False): - ''' - del_barcode_file: - deletedBarcode.txt 格式的 1:n 数据结果文件 - returnGoods.txt格式数据文件不需要调用该函数,one2n_old() 函数返回的 errpairs - 中元素为三元元组(取出,放入, 错误匹配) - ''' +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_barcode_file) + all_list = read_deletedBarcode_file(del_bfile) '''2. 算法性能评估,并输出 (取出,删除, 错误匹配) 对 ''' - errpairs, corrpairs, _, _ = one2n_old(all_list) + corrpairs, errpairs, _, _ = one2n_deleted(all_list) '''3. 构造事件组合(取出,放入并删除, 错误匹配) 对应路径 ''' for errpair in errpairs: GetoutPath, InputPath, ErrorPath = get_contrast_paths(errpair, basepath) - relative_paths.append((GetoutPath, InputPath, ErrorPath)) + pairs = (GetoutPath, InputPath, ErrorPath) + relative_paths.append(pairs) + + print(InputPath) '''3. 获取 (取出,放入并删除, 错误匹配) 对应路径,保存相应轨迹图像''' - if saveimgs: - save_tracking_imgpairs(errpair, basepath, savepath) + if saveimgs: + save_tracking_imgpairs(pairs, savepath) - return relative_paths - - -def one2n_test(): - fpath = r'\\192.168.1.28\share\测试_202406\deletedBarcode\other' - fpath = r'\\192.168.1.28\share\测试_202406\1030\images' +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, basepath) + 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\returnGoods\all' # returnGoods.txt savepath = r'\\192.168.1.28\share\测试_202406\deletedBarcode\illustration' - if not os.path.exists(savepath): - os.mkdir(savepath) if os.path.isdir(fpath): filepaths = [os.path.join(fpath, f) for f in os.listdir(fpath) @@ -366,37 +446,27 @@ def one2n_test(): filepaths = [fpath] else: return - - - FileFormat = {} + 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: - FileFormat[file] = 'deletedBarcode' blist = read_deletedBarcode_file(pth) - elif file.find('returnGoods')>=0: - FileFormat[file] = 'returnGoods' + if file.find('returnGoods')>=0: blist = read_returnGoods_file(pth) - else: - return - - + BarLists.update({file: blist}) blists.extend(blist) - BarLists.update({file: blist}) - BarLists.update({"Total": blists}) - + if len(blists): BarLists.update({"Total": blists}) for file, blist in BarLists.items(): - if FileFormat[file] == 'deletedBarcode': - _, _, err_similarity, correct_similarity = one2n_old(blist) - elif FileFormat[file] == 'returnGoods': - _, _, err_similarity, correct_similarity = one2n_new(blist) - else: - _, _, err_similarity, correct_similarity = one2n_old(blist) - + 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) @@ -413,51 +483,16 @@ def one2n_test(): - -def test_getreltpath(): - ''' - 适用于:deletedBarcode.txt,不适用于:returnGoods.txt - ''' - - del_barcode_file = r'\\192.168.1.28\share\测试_202406\709\deletedBarcode.txt' - basepath = r'\\192.168.1.28\share\测试_202406\709' - - # del_barcode_file = r'\\192.168.1.28\share\测试_202406\1030\images\returnGoods.txt' - # basepath = r'\\192.168.1.28\share\测试_202406\1030\images' - - savepath = r'D:\contrast\dataset\result' - saveimgs = True - try: - relative_path = get_relative_paths(del_barcode_file, basepath, savepath, saveimgs) - except Exception as e: - print(f'Error Type: {e}') - - if __name__ == '__main__': - - one2n_test() - - # test_getreltpath() - + # 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) - - - - - - - - - - - - - - - - - - - - diff --git a/contrast/one2one_contrast.py b/contrast/one2one_contrast.py index 27f4b20..289d4fd 100644 --- a/contrast/one2one_contrast.py +++ b/contrast/one2one_contrast.py @@ -11,7 +11,7 @@ Created on Fri Aug 30 17:53:03 2024 标准特征提取,并保存至文件夹 stdFeaturePath 中, 也可在运行过程中根据与购物事件集合 barcodes 交集执行 2. 1:1 比对性能测试, - func: contrast_performance_evaluate(resultPath) + func: one2one_eval(resultPath) (1) 求购物事件和标准特征级 Barcode 交集,构造 evtDict、stdDict (2) 构造扫 A 放 A、扫 A 放 B 组合,mergePairs = AA_list + AB_list (3) 循环计算 mergePairs 中元素 "(A, A) 或 (A, B)" 相似度; @@ -32,86 +32,83 @@ import os import sys import random import pickle -import torch +# import torch import time -import json +# import json from pathlib import Path from scipy.spatial.distance import cdist import matplotlib.pyplot as plt import shutil from datetime import datetime -from openpyxl import load_workbook, Workbook +# from openpyxl import load_workbook, Workbook -# Vit版resnet, 和现场特征不一致,需将resnet_vit中文件提出 # from config import config as conf -# from model import resnet18 -# from inference import load_contrast_model -# from inference import featurize -# embedding_size = conf.embedding_size -# img_size = conf.img_size -# device = conf.device -# model = load_contrast_model() +# from model import resnet18 as resnet18 +# from feat_inference import inference_image sys.path.append(r"D:\DetectTracking") -from tracking.utils.read_data import extract_data, read_tracking_output, read_deletedBarcode_file - -from config import config as conf -from model import resnet18 as resnet18 -from feat_inference import inference_image +from tracking.utils.read_data import extract_data, read_tracking_output, read_one2one_simi, read_deletedBarcode_file +from genfeats import genfeatures, stdfeat_infer IMG_FORMAT = ['.bmp', '.jpg', '.jpeg', '.png'] -''' -共6个地址: - (1) stdSamplePath: 用于生成比对标准特征集的原始图像地址 - (2) stdBarcodePath: 比对标准特征集原始图像地址的pickle文件存储,{barcode: [imgpath1, imgpath1, ...]} - (3) stdFeaturePath: 比对标准特征集特征存储地址 - (4) eventFeatPath: 用于1:1比对的购物事件特征存储地址、对应子图存储地址 - (5) subimgPath: 1:1比对购物事件轨迹、标准barcode所对应的 subimgs 存储地址 - (6) resultPath: 1:1比对结果存储地址 -''' - -stdSamplePath = r"\\192.168.1.28\share\已标注数据备份\对比数据\barcode\barcode_500_1979_已清洗" -stdBarcodePath = r"\\192.168.1.28\share\测试_202406\contrast\std_barcodes_2192" -stdFeaturePath = r"\\192.168.1.28\share\测试_202406\contrast\std_features_ft32" -eventFeatPath = r"\\192.168.1.28\share\测试_202406\contrast\events" -subimgPath = r'\\192.168.1.28\share\测试_202406\contrast\subimgs' -resultPath = r"D:\DetectTracking\contrast\result\pickle" -if not os.path.exists(resultPath): - os.makedirs(resultPath) - -##============ load resnet mdoel -model = resnet18().to(conf.device) -# model = nn.DataParallel(model).to(conf.device) -model.load_state_dict(torch.load(conf.test_model, map_location=conf.device)) -model.eval() -print('load model {} '.format(conf.testbackbone)) -def creat_shopping_event(eventPath, subimgPath=False): +def int8_to_ft16(arr_uint8, amin, amax): + arr_ft16 = (arr_uint8 / 255 * (amax-amin) + amin).astype(np.float16) + + return arr_ft16 + +def ft16_to_uint8(arr_ft16): + # pickpath = r"\\192.168.1.28\share\测试_202406\contrast\std_features_ft32vsft16\6902265587712_ft16.pickle" + + # with open(pickpath, 'rb') as f: + # edict = pickle.load(f) + + # arr_ft16 = edict['feats'] + + amin = np.min(arr_ft16) + amax = np.max(arr_ft16) + arr_ft255 = (arr_ft16 - amin) * 255 / (amax-amin) + arr_uint8 = arr_ft255.astype(np.uint8) + + arr_ft16_ = int8_to_ft16(arr_uint8, amin, amax) + + arrDistNorm = np.linalg.norm(arr_ft16_ - arr_ft16) / arr_ft16_.size + + return arr_uint8, arr_ft16_ + +def creat_shopping_event(eventPath): '''构造放入商品事件字典,这些事件需满足条件: 1) 前后摄至少有一条轨迹输出 2) 保存有帧图像,以便裁剪出 boxe 子图 ''' - # filename = "20240723-155413_6904406215720" - - '''filename下为一次购物事件''' - eventName = os.path.basename(eventPath) - '''================ 0. 检查 filename 及 eventPath 正确性和有效性 ================''' - nmlist = eventName.split('_') - # if eventName.find('2024')<0 or len(nmlist)!=2 or len(nmlist[0])!=15 or len(nmlist[1])<11: - # return - if eventName.find('2024')<0 or len(nmlist)!=2 or len(nmlist[1])<11: + '''evtName 为一次购物事件''' + evtName = os.path.basename(eventPath) + evtList = evtName.split('_') + + '''================ 0. 检查 evtName 及 eventPath 正确性和有效性 ================''' + if evtName.find('2024')<0 and len(evtList[0])!=15: return if not os.path.isdir(eventPath): return + + if len(evtList)==1 or (len(evtList)==2 and len(evtList[1])==0): + barcode = '' + else: + barcode = evtList[-1] + + if len(evtList)==3 and evtList[-1]== evtList[-2]: + evtType = 'input' + else: + evtType = 'other' '''================ 1. 构造事件描述字典,暂定 9 items ===============''' event = {} - event['barcode'] = eventName.split('_')[1] - event['type'] = 'input' + event['barcode'] = barcode + event['type'] = evtType event['filepath'] = eventPath event['back_imgpaths'] = [] event['front_imgpaths'] = [] @@ -120,7 +117,8 @@ def creat_shopping_event(eventPath, subimgPath=False): event['back_feats'] = np.empty((0, 256), dtype=np.float64) event['front_feats'] = np.empty((0, 256), dtype=np.float64) event['feats_compose'] = np.empty((0, 256), dtype=np.float64) - # event['feats_select'] = np.empty((0, 256), dtype=np.float64) + event['one2one_simi'] = None + event['feats_select'] = np.empty((0, 256), dtype=np.float64) '''================= 2. 读取 data 文件 =============================''' @@ -144,8 +142,12 @@ def creat_shopping_event(eventPath, subimgPath=False): elif CamerType == '1': event['front_boxes'] = tracking_output_boxes event['front_feats'] = tracking_output_feats - - + + if dataname.find("process.data")==0: + simiDict = read_one2one_simi(datapath) + event['one2one_simi'] = simiDict + + if len(event['back_boxes'])==0 or len(event['front_boxes'])==0: return None @@ -165,16 +167,8 @@ def creat_shopping_event(eventPath, subimgPath=False): if len(ft_feats): event['feats_select'] = ft_feats - # pickpath = os.path.join(savePath, f"{filename}.pickle") - # with open(pickpath, 'wb') as f: - # pickle.dump(event, f) - # print(f"Event: {filename}") - - # if subimgPath==False: - # eventList.append(event) - # continue - '''================ 2. 读取图像文件地址,并按照帧ID排序 =============''' + '''================ 3. 读取图像文件地址,并按照帧ID排序 =============''' frontImgs, frontFid = [], [] backImgs, backFid = [], [] for imgname in os.listdir(eventPath): @@ -194,11 +188,11 @@ def creat_shopping_event(eventPath, subimgPath=False): frontIdx = np.argsort(np.array(frontFid)) backIdx = np.argsort(np.array(backFid)) - '''2.1 生成依据帧 ID 排序的前后摄图像地址列表''' + '''3.1 生成依据帧 ID 排序的前后摄图像地址列表''' frontImgs = [frontImgs[i] for i in frontIdx] backImgs = [backImgs[i] for i in backIdx] - '''2.2 将前、后摄图像路径添加至事件字典''' + '''3.2 将前、后摄图像路径添加至事件字典''' bfid = event['back_boxes'][:, 7].astype(np.int64) @@ -209,101 +203,16 @@ def creat_shopping_event(eventPath, subimgPath=False): event['front_imgpaths'] = [frontImgs[i-1] for i in ffid] - '''================ 3. 判断当前事件有效性,并添加至事件列表 ==========''' + '''================ 4. 判断当前事件有效性,并添加至事件列表 ==========''' condt1 = len(event['back_imgpaths'])==0 or len(event['front_imgpaths'])==0 condt2 = len(event['front_feats'])==0 and len(event['back_feats'])==0 if condt1 or condt2: - print(f"Event: {eventName}, Error, condt1: {condt1}, condt2: {condt2}") + print(f"Event: {evtName}, Error, condt1: {condt1}, condt2: {condt2}") return None - - - - - '''构造放入商品事件列表,暂不处理''' - # delepath = os.path.join(basePath, 'deletedBarcode.txt') - # bcdList = read_deletedBarcode_file(delepath) - # for slist in bcdList: - # getoutFold = slist['SeqDir'].strip() - # getoutPath = os.path.join(basePath, getoutFold) - - # '''取出事件文件夹不存在,跳出循环''' - # if not os.path.exists(getoutPath) and not os.path.isdir(getoutPath): - # continue - - # ''' 生成取出事件字典 ''' - # event = {} - # event['barcode'] = slist['Deleted'].strip() - # event['type'] = 'getout' - # event['basePath'] = getoutPath return event -# def get_std_barcodeDict(bcdpath, savepath): -# ''' -# inputs: -# bcdpath: 已清洗的barcode样本图像,如果barcode下有'base'文件夹,只选用该文件夹下图像 -# (default = r'\\192.168.1.28\share\已标注数据备份\对比数据\barcode\barcode_1771') -# 功能: -# 生成并保存只有一个key值的字典 {barcode: [imgpath1, imgpath1, ...]}, -# savepath: 字典存储地址,文件名格式:barcode.pickle -# ''' - -# # savepath = r'\\192.168.1.28\share\测试_202406\contrast\std_barcodes' - -# '''读取数据集中 barcode 列表''' -# stdBarcodeList = [] -# for filename in os.listdir(bcdpath): -# filepath = os.path.join(bcdpath, filename) -# # if not os.path.isdir(filepath) or not filename.isdigit() or len(filename)<8: -# # continue -# stdBarcodeList.append(filename) - -# bcdPaths = [(barcode, os.path.join(bcdpath, barcode)) for barcode in stdBarcodeList] - -# '''遍历数据集,针对每一个barcode,生成并保存字典{barcode: [imgpath1, imgpath1, ...]}''' -# k = 0 -# errbarcodes = [] -# for barcode, bpath in bcdPaths: -# pickpath = os.path.join(savepath, f"{barcode}.pickle") -# if os.path.isfile(pickpath): -# continue - -# stdBarcodeDict = {} -# stdBarcodeDict[barcode] = [] -# for root, dirs, files in os.walk(bpath): -# imgpaths = [] -# if "base" in dirs: -# broot = os.path.join(root, "base") -# for imgname in os.listdir(broot): -# imgpath = os.path.join(broot, imgname) -# file, ext = os.path.splitext(imgpath) - -# if ext not in IMG_FORMAT: -# continue -# imgpaths.append(imgpath) - -# stdBarcodeDict[barcode].extend(imgpaths) -# break - -# else: -# for imgname in files: -# imgpath = os.path.join(root, imgname) -# _, ext = os.path.splitext(imgpath) -# if ext not in IMG_FORMAT: continue -# imgpaths.append(imgpath) -# stdBarcodeDict[barcode].extend(imgpaths) - -# pickpath = os.path.join(savepath, f"{barcode}.pickle") -# with open(pickpath, 'wb') as f: -# pickle.dump(stdBarcodeDict, f) -# print(f"Barcode: {barcode}") - -# # k += 1 -# # if k == 10: -# # break -# print(f"Len of errbarcodes: {len(errbarcodes)}") -# return def save_event_subimg(event, savepath): ''' @@ -340,131 +249,20 @@ def save_event_subimg(event, savepath): print(f"Image saved: {os.path.basename(event['filepath'])}") - -def batch_inference(imgpaths, batch): - size = len(imgpaths) - groups = [] - for i in range(0, size, batch): - end = min(batch + i, size) - groups.append(imgpaths[i: end]) - features = [] - for group in groups: - feature = featurize(group, conf.test_transform, model, conf.device) - features.append(feature) - features = np.concatenate(features, axis=0) - return features - -# def stdfeat_infer(imgPath, featPath, bcdSet=None): -# ''' -# inputs: -# imgPath: 该文件夹下的 pickle 文件格式 {barcode: [imgpath1, imgpath1, ...]} -# featPath: imgPath图像对应特征的存储地址 -# 功能: -# 对 imgPath中图像进行特征提取,生成只有一个key值的字典, -# {barcode: features},features.shape=(nsample, 256),并保存至 featPath 中 - -# ''' - -# # imgPath = r"\\192.168.1.28\share\测试_202406\contrast\std_barcodes" -# # featPath = r"\\192.168.1.28\share\测试_202406\contrast\std_features" -# stdBarcodeDict = {} -# stdBarcodeDict_ft16 = {} - - -# '''4处同名: (1)barcode原始图像文件夹; (2)imgPath中的 .pickle 文件名、该pickle文件中字典的key值''' - -# k = 0 -# for filename in os.listdir(imgPath): -# bcd, ext = os.path.splitext(filename) -# pkpath = os.path.join(featPath, f"{bcd}.pickle") - -# if os.path.isfile(pkpath): continue -# if bcdSet is not None and bcd not in bcdSet: -# continue - -# filepath = os.path.join(imgPath, filename) - -# stdbDict = {} -# stdbDict_ft16 = {} -# stdbDict_uint8 = {} - -# t1 = time.time() - -# try: -# with open(filepath, 'rb') as f: -# bpDict = pickle.load(f) -# for barcode, imgpaths in bpDict.items(): -# # feature = batch_inference(imgpaths, 8) #from vit distilled model of LiChen -# feature = inference_image(imgpaths, conf.test_transform, model, conf.device) -# feature /= np.linalg.norm(feature, axis=1)[:, None] - -# # float16 -# feature_ft16 = feature.astype(np.float16) -# feature_ft16 /= np.linalg.norm(feature_ft16, axis=1)[:, None] - -# # uint8, 两种策略,1) 精度损失小, 2) 计算复杂度小 -# # feature_uint8, _ = ft16_to_uint8(feature_ft16) -# feature_uint8 = (feature_ft16*128).astype(np.int8) - -# except Exception as e: -# print(f"Error accured at: {filename}, with Exception is: {e}") - -# '''================ 保存单个barcode特征 ================''' -# ##================== float32 -# stdbDict["barcode"] = barcode -# stdbDict["imgpaths"] = imgpaths -# stdbDict["feats_ft32"] = feature -# stdbDict["feats_ft16"] = feature_ft16 -# stdbDict["feats_uint8"] = feature_uint8 - -# with open(pkpath, 'wb') as f: -# pickle.dump(stdbDict, f) - -# stdBarcodeDict[barcode] = feature -# stdBarcodeDict_ft16[barcode] = feature_ft16 - -# t2 = time.time() -# print(f"Barcode: {barcode}, need time: {t2-t1:.1f} secs") -# # k += 1 -# # if k == 10: -# # break - -# ##================== float32 -# # pickpath = os.path.join(featPath, f"barcode_features_{k}.pickle") -# # with open(pickpath, 'wb') as f: -# # pickle.dump(stdBarcodeDict, f) - -# ##================== float16 -# # pickpath_ft16 = os.path.join(featPath, f"barcode_features_ft16_{k}.pickle") -# # with open(pickpath_ft16, 'wb') as f: -# # pickle.dump(stdBarcodeDict_ft16, f) - -# return - - -def contrast_performance_evaluate(resultPath): +def one2one_eval(resultPath): # stdBarcode = [p.stem for p in Path(stdFeaturePath).iterdir() if p.is_file() and p.suffix=='.pickle'] stdBarcode = [p.stem for p in Path(stdBarcodePath).iterdir() if p.is_file() and p.suffix=='.pickle'] - '''购物事件列表,该列表中的 Barcode 存在于标准的 stdBarcode 内''' - # evtList = [(p.stem, p.stem.split('_')[1]) for p in Path(eventFeatPath).iterdir() - # if p.is_file() - # and p.suffix=='.pickle' - # and len(p.stem.split('_'))==2 - # and p.stem.split('_')[1].isdigit() - # and p.stem.split('_')[1] in stdBarcode - # ] - - evtList = [(p.stem, p.stem.split('_')[1]) for p in Path(eventFeatPath).iterdir() + '''购物事件列表,该列表中的 Barcode 存在于标准的 stdBarcode 内''' + evtList = [(p.stem, p.stem.split('_')[-1]) for p in Path(eventFeatPath).iterdir() if p.is_file() - and str(p).find('240910')>0 and p.suffix=='.pickle' - and len(p.stem.split('_'))==2 - and p.stem.split('_')[1].isdigit() - and p.stem.split('_')[1] in stdBarcode + and (len(p.stem.split('_'))==2 or len(p.stem.split('_'))==3) + and p.stem.split('_')[-1].isdigit() + and p.stem.split('_')[-1] in stdBarcode ] barcodes = set([bcd for _, bcd in evtList]) @@ -612,7 +410,7 @@ def contrast_performance_evaluate(resultPath): f.write(line + '\n') - print("func: contrast_performance_evaluate(), have finished!") + print("func: one2one_eval(), have finished!") @@ -684,44 +482,16 @@ def compute_precise_recall(pickpath): plt.savefig(f'./result/{file}_pr.png') # svg, png, pdf - - -def generate_event_and_stdfeatures(): - '''=========================== 1. 生成标准特征集 ========================''' - '''1.1 提取 stdSamplePath 中样本地址,生成字典{barcode: [imgpath1, imgpath1, ...]} - 并存储为 pickle 文件,barcode.pickle''' - # get_std_barcodeDict(stdSamplePath, stdBarcodePath) - # print("standard imgpath have extracted and saved") - - - '''1.2 特征提取,并保存至文件夹 stdFeaturePath 中,也可在运行过程中根据 barcodes 交集执行''' - # stdfeat_infer(stdBarcodePath, stdFeaturePath, bcdSet=None) - # print("standard features have generated!") - - - '''=========================== 2. 提取并存储事件特征 ========================''' - eventDatePath = [r'\\192.168.1.28\share\测试_202406\0910\images', - # r'\\192.168.1.28\share\测试_202406\0723\0723_1', - # r'\\192.168.1.28\share\测试_202406\0723\0723_2', - # r'\\192.168.1.28\share\测试_202406\0723\0723_3', - # r'\\192.168.1.28\share\测试_202406\0722\0722_01', - # r'\\192.168.1.28\share\测试_202406\0722\0722_02' - # r'\\192.168.1.28\share\测试_202406\0719\719_3', - # r'\\192.168.1.28\share\测试_202406\0716\0716_1', - # r'\\192.168.1.28\share\测试_202406\0716\0716_2', - # r'\\192.168.1.28\share\测试_202406\0716\0716_3', - # r'\\192.168.1.28\share\测试_202406\0712\0712_1', # 无帧图像 - # r'\\192.168.1.28\share\测试_202406\0712\0712_2', # 无帧图像 - ] +def gen_eventdict(eventDatePath, saveimg=True): eventList = [] # k = 0 for datePath in eventDatePath: for eventName in os.listdir(datePath): + pickpath = os.path.join(eventFeatPath, f"{eventName}.pickle") if os.path.isfile(pickpath): continue - eventPath = os.path.join(datePath, eventName) eventDict = creat_shopping_event(eventPath) @@ -736,52 +506,61 @@ def generate_event_and_stdfeatures(): # break ## 保存轨迹中 boxes 子图 + if not saveimg: + return for event in eventList: basename = os.path.basename(event['filepath']) savepath = os.path.join(subimgPath, basename) if not os.path.exists(savepath): os.makedirs(savepath) save_event_subimg(event, savepath) + + + + + +def test_one2one(): + eventDatePath = [r'\\192.168.1.28\share\测试_202406\1101\images', + # r'\\192.168.1.28\share\测试_202406\0910\images', + # r'\\192.168.1.28\share\测试_202406\0723\0723_1', + # r'\\192.168.1.28\share\测试_202406\0723\0723_2', + # r'\\192.168.1.28\share\测试_202406\0723\0723_3', + # r'\\192.168.1.28\share\测试_202406\0722\0722_01', + # r'\\192.168.1.28\share\测试_202406\0722\0722_02' + # r'\\192.168.1.28\share\测试_202406\0719\719_3', + # r'\\192.168.1.28\share\测试_202406\0716\0716_1', + # r'\\192.168.1.28\share\测试_202406\0716\0716_2', + # r'\\192.168.1.28\share\测试_202406\0716\0716_3', + # r'\\192.168.1.28\share\测试_202406\0712\0712_1', # 无帧图像 + # r'\\192.168.1.28\share\测试_202406\0712\0712_2', # 无帧图像 + ] + bcdList = [] + for evtpath in eventDatePath: + for evtname in os.listdir(evtpath): + evt = evtname.split('_') + if len(evt)>=2 and evt[-1].isdigit() and len(evt[-1])>=10: + bcdList.append(evt[-1]) + + bcdSet = set(bcdList) - print("eventList have generated and features have saved!") - -def int8_to_ft16(arr_uint8, amin, amax): - arr_ft16 = (arr_uint8 / 255 * (amax-amin) + amin).astype(np.float16) - - return arr_ft16 - -def ft16_to_uint8(arr_ft16): - # pickpath = r"\\192.168.1.28\share\测试_202406\contrast\std_features_ft32vsft16\6902265587712_ft16.pickle" - - # with open(pickpath, 'rb') as f: - # edict = pickle.load(f) - # arr_ft16 = edict['feats'] - - amin = np.min(arr_ft16) - amax = np.max(arr_ft16) - arr_ft255 = (arr_ft16 - amin) * 255 / (amax-amin) - arr_uint8 = arr_ft255.astype(np.uint8) - arr_ft16_ = int8_to_ft16(arr_uint8, amin, amax) + + '''==== 1. 生成标准特征集, 只需运行一次 ===============''' + genfeatures(stdSamplePath, stdBarcodePath, stdFeaturePath, bcdSet) + print("stdFeats have generated and saved!") - arrDistNorm = np.linalg.norm(arr_ft16_ - arr_ft16) / arr_ft16_.size - - - return arr_uint8, arr_ft16_ + '''==== 2. 生成事件字典, 只需运行一次 ===============''' + + gen_eventdict(eventDatePath) + print("eventList have generated and saved!") - - - - -def main(): - # generate_event_and_stdfeatures() - - contrast_performance_evaluate(resultPath) + '''==== 3. 1:1性能评估 ===============''' + one2one_eval(resultPath) for filename in os.listdir(resultPath): if filename.find('.pickle') < 0: continue if filename.find('0911') < 0: continue @@ -789,63 +568,29 @@ def main(): compute_precise_recall(pickpath) -# def main_std(): -# std_sample_path = r"\\192.168.1.28\share\已标注数据备份\对比数据\barcode\barcode_500_2192_已清洗" -# std_barcode_path = r"\\192.168.1.28\share\测试_202406\contrast\std_barcodes_2192" -# std_feature_path = r"\\192.168.1.28\share\测试_202406\contrast\std_features_2192_ft32vsft16" - - -# get_std_barcodeDict(std_sample_path, std_barcode_path) -# stdfeat_infer(std_barcode_path, std_feature_path, bcdSet=None) - -# # fileList = [] -# # for filename in os.listdir(std_barcode_path): -# # filepath = os.path.join(std_barcode_path, filename) -# # with open(filepath, 'rb') as f: -# # bpDict = pickle.load(f) - -# # for v in bpDict.values(): -# # fileList.append(len(v)) -# # print("done") if __name__ == '__main__': - main() - # main_std() + ''' + 共6个地址: + (1) stdSamplePath: 用于生成比对标准特征集的原始图像地址 + (2) stdBarcodePath: 比对标准特征集原始图像地址的pickle文件存储,{barcode: [imgpath1, imgpath1, ...]} + (3) stdFeaturePath: 比对标准特征集特征存储地址 + (4) eventFeatPath: 用于1:1比对的购物事件特征存储地址、对应子图存储地址 + (5) subimgPath: 1:1比对购物事件轨迹、标准barcode所对应的 subimgs 存储地址 + (6) resultPath: 1:1比对结果存储地址 + ''' + + stdSamplePath = r"\\192.168.1.28\share\已标注数据备份\对比数据\barcode\barcode_500_1979_已清洗" + stdBarcodePath = r"\\192.168.1.28\share\测试_202406\contrast\std_barcodes_2192" + stdFeaturePath = r"\\192.168.1.28\share\测试_202406\contrast\std_features_ft32" + eventFeatPath = r"\\192.168.1.28\share\测试_202406\contrast\events" + subimgPath = r'\\192.168.1.28\share\测试_202406\contrast\subimgs' + resultPath = r"D:\DetectTracking\contrast\result\pickle" + if not os.path.exists(resultPath): + os.makedirs(resultPath) + + test_one2one() - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/time_devide.py b/time_devide.py index e843a7e..28d4d65 100644 --- a/time_devide.py +++ b/time_devide.py @@ -17,7 +17,6 @@ import copy import matplotlib.pyplot as plt from imgs_inference import run_yolo - from event_time_specify import devide_motion_state#, state_measure from tracking.utils.read_data import read_seneor diff --git a/tracking/utils/__pycache__/plotting.cpython-39.pyc b/tracking/utils/__pycache__/plotting.cpython-39.pyc index ab513f6b2d59fb87433800383ff312d5741762b7..a0008c175516836579df5c2b03fa615c6aa0397a 100644 GIT binary patch delta 3581 zcmaJ@U2Ggz72esIo&B*LJAcF}actu_WSk%GpOf7XlGxrXL`kd&LM69NR^y%7-HCT+ zHfLtjby#;14lPnCJlqGGR-jZAAy=XjxKFeM9;ko{AtXScD~O^Z1^EF~${SP)=iG6; zi-lNezkBX?&OP_ubI-YV{$hM&^yz(lu>k(Qu;WPigCF!wC~dCh^QlZKLv1#fJwfe> zcp^{jOfr$<>TEujOeMIQ&g8T4X|86Iv$F}bOXYGind4kdOlMQ6G*{#CTzY1PtI64H zb{hS~505}8FoiF)=aPB7%;RsqHC3Fx!9`G zPyWmQdhYr=9;=*zGwh>nXX9e&IaI8N5VW1}B#qw!SBUe0-RK`=5BftV&k*;2LEHYn z^^aYUnRCCBzYU(_+K4vtuVgugkhkH;+6vN4Eu(ZskrP^@tEifOwJaMg3Fmg|Z0 z1nvedUx)VMwzxVv3EvjoQCIGhS{AnYwpf( z%I(hbsBGr6AXg3Zrd2dy68mNR2LcbAvoMb>CWLHQHEa}YTyTjSgzMM?C;yE=fr zB-X^0qElajgizE?s5Lwjo}r#xtT%YbZq({aQ}9({g1FxX399GsI9#eax|hO@Hf;As z!!&Q1JY2*PfXQ`@-P<#MNhkYg37ndkQ|s|dBvjMgMHdX=&8ij3G?!kjS9IPBrf1oD zL0Iq}(G-eK6(h{zgS!s$FxnG~XWw}ln*GYV8?Z<=vRMg8P&$IiJ zgY4Hs`;Us;IE&n>UwK?=ZuM~hwcn*t<81H#qkB4M@B)z{tP<28du(rd1Tjc-1&Bf< zXYUAS1UAB)wxe?>@FLM7NxnvsA2t)CZ-R~|QX-O~B~A*OC~>uDK@n4n?hm-tCM*)K zR4v;CllpfMuuiEaxUyLHT;H(@x?we39zm)=)?BesM8u52__~F<DMi14 zLK6?d0fUE^HU!KbyTpTd7!wMPNpQj>4-uX4o8;EGzQNueep))o_KcJxOSHfcjI!rP z_HV7%rM0(4(m_A>C9;!1MDQ5xMvCE;DY_PRMdHH^lIUDE;=2t<$HQe4%j%ZtNBc*l zr)hb}tyeAFv}ZOwxJL8>0mT-+NFa`*eT&2vg0@Wr65b}_X9QnD;40n)6->_Pg3~Ox z-V&b3ZBovVGDOjJxm18v;#LU0Lhxk*ksbm>j*!oH@$b^J5(q}50cn@S9*(_v*26x? z1azYQ!W5Lak^}u&pgmzY=$L)o7RPtk?+)A?rsD6)vk~fc88U19X!|0PdANj#FJqM~ zY6KK=oPZKPkBaXQ_Y}evO`e;Blcbe}5&T4$^g^CYK11+Xg7XC88G4?iR|wu9pp)=} zNjv*Eyhr`csye~Bz~Tpor3-794?Ya`WXXzh0#34N?L=Egk;^s9_KQK>X0a#rYQsDS z;J`+`fJtef#l-YHYSrQex1!havd0>;oI+hUh)ry;N?EsTE+Z>;g>_|?JoqV16#}bV z@ix~P!S4ZD%**VNHmSZ$;yg=Fyw|3p)WUFq#zerpX@YAS8xI7&6n;gEh|s>ZUc9+Y z4?iesWuQx)M|InF@WsaTQkqN6B_6a4c#AZ0vFgGvP=eieY6 zvNsP8&Gll)49N)I4lK*%z_Q{6TGEOH`&u%!%L;NKPiiSEQZ8`y{xiX4bvf(>TVX@q z8$f-;lUspS#83tUdjoeB)^}vM9c=ZiNUsJA747-6-y!K~Yzv<;ENQG`d<^MkGY;079M>Ya;c7Ah9OsclXU9h0IDwG)?ge3_R{2V`xJeJ6rEcAH2e`c+#J;de2+l9 z6_k!3o*9Fr&HRJEVprQK@(8yew&TKwWb=1|bp#%E8w;3cuKzlO{B6p(Y4|hQ+z%W_ zBiY-?Q+PmQH&SN%#|4i*5Xaq%pQ9G1Pkq#Xu~wO_3rJJC)eKdsh(tjg%(M z;q5;!B+O+ek(Qe5^~8bVH;@u%=YN>Um(O4H?@78HAw-}e@SeI=El~Mcjtya=#nwe6 TM7_RG98J}ALVl3h;bi7NTTE+; delta 3514 zcmaJ@U2Gf25$5rZ#~+C%E%`_OktNrbowH?&Kax$QX<~^qlQ1XVkvxmM zqvwvcWKg98r$JDo4UjF67HLuCp+MB4X=CN3NL;iJL6D*-`cR<2JsAjKKtNj*&0Ar> zo!O%)RR~Ie-_CwBJG(nOvwIKq&-Az!kH-S|d-s#iE1$d{KPGilxme8RvN>v}3)82m zJ)KGysh!QF3#yzi7BbniDo^H$)2SI%p3da+X|&503bVOWs+^vg&Soc7Ih86*&d#cG zCO69iCY8!f;Y71Y@QJ6V z@;R0LMY`V^z{Rfrm>`Rwh`@=vL{vDj{s0>oA`m#iEno)`WQ#*cUjNf3f_T`ymDst7 z;L2TrK&R(~Yd3r4PB=l(U77EdMn5L_ID+m%HkOA(Zw*{RqPGSvDdIDHQ~sFl_Ndul zA5YU`SN#zALk8GCnVvFN}y8r)BiV8!sKC-??v7a$C*10mn(pXW|l#g(&+t`i&EZNPGgp>vvquHOmddt=T$6dm}cj za;*?sl@jE?`k(Jy{m5mtXFy>Ox1CAxrJqE_dI&)ogfrM|g{O)0fn7@svHOY8lL~SF z7nJQ^tbgo+-0c0L>3ohoN}LzI#Lg#&WjX4oxX<-npvVn28pcDCohiQOA#U=zv1D&U&B9y>jc z@EYm2Bp*5Zh&vk(A zMxL;shI#Z$C@kVZ*r2Q7C10TIu_|5=5964GW6~aBMhy|2_M6PsP~2f3j$9GO*zVD4 zM56_UAkJPJJ+QT2wY3jMCxd?O^UGU+AJV4wB6va!uT0*3jyOtuxI#eZ(v9ynAe|Sk z8dz304L{m%lAfmZLQb=8;-+0=(S>tFQ+@K-LYX9f9G!U*bp&M_4Nl7i*FK8$Z-Nn{30q|C9Z&QSrO;vfGPu7GJ>}dib_Aw79dTKA;=OOBCrTvA-F?8 zC*cS47E1eIh58%I=MsO(rdaC8h%mKw>Bxg%-(j+%oPaSlqnz&WauFM*&8&oBipE61xNd-B=-mebUkbmXc|=yo zvLA15!^IDZMistJW1^a6+4y4P>mn^KEiQRMQ-?Q5BbMt9{0t?i5YR-bgya6_7GulD zkINsB{xEy*`0(sQ6m>xlz8Y8-+hSX|Ei6mbz;eh9w58iZA@HL2LU37L4!c4-tc!aB zsE@e8cAy>6rJ=x{z>3KBjE^WnyYIH}c0iZWF78Y1em(rQ^iz2`(T?kpg&@4?O0K}P z@xgs}IU~YdVrZluy&YUmS}|8*Z;THg4Yjwo6YZoP|Gp>$uAOT~SLAmB%LDDuO1K?q z4^)Eh2*~eW``dUV*x?@*{NPXGUT!8X)eX%tM$0v$ym0W~K_%)xadOKt@jb%Y#Dc_E zjjl*f!bjTmLN{s#kfzx*EZu+jM8|Ly*^}q7gbhcHxuBI7N)=OgRJrbRQl(_--cHff z7r~&2Zscf!ITKfQ@|E#7;$2enqxl8mwSkB&J%H~@EfvuAHfsdZkEAXAaDfx^VsjD8CHawfnSp~U;OV$O0ec`t_moUojv80d;#)1RF0QG|KDcUK*oFa6;STH|dPfrRjvwP{o weK*JAoXEG3@^{faeTKWwx!7MEwtJsT6tjN23D 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 delta 4319 zcmZ`7TX0)Pb@%Gtt1DTup4Q8f-%YG0Z5?RqHg!m+HHCyW)7mL%OsT4RuN~R4WbeIp z60<@fPH8)k)?tAubi&wW2Ffr%Umpxp$_M=SgO8RwL#Mz`Kl%X!(_wfN&RNNFoPss? z+&yQ{p561@bA4gzhbIn}!{H!-zn}hfX#U_~LjHuvwSNX6cf;ch(JKd^ZQ4C7v#4!S z-p8^tDMn|~w!W3IQ`>Zse9@iBvfND8))#VHy>`mZZfi4ng%#}lHs$Zx*{wd-yGG#15+$2-rEle>SKj%EQcu3E9i?%Z z_Wg=xUwhk^2f6ZZ`dtUYAjw)pN$VoCWw36A!&1Z*1vw&V!ibzP3U@|3{I9m>krKoC zC$%iu(zi(?D$Fgv+a;nKbQ|_*$(1h~xAeyad4aIRReghAq`=YI0ryO*9X>Lq;apSZ zcC$xun8LR~T~h!*Sk>p`juV!`nF?tnML;B3dV+``yfYKTjQ}U`Z=kI&HG15r@QEH4 znS*nIlopoVgXLP7k7%TkYNQ(()+^F4kgM91NUqUMAO9xHS4f4z2JH#ht~1UOmIsw% zA|rIzNSOcyR+QSCzLmrCWFAEujVvq3-}uLG>uZ}&=Sfy*p?Tm6bx<-WokwO(jFKD3ikJ=javNjzw=!`oWfYNMG zWMG}|di_MEqmeGh0)_q|<-}o;2X1f-C8x+~(7loWa=sRXFsTNz+Q=7p3j zo5Oy#TUr}rks?zSkVtN8dRZc&t1Ld986N0Mh$YRoMd0wmas{CBv}dnQA0jy^Z4pi;h zs4{$U@Cc5Tm5RjxzZJP|L(q-j5P~}qL;!fYQ(3q99f*$uD4L!%SE<^|W%mrf52?zx zI@0)YwE$wG%&}6-3((eo<;sOVg>Q1!+jj(V+T;vy-9_J*6R{UZ`QJrYK;4A23bBZ){Xs>EC`wdOax5mJ@%=a4CrscCK&>)_ ze}h7meMEp8SWr<6MXAb1TX@EkXCdK$3+sg06r*B3Rd46s$SIe{Zk2D?t zT&b*-ZGkSNg#f%RbBWJS4lWQBYFNxN#hHuLoRD~@}z?E^2s?J|RG zvmKtqHOd{zF=+Xg4{n#gPh{vZ`C;OI6O(`+m!C}@YyJd=&OHDKje~uIG^%xLQLt@D zvy|1NG!9meg59IEn|1@$f?0gP7w{lw9M;}S`8kj>i-+F%i^9Ny=U#Z6$F=MHqdj-H zA>%!hbWNV>`OmRs5fP?xP-M$uNvObqECEUnIH;SYl!Gp?bi-Jg5(b|V0Z0P4lECbK z9PO@=KTZucGp+SFzcSTv=-1_l)qz!9<)P zm_vYBa9v=$Cm+k)-JHjXGXOlpUbAbir@QBuZC*hNy|EQC7(DB~Lx*cBc=#ADSwOG| z;N(B(k)7PFB2h)mZWgPExg94|>S8JvqkIVoH9{UD{1^^h1j`8O2v!hq1P%Z%sE$^u zLX5%%0q0XgReM`;zlyAD2+m4+Lqa~EO_{#~)Okd{o;}*!jjbe2(v*rXjIlm?qsE)S zwe4BFu~?RA(pv zZPWzJ&-~1SI_(EqpjD?Emate5B9sbqf~@TOSgCz_kM}8*hL4xsy=lIqm3+D|u0x#| zm%lEIrp6$nco@`L@5eMRId;vib9rSjDIZJ(n?;jDVv$xczRsb_c>(??%zMF8c4hvI zJBgPdII``>RwclB|Dt{VY@IWH7BOS3Q;c`R(CfP90Q=xrPLgDRo0_URLxt9`LL{|= z8h`S&KlD!1$-SY@JNkNN>o{21YEGSdUCX>aYdg-#%98DMJ-CbTVR^3bnSOo&HsW7F z@IP|nA^Ab!XkFb$*O@>?GTMRr0TjDDKVCQw!X0!Ga4*=}9dG6~8AsqYhZb{#X7EPoW+w2x%lwV-%1f}SD?@Mu96kZ7Hs~|-DLMz=1}t#N!sY{- zRG*>*6~#~#13PZuZ{l>+wH5-bi-j)JMoh#Of-KD7Vq_8ZL|Kf*FI$bch;4O=I7?&+ zbR>y3mQ+|$Bo;y-P-i``Hg#F2#0|4nLqGZqd5XY+(rSBCZQmo3z;B42Gm0I05%}b} zAQD^M49YaTBg`+N+Zv3bEW1tTfCI)c2H#IGO1Alu9lj*+!S@&Pxz<*E8!W{LBv}3g zSDniN`N6<}R8eb{!yCc=txAX^`IkUS{%j~K-x`d|>A@j-POc4Bv(F;aCIS^+o$L6# z{O90^92qLnVR>ojR1+hxNL!_BFXvM`d3ut66`0n8qZrGF2bP?o=R5Ym!^H%&sjj`` zvhicD`0#>Y(OX=$YL!o>n{SX_Z6pe1boQ zVx&1Tx?k0WD<~Q*;l-A#br&lSq-tq)m9N>SG5t@-herk?swId*<6u!!3u>B)j4_d z{(Vy0cdtCYuXlJDCX4-^zf@xN*%Ew<)K-_4&nr868rVy#JMxy%JDS_T$2;F6dsWcPBGdt?g9$obOc%d<9!&D=SJf4mUdHO=VQsch_S)N&O zR7VSS2fhVg86Ex<{5yi^er%g88p6kC1+9=(voh8}>j5if4OvGme-N519W>XWgyx`- J_Q8WI{tMC@13>@) diff --git a/tracking/utils/plotting.py b/tracking/utils/plotting.py index 50a6dc1..9eb4c78 100644 --- a/tracking/utils/plotting.py +++ b/tracking/utils/plotting.py @@ -285,6 +285,38 @@ def boxing_img(det, img, line_width=3): return imgx +def array2list(bboxes): + track_fids = np.unique(bboxes[:, 7].astype(int)) + track_fids.sort() + + lboxes = [] + for f_id in track_fids: + # print(f"The ID is: {t_id}") + idx = np.where(bboxes[:, 7] == f_id)[0] + box = bboxes[idx, :] + lboxes.append(box) + + assert len(set(box[:, 4])) == len(box), "Please check!!!" + + return lboxes + + +def get_subimgs(imgs, tracks, scale=2): + bboxes = [] + if len(tracks): + bboxes = array2list(tracks) + + subimgs = [] + for i, boxes in enumerate(bboxes): + fid = int(boxes[0, 7]) + + for *xyxy, tid, conf, cls, fid, bid in boxes: + pt2 = [p/scale for p in xyxy] + x1, y1, x2, y2 = (int(pt2[0]), int(pt2[1])), (int(pt2[2]), int(pt2[3])) + subimgs.append((int(fid), int(bid), imgs[fid-1][y1:y2, x1:x2])) + + return subimgs + def draw_tracking_boxes(imgs, tracks, scale=2): '''需要确保 imgs 覆盖tracks中的帧ID数 tracks: [x1, y1, x2, y2, track_id, score, cls, frame_index, box_index] @@ -295,27 +327,15 @@ def draw_tracking_boxes(imgs, tracks, scale=2): ''' - def array2list(bboxes): - track_fids = np.unique(bboxes[:, 7].astype(int)) - track_fids.sort() - - lboxes = [] - for f_id in track_fids: - # print(f"The ID is: {t_id}") - idx = np.where(bboxes[:, 7] == f_id)[0] - box = bboxes[idx, :] - lboxes.append(box) - - assert len(set(box[:, 4])) == len(box), "Please check!!!" - - return lboxes - - bboxes = array2list(tracks) + + bboxes = [] + if len(tracks): + bboxes = array2list(tracks) # if len(bboxes)!=len(imgs): # return False, imgs - subimgs = [] + annimgs = [] for i, boxes in enumerate(bboxes): fid = int(boxes[0, 7]) annotator = Annotator(imgs[fid-1].copy()) @@ -331,11 +351,11 @@ def draw_tracking_boxes(imgs, tracks, scale=2): pt2 = [p/scale for p in xyxy] annotator.box_label(pt2, label, color=color) - + img = annotator.result() - subimgs.append((fid, img)) + annimgs.append((int(fid), img)) - return subimgs + return annimgs diff --git a/tracking/utils/read_data.py b/tracking/utils/read_data.py index 663890d..a733fe6 100644 --- a/tracking/utils/read_data.py +++ b/tracking/utils/read_data.py @@ -37,6 +37,9 @@ def find_samebox_in_array(arr, target): def extract_data(datapath): + ''' + 0/1_track.data 数据读取 + ''' bboxes, ffeats = [], [] trackerboxes = np.empty((0, 9), dtype=np.float64) @@ -147,8 +150,15 @@ def extract_data(datapath): return bboxes, ffeats, trackerboxes, tracker_feat_dict, trackingboxes, tracking_feat_dict def read_tracking_output(filepath): + ''' + 0/1_tracking_output.data 数据读取 + ''' + boxes = [] feats = [] + if not os.path.isfile(filepath): + return np.array(boxes), np.array(feats) + with open(filepath, 'r', encoding='utf-8') as file: for line in file: line = line.strip() # 去除行尾的换行符和可能的空白字符 @@ -176,7 +186,6 @@ def read_deletedBarcode_file(filePath): split_flag, all_list = False, [] dict, barcode_list, similarity_list = {}, [], [] - clean_lines = [line.strip().replace("'", '').replace('"', '') for line in lines] for i, line in enumerate(clean_lines): @@ -199,6 +208,7 @@ def read_deletedBarcode_file(filePath): if label == 'SeqDir': dict['SeqDir'] = value + dict['filetype'] = "deletedBarcode" if label == 'Deleted': dict['Deleted'] = value if label == 'List': @@ -259,15 +269,19 @@ def read_returnGoods_file(filePath): if label == 'SeqDir': dict['SeqDir'] = value dict['Deleted'] = value.split('_')[-1] + dict['filetype'] = "returnGoods" if label == 'List': split_flag = True continue if split_flag: + bcd = label.split('_')[-1] + # event_list.append(label + '_' + bcd) event_list.append(label) - barcode_list.append(label.split('_')[-1]) + barcode_list.append(bcd) similarity_list.append(value.split(',')[0]) type_list.append(value.split('=')[-1]) + if len(barcode_list): dict['barcode'] = barcode_list if len(similarity_list): dict['similarity'] = similarity_list if len(event_list): dict['event'] = event_list @@ -279,33 +293,51 @@ def read_returnGoods_file(filePath): + +# ============================================================================= +# def read_seneor(filepath): +# WeightDict = OrderedDict() +# with open(filepath, 'r', encoding='utf-8') as f: +# lines = f.readlines() +# for i, line in enumerate(lines): +# line = line.strip() +# +# keyword = line.split(':')[0] +# value = line.split(':')[1] +# +# vdata = [float(s) for s in value.split(',') if len(s)] +# +# WeightDict[keyword] = vdata[-1] +# +# return WeightDict +# ============================================================================= + +def read_one2one_simi(filePath): - - - - - - - - - - - -def read_seneor(filepath): - WeightDict = OrderedDict() - with open(filepath, 'r', encoding='utf-8') as f: + SimiDict = {} + with open(filePath, 'r', encoding='utf-8') as f: lines = f.readlines() + flag = False for i, line in enumerate(lines): line = line.strip() + if line.find('barcode:')<0 and not flag: + continue + if line.find('barcode:')==0 : + flag = True + continue - keyword = line.split(':')[0] - value = line.split(':')[1] - - vdata = [float(s) for s in value.split(',') if len(s)] - - WeightDict[keyword] = vdata[-1] - - return WeightDict + # if line.endswith(','): + # line = line[:-1] + if flag: + barcode = line.split(',')[0].strip() + value = line.split(',')[1].split(':')[1].strip() + SimiDict[barcode] = float(value) + + if flag and not line: + flag = False + + return SimiDict + def read_weight_timeConsuming(filePth): @@ -362,15 +394,14 @@ def plot_sensor_curve(WeightDict, SensorDict, ProcessTimeDict): nw = len(wdata) assert(nw) >= 8, "The num of weight data is less than 8!" - i1, i2 = 0, 7 - while i2 < nw: - data = wdata[i1:(i2+1)] - max(data) - min(data) - - if i2<7: - i1 = 0 - else: - i1 = i2-windth + # i1, i2 = 0, 7 + # while i2 < nw: + # data = wdata[i1:(i2+1)] + # max(data) - min(data) + # if i2<7: + # i1 = 0 + # else: + # i1 = i2-windth min_t = min(wtime + stime) wtime = [t-min_t for t in wtime] @@ -405,15 +436,12 @@ def plot_sensor_curve(WeightDict, SensorDict, ProcessTimeDict): -def main(file_path): +def test_process(file_path): WeightDict, SensorDict, ProcessTimeDict = read_weight_timeConsuming(file_path) plot_sensor_curve(WeightDict, SensorDict, ProcessTimeDict) - - - - -if __name__ == "__main__": + +def main(): files_path = r'\\192.168.1.28\share\测试_202406\0814\0814\20240814-102227-62264578-a720-4eb9-b95e-cb8be009aa98_null' k = 0 for filename in os.listdir(files_path): @@ -424,42 +452,21 @@ if __name__ == "__main__": extract_data(file_path) if os.path.isfile(file_path) and filename.find("process.data")>=0: - main(file_path) + test_process(file_path) k += 1 if k == 1: break - - - - # print("Done") - - - - - - - - - - - - - - - - - - - - - - - - - - + +def main1(): + fpath = r'\\192.168.1.28\share\测试_202406\1101\images\20241101-140456-44dc75b5-c406-4cb2-8317-c4660bb727a3_6922130101355_6922130101355\process.data' + simidct = read_one2one_simi(fpath) + print(simidct) + +if __name__ == "__main__": + # main() + main1() diff --git a/说明文档.txt b/说明文档.txt index 90b9d34..00b3ee9 100644 --- a/说明文档.txt +++ b/说明文档.txt @@ -144,15 +144,124 @@ precision_compare(filepath, savepath) 读取 deletedBarcode.txt 和 deletedBarcodeTest.txt 中的数据,进行相似度比较 - + + genfeats.py + get_std_barcodeDict(bcdpath, savepath) + 功能: 生成并保存只有一个key值的字典 {barcode: [imgpath1, imgpath1, ...]} + + stdfeat_infer(imgPath, featPath, bcdSet=None) + 功能: 对 imgPath 中图像进行特征提取,生成只有一个key值的字典。 + {barcode: features},features.shape=(nsample, 256),并保存至 featPath 中 + one2n_contrast.py - 1:n 比对,读取 deletedBarcode.txt,实现现场测试评估。 - main(): - 循环读取不同文件夹中的 deletedBarcode.txt,合并评估。 - main1(): - 指定deletedBarcode.txt进行1:n性能评估 + test_one2n() + 1:n 现场测试性能评估,输出 PR 曲线 + 兼容 2 种 txt 文件格式:returnGoods.txt, deletedBarcode.txt, + 分别对应不同的文件读取函数: + - read_deletedBarcode_file() + - read_returnGoods_file() + + one2n_return(all_list) + 输入:从returnGoods.txt读取的数据 + 输出: + corrpairs:(取出事件, 正确匹配的放入事件) + errpairs:(取出事件, 放入事件, 错误匹配的放入事件) + corr_similarity: (正确匹配时的相似度) + err_similarity: (错误匹配时的相似度) + + + one2n_deleted(all_list) + 输入: 从deletedBarcode.txt读取的数据 + 输出: + corrpairs:(取出事件, 取出的barcode) + errpairs:(取出事件, 取出的barcode, 错误匹配的barcode) + corr_similarity: (正确匹配时的相似度) + err_similarity: (错误匹配时的相似度) + + save_tracking_imgpairs(pairs, savepath) + 输入: + pairs:匹配时间对,len(2)=2 or 3, 对应正确匹配与错误匹配 + savepath:结果保存地址,其中图像文件的命名为:取出事件 + 放入事件 + 错误匹配时间 + 子函数 get_event_path(), 扫码放入的对齐名 + 对于 returnGoods.txt, 放入事件的事件名和对应的文件夹名不一致,需要对齐 + + test_rpath_deleted() + 功能: + 针对 eletedBarcode.txt 格式的 1:n 数据结果文件 + 获得 1:n 情况下正确或匹配事件对(取出事件、放入事件、错误匹配事件) + 匹配事件分析, 实现函数:save_tracking_imgpairs() + 重要参数: + del_barcode_file: + basepath: 对应事件路径 + savepath: 存储路径, 是函数 save_tracking_imgpairs() 的输入 + saveimgs: Ture, False, 是否保存错误匹配的事件对 + + get_contrast_paths() + 针对 eletedBarcode.txt 格式的 1:n 数据结果文件,返回三元时间元组(getoutpath, inputpath, errorpath) + + test_rpath_return() + 针对 returnGoods.txt 格式 1:n 数据文件,不需要调用函数get_contrast_paths() + 获得 1:n 情况下正确或匹配事件对(取出事件、放入事件、错误匹配事件) + 匹配事件分析, 实现函数:save_tracking_imgpairs() + + + one2one_contrast.py + 共6个地址: + (1) stdSamplePath: 用于生成比对标准特征集的原始图像地址 + (2) stdBarcodePath: 比对标准特征集原始图像地址的pickle文件存储,{barcode: [imgpath1, imgpath1, ...]} + (3) stdFeaturePath: 比对标准特征集特征存储地址 + (4) eventFeatPath: 用于1:1比对的购物事件特征存储地址、对应子图存储地址 + (5) subimgPath: 1:1比对购物事件轨迹、标准barcode所对应的 subimgs 存储地址 + (6) resultPath: 1:1比对结果存储地址 + + (1), (2), (3): 保存标准特征集向量,只需运行一次 + (4): 保存测试的事件字典,只需运行一次 + + + test_one2one() + (1) 生成标准特征集, 只需运行一次 + genfeatures() + (2) 生成事件字典, 只需运行一次 + gen_eventdict(eventDatePath, saveimg) + 参数: + eventDatePath: 事件集列表,其中每个元素均为事件的集合; + saveimg: 是否保存事件子图 + + (3) 1:1性能评估 + (4) 计算PR曲线 + + + + creat_shopping_event(eventPath, subimgPath=False) + 构造一次购物事件字典, 共12个关键字。 + save_event_subimg(event, savepath) + 保存一次购物事件的子图 + + + one2one_eval() + + + + compute_precise_recall() + + + + + int8_to_ft16() + + + ft16_to_uint8() + + + + + + + + + one2one_onsite.py 现场试验输出数据的 1:1 性能评估; 适用于202410前数据保存版本的,需调用 OneToOneCompare.txt @@ -161,11 +270,13 @@ std_sample_path:图像样本的存储地址 std_barcode_path:对 std_sample_path 中文件列表进行遍历,形成{barcode: 图像样本地址}形式字典并进行存储 std_feature_path:调用 inference_image(), 对每一个barcode,生成字典并进行存储 - - + + + genfeats.py genfeatures(imgpath, bcdpath, featpath) - 功能:生成标准特征向量 + 功能:生成标准特征向量的字典, 并保存为: barcode.pickle + keys: barcode, imgpaths, feats_ft32, feats_ft16, feats_uint8 参数: (1) imgpath:图像样本的存储地址 (2) bcdpath:对 imgpath 中文件列表进行遍历,形成{barcode: 图像样本地址}形式字典并进行存储