This commit is contained in:
王庆刚
2024-12-18 17:35:24 +08:00
parent 39f94c7bd4
commit dac3b3f2b6
8 changed files with 862 additions and 787 deletions

View File

@ -7,7 +7,7 @@ Created on Mon Dec 16 18:56:18 2024
import os import os
import cv2 import cv2
from utils.event import ShoppingEvent from utils.event import ShoppingEvent, save_data
def main(): def main():
evtpaths = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\images" evtpaths = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\images"
@ -29,39 +29,14 @@ def main():
events = list(set(events)) events = list(set(events))
'''定义当前事件存储地址及生成相应文件件''' '''定义当前事件存储地址及生成相应文件件'''
resultPath = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\result" resultPath = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\result\single_event"
for evtpath in events: for evtpath in events:
evtname = os.path.basename(evtpath)
event = ShoppingEvent(evtpath) event = ShoppingEvent(evtpath)
save_data(event, resultPath)
img_cat = event.draw_tracks() print(event.evtname)
trajpath = os.path.join(resultPath, "trajectory")
if not os.path.exists(trajpath):
os.makedirs(trajpath)
traj_imgpath = os.path.join(trajpath, evtname+".png")
cv2.imwrite(traj_imgpath, img_cat)
## 保存序列图像和轨迹子图
subimgpath = os.path.join(resultPath, f"{evtname}", "subimg")
imgspath = os.path.join(resultPath, f"{evtname}", "imgs")
if not os.path.exists(subimgpath):
os.makedirs(subimgpath)
if not os.path.exists(imgspath):
os.makedirs(imgspath)
subimgpairs = event.save_event_subimg(subimgpath)
for subimgName, subimg in subimgpairs:
spath = os.path.join(subimgpath, subimgName)
cv2.imwrite(spath, subimg)
imgpairs = event.plot_save_image(imgspath)
for imgname, img in imgpairs:
spath = os.path.join(imgspath, imgname)
cv2.imwrite(spath, img)
print(f"{evtname}")

View File

