增加了单帧入侵判断及yoloV10

This commit is contained in:
18262620154
2025-04-11 17:02:39 +08:00
parent 798c596acc
commit e044c85a04
197 changed files with 1863 additions and 997 deletions

View File

@ -27,188 +27,24 @@ Created on Fri Aug 30 17:53:03 2024
"""
import numpy as np
import cv2
import os
import sys
import random
import pickle
import json
import random
import copy
import sys
# import torch
import time
# import json
from pathlib import Path
from scipy.spatial.distance import cdist
import matplotlib.pyplot as plt
import shutil
from datetime import datetime
# from openpyxl import load_workbook, Workbook
# from config import config as conf
# from model import resnet18 as resnet18
# from feat_inference import inference_image
FILE = Path(__file__).resolve()
ROOT = FILE.parents[1] # YOLOv5 root directory
if str(ROOT) not in sys.path:
sys.path.append(str(ROOT))
sys.path.append(r"D:\DetectTracking")
from tracking.utils.read_data import extract_data, read_tracking_output, read_similar, read_deletedBarcode_file
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, save_data
from utils.calsimi import calsimi_vs_stdfeat, calsimi_vs_stdfeat_new
from utils.tools import get_evtList, init_eventDict
from utils.databits import data_precision_compare
from genfeats import gen_bcd_features
from event_test import calc_simil
from one2n_contrast import init_eventDict
def int8_to_ft16(arr_uint8, amin, amax):
arr_ft16 = (arr_uint8 / 255 * (amax-amin) + amin).astype(np.float16)
return arr_ft16
def ft16_to_uint8(arr_ft16):
# pickpath = r"\\192.168.1.28\share\测试_202406\contrast\std_features_ft32vsft16\6902265587712_ft16.pickle"
# with open(pickpath, 'rb') as f:
# edict = pickle.load(f)
# arr_ft16 = edict['feats']
amin = np.min(arr_ft16)
amax = np.max(arr_ft16)
arr_ft255 = (arr_ft16 - amin) * 255 / (amax-amin)
arr_uint8 = arr_ft255.astype(np.uint8)
arr_ft16_ = int8_to_ft16(arr_uint8, amin, amax)
arrDistNorm = np.linalg.norm(arr_ft16_ - arr_ft16) / arr_ft16_.size
return arr_uint8, arr_ft16_
def data_precision_compare(stdfeat, evtfeat, evtMessage, save=True):
evt, stdbcd, label = evtMessage
rltdata, rltdata_ft16, rltdata_ft16_ = [], [], []
matrix = 1 - cdist(stdfeat, evtfeat, 'cosine')
simi_mean = np.mean(matrix)
simi_max = np.max(matrix)
stdfeatm = np.mean(stdfeat, axis=0, keepdims=True)
evtfeatm = np.mean(evtfeat, axis=0, keepdims=True)
simi_mfeat = 1- np.maximum(0.0, cdist(stdfeatm, evtfeatm, 'cosine'))
rltdata = [label, stdbcd, evt, simi_mean, simi_max, simi_mfeat[0,0]]
##================================================================= float16
stdfeat_ft16 = stdfeat.astype(np.float16)
evtfeat_ft16 = evtfeat.astype(np.float16)
stdfeat_ft16 /= np.linalg.norm(stdfeat_ft16, axis=1)[:, None]
evtfeat_ft16 /= np.linalg.norm(evtfeat_ft16, axis=1)[:, None]
matrix_ft16 = 1 - cdist(stdfeat_ft16, evtfeat_ft16, 'cosine')
simi_mean_ft16 = np.mean(matrix_ft16)
simi_max_ft16 = np.max(matrix_ft16)
stdfeatm_ft16 = np.mean(stdfeat_ft16, axis=0, keepdims=True)
evtfeatm_ft16 = np.mean(evtfeat_ft16, axis=0, keepdims=True)
simi_mfeat_ft16 = 1- np.maximum(0.0, cdist(stdfeatm_ft16, evtfeatm_ft16, 'cosine'))
rltdata_ft16 = [label, stdbcd, evt, simi_mean_ft16, simi_max_ft16, simi_mfeat_ft16[0,0]]
'''****************** uint8 is ok!!!!!! ******************'''
##=================================================================== uint8
# stdfeat_uint8, stdfeat_ft16_ = ft16_to_uint8(stdfeat_ft16)
# evtfeat_uint8, evtfeat_ft16_ = ft16_to_uint8(evtfeat_ft16)
stdfeat_uint8 = (stdfeat_ft16*128).astype(np.int8)
evtfeat_uint8 = (evtfeat_ft16*128).astype(np.int8)
stdfeat_ft16_ = stdfeat_uint8.astype(np.float16)/128
evtfeat_ft16_ = evtfeat_uint8.astype(np.float16)/128
absdiff = np.linalg.norm(stdfeat_ft16_ - stdfeat) / stdfeat.size
matrix_ft16_ = 1 - cdist(stdfeat_ft16_, evtfeat_ft16_, 'cosine')
simi_mean_ft16_ = np.mean(matrix_ft16_)
simi_max_ft16_ = np.max(matrix_ft16_)
stdfeatm_ft16_ = np.mean(stdfeat_ft16_, axis=0, keepdims=True)
evtfeatm_ft16_ = np.mean(evtfeat_ft16_, axis=0, keepdims=True)
simi_mfeat_ft16_ = 1- np.maximum(0.0, cdist(stdfeatm_ft16_, evtfeatm_ft16_, 'cosine'))
rltdata_ft16_ = [label, stdbcd, evt, simi_mean_ft16_, simi_max_ft16_, simi_mfeat_ft16_[0,0]]
if not save:
return
##========================================================= save as float32
rppath = os.path.join(similPath, f'{evt}_ft32.pickle')
with open(rppath, 'wb') as f:
pickle.dump(rltdata, f)
rtpath = os.path.join(similPath, f'{evt}_ft32.txt')
with open(rtpath, 'w', encoding='utf-8') as f:
for result in rltdata:
part = [f"{x:.3f}" if isinstance(x, float) else str(x) for x in result]
line = ', '.join(part)
f.write(line + '\n')
##========================================================= save as float16
rppath_ft16 = os.path.join(similPath, f'{evt}_ft16.pickle')
with open(rppath_ft16, 'wb') as f:
pickle.dump(rltdata_ft16, f)
rtpath_ft16 = os.path.join(similPath, f'{evt}_ft16.txt')
with open(rtpath_ft16, 'w', encoding='utf-8') as f:
for result in rltdata_ft16:
part = [f"{x:.3f}" if isinstance(x, float) else str(x) for x in result]
line = ', '.join(part)
f.write(line + '\n')
##=========================================================== save as uint8
rppath_uint8 = os.path.join(similPath, f'{evt}_uint8.pickle')
with open(rppath_uint8, 'wb') as f:
pickle.dump(rltdata_ft16_, f)
rtpath_uint8 = os.path.join(similPath, f'{evt}_uint8.txt')
with open(rtpath_uint8, 'w', encoding='utf-8') as f:
for result in rltdata_ft16_:
part = [f"{x:.3f}" if isinstance(x, float) else str(x) for x in result]
line = ', '.join(part)
f.write(line + '\n')
def simi_calc(event, stdfeat):
evtfeat = event.feats_compose
if isinstance(event.feats_select, list):
if len(event.feats_select) and len(event.feats_select[0]):
evtfeat = event.feats_select[0]
else:
return None, None, None
else:
evtfeat = event.feats_select
if len(evtfeat)==0 or len(stdfeat)==0:
return None, None, None
evtfeat /= np.linalg.norm(evtfeat, axis=1)[:, None]
stdfeat /= np.linalg.norm(stdfeat, axis=1)[:, None]
matrix = 1 - cdist(evtfeat, stdfeat, 'cosine')
matrix[matrix < 0] = 0
simi_mean = np.mean(matrix)
simi_max = np.max(matrix)
stdfeatm = np.mean(stdfeat, axis=0, keepdims=True)
evtfeatm = np.mean(evtfeat, axis=0, keepdims=True)
simi_mfeat = 1- np.maximum(0.0, cdist(stdfeatm, evtfeatm, 'cosine'))
return simi_mean, simi_max, simi_mfeat[0,0]
def build_std_evt_dict():
@ -218,18 +54,6 @@ def build_std_evt_dict():
'''
stdBarcode = [p.stem for p in Path(stdFeaturePath).iterdir() if p.is_file() and (p.suffix=='.json' or p.suffix=='.pickle')]
'''*********** USearch ***********'''
# stdFeaturePath = r"D:\contrast\stdlib\v11_test.json"
# stdBarcode = []
# stdlib = {}
# with open(stdFeaturePath, 'r', encoding='utf-8') as f:
# data = json.load(f)
# for dic in data['total']:
# barcode = dic['key']
# feature = np.array(dic['value'])
# stdBarcode.append(barcode)
# stdlib[barcode] = feature
'''======1. 购物事件列表,该列表中的 Barcode 存在于标准的 stdBarcode 内 ==='''
evtList = [(p.stem, p.stem.split('_')[-1]) for p in Path(eventDataPath).iterdir()
@ -259,10 +83,7 @@ def build_std_evt_dict():
stddata = pickle.load(f)
feat = stddata["feats_ft32"]
stdDict[barcode] = feat
'''*********** USearch ***********'''
# stdDict = {}
# for barcode in barcodes:
@ -282,7 +103,7 @@ def build_std_evt_dict():
return evtList, evtDict, stdDict
def one2SN_pr(evtList, evtDict, stdDict):
def one2SN_pr(evtList, evtDict, stdDict, simType="simple"):
std_barcodes = set([bcd for _, bcd in evtList])
@ -312,8 +133,14 @@ def one2SN_pr(evtList, evtDict, stdDict):
barcodes, similars = [], []
for stdbcd in bcd_selected:
stdfeat = stdDict[stdbcd]
simi_mean, simi_max, simi_mfeat = simi_calc(event, stdfeat)
# simi_mean = calc_simil(event, stdfeat)
if simType=="typea":
simi_mean, simi_max, simi_mfeat = calsimi_vs_stdfeat(event, stdfeat)
elif simType=="typeb":
pass
else:
simi_mean, simi_1, simi_2 = calsimi_vs_stdfeat_new(event, stdfeat)
## 在event.front_feats和event.back_feats同时为空时此处不需要保护
# if simi_mean==None:
@ -376,6 +203,10 @@ def one2SN_pr(evtList, evtDict, stdDict):
ax.set_xlabel(f"Event Num: {len(tp_events) + len(fn_events)}")
ax.legend()
plt.show()
rltpath = os.path.join(similPath, f'pr_1toSN_{simType}.png')
plt.savefig(rltpath)
## ============================= 1:N 展厅 直方图'''
fig, axes = plt.subplots(2, 2)
axes[0, 0].hist(tp_simi, bins=60, range=(-0.2, 1), edgecolor='black')
@ -391,11 +222,14 @@ def one2SN_pr(evtList, evtDict, stdDict):
axes[1, 1].set_xlim([-0.2, 1])
axes[1, 1].set_title(f'FN({len(fn_simi)})')
plt.show()
rltpath = os.path.join(similPath, f'hist_1toSN_{simType}.png')
plt.savefig(rltpath)
def one2one_simi(evtList, evtDict, stdDict):
def one2one_simi(evtList, evtDict, stdDict, simType):
barcodes = set([bcd for _, bcd in evtList])
'''======1 构造 3 个事件对: 扫 A 放 A, 扫 A 放 B, 合并 ===================='''
@ -421,31 +255,50 @@ def one2one_simi(evtList, evtDict, stdDict):
continue
stdfeat = stdDict[stdbcd] # float32
simi_mean, simi_max, simi_mfeat = simi_calc(event, stdfeat)
if simType=="typea":
simi_mean, simi_1, simi_2 = calsimi_vs_stdfeat_new(event, stdfeat)
elif simType=="typeb":
pass
else:
simi_mean, simi_1, simi_2 = calsimi_vs_stdfeat(event, stdfeat)
if simi_mean is None:
continue
rltdata.append((label, stdbcd, evtname, simi_mean, simi_max, simi_mfeat))
rltdata.append((label, stdbcd, evtname, simi_mean, simi_1, simi_2))
'''================ float32、16、int8 精度比较与存储 ============='''
# data_precision_compare(stdfeat, evtfeat, mergePairs[i], save=True)
# data_precision_compare(stdfeat, evtfeat, mergePairs[i], similPath, save=True)
errorFile_one2one = list(set(errorFile_one2one))
return rltdata, errorFile_one2one
def one2one_pr(evtList, evtDict, stdDict):
def one2one_pr(evtList, evtDict, stdDict, simType="simple"):
rltdata, errorFile_one2one = one2one_simi(evtList, evtDict, stdDict)
rltdata, errorFile_one2one = one2one_simi(evtList, evtDict, stdDict, simType)
Same, Cross = [], []
for label, stdbcd, evtname, simi_mean, simi_max, simi_mft in rltdata:
if label == "same":
if simType=="simple" and label == "same":
Same.append(simi_max)
if label == "diff":
if simType=="simple" and label == "diff":
Cross.append(simi_max)
if simType=="typea" and label == "same":
Same.append(simi_mean)
if simType=="typea" and label == "diff":
Cross.append(simi_mean)
# for label, stdbcd, evtname, simi_mean, simi_max, simi_mft in rltdata:
# if label == "same":
# Same.append(simi_mean)
# if label == "diff":
# Cross.append(simi_mean)
Same = np.array(Same)
Cross = np.array(Cross)
@ -508,7 +361,7 @@ def one2one_pr(evtList, evtDict, stdDict):
ax.legend()
plt.show()
rltpath = os.path.join(similPath, 'pr.png')
rltpath = os.path.join(similPath, f'pr_1to1_{simType}.png')
plt.savefig(rltpath) # svg, png, pdf
@ -521,7 +374,7 @@ def one2one_pr(evtList, evtDict, stdDict):
axes[1].set_xlim([-0.2, 1])
axes[1].set_title(f'TN({len(Cross)})')
rltpath = os.path.join(similPath, 'hist.png')
rltpath = os.path.join(similPath, f'hist_1to1_{simType}.png')
plt.savefig(rltpath)
@ -529,158 +382,25 @@ def one2one_pr(evtList, evtDict, stdDict):
def gen_eventdict(sourcePath, saveimg=True):
k, errEvents = 0, []
for source_path in sourcePath:
evtpath, bname = os.path.split(source_path)
## 兼容事件的两种情况:文件夹 和 Yolo-Resnet-Tracker 的输出
if os.path.isfile(source_path):
bname, ext = os.path.splitext(bname)
# evt = bname.split("_")
evt = bname.split('_')
condt = len(evt)>=2 and evt[-1].isdigit() and len(evt[-1])>=10
if not condt: continue
# 如果已完成事件生成,则不执行
pickpath = os.path.join(eventDataPath, f"{bname}.pickle")
if os.path.isfile(pickpath): continue
try:
event = ShoppingEvent(source_path, stype=source_type)
# save_data(event, resultPath)
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 init_std_evt_dict():
# '''==== 0. 生成事件列表和对应的 Barcodes列表 ==========='''
# bcdList, event_spath = [], []
# for evtname in os.listdir(eventSourcePath):
# bname, ext = os.path.splitext(evtname)
# ## 处理事件的两种情况:文件夹 和 Yolo-Resnet-Tracker 的输出
# fpath = os.path.join(eventSourcePath, evtname)
# if os.path.isfile(fpath) and (ext==".pkl" or ext==".pickle"):
# evt = bname.split('_')
# elif os.path.isdir(fpath):
# evt = evtname.split('_')
# else:
# continue
# if len(evt)>=2 and evt[-1].isdigit() and len(evt[-1])>=10:
# bcdList.append(evt[-1])
# event_spath.append(fpath)
# '''==== 1. 生成标准特征集, 只需运行一次, 在 genfeats.py 中实现 ==========='''
# bcdSet = set(bcdList)
# gen_bcd_features(stdSamplePath, stdBarcodePath, stdFeaturePath, bcdSet)
# print("stdFeats have generated and saved!")
# '''==== 2. 生成事件字典, 只需运行一次 ==============='''
# gen_eventdict(event_spath)
# print("eventList have generated and saved!")
def get_evtList():
'''==== 0. 生成事件列表和对应的 Barcodes 集合 ==========='''
bcdList, evtpaths = [], []
for evtname in os.listdir(eventSourcePath):
bname, ext = os.path.splitext(evtname)
## 处理事件的两种情况:文件夹 和 Yolo-Resnet-Tracker 的输出
fpath = os.path.join(eventSourcePath, evtname)
if os.path.isfile(fpath) and (ext==".pkl" or ext==".pickle"):
evt = bname.split('_')
elif os.path.isdir(fpath):
evt = evtname.split('_')
else:
continue
if len(evt)>=2 and evt[-1].isdigit() and len(evt[-1])>=10:
bcdList.append(evt[-1])
evtpaths.append(fpath)
bcdSet = set(bcdList)
return evtpaths, bcdSet
# def init_stdDict():
# evtpaths, bcdSet = get_evtList()
# gen_bcd_features(stdSamplePath, stdBarcodePath, stdFeaturePath, bcdSet)
# print("stdFeats have generated and saved!")
# def init_evtDict():
# '''==== 0. 生成事件列表和对应的 Barcodes列表 ==========='''
# bcdList, event_spath = [], []
# for evtname in os.listdir(eventSourcePath):
# bname, ext = os.path.splitext(evtname)
# ## 处理事件的两种情况:文件夹 和 Yolo-Resnet-Tracker 的输出
# fpath = os.path.join(eventSourcePath, evtname)
# if os.path.isfile(fpath) and (ext==".pkl" or ext==".pickle"):
# evt = bname.split('_')
# elif os.path.isdir(fpath):
# evt = evtname.split('_')
# else:
# continue
# if len(evt)>=2 and evt[-1].isdigit() and len(evt[-1])>=10:
# bcdList.append(evt[-1])
# event_spath.append(fpath)
# '''==== 2. 生成事件字典, 只需运行一次 ==============='''
# gen_eventdict(event_spath)
# print("eventList have generated and saved!")
def test_one2one_one2SN():
def test_one2one_one2SN(simType):
'''1:1性能评估'''
# evtpaths, bcdSet = get_evtList()
# evtpaths, bcdSet = get_evtList(eventSourcePath)
'''=== 1. 只需运行一次,生成事件对应的标准特征库字典,如已生成,无需运行 ===='''
# gen_bcd_features(stdSamplePath, stdBarcodePath, stdFeaturePath, eventSourcePath)
'''==== 2. 生成事件字典, 只需运行一次 ===================='''
# date_ = ['2025-3-4_1', '2025-3-5_1', '2025-3-5_2']
# for dt in date_:
# evtpaths = os.path.join(eventSourcePath, dt)
# init_eventDict(evtpaths, eventDataPath, source_type)
init_eventDict(eventSourcePath, eventDataPath, source_type)
# init_eventDict(eventSourcePath, eventDataPath, source_type)
'''==== 2. 基于事件barcode集和标准库barcode交集构造事件集合 ========='''
'''==== 3. 基于事件barcode集和标准库barcode交集构造事件集合 ========='''
evtList, evtDict, stdDict = build_std_evt_dict()
one2one_pr(evtList, evtDict, stdDict)
one2one_pr(evtList, evtDict, stdDict, simType)
one2SN_pr(evtList, evtDict, stdDict)
one2SN_pr(evtList, evtDict, stdDict, simType)
if __name__ == '__main__':
'''
@ -694,21 +414,10 @@ if __name__ == '__main__':
(7) similPath: 1:1比对结果存储地址(事件级)在resultPath下
'''
# stdSamplePath = r"\\192.168.1.28\share\数据\已完成数据\展厅数据\v1.0\比对数据\整理\zhantingBase"
# stdBarcodePath = r"D:\exhibition\dataset\bcdpath"
# stdFeaturePath = r"\\192.168.1.28\share\数据\已完成数据\比对数据\barcode\all_totalBarocde\features_json\v11_barcode_11592"
stdSamplePath = "/home/wqg/dataset/total_barcode/totalBarcode"
stdBarcodePath = "/home/wqg/dataset/total_barcode/bcdpath"
stdFeaturePath = "/home/wqg/dataset/test_dataset/total_barcode/features_json/v11_barcode_0304/"
# eventSourcePath = r'D:\exhibition\images\20241202'
# eventSourcePath = r"\\192.168.1.28\share\测试视频数据以及日志\各模块测试记录\展厅测试\1129_展厅模型v801测试组测试"
# stdSamplePath = r"\\192.168.1.28\share\数据\已完成数据\展厅数据\v2.0_abroad\比对数据\all_base_二筛"
# stdBarcodePath = r"\\192.168.1.28\share\测试视频数据以及日志\海外展厅测试数据\比对测试数据20250121_testing\bcdpath"
# stdFeaturePath = r"\\192.168.1.28\share\测试视频数据以及日志\海外展厅测试数据\比对测试数据20250121_testing\stdfeats"
stdSamplePath = r"\\192.168.1.28\share\数据\已完成数据\比对数据\barcode\all_totalBarocde\totalBarcode"
stdBarcodePath = r"\\192.168.1.28\share\测试视频数据以及日志\全实时测试\testing\bcdpath"
stdFeaturePath = r"\\192.168.1.28\share\数据\已完成数据\比对数据\barcode\all_totalBarocde\features_json\v11_barcode_0304"
if not os.path.exists(stdBarcodePath):
os.makedirs(stdBarcodePath)
if not os.path.exists(stdFeaturePath):
@ -719,18 +428,24 @@ if __name__ == '__main__':
"data": 基于事件切分的原 data 文件版本
"realtime": 全实时生成的 data 文件
'''
source_type = 'realtime' # 'source', 'data', 'realtime'
eventSourcePath = r"\\192.168.1.28\share\测试视频数据以及日志\全实时测试\V12\基准数据集\2025-3-4_1"
resultPath = r"\\192.168.1.28\share\测试视频数据以及日志\全实时测试\testing"
source_type = 'source' # 'source', 'data', 'realtime'
simType = "typea" # "simple", "typea", "typeb"
eventDataPath = os.path.join(resultPath, "evtobjs_0304_1")
similPath = os.path.join(resultPath, "simidata_0304_1")
evttype = "single_event_V10"
# evttype = "single_event_V5"
# evttype = "performence_V10"
# evttype = "performence_V5"
eventSourcePath = "/home/wqg/dataset/pipeline/yrt/{}/shopping_pkl".format(evttype)
resultPath = "/home/wqg/dataset/pipeline/contrast/{}".format(evttype)
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)
test_one2one_one2SN()
test_one2one_one2SN(simType)