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 cv2
from utils.event import ShoppingEvent
from utils.event import ShoppingEvent, save_data
def main():
evtpaths = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\images"
@ -29,39 +29,14 @@ def main():
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:
evtname = os.path.basename(evtpath)
event = ShoppingEvent(evtpath)
save_data(event, resultPath)
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, evtname+".png")
cv2.imwrite(traj_imgpath, img_cat)
print(event.evtname)
## 保存序列图像和轨迹子图
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 -*-
"""
Created on Sat Jul ** 14:07:25 2024
现场测试精度、召回率分析程序,是 feat_select.py 的简化版,
但支持循环计算并输出总的pr曲线
Created on Wed Dec 18 11:49:01 2024
@author: ym
"""
import os.path
import shutil
import os
import pickle
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
import matplotlib.pyplot as plt
from scipy.spatial.distance import cdist
from utils.event import ShoppingEvent
# =============================================================================
# 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):
def gen_eventdict(sourcePath, stype="data"):
'''stype: str,
'source': 由 videos 或 images 生成的 pickle 文件
'data': 从 data 文件中读取的现场运行数据
'''
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)
k, errEvents = 0, []
for source_path in sourcePath:
evtpath, bname = os.path.split(source_path)
# bname = r"20241126-135911-bdf91cf9-3e9a-426d-94e8-ddf92238e175_6923555210479"
source_path = os.path.join(evtpath, bname)
pickpath = os.path.join(eventDataPath, f"{bname}.pickle")
if os.path.isfile(pickpath): continue
try:
event = ShoppingEvent(source_path, stype)
# save_data(event, resultPath)
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
with open(pickpath, 'wb') as f:
pickle.dump(event, f)
print(bname)
except Exception as e:
errEvents.append(source_path)
print(e)
# k += 1
# if k==1:
# break
errfile = os.path.join(resultPath, 'error_events.txt')
with open(errfile, 'w', encoding='utf-8') as f:
for line in errEvents:
f.write(line + '\n')
# =============================================================================
# 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 read_eventdict(eventDataPath):
evtDict = {}
for filename in os.listdir(eventDataPath):
evtname, ext = os.path.splitext(filename)
if ext != ".pickle": continue
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)
evtpath = os.path.join(eventDataPath, filename)
with open(evtpath, 'rb') as f:
evtdata = pickle.load(f)
evtDict[evtname] = evtdata
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
return evtDict
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)
def one2n_pr(evtDicts):
tpevents, fnevents, fpevents, tnevents = [], [], [], []
tpsimi, fnsimi, tnsimi, fpsimi = [], [], [], []
errorFile_one2n = []
for evtname, event in evtDicts.items():
evt_names, evt_barcodes, evt_similars, evt_types = [], [], [], []
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(',')]
for ndict in event.one2n:
nname = ndict["event"]
barcode = ndict["barcode"]
similar = ndict["similar"]
typee = ndict["type"].strip()
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]
o2n_evt = [evt for name, evt in evtDicts.items() if name.find(nname[:15])==0]
if len(o2n_evt)==1:
o2nevt = o2n_evt[0]
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]))
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)
evt_names.append(nname)
evt_barcodes.append(barcode)
evt_similars.append(simi_mean)
evt_types.append(typee)
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'
if len(evt_names)==len(evt_barcodes) and len(evt_barcodes)==len(evt_similars) \
and len(evt_similars)==len(evt_types) and len(evt_names)>0:
maxsim = evt_similars[evt_similars.index(max(evt_similars))]
for i in range(len(evt_names)):
bcd, simi = evt_barcodes[i], evt_similars[i]
if bcd==event.barcode and simi==maxsim:
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)
corrpairs, errpairs, _, _ = one2n_return(all_list)
for corrpair in corrpairs:
GetoutPath = os.path.join(basepath, corrpair[0])
InputPath = os.path.join(basepath, corrpair[1])
Thresh = np.linspace(-0.2, 1, 100)
for th in Thresh:
'''============================= 1:n 计算'''
TP = sum(np.array(tpsimi) >= th)
FP = sum(np.array(fpsimi) >= th)
FN = sum(np.array(fnsimi) < th)
TN = sum(np.array(tnsimi) < th)
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])
PPrecise.append(TP/(TP+FP+1e-6))
PRecall.append(TP/(len(tpsimi)+len(fnsimi)+1e-6))
NPrecise.append(TN/(TN+FN+1e-6))
NRecall.append(TN/(len(tnsimi)+len(fpsimi)+1e-6))
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
'''4. ============================= 1:n 曲线,'''
fig, ax = plt.subplots()
ax.plot(Thresh, PPrecise, 'r', label='Precise_Pos: TP/TPFP')
ax.plot(Thresh, PRecall, 'b', label='Recall_Pos: TP/TPFN')
ax.plot(Thresh, NPrecise, 'g', label='Precise_Neg: TN/TNFP')
ax.plot(Thresh, NRecall, 'c', label='Recall_Neg: TN/TNFN')
ax.set_xlim([0, 1])
ax.set_ylim([0, 1])
ax.grid(True)
ax.set_title('1:n Precise & Recall')
ax.set_xlabel(f"Event Num: {len(tpsimi)+len(fnsimi)}")
ax.legend()
plt.show()
## ============================= 1:n 直方图'''
fig, axes = plt.subplots(2, 2)
axes[0, 0].hist(tpsimi, bins=60, edgecolor='black')
axes[0, 0].set_xlim([-0.2, 1])
axes[0, 0].set_title('TP')
axes[0, 1].hist(fpsimi, bins=60, edgecolor='black')
axes[0, 1].set_xlim([-0.2, 1])
axes[0, 1].set_title('FP')
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):
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)
'''1. 生成事件字典并保存至 eventDataPath, 只需运行一次 '''
# gen_eventdict(sourcePath)
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()
'''2. 读取时间字典 '''
evtDicts = read_eventdict(eventDataPath)
'''3. 1:n 比对事件评估 '''
fpevents = one2n_pr(evtDicts)
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__':
# test_one2n()
test_rpath_return() # returnGoods.txt
# test_rpath_deleted() # deleteBarcode.txt
eventSourcePath = [r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\images"]
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 feat_extract.config import config as conf
from feat_extract.inference import FeatsInterface
from utils.event import ShoppingEvent
from utils.event import ShoppingEvent, save_data
from genfeats import gen_bcd_features
@ -84,86 +84,6 @@ def ft16_to_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):
evt, stdbcd, label = evtMessage
rltdata, rltdata_ft16, rltdata_ft16_ = [], [], []
@ -289,43 +209,7 @@ def one2one_simi():
with open(evtpath, 'rb') as f:
evtdata = pickle.load(f)
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 标准图像保存 =================='''
# for stdbcd in barcodes:
@ -440,16 +324,13 @@ def compute_precise_recall(rltdata):
rltpath = os.path.join(similPath, 'pr.png')
plt.savefig(rltpath) # svg, png, pdf
def gen_eventdict(sourcePath, saveimg=True):
eventList = []
errEvents = []
k = 0
k, errEvents = 0, []
for source_path in sourcePath:
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)
pickpath = os.path.join(eventDataPath, f"{bname}.pickle")
@ -457,7 +338,8 @@ def gen_eventdict(sourcePath, saveimg=True):
try:
event = ShoppingEvent(source_path, stype="data")
eventList.append(event)
# save_data(event, resultPath)
with open(pickpath, 'wb') as f:
pickle.dump(event, f)
print(bname)
@ -465,11 +347,12 @@ def gen_eventdict(sourcePath, saveimg=True):
errEvents.append(source_path)
print(e)
k += 1
if k==1:
break
# k += 1
# if k==1:
# 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:
for line in errEvents:
f.write(line + '\n')
@ -477,6 +360,8 @@ def gen_eventdict(sourcePath, saveimg=True):
def test_one2one():
'''==== 0. 生成事件列表和对应的 Barcodes列表 ==========='''
bcdList, event_spath = [], []
for evtpath in eventSourcePath:
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:
bcdList.append(evt[-1])
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)
print("stdFeats have generated and saved!")
@ -511,40 +396,25 @@ if __name__ == '__main__':
(3) stdFeaturePath: 比对标准特征集特征存储地址
(4) eventSourcePath: 事件地址
(5) resultPath: 结果存储地址
(6) eventDataPath: 用于1:1比对的购物事件特征存储地址、对应子图存储地址
(7) subimgPath: 1:1比对购物事件轨迹、标准barcode所对应的 subimgs 存储地址
(8) similPath: 1:1比对结果存储地址(事件级)
(6) eventDataPath: 用于1:1比对的购物事件存储地址在resultPath下
(7) similPath: 1:1比对结果存储地址(事件级)在resultPath下
'''
# 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"
stdBarcodePath = r"D:\exhibition\dataset\bcdpath"
stdFeaturePath = r"D:\exhibition\dataset\feats"
resultPath = r"D:\exhibition\result\events"
# eventSourcePath = [r'D:\exhibition\images\20241202']
# 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, "1126", "evtobjs")
subimgPath = os.path.join(resultPath, "1126", "subimgs")
imagePath = os.path.join(resultPath, "1126", "image")
similPath = os.path.join(resultPath, "1126", "simidata")
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(subimgPath):
os.makedirs(subimgPath)
if not os.path.exists(imagePath):
os.makedirs(imagePath)
if not os.path.exists(similPath):
os.makedirs(similPath)