@ -1,498 +1,249 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
Created on Sat Jul ** 14:07:25 2024 Created on Wed Dec 18 11:49:01 2024
现场测试精度、召回率分析程序,是 feat_select.py 的简化版,
但支持循环计算并输出总的pr曲线
@author: ym @author: ym
""" """
import os
import pickle
import os.path
import shutil
import numpy as np import numpy as np
import matplotlib.pyplot as plt
import cv2
from pathlib import Path from pathlib import Path
import sys import matplotlib.pyplot as plt
sys.path.append(r"D:\DetectTracking") from scipy.spatial.distance import cdist
from tracking.utils.plotting import Annotator, colors from utils.event import ShoppingEvent
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 gen_eventdict(sourcePath, stype="data"):
# def read_tracking_output(filepath): '''stype: str,
# boxes = [] 'source': 由 videos 或 images 生成的 pickle 文件
# feats = [] 'data': 从 data 文件中读取的现场运行数据
# 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 k, errEvents = 0, []
output for source_path in sourcePath:
imgs_0后摄图像根据 frameId 进行了排序 evtpath, bname = os.path.split(source_path)
imgs_1前摄图像根据 frameId 进行了排序
''' # bname = r"20241126-135911-bdf91cf9-3e9a-426d-94e8-ddf92238e175_6923555210479"
imgs_0, frmIDs_0, imgs_1, frmIDs_1 = [], [], [], [] source_path = os.path.join(evtpath, bname)
for filename in os.listdir(imgspath): pickpath = os.path.join(eventDataPath, f"{bname}.pickle")
file, ext = os.path.splitext(filename) if os.path.isfile(pickpath): continue
flist = file.split('_')
if len(flist)==4 and ext==".jpg": try:
camID, frmID = flist[0], int(flist[-1]) event = ShoppingEvent(source_path, stype)
imgpath = os.path.join(imgspath, filename) # save_data(event, resultPath)
img = cv2.imread(imgpath)
if camID=='0': with open(pickpath, 'wb') as f:
imgs_0.append(img) pickle.dump(event, f)
frmIDs_0.append(frmID) print(bname)
if camID=='1': except Exception as e:
imgs_1.append(img) errEvents.append(source_path)
frmIDs_1.append(frmID) print(e)
# k += 1
if len(frmIDs_0): # if k==1:
indice = np.argsort(np.array(frmIDs_0)) # break
imgs_0 = [imgs_0[i] for i in indice ]
if len(frmIDs_1): errfile = os.path.join(resultPath, 'error_events.txt')
indice = np.argsort(np.array(frmIDs_1)) with open(errfile, 'w', encoding='utf-8') as f:
imgs_1 = [imgs_1[i] for i in indice ] for line in errEvents:
f.write(line + '\n')
return imgs_0, imgs_1
# ============================================================================= def read_eventdict(eventDataPath):
# def draw_tracking_boxes(imgs, tracks): evtDict = {}
# '''tracks: [x1, y1, x2, y2, track_id, score, cls, frame_index, box_index] for filename in os.listdir(eventDataPath):
# 0 1 2 3 4 5 6 7 8 evtname, ext = os.path.splitext(filename)
# 关键imgs中的次序和 track 中的 fid 对应 if ext != ".pickle": continue
# '''
# 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): evtpath = os.path.join(eventDataPath, filename)
assert(len(pair)==2 or len(pair)==3), "pair: seqdir, delete, barcodes" with open(evtpath, 'rb') as f:
evtdata = pickle.load(f)
getout_fold = pair[0] # 取出操作对应的文件夹 evtDict[evtname] = evtdata
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)<int(hms):
input_folds.append(pathname)
times.append(int(hms1))
if day1==day and len(error_match) and infold[1]==error_match and int(hms1)<int(hms):
errmatch_folds.append(pathname)
errmatch_times.append(int(hms1))
''' 根据时间排序,选择离取出操作最近时间的文件夹,
作为取出操作应正确匹配的放入操作所对应的文件夹 '''
if len(input_folds):
indice = np.argsort(np.array(times))
input_fold = input_folds[indice[-1]]
inputpath = os.path.join(basepath, input_fold)
'''取出操作错误匹配的放入操作对应的文件夹'''
if len(errmatch_folds):
indice = np.argsort(np.array(errmatch_times))
errmatch_fold = errmatch_folds[indice[-1]]
errorpath = os.path.join(basepath, errmatch_fold)
'''放入事件文件夹地址、取出事件文件夹地址'''
getoutpath = os.path.join(basepath, getout_fold)
return getoutpath, inputpath, errorpath return evtDict
def save_tracking_imgpairs(pairs, savepath):
'''
pairs: 匹配事件对
savepath: 保存的目标文件夹
'''
def get_event_path(evtpath):
basepath, eventname = os.path.split(evtpath)
evt_path = ''
for filename in os.listdir(basepath):
if filename.find(eventname)==0:
evt_path = os.path.join(basepath, filename)
break
return evt_path
getoutpath = get_event_path(pairs[0])
inputpath = get_event_path(pairs[1])
if len(pairs) == 3: def one2n_pr(evtDicts):
errorpath = get_event_path(pairs[2]) tpevents, fnevents, fpevents, tnevents = [], [], [], []
else: tpsimi, fnsimi, tnsimi, fpsimi = [], [], [], []
errorpath = '' errorFile_one2n = []
for evtname, event in evtDicts.items():
''' 1. 读取放入、取出事件对应的 Yolo输入的前后摄图像0后摄1前摄 evt_names, evt_barcodes, evt_similars, evt_types = [], [], [], []
2. 读取放入、取出事件对应的 tracking 输出boxes, feats
3. boxes绘制并保存图像序列
4. 截取并保存轨迹子图
'''
if len(getoutpath):
imgs_getout_0, imgs_getout_1 = read_tracking_imgs(getoutpath)
getout_data_0 = os.path.join(getoutpath, '0_tracking_output.data') for ndict in event.one2n:
getout_data_1 = os.path.join(getoutpath, '1_tracking_output.data') nname = ndict["event"]
boxes_output_0, feats_output_0 = read_tracking_output(getout_data_0) barcode = ndict["barcode"]
boxes_output_1, feats_output_1 = read_tracking_output(getout_data_1) similar = ndict["similar"]
ImgsGetout_0 = draw_tracking_boxes(imgs_getout_0, boxes_output_0) typee = ndict["type"].strip()
ImgsGetout_1 = draw_tracking_boxes(imgs_getout_1, boxes_output_1)
SubimgsGetout_0 = get_subimgs(imgs_getout_0, boxes_output_0)
SubimgsGetout_1 = get_subimgs(imgs_getout_1, boxes_output_1)
savedir = os.path.basename(getoutpath)
if len(inputpath):
imgs_input_0, imgs_input_1 = read_tracking_imgs(inputpath)
input_data_0 = os.path.join(inputpath, '0_tracking_output.data')
input_data_1 = os.path.join(inputpath, '1_tracking_output.data')
boxes_input_0, feats_input_0 = read_tracking_output(input_data_0)
boxes_input_1, feats_input_1 = read_tracking_output(input_data_1)
ImgsInput_0 = draw_tracking_boxes(imgs_input_0, boxes_input_0)
ImgsInput_1 = draw_tracking_boxes(imgs_input_1, boxes_input_1)
SubimgsInput_0 = get_subimgs(imgs_input_0, boxes_input_0)
SubimgsInput_1 = get_subimgs(imgs_input_1, boxes_input_1)
savedir = savedir + '+' + os.path.basename(inputpath)
if len(errorpath):
imgs_error_0, imgs_error_1 = read_tracking_imgs(errorpath)
error_data_0 = os.path.join(errorpath, '0_tracking_output.data')
error_data_1 = os.path.join(errorpath, '1_tracking_output.data')
boxes_error_0, feats_error_0 = read_tracking_output(error_data_0)
boxes_error_1, feats_error_1 = read_tracking_output(error_data_1)
ImgsError_0 = draw_tracking_boxes(imgs_error_0, boxes_error_0)
ImgsError_1 = draw_tracking_boxes(imgs_error_1, boxes_error_1)
SubimgsError_0 = get_subimgs(imgs_error_0, boxes_error_0)
SubimgsError_1 = get_subimgs(imgs_error_0, boxes_error_0)
savedir = savedir + '+' + os.path.basename(errorpath)
''' savepath\pairs\savedir\eventpairs\保存画框后的图像序列 '''
entpairs = os.path.join(savepath, 'pairs', savedir, 'eventpairs')
if not os.path.exists(entpairs):
os.makedirs(entpairs)
for fid, img in ImgsInput_0:
imgpath = os.path.join(entpairs, f'input_0_{fid}.png')
cv2.imwrite(imgpath, img)
for fid, img in ImgsInput_1:
imgpath = os.path.join(entpairs, f'input_1_{fid}.png')
cv2.imwrite(imgpath, img)
for fid, img in ImgsGetout_0:
imgpath = os.path.join(entpairs, f'getout_0_{fid}.png')
cv2.imwrite(imgpath, img)
for fid, img in ImgsGetout_1:
imgpath = os.path.join(entpairs, f'getout_1_{fid}.png')
cv2.imwrite(imgpath, img)
if 'ImgsError_0' in vars() and 'ImgsError_1' in vars():
for fid, img in ImgsError_0:
imgpath = os.path.join(entpairs, f'errMatch_0_{fid}.png')
cv2.imwrite(imgpath, img)
for fid, img in ImgsError_1:
imgpath = os.path.join(entpairs, f'errMatch_1_{fid}.png')
cv2.imwrite(imgpath, img)
''' savepath\pairs\savedir\subimgpairs\保存轨迹子图 '''
subimgpairs = os.path.join(savepath, 'pairs', savedir, 'subimgpairs')
if not os.path.exists(subimgpairs):
os.makedirs(subimgpairs)
for fid, bid, img in SubimgsGetout_0:
imgpath = os.path.join(subimgpairs, f'getout_0_{fid}_{bid}.png')
cv2.imwrite(imgpath, img)
for fid, bid, img in SubimgsGetout_1:
imgpath = os.path.join(subimgpairs, f'getout_1_{fid}_{bid}.png')
cv2.imwrite(imgpath, img)
for fid, bid, img in SubimgsInput_0:
imgpath = os.path.join(subimgpairs, f'input_0_{fid}_{bid}.png')
cv2.imwrite(imgpath, img)
for fid, bid, img in SubimgsInput_1:
imgpath = os.path.join(subimgpairs, f'input_1_{fid}_{bid}.png')
cv2.imwrite(imgpath, img)
if 'SubimgsError_0' in vars() and 'SubimgsError_1' in vars():
for fid, bid, img in SubimgsError_0:
imgpath = os.path.join(subimgpairs, f'errMatch_0_{fid}_{bid}.png')
cv2.imwrite(imgpath, img)
for fid, bid, img in SubimgsError_1:
imgpath = os.path.join(subimgpairs, f'errMatch_1_{fid}_{bid}.png')
cv2.imwrite(imgpath, img)
def one2n_deleted(all_list):
corrpairs, errpairs, correct_similarity, err_similarity = [], [], [], []
for s_list in all_list:
seqdir = s_list['SeqDir'].strip()
delete = s_list['Deleted'].strip()
barcodes = [s.strip() for s in s_list['barcode']]
similarity_comp, similarity_front = [], []
for simil in s_list['similarity']:
ss = [float(s.strip()) for s in simil.split(',')]
similarity_comp.append(ss[0]) o2n_evt = [evt for name, evt in evtDicts.items() if name.find(nname[:15])==0]
if len(ss)==3: if len(o2n_evt)==1:
similarity_front.append(ss[2]) o2nevt = o2n_evt[0]
if len(similarity_front):
similarity = [s for s in similarity_front]
else:
similarity = [s for s in similarity_comp]
index = similarity.index(max(similarity))
matched_barcode = barcodes[index]
if matched_barcode == delete:
corrpairs.append((seqdir, delete))
correct_similarity.append(max(similarity))
else:
errpairs.append((seqdir, delete, matched_barcode))
err_similarity.append(max(similarity))
return corrpairs, errpairs, correct_similarity, err_similarity
def one2n_return(all_list):
corrpairs, corr_similarity, errpairs, err_similarity = [], [], [], []
for s_list in all_list:
seqdir = s_list['SeqDir'].strip()
delete = s_list['Deleted'].strip()
barcodes = [s.strip() for s in s_list['barcode']]
events = [s.strip() for s in s_list['event']]
types = [s.strip() for s in s_list['type']]
## =================== 读入相似度值
similarity_comp, similarity_front = [], []
for simil in s_list['similarity']:
ss = [float(s.strip()) for s in simil.split(',')]
similarity_comp.append(ss[0])
if len(ss)==3:
similarity_front.append(ss[2])
if len(similarity_front):
similarity = [s for s in similarity_front]
else:
similarity = [s for s in similarity_comp]
index = similarity.index(max(similarity))
matched_barcode = barcodes[index]
if matched_barcode == delete:
corrpairs.append((seqdir, events[index]))
corr_similarity.append(max(similarity))
else:
idx = [i for i, name in enumerate(events) if name.split('_')[-1] == delete]
idxmax, simimax = -1, -1
# idxmax, simimax = k, similarity[k] for k in idx if similarity[k] > simimax
for k in idx:
if similarity[k] > simimax:
idxmax = k
simimax = similarity[k]
if idxmax>-1:
input_event = events[idxmax]
else: else:
input_event = '' continue
if typee == "11":
boxes1 = event.front_trackingboxes
boxes2 = o2nevt.front_trackingboxes
feat1 = event.front_trackingfeats
feat2 = o2nevt.front_trackingfeats
if typee == "10":
boxes1 = event.front_trackingboxes
boxes2 = o2nevt.back_trackingboxes
feat1 = event.front_trackingfeats
feat2 = o2nevt.back_trackingfeats
if typee == "00":
boxes1 = event.back_trackingboxes
boxes2 = o2nevt.back_trackingboxes
feat1 = event.back_trackingfeats
feat2 = o2nevt.back_trackingfeats
if typee == "01":
boxes1 = event.back_trackingboxes
boxes2 = o2nevt.front_trackingboxes
feat1 = event.back_trackingfeats
feat2 = o2nevt.front_trackingfeats
matrix = 1 - cdist(feat1[0], feat2[0], 'cosine')
simi_mean = np.mean(matrix)
simi_max = np.max(matrix)
errpairs.append((seqdir, input_event, events[index])) evt_names.append(nname)
err_similarity.append(max(similarity)) evt_barcodes.append(barcode)
evt_similars.append(simi_mean)
return corrpairs, errpairs, corr_similarity, err_similarity evt_types.append(typee)
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) if len(evt_names)==len(evt_barcodes) and len(evt_barcodes)==len(evt_similars) \
'''3. 获取 (取出,放入并删除, 错误匹配) 对应路径,保存相应轨迹图像''' and len(evt_similars)==len(evt_types) and len(evt_names)>0:
if saveimgs:
save_tracking_imgpairs(pairs, savepath) maxsim = evt_similars[evt_similars.index(max(evt_similars))]
for i in range(len(evt_names)):
def test_rpath_return(): bcd, simi = evt_barcodes[i], evt_similars[i]
return_bfile = r'\\192.168.1.28\share\测试_202406\1101\images\returnGoods.txt'
basepath = r'\\192.168.1.28\share\测试_202406\1101\images' if bcd==event.barcode and simi==maxsim:
savepath = r'D:\DetectTracking\contrast\result' tpsimi.append(simi)
tpevents.append(evtname)
elif bcd==event.barcode and simi!=maxsim:
fnsimi.append(simi)
fnevents.append(evtname)
elif bcd!=event.barcode and simi!=maxsim:
tnsimi.append(simi)
tnevents.append(evtname)
elif bcd!=event.barcode and simi==maxsim and event.barcode in evt_barcodes:
fpsimi.append(simi)
fpevents.append(evtname)
else:
errorFile_one2n.append(evtname)
''' 1:n 数据存储,需根据相似度排序'''
PPrecise, PRecall = [], []
NPrecise, NRecall = [], []
all_list = read_returnGoods_file(return_bfile) Thresh = np.linspace(-0.2, 1, 100)
corrpairs, errpairs, _, _ = one2n_return(all_list) for th in Thresh:
for corrpair in corrpairs: '''============================= 1:n 计算'''
GetoutPath = os.path.join(basepath, corrpair[0]) TP = sum(np.array(tpsimi) >= th)
InputPath = os.path.join(basepath, corrpair[1]) FP = sum(np.array(fpsimi) >= th)
FN = sum(np.array(fnsimi) < th)
TN = sum(np.array(tnsimi) < th)
pairs = (GetoutPath, InputPath) PPrecise.append(TP/(TP+FP+1e-6))
save_tracking_imgpairs(pairs, savepath) PRecall.append(TP/(len(tpsimi)+len(fnsimi)+1e-6))
NPrecise.append(TN/(TN+FN+1e-6))
for errpair in errpairs: NRecall.append(TN/(len(tnsimi)+len(fpsimi)+1e-6))
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) '''4. ============================= 1:n 曲线,'''
fig, ax = plt.subplots()
ax.plot(Thresh, PPrecise, 'r', label='Precise_Pos: TP/TPFP')
def test_one2n(): ax.plot(Thresh, PRecall, 'b', label='Recall_Pos: TP/TPFN')
''' ax.plot(Thresh, NPrecise, 'g', label='Precise_Neg: TN/TNFP')
1:n 性能测试 ax.plot(Thresh, NRecall, 'c', label='Recall_Neg: TN/TNFN')
兼容 2 种 txt 文件格式returnGoods.txt, deletedBarcode.txt ax.set_xlim([0, 1])
fpath: 文件路径、或文件夹,其中包含多个 txt 文件 ax.set_ylim([0, 1])
savepath: pr曲线保存路径 ax.grid(True)
''' ax.set_title('1:n Precise & Recall')
# fpath = r'\\192.168.1.28\share\测试_202406\deletedBarcode\other' # deletedBarcode.txt ax.set_xlabel(f"Event Num: {len(tpsimi)+len(fnsimi)}")
fpath = r'\\192.168.1.28\share\测试_202406\1108_展厅模型v800测试' # returnGoods.txt ax.legend()
savepath = r'\\192.168.1.28\share\测试_202406\deletedBarcode\illustration' plt.show()
## ============================= 1:n 直方图'''
if os.path.isdir(fpath): fig, axes = plt.subplots(2, 2)
filepaths = [os.path.join(fpath, f) for f in os.listdir(fpath) axes[0, 0].hist(tpsimi, bins=60, edgecolor='black')
if f.find('.txt')>0 axes[0, 0].set_xlim([-0.2, 1])
and (f.find('deletedBarcode')>=0 or f.find('returnGoods')>=0)] axes[0, 0].set_title('TP')
elif os.path.isfile(fpath): axes[0, 1].hist(fpsimi, bins=60, edgecolor='black')
filepaths = [fpath] axes[0, 1].set_xlim([-0.2, 1])
else: axes[0, 1].set_title('FP')
return axes[1, 0].hist(tnsimi, bins=60, edgecolor='black')
axes[1, 0].set_xlim([-0.2, 1])
axes[1, 0].set_title('TN')
axes[1, 1].hist(fnsimi, bins=60, edgecolor='black')
axes[1, 1].set_xlim([-0.2, 1])
axes[1, 1].set_title('FN')
plt.show()
return fpevents
def main():
if not os.path.exists(savepath): '''1. 生成事件字典并保存至 eventDataPath, 只需运行一次 '''
os.mkdir(savepath) # gen_eventdict(sourcePath)
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}) '''2. 读取时间字典 '''
for file, blist in BarLists.items(): evtDicts = read_eventdict(eventDataPath)
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): '''3. 1:n 比对事件评估 '''
_, _, correct_similarity, err_similarity = one2n_return(blist) fpevents = one2n_pr(evtDicts)
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()
fpErrFile = str(Path(resultPath).joinpath("one2n_Error.txt"))
with open(fpErrFile, "w") as file:
for item in fpevents:
file.write(item + "\n")
if __name__ == '__main__': if __name__ == '__main__':
# test_one2n()
test_rpath_return() # returnGoods.txt eventSourcePath = [r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\images"]
# test_rpath_deleted() # deleteBarcode.txt resultPath = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\result"
eventDataPath = os.path.join(resultPath, "evtobjs")
similPath = os.path.join(resultPath, "simidata")
if not os.path.exists(eventDataPath):
os.makedirs(eventDataPath)
if not os.path.exists(similPath):
os.makedirs(similPath)
main()
# try:
# test_rpath_return()
# test_rpath_deleted()
# except Exception as e:
# print(e)

