五个功能模块
1. Yolo + Tracker + Resnet, 其中 Resnet 的实现在./contrast中
	track_reid.py
	
2. 轨迹分析模块，目录为：./tracking
	(1) 基于模块（Yolo + Tracker + Resnet）的输出
		tracking_test.py
	
	(2) 基于测试过程数据（track.data, tracking_output.data）的输出
		module_analysis.py
	
3. 比对分析模块，目录为：./contrast
	2个场景：1:1，1:n
	1:1场景：
		(1) 利用现场保存数据进行比对
			OneToOneCompare.txt（现场保存数据）
			one2one_onsite.py
		(2) 利用本地算法进行特征提取
			one2one_contrast.py
	1:n场景：
		(1) 直接利用 deletedBarcode.txt 中数据
			one2n_contrast.py
		(2) 构造取出、放入事件，设计不同的特征，
			feat_select.py


4. 整体流程仿真
	pipeline.py
		需要指定是个变量：
	(1) evtdir: 保存各个事件的文件夹
	(2) SourceType: "image", "video", yolo+resent+tracker模块输入数据类型
	(3) savepath: 结果数据保存位置
	(4) weights: YoloV5 模型权重
	
	savepath
		(1) Yolos_Tracking
			eventname文件夹，保存yolo+resent+tracker模块输出，包括：
				(1) images 或 {videoname}
				(2) subimgs
				(3) trajectory
				(4) front_y2.png
				(5) trajectory.png
		(2) ShoppingDict_pkfile
			保存 ShoppingDict 字典的 pickle 文件，可用于构造 ShoppingEvent 对象。
			
		(3) contrast
			保存1:1、1:SN、1:n数据
			
		(4) error_events.txt
	
	事件字典结构：
		ShoppingDict = {"eventPath": eventpath, 
						"eventName": evtname,
						"barcode": barcode,
						"eventType": '',   # "input", "output", "other"
						"frontCamera": {}, 
						"backCamera": {},
						"one2n": []
						}
		
			相机字典：			
			CameraEvent = {"cameraType": '',   # "front", "back"
						   "videoPath": '',
						   "imagePaths": [],
						   "yoloResnetTracker": [],
						   "tracking": [],
						   }
				
				yoloResnetTracker，列表，元素 "frameDict" 为有关帧数据的字典结构
				frameDict = {"path": path, 
							 "fid": int(frameId),
							 "bboxes": det,
							 "tboxes": tracks,
							 "imgs": imgdict,
							 "feats": featdict}
				
			
	



5. 全实时时间切分仿真分析
	time_devide.py
	需分 2 步运行模块:
    (1) runyolo()
	
		该模块调用 imgs_inference.py 中模块 run_yolo, 该模块重新定义了类 LoadImages, 对图像进行了旋转。
		后续工作：
		1). 将run_yolo模块与track_redi.yolo_resnet_tracker模块合并
		2). 图像文件名标准化
    
    (2) show_seri()
		该模块调用 event_time_specify.py 中模块 devide_motion_state


具体实现：
./tracking
	tracking_test.py
		have_tracked():
			轨迹分析测试。遍历track_reid.py输出的文件夹trackdict下的所有.pkl文件。

	time_test.py
		统计Pipeline整体流程中各模块耗时
		
	module_analysis.py
		该模块中需要借助 try...except... 捕获data文件中的异常
		main(): 
			遍历文件夹下的每一个子文件夹，对子文件夹执行tracking_simulate() 函数；
		
		main_loop()：
			(1) 根据 deletedBarcode.txt 生成事件对，并利用事件对生成存储地址
			(2) 调用 tracking_simulate() 函数
		
		tracking_simulate(eventpath, savepath)：
			(1) 根据event_names获取事件名enent_name
			(2) 遍历并执行 eventpath 文件夹下的 0_track.data、1_track.data 文件，并调用do_tracking() 执行
			(3) 将前后摄、本地与现场，工8幅子图合并为1幅大图。
				上下子图分别显示的是前后摄，每一行4个子图，分别为：
				(a) tracker输出原始轨迹; 
				(b) 本地tracking输出; 
				(c) 现场算法轨迹选择前轨迹; 
				(d) 现场算法轨迹选择后的轨迹
				
			
		
		do_tracking(fpath, savedir, event_name)
			inputs：
				fpath: 0/1_track.data文件，并核验是否存在 0/1_tracking_output.data，若不存在该文件，直接返回 None, None
				
				savedir: 在该文件夹下会建立3个子文件夹及一个png轨迹图
					./savedir/event_name_images, 画boxes后的图像序列
					./savedir/event_name_subimgs, 轨迹分析后的目标子图，无 _x 为PC机结果，有 _x 为平板单摄像头轨迹选择后的输出
					./savedir/trajectory, 存储每一个轨迹图
					./savedir/event_name_tracking_select.png 或 enent_name_tracking.png 或 enent_name_select.png
					
			outputs:
				img_tracking：本机tracker、tracking 输出的结果比较图
				abimg: 部署算法的tracking、轨迹选择分析比较图
			

	./utils/read_data.py
		0/1_track.data 文件保存：yolo、Resnet、tracker、tracking模块的输出
		函数: extract_data(datapath)
			异常排除：
				(1) assert len(boxes)==len(feats)，确保每一帧内boxes数和feats数相等
				(2) assert(len(bboxes)==len(ffeats)), 确保关于bboxes的帧数和关于ffeats的帧数相等
				(3) assert(len(trackerboxes)==len(trackerfeats))，确保tracker输出的boxes可以对应到相应的feats上 
				这里未对 len(box)!=9、len(feat)!=256, 的情况做出约束
			输出：
				bboxes
				ffeats
				trackerboxes
				tracker_feat_dict[f"frame_{fid}"]["feats"]{{bid}: (256,)
											 }
				trackingboxes		
				tracking_feat_dict[f"track_{tid}"]["feats"]{f"{fid}_{bid}": tracker_feat_dict[f"frame_{fid}"]["feats"][bid]})
		
		
		
		0/1_tracking_output.data 文件保存用于比对的boxes、features
		函数: read_tracking_output(filepath)
			异常排除：
				(1) assert len(feats)==len(boxes)
				(2) box.size==9、feat.size=256
		
		

	./deprecated/contrast_one2one.py
		1:1 比对评估。have Deprecated! 
	./enentmatch.py
		1:n 模拟测试，have Deprecated! 
		
		