View File

@ -104,7 +104,7 @@ def test_compare():
plot_pr_curve(simiList)
def one2one_pr(paths):
def contrast_pr(paths):
'''
1:1
@ -501,7 +501,7 @@ def one2one_pr(paths):
if __name__ == "__main__":
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']
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):
'''
@ -44,7 +75,7 @@ def array2list(bboxes):
class ShoppingEvent:
def __init__(self, eventpath, stype="data"):
'''stype: str, 'pickle', 'data', '''
'''stype: str, 'source', 'data', '''
self.eventpath = eventpath
self.evtname = str(Path(eventpath).stem)
@ -60,6 +91,7 @@ class ShoppingEvent:
'''=========== process.data ==============================='''
self.one2one = None
self.one2n = None
self.one2SN = None
'''=========== 0/1_track.data ============================='''
self.back_yolobboxes = []
@ -85,8 +117,8 @@ class ShoppingEvent:
if stype=="data":
self.from_datafile(eventpath)
if stype=="pickle":
self.from_pklfile(eventpath)
if stype=="source":
self.from_source_pkl(eventpath)
self.feats_select = []
self.feats_compose = np.empty((0, 256), dtype=np.float64)
@ -131,7 +163,7 @@ class ShoppingEvent:
return kdata, outdata
def from_pklfile(self, eventpath):
def from_source_pkl(self, eventpath):
with open(eventpath, 'rb') as f:
ShoppingDict = pickle.load(f)
@ -222,7 +254,7 @@ class ShoppingEvent:
SimiDict = read_similar(procpath)
self.one2one = SimiDict['one2one']
self.one2n = SimiDict['one2n']
self.one2SN = SimiDict['one2SN']
'''=========== 0/1_track.data & 0/1_tracking_output.data ======='''
for dataname in os.listdir(eventpath):
@ -411,14 +443,10 @@ class ShoppingEvent:
def main():
def main():
# 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"
evt = ShoppingEvent(evtpath, stype='data')
@ -427,65 +455,7 @@ def main():
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__":

View File

@ -155,58 +155,15 @@
stdfeat_infer(imgPath, featPath, bcdSet=None)
功能: 对 imgPath 中图像进行特征提取生成只有一个key值的字典。
{barcode: features}features.shape=(nsample, 256),并保存至 featPath 中
one2n_contrast.py
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: (错误匹配时的相似度)
onsite_contrast_pr.py
one2one_pr()
现场试验输出数据的性能评估输出1:1, 1:SN, 1:n的PR曲线和相似度直方图分布。
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()
test_compare()
适用于202410前数据保存版本的需调用 OneToOneCompare.txt
one2one_contrast.py
@ -258,7 +215,20 @@
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
runyolo()