View File

@ -0,0 +1,498 @@
# -*- 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)<int(hms):
input_folds.append(pathname)
times.append(int(hms1))
if day1==day and len(error_match) and infold[1]==error_match and int(hms1)<int(hms):
errmatch_folds.append(pathname)
errmatch_times.append(int(hms1))
''' 根据时间排序,选择离取出操作最近时间的文件夹,
作为取出操作应正确匹配的放入操作所对应的文件夹 '''
if len(input_folds):
indice = np.argsort(np.array(times))
input_fold = input_folds[indice[-1]]
inputpath = os.path.join(basepath, input_fold)
'''取出操作错误匹配的放入操作对应的文件夹'''
if len(errmatch_folds):
indice = np.argsort(np.array(errmatch_times))
errmatch_fold = errmatch_folds[indice[-1]]
errorpath = os.path.join(basepath, errmatch_fold)
'''放入事件文件夹地址、取出事件文件夹地址'''
getoutpath = os.path.join(basepath, getout_fold)
return getoutpath, inputpath, errorpath
def save_tracking_imgpairs(pairs, savepath):
'''
pairs: 匹配事件对
savepath: 保存的目标文件夹
'''
def get_event_path(evtpath):
basepath, eventname = os.path.split(evtpath)
evt_path = ''
for filename in os.listdir(basepath):
if filename.find(eventname)==0:
evt_path = os.path.join(basepath, filename)
break
return evt_path
getoutpath = get_event_path(pairs[0])
inputpath = get_event_path(pairs[1])
if len(pairs) == 3:
errorpath = get_event_path(pairs[2])
else:
errorpath = ''
''' 1. 读取放入、取出事件对应的 Yolo输入的前后摄图像0后摄1前摄
2. 读取放入、取出事件对应的 tracking 输出boxes, feats
3. boxes绘制并保存图像序列
4. 截取并保存轨迹子图
'''
if len(getoutpath):
imgs_getout_0, imgs_getout_1 = read_tracking_imgs(getoutpath)
getout_data_0 = os.path.join(getoutpath, '0_tracking_output.data')
getout_data_1 = os.path.join(getoutpath, '1_tracking_output.data')
boxes_output_0, feats_output_0 = read_tracking_output(getout_data_0)
boxes_output_1, feats_output_1 = read_tracking_output(getout_data_1)
ImgsGetout_0 = draw_tracking_boxes(imgs_getout_0, boxes_output_0)
ImgsGetout_1 = draw_tracking_boxes(imgs_getout_1, boxes_output_1)
SubimgsGetout_0 = get_subimgs(imgs_getout_0, boxes_output_0)
SubimgsGetout_1 = get_subimgs(imgs_getout_1, boxes_output_1)
savedir = os.path.basename(getoutpath)
if len(inputpath):
imgs_input_0, imgs_input_1 = read_tracking_imgs(inputpath)
input_data_0 = os.path.join(inputpath, '0_tracking_output.data')
input_data_1 = os.path.join(inputpath, '1_tracking_output.data')
boxes_input_0, feats_input_0 = read_tracking_output(input_data_0)
boxes_input_1, feats_input_1 = read_tracking_output(input_data_1)
ImgsInput_0 = draw_tracking_boxes(imgs_input_0, boxes_input_0)
ImgsInput_1 = draw_tracking_boxes(imgs_input_1, boxes_input_1)
SubimgsInput_0 = get_subimgs(imgs_input_0, boxes_input_0)
SubimgsInput_1 = get_subimgs(imgs_input_1, boxes_input_1)
savedir = savedir + '+' + os.path.basename(inputpath)
if len(errorpath):
imgs_error_0, imgs_error_1 = read_tracking_imgs(errorpath)
error_data_0 = os.path.join(errorpath, '0_tracking_output.data')
error_data_1 = os.path.join(errorpath, '1_tracking_output.data')
boxes_error_0, feats_error_0 = read_tracking_output(error_data_0)
boxes_error_1, feats_error_1 = read_tracking_output(error_data_1)
ImgsError_0 = draw_tracking_boxes(imgs_error_0, boxes_error_0)
ImgsError_1 = draw_tracking_boxes(imgs_error_1, boxes_error_1)
SubimgsError_0 = get_subimgs(imgs_error_0, boxes_error_0)
SubimgsError_1 = get_subimgs(imgs_error_0, boxes_error_0)
savedir = savedir + '+' + os.path.basename(errorpath)
''' savepath\pairs\savedir\eventpairs\保存画框后的图像序列 '''
entpairs = os.path.join(savepath, 'pairs', savedir, 'eventpairs')
if not os.path.exists(entpairs):
os.makedirs(entpairs)
for fid, img in ImgsInput_0:
imgpath = os.path.join(entpairs, f'input_0_{fid}.png')
cv2.imwrite(imgpath, img)
for fid, img in ImgsInput_1:
imgpath = os.path.join(entpairs, f'input_1_{fid}.png')
cv2.imwrite(imgpath, img)
for fid, img in ImgsGetout_0:
imgpath = os.path.join(entpairs, f'getout_0_{fid}.png')
cv2.imwrite(imgpath, img)
for fid, img in ImgsGetout_1:
imgpath = os.path.join(entpairs, f'getout_1_{fid}.png')
cv2.imwrite(imgpath, img)
if 'ImgsError_0' in vars() and 'ImgsError_1' in vars():
for fid, img in ImgsError_0:
imgpath = os.path.join(entpairs, f'errMatch_0_{fid}.png')
cv2.imwrite(imgpath, img)
for fid, img in ImgsError_1:
imgpath = os.path.join(entpairs, f'errMatch_1_{fid}.png')
cv2.imwrite(imgpath, img)
''' savepath\pairs\savedir\subimgpairs\保存轨迹子图 '''
subimgpairs = os.path.join(savepath, 'pairs', savedir, 'subimgpairs')
if not os.path.exists(subimgpairs):
os.makedirs(subimgpairs)
for fid, bid, img in SubimgsGetout_0:
imgpath = os.path.join(subimgpairs, f'getout_0_{fid}_{bid}.png')
cv2.imwrite(imgpath, img)
for fid, bid, img in SubimgsGetout_1:
imgpath = os.path.join(subimgpairs, f'getout_1_{fid}_{bid}.png')
cv2.imwrite(imgpath, img)
for fid, bid, img in SubimgsInput_0:
imgpath = os.path.join(subimgpairs, f'input_0_{fid}_{bid}.png')
cv2.imwrite(imgpath, img)
for fid, bid, img in SubimgsInput_1:
imgpath = os.path.join(subimgpairs, f'input_1_{fid}_{bid}.png')
cv2.imwrite(imgpath, img)
if 'SubimgsError_0' in vars() and 'SubimgsError_1' in vars():
for fid, bid, img in SubimgsError_0:
imgpath = os.path.join(subimgpairs, f'errMatch_0_{fid}_{bid}.png')
cv2.imwrite(imgpath, img)
for fid, bid, img in SubimgsError_1:
imgpath = os.path.join(subimgpairs, f'errMatch_1_{fid}_{bid}.png')
cv2.imwrite(imgpath, img)
def one2n_deleted(all_list):
corrpairs, errpairs, correct_similarity, err_similarity = [], [], [], []
for s_list in all_list:
seqdir = s_list['SeqDir'].strip()
delete = s_list['Deleted'].strip()
barcodes = [s.strip() for s in s_list['barcode']]
similarity_comp, similarity_front = [], []
for simil in s_list['similarity']:
ss = [float(s.strip()) for s in simil.split(',')]
similarity_comp.append(ss[0])
if len(ss)==3:
similarity_front.append(ss[2])
if len(similarity_front):
similarity = [s for s in similarity_front]
else:
similarity = [s for s in similarity_comp]
index = similarity.index(max(similarity))
matched_barcode = barcodes[index]
if matched_barcode == delete:
corrpairs.append((seqdir, delete))
correct_similarity.append(max(similarity))
else:
errpairs.append((seqdir, delete, matched_barcode))
err_similarity.append(max(similarity))
return corrpairs, errpairs, correct_similarity, err_similarity
def one2n_return(all_list):
corrpairs, corr_similarity, errpairs, err_similarity = [], [], [], []
for s_list in all_list:
seqdir = s_list['SeqDir'].strip()
delete = s_list['Deleted'].strip()
barcodes = [s.strip() for s in s_list['barcode']]
events = [s.strip() for s in s_list['event']]
types = [s.strip() for s in s_list['type']]
## =================== 读入相似度值
similarity_comp, similarity_front = [], []
for simil in s_list['similarity']:
ss = [float(s.strip()) for s in simil.split(',')]
similarity_comp.append(ss[0])
if len(ss)==3:
similarity_front.append(ss[2])
if len(similarity_front):
similarity = [s for s in similarity_front]
else:
similarity = [s for s in similarity_comp]
index = similarity.index(max(similarity))
matched_barcode = barcodes[index]
if matched_barcode == delete:
corrpairs.append((seqdir, events[index]))
corr_similarity.append(max(similarity))
else:
idx = [i for i, name in enumerate(events) if name.split('_')[-1] == delete]
idxmax, simimax = -1, -1
# idxmax, simimax = k, similarity[k] for k in idx if similarity[k] > 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)