./contrast
	seqfeat_compare.py 
		similarity_compare_sequence(root_dir)
			inputs:
				root_dir：文件夹，包含"subimgs"字段，对该文件夹中的相邻图像进行相似度比较
		silimarity_compare()
			功能：对imgpaths文件夹中的图像进行相似度比较
	select_subimgs.py
		为吴华琦实现的样本选择程序
		

	event_test.py
		calc_simil(event, stdfeat)
			事件与标准库的对比策略，该函数在one2one_contrast.py中调用
			calsiml(feat1, feat2, topkp=75, cluth=0.15):
				功能：计算2个样本集的相似度
				（1）(feat1, feat2)，对于单样本，选择 topkp 的相似度，并求均值，得到单样本对另一个特征集的相似度；
				（2）simi_max：样本集 feat1 对样本集 feat2 的相似度，是一个向量
				（3）对 simi_max 进行聚类，阈值为 cluth，选取值最大的聚类中心，作为2个样本集相似度的度量
			前后摄轨迹选择：
				情况1：前后摄轨迹（与标准集的）相似度的差 > 阈值，表明前后摄中有一个轨迹与标准集相差较远，丢弃相应轨迹，保留具有较大相似度的轨迹
				情况2：前后摄轨迹（与标准集的）相似度的差 >=阈值，表明前后摄轨迹与标准集均相似，求轨迹相似度均值
		
			
	
	
	
	

		
	input_getout_compare.py
		creatd_deletedBarcode_front(filepath)
			(1) 基于 deletedBarcode.txt, 构造取出事件和相应的放入事件，构成列表并更新这些列表。
				MatchList = [(getout_event, InputList), ...]
				
			(2) 设计不同的特征选择方式，计算 getout 事件和各 input 事件的相似度，并保存于文件：
				deletedBarcodeTest.txt
		
		
		precision_compare(filepath, savepath)
			读取 deletedBarcode.txt 和 deletedBarcodeTest.txt 中的数据，进行相似度比较
	
	stdfeat_analys()：
		feat_analysis(featpath): 标准特征集中样本类内、类间相似度分布
	
	feat_infer.py
		简单的subimg特征提取
	
	
	
	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 中
			  
			  
	onsite_contrast_pr.py
		one2one_pr()
			现场试验输出数据的性能评估，输出1:1, 1:SN, 1:n的PR曲线和相似度直方图分布。
		
		
		test_compare()
			适用于202410前数据保存版本的，需调用 OneToOneCompare.txt		  
	
	
	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:1比对
			(1) 初始化事件和标准特征集, 只需运行一次
				init_std_evt_dict()
			(2) 事件barcode集和标准库barcode求交集
				build_std_evt_dict()
			(3) 1:1性能评估
				one2one_simi()
			(4) 计算PR曲线
				one2one_pr()
		
		test_one2SN()
			1:SN比对
			(1) 初始化事件和标准特征集, 只需运行一次
				init_std_evt_dict()
			(2) 事件barcode集和标准库barcode求交集
				build_std_evt__dict()
			(3) 1:SN性能评估
				one2SN_pr()

		
		init_std_evt_dict()
			生成标准特征集与事件对象并存储，并存储相关数据，只需运行一次
			
			(1) Barcode图像进行特征推理并保存
			gen_bcd_features(stdSamplePath, stdBarcodePath, stdFeaturePath, bcdSet)
			
			(2) 基于data文件或pipeline输出的pickle文件生成 ShoppingEvent 对象
			gen_eventdict(eventDatePath, saveimg)
		
		build_std_evt_dict()
			基于事件barcode集和标准库barcode交集构造用于评估性能的事件集合。

		simi_calc()
			计算事件和标准特征集的相似度

		data_precision_compare()
			不同数据精度下的性能比较
		
		

		int8_to_ft16()
		
		
		ft16_to_uint8()
		
	one2n_contrast.py
		执行1:n共需要3步，分别对应3个函数：
			(1) 生成事件字典并保存至 eventDataPath, 只需运行一次
			(2) 读取事件字典
			(3) 1:n 比对事件评估
		
		(1) gen_eventdict(sourcePath)
		
		
		(2) read_eventdict()
			inputs：
				eventDataPath: 类 ShoppingEvent 对象存储地址，该对象由函数 gen_eventdict() 生成。
				
			output：
				evtDicts
		
		
		(3) one2n_pr()
			inputs：
				evtDicts
				
			output：
				fpevents：FP事件地址
				
		(4) simi_calc()
			计算两个事件的相似度
	
	
			
	one2n_contrast_old.py (disused)
		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()
	
			
time_devide.py
	runyolo()
		执行 imgs_inference.py 中的 run_yolo()模块，该模块重新定义了类 LoadImages, 对图像进行了旋转。
	
	
	show_seri()
		
		