diff --git a/__pycache__/track_reid.cpython-39.pyc b/__pycache__/track_reid.cpython-39.pyc index 736b8a3..e5287f5 100644 Binary files a/__pycache__/track_reid.cpython-39.pyc and b/__pycache__/track_reid.cpython-39.pyc differ diff --git a/contrast/one2one_contrast.py b/contrast/one2one_contrast.py index 69f96ae..663d16f 100644 --- a/contrast/one2one_contrast.py +++ b/contrast/one2one_contrast.py @@ -52,10 +52,10 @@ from tracking.utils.read_data import extract_data, read_tracking_output, read_si from tracking.utils.plotting import Annotator, colors from feat_extract.config import config as conf from feat_extract.inference import FeatsInterface -from utils.event import Event +from utils.event import ShoppingEvent from genfeats import gen_bcd_features -IMG_FORMAT = ['.bmp', '.jpg', '.jpeg', '.png'] + @@ -83,148 +83,6 @@ def ft16_to_uint8(arr_ft16): return arr_uint8, arr_ft16_ -def creat_shopping_event(eventPath): - '''构造放入商品事件字典,这些事件需满足条件: - 1) 前后摄至少有一条轨迹输出 - 2) 保存有帧图像,以便裁剪出 boxe 子图 - ''' - - '''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'] = barcode - event['type'] = evtType - event['filepath'] = eventPath - event['back_imgpaths'] = [] - event['front_imgpaths'] = [] - event['back_boxes'] = np.empty((0, 9), dtype=np.float64) - event['front_boxes'] = np.empty((0, 9), dtype=np.float64) - 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['one2one'] = None - event['one2n'] = None - event['feats_select'] = np.empty((0, 256), dtype=np.float64) - - - '''================= 2. 读取 data 文件 =============================''' - for dataname in os.listdir(eventPath): - # filename = '1_track.data' - datapath = os.path.join(eventPath, dataname) - if not os.path.isfile(datapath): continue - - CamerType = dataname.split('_')[0] - ''' 2.1 读取 0/1_track.data 中数据,暂不考虑''' - # if dataname.find("_track.data")>0: - # bboxes, ffeats, trackerboxes, tracker_feat_dict, trackingboxes, tracking_feat_dict = extract_data(datapath) - - ''' 2.2 读取 0/1_tracking_output.data 中数据''' - if dataname.find("_tracking_output.data")>0: - tracking_output_boxes, tracking_output_feats = read_tracking_output(datapath) - if len(tracking_output_boxes) != len(tracking_output_feats): continue - if CamerType == '0': - event['back_boxes'] = tracking_output_boxes - event['back_feats'] = tracking_output_feats - elif CamerType == '1': - event['front_boxes'] = tracking_output_boxes - event['front_feats'] = tracking_output_feats - - if dataname.find("process.data")==0: - simiDict = read_similar(datapath) - event['one2one'] = simiDict['one2one'] - event['one2n'] = simiDict['one2n'] - - - if len(event['back_boxes'])==0 or len(event['front_boxes'])==0: - return None - - '''2.3 事件的特征表征方式: 特征选择、特征集成''' - bk_feats = event['back_feats'] - ft_feats = event['front_feats'] - - '''2.3.1 特征集成''' - feats_compose = np.empty((0, 256), dtype=np.float64) - if len(ft_feats): - feats_compose = np.concatenate((feats_compose, ft_feats), axis=0) - if len(bk_feats): - feats_compose = np.concatenate((feats_compose, bk_feats), axis=0) - event['feats_compose'] = feats_compose - - '''2.3.1 特征选择''' - if len(ft_feats): - event['feats_select'] = ft_feats - - - '''================ 3. 读取图像文件地址,并按照帧ID排序 =============''' - frontImgs, frontFid = [], [] - backImgs, backFid = [], [] - for imgname in os.listdir(eventPath): - name, ext = os.path.splitext(imgname) - if ext not in IMG_FORMAT or name.find('frameId')<0: continue - - CamerType = name.split('_')[0] - frameId = int(name.split('_')[3]) - imgpath = os.path.join(eventPath, imgname) - if CamerType == '0': - backImgs.append(imgpath) - backFid.append(frameId) - if CamerType == '1': - frontImgs.append(imgpath) - frontFid.append(frameId) - - frontIdx = np.argsort(np.array(frontFid)) - backIdx = np.argsort(np.array(backFid)) - - '''3.1 生成依据帧 ID 排序的前后摄图像地址列表''' - frontImgs = [frontImgs[i] for i in frontIdx] - backImgs = [backImgs[i] for i in backIdx] - - '''3.2 将前、后摄图像路径添加至事件字典''' - - - bfid = event['back_boxes'][:, 7].astype(np.int64) - ffid = event['front_boxes'][:, 7].astype(np.int64) - if len(bfid) and max(bfid) <= len(backImgs): - event['back_imgpaths'] = [backImgs[i-1] for i in bfid] - if len(ffid) and max(ffid) <= len(frontImgs): - event['front_imgpaths'] = [frontImgs[i-1] for i in ffid] - - - '''================ 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: {evtName}, Error, condt1: {condt1}, condt2: {condt2}") - return None - - return event - - - def plot_save_image(event, savepath): cameras = ('front', 'back') @@ -286,9 +144,6 @@ def save_event_subimg(event, savepath): else: boxes = event.back_boxes imgpaths = event.back_imgpaths - - - for i, box in enumerate(boxes): x1, y1, x2, y2, tid, score, cls, fid, bid = box @@ -491,8 +346,8 @@ def one2one_simi(): ##============================================ float32 stdfeat = stdDict[stdbcd]["feats_ft32"] - evtfeat = event.feats_compose - + + evtfeat = event.feats_compose if len(evtfeat)==0: continue matrix = 1 - cdist(stdfeat, evtfeat, 'cosine') @@ -585,28 +440,9 @@ def gen_eventdict(sourcePath, saveimg=True): pickpath = os.path.join(eventDataPath, f"{bname}.pickle") if os.path.isfile(pickpath): continue - - # if bname != "20241129-100321-a9dae9e3-7db5-4e31-959c-d7dfc228923e_6972636670213": - # continue - - - # eventDict = creat_shopping_event(eventPath) - # if eventDict: - # eventList.append(eventDict) - # with open(pickpath, 'wb') as f: - # pickle.dump(eventDict, f) - # print(f"Event: {eventName}, have saved!") - - # if saveimg and eventDict: - # basename = os.path.basename(eventDict['filepath']) - # savepath = os.path.join(subimgPath, basename) - # if not os.path.exists(savepath): - # os.makedirs(savepath) - # save_event_subimg(eventDict, savepath) - try: - event = Event(source_path) + event = ShoppingEvent(source_path, stype="data") eventList.append(event) with open(pickpath, 'wb') as f: pickle.dump(event, f) @@ -624,9 +460,7 @@ def gen_eventdict(sourcePath, saveimg=True): for line in errEvents: f.write(line + '\n') - - def test_one2one(): bcdList, event_spath = [], [] diff --git a/contrast/utils/__pycache__/event.cpython-39.pyc b/contrast/utils/__pycache__/event.cpython-39.pyc index 25c22c0..113c3dd 100644 Binary files a/contrast/utils/__pycache__/event.cpython-39.pyc and b/contrast/utils/__pycache__/event.cpython-39.pyc differ diff --git a/contrast/utils/dotest.py b/contrast/utils/dotest.py new file mode 100644 index 0000000..569b861 --- /dev/null +++ b/contrast/utils/dotest.py @@ -0,0 +1,155 @@ +# -*- coding: utf-8 -*- +""" +Created on Tue Dec 10 14:30:16 2024 + +@author: ym +""" +import os +import sys +import numpy as np +sys.path.append(r"D:\DetectTracking") +from tracking.utils.read_data import read_tracking_output, read_similar #, extract_data, read_deletedBarcode_file + + +IMG_FORMAT = ['.bmp', '.jpg', '.jpeg', '.png'] + + +def creat_shopping_event(eventPath): + '''构造放入商品事件字典,这些事件需满足条件: + 1) 前后摄至少有一条轨迹输出 + 2) 保存有帧图像,以便裁剪出 boxe 子图 + ''' + + '''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'] = barcode + event['type'] = evtType + event['filepath'] = eventPath + event['back_imgpaths'] = [] + event['front_imgpaths'] = [] + event['back_boxes'] = np.empty((0, 9), dtype=np.float64) + event['front_boxes'] = np.empty((0, 9), dtype=np.float64) + 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['one2one'] = None + event['one2n'] = None + event['feats_select'] = np.empty((0, 256), dtype=np.float64) + + + '''================= 2. 读取 data 文件 =============================''' + for dataname in os.listdir(eventPath): + # filename = '1_track.data' + datapath = os.path.join(eventPath, dataname) + if not os.path.isfile(datapath): continue + + CamerType = dataname.split('_')[0] + ''' 2.1 读取 0/1_track.data 中数据,暂不考虑''' + # if dataname.find("_track.data")>0: + # bboxes, ffeats, trackerboxes, tracker_feat_dict, trackingboxes, tracking_feat_dict = extract_data(datapath) + + ''' 2.2 读取 0/1_tracking_output.data 中数据''' + if dataname.find("_tracking_output.data")>0: + tracking_output_boxes, tracking_output_feats = read_tracking_output(datapath) + if len(tracking_output_boxes) != len(tracking_output_feats): continue + if CamerType == '0': + event['back_boxes'] = tracking_output_boxes + event['back_feats'] = tracking_output_feats + elif CamerType == '1': + event['front_boxes'] = tracking_output_boxes + event['front_feats'] = tracking_output_feats + + if dataname.find("process.data")==0: + simiDict = read_similar(datapath) + event['one2one'] = simiDict['one2one'] + event['one2n'] = simiDict['one2n'] + + + if len(event['back_boxes'])==0 or len(event['front_boxes'])==0: + return None + + '''2.3 事件的特征表征方式: 特征选择、特征集成''' + bk_feats = event['back_feats'] + ft_feats = event['front_feats'] + + '''2.3.1 特征集成''' + feats_compose = np.empty((0, 256), dtype=np.float64) + if len(ft_feats): + feats_compose = np.concatenate((feats_compose, ft_feats), axis=0) + if len(bk_feats): + feats_compose = np.concatenate((feats_compose, bk_feats), axis=0) + event['feats_compose'] = feats_compose + + '''2.3.1 特征选择''' + if len(ft_feats): + event['feats_select'] = ft_feats + + + '''================ 3. 读取图像文件地址,并按照帧ID排序 =============''' + frontImgs, frontFid = [], [] + backImgs, backFid = [], [] + for imgname in os.listdir(eventPath): + name, ext = os.path.splitext(imgname) + if ext not in IMG_FORMAT or name.find('frameId')<0: continue + + CamerType = name.split('_')[0] + frameId = int(name.split('_')[3]) + imgpath = os.path.join(eventPath, imgname) + if CamerType == '0': + backImgs.append(imgpath) + backFid.append(frameId) + if CamerType == '1': + frontImgs.append(imgpath) + frontFid.append(frameId) + + frontIdx = np.argsort(np.array(frontFid)) + backIdx = np.argsort(np.array(backFid)) + + '''3.1 生成依据帧 ID 排序的前后摄图像地址列表''' + frontImgs = [frontImgs[i] for i in frontIdx] + backImgs = [backImgs[i] for i in backIdx] + + '''3.2 将前、后摄图像路径添加至事件字典''' + + + bfid = event['back_boxes'][:, 7].astype(np.int64) + ffid = event['front_boxes'][:, 7].astype(np.int64) + if len(bfid) and max(bfid) <= len(backImgs): + event['back_imgpaths'] = [backImgs[i-1] for i in bfid] + if len(ffid) and max(ffid) <= len(frontImgs): + event['front_imgpaths'] = [frontImgs[i-1] for i in ffid] + + + '''================ 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: {evtName}, Error, condt1: {condt1}, condt2: {condt2}") + return None + + return event \ No newline at end of file diff --git a/contrast/utils/event.py b/contrast/utils/event.py index e28f56e..fa0757f 100644 --- a/contrast/utils/event.py +++ b/contrast/utils/event.py @@ -5,6 +5,7 @@ Created on Tue Nov 26 17:35:05 2024 @author: ym """ import os +import pickle import numpy as np from pathlib import Path @@ -15,9 +16,9 @@ from tracking.utils.read_data import extract_data, read_tracking_output, read_si IMG_FORMAT = ['.bmp', '.jpg', '.jpeg', '.png'] VID_FORMAT = ['.mp4', '.avi'] -class Event: +class ShoppingEvent: def __init__(self, eventpath, stype="data"): - '''stype: str, 'video', 'image', 'data', ''' + '''stype: str, 'pickle', 'data', ''' self.eventpath = eventpath self.evtname = str(Path(eventpath).stem) @@ -35,37 +36,115 @@ class Event: self.one2n = None '''=========== 0/1_track.data =============================''' - self.back_yolobboxes = np.empty((0, 6), dtype=np.float64) - self.back_yolofeats = np.empty((0, 256), dtype=np.float64) - self.back_trackerboxes = np.empty((0, 9), dtype=np.float64) - self.back_trackerfeats = np.empty((0, 256), dtype=np.float64) - self.back_trackingboxes = np.empty((0, 9), dtype=np.float64) - self.back_trackingfeats = np.empty((0, 256), dtype=np.float64) + self.back_yolobboxes = [] + self.back_yolofeats = [] + self.back_trackerboxes = np.empty((0, 9), dtype=np.float64) ##和类doTracks兼容 + self.back_trackerfeats = {} + self.back_trackingboxes = [] + self.back_trackingfeats = [] - self.front_yolobboxes = np.empty((0, 6), dtype=np.float64) - self.front_yolofeats = np.empty((0, 256), dtype=np.float64) - self.front_trackerboxes = np.empty((0, 9), dtype=np.float64) - self.front_trackerfeats = np.empty((0, 256), dtype=np.float64) - self.front_trackingboxes = np.empty((0, 9), dtype=np.float64) - self.front_trackingfeats = np.empty((0, 256), dtype=np.float64) + self.front_yolobboxes = [] + self.front_yolofeats = [] + self.front_trackerboxes = np.empty((0, 9), dtype=np.float64) ##和类doTracks兼容 + self.front_trackerfeats = {} + self.front_trackingboxes = [] + self.front_trackingfeats = [] '''=========== 0/1_tracking_output.data ===================''' - self.back_boxes = np.empty((0, 9), dtype=np.float64) - self.front_boxes = np.empty((0, 9), dtype=np.float64) - self.back_feats = np.empty((0, 256), dtype=np.float64) - self.front_feats = np.empty((0, 256), dtype=np.float64) - self.feats_compose = np.empty((0, 256), dtype=np.float64) - self.feats_select = np.empty((0, 256), dtype=np.float64) + self.back_boxes = [] + self.back_feats = [] + self.front_boxes = [] + self.front_feats = [] + if stype=="data": self.from_datafile(eventpath) + if stype=="pickle": + self.from_pklfile(eventpath) + + self.feats_select = [] + self.feats_compose = np.empty((0, 256), dtype=np.float64) + self.select_feats() + self.compose_feats() + + # if stype=="image": + # self.from_image(eventpath) + + def kerndata(self, ShoppingDict, camtype="backCamera"): + ''' + camtype: str, "backCamera" or "frontCamera" + ''' + yoloboxes, resfeats = [], [] + trackerboxes = np.empty((0, 9), dtype=np.float64) + trackefeats = {} + trackingboxes, trackingfeats = [], [] + + frameDictList = ShoppingDict[camtype]["yoloResnetTracker"] + for frameDict in frameDictList: + yoloboxes.append(frameDict["bboxes"]) - if stype=="video": - self.from_video(eventpath) + tboxes = frameDict["tboxes"] + trackefeats.update(frameDict["feats"]) + + trackerboxes = np.concatenate((trackerboxes, np.array(tboxes)), axis=0) + + Residual = ShoppingDict[camtype]["tracking"].Residual + for track in Residual: + trackingboxes.append(track.boxes) + trackingfeats.append(track.features) + kdata = (yoloboxes, resfeats, trackerboxes, trackefeats, trackingboxes, trackingfeats) + + + tracking_out_boxes, tracking_out_feats = [], [] + Confirmed = ShoppingDict[camtype]["tracking"].Confirmed + for track in Confirmed: + tracking_out_boxes.append(track.boxes) + tracking_out_feats.append(track.features) + outdata = (tracking_out_boxes, tracking_out_feats) + + return kdata, outdata + + + def from_pklfile(self, eventpath): - if stype=="image": - self.from_image(eventpath) + with open(eventpath, 'rb') as f: + ShoppingDict = pickle.load(f) + + self.eventpath = ShoppingDict["eventPath"] + self.evtname = ShoppingDict["eventName"] + self.barcode = ShoppingDict["barcode"] + + '''=========== path of image and video =========== ''' + self.back_videopath = ShoppingDict["backCamera"]["videoPath"] + self.front_videopath = ShoppingDict["frontCamera"]["videoPath"] + self.back_imgpaths = ShoppingDict["backCamera"]["imagePaths"] + self.front_imgpaths = ShoppingDict["frontCamera"]["imagePaths"] + + '''===========对应于 0/1_track.data =============================''' + backdata, back_outdata = self.kerndata(ShoppingDict, "backCamera") + frontdata, front_outdata = self.kerndata(ShoppingDict, "frontCamera") + self.back_yolobboxes = backdata[0] + self.back_yolofeats = backdata[1] + self.back_trackerboxes = backdata[2] + self.back_trackerfeats = [3] + self.back_trackingboxes = [4] + self.back_trackingfeats = [5] + + self.front_yolobboxes = frontdata[0] + self.front_yolofeats = frontdata[1] + self.front_trackerboxes = frontdata[2] + self.front_trackerfeats = frontdata[3] + self.front_trackingboxes = frontdata[4] + self.front_trackingfeats = frontdata[5] + + '''===========对应于 0/1_tracking_output.data =============================''' + self.back_boxes = back_outdata[0] + self.back_feats = back_outdata[1] + self.front_boxes = front_outdata[0] + self.front_feats = front_outdata[1] + + def from_datafile(self, eventpath): evtList = self.evtname.split('_') if len(evtList)>=2 and len(evtList[-1])>=10 and evtList[-1].isdigit(): @@ -127,21 +206,21 @@ class Event: '''========== 0/1_track.data ==========''' if dataname.find("_track.data")>0: - bboxes, ffeats, trackerboxes, tracker_feat_dict, trackingboxes, tracking_feat_dict = extract_data(datapath) + bboxes, ffeats, trackerboxes, trackerfeats, trackingboxes, trackingfeats = extract_data(datapath) if CamerType == '0': self.back_yolobboxes = bboxes self.back_yolofeats = ffeats self.back_trackerboxes = trackerboxes - self.back_trackerfeats = tracker_feat_dict + self.back_trackerfeats = trackerfeats self.back_trackingboxes = trackingboxes - self.back_trackingfeats = tracking_feat_dict + self.back_trackingfeats = trackingfeats if CamerType == '1': self.front_yolobboxes = bboxes self.front_yolofeats = ffeats self.front_trackerboxes = trackerboxes - self.front_trackerfeats = tracker_feat_dict + self.front_trackerfeats = trackerfeats self.front_trackingboxes = trackingboxes - self.front_trackingfeats = tracking_feat_dict + self.front_trackingfeats = trackingfeats '''========== 0/1_tracking_output.data ==========''' if dataname.find("_tracking_output.data")>0: @@ -152,26 +231,37 @@ class Event: elif CamerType == '1': self.front_boxes = tracking_output_boxes self.front_feats = tracking_output_feats - self.select_feat() - self.compose_feats() + def compose_feats(self): '''事件的特征集成''' feats_compose = np.empty((0, 256), dtype=np.float64) if len(self.front_feats): - feats_compose = np.concatenate((feats_compose, self.front_feats), axis=0) + for feat in self.front_feats: + feats_compose = np.concatenate((feats_compose, feat), axis=0) if len(self.back_feats): - feats_compose = np.concatenate((feats_compose, self.back_feats), axis=0) + for feat in self.back_feats: + feats_compose = np.concatenate((feats_compose, feat), axis=0) self.feats_compose = feats_compose def select_feats(self): '''事件的特征选择''' + self.feats_select = [] if len(self.front_feats): self.feats_select = self.front_feats - else: + elif len(self.back_feats): self.feats_select = self.back_feats - + +def main(): + pklpath = r"D:\DetectTracking\evtresult\images2\ShoppingDict.pkl" + + evt = ShoppingEvent(pklpath, stype='pickle') + + +if __name__ == "__main__": + main() + diff --git a/pipeline.py b/pipeline.py index 4faba3f..71fa31b 100644 --- a/pipeline.py +++ b/pipeline.py @@ -45,7 +45,7 @@ def get_interbcd_inputenents(): def pipeline( eventpath, - savepath, + savepath = '', SourceType = "image", # video stdfeat_path = None ): @@ -53,47 +53,120 @@ def pipeline( vpaths = get_video_pairs(eventpath) elif SourceType == "image": vpaths = get_image_pairs(eventpath) - + ''' + eventpath: 单个事件的存储路径 + + ''' + '''======== 函数 yolo_resnet_tracker() 的参数字典 ========''' opt = parse_opt() optdict = vars(opt) + + + optdict["weights"] = r'D:\DetectTracking\ckpts\best_cls10_0906.pt' optdict["is_save_img"] = True optdict["is_save_video"] = True event_tracks = [] + + ## 构造购物事件字典 + evtname = Path(eventpath).stem + barcode = evtname.split('_')[-1] if len(evtname.split('_'))>=2 \ + and len(evtname.split('_')[-1])>=8 \ + and evtname.split('_')[-1].isdigit() else '' + '''事件结果存储文件夹''' + if not savepath: + savepath = Path(__file__).resolve().parents[0] / "evtresult" + save_dir_event = Path(savepath) / evtname + + + ShoppingDict = {"eventPath": eventpath, + "eventName": evtname, + "barcode": barcode, + "eventType": '', # "input", "output", "other" + "frontCamera": {}, + "backCamera": {}} + for vpath in vpaths: - '''事件结果文件夹''' - save_dir_event = Path(savepath) / Path(os.path.basename(eventpath)) + '''相机事件字典构造''' + CameraEvent = {"cameraType": '', # "front", "back" + "videoPath": '', + "imagePaths": [], + "yoloResnetTracker": [], + "tracking": [], + } + if isinstance(vpath, list): - save_dir_video = save_dir_event / Path("images") + CameraEvent["imagePaths"] = vpath + bname = os.path.basename(vpath[0]) + if not isinstance(vpath, list): + CameraEvent["videoPath"] = vpath + bname = os.path.basename(vpath) + if bname.split('_')[0] == "0" or bname.find('back')>=0: + CameraEvent["cameraType"] = "back" + if bname.split('_')[0] == "1" or bname.find('front')>=0: + CameraEvent["cameraType"] = "front" + + '''事件结果存储文件夹''' + + if isinstance(vpath, list): + save_dir_video = save_dir_event / Path("images") else: save_dir_video = save_dir_event / Path(str(Path(vpath).stem)) - if not save_dir_video.exists(): save_dir_video.mkdir(parents=True, exist_ok=True) + '''Yolo + Resnet + Tracker''' optdict["source"] = vpath optdict["save_dir"] = save_dir_video + yrtOut = yolo_resnet_tracker(**optdict) - tracksdict = yolo_resnet_tracker(**optdict) + CameraEvent["yoloResnetTracker"] = yrtOut - bboxes = tracksdict['TrackBoxes'] - bname = os.path.basename(vpath[0]) if isinstance(vpath, list) else os.path.basename(vpath) - if bname.split('_')[0] == "0" or bname.find('back')>=0: - vts = doBackTracks(bboxes, tracksdict) - vts.classify() + # bboxes = np.empty((0, 9), dtype = np.float32) + # for frameDict in yrtOut: + # bboxes = np.concatenate([bboxes, frameDict["tboxes"]], axis=0) + trackerboxes = np.empty((0, 9), dtype=np.float64) + trackefeats = {} + for frameDict in yrtOut: + tboxes = frameDict["tboxes"] + ffeats = frameDict["feats"] + + trackerboxes = np.concatenate((trackerboxes, np.array(tboxes)), axis=0) + for i in range(len(tboxes)): + fid, bid = int(tboxes[i, 7]), int(tboxes[i, 8]) + trackefeats.update({f"{fid}_{bid}": ffeats[f"{fid}_{bid}"]}) + + + '''tracking''' + if CameraEvent["cameraType"] == "back": + vts = doBackTracks(trackerboxes, trackefeats) + vts.classify() event_tracks.append(("back", vts)) - if bname.split('_')[0] == "1" or bname.find('front')>=0: - vts = doFrontTracks(bboxes, tracksdict) + CameraEvent["tracking"] = vts + ShoppingDict["backCamera"] = CameraEvent + + if CameraEvent["cameraType"] == "front": + vts = doFrontTracks(trackerboxes, trackefeats) vts.classify() event_tracks.append(("front", vts)) + + CameraEvent["tracking"] = vts + ShoppingDict["frontCamera"] = CameraEvent - + # pklpath = save_dir_event / "ShoppingDict.pkl" + # with open(str(pklpath), 'wb') as f: + # pickle.dump(ShoppingDict, f) + pklpath = Path(savepath) / evtname+".pkl" + with open(str(pklpath), 'wb') as f: + pickle.dump(ShoppingDict, f) + + '''轨迹显示模块''' illus = [None, None] for CamerType, vts in event_tracks: @@ -182,14 +255,39 @@ def main(): ''' 函数:pipeline(),遍历事件文件夹,选择类型 image 或 video, ''' - parmDict = {} - parmDict["eventpath"] = r"\\192.168.1.28\share\测试视频数据以及日志\各模块测试记录\展厅测试\1120_展厅模型v801测试\扫A放A\20241121-144855-dce94b09-1100-43f1-92e8-33a1b538b159_6924743915848_6924743915848" + evtdir = r"\\192.168.1.28\share\测试视频数据以及日志\各模块测试记录\比对测试\1209永辉超市测试" + evtdir = Path(evtdir) - parmDict["savepath"] = r"D:\contrast\detect" + parmDict = {} + parmDict["savepath"] = r"D:\contrast\detect\pipeline" parmDict["SourceType"] = "image" # video, image parmDict["stdfeat_path"] = None - - pipeline(**parmDict) + + k = 1 + errEvents = [] + for item in evtdir.iterdir(): + if item.is_dir(): + item = r"D:\exhibition\images\images2\images2" + + + parmDict["eventpath"] = item + + + try: + pipeline(**parmDict) + except Exception as e: + errEvents.append(item) + + + # k+=1 + # if k==1: + # break + + errfile = os.path.join(parmDict["savepath"], f'error_events.txt') + with open(errfile, 'w', encoding='utf-8') as f: + for line in errEvents: + f.write(line + '\n') + if __name__ == "__main__": diff --git a/track_reid.py b/track_reid.py index 76ddb95..06c33e1 100644 --- a/track_reid.py +++ b/track_reid.py @@ -196,8 +196,8 @@ def yolo_resnet_tracker( tracker = init_trackers(tracker_yaml, bs)[0] dt = (Profile(), Profile(), Profile()) - track_boxes = np.empty((0, 9), dtype = np.float32) - TracksDict = {} + # trackerBoxes = np.empty((0, 9), dtype = np.float32) + yoloResnetTracker = [] for path, im, im0s, vid_cap, s in dataset: with dt[0]: im = torch.from_numpy(im).to(model.device) @@ -245,24 +245,23 @@ def yolo_resnet_tracker( tracks[:, 7] = frameId - + # trackerBoxes = np.concatenate([trackerBoxes, tracks], axis=0) '''================== 1. 存储 dets/subimgs/features Dict =============''' imgs, features = ReIDEncoder.inference(im0, tracks) - - # imgs, features = inference_image(im0, tracks) - - # TrackerFeats = np.concatenate([TrackerFeats, features], axis=0) - - imgdict = {} - boxdict = {} featdict = {} for ii, bid in enumerate(tracks[:, 8]): - imgdict.update({int(bid): imgs[ii]}) # [f"img_{int(bid)}"] = imgs[i] - boxdict.update({int(bid): tracks[ii, :]}) # [f"box_{int(bid)}"] = tracks[i, :] - featdict.update({int(bid): features[ii, :]}) # [f"feat_{int(bid)}"] = features[i, :] - TracksDict[f"frame_{int(frameId)}"] = {"imgs":imgdict, "boxes":boxdict, "feats":featdict} - - track_boxes = np.concatenate([track_boxes, tracks], axis=0) + featdict.update({f"{int(frameId)}_{int(bid)}": features[ii, :]}) # [f"feat_{int(bid)}"] = features[i, :] + + frameDict = {"path": path, + "fid": int(frameId), + "bboxes": det, + "tboxes": tracks, + "imgs": imgs, + "feats": featdict} + yoloResnetTracker.append(frameDict) + + # imgs, features = inference_image(im0, tracks) + # TrackerFeats = np.concatenate([TrackerFeats, features], axis=0) '''================== 2. 提取手势位置 ===================''' for *xyxy, id, conf, cls, fid, bid in reversed(tracks): @@ -314,11 +313,8 @@ def yolo_resnet_tracker( # Print time (inference-only) LOGGER.info(f"{s}{'' if len(det) else '(no detections), '}{dt[1].dt * 1E3:.1f}ms") - ## track_boxes: Array, [x1, y1, x2, y2, track_id, score, cls, frame_index, box_id] - TracksDict.update({"TrackBoxes": track_boxes}) - - - return TracksDict + + return yoloResnetTracker diff --git a/tracking/dotrack/__pycache__/dotracks.cpython-39.pyc b/tracking/dotrack/__pycache__/dotracks.cpython-39.pyc index c349263..212091f 100644 Binary files a/tracking/dotrack/__pycache__/dotracks.cpython-39.pyc and b/tracking/dotrack/__pycache__/dotracks.cpython-39.pyc differ diff --git a/tracking/dotrack/__pycache__/dotracks_back.cpython-39.pyc b/tracking/dotrack/__pycache__/dotracks_back.cpython-39.pyc index c72f837..c920469 100644 Binary files a/tracking/dotrack/__pycache__/dotracks_back.cpython-39.pyc and b/tracking/dotrack/__pycache__/dotracks_back.cpython-39.pyc differ diff --git a/tracking/dotrack/__pycache__/dotracks_front.cpython-39.pyc b/tracking/dotrack/__pycache__/dotracks_front.cpython-39.pyc index e7a572c..35b16cb 100644 Binary files a/tracking/dotrack/__pycache__/dotracks_front.cpython-39.pyc and b/tracking/dotrack/__pycache__/dotracks_front.cpython-39.pyc differ diff --git a/tracking/dotrack/dotracks.py b/tracking/dotrack/dotracks.py index a3ec32b..dc1790f 100644 --- a/tracking/dotrack/dotracks.py +++ b/tracking/dotrack/dotracks.py @@ -394,21 +394,24 @@ class Track: class doTracks: - def __init__(self, bboxes, TracksDict): - '''fundamental property''' + def __init__(self, bboxes, trackefeats): + '''fundamental property + trackefeats: dict, key 格式 "fid_bid" + ''' self.bboxes = bboxes # self.TracksDict = TracksDict self.frameID = np.unique(bboxes[:, 7].astype(int)) self.trackID = np.unique(bboxes[:, 4].astype(int)) self.lboxes = self.array2list() - self.lfeats = self.getfeats(TracksDict) + self.lfeats = self.getfeats(trackefeats) '''对 self.tracks 中的元素进行分类,将 track 归入相应列表中''' self.Hands = [] self.Kids = [] self.Static = [] - self.Residual = [] + self.Residual = [] + self.Confirmed = [] self.DownWard = [] # subset of self.Residual self.UpWard = [] # subset of self.Residual self.FreeMove = [] # subset of self.Residual @@ -435,15 +438,22 @@ class doTracks: return lboxes - def getfeats(self, TracksDict): + def getfeats(self, trackefeats): lboxes = self.lboxes lfeats = [] for boxes in lboxes: - afeat = readDict(boxes, TracksDict) - lfeats.append(afeat) + feats = [] + for i in range(boxes.shape[0]): + fid, bid = int(boxes[i, 7]), int(boxes[i, 8]) + key = f"{int(fid)}_{int(bid)}" + if key in trackefeats: + feats.append(trackefeats[key]) + feats = np.asarray(feats, dtype=np.float32) + lfeats.append(feats) return lfeats - + + def similarity(self): nt = len(self.tracks) diff --git a/tracking/dotrack/dotracks_back.py b/tracking/dotrack/dotracks_back.py index dd5d67b..d5235f3 100644 --- a/tracking/dotrack/dotracks_back.py +++ b/tracking/dotrack/dotracks_back.py @@ -6,6 +6,7 @@ Created on Mon Mar 4 18:36:31 2024 """ import numpy as np import cv2 +import copy from tracking.utils.mergetrack import track_equal_track from scipy.spatial.distance import cdist from pathlib import Path @@ -19,9 +20,9 @@ from .track_back import backTrack class doBackTracks(doTracks): - def __init__(self, bboxes, TracksDict): + def __init__(self, bboxes, trackefeats): - super().__init__(bboxes, TracksDict) + super().__init__(bboxes, trackefeats) self.tracks = [backTrack(b, f) for b, f in zip(self.lboxes, self.lfeats)] @@ -113,6 +114,22 @@ class doBackTracks(doTracks): # self.merge_based_hands(htrack) self.Residual = tracks + self.Confirmed = self.confirm_track() + + def confirm_track(self): + Confirmed = None + mindist = 0 + for track in self.Residual: + md = min(track.trajrects_wh) + if md > mindist: + mindist = copy.deepcopy(md) + Confirmed = copy.deepcopy(track) + + if Confirmed is not None: + return [Confirmed] + + return [] + # def merge_based_hands(self, htrack): # gtracks = htrack.Goods @@ -122,6 +139,8 @@ class doBackTracks(doTracks): # btrack, bfious = gtracks[1] + + def associate_with_hand(self, htrack, gtrack): ''' 迁移至基类: diff --git a/tracking/dotrack/dotracks_front.py b/tracking/dotrack/dotracks_front.py index a61e39a..48f54f8 100644 --- a/tracking/dotrack/dotracks_front.py +++ b/tracking/dotrack/dotracks_front.py @@ -5,6 +5,7 @@ Created on Mon Mar 4 18:38:20 2024 @author: ym """ import cv2 +import copy import numpy as np from pathlib import Path @@ -16,8 +17,8 @@ from .dotracks import doTracks from .track_front import frontTrack class doFrontTracks(doTracks): - def __init__(self, bboxes, TracksDict): - super().__init__(bboxes, TracksDict) + def __init__(self, bboxes, frameDictList): + super().__init__(bboxes, frameDictList) # self.tracks = [frontTrack(b) for b in self.lboxes] self.tracks = [frontTrack(b, f) for b, f in zip(self.lboxes, self.lfeats)] @@ -84,11 +85,24 @@ class doFrontTracks(doTracks): tracks = self.sub_tracks(tracks, static_tracks) freemoved_tracks = [t for t in tracks if t.is_free_move()] - tracks = self.sub_tracks(tracks, freemoved_tracks) - - + self.Residual = tracks + self.Confirmed = self.confirm_track() + + def confirm_track(self): + Confirmed = None + mindist = 0 + for track in self.Residual: + md = min(track.trajrects_wh) + if md > mindist: + mindist = copy.deepcopy(md) + Confirmed = copy.deepcopy(track) + + if Confirmed is not None: + return [Confirmed] + + return [] def associate_with_hand(self, htrack, gtrack): ''' diff --git a/tracking/utils/__pycache__/read_data.cpython-39.pyc b/tracking/utils/__pycache__/read_data.cpython-39.pyc index f761704..3bc17c6 100644 Binary files a/tracking/utils/__pycache__/read_data.cpython-39.pyc and b/tracking/utils/__pycache__/read_data.cpython-39.pyc differ diff --git a/tracking/utils/read_data.py b/tracking/utils/read_data.py index 32032d2..36b05a6 100644 --- a/tracking/utils/read_data.py +++ b/tracking/utils/read_data.py @@ -34,10 +34,12 @@ def find_samebox_in_array(arr, target): return -1 - def extract_data(datapath): ''' 0/1_track.data 数据读取 + 对于特征,需要构造两个对象: + (1) tracking输出 boxes,依据 (fid, bid) 找到对应的 feats, tracker_feat_dict 实现较为方便 + (2) frameDictList 中元素为 frameDict,输出同一接口 ''' bboxes, ffeats = [], [] @@ -45,9 +47,7 @@ def extract_data(datapath): trackerfeats = np.empty((0, 256), dtype=np.float64) boxes, feats, tboxes, tfeats = [], [], [], [] - timestamps, frameIds = [], [] - with open(datapath, 'r', encoding='utf-8') as lines: for line in lines: line = line.strip() # 去除行尾的换行符和可能的空白字符 @@ -102,16 +102,17 @@ def extract_data(datapath): assert(len(bboxes)==len(ffeats)), "Error at Yolo output!" assert(len(trackerboxes)==len(trackerfeats)), "Error at tracker output!" - tracker_feat_dict = {} - tracker_feat_dict["timestamps"] = timestamps - tracker_feat_dict["frameIds"] = frameIds - - for i in range(len(trackerboxes)): - tid, fid, bid = int(trackerboxes[i, 4]), int(trackerboxes[i, 7]), int(trackerboxes[i, 8]) - if f"frame_{fid}" not in tracker_feat_dict: - tracker_feat_dict[f"frame_{fid}"]= {"feats": {}} - tracker_feat_dict[f"frame_{fid}"]["feats"].update({bid: trackerfeats[i, :]}) - + ## 生成帧为单位的特征列表 + tracker_feats = {} + frmIDs = np.sort(np.unique(trackerboxes[:, 7].astype(int))) + for fid in frmIDs: + idx = np.where(trackerboxes[:, 7] == fid)[0] + boxes = trackerboxes[idx, :] + feats = trackerfeats[idx, :] + + for i in range(len(boxes)): + f, b = int(boxes[i, 7]), int(boxes[i, 8]) + tracker_feats.update({f"{f}_{b}": feats[i, :]}) boxes, trackingboxes= [], [] tracking_flag = False @@ -137,18 +138,41 @@ def extract_data(datapath): if len(boxes): trackingboxes.append(np.array(boxes)) - tracking_feat_dict = {} + # tracking_feat_dict = {} + # try: + # for i, boxes in enumerate(trackingboxes): + # for box in boxes: + # tid, fid, bid = int(box[4]), int(box[7]), int(box[8]) + # if f"track_{tid}" not in tracking_feat_dict: + # tracking_feat_dict[f"track_{tid}"]= {"feats": {}} + # tracking_feat_dict[f"track_{tid}"]["feats"].update({f"{fid}_{bid}": tracker_feat_dict[f"frame_{fid}"]["feats"][bid]}) + # except Exception as e: + # print(f'Path: {datapath}, tracking_feat_dict can not be structured correcttly, Error: {e}') + + # tracker_feat_dict = {} + # tracker_feat_dict["timestamps"] = timestamps + # tracker_feat_dict["frameIds"] = frameIds + + # for i in range(len(trackerboxes)): + # fid, bid = int(trackerboxes[i, 7]), int(trackerboxes[i, 8]) + # if f"frame_{fid}" not in tracker_feat_dict: + # tracker_feat_dict[f"frame_{fid}"]= {"feats": {}} + # tracker_feat_dict[f"frame_{fid}"]["feats"].update({bid: trackerfeats[i, :]}) + + trackingfeats = [] try: for i, boxes in enumerate(trackingboxes): + feats = [] for box in boxes: - tid, fid, bid = int(box[4]), int(box[7]), int(box[8]) - if f"track_{tid}" not in tracking_feat_dict: - tracking_feat_dict[f"track_{tid}"]= {"feats": {}} - tracking_feat_dict[f"track_{tid}"]["feats"].update({f"{fid}_{bid}": tracker_feat_dict[f"frame_{fid}"]["feats"][bid]}) + fid, bid = int(box[7]), int(box[8]) + feat = tracker_feats[f"{fid}_{bid}"] + feats.append(feat) + trackingfeats.append(np.array(feats)) except Exception as e: - print(f'Path: {datapath}, tracking_feat_dict can not be structured correcttly, Error: {e}') + print(f'Path: {datapath}, trackingfeats can not be structured correcttly, Error: {e}') - return bboxes, ffeats, trackerboxes, tracker_feat_dict, trackingboxes, tracking_feat_dict + # return bboxes, ffeats, trackerboxes, tracker_feat_dict, trackingboxes, trackingfeats + return bboxes, ffeats, trackerboxes, tracker_feats, trackingboxes, trackingfeats def read_tracking_output(filepath): ''' @@ -236,8 +260,6 @@ def read_returnGoods_file(filePath): lines = f.readlines() clean_lines = [line.strip().replace("'", '').replace('"', '') for line in lines] - - all_list = [] split_flag, dict = False, {} barcode_list, similarity_list = [], [] @@ -318,14 +340,15 @@ def read_seneor(filepath): def read_similar(filePath): SimiDict = {} SimiDict['one2one'] = [] + SimiDict['one2SN'] = [] SimiDict['one2n'] = [] with open(filePath, 'r', encoding='utf-8') as f: lines = f.readlines() clean_lines = [line.strip().replace("'", '').replace('"', '') for line in lines] - one2one_list, one2n_list = [], [] + one2one_list, one2SN_list, one2n_list = [], [], [] - Flag_1to1, Flag_1ton = False, False + Flag_1to1, Flag_1toSN, Flag_1ton = False, False, False for i, line in enumerate(clean_lines): line = line.strip() if line.endswith(','): @@ -334,18 +357,26 @@ def read_similar(filePath): if not line: if len(one2one_list): SimiDict['one2one'] = one2one_list + if len(one2SN_list): SimiDict['one2SN'] = one2SN_list if len(one2n_list): SimiDict['one2n'] = one2n_list - one2one_list, one2n_list = [], [] - Flag_1to1, Flag_1ton = False, False + + + one2one_list, one2SN_list, one2n_list = [], [], [] + Flag_1to1, Flag_1toSN, Flag_1ton = False, False, False continue if line.find('oneToOne')>=0: - Flag_1to1, Flag_1ton = True, False + Flag_1to1, Flag_1toSN, Flag_1ton = True, False,False + continue + if line.find('oneToSN')>=0: + Flag_1to1, Flag_1toSN, Flag_1ton = False, True, False continue if line.find('oneTon')>=0: - Flag_1to1, Flag_1ton = False, True + Flag_1to1, Flag_1toSN, Flag_1ton = False, False, True continue + + if Flag_1to1: barcode = line.split(',')[0].strip() value = line.split(',')[1].split(':')[1].strip() @@ -353,6 +384,14 @@ def read_similar(filePath): Dict['similar'] = float(value) one2one_list.append(Dict) continue + + if Flag_1toSN: + barcode = line.split(',')[0].strip() + value = line.split(',')[1].split(':')[1].strip() + Dict['barcode'] = barcode + Dict['similar'] = float(value) + one2SN_list.append(Dict) + continue if Flag_1ton: label = line.split(':')[0].strip()