View File

@ -52,7 +52,7 @@ from tracking.utils.read_data import extract_data, read_tracking_output, read_si
from tracking.utils.plotting import Annotator, colors from tracking.utils.plotting import Annotator, colors
from feat_extract.config import config as conf from feat_extract.config import config as conf
from feat_extract.inference import FeatsInterface from feat_extract.inference import FeatsInterface
from utils.event import ShoppingEvent from utils.event import ShoppingEvent, save_data
from genfeats import gen_bcd_features from genfeats import gen_bcd_features
@ -84,86 +84,6 @@ def ft16_to_uint8(arr_ft16):
return arr_uint8, arr_ft16_ return arr_uint8, arr_ft16_
# =============================================================================
# def plot_save_image(event, savepath):
# cameras = ('front', 'back')
# for camera in cameras:
# if camera == 'front':
# boxes = event.front_trackerboxes
# imgpaths = event.front_imgpaths
# else:
# boxes = event.back_trackerboxes
# imgpaths = event.back_imgpaths
#
# def array2list(bboxes):
# '''[x1, y1, x2, y2, track_id, score, cls, frame_index, box_index]'''
# frame_ids = bboxes[:, 7].astype(int)
# fID = np.unique(bboxes[:, 7].astype(int))
# fboxes = []
# for f_id in fID:
# idx = np.where(frame_ids==f_id)[0]
# box = bboxes[idx, :]
# fboxes.append((f_id, box))
# return fboxes
#
# fboxes = array2list(boxes)
#
# for fid, fbox in fboxes:
# imgpath = imgpaths[int(fid-1)]
#
# image = cv2.imread(imgpath)
#
# annotator = Annotator(image.copy(), line_width=2)
# for i, *xyxy, tid, score, cls, fid, bid in enumerate(fbox):
# label = f'{int(id), int(cls)}'
# if tid >=0 and cls==0:
# color = colors(int(cls), True)
# elif tid >=0 and cls!=0:
# color = colors(int(id), True)
# else:
# color = colors(19, True) # 19为调色板的最后一个元素
# annotator.box_label(xyxy, label, color=color)
#
# im0 = annotator.result()
# spath = os.path.join(savepath, Path(imgpath).name)
# cv2.imwrite(spath, im0)
#
#
# def save_event_subimg(event, savepath):
# '''
# 功能: 保存一次购物事件的轨迹子图
# 9 items: barcode, type, filepath, back_imgpaths, front_imgpaths,
# back_boxes, front_boxes, back_feats, front_feats,
# feats_compose, feats_select
# 子图保存次序:先前摄、后后摄,以 k 为编号,和 "feats_compose" 中次序相同
# '''
# cameras = ('front', 'back')
# for camera in cameras:
# if camera == 'front':
# boxes = event.front_boxes
# imgpaths = event.front_imgpaths
# 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
#
# imgpath = imgpaths[int(fid-1)]
# image = cv2.imread(imgpath)
#
# subimg = image[int(y1/2):int(y2/2), int(x1/2):int(x2/2), :]
#
# camerType, timeTamp, _, frameID = os.path.basename(imgpath).split('.')[0].split('_')
# subimgName = f"cam{camerType}_{i}_tid{int(tid)}_fid({int(fid)}, {frameID}).png"
# spath = os.path.join(savepath, subimgName)
#
# cv2.imwrite(spath, subimg)
# # basename = os.path.basename(event['filepath'])
# print(f"Image saved: {os.path.basename(event.eventpath)}")
# =============================================================================
def data_precision_compare(stdfeat, evtfeat, evtMessage, save=True): def data_precision_compare(stdfeat, evtfeat, evtMessage, save=True):
evt, stdbcd, label = evtMessage evt, stdbcd, label = evtMessage
rltdata, rltdata_ft16, rltdata_ft16_ = [], [], [] rltdata, rltdata_ft16, rltdata_ft16_ = [], [], []
@ -289,43 +209,7 @@ def one2one_simi():
with open(evtpath, 'rb') as f: with open(evtpath, 'rb') as f:
evtdata = pickle.load(f) evtdata = pickle.load(f)
evtDict[evtname] = evtdata evtDict[evtname] = evtdata
'''======4.1 事件轨迹子图保存 ======================'''
error_event = []
for evtname, event in evtDict.items():
pairpath = os.path.join(subimgPath, f"{evtname}")
if not os.path.exists(pairpath):
os.makedirs(pairpath)
try:
subimgpairs = event.save_event_subimg(pairpath)
for subimgName, subimg in subimgpairs:
spath = os.path.join(pairpath, subimgName)
cv2.imwrite(spath, subimg)
except Exception as e:
error_event.append(evtname)
img_path = os.path.join(imagePath, f"{evtname}")
if not os.path.exists(img_path):
os.makedirs(img_path)
try:
imgpairs = event.plot_save_image(img_path)
for imgname, img in imgpairs:
spath = os.path.join(img_path, imgname)
cv2.imwrite(spath, img)
except Exception as e:
error_event.append(evtname)
errfile = os.path.join(subimgPath, f'error_event.txt')
with open(errfile, 'w', encoding='utf-8') as f:
for line in error_event:
f.write(line + '\n')
'''======4.2 barcode 标准图像保存 ==================''' '''======4.2 barcode 标准图像保存 =================='''
# for stdbcd in barcodes: # for stdbcd in barcodes:
@ -440,16 +324,13 @@ def compute_precise_recall(rltdata):
rltpath = os.path.join(similPath, 'pr.png') rltpath = os.path.join(similPath, 'pr.png')
plt.savefig(rltpath) # svg, png, pdf plt.savefig(rltpath) # svg, png, pdf
def gen_eventdict(sourcePath, saveimg=True): def gen_eventdict(sourcePath, saveimg=True):
eventList = [] k, errEvents = 0, []
errEvents = []
k = 0
for source_path in sourcePath: for source_path in sourcePath:
evtpath, bname = os.path.split(source_path) evtpath, bname = os.path.split(source_path)
bname = r"20241126-135911-bdf91cf9-3e9a-426d-94e8-ddf92238e175_6923555210479" # bname = r"20241126-135911-bdf91cf9-3e9a-426d-94e8-ddf92238e175_6923555210479"
source_path = os.path.join(evtpath, bname) source_path = os.path.join(evtpath, bname)
pickpath = os.path.join(eventDataPath, f"{bname}.pickle") pickpath = os.path.join(eventDataPath, f"{bname}.pickle")
@ -457,7 +338,8 @@ def gen_eventdict(sourcePath, saveimg=True):
try: try:
event = ShoppingEvent(source_path, stype="data") event = ShoppingEvent(source_path, stype="data")
eventList.append(event) # save_data(event, resultPath)
with open(pickpath, 'wb') as f: with open(pickpath, 'wb') as f:
pickle.dump(event, f) pickle.dump(event, f)
print(bname) print(bname)
@ -465,11 +347,12 @@ def gen_eventdict(sourcePath, saveimg=True):
errEvents.append(source_path) errEvents.append(source_path)
print(e) print(e)
k += 1 # k += 1
if k==1: # if k==1:
break # break
errfile = os.path.join(eventDataPath, f'error_events.txt') errfile = os.path.join(resultPath, 'error_events.txt')
with open(errfile, 'w', encoding='utf-8') as f: with open(errfile, 'w', encoding='utf-8') as f:
for line in errEvents: for line in errEvents:
f.write(line + '\n') f.write(line + '\n')
@ -477,6 +360,8 @@ def gen_eventdict(sourcePath, saveimg=True):
def test_one2one(): def test_one2one():
'''==== 0. 生成事件列表和对应的 Barcodes列表 ==========='''
bcdList, event_spath = [], [] bcdList, event_spath = [], []
for evtpath in eventSourcePath: for evtpath in eventSourcePath:
for evtname in os.listdir(evtpath): for evtname in os.listdir(evtpath):
@ -486,9 +371,9 @@ def test_one2one():
if len(evt)>=2 and evt[-1].isdigit() and len(evt[-1])>=10: if len(evt)>=2 and evt[-1].isdigit() and len(evt[-1])>=10:
bcdList.append(evt[-1]) bcdList.append(evt[-1])
event_spath.append(os.path.join(evtpath, evtname)) event_spath.append(os.path.join(evtpath, evtname))
bcdSet = set(bcdList) '''==== 1. 生成标准特征集, 只需运行一次, 在 genfeats.py 中实现 ==========='''
'''==== 1. 生成标准特征集, 只需运行一次, 在 genfeats.py 中实现 ===========''' # bcdSet = set(bcdList)
# gen_bcd_features(stdSamplePath, stdBarcodePath, stdFeaturePath, bcdSet) # gen_bcd_features(stdSamplePath, stdBarcodePath, stdFeaturePath, bcdSet)
print("stdFeats have generated and saved!") print("stdFeats have generated and saved!")
@ -511,40 +396,25 @@ if __name__ == '__main__':
(3) stdFeaturePath: 比对标准特征集特征存储地址 (3) stdFeaturePath: 比对标准特征集特征存储地址
(4) eventSourcePath: 事件地址 (4) eventSourcePath: 事件地址
(5) resultPath: 结果存储地址 (5) resultPath: 结果存储地址
(6) eventDataPath: 用于1:1比对的购物事件特征存储地址、对应子图存储地址 (6) eventDataPath: 用于1:1比对的购物事件存储地址在resultPath下
(7) subimgPath: 1:1比对购物事件轨迹、标准barcode所对应的 subimgs 存储地址 (7) similPath: 1:1比对结果存储地址(事件级)在resultPath下
(8) similPath: 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"
# eventDataPath = r"\\192.168.1.28\share\测试_202406\contrast\events"
# subimgPath = r'\\192.168.1.28\share\测试_202406\contrast\subimgs'
# similPath = r"D:\DetectTracking\contrast\result\pickle"
# eventSourcePath = [r'\\192.168.1.28\share\测试_202406\1101\images']
stdSamplePath = r"\\192.168.1.28\share\数据\已完成数据\展厅数据\v1.0\比对数据\整理\zhantingBase" stdSamplePath = r"\\192.168.1.28\share\数据\已完成数据\展厅数据\v1.0\比对数据\整理\zhantingBase"
stdBarcodePath = r"D:\exhibition\dataset\bcdpath" stdBarcodePath = r"D:\exhibition\dataset\bcdpath"
stdFeaturePath = r"D:\exhibition\dataset\feats" stdFeaturePath = r"D:\exhibition\dataset\feats"
resultPath = r"D:\exhibition\result\events"
# eventSourcePath = [r'D:\exhibition\images\20241202'] # eventSourcePath = [r'D:\exhibition\images\20241202']
# eventSourcePath = [r"\\192.168.1.28\share\测试视频数据以及日志\各模块测试记录\展厅测试\1129_展厅模型v801测试组测试"] # eventSourcePath = [r"\\192.168.1.28\share\测试视频数据以及日志\各模块测试记录\展厅测试\1129_展厅模型v801测试组测试"]
eventSourcePath = [r"\\192.168.1.28\share\测试视频数据以及日志\各模块测试记录\展厅测试\1126_展厅模型v801测试"]
eventSourcePath = [r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\images"]
resultPath = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\result"
'''定义当前事件存储地址及生成相应文件件''' eventDataPath = os.path.join(resultPath, "evtobjs")
eventDataPath = os.path.join(resultPath, "1126", "evtobjs") similPath = os.path.join(resultPath, "simidata")
subimgPath = os.path.join(resultPath, "1126", "subimgs")
imagePath = os.path.join(resultPath, "1126", "image")
similPath = os.path.join(resultPath, "1126", "simidata")
if not os.path.exists(eventDataPath): if not os.path.exists(eventDataPath):
os.makedirs(eventDataPath) os.makedirs(eventDataPath)
if not os.path.exists(subimgPath):
os.makedirs(subimgPath)
if not os.path.exists(imagePath):
os.makedirs(imagePath)
if not os.path.exists(similPath): if not os.path.exists(similPath):
os.makedirs(similPath) os.makedirs(similPath)

View File

@ -104,7 +104,7 @@ def test_compare():
plot_pr_curve(simiList) plot_pr_curve(simiList)
def one2one_pr(paths): def contrast_pr(paths):
''' '''
1:1 1:1
@ -501,7 +501,7 @@ def one2one_pr(paths):
if __name__ == "__main__": if __name__ == "__main__":
evtpaths = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\images" evtpaths = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\images"
one2one_pr(evtpaths) contrast_pr(evtpaths)

View File

@ -19,6 +19,37 @@ from tracking.utils.read_data import extract_data, read_tracking_output, read_si
IMG_FORMAT = ['.bmp', '.jpg', '.jpeg', '.png'] IMG_FORMAT = ['.bmp', '.jpg', '.jpeg', '.png']
VID_FORMAT = ['.mp4', '.avi'] VID_FORMAT = ['.mp4', '.avi']
def save_data(event, resultPath=None):
'''事件轨迹子图保存'''
if resultPath is None:
resultPath = os.path.dirname(os.path.abspath(__file__))
subimgpath = os.path.join(resultPath, f"{event.evtname}", "subimg")
imgspath = os.path.join(resultPath, f"{event.evtname}", "imgs")
if not os.path.exists(subimgpath):
os.makedirs(subimgpath)
if not os.path.exists(imgspath):
os.makedirs(imgspath)
##(2) 保存轨迹中的子图
subimgpairs = event.save_event_subimg(subimgpath)
for subimgName, subimg in subimgpairs:
spath = os.path.join(subimgpath, subimgName)
cv2.imwrite(spath, subimg)
##(3) 保存序列图像
imgpairs = event.plot_save_image(imgspath)
for imgname, img in imgpairs:
spath = os.path.join(imgspath, imgname)
cv2.imwrite(spath, img)
##(4) 保存轨迹散点图
img_cat = event.draw_tracks()
trajpath = os.path.join(resultPath, "trajectory")
if not os.path.exists(trajpath):
os.makedirs(trajpath)
traj_imgpath = os.path.join(trajpath, event.evtname+".png")
cv2.imwrite(traj_imgpath, img_cat)
def array2list(bboxes): def array2list(bboxes):
''' '''
@ -44,7 +75,7 @@ def array2list(bboxes):
class ShoppingEvent: class ShoppingEvent:
def __init__(self, eventpath, stype="data"): def __init__(self, eventpath, stype="data"):
'''stype: str, 'pickle', 'data', ''' '''stype: str, 'source', 'data', '''
self.eventpath = eventpath self.eventpath = eventpath
self.evtname = str(Path(eventpath).stem) self.evtname = str(Path(eventpath).stem)
@ -60,6 +91,7 @@ class ShoppingEvent:
'''=========== process.data ===============================''' '''=========== process.data ==============================='''
self.one2one = None self.one2one = None
self.one2n = None self.one2n = None
self.one2SN = None
'''=========== 0/1_track.data =============================''' '''=========== 0/1_track.data ============================='''
self.back_yolobboxes = [] self.back_yolobboxes = []
@ -85,8 +117,8 @@ class ShoppingEvent:
if stype=="data": if stype=="data":
self.from_datafile(eventpath) self.from_datafile(eventpath)
if stype=="pickle": if stype=="source":
self.from_pklfile(eventpath) self.from_source_pkl(eventpath)
self.feats_select = [] self.feats_select = []
self.feats_compose = np.empty((0, 256), dtype=np.float64) self.feats_compose = np.empty((0, 256), dtype=np.float64)
@ -131,7 +163,7 @@ class ShoppingEvent:
return kdata, outdata return kdata, outdata
def from_pklfile(self, eventpath): def from_source_pkl(self, eventpath):
with open(eventpath, 'rb') as f: with open(eventpath, 'rb') as f:
ShoppingDict = pickle.load(f) ShoppingDict = pickle.load(f)
@ -222,7 +254,7 @@ class ShoppingEvent:
SimiDict = read_similar(procpath) SimiDict = read_similar(procpath)
self.one2one = SimiDict['one2one'] self.one2one = SimiDict['one2one']
self.one2n = SimiDict['one2n'] self.one2n = SimiDict['one2n']
self.one2SN = SimiDict['one2SN']
'''=========== 0/1_track.data & 0/1_tracking_output.data =======''' '''=========== 0/1_track.data & 0/1_tracking_output.data ======='''
for dataname in os.listdir(eventpath): for dataname in os.listdir(eventpath):
@ -411,14 +443,10 @@ class ShoppingEvent:
def main(): def main():
# pklpath = r"D:\DetectTracking\evtresult\images2\ShoppingDict.pkl" # pklpath = r"D:\DetectTracking\evtresult\images2\ShoppingDict.pkl"
# evt = ShoppingEvent(pklpath, stype='pickle') # evt = ShoppingEvent(pklpath, stype='source')
evtpath = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\images\20241209-160248-08edd5f6-1806-45ad-babf-7a4dd11cea60_6973226721445" evtpath = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\images\20241209-160248-08edd5f6-1806-45ad-babf-7a4dd11cea60_6973226721445"
evt = ShoppingEvent(evtpath, stype='data') evt = ShoppingEvent(evtpath, stype='data')
@ -427,65 +455,7 @@ def main():
cv2.imwrite("a.png", img_cat) cv2.imwrite("a.png", img_cat)
# =============================================================================
# def main1():
# evtpaths = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\images"
# text1 = "one2n_Error.txt"
# text2 = "one2SN_Error.txt"
# events = []
# text = (text1, text2)
# for txt in text:
# txtfile = os.path.join(evtpaths, txt)
# with open(txtfile, "r") as f:
# lines = f.readlines()
# for i, line in enumerate(lines):
# line = line.strip()
# if line:
# fpath=os.path.join(evtpaths, line)
# events.append(fpath)
#
#
# events = list(set(events))
#
# '''定义当前事件存储地址及生成相应文件件'''
# resultPath = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\result"
# # eventDataPath = os.path.join(resultPath, "evtobjs")
# # subimgPath = os.path.join(resultPath, "subimgs")
# # imagePath = os.path.join(resultPath, "image")
#
# # if not os.path.exists(eventDataPath):
# # os.makedirs(eventDataPath)
# # if not os.path.exists(subimgPath):
# # os.makedirs(subimgPath)
# # if not os.path.exists(imagePath):
# # os.makedirs(imagePath)
#
#
# for evtpath in events:
# event = ShoppingEvent(evtpath)
#
#
# evtname = os.path.basename(evtpath)
# subimgpath = os.path.join(resultPath, f"{evtname}", "subimg")
# imgspath = os.path.join(resultPath, f"{evtname}", "imgs")
# if not os.path.exists(subimgpath):
# os.makedirs(subimgpath)
# if not os.path.exists(imgspath):
# os.makedirs(imgspath)
#
# subimgpairs = event.save_event_subimg(subimgpath)
#
# for subimgName, subimg in subimgpairs:
# spath = os.path.join(subimgpath, subimgName)
# cv2.imwrite(spath, subimg)
#
# imgpairs = event.plot_save_image(imgspath)
# for imgname, img in imgpairs:
# spath = os.path.join(imgspath, imgname)
# cv2.imwrite(spath, img)
#
# =============================================================================
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -155,58 +155,15 @@
stdfeat_infer(imgPath, featPath, bcdSet=None) stdfeat_infer(imgPath, featPath, bcdSet=None)
功能: 对 imgPath 中图像进行特征提取生成只有一个key值的字典。 功能: 对 imgPath 中图像进行特征提取生成只有一个key值的字典。
{barcode: features}features.shape=(nsample, 256),并保存至 featPath 中 {barcode: features}features.shape=(nsample, 256),并保存至 featPath 中
one2n_contrast.py onsite_contrast_pr.py
test_one2n() one2one_pr()
1:n 现场测试性能评估,输出 PR 曲线 现场试验输出数据的性能评估输出1:1, 1:SN, 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) test_compare()
输入: 从deletedBarcode.txt读取的数据 适用于202410前数据保存版本的需调用 OneToOneCompare.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 one2one_contrast.py
@ -258,7 +215,20 @@
ft16_to_uint8() ft16_to_uint8()
one2n_contrast.py
执行1:n共需要3步
'''1. 生成事件字典并保存至 eventDataPath, 只需运行一次 '''
# gen_eventdict(sourcePath)
'''2. 读取时间字典 '''
evtDicts = read_eventdict(eventDataPath)
'''3. 1:n 比对事件评估 '''
@ -266,26 +236,67 @@
one2one_onsite.py
现场试验输出数据的 1:1 性能评估;
适用于202410前数据保存版本的需调用 OneToOneCompare.txt
标准特征向量生成
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: 图像样本地址}形式字典并进行存储
(3) featpath调用 inference_image(), 对每一个barcode生成字典并进行存储
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 time_devide.py
runyolo() runyolo()